Version 1.10.0-dev.1.0

svn merge -r 44706:45051 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@45054 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..c4321b3
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,214 @@
+## 1.9.1 (2015-03-25)
+
+### Language changes
+
+* Support for `async`, `await`, `sync*`, `async*`, `yield`, `yield*`, and `await
+  for`. See the [the language tour][async] for more details.
+
+* Enum support is fully enabled. See [the language tour][enum] for more details.
+
+[async]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html#asynchrony
+[enum]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html#enums
+
+### Tool changes
+
+* The formatter is much more comprehensive and generates much more readable
+  code. See [its tool page][dartfmt] for more details.
+
+* The analysis server is integrated into the IntelliJ plugin and the Dart
+  editor. This allows analysis to run out-of-process, so that interaction
+  remains smooth even for large projects.
+
+* Analysis supports more and better hints, including unused variables and unused
+  private members.
+
+[dartfmt]: https://www.dartlang.org/tools/dartfmt/
+
+### Core library changes
+
+#### Highlights
+
+* There's a new model for shared server sockets with no need for a `Socket`
+  reference.
+
+* A new, much faster [regular expression engine][regexp].
+
+* The Isolate API now works across the VM and `dart2js`.
+
+[regexp]: http://news.dartlang.org/2015/02/irregexp-dart-vms-new-regexp.html
+
+#### Details
+
+For more information on any of these changes, see the corresponding
+documentation on the [Dart API site](http://api.dartlang.org).
+
+* `dart:async`:
+
+  * `Future.wait` added a new named argument, `cleanUp`, which is a callback
+    that releases resources allocated by a successful `Future`.
+
+  * The `SynchronousStreamController` class was added as an explicit name for
+    the type returned when the `sync` argument is passed to `new
+    StreamController`.
+
+* `dart:collection`: The `new SplayTreeSet.from(Iterable)` constructor was
+  added.
+
+* `dart:convert`: `Utf8Encoder.convert` and `Utf8Decoder.convert` added optional
+  `start` and `end` arguments.
+
+* `dart:core`:
+
+  * `RangeError` added new static helper functions: `checkNotNegative`,
+    `checkValidIndex`, `checkValidRange`, and `checkValueInInterval`.
+
+  * `int` added the `modPow` function.
+
+  * `String` added the `replaceFirstMapped` and `replaceRange` functions.
+
+* `dart:io`:
+
+  * Support for locking files to prevent concurrent modification was added. This
+    includes the `File.lock`, `File.lockSync`, `File.unlock`, and
+    `File.unlockSync` functions as well as the `FileLock` class.
+
+  * Support for starting detached processes by passing the named `mode` argument
+    (a `ProcessStartMode`) to `Process.start`. A process can be fully attached,
+    fully detached, or detached except for its standard IO streams.
+
+  * `HttpServer.bind` and `HttpServer.bindSecure` added the `v6Only` named
+    argument. If this is true, only IPv6 connections will be accepted.
+    
+  * `HttpServer.bind`, `HttpServer.bindSecure`, `ServerSocket.bind`,
+    `RawServerSocket.bind`, `SecureServerSocket.bind` and
+    `RawSecureServerSocket.bind` added the `shared` named argument. If this is
+    true, multiple servers or sockets in the same Dart process may bind to the
+    same address, and incoming requests will automatically be distributed
+    between them.
+
+  * **Deprecation:** the experimental `ServerSocketReference` and
+    `RawServerSocketReference` classes, as well as getters that returned them,
+    are marked as deprecated. The `shared` named argument should be used
+    instead. These will be removed in Dart 1.10.
+
+  * `Socket.connect` and `RawSocket.connect` added the `sourceAddress` named
+    argument, which specifies the local address to bind when making a
+    connection.
+
+  * The static `Process.killPid` method was added to kill a process with a given
+    PID.
+
+  * `Stdout` added the `nonBlocking` instance property, which returns a
+    non-blocking `IOSink` that writes to standard output.
+
+* `dart:isolate`:
+
+  * The static getter `Isolate.current` was added.
+
+  * The `Isolate` methods `addOnExitListener`, `removeOnExitListener`,
+    `setErrorsFatal`, `addOnErrorListener`, and `removeOnErrorListener` now work
+    on the VM.
+
+  * Isolates spawned via `Isolate.spawn` now allow most objects, including
+    top-level and static functions, to be sent between them.
+
+## 1.8.5 (2015-01-21)
+
+* Code generation for SIMD on ARM and ARM64 is fixed.
+
+* A possible crash on MIPS with newer GCC toolchains has been prevented.
+
+* A segfault when using `rethrow` was fixed ([issue 21795][]).
+
+[issue 21795]: https://code.google.com/p/dart/issues/detail?id=21795
+
+## 1.8.3 (2014-12-10)
+
+* Breakpoints can be set in the Editor using file suffixes ([issue 21280][]).
+
+* IPv6 addresses are properly handled by `HttpClient` in `dart:io`, fixing a
+  crash in pub ([issue 21698][]).
+
+* Issues with the experimental `async`/`await` syntax have been fixed.
+
+* Issues with a set of number operations in the VM have been fixed.
+
+* `ListBase` in `dart:collection` always returns an `Iterable` with the correct
+  type argument.
+
+[issue 21280]: https://code.google.com/p/dart/issues/detail?id=21280
+[issue 21698]: https://code.google.com/p/dart/issues/detail?id=21698
+
+## 1.8.0 (2014-11-28)
+
+* `dart:collection`: `SplayTree` added the `toSet` function.
+
+* `dart:convert`: The `JsonUtf8Encoder` class was added.
+
+* `dart:core`:
+
+  * The `IndexError` class was added for errors caused by an index being outside
+    its expected range.
+
+  * The `new RangeError.index` constructor was added. It forwards to `new
+    IndexError`.
+
+  * `RangeError` added three new properties. `invalidProperty` is the value that
+    caused the error, and `start` and `end` are the minimum and maximum values
+    that the value is allowed to assume.
+
+  * `new RangeError.value` and `new RangeError.range` added an optional
+    `message` argument.
+
+  * The `new String.fromCharCodes` constructor added optional `start` and `end`
+    arguments.
+
+* `dart:io`:
+
+  * Support was added for the [Application-Layer Protocol Negotiation][alpn]
+    extension to the TLS protocol for both the client and server.
+
+  * `SecureSocket.connect`, `SecureServerSocket.bind`,
+    `RawSecureSocket.connect`, `RawSecureSocket.secure`,
+    `RawSecureSocket.secureServer`, and `RawSecureServerSocket.bind` added a
+    `supportedProtocols` named argument for protocol negotiation.
+
+  * `RawSecureServerSocket` added a `supportedProtocols` field.
+
+  * `RawSecureSocket` and `SecureSocket` added a `selectedProtocol` field which
+    contains the protocol selected during protocol negotiation.
+
+[alpn]: https://tools.ietf.org/html/rfc7301
+
+## 1.7.0 (2014-10-15)
+
+### Tool changes
+
+* `pub` now generates binstubs for packages that are globally activated so that
+  they can be put on the user's `PATH` and used as normal executables. See the
+  [`pub global activate` documentation][pub global activate].
+
+* When using `dart2js`, deferred loading now works with multiple Dart apps on
+  the same page.
+
+[pub global activate]: https://www.dartlang.org/tools/pub/cmd/pub-global.html#running-a-script-from-your-path
+
+### Core library changes
+
+* `dart:async`: `Zone`, `ZoneDelegate`, and `ZoneSpecification` added the
+  `errorCallback` function, which allows errors that have been programmatically
+  added to a `Future` or `Stream` to be intercepted.
+
+* `dart:io`:
+
+  * **Breaking change:** `HttpClient.close` must be called for all clients or
+    they will keep the Dart process alive until they time out. This fixes the
+    handling of persistent connections. Previously, the client would shut down
+    immediately after a request.
+
+  * **Breaking change:** `HttpServer` no longer compresses all traffic by
+    default. The new `autoCompress` property can be set to `true` to re-enable
+    compression.
+
+* `dart:isolate`: `Isolate.spawnUri` added the optional `packageRoot` argument,
+  which controls how it resolves `package:` URIs.
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 502038c..9c1f568 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -37,7 +37,7 @@
 A conforming  implementation of the Dart programming language must provide and support all the  APIs (libraries, types, functions, getters, setters, whether top-level, static, instance or local) mandated in this specification. 
 
 \LMHash{}
-A conforming implementation is permitted to provide additional APIs, but not additional syntax.
+A conforming implementation is permitted to provide additional APIs, but not additional syntax, except for experimental features in support of null-aware cascades and tear-offs that are likely to be introduced in the next revision of this specification.
 
 \section{Normative References}
 \LMLabel{ecmaNormativeReferences}
@@ -2349,6 +2349,7 @@
       literal;
       identifier;
       newExpression;
+      \NEW{} type `\#' (`{\escapegrammar .}' identifier)?;
       constObjectExpression;
       `(' expression `)'
     .
@@ -3525,11 +3526,14 @@
 }
 
 \LMHash{}
-If $f$ is asynchronous then, when $f$ terminates, any open stream subscriptions associated with any asynchronous for loops  (\ref{asynchronousFor-in}) or yield-each statements  (\ref{yieldEach}) executing within $f$ are canceled.
+If $f$ is asynchronous then, when $f$ terminates, any open stream subscriptions associated with any asynchronous for loops  (\ref{asynchronousFor-in}) or yield-each statements  (\ref{yieldEach}) executing within $f$ are canceled, in the order of their nesting, innermost first.
 
 \rationale{Such streams may be left open by for loops that were escaped when an exception was thrown within them for example.
 }
 
+%\LMHash{}
+%When a stream is canceled, the implementation must wait for the cancelation future returned by \cd{cancell()} to complete before proceeding.
+
 \LMHash{}
 If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned.  
 
@@ -3775,12 +3779,30 @@
 \LMLabel{ordinaryInvocation}
 
 \LMHash{}
-An ordinary method invocation $i$ has the form 
+An ordinary method invocation can be {\em conditional} or {\em unconditional}.
+
+\LMHash{}
+Evaluation of a {\em conditional ordinary method invocation} $e$ of the form 
+
+\LMHash{}
+$o?.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$  
+
+\LMHash{}
+is equivalent to the evaluation of the expression  
+
+\LMHash{}
+$((x) => x == \NULL ? \NULL : x.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k}))(o)$. 
+
+\LMHash{}
+The static type of $e$ is the same as the static type of $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. Exactly the same static warnings that would be caused by $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ are also generated in the case of $o?.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
+
+\LMHash{}
+An {\em unconditional ordinary method invocation} $i$ has the form 
 
 $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$.
 
 \LMHash{}
-Evaluation of an ordinary method invocation $i$ of the form 
+Evaluation of an unconditional ordinary method invocation $i$ of the form 
 
 $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ 
 
@@ -3812,7 +3834,7 @@
 If  getter lookup has also failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
 \begin{itemize}
 \item  \code{im.isMethod} evaluates to \code{\TRUE{}}.
-\item  \code{im.memberName} evaluates to \code{'m'}.
+\item  \code{im.memberName} evaluates to the symbol \code{m}.
 \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}
@@ -3820,10 +3842,10 @@
 \LMHash{}
 Then the method \code{noSuchMethod()} is looked up in $v_o$ 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 $v_o$ 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'}.
-\item \code{im.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
-\item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
+\item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
+\item  \code{im'.memberName} evaluates to \code{\#noSuchMethod}.
+\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
+\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
 \end{itemize}
 
 and the result of the latter invocation is the result of evaluating $i$.
@@ -3876,6 +3898,12 @@
 \LMHash{}
 A cascaded method invocation expression of the form {\em e..suffix} is equivalent to the expression \code{(t)\{t.{\em suffix}; \RETURN{} t;\}($e$)}.
 
+\rationale{
+With the introduction of null-aware conditional assignable expressions (\ref{assignableExpressions}), it would make sense to extend cascades with a null-aware conditional form as well. One might define {\em e?..suffix}  to be equivalent to the expression \code{(t)\{t?.{\em suffix}; \RETURN{} t;\}($e$)}.
+
+The present specification has not added such a construct, in the interests of simplicity and rapid language evolution. However, Dart implementations may experiment with such constructs, as noted in section \ref{ecmaConformance}.
+}
+
 \subsubsection{Super Invocation}
 \LMLabel{superInvocation}
 
@@ -3905,16 +3933,16 @@
 If  getter lookup has also failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
 \begin{itemize}
 \item  \code{im.isMethod} evaluates to \code{\TRUE{}}.
-\item  \code{im.memberName} evaluates to \code{'m'}.
+\item  \code{im.memberName} evaluates to the symbol \code{m}.
 \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 :
 \begin{itemize}
-\item  \code{im.isMethod} evaluates to \code{\TRUE{}}.
-\item  \code{im.memberName} evaluates to \code{noSuchMethod}.
-\item \code{im.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
-\item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
+\item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
+\item  \code{im'.memberName} evaluates to \code{\#noSuchMethod}.
+\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
+\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
 \end{itemize}
 
 and the result of this latter invocation is the result of evaluating $i$.
@@ -3946,36 +3974,62 @@
 \LMLabel{propertyExtraction}
 
 \LMHash{}
-{\em Property extraction} allows for a member of an object to be concisely extracted from the object.
+{\em Property extraction} allows for a member or constructor to be accessed as a property rather than a function.
 A property extraction can be either:
 \begin{enumerate}
-\item A {\em closurization} (\ref{closurization}) which allows a method to be treated as if it were a getter for a function valued object. Or
+\item A {\em closurization} which converts a method or constructor into a closure. Or
 \item A {\em getter invocation} which returns the result of invoking of a getter method.
 \end{enumerate}
 
+
+\commentary{Closures derived from members via closurization are colloquially known as tear-offs}
+
+Property extraction can be either {\em conditional} or {\em unconditional}.
+
+\rationale {
+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$.
+
+\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.
+}
+
+\LMHash{}
+Unconditional property extraction takes several syntactic forms: $e.m$ (\ref{getterAccessAndMethodExtraction}), $\SUPER.m$ (\ref{superGetterAccessAndMethodClosurization}), $e\#m$ (\ref{generalClosurization}), $\NEW{}$ $T\#m$ (\ref{namedConstructorExtraction}), $\NEW{}$ $T\#$ (\ref{anonymousConstructorExtraction}) and $\SUPER\#m$ (\ref{generalSuperPropertyExtraction}), where $e$ is an expression, $m$ is an identifier optionally followed by an equal sign and $T$ is a type.
+
+\subsubsection{Getter Access and Method Extraction}
+\LMLabel{getterAccessAndMethodExtraction}
+
 \LMHash{}
 Evaluation of a property extraction $i$ of the form $e.m$ proceeds as follows:
 
 \LMHash{}
-First, the expression $e$ is evaluated to an object $o$. Let $f$ be the result of looking up (\ref{methodLookup}) method  (\ref{instanceMethods}) $m$ in $o$ with respect to the current library $L$.  If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $m$ is a method that forwards (\ref{functionDeclarations}) to a static method,  method lookup fails. If method lookup succeeds and $f$ is a concrete method then $i$ evaluates to the closurization of $o.m$.  
+First, the expression $e$ is evaluated to an object $o$. Let $f$ be the result of looking up (\ref{methodLookup}) method  (\ref{instanceMethods}) $m$ in $o$ with respect to the current library $L$.  If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards (\ref{functionDeclarations}) to a static method,  method lookup fails. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}).  
+
+\commentary {
+Note that $f$ is never an abstract method, because method lookup skips abstract methods. Hence, if $m$ refers to an abstract method, we will continue to the next step. However, since methods and getters never override each other, getter lookup will necessarily fail as well, and \cd{noSuchMethod()} will ultimately be invoked. The regrettable implication is that the error will refer to a missing getter rather than an attempt to closurize an abstract method.
+}
 
 \LMHash{}
-Otherwise, $i$ is a getter invocation, and the getter function (\ref{getters}) $m$ is looked up (\ref{getterAndSetterLookup}) in $o$  with respect to $L$. If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $m$ is a getter that forwards  to a static getter,  getter lookup fails. Otherwise, the body of $m$ is executed with \THIS{} bound to $o$.  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
+(\ref{getterAndSetterLookup}) getter (\ref{getters}) $m$ in $o$  with respect to $L$. If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a getter that forwards  to a static getter,  getter lookup fails. Otherwise, the body of $f$ is executed with \THIS{} bound to $o$.  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 :
 \begin{itemize}
 \item  \code{im.isGetter} evaluates to \code{\TRUE{}}.
-\item  \code{im.memberName} evaluates to \code{'m'}.
+\item  \code{im.memberName} evaluates to the symbol \code{m}.
 \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 $o$ 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 $o$ 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}.
-\item \code{im.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
-\item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
+\item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
+\item  \code{im'.memberName} evaluates to \code{\#noSuchMethod}.
+\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
+\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
 \end{itemize}
 
 and the result of this latter invocation is the result of evaluating $i$.
@@ -3996,63 +4050,195 @@
 \end{itemize}
 
 \LMHash{}
-If $i$ is a getter invocation, the static type of $i$ is:
+The static type of $i$ is:
 \begin{itemize}
-\item The declared return type of $T.m$, if $T.m$ exists.
-\item The declared return type of $m$, if  $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ has a static method or getter named $m$.
+\item The declared return type of $T.m$, if $T$  has an accessible instance getter named $m$.
+\item The declared return type of $m$, if  $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static getter named $m$.
+\item The static type of function $T.m$ if $T$ has an accessible instance method named $m$.
+\item The static type of function $m$, if  $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static method named $m$.
 \item  The type \DYNAMIC{} otherwise.  
 \end{itemize}
 
-\LMHash{}
-If $i$ is a closurization, its static type is as described in section \ref{closurization}.
+
+\subsubsection{Super Getter Access and Method Closurization}
+\LMLabel{superGetterAccessAndMethodClosurization}
 
 \LMHash{}
 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 $f$ is a concrete method then $i$ evaluates to the closurization of $\SUPER.m$ with respect to superclass $S$(\ref{closurization}).  
+ 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}).  
  
 \LMHash{}
- Otherwise, $i$ is a getter invocation and the getter function $m$ is looked up in $S$  with respect to $L$, and its body 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$  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 :
 \begin{itemize}
 \item  \code{im.isGetter} evaluates to \code{\TRUE{}}.
-\item  \code{im.memberName} evaluates to \code{'m'}.
+\item  \code{im.memberName} evaluates to the symbol \code{m}.
 \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 :
 \begin{itemize}
-\item  \code{im.isMethod} evaluates to \code{\TRUE{}}.
-\item  \code{im.memberName} evaluates to \code{noSuchMethod}.
-\item \code{im.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
-\item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
+\item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
+\item  \code{im'.memberName} evaluates to \code{\#noSuchMethod}.
+\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
+\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
 \end{itemize}
-
 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 a method or getter named $m$.  If $i$ is a getter invocation, the static type of $i$ is the declared return type of $S.m$, if $S.m$ exists and  \DYNAMIC{} otherwise. If $i$ is a closurization, its static type is as described in section \ref{closurization}.
+It is a static type warning if $S$ 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 type  \DYNAMIC{} otherwise. 
+\end{itemize}
 
 
-\subsubsection{Closurization}
-\LMLabel{closurization}
+\subsubsection{General Closurization}
+\LMLabel{generalClosurization}
 
 \LMHash{}
-The {\em closurization of $o.m$} is defined to be equivalent to:
+Evaluation of a property extraction $i$ of the form $e\#m$ proceeds as follows:
 
+\LMHash{}
+First, the expression $e$ is evaluated to an object $o$.  Then:
+
+\LMHash{}
+ if $m$ is a setter name, let $f$ be the result of looking up setter $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static setter, setter lookup fails. If setter lookup succeeds then $i$ evaluates to the closurization of setter $f$ on object $o$ (\ref{ordinaryMemberClosurization}). 
+ If setter lookup failed, a \cd{NoSuchMethodError} is thrown.
+ 
+  \rationale {
+It would be more in keeping with the rules of Dart to invoke \cd{noSuchMethod} in this and similar cases below. However,  current implementations of \cd{noSuchMethod} cannot distinguish between an invocation of a closurization and an actual call.  It is likely that future versions of Dart will provide a mechanism to detect whether \cd{noSuchMethod} is invoked in response to a closurization, say by means of a getter like \cd{isTearOff}. By being conservative at this stage and insisting on failure, we can ensure that no functioning code will break when/if this functionality is introduced.
+ }
+
+ 
+ \LMHash{}
+If $m$ is not a setter name, let $f$ be the result of looking up method $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static method, method lookup fails. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}).  
+ 
+\LMHash{}
+If method lookup failed, let $f$ be the result of looking up getter $m$ in $o$ with respect to the current library $L$.   If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static getter, getter lookup fails. If getter lookup succeeds then $i$ evaluates to the closurization of getter $f$ on object $o$ (\ref{ordinaryMemberClosurization}).  
+ If getter lookup failed, a \cd{NoSuchMethodError} is thrown.
+ 
+  
+ 
+
+%\LMHash{}
+%Otherwise,  a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
+%\begin{itemize}
+%\item  If $m$ is a setter name, \code{im.isSetter} evaluates to \code{\TRUE{}}; otherwise \code{im.isMethod} evaluates to \code{\TRUE{}}
+%\item  \code{im.memberName} evaluates to the symbol \code{m}.
+%\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 $o$ 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 $o$ 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}.
+%\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
+%\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
+%\end{itemize}
+%and the result of this latter invocation is the result of evaluating $i$.
+
+\LMHash{}
+It is a compile-time error if $e$ is a prefix object (\ref{imports}) and $m$ refers to a type or a member of class \cd{Object}.
+
+\commentary{
+This restriction is in line with other limitations on the use of prefixes as objects. The only permitted uses of $p\#m$ are closurizing top level methods and getters imported via the prefix $p$. Top level methods are directly available by their qualified names: $p.m$. However, getters and setters are not, and allowing their closurization is the whole point of the $e\#m$ syntax.
+}
+
+\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$ is \cd{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static method or getter named $m$.
+\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 The type  \DYNAMIC{} otherwise. 
+\end{itemize}
+
+\subsubsection{Named Constructor Extraction}
+\LMLabel{namedConstructorExtraction}
+
+\LMHash{}
+Evaluation of a property extraction $i$ of the form \NEW{} $T\#m$ proceeds as follows:
+
+\LMHash{}
+If $T$ is a malformed type (\ref{staticTypes}), a dynamic error occurs. If $T$ is a deferred type with prefix $p$, then if $p$ has not been successfully loaded, a dynamic error occurs. If $T$ does not denote a class, a dynamic error occurs. In checked mode, if $T$ or any of its superclasses is malbounded a dynamic error occurs. Otherwise, if the type $T$ does not declare an accessible named constructor $f$ with name $m$, a \cd{NoSuchMethodError} is thrown. Otherwise, $i$ evaluates to the closurization of constructor $f$ of type $T$ (\ref{namedConstructorClosurization}).
+
+\commentary{Note that if $T$ is malformed or malbounded, a static warning occurs, as always.}
+
+\LMHash{}
+The static type of $i$ is the type of the constructor function, if $T$ denotes a class in the surrounding scope with an accessible constructor $f$ named $m$. Otherwise the static type of $i$ is \DYNAMIC{}.
+
+\subsubsection{Anonymous Constructor Extraction}
+\LMLabel{anonymousConstructorExtraction}
+
+\LMHash{}
+Evaluation of a property extraction $i$ of the form \NEW{} $T\#$ proceeds as follows:
+
+\LMHash{}
+If $T$ is a malformed type (\ref{staticTypes}), a dynamic error occurs. If $T$ is a deferred type with prefix $p$, then if $p$ has not been successfully loaded, a dynamic error occurs. If $T$ does not denote a class, a dynamic error occurs. In checked mode, if $T$ or any of its superclasses is malbounded a dynamic error occurs. Otherwise, if the type $T$ does not declare an accessible anonymous constructor, a \cd{NoSuchMethodError} is thrown. Otherwise, $i$ evaluates to the closurization of the anonymous constructor of type $T$ (\ref{anonymousConstructorClosurization}).
+
+\commentary{Again, note that if $T$ is malformed or malbounded, existing rules ensure that a static warning occurs. This also means that $x\#$ where $x$ is not a type will always give a static warning.}
+
+\LMHash{}
+The static type of $i$ is the type of the constructor function $T()$, if $T$ denotes a class in the surrounding scope with an anonymous constructor $T()$. Otherwise the static type of $i$ is \DYNAMIC{}.
+
+\subsubsection{General Super Property Extraction}
+\LMLabel{generalSuperPropertyExtraction}
+
+
+\LMHash{}
+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.
+
+ \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 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}).
+
+\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.
+
+\LMHash{}
+It is a static type warning if $S$ 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{}.
+
+
+
+\subsubsection{Ordinary Member Closurization}
+\LMLabel{ordinaryMemberClosurization}
+
+
+\LMHash{}
+Let $o$ be an object, and let $u$ be a fresh final variable bound to $o$.
+The {\em closurization of method $f$ on object $o$} is defined to be equivalent to:
+\begin{itemize}
+\item $(a) \{\RETURN{}$ $u$ $op$ $a;$\} if $f$ is named $op$ and $op$ is one of  \code{$<$, $>$, $<$=, $>$=, ==,  -, +, /, \~{}/, *, \%, $|$, \^{}, \&, $<<$, $>>$} (this precludes closurization of unary -).
+\item $() \{\RETURN{}$ \~{} $u;$\} if $f$ is named \~{}.
+\item $(a) \{\RETURN{}$ $u[a];$\} if $f$ is named $[]$.
+\item $(a, b) \{\RETURN{}$ $u[a] = b;$\} if $f$ is named $[]=$.
 \item  
 \begin{dartCode}
 $(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{
   \RETURN{} $ u.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$
 \} 
 \end{dartCode}
-
-if $m$ has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
 \item 
 \begin{dartCode}
 $(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
@@ -4060,14 +4246,18 @@
 \}
 \end{dartCode}
 
-if $m$ has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
 \end{itemize}
 
-where $u$ is a fresh final variable bound to $o$, except that:
-\begin{enumerate}
-\item  Iff  \code{identical($o_1, o_2$)}  then \cd{$o_1.m$ == $o_2.m$}.
-\item The static type of the property extraction is the static type of function $T.m$, where $T$ is the static type of $e$, if $T.m$ is defined. Otherwise the static type of $e.m$ is \DYNAMIC{}.
-\end{enumerate}
+\LMHash{}
+Except that iff  \code{identical($o_1, o_2$)}  then  \cd{$o_1\#m$ == $o_2\#m$},  \cd{$o_1.m$ == $o_2.m$}, \cd{$o_1\#m$ == $o_2.m$} and  \cd{$o_1.m$ == $o_2\#m$}.
+%\item The static type of the property extraction is the static type of function $T.m$, where $T$ is the static type of $e$, if $T.m$ is defined. Otherwise the static type of $e.m$ is \DYNAMIC{}.
+
+\LMHash{}
+The {\em closurization of getter $f$ on object $o$} is defined to be equivalent to \cd{()\{\RETURN{} u.m;\}} if $f$ is named $m$, except that iff  \code{identical($o_1, o_2$)} then  \cd{$o_1\#m$ == $o_2\#m$}.
+
+\LMHash{}
+The {\em closurization of setter $f$ on object $o$} is defined to be equivalent to \cd{(a)\{\RETURN{} u.m = a;\}} if $f$ is named $m=$, except that iff  \code{identical($o_1, o_2$)} then \cd{$o_1\#m=$ == $o_2\#m=$}.
 
 \commentary{
 There is no guarantee that \cd{identical($o_1.m, o_2.m$)}. Dart implementations are not required to canonicalize these or any other closures.
@@ -4078,50 +4268,112 @@
 The special treatment of equality in this case facilitates the use of extracted property functions in APIs where callbacks such as event listeners must often be registered and later unregistered. A common example is the DOM API in web browsers.
 }
 
+\commentary {
+Observations:
+
+One cannot closurize a constructor, getter or a setter via the dot based syntax. One must use the \# based form. One can tell whether one implemented a property via a method or via a field/getter, which means that one has to plan ahead as to what construct to use, and that choice is reflected in the interface of the class.
+}
 
 
 
-\commentary{Observations:
-\begin{enumerate}
-\item One cannot closurize a getter or a setter.
-\item One can tell whether one implemented a property via a method or via a field/getter, which means that one has to plan ahead as to what construct to use, and that choice is reflected in the interface of the class.
-\end{enumerate}
-} 
+\subsubsection{Named Constructor Closurization}
+\LMLabel{namedConstructorClosurization}
 
-
- 
 \LMHash{}
-The closurization of $\SUPER{}.m$ with respect to superclass $S$ is defined to be equivalent to:
-
+The {\em closurization of constructor $f$ of type $T$} is defined to be equivalent to:
 \begin{itemize}
- %\item $(r_1, \ldots, r_n)\{\RETURN{}$ $o.m(r_1, \ldots, r_n);\}$ if $m$ has only required parameters $r_1, \ldots r_n$.
-%\item $(r_1, \ldots, r_n, rest)\{return$  $o.m(r_1, \ldots, r_n, rest);\}$ if $m$ has required parameters $r_1, \ldots r_n$, and a rest parameter $rest$.
-%\item
 \item  
 \begin{dartCode}
-$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$\{
-   \RETURN{} \SUPER{}$.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k)$;
-\}
-\end{dartCode}
-
-if $m$ has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
-\item 
-\begin{dartCode}
-$(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
-   \RETURN{} \SUPER{}$.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$;
+$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{
+  \RETURN{} \NEW{} $T.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$
 \} 
 \end{dartCode}
 
-if $m$ has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+if $f$ is a named constructor with name $m$ that has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+\item 
+\begin{dartCode}
+$(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
+  \RETURN{} \NEW{} $T.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$;
+\}
+\end{dartCode}
+
+if $f$ is a named constructor with name $m$ that has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
 \end{itemize}
 
 \LMHash{}
-Except that:
-\begin{enumerate}
-\item  iff  \code{identical($o_1, o_2$)}  then \cd{$o_1.m$ == $o_2.m$}.
+Except that iff  \code{identical($T_1, T_2$)}  then  \cd{\NEW{} $T_1\#m$ == \NEW{} $T_2\#m$}.
+
+\commentary{ 
+The above implies that for non-parameterized types, one can rely on the equality of closures resulting from closurization on the ``same'' type. For parameterized types, one cannot, since there is no requirement to canonicalize them.
+}
+
+\subsubsection{Anonymous Constructor Closurization}
+\LMLabel{anonymousConstructorClosurization}
+
+\LMHash{}
+The {\em closurization of anonymous constructor $f$ of type $T$} is defined to be equivalent to:
+\begin{itemize}
+\item  
+\begin{dartCode}
+$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{
+  \RETURN{} \NEW{} $T(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$
+\} 
+\end{dartCode}
+
+if $f$ is an anonymous constructor that has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
 \item 
-The static type of the property extraction is the static type of the method $S.m$,  if $S.m$ is defined. Otherwise the static type of $\SUPER{}.m$ is \DYNAMIC{}.
-\end{enumerate}
+\begin{dartCode}
+$(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
+  \RETURN{} \NEW{} $T(r_1, \ldots, r_n, p_1, \ldots, p_k)$;
+\}
+\end{dartCode}
+
+if $f$ is an anonymous constructor that has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+\end{itemize}
+
+\LMHash{}
+Except that iff  \code{identical($T_1, T_2$)}  then  \cd{\NEW{} $T_1\#$ == \NEW{} $T_2\#$}.
+
+
+\subsubsection{Super Closurization}
+\LMLabel{superClosurization}
+
+\LMHash{}
+The {\em closurization of method $f$ with respect to superclass $S$} is defined to be equivalent to:
+
+\LMHash{}
+\begin{itemize}
+\item $(a) \{\RETURN{}$ \SUPER{} $op$ $a;$\} if $f$ is named $op$ and $op$ is one of  \code{$<$, $>$, $<$=, $>$=, ==,  -, +, /, \~{}/, *, \%, $|$, \^{}, \&, $<<$, $>>$}.
+\item $() \{\RETURN{}$ \~{}\SUPER;\} if $f$ is named \~{}.
+\item $(a) \{\RETURN{}$ $\SUPER[a];$\} if $f$ is named $[]$.
+\item $(a, b) \{\RETURN{}$ $\SUPER[a] = b;$\} if $f$ is named $[]=$.
+\item  
+\begin{dartCode}
+$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{
+  \RETURN{} \SUPER$.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$
+\} 
+\end{dartCode}
+if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+\item 
+\begin{dartCode}
+$(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{
+  \RETURN{} \SUPER$.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$;
+\}
+\end{dartCode}
+
+if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$.
+\end{itemize}
+
+\LMHash{}
+Except that iff two closurizations were created by code declared in the same class with identical bindings of \THIS{} then  \cd{\SUPER$_1\#m$ == \SUPER$_2\#m$},  \cd{\SUPER$_1.m$ == \SUPER$_2.m$}, \cd{\SUPER$_1\#m$ == \SUPER$_2.m$} and  \cd{\SUPER$_1.m$ == \SUPER$_2\#m$}.
+
+
+\LMHash{}
+The {\em closurization of getter $f$  with respect to superclass $S$} is defined to be equivalent to \cd{()\{\RETURN{} \SUPER.m;\}} if $f$ is named $m$, except that iff two closurizations were created by code declared in the same class with identical bindings of \THIS{} then  \cd{\SUPER$_1\#m$ == \SUPER$_2\#m$}.
+
+\LMHash{}
+The {\em closurization of setter $f$  with respect to superclass $S$} is defined to be equivalent to \cd{(a)\{\RETURN{} \SUPER.m = a;\}} if $f$ is named $m=$, except that iff two closurizations were created by code declared in the same class with identical bindings of \THIS{} then \cd{\SUPER$_1\#m=$ == \SUPER$_2\#m=$}.
+
 
 
 \subsection{ Assignment}
@@ -4174,6 +4426,9 @@
 It is a static type warning if the static type of $e$ may not be assigned to the static type of $v$. The static type of the expression $v$ \code{=} $e$ is the static type of $e$.
 
 \LMHash{}
+Evaluation of an assignment $a$ of the form $e_1?.v$ \code{=} $e_2$ is equivalent to the evaluation of the expression $((x) => x == \NULL? \NULL: x.v = e_2)(e_1)$. The static type of $a$ is the static type of $e_2$. 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.v = e_2$ are also generated in the case of $e_1?.v$ \code{=} $e_2$.
+
+\LMHash{}
 Evaluation of an assignment of the form $e_1.v$ \code{=} $e_2$ proceeds as follows:
 
 \LMHash{}
@@ -4183,7 +4438,7 @@
 If the setter lookup has failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
 \begin{itemize}
 \item  \code{im.isSetter} evaluates to \code{\TRUE{}}.
-\item  \code{im.memberName} evaluates to \code{'v='}.
+\item  \code{im.memberName} evaluates to the symbol \code{v=}.
 \item \code{im.positionalArguments} evaluates to an immutable list with the same values as \code{[$o_2$]}.
 \item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
 \end{itemize}
@@ -4192,10 +4447,10 @@
 Then the method \code{noSuchMethod()} is looked up in $o_1$ 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 $o_1$ 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}.
-\item \code{im.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
-\item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
+\item  \code{im'.isMethod} evaluates to \code{\TRUE{}}.
+\item  \code{im'.memberName} evaluates to \code{\#noSuchMethod}.
+\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
+\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
 \end{itemize}
 
 \LMHash{}
@@ -4217,8 +4472,55 @@
 It is a static type warning if the static type of $e_2$ may not be assigned to the static type of the formal parameter of the setter $v=$.   The static type of the expression $e_1.v$ \code{=} $e_2$ is the static type of $e_2$.
 
 \LMHash{}
+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{}. 
+
+\LMHash{}
+If the setter lookup has failed, then a new instance $im$  of the predefined class  \code{Invocation}  is created, such that :
+\begin{itemize}
+\item  \code{im.isSetter} evaluates to \code{\TRUE{}}.
+\item  \code{im.memberName} evaluates to the symbol \code{v=}.
+\item \code{im.positionalArguments} evaluates to an immutable list with the same values as \code{[$o$]}.
+\item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
+\end{itemize}
+
+\LMHash{}
+Then the method \code{noSuchMethod()} is looked up in $S$ 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{}}.
+\item  \code{im'.memberName} evaluates to \code{\#noSuchMethod}.
+\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is  $im$.
+\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}.
+\end{itemize}
+
+\LMHash{}
+The value of the assignment expression is $o$ irrespective of whether setter lookup has failed or succeeded.
+
+\LMHash{}
+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}. 
+
+\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$.
+
+
+
+
+
+
+\LMHash{}
 Evaluation of an assignment of the form $e_1[e_2]$ \code{=} $e_3$ is equivalent to the evaluation of the expression \code{(a, i, e)\{a.[]=(i, e); \RETURN{} e; \} ($e_1, e_2, e_3$)}.  The static type of the expression $e_1[e_2]$ \code{=} $e_3$ is the static type of $e_3$.
 
+\LMHash{}
+An assignment of the form $\SUPER[e_1]$ \code{=} $e_2$ is equivalent to the expression $\SUPER.[e_1]$ \code{=} $e_2$.  The static type of the expression $\SUPER[e_1]$ \code{=} $e_2$ is the static type of $e_2$.
+
+
 % Should we add: It is a dynamic error if $e_1$ evaluates to an  constant list or map.
 
 \LMHash{}
@@ -4233,9 +4535,35 @@
 \LMLabel{compoundAssignment}
 
 \LMHash{}
-A compound assignment of the form $v$ $op\code{=} e$ is equivalent to $v \code{=} v$ $op$ $e$. A compound assignment of the form $C.v$ $op \code{=} e$ is equivalent to $C.v \code{=} C.v$ $op$ $e$. 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$. A compound assignment of the form  $e_1[e_2]$ $op\code{=} e_3$ is equivalent to 
+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  
+$((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{}
+Evaluation of a compound assignment of the form $e_1?.v$  {\em ??=} $e_2$ is equivalent to the evaluation of the expression \code{((x) $=>$ x == \NULL{} ?  \NULL: $x.v ??=  e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. 
+
+
+\LMHash{}
+The static type of a compound assignment of the form $v$ {\em ??=} $e$ is the least upper bound of the static type of $v$ and the static type of $e$.  Exactly the same static warnings that would be caused by $v = e$ are also generated in the case of $v$ {\em ??=} $e$.
+
+
+\LMHash{}
+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$.
+
+\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$.
+
+\LMHash{}
+The static type of a compound assignment of the form $\SUPER.v$  {\em ??=} $e$  is the least upper bound of the static type of $\SUPER.v$ and the static type of $e$. Exactly the same static warnings that would be caused by $\SUPER.v = e$ are also generated in the case of $\SUPER.v$  {\em ??=} $e$.
+
+\LMHash{}
+For any other valid operator $op$, a compound assignment of the form $v$ $op\code{=} e$ is equivalent to $v \code{=} v$ $op$ $e$. A compound assignment of the form $C.v$ $op \code{=} e$ is equivalent to $C.v \code{=} C.v$ $op$ $e$. 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$. A compound assignment of the form  $e_1[e_2]$ $op\code{=} e_3$ is equivalent to 
 \code{((a, i) $=>$ a[i] = a[i] $op$ $e_3$)($e_1, e_2$)} where $a$ and $i$ are a variables that are not used in $e_3$. 
 
+\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$.
 
 \begin{grammar}
 {\bf compoundAssignmentOperator:}`*=';
@@ -4248,7 +4576,8 @@
        `{\escapegrammar \gt \gt}=';
       `\&=';
       `\^{}=';
-      `$|$='
+      `$|$=';
+      `??=';
     .
 \end{grammar}
 
@@ -4261,7 +4590,7 @@
 
 \begin{grammar}
   {\bf conditionalExpression:}
-     logicalOrExpression (`?' expressionWithoutCascade `{\escapegrammar :}' expressionWithoutCascade)?
+     ifNullExpression (`?' expressionWithoutCascade `{\escapegrammar :}' expressionWithoutCascade)?
     . % the first  branches could  top level expressions, it seems, but certainly NOT the second
 \end{grammar}
 
@@ -4284,6 +4613,21 @@
 
 \LMHash{}
  It is a static type warning if the static type of $e_1$ may not be assigned to \code{bool}.  The static type of $c$ is the least upper bound (\ref{leastUpperBounds}) of the static type of $e_2$ and the static type of $e_3$.
+ 
+   
+ \subsection{If-null Expressions}
+ \label{ifNull}
+ 
+ \LMHash{}
+ An {\em if-null expression}evaluates an expression and if the result is \NULL, evaluates another.
+
+\begin{grammar}
+{\bf ifNullExpression:}
+  logicalOrExpression (`??' logicalOrExpression)*
+\end{grammar}
+  
+\LMHash{}
+Evaluation of an if-null expression $e$ of the form $e_1??e_2 $ is equivalent to the evaluation of the expression $((x) => x == \NULL? e_2: x)(e_1)$. The static type of $e$ is least upper bound (\ref{leastUpperBounds}) of the static type of $e_1$ and the static type of $e_2$.
   
 
 \subsection{ Logical Boolean Expressions}
@@ -4633,7 +4977,7 @@
 
  \begin{grammar}
 {\bf postfixExpression:}assignableExpression postfixOperator;
-      primary selector*
+      primary (selector* $|$ ( `\#' ( (identifier `='?) $|$ operator)))
     .
 
 {\bf postfixOperator:}
@@ -4711,21 +5055,27 @@
 \begin{grammar}
 
 {\bf assignableExpression:}primary (arguments* assignableSelector)+;
-      \SUPER{} assignableSelector;
+      \SUPER{} unconditionalAssignableSelector;
       identifier
     .
     
-{\bf assignableSelector:}`[' expression `]'; % again, could be top level
-      `{\escapegrammar .}' identifier
+{\bf unconditionalAssignableSelector:}`[' expression `]'; % again, could be top level
+         `{\escapegrammar .}' identifier
+    .
+
+{\bf assignableSelector:}
+         unconditionalAssignableSelector;
+         `{\escapegrammar ?.}' identifier
     .
 
 \end{grammar}
 
+
 \LMHash{}
 An {\em assignable expression} is either:
 \begin{itemize}
  \item An identifier. 
-\item An invocation of a getter (\ref{getters}) or list access operator on an expression $e$.
+\item An invocation (possibly conditional) of a getter (\ref{getters}) or list access operator on an expression $e$.
 \item An invocation of a getter or list access operator on  \SUPER{}.
 \end{itemize}
 
@@ -4736,7 +5086,7 @@
 %An assignable expression of the form $e.id(a_1, \ldots, a_n)$ is evaluated as a method invocation (\ref{methodInvocation}).
 
 \LMHash{}
-An assignable expression of the form $e.id$ is evaluated as a property extraction  (\ref{propertyExtraction}).
+An assignable expression of the form $e.id$ or $e?.id$ is evaluated as a property extraction  (\ref{propertyExtraction}).
 
 \LMHash{}
 An assignable expression of the form \code{$e_1$[$e_2$]} is evaluated as a method invocation of the operator method \code{[]} on $e_1$ with argument $e_2$.
@@ -5667,7 +6017,7 @@
 A finally clause \FINALLY{} $s$ defines an exception handler $h$ that executes as follows:
 
 \LMHash{}
-Let $r$ be the current return value (\ref{return}). Then the current return value becomes undefined. Any open streams associated with any asynchronous for loops (\ref{asynchronousFor-in}) and yield-each (\ref{yieldEach}) statements executing within the dynamic scope of $h$ are canceled. 
+Let $r$ be the current return value (\ref{return}). Then the current return value becomes undefined. Any open streams associated with any asynchronous for loops (\ref{asynchronousFor-in}) and yield-each (\ref{yieldEach}) statements executing within the dynamic scope of $h$ are canceled, in the order of their nesting, innermost first. 
 
 \rationale{
 Streams left open by for loops that were escaped for whatever reason would be canceled at function termination, but it is best to cancel them as soon as possible.
@@ -5873,7 +6223,7 @@
 Let $s_b$ be a \BREAK{} statement. If $s_b$ is of the form  \code{\BREAK{} $L$;}, then let $s_E$ be the the innermost labeled statement with label $L$ enclosing $s_b$. If $s_b$ is of the form \code{\BREAK{};},  then let $s_E$ be the the innermost  \DO{} (\ref{do}), \FOR{} (\ref{for}), \SWITCH{} (\ref{switch}) or \WHILE{} (\ref{while}) statement enclosing  $s_b$. It is a compile-time error if no such statement $s_E$ exists within the innermost function in which  $s_b$ occurs.  Furthermore, let $s_1, \ldots, s_n$ be those \TRY{} statements that are both enclosed in $s_E$ and that enclose  $s_b$, and that have a \FINALLY{} clause. Lastly, let $f_j$ be the \FINALLY{} clause of $s_j, 1 \le j \le n$.   Executing  $s_b$ first executes $f_1, \ldots,  f_n$ in innermost-clause-first  order and then terminates $s_E$. 
 
 \LMHash{}
-If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), its associated stream subscription is canceled. Furthermore, let $a_k$ be the set of asynchronous for loops  and yield-each statements (\ref{yieldEach}) enclosing $s_b$ that are enclosed in $s_E , 1 \le k \le m$.   The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$. 
+If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), its associated stream subscription is canceled. Furthermore, let $a_k$ be the set of asynchronous for loops  and yield-each statements (\ref{yieldEach}) enclosing $s_b$ that are enclosed in $s_E , 1 \le k \le m$, where $a_k$ is enclosed in $a_{k+1}$.   The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$, innermost first, so that $a_j$ is canceled before $a_{j+1}$. 
 
 
 
@@ -5897,7 +6247,7 @@
  }
  
 \LMHash{}
- If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), let $a_k$ be the set of asynchronous for loops and yield-each statements (\ref{yieldEach}) enclosing $s_c$ that are enclosed in $s_E , 1 \le k \le m$.   The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$. 
+ If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), let $a_k$ be the set of asynchronous for loops and yield-each statements (\ref{yieldEach}) enclosing $s_c$ that are enclosed in $s_E , 1 \le k \le m$, where $a_k$ is enclosed in $a_{k+1}$.   The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$, innermost first, so that $a_j$ is canceled before $a_{j+1}$. 
  
  \subsection{ Yield and Yield-Each}
  \LMLabel{yieldAndYieldEach}
@@ -7222,29 +7572,31 @@
 \hline
 Description &  Operator & Associativity & Precedence \\ 
 \hline
-Unary postfix &  ., e++, e--, e1[e2], e1() , () & None & 15 \\
+Unary postfix &  ., ?., e++, e--, e1[e2], e1() , () & None & 16 \\
 \hline
-Unary prefix & -e, !e, \~{}e, ++e, --e & None & 14\\
+Unary prefix & -e, !e, \~{}e, ++e, --e & None & 15\\
 \hline
-Multiplicative & *, /, \~/,  \%  & Left & 13\\
+Multiplicative & *, /, \~/,  \%  & Left & 14\\
 \hline
-Additive & +, - & Left & 12\\
+Additive & +, - & Left & 13\\
 \hline 
-Shift &  $<<$, $>>$&  Left & 11\\
+Shift &  $<<$, $>>$&  Left & 12\\
 \hline
-Bitwise AND & \& & Left & 10\\
+Bitwise AND & \& & Left & 11\\
 \hline
-Bitwise XOR & \^{} & Left & 9\\
+Bitwise XOR & \^{} & Left & 10\\
 \hline
-Bitwise Or &  $|$ & Left & 8\\
+Bitwise Or &  $|$ & Left & 9\\
 \hline
-Relational & $<$, $>$, $<=$, $>=$, \AS{}, \IS{}, \IS{}! &  None & 7\\
+Relational & $<$, $>$, $<=$, $>=$, \AS{}, \IS{}, \IS{}! &  None & 8\\
 \hline
-Equality &  ==, != & None & 6\\
+Equality &  ==, != & None & 7\\
 \hline
-Logical AND & \&\& & Left & 5\\
+Logical AND & \&\& & Left & 6\\
 \hline
-Logical Or &  $||$ & Left & 4\\
+Logical Or &  $||$ & Left & 5\\
+\hline
+If-null & ?? & Left & 4\\
 \hline
 Conditional &  e1? e2: e3 & Right & 3\\
 \hline
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index f0dac74..59a5359 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -43,7 +43,7 @@
 </style></head>
   <body>
     <h1>Analysis Server API Specification</h1>
-    <h1 style="color:#999999">Version 1.5.0</h1>
+    <h1 style="color:#999999">Version 1.6.0</h1>
     <p>
       This document contains a specification of the API provided by the
       analysis server.  The API in this document is currently under
@@ -2224,25 +2224,31 @@
         
       <dl><dt class="field"><b><i>enableAsync ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
             
-            <p><b><i>Deprecated</i></b>/</p><p>
-            </p><p>
+            <p><b><i>Deprecated</i></b></p>
+            <p>
               True if the client wants to enable support for the
               proposed async feature.
             </p>
           </dd><dt class="field"><b><i>enableDeferredLoading ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
             
-            <p><b><i>Deprecated</i></b>/</p><p>
-            </p><p>
+            <p><b><i>Deprecated</i></b></p>
+            <p>
               True if the client wants to enable support for the
               proposed deferred loading feature.
             </p>
           </dd><dt class="field"><b><i>enableEnums ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
             
-            <p><b><i>Deprecated</i></b>/</p><p>
-            </p><p>
+            <p><b><i>Deprecated</i></b></p>
+            <p>
               True if the client wants to enable support for the
               proposed enum feature.
             </p>
+          </dd><dt class="field"><b><i>enableNullAwareOperators ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
+            
+            <p>
+              True if the client wants to enable support for the
+              proposed "null aware operators" feature.
+            </p>
           </dd><dt class="field"><b><i>generateDart2jsHints ( <span style="color:#999999">optional</span> bool )</i></b></dt><dd>
             
             <p>
@@ -3129,6 +3135,12 @@
               which does not match a file currently subject to
               analysis.
             </p>
+          </dd><dt class="value">INVALID_ANALYSIS_ROOT</dt><dd>
+            
+            <p>
+              A path passed as an argument to a request (such as
+              analysis.reanalyze) is required to be an analysis root, but isn't.
+            </p>
           </dd><dt class="value">INVALID_EXECUTION_CONTEXT</dt><dd>
             
             <p>
@@ -3212,6 +3224,12 @@
               not recognize, or cannot handle in its current
               configuation.
             </p>
+          </dd><dt class="value">UNKNOWN_SOURCE</dt><dd>
+            
+            <p>
+              The analysis server was requested to perform an action
+              on a source that does not exist.
+            </p>
           </dd><dt class="value">UNSUPPORTED_FEATURE</dt><dd>
             
             <p>
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index bad954c..706b382 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -66,7 +66,7 @@
    * The version of the analysis server. The value should be replaced
    * automatically during the build.
    */
-  static final String VERSION = '1.5.0';
+  static final String VERSION = '1.6.0';
 
   /**
    * The number of milliseconds to perform operations before inserting
@@ -463,6 +463,14 @@
         return new ContextSourcePair(context, source);
       }
     }
+    // try to find a context for which the file is a priority source
+    for (InternalAnalysisContext context in folderMap.values) {
+      List<Source> sources = context.getSourcesWithFullName(path);
+      if (sources.isNotEmpty) {
+        Source source = sources.first;
+        return new ContextSourcePair(context, source);
+      }
+    }
     // file-based source
     Source fileSource = file != null ? file.createSource() : null;
     return new ContextSourcePair(null, fileSource);
@@ -733,14 +741,21 @@
   }
 
   /**
-   * Trigger reanalysis of all files from disk.
+   * Trigger reanalysis of all files in the given list of analysis [roots], or
+   * everything if the analysis roots is `null`.
    */
-  void reanalyze() {
+  void reanalyze(List<Resource> roots) {
     // Clear any operations that are pending.
-    operationQueue.clear();
+    if (roots == null) {
+      operationQueue.clear();
+    } else {
+      for (AnalysisContext context in _getContexts(roots)) {
+        operationQueue.contextRemoved(context);
+      }
+    }
     // Instruct the contextDirectoryManager to rebuild all contexts from
     // scratch.
-    contextDirectoryManager.refresh();
+    contextDirectoryManager.refresh(roots);
   }
 
   /**
@@ -916,10 +931,27 @@
         new HashMap<AnalysisContext, List<Source>>();
     List<String> unanalyzed = new List<String>();
     Source firstSource = null;
-    files.forEach((file) {
+    files.forEach((String file) {
       ContextSourcePair contextSource = getContextSourcePair(file);
       AnalysisContext preferredContext = contextSource.context;
       Source source = contextSource.source;
+      // Try to make the file analyzable.
+      // If it is not in any context yet, add it to the first one which
+      // could use it, e.g. imports its package, even if not the library.
+      if (preferredContext == null) {
+        Resource resource = resourceProvider.getResource(file);
+        if (resource is File && resource.exists) {
+          for (AnalysisContext context in folderMap.values) {
+            Uri uri = context.sourceFactory.restoreUri(source);
+            if (uri.scheme != 'file') {
+              preferredContext = context;
+              source = ContextManager.createSourceInContext(context, resource);
+              break;
+            }
+          }
+        }
+      }
+      // Fill the source map.
       bool contextFound = false;
       for (AnalysisContext context in folderMap.values) {
         if (context == preferredContext ||
@@ -1038,10 +1070,24 @@
         throw new AnalysisException('Illegal change type');
       }
       overlayState.setContents(source, newContents);
+      // If the source does not exist, then it was an overlay-only one.
+      // Remove it from contexts.
+      if (newContents == null && !source.exists()) {
+        for (InternalAnalysisContext context in folderMap.values) {
+          List<Source> sources = context.getSourcesWithFullName(file);
+          ChangeSet changeSet = new ChangeSet();
+          sources.forEach(changeSet.removedSource);
+          context.applyChanges(changeSet);
+          schedulePerformAnalysisOperation(context);
+        }
+        return;
+      }
       // Update all contexts.
+      bool anyContextUpdated = false;
       for (InternalAnalysisContext context in folderMap.values) {
         List<Source> sources = context.getSourcesWithFullName(file);
         sources.forEach((Source source) {
+          anyContextUpdated = true;
           if (context.handleContentsChanged(
               source, oldContents, newContents, true)) {
             schedulePerformAnalysisOperation(context);
@@ -1067,6 +1113,16 @@
           }
         });
       }
+      // The source is not analyzed by any context, add to the containing one.
+      if (!anyContextUpdated) {
+        AnalysisContext context = contextSource.context;
+        if (context != null && source != null) {
+          ChangeSet changeSet = new ChangeSet();
+          changeSet.addedSource(source);
+          context.applyChanges(changeSet);
+          schedulePerformAnalysisOperation(context);
+        }
+      }
     });
   }
 
@@ -1096,6 +1152,20 @@
   }
 
   /**
+   * Return a set of contexts containing all of the resources in the given list
+   * of [resources].
+   */
+  Set<AnalysisContext> _getContexts(List<Resource> resources) {
+    Set<AnalysisContext> contexts = new HashSet<AnalysisContext>();
+    resources.forEach((Resource resource) {
+      if (resource is Folder) {
+        contexts.addAll(contextDirectoryManager.contextsInAnalysisRoot(resource));
+      }
+    });
+    return contexts;
+  }
+
+  /**
    * Returns the [CompilationUnit] of the Dart file with the given [source] that
    * should be used to resend notifications for already resolved unit.
    * Returns `null` if the file is not a part of any context, library has not
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index aad7ca3..ceafb22e 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -95,17 +95,20 @@
         // description
         hover.elementDescription = element.toString();
         hover.elementKind = element.kind.displayName;
-        // containing class
-        ClassElement containingClass =
-            element.getAncestor((e) => e is ClassElement);
-        if (containingClass != null) {
-          hover.containingClassDescription = containingClass.toString();
-        }
-        // containing library
-        LibraryElement library = element.library;
-        if (library != null) {
-          hover.containingLibraryName = library.name;
-          hover.containingLibraryPath = library.source.fullName;
+        // not local element
+        if (element.enclosingElement is! ExecutableElement) {
+          // containing class
+          ClassElement containingClass =
+              element.getAncestor((e) => e is ClassElement);
+          if (containingClass != null) {
+            hover.containingClassDescription = containingClass.toString();
+          }
+          // containing library
+          LibraryElement library = element.library;
+          if (library != null) {
+            hover.containingLibraryName = library.name;
+            hover.containingLibraryPath = library.source.fullName;
+          }
         }
         // documentation
         String dartDoc = element.computeDocumentationComment();
diff --git a/pkg/analysis_server/lib/src/computer/computer_overrides.dart b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
index c47e127..ba7cb76 100644
--- a/pkg/analysis_server/lib/src/computer/computer_overrides.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
@@ -45,6 +45,30 @@
     return _overrides;
   }
 
+  void _addInterfaceOverrides(List<engine.Element> elements, String name,
+      engine.InterfaceType type, bool checkType,
+      Set<engine.InterfaceType> visited) {
+    if (type == null) {
+      return;
+    }
+    if (!visited.add(type)) {
+      return;
+    }
+    // check type
+    if (checkType) {
+      engine.Element element = _lookupMember(type.element, name);
+      if (element != null) {
+        elements.add(element);
+      }
+    }
+    // check interfaces
+    for (engine.InterfaceType interfaceType in type.interfaces) {
+      _addInterfaceOverrides(elements, name, interfaceType, true, visited);
+    }
+    // check super
+    _addInterfaceOverrides(elements, name, type.superclass, checkType, visited);
+  }
+
   void _addOverride(int offset, int length, String name) {
     // super
     engine.Element superEngineElement;
@@ -56,21 +80,15 @@
     }
     // interfaces
     List<engine.Element> interfaceEngineElements = <engine.Element>[];
-    for (engine.InterfaceType interfaceType in _currentClass.interfaces) {
-      engine.ClassElement interfaceElement = interfaceType.element;
-      engine.Element interfaceMember = _lookupMember(interfaceElement, name);
-      if (interfaceMember != null) {
-        interfaceEngineElements.add(interfaceMember);
-      }
-    }
+    _addInterfaceOverrides(interfaceEngineElements, name, _currentClass.type,
+        false, new Set<engine.InterfaceType>());
     // is there any override?
     if (superEngineElement != null || interfaceEngineElements.isNotEmpty) {
       OverriddenMember superMember = superEngineElement != null
           ? newOverriddenMember_fromEngine(superEngineElement)
           : null;
       List<OverriddenMember> interfaceMembers = interfaceEngineElements
-          .map(
-              (engine.Element member) => newOverriddenMember_fromEngine(member))
+          .map((member) => newOverriddenMember_fromEngine(member))
           .toList();
       _overrides.add(new Override(offset, length,
           superclassMember: superMember,
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 058662c..b52f6ad 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -163,13 +163,39 @@
   }
 
   /**
-   * Rebuild the set of contexts from scratch based on the data last sent to
-   * setRoots().
+   * Return a list containing all of the contexts contained in the given
+   * [analysisRoot].
    */
-  void refresh() {
+  List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) {
+    List<AnalysisContext> contexts = <AnalysisContext>[];
+    _contexts.forEach((Folder contextFolder, _ContextInfo info) {
+      if (analysisRoot.isOrContains(contextFolder.path)) {
+        contexts.add(info.context);
+      }
+    });
+    return contexts;
+  }
+
+  /**
+   * Rebuild the set of contexts from scratch based on the data last sent to
+   * setRoots(). Only contexts contained in the given list of analysis [roots]
+   * will be rebuilt, unless the list is `null`, in which case every context
+   * will be rebuilt.
+   */
+  void refresh(List<Resource> roots) {
     // Destroy old contexts
     List<Folder> contextFolders = _contexts.keys.toList();
-    contextFolders.forEach(_destroyContext);
+    if (roots == null) {
+      contextFolders.forEach(_destroyContext);
+    } else {
+      roots.forEach((Resource resource) {
+        contextFolders.forEach((Folder contextFolder) {
+          if (resource is Folder && resource.isOrContains(contextFolder.path)) {
+            _destroyContext(contextFolder);
+          }
+        });
+      });
+    }
 
     // Rebuild contexts based on the data last sent to setRoots().
     setRoots(includedPaths, excludedPaths, packageRoots);
@@ -335,7 +361,7 @@
     for (Resource child in children) {
       String path = child.path;
       // ignore excluded files or folders
-      if (_isExcluded(path)) {
+      if (_isExcluded(path) || info.excludes(path)) {
         continue;
       }
       // add files, recurse into folders
@@ -400,47 +426,45 @@
   }
 
   /**
-   * Creates a new context associated with [folder].
+   * Potentially create a new context associated with the given [folder].
    *
-   * If there are subfolders with 'pubspec.yaml' files, separate contexts
-   * are created for them, and excluded from the context associated with
+   * If there are subfolders with 'pubspec.yaml' files, separate contexts are
+   * created for them and excluded from the context associated with the
    * [folder].
    *
-   * If [folder] itself contains a 'pubspec.yaml' file, subfolders are ignored.
-   *
    * If [withPubspecOnly] is `true`, a context will be created only if there
-   * is a 'pubspec.yaml' file in [folder].
+   * is a 'pubspec.yaml' file in the [folder].
    *
    * Returns create pubspec-based contexts.
    */
   List<_ContextInfo> _createContexts(Folder folder, bool withPubspecOnly) {
-    // check whether there is a pubspec in the folder
-    File pubspecFile = folder.getChild(PUBSPEC_NAME);
-    if (pubspecFile.exists) {
-      _ContextInfo info =
-          _createContextWithSources(folder, pubspecFile, <_ContextInfo>[]);
-      return [info];
-    }
     // try to find subfolders with pubspec files
     List<_ContextInfo> children = <_ContextInfo>[];
     try {
       for (Resource child in folder.getChildren()) {
         if (child is Folder) {
-          List<_ContextInfo> childContexts = _createContexts(child, true);
-          children.addAll(childContexts);
+          children.addAll(_createContexts(child, true));
         }
       }
     } on FileSystemException {
       // The directory either doesn't exist or cannot be read. Either way, there
       // are no subfolders that need to be added.
     }
+    // check whether there is a pubspec in the folder
+    File pubspecFile = folder.getChild(PUBSPEC_NAME);
+    if (pubspecFile.exists) {
+      return <_ContextInfo>[
+        _createContextWithSources(folder, pubspecFile, children)
+      ];
+    }
     // no pubspec, done
     if (withPubspecOnly) {
       return children;
     }
     // OK, create a context without a pubspec
-    _createContextWithSources(folder, pubspecFile, children);
-    return children;
+    return <_ContextInfo>[
+      _createContextWithSources(folder, pubspecFile, children)
+    ];
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 5b46107..d6e2ec5 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -11,6 +11,7 @@
 import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
 
@@ -136,7 +137,23 @@
    * Implement the 'analysis.reanalyze' request.
    */
   Response reanalyze(Request request) {
-    server.reanalyze();
+    AnalysisReanalyzeParams params =
+        new AnalysisReanalyzeParams.fromRequest(request);
+    List<String> roots = params.roots;
+    if (roots == null || roots.isNotEmpty) {
+      List<String> includedPaths = server.contextDirectoryManager.includedPaths;
+      List<Resource> rootResources = null;
+      if (roots != null) {
+        rootResources = <Resource>[];
+        for (String rootPath in roots) {
+          if (!includedPaths.contains(rootPath)) {
+            return new Response.invalidAnalysisRoot(request, rootPath);
+          }
+          rootResources.add(server.resourceProvider.getResource(rootPath));
+        }
+      }
+      server.reanalyze(rootResources);
+    }
     return new AnalysisReanalyzeResult().toResponse(request.id);
   }
 
@@ -189,6 +206,11 @@
     var params = new AnalysisUpdateOptionsParams.fromRequest(request);
     AnalysisOptions newOptions = params.options;
     List<OptionUpdater> updaters = new List<OptionUpdater>();
+    if (newOptions.enableNullAwareOperators != null) {
+      updaters.add((engine.AnalysisOptionsImpl options) {
+        options.enableNullAwareOperators = newOptions.enableNullAwareOperators;
+      });
+    }
     if (newOptions.generateDart2jsHints != null) {
       updaters.add((engine.AnalysisOptionsImpl options) {
         options.dart2jsHint = newOptions.generateDart2jsHints;
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index affe17c..70808d5 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -177,6 +177,9 @@
     ContextSourcePair contextSource = server.getContextSourcePair(params.file);
     AnalysisContext context = contextSource.context;
     Source source = contextSource.source;
+    if (context == null || !context.exists(source)) {
+      return new Response.unknownSource(request);
+    }
     recordRequest(performance, context, source, params.offset);
     if (manager == null) {
       manager = completionManagerFor(context, source);
diff --git a/pkg/analysis_server/lib/src/generated_protocol.dart b/pkg/analysis_server/lib/src/generated_protocol.dart
index bbd7572..27ad110 100644
--- a/pkg/analysis_server/lib/src/generated_protocol.dart
+++ b/pkg/analysis_server/lib/src/generated_protocol.dart
@@ -5644,6 +5644,7 @@
  *   "enableAsync": optional bool
  *   "enableDeferredLoading": optional bool
  *   "enableEnums": optional bool
+ *   "enableNullAwareOperators": optional bool
  *   "generateDart2jsHints": optional bool
  *   "generateHints": optional bool
  *   "generateLints": optional bool
@@ -5651,14 +5652,14 @@
  */
 class AnalysisOptions implements HasToJson {
   /**
-   * Deprecated/
+   * Deprecated
    *
    * True if the client wants to enable support for the proposed async feature.
    */
   bool enableAsync;
 
   /**
-   * Deprecated/
+   * Deprecated
    *
    * True if the client wants to enable support for the proposed deferred
    * loading feature.
@@ -5666,13 +5667,19 @@
   bool enableDeferredLoading;
 
   /**
-   * Deprecated/
+   * Deprecated
    *
    * True if the client wants to enable support for the proposed enum feature.
    */
   bool enableEnums;
 
   /**
+   * True if the client wants to enable support for the proposed "null aware
+   * operators" feature.
+   */
+  bool enableNullAwareOperators;
+
+  /**
    * True if hints that are specific to dart2js should be generated. This
    * option is ignored if generateHints is false.
    */
@@ -5690,7 +5697,7 @@
    */
   bool generateLints;
 
-  AnalysisOptions({this.enableAsync, this.enableDeferredLoading, this.enableEnums, this.generateDart2jsHints, this.generateHints, this.generateLints});
+  AnalysisOptions({this.enableAsync, this.enableDeferredLoading, this.enableEnums, this.enableNullAwareOperators, this.generateDart2jsHints, this.generateHints, this.generateLints});
 
   factory AnalysisOptions.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {
     if (json == null) {
@@ -5709,6 +5716,10 @@
       if (json.containsKey("enableEnums")) {
         enableEnums = jsonDecoder._decodeBool(jsonPath + ".enableEnums", json["enableEnums"]);
       }
+      bool enableNullAwareOperators;
+      if (json.containsKey("enableNullAwareOperators")) {
+        enableNullAwareOperators = jsonDecoder._decodeBool(jsonPath + ".enableNullAwareOperators", json["enableNullAwareOperators"]);
+      }
       bool generateDart2jsHints;
       if (json.containsKey("generateDart2jsHints")) {
         generateDart2jsHints = jsonDecoder._decodeBool(jsonPath + ".generateDart2jsHints", json["generateDart2jsHints"]);
@@ -5721,7 +5732,7 @@
       if (json.containsKey("generateLints")) {
         generateLints = jsonDecoder._decodeBool(jsonPath + ".generateLints", json["generateLints"]);
       }
-      return new AnalysisOptions(enableAsync: enableAsync, enableDeferredLoading: enableDeferredLoading, enableEnums: enableEnums, generateDart2jsHints: generateDart2jsHints, generateHints: generateHints, generateLints: generateLints);
+      return new AnalysisOptions(enableAsync: enableAsync, enableDeferredLoading: enableDeferredLoading, enableEnums: enableEnums, enableNullAwareOperators: enableNullAwareOperators, generateDart2jsHints: generateDart2jsHints, generateHints: generateHints, generateLints: generateLints);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "AnalysisOptions");
     }
@@ -5738,6 +5749,9 @@
     if (enableEnums != null) {
       result["enableEnums"] = enableEnums;
     }
+    if (enableNullAwareOperators != null) {
+      result["enableNullAwareOperators"] = enableNullAwareOperators;
+    }
     if (generateDart2jsHints != null) {
       result["generateDart2jsHints"] = generateDart2jsHints;
     }
@@ -5759,6 +5773,7 @@
       return enableAsync == other.enableAsync &&
           enableDeferredLoading == other.enableDeferredLoading &&
           enableEnums == other.enableEnums &&
+          enableNullAwareOperators == other.enableNullAwareOperators &&
           generateDart2jsHints == other.generateDart2jsHints &&
           generateHints == other.generateHints &&
           generateLints == other.generateLints;
@@ -5772,6 +5787,7 @@
     hash = _JenkinsSmiHash.combine(hash, enableAsync.hashCode);
     hash = _JenkinsSmiHash.combine(hash, enableDeferredLoading.hashCode);
     hash = _JenkinsSmiHash.combine(hash, enableEnums.hashCode);
+    hash = _JenkinsSmiHash.combine(hash, enableNullAwareOperators.hashCode);
     hash = _JenkinsSmiHash.combine(hash, generateDart2jsHints.hashCode);
     hash = _JenkinsSmiHash.combine(hash, generateHints.hashCode);
     hash = _JenkinsSmiHash.combine(hash, generateLints.hashCode);
@@ -9338,6 +9354,7 @@
  *   CONTENT_MODIFIED
  *   FORMAT_INVALID_FILE
  *   GET_ERRORS_INVALID_FILE
+ *   INVALID_ANALYSIS_ROOT
  *   INVALID_EXECUTION_CONTEXT
  *   INVALID_OVERLAY_CHANGE
  *   INVALID_PARAMETER
@@ -9350,6 +9367,7 @@
  *   SORT_MEMBERS_PARSE_ERRORS
  *   UNANALYZED_PRIORITY_FILES
  *   UNKNOWN_REQUEST
+ *   UNKNOWN_SOURCE
  *   UNSUPPORTED_FEATURE
  * }
  */
@@ -9374,6 +9392,12 @@
   static const GET_ERRORS_INVALID_FILE = const RequestErrorCode._("GET_ERRORS_INVALID_FILE");
 
   /**
+   * A path passed as an argument to a request (such as analysis.reanalyze) is
+   * required to be an analysis root, but isn't.
+   */
+  static const INVALID_ANALYSIS_ROOT = const RequestErrorCode._("INVALID_ANALYSIS_ROOT");
+
+  /**
    * The context root used to create an execution context does not exist.
    */
   static const INVALID_EXECUTION_CONTEXT = const RequestErrorCode._("INVALID_EXECUTION_CONTEXT");
@@ -9450,6 +9474,12 @@
   static const UNKNOWN_REQUEST = const RequestErrorCode._("UNKNOWN_REQUEST");
 
   /**
+   * The analysis server was requested to perform an action on a source that
+   * does not exist.
+   */
+  static const UNKNOWN_SOURCE = const RequestErrorCode._("UNKNOWN_SOURCE");
+
+  /**
    * The analysis server was requested to perform an action which is not
    * supported.
    *
@@ -9461,7 +9491,7 @@
   /**
    * A list containing all of the enum values that are defined.
    */
-  static const List<RequestErrorCode> VALUES = const <RequestErrorCode>[CONTENT_MODIFIED, FORMAT_INVALID_FILE, GET_ERRORS_INVALID_FILE, INVALID_EXECUTION_CONTEXT, INVALID_OVERLAY_CHANGE, INVALID_PARAMETER, INVALID_REQUEST, NO_INDEX_GENERATED, REFACTORING_REQUEST_CANCELLED, SERVER_ALREADY_STARTED, SERVER_ERROR, SORT_MEMBERS_INVALID_FILE, SORT_MEMBERS_PARSE_ERRORS, UNANALYZED_PRIORITY_FILES, UNKNOWN_REQUEST, UNSUPPORTED_FEATURE];
+  static const List<RequestErrorCode> VALUES = const <RequestErrorCode>[CONTENT_MODIFIED, FORMAT_INVALID_FILE, GET_ERRORS_INVALID_FILE, INVALID_ANALYSIS_ROOT, INVALID_EXECUTION_CONTEXT, INVALID_OVERLAY_CHANGE, INVALID_PARAMETER, INVALID_REQUEST, NO_INDEX_GENERATED, REFACTORING_REQUEST_CANCELLED, SERVER_ALREADY_STARTED, SERVER_ERROR, SORT_MEMBERS_INVALID_FILE, SORT_MEMBERS_PARSE_ERRORS, UNANALYZED_PRIORITY_FILES, UNKNOWN_REQUEST, UNKNOWN_SOURCE, UNSUPPORTED_FEATURE];
 
   final String name;
 
@@ -9475,6 +9505,8 @@
         return FORMAT_INVALID_FILE;
       case "GET_ERRORS_INVALID_FILE":
         return GET_ERRORS_INVALID_FILE;
+      case "INVALID_ANALYSIS_ROOT":
+        return INVALID_ANALYSIS_ROOT;
       case "INVALID_EXECUTION_CONTEXT":
         return INVALID_EXECUTION_CONTEXT;
       case "INVALID_OVERLAY_CHANGE":
@@ -9499,6 +9531,8 @@
         return UNANALYZED_PRIORITY_FILES;
       case "UNKNOWN_REQUEST":
         return UNKNOWN_REQUEST;
+      case "UNKNOWN_SOURCE":
+        return UNKNOWN_SOURCE;
       case "UNSUPPORTED_FEATURE":
         return UNSUPPORTED_FEATURE;
     }
diff --git a/pkg/analysis_server/lib/src/get_handler.dart b/pkg/analysis_server/lib/src/get_handler.dart
index fffe9ad..14d18cd 100644
--- a/pkg/analysis_server/lib/src/get_handler.dart
+++ b/pkg/analysis_server/lib/src/get_handler.dart
@@ -1007,6 +1007,8 @@
       _writeOption(
           buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
       _writeOption(buffer, 'Cache size', options.cacheSize);
+      _writeOption(buffer, 'Enable null-aware operators',
+          options.enableNullAwareOperators);
       _writeOption(
           buffer, 'Enable strict call checks', options.enableStrictCallChecks);
       _writeOption(buffer, 'Generate hints', options.hint);
diff --git a/pkg/analysis_server/lib/src/protocol.dart b/pkg/analysis_server/lib/src/protocol.dart
index 31e52c9..bdc8608 100644
--- a/pkg/analysis_server/lib/src/protocol.dart
+++ b/pkg/analysis_server/lib/src/protocol.dart
@@ -733,6 +733,16 @@
 
   /**
    * Initialize a newly created instance to represent an error condition caused
+   * by an analysis.reanalyze [request] that specifies an analysis root that is
+   * not in the current list of analysis roots.
+   */
+  Response.invalidAnalysisRoot(Request request, String rootPath) : this(
+          request.id,
+          error: new RequestError(RequestErrorCode.INVALID_ANALYSIS_ROOT,
+              "Invalid analysis root: $rootPath"));
+
+  /**
+   * Initialize a newly created instance to represent an error condition caused
    * by a [request] that specifies an execution context whose context root does
    * not exist.
    */
@@ -826,6 +836,14 @@
           error: new RequestError(
               RequestErrorCode.UNKNOWN_REQUEST, 'Unknown request'));
 
+  /**
+   * Initialize a newly created instance to represent an error condition caused
+   * by a [request] referencing a source that does not exist.
+   */
+  Response.unknownSource(Request request) : this(request.id,
+          error: new RequestError(
+              RequestErrorCode.UNKNOWN_SOURCE, 'Unknown source'));
+
   Response.unsupportedFeature(String requestId, String message) : this(
           requestId,
           error: new RequestError(
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index f5c5806..913e1f2 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -213,18 +213,6 @@
     engine.Element element, int fileToIndex(String file)) {
   ElementKind kind = newElementKind_fromEngine(element.kind);
   Location location = newLocation_fromElement(element);
-  // TODO(scheglov) debug null Location
-  if (location == null) {
-    String desc = 'location == null';
-    try {
-      desc += ' for: $element';
-      desc += ' of type: ${element.runtimeType}';
-      desc += ' element.location: ${element.location}';
-      desc += ' element.context: ${element.context}';
-      desc += ' element.source: ${element.source}';
-    } catch (e) {}
-    throw new ArgumentError(desc);
-  }
   String file = location.file;
   int fileIndex = fileToIndex(file);
   return new NavigationTarget(kind, fileIndex, location.offset, location.length,
diff --git a/pkg/analysis_server/lib/src/services/completion/arglist_computer.dart b/pkg/analysis_server/lib/src/services/completion/arglist_computer.dart
deleted file mode 100644
index 55b342a..0000000
--- a/pkg/analysis_server/lib/src/services/completion/arglist_computer.dart
+++ /dev/null
@@ -1,201 +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 services.completion.computer.dart.arglist;
-
-import 'dart:async';
-
-import 'package:analysis_server/src/protocol_server.dart'
-    hide Element, ElementKind;
-import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/completion/local_declaration_visitor.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-
-/**
- * A computer for calculating `completion.getSuggestions` request results
- * when the cursor position is inside the arguments to a method call.
- */
-class ArgListComputer extends DartCompletionComputer {
-  _ArgListSuggestionBuilder builder;
-
-  @override
-  bool computeFast(DartCompletionRequest request) {
-    builder = request.node.accept(new _ArgListAstVisitor(request));
-    return builder == null;
-  }
-
-  @override
-  Future<bool> computeFull(DartCompletionRequest request) {
-    if (builder != null) {
-      return builder.compute(request.node);
-    }
-    return new Future.value(false);
-  }
-}
-
-/**
- * A visitor for determining whether an argument list suggestion is needed
- * and instantiating the builder to create the suggestion.
- */
-class _ArgListAstVisitor
-    extends GeneralizingAstVisitor<_ArgListSuggestionBuilder> {
-  final DartCompletionRequest request;
-
-  _ArgListAstVisitor(this.request);
-
-  @override
-  _ArgListSuggestionBuilder visitArgumentList(ArgumentList node) {
-    Token leftParen = node.leftParenthesis;
-    if (leftParen != null && request.offset > leftParen.offset) {
-      AstNode parent = node.parent;
-      if (parent is MethodInvocation) {
-        SimpleIdentifier selector = parent.methodName;
-        if (selector != null) {
-          String name = selector.name;
-          if (name != null && name.length > 0) {
-            if (parent.period == null) {
-              /*
-               * If a local declaration is found, then return null
-               * indicating that suggestions were added
-               * and no further action is necessary
-               */
-              if (new _LocalDeclarationFinder(request, request.offset, name)
-                  .visit(node)) {
-                return null;
-              }
-            } else {
-              // determine target
-            }
-          }
-        }
-      }
-      return new _ArgListSuggestionBuilder(request);
-    }
-    return null;
-  }
-
-  @override
-  _ArgListSuggestionBuilder visitNode(AstNode node) {
-    return null;
-  }
-}
-
-/**
- * A `_ArgListSuggestionBuilder` determines which method or function is being
- * invoked, then builds the argument list suggestion.
- * This operation is instantiated during `computeFast`
- * and calculates the suggestions during `computeFull`.
- */
-class _ArgListSuggestionBuilder {
-  final DartCompletionRequest request;
-
-  _ArgListSuggestionBuilder(this.request);
-
-  Future<bool> compute(ArgumentList node) {
-    return new Future.value(false);
-  }
-}
-
-/**
- * `_LocalDeclarationFinder` visits an [AstNode] and its parent recursively
- * looking for a matching declaration. If found, it adds the appropriate
- * suggestions and sets finished to `true`.
- */
-class _LocalDeclarationFinder extends LocalDeclarationVisitor {
-  final DartCompletionRequest request;
-  final String name;
-
-  _LocalDeclarationFinder(this.request, int offset, this.name) : super(offset);
-
-  @override
-  void declaredClass(ClassDeclaration declaration) {}
-
-  @override
-  void declaredClassTypeAlias(ClassTypeAlias declaration) {}
-
-  @override
-  void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {}
-
-  @override
-  void declaredFunction(FunctionDeclaration declaration) {
-    SimpleIdentifier selector = declaration.name;
-    if (selector != null && name == selector.name) {
-      _addArgListSuggestion(declaration.functionExpression.parameters);
-      finished();
-    }
-  }
-
-  @override
-  void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {}
-
-  @override
-  void declaredLabel(Label label, bool isCaseLabel) {}
-
-  @override
-  void declaredLocalVar(SimpleIdentifier name, TypeName type) {}
-
-  @override
-  void declaredMethod(MethodDeclaration declaration) {
-    SimpleIdentifier selector = declaration.name;
-    if (selector != null && name == selector.name) {
-      _addArgListSuggestion(declaration.parameters);
-      finished();
-    }
-  }
-
-  @override
-  void declaredParam(SimpleIdentifier name, TypeName type) {}
-
-  @override
-  void declaredTopLevelVar(
-      VariableDeclarationList varList, VariableDeclaration varDecl) {}
-
-  void _addArgListSuggestion(FormalParameterList parameters) {
-    if (parameters.parameters.length == 0) {
-      return;
-    }
-    StringBuffer completion = new StringBuffer('(');
-    List<String> paramNames = new List<String>();
-    List<String> paramTypes = new List<String>();
-    for (FormalParameter param in parameters.parameters) {
-      SimpleIdentifier paramId = param.identifier;
-      if (paramId != null) {
-        String name = paramId.name;
-        if (name != null && name.length > 0) {
-          if (completion.length > 1) {
-            completion.write(', ');
-          }
-          completion.write(name);
-          paramNames.add(name);
-          paramTypes.add(_getParamType(param));
-        }
-      }
-    }
-    completion.write(')');
-    CompletionSuggestion suggestion = new CompletionSuggestion(
-        CompletionSuggestionKind.ARGUMENT_LIST, DART_RELEVANCE_HIGH,
-        completion.toString(), completion.length, 0, false, false);
-    suggestion.parameterNames = paramNames;
-    suggestion.parameterTypes = paramTypes;
-    request.addSuggestion(suggestion);
-  }
-
-  String _getParamType(FormalParameter param) {
-    TypeName type;
-    if (param is SimpleFormalParameter) {
-      type = param.type;
-    }
-    if (type != null) {
-      Identifier id = type.name;
-      if (id != null) {
-        String name = id.name;
-        if (name != null && name.length > 0) {
-          return name;
-        }
-      }
-    }
-    return 'dynamic';
-  }
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/arglist_contributor.dart
new file mode 100644
index 0000000..0dac520
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/arglist_contributor.dart
@@ -0,0 +1,359 @@
+// 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 services.completion.contributor.dart.arglist;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/protocol_server.dart'
+    hide Element, ElementKind;
+import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
+import 'package:analysis_server/src/services/completion/local_declaration_visitor.dart';
+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/utilities_dart.dart';
+
+void _addNamedParameterSuggestion(
+    DartCompletionRequest request, List<String> namedArgs, String name) {
+  if (name != null && name.length > 0 && !namedArgs.contains(name)) {
+    request.addSuggestion(new CompletionSuggestion(
+        CompletionSuggestionKind.NAMED_ARGUMENT, DART_RELEVANCE_PARAMETER,
+        '$name: ', name.length + 2, 0, false, false));
+  }
+}
+
+/**
+ * Determine the number of arguments.
+ */
+int _argCount(DartCompletionRequest request) {
+  AstNode node = request.target.containingNode;
+  if (node is ArgumentList) {
+    return node.arguments.length;
+  }
+  return 0;
+}
+
+/**
+ * Determine if the completion target is at the end of the list of arguments.
+ */
+bool _isAppendingToArgList(DartCompletionRequest request) {
+  AstNode node = request.target.containingNode;
+  if (node is ArgumentList) {
+    var entity = request.target.entity;
+    if (entity == node.rightParenthesis) {
+      return true;
+    }
+    if (node.arguments.length > 0 && node.arguments.last == entity) {
+      return entity is SimpleIdentifier;
+    }
+  }
+  return false;
+}
+
+/**
+ * Determine if the completion target is an emtpy argument list.
+ */
+bool _isEmptyArgList(DartCompletionRequest request) {
+  AstNode node = request.target.containingNode;
+  return node is ArgumentList &&
+      node.leftParenthesis.next == node.rightParenthesis;
+}
+
+/**
+ * Return a collection of currently specified named arguments
+ */
+Iterable<String> _namedArgs(DartCompletionRequest request) {
+  AstNode node = request.target.containingNode;
+  List<String> namedArgs = new List<String>();
+  if (node is ArgumentList) {
+    for (Expression arg in node.arguments) {
+      if (arg is NamedExpression) {
+        namedArgs.add(arg.name.label.name);
+      }
+    }
+  }
+  return namedArgs;
+}
+
+/**
+ * A contributor for calculating `completion.getSuggestions` request results
+ * when the cursor position is inside the arguments to a method call.
+ */
+class ArgListContributor extends DartCompletionContributor {
+  _ArgSuggestionBuilder builder;
+
+  @override
+  bool computeFast(DartCompletionRequest request) {
+    builder =
+        request.target.containingNode.accept(new _ArgListAstVisitor(request));
+    return builder == null;
+  }
+
+  @override
+  Future<bool> computeFull(DartCompletionRequest request) {
+    if (builder != null) {
+      return builder.compute(request.target.containingNode);
+    }
+    return new Future.value(false);
+  }
+}
+
+/**
+ * A visitor for determining whether an argument list suggestion is needed
+ * and instantiating the builder to create the suggestion.
+ */
+class _ArgListAstVisitor extends GeneralizingAstVisitor<_ArgSuggestionBuilder> {
+  final DartCompletionRequest request;
+
+  _ArgListAstVisitor(this.request);
+
+  @override
+  _ArgSuggestionBuilder visitArgumentList(ArgumentList node) {
+    Token leftParen = node.leftParenthesis;
+    if (leftParen != null && request.offset > leftParen.offset) {
+      AstNode parent = node.parent;
+      if (parent is MethodInvocation) {
+        SimpleIdentifier selector = parent.methodName;
+        if (selector != null) {
+          String name = selector.name;
+          if (name != null && name.length > 0) {
+            if (parent.operator == null) {
+              /*
+               * If a local declaration is found, then return null
+               * indicating that suggestions were added
+               * and no further action is necessary
+               */
+              if (new _LocalArgSuggestionBuilder(request, request.offset, name)
+                  .visit(node)) {
+                return null;
+              }
+            } else {
+              // determine target
+            }
+            return new _ArgSuggestionBuilder(request, name);
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @override
+  _ArgSuggestionBuilder visitNode(AstNode node) {
+    return null;
+  }
+}
+
+/**
+ * A [_ArgSuggestionBuilder] determines which method or function is being
+ * invoked, then builds the argument list suggestion.
+ * This operation is instantiated during `computeFast`
+ * and calculates the suggestions during `computeFull`.
+ */
+class _ArgSuggestionBuilder {
+  final DartCompletionRequest request;
+  final String methodName;
+
+  _ArgSuggestionBuilder(this.request, this.methodName);
+
+  Future<bool> compute(ArgumentList node) {
+    AstNode parent = node.parent;
+    if (parent is MethodInvocation) {
+      SimpleIdentifier methodName = parent.methodName;
+      if (methodName != null) {
+        Element methodElem = methodName.bestElement;
+        if (methodElem is ExecutableElement) {
+          _addSuggestions(methodElem.parameters);
+        }
+      }
+    }
+    return new Future.value(false);
+  }
+
+  void _addArgListSuggestion(Iterable<ParameterElement> requiredParam) {
+    StringBuffer completion = new StringBuffer('(');
+    List<String> paramNames = new List<String>();
+    List<String> paramTypes = new List<String>();
+    for (ParameterElement param in requiredParam) {
+      String name = param.name;
+      if (name != null && name.length > 0) {
+        if (completion.length > 1) {
+          completion.write(', ');
+        }
+        completion.write(name);
+        paramNames.add(name);
+        paramTypes.add(_getParamType(param));
+      }
+    }
+    completion.write(')');
+    CompletionSuggestion suggestion = new CompletionSuggestion(
+        CompletionSuggestionKind.ARGUMENT_LIST, DART_RELEVANCE_HIGH,
+        completion.toString(), completion.length, 0, false, false);
+    suggestion.parameterNames = paramNames;
+    suggestion.parameterTypes = paramTypes;
+    request.addSuggestion(suggestion);
+  }
+
+  void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters) {
+    Iterable<String> namedArgs = _namedArgs(request);
+    for (ParameterElement param in parameters) {
+      if (param.parameterKind == ParameterKind.NAMED) {
+        _addNamedParameterSuggestion(request, namedArgs, param.name);
+      }
+    }
+  }
+
+  void _addSuggestions(Iterable<ParameterElement> parameters) {
+    if (parameters == null || parameters.length == 0) {
+      return;
+    }
+    Iterable<ParameterElement> requiredParam = parameters.where(
+        (ParameterElement p) => p.parameterKind == ParameterKind.REQUIRED);
+    if (requiredParam.length > 0 && _isEmptyArgList(request)) {
+      _addArgListSuggestion(requiredParam);
+      return;
+    }
+    if (_isAppendingToArgList(request) &&
+        _argCount(request) > requiredParam.length) {
+      _addDefaultParamSuggestions(parameters);
+    }
+  }
+
+  String _getParamType(ParameterElement param) {
+    DartType type = param.type;
+    if (type != null) {
+      return type.displayName;
+    }
+    return 'dynamic';
+  }
+}
+
+/**
+ * [_LocalArgSuggestionBuilder] visits an [AstNode] and its parent recursively
+ * looking for a matching declaration. If found, it adds the appropriate
+ * suggestions and sets finished to `true`.
+ */
+class _LocalArgSuggestionBuilder extends LocalDeclarationVisitor {
+  final DartCompletionRequest request;
+  final String name;
+
+  _LocalArgSuggestionBuilder(this.request, int offset, this.name)
+      : super(offset);
+
+  @override
+  void declaredClass(ClassDeclaration declaration) {}
+
+  @override
+  void declaredClassTypeAlias(ClassTypeAlias declaration) {}
+
+  @override
+  void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {}
+
+  @override
+  void declaredFunction(FunctionDeclaration declaration) {
+    SimpleIdentifier selector = declaration.name;
+    if (selector != null && name == selector.name) {
+      _addSuggestions(declaration.functionExpression.parameters);
+      finished();
+    }
+  }
+
+  @override
+  void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {}
+
+  @override
+  void declaredLabel(Label label, bool isCaseLabel) {}
+
+  @override
+  void declaredLocalVar(SimpleIdentifier name, TypeName type) {}
+
+  @override
+  void declaredMethod(MethodDeclaration declaration) {
+    SimpleIdentifier selector = declaration.name;
+    if (selector != null && name == selector.name) {
+      _addSuggestions(declaration.parameters);
+      finished();
+    }
+  }
+
+  @override
+  void declaredParam(SimpleIdentifier name, TypeName type) {}
+
+  @override
+  void declaredTopLevelVar(
+      VariableDeclarationList varList, VariableDeclaration varDecl) {}
+
+  void _addArgListSuggestion(Iterable<FormalParameter> requiredParam) {
+    StringBuffer completion = new StringBuffer('(');
+    List<String> paramNames = new List<String>();
+    List<String> paramTypes = new List<String>();
+    for (FormalParameter param in requiredParam) {
+      SimpleIdentifier paramId = param.identifier;
+      if (paramId != null) {
+        String name = paramId.name;
+        if (name != null && name.length > 0) {
+          if (completion.length > 1) {
+            completion.write(', ');
+          }
+          completion.write(name);
+          paramNames.add(name);
+          paramTypes.add(_getParamType(param));
+        }
+      }
+    }
+    completion.write(')');
+    CompletionSuggestion suggestion = new CompletionSuggestion(
+        CompletionSuggestionKind.ARGUMENT_LIST, DART_RELEVANCE_HIGH,
+        completion.toString(), completion.length, 0, false, false);
+    suggestion.parameterNames = paramNames;
+    suggestion.parameterTypes = paramTypes;
+    request.addSuggestion(suggestion);
+  }
+
+  void _addDefaultParamSuggestions(FormalParameterList parameters) {
+    Iterable<String> namedArgs = _namedArgs(request);
+    for (FormalParameter param in parameters.parameters) {
+      if (param.kind == ParameterKind.NAMED) {
+        SimpleIdentifier paramId = param.identifier;
+        if (paramId != null) {
+          _addNamedParameterSuggestion(request, namedArgs, paramId.name);
+        }
+      }
+    }
+  }
+
+  void _addSuggestions(FormalParameterList parameters) {
+    if (parameters == null || parameters.parameters.length == 0) {
+      return;
+    }
+    Iterable<FormalParameter> requiredParam = parameters.parameters
+        .where((FormalParameter p) => p.kind == ParameterKind.REQUIRED);
+    if (requiredParam.length > 0 && _isEmptyArgList(request)) {
+      _addArgListSuggestion(requiredParam);
+      return;
+    }
+    if (_isAppendingToArgList(request) &&
+        _argCount(request) > requiredParam.length) {
+      _addDefaultParamSuggestions(parameters);
+    }
+  }
+
+  String _getParamType(FormalParameter param) {
+    TypeName type;
+    if (param is SimpleFormalParameter) {
+      type = param.type;
+    }
+    if (type != null) {
+      Identifier id = type.name;
+      if (id != null) {
+        String name = id.name;
+        if (name != null && name.length > 0) {
+          return name;
+        }
+      }
+    }
+    return 'dynamic';
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/combinator_computer.dart b/pkg/analysis_server/lib/src/services/completion/combinator_contributor.dart
similarity index 83%
rename from pkg/analysis_server/lib/src/services/completion/combinator_computer.dart
rename to pkg/analysis_server/lib/src/services/completion/combinator_contributor.dart
index 3da2f69..402d4a2 100644
--- a/pkg/analysis_server/lib/src/services/completion/combinator_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/combinator_contributor.dart
@@ -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.
 
-library services.completion.computer.dart.combinator;
+library services.completion.contributor.dart.combinator;
 
 import 'dart:async';
 
@@ -14,22 +14,23 @@
 import 'package:analyzer/src/generated/element.dart';
 
 /**
- * A computer for calculating `completion.getSuggestions` request results
+ * A contributor for calculating `completion.getSuggestions` request results
  * for the import combinators show and hide.
  */
-class CombinatorComputer extends DartCompletionComputer {
+class CombinatorContributor extends DartCompletionContributor {
   _CombinatorSuggestionBuilder builder;
 
   @override
   bool computeFast(DartCompletionRequest request) {
-    builder = request.node.accept(new _CombinatorAstVisitor(request));
+    builder = request.target.containingNode
+        .accept(new _CombinatorAstVisitor(request));
     return builder == null;
   }
 
   @override
   Future<bool> computeFull(DartCompletionRequest request) {
     if (builder != null) {
-      return builder.execute(request.node);
+      return builder.execute(request.target.containingNode);
     }
     return new Future.value(false);
   }
@@ -55,11 +56,6 @@
   _CombinatorSuggestionBuilder visitNode(AstNode node) {
     return null;
   }
-
-  @override
-  _CombinatorSuggestionBuilder visitSimpleIdentifier(SimpleIdentifier node) {
-    return node.parent.accept(this);
-  }
 }
 
 /**
@@ -71,7 +67,7 @@
 class _CombinatorSuggestionBuilder extends LibraryElementSuggestionBuilder {
   _CombinatorSuggestionBuilder(
       DartCompletionRequest request, CompletionSuggestionKind kind)
-      : super(request, kind);
+      : super(request, kind, false);
 
   Future<bool> execute(AstNode node) {
     var directive = node.getAncestor((parent) => parent is NamespaceDirective);
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
index a46adae..5ed7b1a 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_manager.dart
@@ -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.
 
-library services.completion.computer;
+library services.completion.manager;
 
 import 'dart:async';
 
@@ -32,7 +32,7 @@
 }
 
 /**
- * Manages `CompletionComputer`s for a given completion request.
+ * Manages completion contributors for a given completion request.
  */
 abstract class CompletionManager {
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
index 17127f7..d8afca4 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_cache.dart
@@ -127,7 +127,7 @@
     assert(unit.element.source == source);
 
     // Exclude elements from local library
-    // because they are provided by LocalComputer
+    // because they are provided by LocalReferenceContributor
     Set<LibraryElement> excludedLibs = new Set<LibraryElement>();
     excludedLibs.add(unit.element.enclosingElement);
 
@@ -237,7 +237,7 @@
               });
             } else {
               // Exclude elements from prefixed imports
-              // because they are provided by InvocationComputer
+              // because they are provided by PrefixedElementContributor
               _addLibraryPrefixSuggestion(importElem);
               excludedLibs.add(importElem.importedLibrary);
             }
@@ -277,6 +277,20 @@
    */
   void _addNonImportedElementSuggestions(
       List<SearchMatch> matches, Set<LibraryElement> excludedLibs) {
+
+    // Exclude internal Dart SDK libraries
+    for (var lib in context.sourceFactory.dartSdk.sdkLibraries) {
+      if (lib.isInternal) {
+        Source libUri = context.sourceFactory.forUri(lib.shortName);
+        if (libUri != null) {
+          LibraryElement libElem = context.getLibraryElement(libUri);
+          if (libElem != null) {
+            excludedLibs.add(libElem);
+          }
+        }
+      }
+    }
+
     AnalysisContext sdkContext = context.sourceFactory.dartSdk.context;
     matches.forEach((SearchMatch match) {
       if (match.kind == MatchKind.DECLARATION) {
@@ -296,9 +310,15 @@
    */
   void _addSuggestion(Element element, int relevance) {
     if (element is ExecutableElement) {
+      // Do not suggest operators or local functions
       if (element.isOperator) {
         return;
       }
+      if (element is FunctionElement) {
+        if (element.enclosingElement is! CompilationUnitElement) {
+          return;
+        }
+      }
     }
 
     CompletionSuggestion suggestion =
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
index 0f77b19..c1b0339 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
@@ -7,16 +7,16 @@
 import 'dart:async';
 
 import 'package:analysis_server/src/protocol.dart';
-import 'package:analysis_server/src/services/completion/arglist_computer.dart';
-import 'package:analysis_server/src/services/completion/combinator_computer.dart';
+import 'package:analysis_server/src/services/completion/arglist_contributor.dart';
+import 'package:analysis_server/src/services/completion/combinator_contributor.dart';
 import 'package:analysis_server/src/services/completion/common_usage_computer.dart';
 import 'package:analysis_server/src/services/completion/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/completion_target.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_cache.dart';
-import 'package:analysis_server/src/services/completion/imported_computer.dart';
-import 'package:analysis_server/src/services/completion/invocation_computer.dart';
-import 'package:analysis_server/src/services/completion/keyword_computer.dart';
-import 'package:analysis_server/src/services/completion/local_computer.dart';
+import 'package:analysis_server/src/services/completion/imported_reference_contributor.dart';
+import 'package:analysis_server/src/services/completion/prefixed_element_contributor.dart';
+import 'package:analysis_server/src/services/completion/keyword_contributor.dart';
+import 'package:analysis_server/src/services/completion/local_reference_contributor.dart';
 import 'package:analysis_server/src/services/completion/optype.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/src/generated/ast.dart';
@@ -41,15 +41,15 @@
 const int DART_RELEVANCE_PARAMETER = 1059;
 
 /**
- * The base class for computing code completion suggestions.
+ * The base class for contributing code completion suggestions.
  */
-abstract class DartCompletionComputer {
+abstract class DartCompletionContributor {
   /**
    * Computes the initial set of [CompletionSuggestion]s based on
    * the given completion context. The compilation unit and completion node
    * in the given completion context may not be resolved.
    * This method should execute quickly and not block waiting for any analysis.
-   * Returns `true` if the computer's work is complete
+   * Returns `true` if the contributor's work is complete
    * or `false` if [computeFull] should be called to complete the work.
    */
   bool computeFast(DartCompletionRequest request);
@@ -69,23 +69,24 @@
 class DartCompletionManager extends CompletionManager {
   final SearchEngine searchEngine;
   final DartCompletionCache cache;
-  List<DartCompletionComputer> computers;
+  List<DartCompletionContributor> contributors;
   CommonUsageComputer commonUsageComputer;
 
   DartCompletionManager(
       AnalysisContext context, this.searchEngine, Source source, this.cache,
-      [this.computers, this.commonUsageComputer])
+      [this.contributors, this.commonUsageComputer])
       : super(context, source) {
-    if (computers == null) {
-      computers = [
-        // LocalComputer before ImportedComputer
+    if (contributors == null) {
+      contributors = [
+        // LocalReferenceContributor before ImportedReferenceContributor
         // because local suggestions take precedence
-        new LocalComputer(),
-        new ImportedComputer(),
-        new KeywordComputer(),
-        new ArgListComputer(),
-        new CombinatorComputer(),
-        new InvocationComputer()
+        // and can hide other suggestions with the same name
+        new LocalReferenceContributor(),
+        new ImportedReferenceContributor(),
+        new KeywordContributor(),
+        new ArgListContributor(),
+        new CombinatorContributor(),
+        new PrefixedElementContributor()
       ];
     }
     if (commonUsageComputer == null) {
@@ -116,20 +117,20 @@
   /**
    * Compute suggestions based upon cached information only
    * then send an initial response to the client.
-   * Return a list of computers for which [computeFull] should be called
+   * Return a list of contributors for which [computeFull] should be called
    */
-  List<DartCompletionComputer> computeFast(DartCompletionRequest request) {
+  List<DartCompletionContributor> computeFast(DartCompletionRequest request) {
     return request.performance.logElapseTime('computeFast', () {
       CompilationUnit unit = context.parseCompilationUnit(source);
       request.unit = unit;
-      request.node = new NodeLocator.con1(request.offset).searchWithin(unit);
       request.target = new CompletionTarget.forOffset(unit, request.offset);
-      if (request.node == null) {
+      request.replacementOffset = request.offset;
+      request.replacementLength = 0;
+      if (request.offset < 0 || request.offset > unit.end) {
+        sendResults(request, true);
         return [];
       }
 
-      request.replacementOffset = request.offset;
-      request.replacementLength = 0;
       var entity = request.target.entity;
       Token token = entity is AstNode ? entity.beginToken : entity;
       if (token != null &&
@@ -140,8 +141,8 @@
         request.replacementLength = token.length;
       }
 
-      List<DartCompletionComputer> todo = new List.from(computers);
-      todo.removeWhere((DartCompletionComputer c) {
+      List<DartCompletionContributor> todo = new List.from(contributors);
+      todo.removeWhere((DartCompletionContributor c) {
         return request.performance.logElapseTime('computeFast ${c.runtimeType}',
             () {
           return c.computeFast(request);
@@ -155,11 +156,11 @@
 
   /**
    * If there is remaining work to be done, then wait for the unit to be
-   * resolved and request that each remaining computer finish their work.
+   * resolved and request that each remaining contributor finish their work.
    * Return a [Future] that completes when the last notification has been sent.
    */
   Future computeFull(
-      DartCompletionRequest request, List<DartCompletionComputer> todo) {
+      DartCompletionRequest request, List<DartCompletionContributor> todo) {
     request.performance.logStartTime('waitForAnalysis');
     return waitForAnalysis().then((CompilationUnit unit) {
       if (controller.isClosed) {
@@ -172,12 +173,11 @@
       }
       request.performance.logElapseTime('computeFull', () {
         request.unit = unit;
-        request.node = new NodeLocator.con1(request.offset).searchWithin(unit);
         // TODO(paulberry): Do we need to invoke _ReplacementOffsetBuilder
         // again?
         request.target = new CompletionTarget.forOffset(unit, request.offset);
         int count = todo.length;
-        todo.forEach((DartCompletionComputer c) {
+        todo.forEach((DartCompletionContributor c) {
           String name = c.runtimeType.toString();
           String completeTag = 'computeFull $name complete';
           request.performance.logStartTime(completeTag);
@@ -202,7 +202,7 @@
         searchEngine, source, completionRequest.offset, cache,
         completionRequest.performance);
     request.performance.logElapseTime('compute', () {
-      List<DartCompletionComputer> todo = computeFast(request);
+      List<DartCompletionContributor> todo = computeFast(request);
       if (!todo.isEmpty) {
         computeFull(request, todo);
       }
@@ -272,24 +272,14 @@
 
   /**
    * The compilation unit in which the completion was requested. This unit
-   * may or may not be resolved when [DartCompletionComputer.computeFast]
-   * is called but is resolved when [DartCompletionComputer.computeFull].
+   * may or may not be resolved when [DartCompletionContributor.computeFast]
+   * is called but is resolved when [DartCompletionContributor.computeFull].
    */
   CompilationUnit unit;
 
   /**
-   * The node in which the completion occurred. This node
-   * may or may not be resolved when [DartCompletionComputer.computeFast]
-   * is called but is resolved when [DartCompletionComputer.computeFull].
-   */
-  AstNode node;
-
-  /**
    * The completion target.  This determines what part of the parse tree
    * will receive the newly inserted text.
-   *
-   * TODO(paulberry) gradually transition code over to using this rather than
-   * [node].
    */
   CompletionTarget target;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/imported_computer.dart b/pkg/analysis_server/lib/src/services/completion/imported_reference_contributor.dart
similarity index 85%
rename from pkg/analysis_server/lib/src/services/completion/imported_computer.dart
rename to pkg/analysis_server/lib/src/services/completion/imported_reference_contributor.dart
index 2031557..5608f8f 100644
--- a/pkg/analysis_server/lib/src/services/completion/imported_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/imported_reference_contributor.dart
@@ -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.
 
-library services.completion.computer.dart.toplevel;
+library services.completion.contributor.dart.toplevel;
 
 import 'dart:async';
 import 'dart:collection';
@@ -17,47 +17,48 @@
 import 'package:analyzer/src/generated/element.dart';
 
 /**
- * A computer for calculating imported class and top level variable
+ * A contributor for calculating imported class and top level variable
  * `completion.getSuggestions` request results.
  */
-class ImportedComputer extends DartCompletionComputer {
+class ImportedReferenceContributor extends DartCompletionContributor {
   bool shouldWaitForLowPrioritySuggestions;
   bool suggestionsComputed;
   _ImportedSuggestionBuilder builder;
 
-  ImportedComputer({this.shouldWaitForLowPrioritySuggestions: false});
+  ImportedReferenceContributor({this.shouldWaitForLowPrioritySuggestions: false});
 
   @override
   bool computeFast(DartCompletionRequest request) {
     OpType optype = request.optype;
-    if (optype.includeReturnValueSuggestions ||
-        optype.includeTypeNameSuggestions ||
-        optype.includeVoidReturnSuggestions ||
-        optype.includeConstructorSuggestions) {
-      builder = new _ImportedSuggestionBuilder(request, optype);
-      builder.shouldWaitForLowPrioritySuggestions =
-          shouldWaitForLowPrioritySuggestions;
-      // If target is an argument in an argument list
-      // then suggestions may need to be adjusted
-      suggestionsComputed = builder.computeFast(request.node);
-      return suggestionsComputed && request.target.argIndex == null;
+    if (!optype.isPrefixed) {
+      if (optype.includeReturnValueSuggestions ||
+          optype.includeTypeNameSuggestions ||
+          optype.includeVoidReturnSuggestions ||
+          optype.includeConstructorSuggestions) {
+        builder = new _ImportedSuggestionBuilder(request, optype);
+        builder.shouldWaitForLowPrioritySuggestions =
+            shouldWaitForLowPrioritySuggestions;
+        // If target is an argument in an argument list
+        // then suggestions may need to be adjusted
+        suggestionsComputed = builder.computeFast(request.target.containingNode);
+        return suggestionsComputed && request.target.argIndex == null;
+      }
     }
     return true;
   }
 
   @override
-  Future<bool> computeFull(DartCompletionRequest request) {
+  Future<bool> computeFull(DartCompletionRequest request) async {
     if (builder != null) {
       if (!suggestionsComputed) {
-        return builder.computeFull(request.node).then((bool result) {
-          _updateSuggestions(request);
-          return result;
-        });
+        bool result = await builder.computeFull(request.target.containingNode);
+        _updateSuggestions(request);
+        return result;
       }
       _updateSuggestions(request);
-      return new Future.value(true);
+      return true;
     }
-    return new Future.value(false);
+    return false;
   }
 
   /**
@@ -143,7 +144,7 @@
    */
   void _addElementSuggestions(List<Element> elements,
       {int relevance: DART_RELEVANCE_DEFAULT}) {
-    elements.forEach((Element elem) {
+    for (Element elem in elements) {
       if (elem is! ClassElement) {
         if (optype.includeOnlyTypeNameSuggestions) {
           return;
@@ -158,7 +159,8 @@
         }
       }
       addSuggestion(elem, relevance: relevance);
-    });
+    }
+    ;
   }
 
   /**
@@ -190,7 +192,7 @@
       // and include any inherited imported members
       List<String> inheritedTypes = new List<String>();
       visitInheritedTypes(classDecl, (_) {
-        // local declarations are handled by the local computer
+        // local declarations are handled by the local reference contributor
       }, (String typeName) {
         inheritedTypes.add(typeName);
       });
diff --git a/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart b/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart
deleted file mode 100644
index 36d403b..0000000
--- a/pkg/analysis_server/lib/src/services/completion/keyword_computer.dart
+++ /dev/null
@@ -1,259 +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 services.completion.computer.dart.keyword;
-
-import 'dart:async';
-
-import 'package:analysis_server/src/protocol.dart';
-import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-
-/**
- * A computer for calculating `completion.getSuggestions` request results
- * for the local library in which the completion is requested.
- */
-class KeywordComputer extends DartCompletionComputer {
-  @override
-  bool computeFast(DartCompletionRequest request) {
-    request.node.accept(new _KeywordVisitor(request));
-    return true;
-  }
-
-  @override
-  Future<bool> computeFull(DartCompletionRequest request) {
-    return new Future.value(false);
-  }
-}
-
-/**
- * A vistor for generating keyword suggestions.
- */
-class _KeywordVisitor extends GeneralizingAstVisitor {
-  final DartCompletionRequest request;
-
-  /**
-   * The identifier visited or `null` if not visited.
-   */
-  SimpleIdentifier identifier;
-
-  _KeywordVisitor(this.request);
-
-  @override
-  visitBlock(Block node) {
-    if (_isInClassMemberBody(node)) {
-      _addSuggestions([
-        Keyword.ASSERT,
-        Keyword.CASE,
-        Keyword.CONTINUE,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETHROW,
-        Keyword.RETURN,
-        Keyword.SUPER,
-        Keyword.SWITCH,
-        Keyword.THIS,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ]);
-    } else {
-      _addSuggestions([
-        Keyword.ASSERT,
-        Keyword.CASE,
-        Keyword.CONTINUE,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETHROW,
-        Keyword.RETURN,
-        Keyword.SWITCH,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ]);
-    }
-  }
-
-  @override
-  visitClassDeclaration(ClassDeclaration node) {
-    // Don't suggest class name
-    if (node.name == identifier) {
-      return;
-    }
-    // Inside the class declaration { }
-    if (request.offset > node.leftBracket.offset) {
-      _addSuggestions([
-        Keyword.CONST,
-        Keyword.DYNAMIC,
-        Keyword.FACTORY,
-        Keyword.FINAL,
-        Keyword.GET,
-        Keyword.OPERATOR,
-        Keyword.SET,
-        Keyword.STATIC,
-        Keyword.VAR,
-        Keyword.VOID
-      ]);
-      return;
-    }
-    _addClassDeclarationKeywords(node);
-  }
-
-  @override
-  visitCompilationUnit(CompilationUnit node) {
-    Directive firstDirective;
-    int endOfDirectives = 0;
-    if (node.directives.length > 0) {
-      firstDirective = node.directives[0];
-      endOfDirectives = node.directives.last.end - 1;
-    }
-    int startOfDeclarations = node.end;
-    if (node.declarations.length > 0) {
-      startOfDeclarations = node.declarations[0].offset;
-      // If the first token is a simple identifier
-      // and cursor position in within that first token
-      // then consider cursor to be before the first declaration
-      Token token = node.declarations[0].firstTokenAfterCommentAndMetadata;
-      if (token.offset <= request.offset && request.offset <= token.end) {
-        startOfDeclarations = token.end;
-      }
-    }
-
-    // Simplistic check for library as first directive
-    if (firstDirective is! LibraryDirective) {
-      if (firstDirective != null) {
-        if (request.offset <= firstDirective.offset) {
-          _addSuggestions([Keyword.LIBRARY], DART_RELEVANCE_HIGH);
-        }
-      } else {
-        if (request.offset <= startOfDeclarations) {
-          _addSuggestions([Keyword.LIBRARY], DART_RELEVANCE_HIGH);
-        }
-      }
-    }
-    if (request.offset <= startOfDeclarations) {
-      _addSuggestions(
-          [Keyword.EXPORT, Keyword.IMPORT, Keyword.PART], DART_RELEVANCE_HIGH);
-    }
-    if (request.offset >= endOfDirectives) {
-      _addSuggestions([
-        Keyword.ABSTRACT,
-        Keyword.CLASS,
-        Keyword.CONST,
-        Keyword.FINAL,
-        Keyword.TYPEDEF,
-        Keyword.VAR
-      ], DART_RELEVANCE_HIGH);
-    }
-  }
-
-  @override
-  visitNode(AstNode node) {
-    if (_isOffsetAfterNode(node)) {
-      node.parent.accept(this);
-    }
-  }
-
-  visitSimpleIdentifier(SimpleIdentifier node) {
-    identifier = node;
-    node.parent.accept(this);
-  }
-
-  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    if (identifier != null && node.beginToken == identifier.beginToken) {
-      AstNode unit = node.parent;
-      if (unit is CompilationUnit) {
-        CompilationUnitMember previous;
-        for (CompilationUnitMember member in unit.declarations) {
-          if (member == node && previous is ClassDeclaration) {
-            if (previous.endToken.isSynthetic) {
-              // Partial keywords (simple identifirs) that are part of a
-              // class declaration can be parsed
-              // as a TypeName in a TopLevelVariableDeclaration
-              _addClassDeclarationKeywords(previous);
-              return;
-            }
-          }
-          previous = member;
-        }
-        // Partial keywords (simple identifiers) can be parsed
-        // as a TypeName in a TopLevelVariableDeclaration
-        unit.accept(this);
-      }
-    }
-  }
-
-  void visitTypeName(TypeName node) {
-    node.parent.accept(this);
-  }
-
-  void visitVariableDeclarationList(VariableDeclarationList node) {
-    node.parent.accept(this);
-  }
-
-  void _addClassDeclarationKeywords(ClassDeclaration node) {
-    // Very simplistic suggestion because analyzer will warn if
-    // the extends / with / implements keywords are out of order
-    if (node.extendsClause == null) {
-      _addSuggestion(Keyword.EXTENDS, DART_RELEVANCE_HIGH);
-    } else if (node.withClause == null) {
-      _addSuggestion(Keyword.WITH, DART_RELEVANCE_HIGH);
-    }
-    if (node.implementsClause == null) {
-      _addSuggestion(Keyword.IMPLEMENTS, DART_RELEVANCE_HIGH);
-    }
-  }
-
-  void _addSuggestion(Keyword keyword,
-      [int relevance = DART_RELEVANCE_DEFAULT]) {
-    String completion = keyword.syntax;
-    request.addSuggestion(new CompletionSuggestion(
-        CompletionSuggestionKind.KEYWORD,
-        relevance, completion, completion.length, 0, false, false));
-  }
-
-  void _addSuggestions(List<Keyword> keywords,
-      [int relevance = DART_RELEVANCE_KEYWORD]) {
-    keywords.forEach((Keyword keyword) {
-      _addSuggestion(keyword, relevance);
-    });
-  }
-
-  bool _isOffsetAfterNode(AstNode node) {
-    if (request.offset == node.end) {
-      Token token = node.endToken;
-      if (token != null && !token.isSynthetic) {
-        if (token.lexeme == ';' || token.lexeme == '}') {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  static bool _isInClassMemberBody(AstNode node) {
-    while (true) {
-      AstNode body = node.getAncestor((n) => n is FunctionBody);
-      if (body == null) {
-        return false;
-      }
-      AstNode parent = body.parent;
-      if (parent is ConstructorDeclaration || parent is MethodDeclaration) {
-        return true;
-      }
-      node = parent;
-    }
-  }
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart
new file mode 100644
index 0000000..b979b8b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart
@@ -0,0 +1,202 @@
+// 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 services.completion.contributor.dart.keyword;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/protocol.dart';
+import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+
+/**
+ * A contributor for calculating `completion.getSuggestions` request results
+ * for the local library in which the completion is requested.
+ */
+class KeywordContributor extends DartCompletionContributor {
+  @override
+  bool computeFast(DartCompletionRequest request) {
+    request.target.containingNode.accept(new _KeywordVisitor(request));
+    return true;
+  }
+
+  @override
+  Future<bool> computeFull(DartCompletionRequest request) {
+    return new Future.value(false);
+  }
+}
+
+/**
+ * A vistor for generating keyword suggestions.
+ */
+class _KeywordVisitor extends GeneralizingAstVisitor {
+  final DartCompletionRequest request;
+  final Object entity;
+
+  _KeywordVisitor(DartCompletionRequest request)
+      : this.request = request,
+        this.entity = request.target.entity;
+
+  @override
+  visitBlock(Block node) {
+    if (_isInClassMemberBody(node)) {
+      _addSuggestions([Keyword.SUPER, Keyword.THIS,]);
+    }
+    _addSuggestions([
+      Keyword.ASSERT,
+      Keyword.CASE,
+      Keyword.CONTINUE,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETHROW,
+      Keyword.RETURN,
+      Keyword.SWITCH,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ]);
+  }
+
+  @override
+  visitClassDeclaration(ClassDeclaration node) {
+    // Don't suggest class name
+    if (entity == node.name) {
+      return;
+    }
+    if (entity == node.rightBracket || entity is ClassMember) {
+      _addSuggestions([
+        Keyword.CONST,
+        Keyword.DYNAMIC,
+        Keyword.FACTORY,
+        Keyword.FINAL,
+        Keyword.GET,
+        Keyword.OPERATOR,
+        Keyword.SET,
+        Keyword.STATIC,
+        Keyword.VAR,
+        Keyword.VOID
+      ]);
+      return;
+    }
+    _addClassDeclarationKeywords(node);
+  }
+
+  @override
+  visitCompilationUnit(CompilationUnit node) {
+    var previousMember = null;
+    for (var member in node.childEntities) {
+      if (entity == member) {
+        break;
+      }
+      previousMember = member;
+    }
+    if (previousMember is ClassDeclaration) {
+      if (previousMember.leftBracket == null ||
+          previousMember.leftBracket.isSynthetic) {
+        // If the prior member is an unfinished class declaration
+        // then the user is probably finishing that
+        _addClassDeclarationKeywords(previousMember);
+        return;
+      }
+    }
+    if (previousMember is ImportDirective) {
+      if (previousMember.semicolon == null ||
+          previousMember.semicolon.isSynthetic) {
+        // If the prior member is an unfinished import directive
+        // then the user is probably finishing that
+        _addImportDirectiveKeywords(previousMember);
+        return;
+      }
+    }
+    if (previousMember == null || previousMember is Directive) {
+      if (previousMember == null &&
+          !node.directives.any((d) => d is LibraryDirective)) {
+        _addSuggestions([Keyword.LIBRARY], DART_RELEVANCE_HIGH);
+      }
+      _addSuggestions(
+          [Keyword.EXPORT, Keyword.IMPORT, Keyword.PART], DART_RELEVANCE_HIGH);
+    }
+    if (entity == null || entity is Declaration) {
+      _addSuggestions([
+        Keyword.ABSTRACT,
+        Keyword.CLASS,
+        Keyword.CONST,
+        Keyword.DYNAMIC,
+        Keyword.FINAL,
+        Keyword.TYPEDEF,
+        Keyword.VAR,
+        Keyword.VOID
+      ], DART_RELEVANCE_HIGH);
+    }
+  }
+
+  @override
+  visitImportDirective(ImportDirective node) {
+    if (entity == node.asKeyword) {
+      if (node.deferredKeyword == null) {
+        _addSuggestion(Keyword.DEFERRED, DART_RELEVANCE_HIGH);
+      }
+    }
+    if (entity == node.semicolon || node.combinators.contains(entity)) {
+      _addImportDirectiveKeywords(node);
+    }
+  }
+
+  void _addImportDirectiveKeywords(ImportDirective node) {
+    if (node.asKeyword == null) {
+      _addSuggestion(Keyword.AS, DART_RELEVANCE_HIGH);
+      if (node.deferredKeyword == null) {
+        _addSuggestion(Keyword.DEFERRED, DART_RELEVANCE_HIGH);
+      }
+    }
+  }
+
+  void _addClassDeclarationKeywords(ClassDeclaration node) {
+    // Very simplistic suggestion because analyzer will warn if
+    // the extends / with / implements keywords are out of order
+    if (node.extendsClause == null) {
+      _addSuggestion(Keyword.EXTENDS, DART_RELEVANCE_HIGH);
+    } else if (node.withClause == null) {
+      _addSuggestion(Keyword.WITH, DART_RELEVANCE_HIGH);
+    }
+    if (node.implementsClause == null) {
+      _addSuggestion(Keyword.IMPLEMENTS, DART_RELEVANCE_HIGH);
+    }
+  }
+
+  void _addSuggestion(Keyword keyword,
+      [int relevance = DART_RELEVANCE_DEFAULT]) {
+    String completion = keyword.syntax;
+    request.addSuggestion(new CompletionSuggestion(
+        CompletionSuggestionKind.KEYWORD, relevance, completion,
+        completion.length, 0, false, false));
+  }
+
+  void _addSuggestions(List<Keyword> keywords,
+      [int relevance = DART_RELEVANCE_KEYWORD]) {
+    keywords.forEach((Keyword keyword) {
+      _addSuggestion(keyword, relevance);
+    });
+  }
+
+  bool _isInClassMemberBody(AstNode node) {
+    while (true) {
+      AstNode body = node.getAncestor((n) => n is FunctionBody);
+      if (body == null) {
+        return false;
+      }
+      AstNode parent = body.parent;
+      if (parent is ConstructorDeclaration || parent is MethodDeclaration) {
+        return true;
+      }
+      node = parent;
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/local_declaration_visitor.dart b/pkg/analysis_server/lib/src/services/completion/local_declaration_visitor.dart
index ef36304..d00921a 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_declaration_visitor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_declaration_visitor.dart
@@ -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.
 
-library services.completion.computer.dart.local.Declaration.visitor;
+library services.completion.dart.local.declaration.visitor;
 
 import 'package:analysis_server/src/services/completion/suggestion_builder.dart';
 import 'package:analyzer/src/generated/ast.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/local_computer.dart b/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
similarity index 94%
rename from pkg/analysis_server/lib/src/services/completion/local_computer.dart
rename to pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
index 5602d81..12cdd5e 100644
--- a/pkg/analysis_server/lib/src/services/completion/local_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/local_reference_contributor.dart
@@ -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.
 
-library services.completion.computer.dart.local;
+library services.completion.contributor.dart.local;
 
 import 'dart:async';
 
@@ -77,32 +77,34 @@
 }
 
 /**
- * A computer for calculating `completion.getSuggestions` request results
+ * A contributor for calculating `completion.getSuggestions` request results
  * for the local library in which the completion is requested.
  */
-class LocalComputer extends DartCompletionComputer {
+class LocalReferenceContributor extends DartCompletionContributor {
   @override
   bool computeFast(DartCompletionRequest request) {
     OpType optype = request.optype;
 
     // Collect suggestions from the specific child [AstNode] that contains
     // the completion offset and all of its parents recursively.
-    if (optype.includeReturnValueSuggestions ||
-        optype.includeTypeNameSuggestions ||
-        optype.includeVoidReturnSuggestions) {
-      _LocalVisitor localVisitor =
-          new _LocalVisitor(request, request.offset, optype);
-      localVisitor.visit(request.node);
-    }
-    if (optype.includeStatementLabelSuggestions ||
-        optype.includeCaseLabelSuggestions) {
-      _LabelVisitor labelVisitor = new _LabelVisitor(request,
-          optype.includeStatementLabelSuggestions,
-          optype.includeCaseLabelSuggestions);
-      labelVisitor.visit(request.node);
-    }
-    if (optype.includeConstructorSuggestions) {
-      new _ConstructorVisitor(request).visit(request.node);
+    if (!optype.isPrefixed) {
+      if (optype.includeReturnValueSuggestions ||
+          optype.includeTypeNameSuggestions ||
+          optype.includeVoidReturnSuggestions) {
+        _LocalVisitor localVisitor =
+            new _LocalVisitor(request, request.offset, optype);
+        localVisitor.visit(request.target.containingNode);
+      }
+      if (optype.includeStatementLabelSuggestions ||
+          optype.includeCaseLabelSuggestions) {
+        _LabelVisitor labelVisitor = new _LabelVisitor(request,
+            optype.includeStatementLabelSuggestions,
+            optype.includeCaseLabelSuggestions);
+        labelVisitor.visit(request.target.containingNode);
+      }
+      if (optype.includeConstructorSuggestions) {
+        new _ConstructorVisitor(request).visit(request.target.containingNode);
+      }
     }
 
     // If target is an argument in an argument list
@@ -429,11 +431,6 @@
   final DartCompletionRequest request;
   final OpType optype;
 
-  /**
-   * The simple identifier that is being completed, or `null` if none.
-   */
-  SimpleIdentifier targetId;
-
   _LocalVisitor(this.request, int offset, this.optype) : super(offset);
 
   @override
@@ -631,13 +628,6 @@
     }
   }
 
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    // Record the visited identifier so as not to suggest it
-    targetId = node;
-    return super.visitSimpleIdentifier(node);
-  }
-
   void _addParameterInfo(
       CompletionSuggestion suggestion, FormalParameterList parameters) {
     var paramList = parameters.parameters;
@@ -676,7 +666,7 @@
 
   CompletionSuggestion _addSuggestion(SimpleIdentifier id, TypeName returnType,
       bool isDeprecated, int defaultRelevance, {ClassDeclaration classDecl}) {
-    if (id != null && !identical(id, targetId)) {
+    if (id != null) {
       String completion = id.name;
       if (completion != null && completion.length > 0 && completion != '_') {
         CompletionSuggestion suggestion = new CompletionSuggestion(
diff --git a/pkg/analysis_server/lib/src/services/completion/optype.dart b/pkg/analysis_server/lib/src/services/completion/optype.dart
index 83ef718..84bced9 100644
--- a/pkg/analysis_server/lib/src/services/completion/optype.dart
+++ b/pkg/analysis_server/lib/src/services/completion/optype.dart
@@ -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.
 
-library services.completion.computer.dart.optype;
+library services.completion.dart.optype;
 
 import 'package:analysis_server/src/services/completion/completion_target.dart';
 import 'package:analyzer/src/generated/ast.dart';
@@ -21,11 +21,6 @@
   bool includeConstructorSuggestions = false;
 
   /**
-   * Indicates whether invocation suggestions should be included.
-   */
-  bool includeInvocationSuggestions = false;
-
-  /**
    * Indicates whether type names should be suggested.
    */
   bool includeTypeNameSuggestions = false;
@@ -53,6 +48,11 @@
   bool includeCaseLabelSuggestions = false;
 
   /**
+   * Indicates whether the completion target is prefixed.
+   */
+  bool isPrefixed = false;
+
+  /**
    * Determine the suggestions that should be made based upon the given
    * [CompletionTarget] and [offset].
    */
@@ -70,8 +70,7 @@
    */
   bool get includeOnlyTypeNameSuggestions => includeTypeNameSuggestions &&
       !includeReturnValueSuggestions &&
-      !includeVoidReturnSuggestions &&
-      !includeInvocationSuggestions;
+      !includeVoidReturnSuggestions;
 }
 
 class _OpTypeAstVisitor extends GeneralizingAstVisitor {
@@ -100,7 +99,9 @@
       optype.includeTypeNameSuggestions = true;
       optype.includeReturnValueSuggestions = true;
     } else if (identical(entity, node.constructorName)) {
-      optype.includeInvocationSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+      optype.includeReturnValueSuggestions = true;
+      optype.isPrefixed = true;
     }
   }
 
@@ -161,7 +162,16 @@
   @override
   void visitCascadeExpression(CascadeExpression node) {
     if (node.cascadeSections.contains(entity)) {
-      optype.includeInvocationSuggestions = true;
+      optype.includeReturnValueSuggestions = true;
+      optype.includeVoidReturnSuggestions = true;
+      optype.isPrefixed = true;
+    }
+  }
+
+  @override
+  void visitCatchClause(CatchClause node) {
+    if (identical(entity, node.exceptionType)) {
+      optype.includeTypeNameSuggestions = true;
     }
   }
 
@@ -204,7 +214,8 @@
       if (type != null) {
         SimpleIdentifier prefix = type.name;
         if (prefix != null) {
-          optype.includeInvocationSuggestions = true;
+          optype.includeConstructorSuggestions = true;
+          optype.isPrefixed = true;
         }
       }
     }
@@ -297,7 +308,6 @@
 
   @override
   void visitFormalParameterList(FormalParameterList node) {
-    optype.includeReturnValueSuggestions = true;
     optype.includeTypeNameSuggestions = true;
   }
 
@@ -402,12 +412,19 @@
 
   @override
   void visitMethodInvocation(MethodInvocation node) {
-    if (identical(entity, node.period) && offset > node.period.offset) {
+    bool isThis = node.target is ThisExpression;
+    if (identical(entity, node.operator) && offset > node.operator.offset) {
       // The cursor is between the two dots of a ".." token, so we need to
       // generate the completions we would generate after a "." token.
-      optype.includeInvocationSuggestions = true;
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = !isThis;
+      optype.includeVoidReturnSuggestions = true;
+      optype.isPrefixed = true;
     } else if (identical(entity, node.methodName)) {
-      optype.includeInvocationSuggestions = true;
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = !isThis;
+      optype.includeVoidReturnSuggestions = true;
+      optype.isPrefixed = true;
     }
   }
 
@@ -446,7 +463,15 @@
   @override
   void visitPrefixedIdentifier(PrefixedIdentifier node) {
     if (identical(entity, node.identifier)) {
-      optype.includeInvocationSuggestions = true;
+      optype.isPrefixed = true;
+      if (node.parent is TypeName && node.parent.parent is ConstructorName) {
+        optype.includeConstructorSuggestions = true;
+      } else {
+        optype.includeReturnValueSuggestions = true;
+        optype.includeTypeNameSuggestions = true;
+        optype.includeVoidReturnSuggestions =
+            node.parent is ExpressionStatement;
+      }
     }
   }
 
@@ -460,12 +485,25 @@
 
   @override
   void visitPropertyAccess(PropertyAccess node) {
+    bool isThis = node.target is ThisExpression;
+    if (node.realTarget is SimpleIdentifier && node.realTarget.isSynthetic) {
+      // If the access has no target (empty string)
+      // then don't suggest anything
+      return;
+    }
     if (identical(entity, node.operator) && offset > node.operator.offset) {
       // The cursor is between the two dots of a ".." token, so we need to
       // generate the completions we would generate after a "." token.
-      optype.includeInvocationSuggestions = true;
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = !isThis;
+      optype.includeVoidReturnSuggestions = true;
+      optype.isPrefixed = true;
     } else if (identical(entity, node.propertyName)) {
-      optype.includeInvocationSuggestions = true;
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions =
+          !isThis && (node.parent is! CascadeExpression);
+      optype.includeVoidReturnSuggestions = true;
+      optype.isPrefixed = true;
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/invocation_computer.dart b/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
similarity index 84%
rename from pkg/analysis_server/lib/src/services/completion/invocation_computer.dart
rename to pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
index 9d154ec..cb6ccf4 100644
--- a/pkg/analysis_server/lib/src/services/completion/invocation_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/prefixed_element_contributor.dart
@@ -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.
 
-library services.completion.computer.dart.invocation;
+library services.completion.contributor.dart.invocation;
 
 import 'dart:async';
 
@@ -13,22 +13,25 @@
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 
-import '../../protocol_server.dart' show CompletionSuggestionKind;
+import '../../protocol_server.dart' as protocol;
+import '../../protocol_server.dart'
+    show CompletionSuggestion, CompletionSuggestionKind;
 
 /**
- * A computer for calculating invocation / access suggestions
+ * A contributor for calculating invocation / access suggestions
  * `completion.getSuggestions` request results.
  */
-class InvocationComputer extends DartCompletionComputer {
+class PrefixedElementContributor extends DartCompletionContributor {
   SuggestionBuilder builder;
 
   @override
   bool computeFast(DartCompletionRequest request) {
     OpType optype = request.optype;
-    if (optype.includeInvocationSuggestions) {
-      builder = request.node.accept(new _InvocationAstVisitor(request));
+    if (optype.isPrefixed) {
+      builder = request.target.containingNode
+          .accept(new _InvocationAstVisitor(request));
       if (builder != null) {
-        return builder.computeFast(request.node);
+        return builder.computeFast(request.target.containingNode);
       }
     }
 
@@ -38,7 +41,7 @@
   @override
   Future<bool> computeFull(DartCompletionRequest request) {
     if (builder != null) {
-      return builder.computeFull(request.node);
+      return builder.computeFull(request.target.containingNode);
     }
     return new Future.value(false);
   }
@@ -56,9 +59,6 @@
 
   @override
   Future<bool> computeFull(AstNode node) {
-    if (node is SimpleIdentifier) {
-      node = node.parent;
-    }
     if (node is MethodInvocation) {
       node = (node as MethodInvocation).realTarget;
     } else if (node is PropertyAccess) {
@@ -89,7 +89,7 @@
   _InvocationAstVisitor(this.request);
 
   @override
-  visitConstructorName(ConstructorName node) {
+  SuggestionBuilder visitConstructorName(ConstructorName node) {
     // some PrefixedIdentifier nodes are transformed into
     // ConstructorName nodes during the resolution process.
     return new _PrefixedIdentifierSuggestionBuilder(request);
@@ -116,11 +116,6 @@
   SuggestionBuilder visitPropertyAccess(PropertyAccess node) {
     return new _ExpressionSuggestionBuilder(request);
   }
-
-  @override
-  SuggestionBuilder visitSimpleIdentifier(SimpleIdentifier node) {
-    return node.parent.accept(this);
-  }
 }
 
 /**
@@ -254,9 +249,6 @@
 
   @override
   Future<bool> computeFull(AstNode node) {
-    if (node is SimpleIdentifier) {
-      node = node.parent;
-    }
     if (node is ConstructorName) {
       // some PrefixedIdentifier nodes are transformed into
       // ConstructorName nodes during the resolution process.
@@ -313,8 +305,6 @@
 
   @override
   Future<bool> visitPrefixElement(PrefixElement element) {
-    //TODO (danrubel) reimplement to use prefixElement.importedLibraries
-    // once that accessor is implemented and available in Dart
     bool modified = false;
     // Find the import directive with the given prefix
     for (Directive directive in request.unit.directives) {
@@ -323,9 +313,26 @@
           if (directive.prefix.name == element.name) {
             // Suggest elements from the imported library
             LibraryElement library = directive.uriElement;
-            LibraryElementSuggestionBuilder.suggestionsFor(
-                request, CompletionSuggestionKind.INVOCATION, library);
+            LibraryElementSuggestionBuilder.suggestionsFor(request,
+                CompletionSuggestionKind.INVOCATION, library,
+                request.target.containingNode.parent is TypeName);
             modified = true;
+            if (directive.deferredKeyword != null) {
+              String completion = 'loadLibrary';
+              CompletionSuggestion suggestion = new CompletionSuggestion(
+                  CompletionSuggestionKind.INVOCATION, DART_RELEVANCE_DEFAULT,
+                  completion, completion.length, 0, false, false,
+                  parameterNames: [],
+                  parameterTypes: [],
+                  requiredParameterCount: 0,
+                  hasNamedParameters: false,
+                  returnType: 'void');
+              suggestion.element = new protocol.Element(
+                  protocol.ElementKind.FUNCTION, completion,
+                  protocol.Element.makeFlags(),
+                  parameters: '()', returnType: 'void');
+              request.addSuggestion(suggestion);
+            }
           }
         }
       }
diff --git a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
index e882474..ac87e30 100644
--- a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
@@ -180,7 +180,11 @@
   void addSuggestion(Element element, {int relevance: DART_RELEVANCE_DEFAULT}) {
     if (element.isPrivate) {
       LibraryElement elementLibrary = element.library;
-      LibraryElement unitLibrary = request.unit.element.library;
+      CompilationUnitElement unitElem = request.unit.element;
+      if (unitElem == null) {
+        return;
+      }
+      LibraryElement unitLibrary = unitElem.library;
       if (elementLibrary != unitLibrary) {
         return;
       }
@@ -373,7 +377,7 @@
    */
   static void suggestionsFor(DartCompletionRequest request, DartType type) {
     CompilationUnit compilationUnit =
-        request.node.getAncestor((AstNode node) => node is CompilationUnit);
+        request.target.containingNode.getAncestor((n) => n is CompilationUnit);
     LibraryElement library = compilationUnit.element.library;
     if (type is DynamicTypeImpl) {
       type = request.cache.objectClassElement.type;
@@ -394,8 +398,9 @@
     with ElementSuggestionBuilder {
   final DartCompletionRequest request;
   final CompletionSuggestionKind kind;
+  final bool typesOnly;
 
-  LibraryElementSuggestionBuilder(this.request, this.kind);
+  LibraryElementSuggestionBuilder(this.request, this.kind, this.typesOnly);
 
   @override
   visitClassElement(ClassElement element) {
@@ -414,7 +419,9 @@
 
   @override
   visitFunctionElement(FunctionElement element) {
-    addSuggestion(element);
+    if (!typesOnly) {
+      addSuggestion(element);
+    }
   }
 
   @override
@@ -424,16 +431,19 @@
 
   @override
   visitTopLevelVariableElement(TopLevelVariableElement element) {
-    addSuggestion(element);
+    if (!typesOnly) {
+      addSuggestion(element);
+    }
   }
 
   /**
    * Add suggestions for the visible members in the given library
    */
   static void suggestionsFor(DartCompletionRequest request,
-      CompletionSuggestionKind kind, LibraryElement library) {
+      CompletionSuggestionKind kind, LibraryElement library, bool typesOnly) {
     if (library != null) {
-      library.visitChildren(new LibraryElementSuggestionBuilder(request, kind));
+      library.visitChildren(
+          new LibraryElementSuggestionBuilder(request, kind, typesOnly));
     }
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index f71a98f..f84e1f7a 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -57,6 +57,8 @@
       const AssistKind('CONVERT_INTO_IS_NOT', 30, "Convert into is!");
   static const CONVERT_INTO_IS_NOT_EMPTY = const AssistKind(
       'CONVERT_INTO_IS_NOT_EMPTY', 30, "Convert into 'isNotEmpty'");
+  static const ENCAPSULATE_FIELD =
+      const AssistKind('ENCAPSULATE_FIELD', 30, "Encapsulate field");
   static const EXCHANGE_OPERANDS =
       const AssistKind('EXCHANGE_OPERANDS', 30, "Exchange operands");
   static const EXTRACT_CLASS =
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 63287c4..324ab85 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -85,6 +85,7 @@
     _addProposal_convertToIsNot_onIs();
     _addProposal_convertToIsNot_onNot();
     _addProposal_convertToIsNotEmpty();
+    _addProposal_encapsulateField();
     _addProposal_exchangeOperands();
     _addProposal_importAddShow();
     _addProposal_introduceLocalTestedType();
@@ -660,6 +661,7 @@
         isEmptyAccess.parent as PrefixExpression;
     // should be !
     if (prefixExpression.operator.type != TokenType.BANG) {
+      _coverageMarker();
       return;
     }
     // do replace
@@ -669,6 +671,79 @@
     _addAssist(AssistKind.CONVERT_INTO_IS_NOT_EMPTY, []);
   }
 
+  void _addProposal_encapsulateField() {
+    // find FieldDeclaration
+    FieldDeclaration fieldDeclaraton =
+        node.getAncestor((x) => x is FieldDeclaration);
+    if (fieldDeclaraton == null) {
+      _coverageMarker();
+      return;
+    }
+    // not interesting for static
+    if (fieldDeclaraton.isStatic) {
+      _coverageMarker();
+      return;
+    }
+    // has a parse error
+    VariableDeclarationList variableList = fieldDeclaraton.fields;
+    if (variableList.keyword == null && variableList.type == null) {
+      _coverageMarker();
+      return;
+    }
+    // not interesting for final
+    if (variableList.isFinal) {
+      _coverageMarker();
+      return;
+    }
+    // should have exactly one field
+    List<VariableDeclaration> fields = variableList.variables;
+    if (fields.length != 1) {
+      _coverageMarker();
+      return;
+    }
+    VariableDeclaration field = fields.first;
+    SimpleIdentifier nameNode = field.name;
+    FieldElement fieldElement = nameNode.staticElement;
+    // should have a public name
+    String name = nameNode.name;
+    if (Identifier.isPrivateName(name)) {
+      _coverageMarker();
+      return;
+    }
+    // should be on the name
+    if (nameNode != node) {
+      _coverageMarker();
+      return;
+    }
+    // rename field
+    _addReplaceEdit(rangeNode(nameNode), '_$name');
+    // update references in constructors
+    ClassDeclaration classDeclaration = fieldDeclaraton.parent;
+    for (ClassMember member in classDeclaration.members) {
+      if (member is ConstructorDeclaration) {
+        for (FormalParameter parameter in member.parameters.parameters) {
+          ParameterElement parameterElement = parameter.element;
+          if (parameterElement is FieldFormalParameterElement &&
+              parameterElement.field == fieldElement) {
+            _addReplaceEdit(rangeNode(parameter.identifier), '_$name');
+          }
+        }
+      }
+    }
+    // add accessors
+    String eol2 = eol + eol;
+    String typeNameCode =
+        variableList.type != null ? _getNodeText(variableList.type) + ' ' : '';
+    String getterCode = '$eol2  ${typeNameCode}get $name => _$name;';
+    String setterCode = '$eol2'
+        '  void set $name(${typeNameCode}$name) {$eol'
+        '    _$name = $name;$eol'
+        '  }';
+    _addInsertEdit(fieldDeclaraton.end, getterCode + setterCode);
+    // add proposal
+    _addAssist(AssistKind.ENCAPSULATE_FIELD, []);
+  }
+
   void _addProposal_exchangeOperands() {
     // check that user invokes quick assist on binary expression
     if (node is! BinaryExpression) {
@@ -1126,50 +1201,48 @@
   }
 
   void _addProposal_removeTypeAnnotation() {
-    AstNode typeStart = null;
-    AstNode typeEnd = null;
+    VariableDeclarationList variableList;
     // try top-level variable
     {
       TopLevelVariableDeclaration declaration =
           node.getAncestor((node) => node is TopLevelVariableDeclaration);
       if (declaration != null) {
-        TypeName typeNode = declaration.variables.type;
-        if (typeNode != null) {
-          VariableDeclaration field = declaration.variables.variables[0];
-          typeStart = declaration;
-          typeEnd = field;
-        }
+        variableList = declaration.variables;
       }
     }
     // try class field
-    {
+    if (variableList == null) {
       FieldDeclaration fieldDeclaration =
           node.getAncestor((node) => node is FieldDeclaration);
       if (fieldDeclaration != null) {
-        TypeName typeNode = fieldDeclaration.fields.type;
-        if (typeNode != null) {
-          VariableDeclaration field = fieldDeclaration.fields.variables[0];
-          typeStart = fieldDeclaration;
-          typeEnd = field;
-        }
+        variableList = fieldDeclaration.fields;
       }
     }
     // try local variable
-    {
+    if (variableList == null) {
       VariableDeclarationStatement statement =
           node.getAncestor((node) => node is VariableDeclarationStatement);
       if (statement != null) {
-        TypeName typeNode = statement.variables.type;
-        if (typeNode != null) {
-          VariableDeclaration variable = statement.variables.variables[0];
-          typeStart = typeNode;
-          typeEnd = variable;
-        }
+        variableList = statement.variables;
       }
     }
+    if (variableList == null) {
+      _coverageMarker();
+      return;
+    }
+    // we need a type
+    TypeName typeNode = variableList.type;
+    if (typeNode == null) {
+      _coverageMarker();
+      return;
+    }
     // add edit
-    if (typeStart != null && typeEnd != null) {
-      SourceRange typeRange = rangeStartStart(typeStart, typeEnd);
+    Token keyword = variableList.keyword;
+    VariableDeclaration firstVariable = variableList.variables[0];
+    SourceRange typeRange = rangeStartStart(typeNode, firstVariable);
+    if (keyword != null && keyword.lexeme != 'var') {
+      _addReplaceEdit(typeRange, '');
+    } else {
       _addReplaceEdit(typeRange, 'var ');
     }
     // add proposal
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 0ff70e6..f38c00c9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -376,6 +376,9 @@
     }
     ClassDeclaration classDeclaration =
         node.getAncestor((node) => node is ClassDeclaration);
+    if (classDeclaration == null) {
+      return;
+    }
     // prepare names of uninitialized final fields
     List<String> fieldNames = <String>[];
     for (ClassMember member in classDeclaration.members) {
@@ -450,7 +453,7 @@
     }
     ClassElement targetElement = targetType.element as ClassElement;
     String targetFile = targetElement.source.fullName;
-    ClassDeclaration targetClass = targetElement.node;
+    ClassDeclaration targetClass = getParsedClassElementNode(targetElement);
     _ConstructorLocation targetLocation =
         _prepareNewConstructorLocation(targetClass);
     // build method source
@@ -504,7 +507,7 @@
     }
     ClassElement targetElement = targetType.element as ClassElement;
     String targetFile = targetElement.source.fullName;
-    ClassDeclaration targetClass = targetElement.node;
+    ClassDeclaration targetClass = getParsedClassElementNode(targetElement);
     _ConstructorLocation targetLocation =
         _prepareNewConstructorLocation(targetClass);
     // build method source
@@ -675,6 +678,9 @@
   }
 
   void _addFix_createField() {
+    if (node is! SimpleIdentifier) {
+      return;
+    }
     SimpleIdentifier nameNode = node;
     String name = nameNode.name;
     // prepare target Expression
@@ -713,7 +719,7 @@
     }
     utils.targetClassElement = targetClassElement;
     // prepare target ClassDeclaration
-    AstNode targetTypeNode = targetClassElement.node;
+    AstNode targetTypeNode = getParsedClassElementNode(targetClassElement);
     if (targetTypeNode is! ClassDeclaration) {
       return;
     }
@@ -802,6 +808,9 @@
   }
 
   void _addFix_createGetter() {
+    if (node is! SimpleIdentifier) {
+      return;
+    }
     SimpleIdentifier nameNode = node;
     String name = nameNode.name;
     if (!nameNode.inGetterContext()) {
@@ -843,7 +852,7 @@
     }
     utils.targetClassElement = targetClassElement;
     // prepare target ClassDeclaration
-    AstNode targetTypeNode = targetClassElement.node;
+    AstNode targetTypeNode = getParsedClassElementNode(targetClassElement);
     if (targetTypeNode is! ClassDeclaration) {
       return;
     }
@@ -902,6 +911,9 @@
   }
 
   void _addFix_createLocalVariable() {
+    if (node is! SimpleIdentifier) {
+      return;
+    }
     SimpleIdentifier nameNode = node;
     String name = nameNode.name;
     // if variable is assigned, convert assignment into declaration
@@ -1123,7 +1135,7 @@
   void _addFix_importLibrary(FixKind kind, String importPath) {
     CompilationUnitElement libraryUnitElement =
         unitLibraryElement.definingCompilationUnit;
-    CompilationUnit libraryUnit = libraryUnitElement.node;
+    CompilationUnit libraryUnit = getParsedUnit(libraryUnitElement);
     // prepare new import location
     int offset = 0;
     String prefix;
@@ -1655,7 +1667,8 @@
           staticModifier = target.bestElement.kind == ElementKind.CLASS;
         }
         // prepare insert offset
-        ClassDeclaration targetClassNode = targetClassElement.node;
+        ClassDeclaration targetClassNode =
+            getParsedClassElementNode(targetClassElement);
         prefix = '  ';
         insertOffset = targetClassNode.end - 1;
         if (targetClassNode.members.isEmpty) {
@@ -1967,7 +1980,8 @@
     // prepare environment
     Source targetSource = targetClassElement.source;
     // prepare insert offset
-    ClassDeclaration targetClassNode = targetClassElement.node;
+    ClassDeclaration targetClassNode =
+        getParsedClassElementNode(targetClassElement);
     int insertOffset = targetClassNode.end - 1;
     // prepare prefix
     String prefix = '  ';
@@ -2385,9 +2399,8 @@
   static void _addSuperTypeProposals(
       SourceBuilder sb, Set<DartType> alreadyAdded, DartType type) {
     if (type != null &&
-        !alreadyAdded.contains(type) &&
-        type.element is ClassElement) {
-      alreadyAdded.add(type);
+        type.element is ClassElement &&
+        alreadyAdded.add(type)) {
       ClassElement element = type.element as ClassElement;
       sb.addSuggestion(LinkedEditSuggestionKind.TYPE, element.name);
       _addSuperTypeProposals(sb, alreadyAdded, element.supertype);
diff --git a/pkg/analysis_server/lib/src/services/correction/namespace.dart b/pkg/analysis_server/lib/src/services/correction/namespace.dart
index 899fae0..305052a 100644
--- a/pkg/analysis_server/lib/src/services/correction/namespace.dart
+++ b/pkg/analysis_server/lib/src/services/correction/namespace.dart
@@ -152,7 +152,7 @@
     MethodInvocation invocation = parent;
     if (invocation.target == prefixNode) {
       usedElement = invocation.methodName.staticElement;
-      info.periodEnd = invocation.period.end;
+      info.periodEnd = invocation.operator.end;
     }
   }
   // we need used Element
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index c19a4c8..ba7a858 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -27,7 +27,8 @@
  */
 void addLibraryImports(SourceChange change, LibraryElement targetLibrary,
     Set<LibraryElement> libraries) {
-  CompilationUnit libUnit = targetLibrary.definingCompilationUnit.node;
+  CompilationUnitElement libUnitElement = targetLibrary.definingCompilationUnit;
+  CompilationUnit libUnit = getParsedUnit(libUnitElement);
   // prepare new import location
   int offset = 0;
   String prefix;
@@ -113,6 +114,16 @@
 }
 
 /**
+ * Returns the EOL to use for the given [code].
+ */
+String getCodeEndOfLine(String code) {
+  if (code.contains('\r\n')) {
+    return '\r\n';
+  }
+  return '\n';
+}
+
+/**
  * TODO(scheglov) replace with nodes once there will be [CompilationUnit.getComments].
  *
  * Returns [SourceRange]s of all comments in [unit].
@@ -250,6 +261,9 @@
   if (parent is ParenthesizedExpression) {
     return 0;
   }
+  if (parent is IndexExpression && parent.index == node) {
+    return 0;
+  }
   return getExpressionPrecedence(parent);
 }
 
@@ -419,6 +433,41 @@
 }
 
 /**
+ * Returns a parsed [AstNode] for the given [classElement].
+ *
+ * The resulting AST structure may or may not be resolved.
+ */
+AstNode getParsedClassElementNode(ClassElement classElement) {
+  CompilationUnitElement unitElement =
+      classElement.getAncestor((e) => e is CompilationUnitElement);
+  CompilationUnit unit = getParsedUnit(unitElement);
+  int offset = classElement.nameOffset;
+  AstNode classNameNode = new NodeLocator.con1(offset).searchWithin(unit);
+  if (classElement.isEnum) {
+    return classNameNode.getAncestor((node) => node is EnumDeclaration);
+  } else {
+    return classNameNode.getAncestor(
+        (node) => node is ClassDeclaration || node is ClassTypeAlias);
+  }
+}
+
+/**
+ * Returns a parsed [CompilationUnit] for the given [unitElement].
+ *
+ * The resulting AST structure may or may not be resolved.
+ * If it is not resolved, then at least the given [unitElement] will be set.
+ */
+CompilationUnit getParsedUnit(CompilationUnitElement unitElement) {
+  AnalysisContext context = unitElement.context;
+  Source source = unitElement.source;
+  CompilationUnit unit = context.parseCompilationUnit(source);
+  if (unit.element == null) {
+    unit.element = unitElement;
+  }
+  return unit;
+}
+
+/**
  * Returns a [PropertyAccessorElement] if the given [SimpleIdentifier] is a
  * reference to a property, or `null` in the other case.
  */
diff --git a/pkg/analysis_server/lib/src/services/index/store/codec.dart b/pkg/analysis_server/lib/src/services/index/store/codec.dart
index 97e4dbb..0283594 100644
--- a/pkg/analysis_server/lib/src/services/index/store/codec.dart
+++ b/pkg/analysis_server/lib/src/services/index/store/codec.dart
@@ -7,7 +7,6 @@
 import 'dart:collection';
 
 import 'package:analysis_server/src/services/index/index.dart';
-import 'package:analysis_server/src/services/index/store/collection.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -67,76 +66,98 @@
  * A helper that encodes/decodes [Element]s to/from integers.
  */
 class ElementCodec {
+  static const int _CONSTRUCTOR_KIND_BASE = -100;
+
   final StringCodec _stringCodec;
 
-  /**
-   * A table mapping element encodings to a single integer.
-   */
-  final IntArrayToIntMap _pathToIndex = new IntArrayToIntMap();
-
-  /**
-   * A list that works as a mapping of integers to element encodings.
-   */
-  final List<List<int>> _indexToPath = <List<int>>[];
-
   ElementCodec(this._stringCodec);
 
   /**
-   * Returns an [Element] that corresponds to the given location.
-   *
-   * @param context the [AnalysisContext] to find [Element] in
-   * @param index an integer corresponding to the [Element]
-   * @return the [Element] or `null`
+   * Returns an [Element] that corresponds to the given identifiers.
    */
-  Element decode(AnalysisContext context, int index) {
-    List<int> path = _indexToPath[index];
-    List<String> components = _getLocationComponents(path);
-    ElementLocation location = new ElementLocationImpl.con3(components);
-    return context.getElement(location);
+  Element decode(AnalysisContext context, int fileId, int offset, int kindId) {
+    String filePath = _stringCodec.decode(fileId);
+    List<Source> unitSources = context.getSourcesWithFullName(filePath);
+    for (Source unitSource in unitSources) {
+      List<Source> libSources = context.getLibrariesContaining(unitSource);
+      for (Source libSource in libSources) {
+        LibraryElement libraryElement = context.getLibraryElement(libSource);
+        if (libraryElement == null) {
+          return null;
+        }
+        if (kindId == ElementKind.LIBRARY.ordinal) {
+          return libraryElement;
+        } else if (kindId == ElementKind.COMPILATION_UNIT.ordinal) {
+          for (CompilationUnitElement unit in libraryElement.units) {
+            if (unit.source.fullName == filePath) {
+              return unit;
+            }
+          }
+          return null;
+        } else {
+          Element element = libraryElement.getElementAt(offset);
+          if (element == null) {
+            return null;
+          }
+          if (element is ClassElement && kindId <= _CONSTRUCTOR_KIND_BASE) {
+            int constructorIndex = -1 * (kindId - _CONSTRUCTOR_KIND_BASE);
+            return element.constructors[constructorIndex];
+          }
+          if (element is PropertyInducingElement) {
+            if (kindId == ElementKind.GETTER.ordinal) {
+              return element.getter;
+            }
+            if (kindId == ElementKind.SETTER.ordinal) {
+              return element.setter;
+            }
+          }
+          return element;
+        }
+      }
+    }
+    return null;
   }
 
   /**
-   * Returns a unique integer that corresponds to the given [Element].
-   *
-   * If [forKey] is `true` then [element] is a part of a key, so it should use
-   * file paths instead of [Element] location URIs.
+   * Returns the first component of the [element] id.
+   * In the most cases it is an encoding of the [element]'s file path.
+   * If the given [element] is not defined in a file, returns `-1`.
    */
-  int encode(Element element, bool forKey) {
+  int encode1(Element element) {
+    Source source = element.source;
+    if (source == null) {
+      return -1;
+    }
+    String filePath = source.fullName;
+    return _stringCodec.encode(filePath);
+  }
+
+  /**
+   * Returns the second component of the [element] id.
+   * In the most cases it is the [element]'s name offset.
+   */
+  int encode2(Element element) {
     if (element is NameElement) {
       String name = element.name;
-      int nameId = _stringCodec.encode(name);
-      return _encodePath(<int>[nameId]);
+      return _stringCodec.encode(name);
     }
-    // check the location has a cached id
-    ElementLocationImpl location = element.location;
-    if (!identical(location.indexOwner, this)) {
-      location.indexKeyId = null;
-      location.indexLocationId = null;
+    if (element is ConstructorElement) {
+      return element.enclosingElement.nameOffset;
     }
-    if (forKey) {
-      int id = location.indexKeyId;
-      if (id != null) {
-        return id;
-      }
-    } else {
-      int id = location.indexLocationId;
-      if (id != null) {
-        return id;
-      }
+    return element.nameOffset;
+  }
+
+  /**
+   * Returns the third component of the [element] id.
+   * In the most cases it is the [element]'s kind.
+   */
+  int encode3(Element element) {
+    if (element is ConstructorElement) {
+      ClassElement classElement = element.enclosingElement;
+      int constructorIndex = classElement.constructors.indexOf(element);
+      return _CONSTRUCTOR_KIND_BASE - constructorIndex;
     }
-    // prepare an id
-    List<int> path = _getLocationPath(element, location, forKey);
-    int index = _encodePath(path);
-    // put the id into the location
-    if (forKey) {
-      location.indexOwner = this;
-      location.indexKeyId = index;
-    } else {
-      location.indexOwner = this;
-      location.indexLocationId = index;
-    }
-    // done
-    return index;
+    return element.kind.ordinal;
   }
 
   /**
@@ -154,114 +175,6 @@
       return elementNameId;
     }
   }
-
-  /**
-   * Returns a list with the location components of the element with the
-   * given encoded ID.
-   */
-  List<String> inspect_decodePath(int id) {
-    List<int> path = _indexToPath[id];
-    return _getLocationComponents(path);
-  }
-
-  /**
-   * Returns a map of element IDs to their locations for elements with
-   * the [requiredName].
-   */
-  Map<int, List<String>> inspect_getElements(String requiredName) {
-    Map<int, List<String>> result = <int, List<String>>{};
-    for (int i = 0; i < _indexToPath.length; i++) {
-      List<int> path = _indexToPath[i];
-      int nameIndex = path[path.length - 1];
-      if (nameIndex >= 0) {
-        String name = _stringCodec.decode(nameIndex);
-        if (name == requiredName) {
-          result[i] = path.map(_stringCodec.decode).toList();
-        }
-      }
-    }
-    return result;
-  }
-
-  int _encodePath(List<int> path) {
-    int index = _pathToIndex[path];
-    if (index == null) {
-      index = _indexToPath.length;
-      _pathToIndex[path] = index;
-      _indexToPath.add(path);
-    }
-    return index;
-  }
-
-  List<String> _getLocationComponents(List<int> path) {
-    int length = path.length;
-    List<String> components = new List<String>();
-    for (int i = 0; i < length; i++) {
-      int componentId = path[i];
-      String component = _stringCodec.decode(componentId);
-      if (i < length - 1 && path[i + 1] < 0) {
-        component += '@${(-path[i + 1])}';
-        i++;
-      }
-      components.add(component);
-    }
-    return components;
-  }
-
-  /**
-   * If [usePath] is `true` then [Source] path should be used instead of URI.
-   */
-  List<int> _getLocationPath(
-      Element element, ElementLocation location, bool usePath) {
-    // prepare the location components
-    List<String> components = location.components;
-    if (usePath) {
-      LibraryElement library = element.library;
-      if (library != null) {
-        components = components.toList();
-        components[0] = library.source.fullName;
-        for (Element e = element; e != null; e = e.enclosingElement) {
-          if (e is CompilationUnitElement) {
-            components[1] = e.source.fullName;
-            break;
-          }
-        }
-      }
-    }
-    // encode the location
-    int length = components.length;
-    if (_hasLocalOffset(components)) {
-      List<int> path = new List<int>();
-      for (String component in components) {
-        int atOffset = component.indexOf('@');
-        if (atOffset == -1) {
-          path.add(_stringCodec.encode(component));
-        } else {
-          String preAtString = component.substring(0, atOffset);
-          String atString = component.substring(atOffset + 1);
-          path.add(_stringCodec.encode(preAtString));
-          path.add(-1 * int.parse(atString));
-        }
-      }
-      return path;
-    } else {
-      List<int> path = new List<int>.filled(length, 0);
-      for (int i = 0; i < length; i++) {
-        String component = components[i];
-        path[i] = _stringCodec.encode(component);
-      }
-      return path;
-    }
-  }
-
-  static bool _hasLocalOffset(List<String> components) {
-    for (String component in components) {
-      if (component.indexOf('@') != -1) {
-        return true;
-      }
-    }
-    return false;
-  }
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/services/index/store/memory_node_manager.dart b/pkg/analysis_server/lib/src/services/index/store/memory_node_manager.dart
index 27832d7..500626b 100644
--- a/pkg/analysis_server/lib/src/services/index/store/memory_node_manager.dart
+++ b/pkg/analysis_server/lib/src/services/index/store/memory_node_manager.dart
@@ -12,9 +12,15 @@
 import 'package:analyzer/src/generated/engine.dart';
 
 class MemoryNodeManager implements NodeManager {
-  StringCodec _stringCodec = new StringCodec();
-  ContextCodec _contextCodec = new ContextCodec();
-  ElementCodec _elementCodec;
+  @override
+  StringCodec stringCodec = new StringCodec();
+
+  @override
+  ContextCodec contextCodec = new ContextCodec();
+
+  @override
+  ElementCodec elementCodec;
+
   RelationshipCodec _relationshipCodec;
 
   int _locationCount = 0;
@@ -22,18 +28,8 @@
   final Map<String, IndexNode> _nodes = new HashMap<String, IndexNode>();
 
   MemoryNodeManager() {
-    _elementCodec = new ElementCodec(_stringCodec);
-    _relationshipCodec = new RelationshipCodec(_stringCodec);
-  }
-
-  @override
-  ContextCodec get contextCodec {
-    return _contextCodec;
-  }
-
-  @override
-  ElementCodec get elementCodec {
-    return _elementCodec;
+    elementCodec = new ElementCodec(stringCodec);
+    _relationshipCodec = new RelationshipCodec(stringCodec);
   }
 
   @override
@@ -42,11 +38,6 @@
   }
 
   @override
-  StringCodec get stringCodec {
-    return _stringCodec;
-  }
-
-  @override
   void clear() {
     _nodes.clear();
   }
diff --git a/pkg/analysis_server/lib/src/services/index/store/split_store.dart b/pkg/analysis_server/lib/src/services/index/store/split_store.dart
index ab2f025..6610d8a 100644
--- a/pkg/analysis_server/lib/src/services/index/store/split_store.dart
+++ b/pkg/analysis_server/lib/src/services/index/store/split_store.dart
@@ -17,20 +17,24 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
 
 class _TopElementData {
   final String name;
-  final int elementId;
+  final int elementId1;
+  final int elementId2;
+  final int elementId3;
 
   factory _TopElementData(ElementCodec elementCodec, Element element) {
-    return new _TopElementData._(
-        element.name, elementCodec.encode(element, false));
+    return new _TopElementData._(element.name, elementCodec.encode1(element),
+        elementCodec.encode2(element), elementCodec.encode3(element));
   }
 
-  _TopElementData._(this.name, this.elementId);
+  _TopElementData._(
+      this.name, this.elementId1, this.elementId2, this.elementId3);
 
   Element getElement(AnalysisContext context, ElementCodec elementCodec) {
-    return elementCodec.decode(context, elementId);
+    return elementCodec.decode(context, elementId1, elementId2, elementId3);
   }
 }
 
@@ -156,17 +160,23 @@
   }
 
   RelationKeyData _readElementRelationKey(_DataInputStream stream) {
-    int elementId = stream.readInt();
+    int elementId1 = stream.readInt();
+    int elementId2 = stream.readInt();
+    int elementId3 = stream.readInt();
     int relationshipId = stream.readInt();
-    return new RelationKeyData.forData(elementId, relationshipId);
+    return new RelationKeyData.forData(
+        elementId1, elementId2, elementId3, relationshipId);
   }
 
   LocationData _readLocationData(_DataInputStream stream) {
-    int elementId = stream.readInt();
+    int elementId1 = stream.readInt();
+    int elementId2 = stream.readInt();
+    int elementId3 = stream.readInt();
     int offset = stream.readInt();
     int length = stream.readInt();
     int flags = stream.readInt();
-    return new LocationData.forData(elementId, offset, length, flags);
+    return new LocationData.forData(
+        elementId1, elementId2, elementId3, offset, length, flags);
   }
 
   IndexNode _readNode(_DataInputStream stream) {
@@ -204,7 +214,9 @@
   }
 
   void _writeElementRelationKey(_DataOutputStream stream, RelationKeyData key) {
-    stream.writeInt(key.elementId);
+    stream.writeInt(key.elementId1);
+    stream.writeInt(key.elementId2);
+    stream.writeInt(key.elementId3);
     stream.writeInt(key.relationshipId);
   }
 
@@ -224,7 +236,9 @@
       _writeElementRelationKey(stream, key);
       stream.writeInt(locations.length);
       for (LocationData location in locations) {
-        stream.writeInt(location.elementId);
+        stream.writeInt(location.elementId1);
+        stream.writeInt(location.elementId2);
+        stream.writeInt(location.elementId3);
         stream.writeInt(location.offset);
         stream.writeInt(location.length);
         stream.writeInt(location.flags);
@@ -305,18 +319,19 @@
    */
   List<InspectLocation> inspect_getRelations(String name, int elementId) {
     List<InspectLocation> result = <InspectLocation>[];
-    _relations.forEach((RelationKeyData key, locations) {
-      if (key.elementId == elementId) {
-        for (LocationData location in locations) {
-          Relationship relationship =
-              _relationshipCodec.decode(key.relationshipId);
-          List<String> path =
-              _elementCodec.inspect_decodePath(location.elementId);
-          result.add(new InspectLocation(name, relationship, path,
-              location.offset, location.length, location.flags));
-        }
-      }
-    });
+    // TODO(scheglov) restore index inspections?
+//    _relations.forEach((RelationKeyData key, locations) {
+//      if (key.elementId == elementId) {
+//        for (LocationData location in locations) {
+//          Relationship relationship =
+//              _relationshipCodec.decode(key.relationshipId);
+//          List<String> path =
+//              _elementCodec.inspect_decodePath(location.elementId);
+//          result.add(new InspectLocation(name, relationship, path,
+//              location.offset, location.length, location.flags));
+//        }
+//      }
+//    });
     return result;
   }
 
@@ -361,15 +376,20 @@
   static const int _FLAG_QUALIFIED = 1 << 0;
   static const int _FLAG_RESOLVED = 1 << 1;
 
-  final int elementId;
+  final int elementId1;
+  final int elementId2;
+  final int elementId3;
   final int offset;
   final int length;
   final int flags;
 
-  LocationData.forData(this.elementId, this.offset, this.length, this.flags);
+  LocationData.forData(this.elementId1, this.elementId2, this.elementId3,
+      this.offset, this.length, this.flags);
 
   LocationData.forObject(ElementCodec elementCodec, Location location)
-      : elementId = elementCodec.encode(location.element, false),
+      : elementId1 = elementCodec.encode1(location.element),
+        elementId2 = elementCodec.encode2(location.element),
+        elementId3 = elementCodec.encode3(location.element),
         offset = location.offset,
         length = location.length,
         flags = (location.isQualified ? _FLAG_QUALIFIED : 0) |
@@ -377,7 +397,13 @@
 
   @override
   int get hashCode {
-    return 31 * (31 * elementId + offset) + length;
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, elementId1);
+    hash = JenkinsSmiHash.combine(hash, elementId2);
+    hash = JenkinsSmiHash.combine(hash, elementId3);
+    hash = JenkinsSmiHash.combine(hash, offset);
+    hash = JenkinsSmiHash.combine(hash, length);
+    return JenkinsSmiHash.finish(hash);
   }
 
   @override
@@ -386,7 +412,9 @@
       return false;
     }
     LocationData other = obj;
-    return other.elementId == elementId &&
+    return other.elementId1 == elementId1 &&
+        other.elementId2 == elementId2 &&
+        other.elementId3 == elementId3 &&
         other.offset == offset &&
         other.length == length &&
         other.flags == flags;
@@ -396,7 +424,8 @@
    * Returns a {@link Location} that is represented by this {@link LocationData}.
    */
   Location getLocation(AnalysisContext context, ElementCodec elementCodec) {
-    Element element = elementCodec.decode(context, elementId);
+    Element element =
+        elementCodec.decode(context, elementId1, elementId2, elementId3);
     if (element == null) {
       return null;
     }
@@ -461,20 +490,35 @@
  * An [Element] to [Location] relation key.
  */
 class RelationKeyData {
-  final int elementId;
+  final int elementId1;
+  final int elementId2;
+  final int elementId3;
   final int relationshipId;
 
-  RelationKeyData.forData(this.elementId, this.relationshipId);
+  RelationKeyData.forData(
+      this.elementId1, this.elementId2, this.elementId3, this.relationshipId);
 
   RelationKeyData.forObject(ElementCodec elementCodec,
       RelationshipCodec relationshipCodec, Element element,
       Relationship relationship)
-      : elementId = elementCodec.encode(element, true),
+      : elementId1 = elementCodec.encode1(element),
+        elementId2 = elementCodec.encode2(element),
+        elementId3 = elementCodec.encode3(element),
         relationshipId = relationshipCodec.encode(relationship);
 
   @override
   int get hashCode {
-    return 31 * elementId + relationshipId;
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, elementId1);
+    hash = JenkinsSmiHash.combine(hash, elementId2);
+    hash = JenkinsSmiHash.combine(hash, elementId3);
+    hash = JenkinsSmiHash.combine(hash, relationshipId);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() {
+    return 'Key($elementId2, $elementId2, $elementId3, $relationshipId)';
   }
 
   @override
@@ -483,7 +527,9 @@
       return false;
     }
     RelationKeyData other = obj;
-    return other.elementId == elementId &&
+    return other.elementId1 == elementId1 &&
+        other.elementId2 == elementId2 &&
+        other.elementId3 == elementId3 &&
         other.relationshipId == relationshipId;
   }
 }
@@ -746,42 +792,44 @@
       String name) {
     Map<List<String>, List<InspectLocation>> result =
         <List<String>, List<InspectLocation>>{};
-    // prepare elements
-    Map<int, List<String>> elementMap = _elementCodec.inspect_getElements(name);
-    // prepare relations with each element
-    List<Future> futures = <Future>[];
-    if (_nodeManager is FileNodeManager) {
-      List<String> nodeNames =
-          (_nodeManager as FileNodeManager).inspect_getAllNodeNames();
-      nodeNames.forEach((nodeName) {
-        Future<IndexNode> nodeFuture = _nodeManager.getNode(nodeName);
-        Future relationsFuture = nodeFuture.then((node) {
-          if (node != null) {
-            elementMap.forEach((int elementId, List<String> elementPath) {
-              List<InspectLocation> relations =
-                  node.inspect_getRelations(nodeName, elementId);
-              List<InspectLocation> resultLocations = result[elementPath];
-              if (resultLocations == null) {
-                resultLocations = <InspectLocation>[];
-                result[elementPath] = resultLocations;
-              }
-              resultLocations.addAll(relations);
-            });
-          }
-        });
-        futures.add(relationsFuture);
-      });
-    }
-    // wait for all nodex
-    return Future.wait(futures).then((_) {
-      return result;
-    });
+    // TODO(scheglov) restore index inspections?
+    return new Future.value(result);
+//    // prepare elements
+//    Map<int, List<String>> elementMap = _elementCodec.inspect_getElements(name);
+//    // prepare relations with each element
+//    List<Future> futures = <Future>[];
+//    if (_nodeManager is FileNodeManager) {
+//      List<String> nodeNames =
+//          (_nodeManager as FileNodeManager).inspect_getAllNodeNames();
+//      nodeNames.forEach((nodeName) {
+//        Future<IndexNode> nodeFuture = _nodeManager.getNode(nodeName);
+//        Future relationsFuture = nodeFuture.then((node) {
+//          if (node != null) {
+//            elementMap.forEach((int elementId, List<String> elementPath) {
+//              List<InspectLocation> relations =
+//                  node.inspect_getRelations(nodeName, elementId);
+//              List<InspectLocation> resultLocations = result[elementPath];
+//              if (resultLocations == null) {
+//                resultLocations = <InspectLocation>[];
+//                result[elementPath] = resultLocations;
+//              }
+//              resultLocations.addAll(relations);
+//            });
+//          }
+//        });
+//        futures.add(relationsFuture);
+//      });
+//    }
+//    // wait for all nodex
+//    return Future.wait(futures).then((_) {
+//      return result;
+//    });
   }
 
   @override
   void recordRelationship(
       Element element, Relationship relationship, Location location) {
-    if (element == null || element.location == null) {
+    if (element == null || element is MultiplyDefinedElement) {
       return;
     }
     if (location == null) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index da4e4e4..0603b43 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -22,6 +22,7 @@
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart' show ExitDetector;
 import 'package:analyzer/src/generated/scanner.dart';
@@ -62,6 +63,7 @@
   final CompilationUnit unit;
   final int selectionOffset;
   final int selectionLength;
+  AnalysisContext context;
   CompilationUnitElement unitElement;
   LibraryElement libraryElement;
   SourceRange selectionRange;
@@ -69,6 +71,7 @@
   Set<LibraryElement> librariesToImport = new Set<LibraryElement>();
 
   String returnType;
+  String variableType;
   String name;
   bool extractAll = true;
   bool canCreateGetter = false;
@@ -77,13 +80,23 @@
   final List<int> offsets = <int>[];
   final List<int> lengths = <int>[];
 
-  Set<String> _usedNames = new Set<String>();
+  /**
+   * The map of local names to their visibility ranges.
+   */
+  Map<String, List<SourceRange>> _localNames = <String, List<SourceRange>>{};
+
+  /**
+   * The set of names that are referenced without any qualifier.
+   */
+  Set<String> _unqualifiedNames = new Set<String>();
+
   Set<String> _excludedNames = new Set<String>();
   List<RefactoringMethodParameter> _parameters = <RefactoringMethodParameter>[];
   Map<String, RefactoringMethodParameter> _parametersMap =
       <String, RefactoringMethodParameter>{};
   Map<String, List<SourceRange>> _parameterReferencesMap =
       <String, List<SourceRange>>{};
+  bool _hasAwait = false;
   DartType _returnType;
   String _returnVariableName;
   AstNode _parentMember;
@@ -97,6 +110,7 @@
       this.selectionOffset, this.selectionLength) {
     unitElement = unit.element;
     libraryElement = unitElement.library;
+    context = libraryElement.context;
     selectionRange = new SourceRange(selectionOffset, selectionLength);
     utils = new CorrectionUtils(unit);
   }
@@ -173,6 +187,7 @@
     }
     // prepare parts
     result.addStatus(_initializeParameters());
+    _initializeHasAwait();
     _initializeReturnType();
     // occurrences
     _initializeOccurrences();
@@ -217,17 +232,17 @@
       } else {
         StringBuffer sb = new StringBuffer();
         // may be returns value
-        if (_selectionStatements != null && returnType != 'void') {
+        if (_selectionStatements != null && variableType != null) {
           // single variable assignment / return statement
           if (_returnVariableName != null) {
             String occurrenceName =
                 occurence._parameterOldToOccurrenceName[_returnVariableName];
             // may be declare variable
             if (!_parametersMap.containsKey(_returnVariableName)) {
-              if (returnType.isEmpty) {
+              if (variableType.isEmpty) {
                 sb.write('var ');
               } else {
-                sb.write(returnType);
+                sb.write(variableType);
                 sb.write(' ');
               }
             }
@@ -238,6 +253,10 @@
             sb.write('return ');
           }
         }
+        // await
+        if (_hasAwait) {
+          sb.write('await ');
+        }
         // invocation itself
         sb.write(name);
         if (!createGetter) {
@@ -293,6 +312,8 @@
             declarationSource += ';';
           }
         }
+        // optional 'async' body modifier
+        String asyncKeyword = _hasAwait ? ' async' : '';
         // expression
         if (_selectionExpression != null) {
           // add return type
@@ -300,15 +321,15 @@
             annotations += '$returnType ';
           }
           // just return expression
-          declarationSource =
-              '${annotations}${signature} => ${returnExpressionSource};';
+          declarationSource = '$annotations$signature$asyncKeyword => ';
+          declarationSource += '$returnExpressionSource;';
         }
         // statements
         if (_selectionStatements != null) {
           if (returnType.isNotEmpty) {
             annotations += returnType + ' ';
           }
-          declarationSource = '${annotations}${signature} {${eol}';
+          declarationSource = '$annotations$signature$asyncKeyword {$eol';
           declarationSource += returnExpressionSource;
           if (_returnVariableName != null) {
             declarationSource +=
@@ -356,7 +377,7 @@
           return result;
         }
       }
-      if (_usedNames.contains(parameter.name)) {
+      if (_isParameterNameConflictWithBody(parameter)) {
         result.addError(format(
             "'{0}' is already used as a name in the selected code",
             parameter.name));
@@ -523,6 +544,16 @@
     return utils.getTypeSource(type, librariesToImport);
   }
 
+  void _initializeHasAwait() {
+    _HasAwaitVisitor visitor = new _HasAwaitVisitor();
+    if (_selectionExpression != null) {
+      _selectionExpression.accept(visitor);
+    } else if (_selectionStatements != null) {
+      _selectionStatements.forEach((statement) => statement.accept(visitor));
+    }
+    _hasAwait = visitor.result;
+  }
+
   /**
    * Fills [_occurrences] field.
    */
@@ -600,15 +631,33 @@
   }
 
   void _initializeReturnType() {
+    InterfaceType futureType = context.typeProvider.futureType;
     if (_selectionFunctionExpression != null) {
+      variableType = '';
       returnType = '';
     } else if (_returnType == null) {
-      returnType = 'void';
+      variableType = null;
+      if (_hasAwait) {
+        returnType = _getTypeCode(futureType);
+      } else {
+        returnType = 'void';
+      }
+    } else if (_returnType.isDynamic) {
+      variableType = '';
+      if (_hasAwait) {
+        returnType = _getTypeCode(futureType);
+      } else {
+        returnType = '';
+      }
     } else {
-      returnType = _getTypeCode(_returnType);
-    }
-    if (returnType == 'dynamic') {
-      returnType = '';
+      variableType = _getTypeCode(_returnType);
+      if (_hasAwait) {
+        if (_returnType.element != futureType.element) {
+          returnType = _getTypeCode(futureType.substitute4([_returnType]));
+        }
+      } else {
+        returnType = variableType;
+      }
     }
   }
 
@@ -628,6 +677,26 @@
     return analyzer.status.isOK;
   }
 
+  bool _isParameterNameConflictWithBody(RefactoringMethodParameter parameter) {
+    String id = parameter.id;
+    String name = parameter.name;
+    List<SourceRange> parameterRanges = _parameterReferencesMap[id];
+    List<SourceRange> otherRanges = _localNames[name];
+    for (SourceRange parameterRange in parameterRanges) {
+      if (otherRanges != null) {
+        for (SourceRange otherRange in otherRanges) {
+          if (parameterRange.intersects(otherRange)) {
+            return true;
+          }
+        }
+      }
+    }
+    if (_unqualifiedNames.contains(name)) {
+      return true;
+    }
+    return false;
+  }
+
   /**
    * Checks if [element] is referenced after [selectionRange].
    */
@@ -855,6 +924,23 @@
   }
 }
 
+class _HasAwaitVisitor extends GeneralizingAstVisitor {
+  bool result = false;
+
+  @override
+  visitAwaitExpression(AwaitExpression node) {
+    result = true;
+  }
+
+  @override
+  visitForEachStatement(ForEachStatement node) {
+    if (node.awaitKeyword != null) {
+      result = true;
+    }
+    super.visitForEachStatement(node);
+  }
+}
+
 class _HasReturnStatementVisitor extends RecursiveAstVisitor {
   bool hasReturn = false;
 
@@ -973,56 +1059,64 @@
   }
 }
 
-class _InitializeParametersVisitor extends GeneralizingAstVisitor<Object> {
+class _InitializeParametersVisitor extends GeneralizingAstVisitor {
   final ExtractMethodRefactoringImpl ref;
   final List<VariableElement> assignedUsedVariables;
 
   _InitializeParametersVisitor(this.ref, this.assignedUsedVariables);
 
   @override
-  Object visitSimpleIdentifier(SimpleIdentifier node) {
+  void visitSimpleIdentifier(SimpleIdentifier node) {
     SourceRange nodeRange = rangeNode(node);
-    if (ref.selectionRange.covers(nodeRange)) {
-      // analyze local variable
-      VariableElement variableElement =
-          getLocalOrParameterVariableElement(node);
-      if (variableElement != null) {
-        // name of the named expression
-        if (isNamedExpressionName(node)) {
-          return null;
-        }
-        // if declared outside, add parameter
-        if (!ref._isDeclaredInSelection(variableElement)) {
-          String variableName = variableElement.displayName;
-          // add parameter
-          RefactoringMethodParameter parameter =
-              ref._parametersMap[variableName];
-          if (parameter == null) {
-            DartType parameterType = node.bestType;
-            String parameterTypeCode = ref._getTypeCode(parameterType);
-            parameter = new RefactoringMethodParameter(
-                RefactoringMethodParameterKind.REQUIRED, parameterTypeCode,
-                variableName, id: variableName);
-            ref._parameters.add(parameter);
-            ref._parametersMap[variableName] = parameter;
-          }
-          // add reference to parameter
-          ref._addParameterReference(variableName, nodeRange);
-        }
-        // remember, if assigned and used after selection
-        if (isLeftHandOfAssignment(node) &&
-            ref._isUsedAfterSelection(variableElement)) {
-          if (!assignedUsedVariables.contains(variableElement)) {
-            assignedUsedVariables.add(variableElement);
-          }
-        }
+    if (!ref.selectionRange.covers(nodeRange)) {
+      return;
+    }
+    String name = node.name;
+    // analyze local variable
+    VariableElement variableElement = getLocalOrParameterVariableElement(node);
+    if (variableElement != null) {
+      // name of the named expression
+      if (isNamedExpressionName(node)) {
+        return;
       }
-      // remember declaration names
-      if (node.inDeclarationContext()) {
-        ref._usedNames.add(node.name);
+      // if declared outside, add parameter
+      if (!ref._isDeclaredInSelection(variableElement)) {
+        // add parameter
+        RefactoringMethodParameter parameter = ref._parametersMap[name];
+        if (parameter == null) {
+          DartType parameterType = node.bestType;
+          String parameterTypeCode = ref._getTypeCode(parameterType);
+          parameter = new RefactoringMethodParameter(
+              RefactoringMethodParameterKind.REQUIRED, parameterTypeCode, name,
+              id: name);
+          ref._parameters.add(parameter);
+          ref._parametersMap[name] = parameter;
+        }
+        // add reference to parameter
+        ref._addParameterReference(name, nodeRange);
+      }
+      // remember, if assigned and used after selection
+      if (isLeftHandOfAssignment(node) &&
+          ref._isUsedAfterSelection(variableElement)) {
+        if (!assignedUsedVariables.contains(variableElement)) {
+          assignedUsedVariables.add(variableElement);
+        }
       }
     }
-    return null;
+    // remember information for conflicts checking
+    if (variableElement is LocalElement) {
+      // declared local elements
+      LocalElement localElement = variableElement as LocalElement;
+      if (node.inDeclarationContext()) {
+        ref._localNames.putIfAbsent(name, () => <SourceRange>[]);
+        ref._localNames[name].add(localElement.visibleRange);
+      }
+    } else {
+      // unqualified non-local names
+      if (!node.isQualified) {
+        ref._unqualifiedNames.add(name);
+      }
+    }
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
index a9b6e79..350517a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -145,14 +145,6 @@
           int initOffset = initializer.contentsOffset;
           int initLength = initializer.contentsEnd - initOffset;
           codeForReference = utils.getText(initOffset, initLength);
-          // drop leading multiline EOL
-          if (initializer.isMultiline) {
-            if (codeForReference.startsWith('\n')) {
-              codeForReference = codeForReference.substring(1);
-            } else if (codeForReference.startsWith('\r\n')) {
-              codeForReference = codeForReference.substring(2);
-            }
-          }
         } else if (_shouldBeExpressionInterpolation(parent, initializer)) {
           codeForReference = '{$initializerCode}';
         } else {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
index e58b535d..6f910a9 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -14,6 +14,7 @@
 import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
 import 'package:analysis_server/src/services/refactoring/rename.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/source.dart';
 
@@ -76,10 +77,38 @@
     List<SourceReference> references = getSourceReferences(matches);
     for (SourceReference reference in references) {
       if (newName.isEmpty) {
-        reference.addEdit(change, newName);
+        reference.addEdit(change, '');
       } else {
-        reference.addEdit(change, "${newName}.");
+        SimpleIdentifier interpolationIdentifier =
+            _getInterpolationIdentifier(reference);
+        if (interpolationIdentifier != null) {
+          doSourceChange_addElementEdit(change, reference.element,
+              new SourceEdit(interpolationIdentifier.offset,
+                  interpolationIdentifier.length,
+                  '{$newName.${interpolationIdentifier.name}}'));
+        } else {
+          reference.addEdit(change, '$newName.');
+        }
       }
     }
   }
+
+  /**
+   * If the given [reference] is before an interpolated [SimpleIdentifier] in
+   * an [InterpolationExpression] without surrounding curly brackets, return it.
+   * Otherwise return `null`.
+   */
+  SimpleIdentifier _getInterpolationIdentifier(SourceReference reference) {
+    Source source = reference.element.source;
+    CompilationUnit unit = context.parseCompilationUnit(source);
+    NodeLocator nodeLocator = new NodeLocator.con1(reference.range.offset);
+    AstNode node = nodeLocator.searchWithin(unit);
+    if (node is SimpleIdentifier) {
+      AstNode parent = node.parent;
+      if (parent is InterpolationExpression && parent.rightBracket == null) {
+        return node;
+      }
+    }
+    return null;
+  }
 }
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 121f148..927bdee 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -6,8 +6,9 @@
 environment:
   sdk: '>=1.0.0 <2.0.0'
 dependencies:
-  analyzer: 0.25.0-dev.1
+  analyzer: '>=0.24.1-alpha.0 <0.25.0'
   args: '>=0.12.1 <0.13.0'
+  dart_style: '>=0.1.7 <0.2.0'
   logging: any
   path: any
   watcher: any
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 423d8d7..bb9a85a 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -44,9 +44,9 @@
   UriResolver resourceResolver;
   AnalysisContext context;
 
-  Source addSource(String path, String content) {
+  Source addSource(String path, String content, [Uri uri]) {
     File file = provider.newFile(path, content);
-    Source source = file.createSource();
+    Source source = file.createSource(uri);
     ChangeSet changeSet = new ChangeSet();
     changeSet.addedSource(source);
     context.applyChanges(changeSet);
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index 51bd183..6d0e7a0 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -23,9 +23,9 @@
   CompilationUnitElement testUnitElement;
   LibraryElement testLibraryElement;
 
-  void addTestSource(String code) {
+  void addTestSource(String code, [Uri uri]) {
     testCode = code;
-    testSource = addSource(testFile, code);
+    testSource = addSource(testFile, code, uri);
   }
 
   void assertNoErrorsInSource(Source source) {
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index d499a4c..6428832 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -129,7 +129,7 @@
       expect(hover.containingLibraryPath, testFile);
       expect(hover.containingClassDescription, 'A');
       expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
-      expect(hover.elementDescription, 'A.mmm(int a, String b) → List<String>');
+      expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
       expect(hover.elementKind, 'method');
       // types
       expect(hover.staticType, '(int, String) → List<String>');
@@ -157,7 +157,7 @@
       // element
       expect(hover.containingLibraryName, 'my.library');
       expect(hover.containingLibraryPath, testFile);
-      expect(hover.elementDescription, 'A.mmm(int a, String b) → List<String>');
+      expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
       expect(hover.elementKind, 'method');
       // types
       expect(hover.staticType, isNull);
@@ -203,8 +203,9 @@
 ''');
     return prepareHover('vvv);').then((HoverInformation hover) {
       // element
-      expect(hover.containingLibraryName, 'my.library');
-      expect(hover.containingLibraryPath, testFile);
+      expect(hover.containingLibraryName, isNull);
+      expect(hover.containingLibraryPath, isNull);
+      expect(hover.containingClassDescription, isNull);
       expect(hover.dartdoc, isNull);
       expect(hover.elementDescription, 'dynamic vvv');
       expect(hover.elementKind, 'local variable');
@@ -214,6 +215,31 @@
     });
   }
 
+  test_expression_variable_inMethod() {
+    addTestFile('''
+library my.library;
+class A {
+  m() {
+    num vvv = 42;
+  }
+}
+''');
+    return prepareHover('vvv = 42').then((HoverInformation hover) {
+      // element
+      expect(hover.containingLibraryName, isNull);
+      expect(hover.containingLibraryPath, isNull);
+      expect(hover.containingClassDescription, isNull);
+      expect(hover.dartdoc, isNull);
+      expect(hover.elementDescription, 'num vvv');
+      expect(hover.elementKind, 'local variable');
+      // types
+      expect(hover.staticType, 'num');
+      expect(hover.propagatedType, 'int');
+      // no parameter
+      expect(hover.parameter, isNull);
+    });
+  }
+
   test_instanceCreation_implicit() {
     addTestFile('''
 library my.library;
diff --git a/pkg/analysis_server/test/analysis/notification_overrides_test.dart b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
index 7875504..17a1e49 100644
--- a/pkg/analysis_server/test/analysis/notification_overrides_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
@@ -138,6 +138,40 @@
     });
   }
 
+  test_definedInInterface_ofInterface() {
+    addTestFile('''
+class A {
+  m() {} // in A
+}
+class B implements A {}
+class C implements B {
+  m() {} // in C
+}
+''');
+    return prepareOverrides().then((_) {
+      assertHasOverride('m() {} // in C');
+      assertNoSuperMember();
+      assertHasInterfaceMember('m() {} // in A');
+    });
+  }
+
+  test_definedInInterface_ofSuper() {
+    addTestFile('''
+class A {
+  m() {} // in A
+}
+class B implements A {}
+class C extends B {
+  m() {} // in C
+}
+''');
+    return prepareOverrides().then((_) {
+      assertHasOverride('m() {} // in C');
+      assertNoSuperMember();
+      assertHasInterfaceMember('m() {} // in A');
+    });
+  }
+
   test_interface_method_direct_multiple() {
     addTestFile('''
 class IA {
@@ -323,6 +357,20 @@
     });
   }
 
+  test_super_method_superTypeCycle() {
+    addTestFile('''
+class A extends B {
+  m() {} // in A
+}
+class B extends A {
+  m() {} // in B
+}
+''');
+    return prepareOverrides().then((_) {
+      // must finish
+    });
+  }
+
   test_super_setterBySetter() {
     addTestFile('''
 class A {
diff --git a/pkg/analysis_server/test/analysis/reanalyze_test.dart b/pkg/analysis_server/test/analysis/reanalyze_test.dart
index 0041e82..2e85d6d 100644
--- a/pkg/analysis_server/test/analysis/reanalyze_test.dart
+++ b/pkg/analysis_server/test/analysis/reanalyze_test.dart
@@ -59,7 +59,7 @@
       // re-analyzed.
       filesErrors.remove(testFile);
       // Reanalyze.
-      server.reanalyze();
+      server.reanalyze(null);
       return waitForTasksFinished();
     }).then((_) {
       // The file should have been reanalyzed.
diff --git a/pkg/analysis_server/test/analysis/update_content_test.dart b/pkg/analysis_server/test/analysis/update_content_test.dart
index 694b9e2..226b6c1 100644
--- a/pkg/analysis_server/test/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/analysis/update_content_test.dart
@@ -7,7 +7,10 @@
 import 'package:analysis_server/src/constants.dart';
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/services/index/index.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:typed_mock/typed_mock.dart';
 import 'package:unittest/unittest.dart';
 
@@ -104,7 +107,7 @@
     verify(server.index.indexUnit(anyObject, testUnitMatcher)).times(2);
   }
 
-  test_multiple_contexts() {
+  test_multiple_contexts() async {
     String fooPath = '/project1/foo.dart';
     resourceProvider.newFile(fooPath, '''
 library foo;
@@ -123,7 +126,8 @@
     Request request = new AnalysisSetAnalysisRootsParams(
         ['/project1', '/project2'], []).toRequest('0');
     handleSuccessfulRequest(request);
-    return waitForTasksFinished().then((_) {
+    {
+      await server.onAnalysisComplete;
       // Files foo.dart and bar.dart should both have errors, since they both
       // call f() with the wrong number of arguments.
       expect(filesErrors[fooPath], hasLength(1));
@@ -135,13 +139,42 @@
 f() {}
 ''')
       });
-      return waitForTasksFinished();
-    }).then((_) {
+    }
+    {
+      await server.onAnalysisComplete;
       // The overlay should have been propagated to both contexts, causing both
       // foo.dart and bar.dart to be reanalyzed and found to be free of errors.
       expect(filesErrors[fooPath], isEmpty);
       expect(filesErrors[barPath], isEmpty);
-    });
+    }
+  }
+
+  test_overlayOnly() async {
+    String filePath = '/User/project1/test.dart';
+    Folder folder1 = resourceProvider.newFolder('/User/project1');
+    Folder folder2 = resourceProvider.newFolder('/User/project2');
+    Request request = new AnalysisSetAnalysisRootsParams(
+        [folder1.path, folder2.path], []).toRequest('0');
+    handleSuccessfulRequest(request);
+    // exactly 2 contexts
+    expect(server.folderMap, hasLength(2));
+    AnalysisContext context1 = server.folderMap[folder1];
+    AnalysisContext context2 = server.folderMap[folder2];
+    // no sources
+    expect(_getUserSources(context1), isEmpty);
+    expect(_getUserSources(context2), isEmpty);
+    // add an overlay - new Source in context1
+    server.updateContent('1', {filePath: new AddContentOverlay('')});
+    {
+      List<Source> sources = _getUserSources(context1);
+      expect(sources, hasLength(1));
+      expect(sources[0].fullName, filePath);
+    }
+    expect(_getUserSources(context2), isEmpty);
+    // remove the overlay - no sources
+    server.updateContent('2', {filePath: new RemoveContentOverlay()});
+    expect(_getUserSources(context1), isEmpty);
+    expect(_getUserSources(context2), isEmpty);
   }
 
   test_sendNoticesAfterNopChange() async {
@@ -180,6 +213,16 @@
     // errors should have been resent
     expect(filesErrors, isNotEmpty);
   }
+
+  List<Source> _getUserSources(AnalysisContext context) {
+    List<Source> sources = <Source>[];
+    context.sources.forEach((source) {
+      if (source.fullName.startsWith('/User/')) {
+        sources.add(source);
+      }
+    });
+    return sources;
+  }
 }
 
 class _ArgumentMatcher_CompilationUnit extends ArgumentMatcher {
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index efd1c16..374f47b 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -203,7 +203,7 @@
     File bar = resourceProvider.newFile('/bar/bar.dart', 'library lib;');
     Source barSource = bar.createSource();
     server.setAnalysisRoots('0', ['/foo', '/bar'], [], {});
-    return pumpEventQueue(40).then((_) {
+    return pumpEventQueue(50).then((_) {
       expect(server.statusAnalyzing, isFalse);
       // Make sure getAnalysisContext returns the proper context for each.
       AnalysisContext fooContext =
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index cc43193..de752be 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -644,10 +644,10 @@
         }''', <String>["1+HttpResponse"]);
 
     buildTests('testCommentSnippets083', '''
-main() {(.!1)}''', <String>["1-toString"], failingTests: '1');
+main() {(.!1)}''', <String>["1-toString"]);
 
     buildTests('testCommentSnippets083a', '''
-main() { .!1 }''', <String>["1-toString"], failingTests: '1');
+main() { .!1 }''', <String>["1-toString"]);
 
     buildTests('testCommentSnippets083b', '''
 main() { null.!1 }''', <String>["1+toString"], failingTests: '1');
@@ -1835,7 +1835,7 @@
       "B-Ctype",
       "C+Bclass",
       "C-Eclass"
-    ], failingTests: '12345679ABC');
+    ], failingTests: '23467ABC');
 
     // keywords
     buildTests('test009', '''
@@ -1852,7 +1852,7 @@
       "5+TestFn2",
       "6+num",
       "7+typedef"
-    ], failingTests: '12347');
+    ], failingTests: '1234');
 
     buildTests('test010', '''
 class test !8<!1t !2 !3extends String,!4 List,!5 !6>!7 {}
@@ -1927,7 +1927,7 @@
       "8+==",
       "9+==",
       "0+k"
-    ], failingTests: '5689');
+    ], failingTests: '689');
 
     // keywords
     buildTests('test014', '''
@@ -1969,7 +1969,7 @@
       "J+if",
       "K+else",
       "L+return"
-    ], failingTests: '123456789ABCDEFGHJKL');
+    ], failingTests: '59BCHK');
 
     // operators in function
     buildTests('test015', '''f(a,b,c) => a + b * c !1;''', <String>["1+=="],
@@ -1995,11 +1995,11 @@
       "6+hide",
       "7+show",
       "8-null"
-    ], failingTests: '1234567');
+    ], failingTests: '1567');
 
     // keywords
     buildTests('test018', '''!1part !2of foo;''', <String>["1+part", "2+of"],
-        failingTests: '12');
+        failingTests: '2');
 
     buildTests('test019', '''
 var truefalse = 0;
@@ -2011,11 +2011,9 @@
     buildTests('test020', '''var x = null.!1''', <String>["1+toString"],
         failingTests: '1');
 
-    buildTests('test021', '''var x = .!1''', <String>["1-toString"],
-        failingTests: '1');
+    buildTests('test021', '''var x = .!1''', <String>["1-toString"]);
 
-    buildTests('test022', '''var x = .!1;''', <String>["1-toString"],
-        failingTests: '1');
+    buildTests('test022', '''var x = .!1;''', <String>["1-toString"]);
 
     buildTests('test023', '''
 class Map{getKeys(){}}
@@ -2100,8 +2098,7 @@
 
     buildTests('test031',
         '''class Caster {} m() {try {} on Cas!1ter catch (CastBlock) {!2}}''',
-        <String>["1+Caster", "1-CastBlock", "2+Caster", "2+CastBlock"],
-        failingTests: '1');
+        <String>["1+Caster", "1-CastBlock", "2+Caster", "2+CastBlock"]);
 
     buildTests('test032', '''
 const ONE = 1;
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 61a3c09..4a4ec36 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -32,10 +32,17 @@
    * The name of the 'bin' directory.
    */
   static const String BIN_NAME = 'bin';
+
+  /**
+   * The name of the 'example' directory.
+   */
+  static const String EXAMPLE_NAME = 'example';
+
   /**
    * The name of the 'lib' directory.
    */
   static const String LIB_NAME = 'lib';
+
   /**
    * The name of the 'src' directory.
    */
@@ -122,7 +129,7 @@
     return pumpEventQueue().then((_) {
       expect(manager.currentContextPaths.toList(), [projPath]);
       manager.now++;
-      manager.refresh();
+      manager.refresh(null);
       return pumpEventQueue().then((_) {
         expect(manager.currentContextPaths.toList(), [projPath]);
         expect(manager.currentContextTimestamps[projPath], manager.now);
@@ -144,7 +151,7 @@
       expect(manager.currentContextPaths.toSet(),
           [subdir1Path, subdir2Path, projPath].toSet());
       manager.now++;
-      manager.refresh();
+      manager.refresh(null);
       return pumpEventQueue().then((_) {
         expect(manager.currentContextPaths.toSet(),
             [subdir1Path, subdir2Path, projPath].toSet());
@@ -155,6 +162,31 @@
     });
   }
 
+  test_refresh_oneContext() {
+    // create two contexts with pubspec.yaml files
+    String pubspecPath = posix.join(projPath, 'pubspec.yaml');
+    resourceProvider.newFile(pubspecPath, 'pubspec1');
+
+    String proj2Path = '/my/proj2';
+    resourceProvider.newFolder(proj2Path);
+    String pubspec2Path = posix.join(proj2Path, 'pubspec.yaml');
+    resourceProvider.newFile(pubspec2Path, 'pubspec2');
+
+    List<String> roots = <String>[projPath, proj2Path];
+    manager.setRoots(roots, <String>[], <String, String>{});
+    return pumpEventQueue().then((_) {
+      expect(manager.currentContextPaths.toList(), unorderedEquals(roots));
+      int then = manager.now;
+      manager.now++;
+      manager.refresh([resourceProvider.getResource(proj2Path)]);
+      return pumpEventQueue().then((_) {
+        expect(manager.currentContextPaths.toList(), unorderedEquals(roots));
+        expect(manager.currentContextTimestamps[projPath], then);
+        expect(manager.currentContextTimestamps[proj2Path], manager.now);
+      });
+    });
+  }
+
   void test_setRoots_addFolderWithDartFile() {
     String filePath = posix.join(projPath, 'foo.dart');
     resourceProvider.newFile(filePath, 'contents');
@@ -184,6 +216,34 @@
     expect(filePaths, isEmpty);
   }
 
+  void test_setRoots_addFolderWithNestedPubspec() {
+    String examplePath = newFolder([projPath, EXAMPLE_NAME]);
+    String libPath = newFolder([projPath, LIB_NAME]);
+
+    newFile([projPath, PUBSPEC_NAME]);
+    newFile([libPath, 'main.dart']);
+    newFile([examplePath, PUBSPEC_NAME]);
+    newFile([examplePath, 'example.dart']);
+
+    packageMapProvider.packageMap['proj'] =
+        [resourceProvider.getResource(libPath)];
+
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+
+    expect(manager.currentContextPaths, hasLength(2));
+
+    expect(manager.currentContextPaths, contains(projPath));
+    Set<Source> projSources = manager.currentContextSources[projPath];
+    expect(projSources, hasLength(1));
+    expect(projSources.first.uri.toString(), 'package:proj/main.dart');
+
+    expect(manager.currentContextPaths, contains(examplePath));
+    Set<Source> exampleSources = manager.currentContextSources[examplePath];
+    expect(exampleSources, hasLength(1));
+    expect(exampleSources.first.uri.toString(),
+        'file:///my/proj/example/example.dart');
+  }
+
   void test_setRoots_addFolderWithoutPubspec() {
     packageMapProvider.packageMap = null;
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -215,9 +275,8 @@
     newFile([srcPath, 'internal.dart']);
     String testFilePath = newFile([testPath, 'main_test.dart']);
 
-    packageMapProvider.packageMap['proj'] = [
-      resourceProvider.getResource(libPath)
-    ];
+    packageMapProvider.packageMap['proj'] =
+        [resourceProvider.getResource(libPath)];
 
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     Set<Source> sources = manager.currentContextSources[projPath];
@@ -276,8 +335,9 @@
     List<String> excludedPaths = <String>[];
     manager.setRoots(includedPaths, excludedPaths, <String, String>{});
     _checkPackageMap(projPath, equals(packageMapProvider.packageMap));
-    manager.setRoots(includedPaths,
-        excludedPaths, <String, String>{projPath: packageRootPath});
+    manager.setRoots(includedPaths, excludedPaths, <String, String>{
+      projPath: packageRootPath
+    });
     _checkPackageRoot(projPath, equals(packageRootPath));
   }
 
@@ -290,8 +350,9 @@
       projPath: packageRootPath1
     });
     _checkPackageRoot(projPath, equals(packageRootPath1));
-    manager.setRoots(includedPaths,
-        excludedPaths, <String, String>{projPath: packageRootPath2});
+    manager.setRoots(includedPaths, excludedPaths, <String, String>{
+      projPath: packageRootPath2
+    });
     _checkPackageRoot(projPath, equals(packageRootPath2));
   }
 
@@ -419,26 +480,6 @@
     manager.assertContextFiles(project, [fileA, fileB]);
   }
 
-  void test_setRoots_ignoreSubContext_ofSubContext() {
-    // prepare paths
-    String root = '/root';
-    String rootFile = '$root/root.dart';
-    String subProject = '$root/sub';
-    String subPubspec = '$subProject/pubspec.yaml';
-    String subFile = '$subProject/bin/sub.dart';
-    String subSubPubspec = '$subProject/subsub/pubspec.yaml';
-    // create files
-    resourceProvider.newFile(rootFile, 'library root;');
-    resourceProvider.newFile(subPubspec, 'pubspec');
-    resourceProvider.newFile(subFile, 'library sub;');
-    resourceProvider.newFile(subSubPubspec, 'pubspec');
-    // set roots
-    manager.setRoots(<String>[root], <String>[], <String, String>{});
-    manager.assertContextPaths([root, subProject]);
-    manager.assertContextFiles(root, [rootFile]);
-    manager.assertContextFiles(subProject, [subFile]);
-  }
-
   void test_setRoots_newFolderWithPackageRoot() {
     String packageRootPath = '/package';
     manager.setRoots(<String>[projPath], <String>[], <String, String>{
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index a41e086..7037f60 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -321,9 +321,8 @@
 library lib_a;
 class A {}
 ''');
-    packageMapProvider.packageMap['pkgA'] = [
-      resourceProvider.getResource('/packages/pkgA')
-    ];
+    packageMapProvider.packageMap['pkgA'] =
+        [resourceProvider.getResource('/packages/pkgA')];
     addTestFile('''
 import 'package:pkgA/libA.dart';
 main(A a) {
@@ -647,6 +646,30 @@
     expect(filesHighlights[pkgFileA], isNotEmpty);
   }
 
+  test_afterAnalysis_packageFile_notUsed() async {
+    String pkgFile = '/packages/pkgA/lib/libA.dart';
+    resourceProvider.newFile(pkgFile, '''
+library lib_a;
+class A {}
+''');
+    packageMapProvider.packageMap = {
+      'pkgA': [(resourceProvider.newFolder('/packages/pkgA/lib'))]
+    };
+    //
+    addTestFile('// no "pkgA" reference');
+    createProject();
+    // wait for analysis, no results initially
+    await waitForTasksFinished();
+    expect(filesHighlights[pkgFile], isNull);
+    // make it a priority file, so make analyzable
+    server.setPriorityFiles('0', [pkgFile]);
+    // subscribe
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, pkgFile);
+    await server.onAnalysisComplete;
+    // there are results
+    expect(filesHighlights[pkgFile], isNotEmpty);
+  }
+
   test_afterAnalysis_sdkFile() async {
     String file = '/lib/core/core.dart';
     addTestFile('// no matter');
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index b594773..e727c6c 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -253,8 +253,13 @@
   List<CompletionSuggestion> suggestions = [];
   bool suggestionsDone = false;
 
-  String addTestFile(String content) {
+  String addTestFile(String content, {offset}) {
     completionOffset = content.indexOf('^');
+    if (offset != null) {
+      expect(completionOffset, -1, reason: 'cannot supply offset and ^');
+      completionOffset = offset;
+      return super.addTestFile(content);
+    }
     expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
     int nextOffset = content.indexOf('^', completionOffset + 1);
     expect(nextOffset, equals(-1), reason: 'too many ^');
@@ -436,6 +441,16 @@
     });
   }
 
+  test_offset_past_eof() {
+    addTestFile('main() { }', offset: 300);
+    return getSuggestions().then((_) {
+      expect(replacementOffset, equals(300));
+      expect(replacementLength, equals(0));
+      expect(suggestionsDone, true);
+      expect(suggestions.length, 0);
+    });
+  }
+
   test_overrides() {
     addFile('/libA.dart', 'class A {m() {}}');
     addTestFile('''
@@ -587,6 +602,11 @@
     return source.contents;
   }
 
+  @override
+  bool exists(Source source) {
+    return source != null && source.exists();
+  }
+
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
diff --git a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
index 1046157..7b5be4d 100644
--- a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
@@ -62,8 +62,8 @@
    * expected propagated type of the element.
    */
   checkHover(String target, int length, List<String> descriptionRegexps,
-      String kind, List<String> staticTypeRegexps, {bool isCore: false,
-      String docRegexp: null, bool isLiteral: false,
+      String kind, List<String> staticTypeRegexps, {bool isLocal: false,
+      bool isCore: false, String docRegexp: null, bool isLiteral: false,
       List<String> parameterRegexps: null, propagatedType: null}) {
     int offset = text.indexOf(target);
     return sendAnalysisGetHover(pathname, offset).then((result) {
@@ -74,7 +74,7 @@
       if (isCore) {
         expect(basename(info.containingLibraryPath), equals('core.dart'));
         expect(info.containingLibraryName, equals('dart.core'));
-      } else if (isLiteral) {
+      } else if (isLocal || isLiteral) {
         expect(info.containingLibraryPath, isNull);
         expect(info.containingLibraryName, isNull);
       } else {
@@ -141,52 +141,44 @@
     // request is made.  So wait for analysis to finish before testing anything.
     return analysisFinished.then((_) {
       List<Future> tests = [];
-      tests.add(checkHover('topLevelVar;', 11,
-          ['List', 'topLevelVar'], 'top level variable', ['List']));
-      tests.add(checkHover('func(', 4, [
-        'func',
-        'int',
-        'param'
-      ], 'function', ['int', 'void'], docRegexp: 'Documentation for func'));
+      tests.add(checkHover('topLevelVar;', 11, [
+        'List',
+        'topLevelVar'
+      ], 'top level variable', ['List']));
+      tests.add(checkHover(
+          'func(', 4, ['func', 'int', 'param'], 'function', ['int', 'void'],
+          docRegexp: 'Documentation for func'));
       tests.add(checkHover('int param', 3, ['int'], 'class', ['int'],
           isCore: true, docRegexp: '.*'));
       tests.add(checkHover('param)', 5, ['int', 'param'], 'parameter', ['int'],
-          docRegexp: 'Documentation for func'));
+          isLocal: true, docRegexp: 'Documentation for func'));
       tests.add(checkHover('num localVar', 3, ['num'], 'class', ['num'],
           isCore: true, docRegexp: '.*'));
-      tests.add(checkHover('localVar =', 8, [
-        'num',
-        'localVar'
-      ], 'local variable', ['num'], propagatedType: 'int'));
+      tests.add(checkHover(
+          'localVar =', 8, ['num', 'localVar'], 'local variable', ['num'],
+          isLocal: true, propagatedType: 'int'));
       tests.add(checkHover('topLevelVar.length;', 11, [
         'List',
         'topLevelVar'
       ], 'top level variable', ['List']));
-      tests.add(checkHover('length;', 6, [
-        'get',
-        'length',
-        'int'
-      ], 'getter', ['int'], isCore: true, docRegexp: '.*'));
-      tests.add(checkHover('length =', 6, [
-        'set',
-        'length',
-        'int'
-      ], 'setter', ['int'], isCore: true, docRegexp: '.*'));
+      tests.add(checkHover(
+          'length;', 6, ['get', 'length', 'int'], 'getter', ['int'],
+          isCore: true, docRegexp: '.*'));
+      tests.add(checkHover(
+          'length =', 6, ['set', 'length', 'int'], 'setter', ['int'],
+          isCore: true, docRegexp: '.*'));
       tests.add(checkHover('param;', 5, ['int', 'param'], 'parameter', ['int'],
-          docRegexp: 'Documentation for func', parameterRegexps: ['.*']));
+          isLocal: true,
+          docRegexp: 'Documentation for func',
+          parameterRegexps: ['.*']));
       tests.add(checkHover('add(', 3, ['List', 'add'], 'method', null,
           isCore: true, docRegexp: '.*'));
-      tests.add(checkHover('localVar)', 8, [
-        'num',
-        'localVar'
-      ], 'local variable', [
-        'num'
-      ], parameterRegexps: ['.*'], propagatedType: 'int'));
-      tests.add(checkHover('func(35', 4, [
-        'func',
-        'int',
-        'param'
-      ], 'function', null, docRegexp: 'Documentation for func'));
+      tests.add(checkHover(
+          'localVar)', 8, ['num', 'localVar'], 'local variable', ['num'],
+          isLocal: true, parameterRegexps: ['.*'], propagatedType: 'int'));
+      tests.add(checkHover(
+          'func(35', 4, ['func', 'int', 'param'], 'function', null,
+          docRegexp: 'Documentation for func'));
       tests.add(checkHover('35', 2, null, null, ['int'],
           isLiteral: true, parameterRegexps: ['int', 'param']));
       tests.add(checkNoHover('comment'));
diff --git a/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart b/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
index 3cdb189..d9c85c1 100644
--- a/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
+++ b/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
@@ -4,8 +4,7 @@
 
 library test.integration.completion.get.suggestions;
 
-import 'dart:async';
-
+import 'package:analysis_server/src/protocol.dart';
 import 'package:unittest/unittest.dart';
 
 import '../../reflective_tests.dart';
@@ -17,35 +16,102 @@
 
 @reflectiveTest
 class Test extends AbstractAnalysisServerIntegrationTest {
-  fail_test_getSuggestions_string_var() {
-    // See dartbug.com/20188
-    String pathname = sourcePath('test.dart');
-    String text = r'''
-var test = '';
-main() {
-  test.
-}
-''';
-    writeFile(pathname, text);
-    standardAnalysisSetup();
+  String path;
+  String content;
+  int completionOffset;
 
-    return analysisFinished.then((_) {
-      return sendCompletionGetSuggestions(
-          pathname, text.indexOf('test.') + 'test.'.length).then((result) {
-        // Since the feature doesn't work yet, just pause for a second to
-        // collect the output of the analysis server, and then stop the test.
-        // TODO(paulberry): finish writing the integration test once the feature
-        // it more complete.
-        return new Future.delayed(new Duration(seconds: 1), () {
-          fail('test not completed yet');
-        });
-      });
-    });
+  void setTestSource(String relPath, String content) {
+    path = sourcePath(relPath);
+    expect(completionOffset, isNull, reason: 'Call addTestUnit exactly once');
+    completionOffset = content.indexOf('^');
+    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
+    int nextOffset = content.indexOf('^', completionOffset + 1);
+    expect(nextOffset, equals(-1), reason: 'too many ^');
+    this.content = content.substring(0, completionOffset) +
+        content.substring(completionOffset + 1);
   }
 
-  test_placeholder() {
-    // The unit test framework freaks out if there are no tests, so this is a
-    // placeholder until we have a passing test.
-    // TODO(paulberry): remove this.
+  test_getSuggestions() async {
+    setTestSource('test.dart', r'''
+String test = '';
+main() {
+  test.^
+}
+''');
+    writeFile(path, content);
+    await standardAnalysisSetup();
+    await analysisFinished;
+    CompletionGetSuggestionsResult result =
+        await sendCompletionGetSuggestions(path, completionOffset);
+    String completionId = result.id;
+    CompletionResultsParams param = await onCompletionResults.firstWhere(
+        (CompletionResultsParams param) =>
+            param.id == completionId && param.isLast);
+    expect(param.replacementOffset, completionOffset);
+    expect(param.replacementLength, 0);
+    param.results.firstWhere(
+        (CompletionSuggestion suggestion) => suggestion.completion == 'length');
+  }
+
+  test_getSuggestions_onlyOverlay() async {
+    setTestSource('test.dart', r'''
+String test = '';
+main() {
+  test.^
+}
+''');
+    // Create an overlay but do not write the file to "disk"
+    //   writeFile(pathname, text);
+    await standardAnalysisSetup();
+    await sendAnalysisUpdateContent({path: new AddContentOverlay(content)});
+    await analysisFinished;
+    CompletionGetSuggestionsResult result =
+        await sendCompletionGetSuggestions(path, completionOffset);
+    String completionId = result.id;
+    CompletionResultsParams param = await onCompletionResults.firstWhere(
+        (CompletionResultsParams param) =>
+            param.id == completionId && param.isLast);
+    expect(param.replacementOffset, completionOffset);
+    expect(param.replacementLength, 0);
+    param.results.firstWhere(
+        (CompletionSuggestion suggestion) => suggestion.completion == 'length');
+  }
+
+  test_getSuggestions_onlyOverlay_noWait() async {
+    setTestSource('test.dart', r'''
+String test = '';
+main() {
+  test.^
+}
+''');
+    // Create an overlay but do not write the file to "disk"
+    //   writeFile(pathname, text);
+    // Don't wait for any results except the completion notifications
+    standardAnalysisSetup(subscribeStatus: false);
+    sendAnalysisUpdateContent({path: new AddContentOverlay(content)});
+    sendCompletionGetSuggestions(path, completionOffset);
+    CompletionResultsParams param = await onCompletionResults
+        .firstWhere((CompletionResultsParams param) => param.isLast);
+    expect(param.replacementOffset, completionOffset);
+    expect(param.replacementLength, 0);
+    param.results.firstWhere(
+        (CompletionSuggestion suggestion) => suggestion.completion == 'length');
+  }
+
+  test_getSuggestions_sourceMissing_noWait() {
+    path = sourcePath('does_not_exist.dart');
+    // Do not write the file to "disk"
+    //   writeFile(pathname, text);
+    // Don't wait for any results except the completion notifications
+    standardAnalysisSetup(subscribeStatus: false);
+    // Missing file and no overlay
+    //sendAnalysisUpdateContent({path: new AddContentOverlay(content)});
+    var errorToken = 'exception from server';
+    return sendCompletionGetSuggestions(path, 0).catchError((e) {
+      // Exception expected
+      return errorToken;
+    }).then((result) {
+      expect(result, same(errorToken));
+    });
   }
 }
diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart
index 1909ee9..83314f9 100644
--- a/pkg/analysis_server/test/integration/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/protocol_matchers.dart
@@ -1022,6 +1022,7 @@
  *   "enableAsync": optional bool
  *   "enableDeferredLoading": optional bool
  *   "enableEnums": optional bool
+ *   "enableNullAwareOperators": optional bool
  *   "generateDart2jsHints": optional bool
  *   "generateHints": optional bool
  *   "generateLints": optional bool
@@ -1032,6 +1033,7 @@
     "enableAsync": isBool,
     "enableDeferredLoading": isBool,
     "enableEnums": isBool,
+    "enableNullAwareOperators": isBool,
     "generateDart2jsHints": isBool,
     "generateHints": isBool,
     "generateLints": isBool
@@ -1821,6 +1823,7 @@
  *   CONTENT_MODIFIED
  *   FORMAT_INVALID_FILE
  *   GET_ERRORS_INVALID_FILE
+ *   INVALID_ANALYSIS_ROOT
  *   INVALID_EXECUTION_CONTEXT
  *   INVALID_OVERLAY_CHANGE
  *   INVALID_PARAMETER
@@ -1833,6 +1836,7 @@
  *   SORT_MEMBERS_PARSE_ERRORS
  *   UNANALYZED_PRIORITY_FILES
  *   UNKNOWN_REQUEST
+ *   UNKNOWN_SOURCE
  *   UNSUPPORTED_FEATURE
  * }
  */
@@ -1840,6 +1844,7 @@
   "CONTENT_MODIFIED",
   "FORMAT_INVALID_FILE",
   "GET_ERRORS_INVALID_FILE",
+  "INVALID_ANALYSIS_ROOT",
   "INVALID_EXECUTION_CONTEXT",
   "INVALID_OVERLAY_CHANGE",
   "INVALID_PARAMETER",
@@ -1852,6 +1857,7 @@
   "SORT_MEMBERS_PARSE_ERRORS",
   "UNANALYZED_PRIORITY_FILES",
   "UNKNOWN_REQUEST",
+  "UNKNOWN_SOURCE",
   "UNSUPPORTED_FEATURE"
 ]);
 
diff --git a/pkg/analysis_server/test/mock_sdk.dart b/pkg/analysis_server/test/mock_sdk.dart
index 920cb32..2cdebda 100644
--- a/pkg/analysis_server/test/mock_sdk.dart
+++ b/pkg/analysis_server/test/mock_sdk.dart
@@ -16,6 +16,7 @@
 library dart.core;
 
 import 'dart:async';
+import 'dart:_internal';
 
 class Object {
   bool operator ==(other) => identical(this, other);
@@ -51,6 +52,7 @@
   num operator +(num other);
   num operator -(num other);
   num operator *(num other);
+  num operator %(num other);
   num operator /(num other);
   int toInt();
   num abs();
@@ -98,6 +100,15 @@
 external bool identical(Object a, Object b);
 
 void print(Object object) {}
+
+class Uri {
+  static List<int> parseIPv6Address(String host, [int start = 0, int end]) {
+    int parseHex(int start, int end) {
+      return 0;
+    }
+    return null;
+  }
+}
 ''');
 
   static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary('dart:async',
@@ -143,6 +154,7 @@
 num min(num a, num b) => 0;
 num max(num a, num b) => 0;
 external double cos(num x);
+external num pow(num x, num exponent);
 external double sin(num x);
 external double sqrt(num x);
 class Random {
@@ -158,6 +170,12 @@
 class HtmlElement {}
 ''');
 
+  static const _MockSdkLibrary LIB_INTERNAL = const _MockSdkLibrary(
+      'dart:_internal', '/lib/internal/internal.dart', '''
+library dart._internal;
+external void printToConsole(String line);
+''');
+
   static const List<SdkLibrary> LIBRARIES = const [
     LIB_CORE,
     LIB_ASYNC,
@@ -165,6 +183,7 @@
     LIB_CONVERT,
     LIB_MATH,
     LIB_HTML,
+    LIB_INTERNAL,
   ];
 
   final resource.MemoryResourceProvider provider =
@@ -263,7 +282,8 @@
       "dart:async": "/lib/async/async.dart",
       "dart:collection": "/lib/collection/collection.dart",
       "dart:convert": "/lib/convert/convert.dart",
-      "dart:math": "/lib/math/math.dart"
+      "dart:math": "/lib/math/math.dart",
+      "dart:_internal": "/lib/internal/internal.dart",
     };
 
     String path = uriToPath[dartUri];
@@ -299,7 +319,7 @@
   bool get isImplementation => throw unimplemented;
 
   @override
-  bool get isInternal => throw unimplemented;
+  bool get isInternal => shortName.startsWith('dart:_');
 
   @override
   bool get isShared => throw unimplemented;
diff --git a/pkg/analysis_server/test/services/completion/arglist_computer_test.dart b/pkg/analysis_server/test/services/completion/arglist_computer_test.dart
deleted file mode 100644
index 67e3814..0000000
--- a/pkg/analysis_server/test/services/completion/arglist_computer_test.dart
+++ /dev/null
@@ -1,115 +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 test.services.completion.dart.arglist;
-
-import 'package:analysis_server/src/protocol.dart';
-import 'package:analysis_server/src/services/completion/arglist_computer.dart';
-import 'package:unittest/unittest.dart';
-
-import '../../reflective_tests.dart';
-import 'completion_test_util.dart';
-
-main() {
-  groupSep = ' | ';
-  runReflectiveTests(ArgListComputerTest);
-}
-
-@reflectiveTest
-class ArgListComputerTest extends AbstractCompletionTest {
-  @override
-  void setUpComputer() {
-    computer = new ArgListComputer();
-  }
-
-  test_ArgumentList_imported_function_0() {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addSource('/libA.dart', '''
-      library A;
-      bool hasLength(int expected) { }
-      expect() { }
-      void baz() { }''');
-    addTestSource('''
-      import '/libA.dart'
-      class B { }
-      String bar() => true;
-      void main() {expect(^)}''');
-    computeFast();
-    return computeFull((bool result) {
-      assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
-    });
-  }
-
-//  test_ArgumentList_imported_function_1() {
-//    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-//    addSource('/libA.dart', '''
-//      library A;
-//      bool hasLength(int expected) { }
-//      expect(String arg) { }
-//      void baz() { }''');
-//    addTestSource('''
-//      import '/libA.dart'
-//      class B { }
-//      String bar() => true;
-//      void main() {expect(^)}''');
-//    computeFast();
-//    return computeFull((bool result) {
-//      assertSuggestArgumentList(['arg'], ['String']);
-//    });
-//  }
-
-  test_ArgumentList_local_function_1() {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addSource('/libA.dart', '''
-      library A;
-      bool hasLength(int expected) { }
-      void baz() { }''');
-    addTestSource('''
-      import '/libA.dart'
-      expect(arg) { }
-      class B { }
-      String bar() => true;
-      void main() {expect(^)}''');
-    computeFast();
-    return computeFull((bool result) {
-      assertSuggestArgumentList(['arg'], ['dynamic']);
-    });
-  }
-
-  test_ArgumentList_local_method_0() {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addSource('/libA.dart', '''
-      library A;
-      bool hasLength(int expected) { }
-      void baz() { }''');
-    addTestSource('''
-      import '/libA.dart'
-      class B {
-        expect() { }
-        void foo() {expect(^)}}
-      String bar() => true;''');
-    computeFast();
-    return computeFull((bool result) {
-      assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
-    });
-  }
-
-  test_ArgumentList_local_method_2() {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addSource('/libA.dart', '''
-      library A;
-      bool hasLength(int expected) { }
-      void baz() { }''');
-    addTestSource('''
-      import '/libA.dart'
-      class B {
-        expect(arg, int blat) { }
-        void foo() {expect(^)}}
-      String bar() => true;''');
-    computeFast();
-    return computeFull((bool result) {
-      assertSuggestArgumentList(['arg', 'blat'], ['dynamic', 'int']);
-    });
-  }
-}
diff --git a/pkg/analysis_server/test/services/completion/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/arglist_contributor_test.dart
new file mode 100644
index 0000000..64979d6
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/arglist_contributor_test.dart
@@ -0,0 +1,455 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.services.completion.dart.arglist;
+
+import 'package:analysis_server/src/protocol.dart';
+import 'package:analysis_server/src/services/completion/arglist_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+import 'completion_test_util.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(ArgListContributorTest);
+}
+
+@reflectiveTest
+class ArgListContributorTest extends AbstractCompletionTest {
+  void assertNoOtherSuggestions(Iterable<CompletionSuggestion> expected) {
+    for (CompletionSuggestion suggestion in request.suggestions) {
+      if (!expected.contains(suggestion)) {
+        failedCompletion('did not expect completion: '
+            '${suggestion.completion}\n  $suggestion');
+      }
+    }
+  }
+
+  void assertSuggestArgumentList(
+      List<String> paramNames, List<String> paramTypes) {
+    CompletionSuggestionKind csKind = CompletionSuggestionKind.ARGUMENT_LIST;
+    CompletionSuggestion cs = getSuggest(csKind: csKind);
+    if (cs == null) {
+      failedCompletion('expected completion $csKind', request.suggestions);
+    }
+    assertSuggestArgumentList_params(
+        paramNames, paramTypes, cs.parameterNames, cs.parameterTypes);
+    expect(cs.relevance, DART_RELEVANCE_HIGH);
+    assertNoOtherSuggestions([cs]);
+  }
+
+  void assertSuggestArgumentList_params(List<String> expectedNames,
+      List<String> expectedTypes, List<String> actualNames,
+      List<String> actualTypes) {
+    if (actualNames != null &&
+        actualNames.length == expectedNames.length &&
+        actualTypes != null &&
+        actualTypes.length == expectedTypes.length) {
+      int index = 0;
+      while (index < expectedNames.length) {
+        if (actualNames[index] != expectedNames[index] ||
+            actualTypes[index] != expectedTypes[index]) {
+          break;
+        }
+        ++index;
+      }
+      if (index == expectedNames.length) {
+        return;
+      }
+    }
+    StringBuffer msg = new StringBuffer();
+    msg.writeln('Argument list not the same');
+    msg.writeln('  Expected names: $expectedNames');
+    msg.writeln('           found: $actualNames');
+    msg.writeln('  Expected types: $expectedTypes');
+    msg.writeln('           found: $actualTypes');
+    fail(msg.toString());
+  }
+
+  /**
+   * Assert that the specified suggestions are the only suggestions.
+   */
+  void assertSuggestArguments({List<String> namedArguments}) {
+    List<CompletionSuggestion> expected = new List<CompletionSuggestion>();
+    for (String name in namedArguments) {
+      expected.add(assertSuggest('$name: ',
+          csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
+          relevance: DART_RELEVANCE_PARAMETER));
+    }
+    assertNoOtherSuggestions(expected);
+  }
+
+  @override
+  void setUpContributor() {
+    contributor = new ArgListContributor();
+  }
+
+  test_ArgumentList_getter() {
+    addTestSource('class A {int get foo => 7; main() {foo(^)}');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_imported_function_0() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      expect() { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B { }
+      String bar() => true;
+      void main() {expect(a^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_imported_function_1() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      expect(String arg) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B { }
+      String bar() => true;
+      void main() {expect(^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArgumentList(['arg'], ['String']);
+    });
+  }
+
+  test_ArgumentList_imported_function_2() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      expect(String arg1, int arg2) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B { }
+      String bar() => true;
+      void main() {expect(^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArgumentList(['arg1', 'arg2'], ['String', 'int']);
+    });
+  }
+
+  test_ArgumentList_imported_function_3() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      expect(String arg1, int arg2, {bool arg3}) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B { }
+      String bar() => true;
+      void main() {expect(^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArgumentList(['arg1', 'arg2'], ['String', 'int']);
+    });
+  }
+
+  test_ArgumentList_imported_function_3a() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      expect(String arg1, int arg2, {bool arg3}) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B { }
+      String bar() => true;
+      void main() {expect('hello', ^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_imported_function_3b() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      expect(String arg1, int arg2, {bool arg3}) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B { }
+      String bar() => true;
+      void main() {expect('hello', ^x)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_imported_function_3c() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      expect(String arg1, int arg2, {bool arg3}) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B { }
+      String bar() => true;
+      void main() {expect('hello', x^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_imported_function_3d() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      expect(String arg1, int arg2, {bool arg3}) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B { }
+      String bar() => true;
+      void main() {expect('hello', x ^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_imported_function_named_param() {
+    //
+    addTestSource('main() { int.parse("16", ^);}');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArguments(namedArguments: ['radix', 'onError']);
+    });
+  }
+
+  test_ArgumentList_imported_function_named_param1() {
+    //
+    addTestSource('main() { int.parse("16", r^);}');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArguments(namedArguments: ['radix', 'onError']);
+    });
+  }
+
+  test_ArgumentList_imported_function_named_param2() {
+    //
+    addTestSource('main() { int.parse("16", radix: 7, ^);}');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArguments(namedArguments: ['onError']);
+    });
+  }
+
+  test_ArgumentList_imported_function_named_param2a() {
+    //
+    addTestSource('main() { int.parse("16", radix: ^);}');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_local_function_1() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      import '/libA.dart'
+      expect(arg) { }
+      class B { }
+      String bar() => true;
+      void main() {expect(^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArgumentList(['arg'], ['dynamic']);
+    });
+  }
+
+  test_ArgumentList_local_function_2() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      import '/libA.dart'
+      expect(arg1, int arg2) { }
+      class B { }
+      String bar() => true;
+      void main() {expect(^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArgumentList(['arg1', 'arg2'], ['dynamic', 'int']);
+    });
+  }
+
+  test_ArgumentList_local_function_3() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      import '/libA.dart'
+      expect(arg1, int arg2) { }
+      class B { }
+      String bar() => true;
+      void main() {expect(^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArgumentList(['arg1', 'arg2'], ['dynamic', 'int']);
+    });
+  }
+
+  test_ArgumentList_local_function_3a() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      import '/libA.dart'
+      expect(arg1, int arg2, {bool arg3}) { }
+      class B { }
+      String bar() => true;
+      void main() {expect('hello', ^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_local_function_3b() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      import '/libA.dart'
+      expect(arg1, int arg2, {bool arg3}) { }
+      class B { }
+      String bar() => true;
+      void main() {expect('hello', ^x)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_local_function_3c() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      import '/libA.dart'
+      expect(arg1, int arg2, {bool arg3}) { }
+      class B { }
+      String bar() => true;
+      void main() {expect('hello', x^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_local_function_3d() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      import '/libA.dart'
+      expect(arg1, int arg2, {bool arg3}) { }
+      class B { }
+      String bar() => true;
+      void main() {expect('hello', x ^)}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_local_function_named_param() {
+    //
+    addTestSource('''
+f(v,{int radix, int onError(String s)}){}
+main() { f("16", ^);}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArguments(namedArguments: ['radix', 'onError']);
+    });
+  }
+
+  test_ArgumentList_local_function_named_param1() {
+    //
+    addTestSource('''
+f(v,{int radix, int onError(String s)}){}
+main() { f("16", r^);}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArguments(namedArguments: ['radix', 'onError']);
+    });
+  }
+
+  test_ArgumentList_local_function_named_param2() {
+    //
+    addTestSource('''
+f(v,{int radix, int onError(String s)}){}
+main() { f("16", radix: 7, ^);}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArguments(namedArguments: ['onError']);
+    });
+  }
+
+  test_ArgumentList_local_function_named_param2a() {
+    //
+    addTestSource('''
+f(v,{int radix, int onError(String s)}){}
+main() { f("16", radix: ^);}''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_local_method_0() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B {
+        expect() { }
+        void foo() {expect(^)}}
+      String bar() => true;''');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_ArgumentList_local_method_2() {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addSource('/libA.dart', '''
+      library A;
+      bool hasLength(int expected) { }
+      void baz() { }''');
+    addTestSource('''
+      import '/libA.dart'
+      class B {
+        expect(arg, int blat) { }
+        void foo() {expect(^)}}
+      String bar() => true;''');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggestArgumentList(['arg', 'blat'], ['dynamic', 'int']);
+    });
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/combinator_computer_test.dart b/pkg/analysis_server/test/services/completion/combinator_contributor_test.dart
similarity index 94%
rename from pkg/analysis_server/test/services/completion/combinator_computer_test.dart
rename to pkg/analysis_server/test/services/completion/combinator_contributor_test.dart
index d924f81..01df6a0 100644
--- a/pkg/analysis_server/test/services/completion/combinator_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/combinator_contributor_test.dart
@@ -5,7 +5,7 @@
 library test.services.completion.dart.combinator;
 
 import 'package:analysis_server/src/protocol.dart';
-import 'package:analysis_server/src/services/completion/combinator_computer.dart';
+import 'package:analysis_server/src/services/completion/combinator_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
 import 'package:unittest/unittest.dart';
 
@@ -14,14 +14,14 @@
 
 main() {
   groupSep = ' | ';
-  runReflectiveTests(CombinatorComputerTest);
+  runReflectiveTests(CombinatorContributorTest);
 }
 
 @reflectiveTest
-class CombinatorComputerTest extends AbstractCompletionTest {
+class CombinatorContributorTest extends AbstractCompletionTest {
   @override
-  void setUpComputer() {
-    computer = new CombinatorComputer();
+  void setUpContributor() {
+    contributor = new CombinatorContributor();
   }
 
   test_Block_inherited_local() {
diff --git a/pkg/analysis_server/test/services/completion/completion_computer_test.dart b/pkg/analysis_server/test/services/completion/completion_computer_test.dart
index 37afa8f..50fee60 100644
--- a/pkg/analysis_server/test/services/completion/completion_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/completion_computer_test.dart
@@ -46,8 +46,8 @@
   Source source;
   CompletionPerformance perf;
   DartCompletionManager manager;
-  MockCompletionComputer computer1;
-  MockCompletionComputer computer2;
+  MockCompletionContributor contributor1;
+  MockCompletionContributor contributor2;
   CompletionSuggestion suggestion1;
   CompletionSuggestion suggestion2;
   bool _continuePerformingAnalysis = true;
@@ -78,25 +78,25 @@
   }
 
   test_compute_fastAndFull() {
-    computer1 = new MockCompletionComputer(suggestion1, null);
-    computer2 = new MockCompletionComputer(null, suggestion2);
-    manager.computers = [computer1, computer2];
+    contributor1 = new MockCompletionContributor(suggestion1, null);
+    contributor2 = new MockCompletionContributor(null, suggestion2);
+    manager.contributors = [contributor1, contributor2];
     int count = 0;
     bool done = false;
     CompletionRequest completionRequest = new CompletionRequest(0, perf);
     manager.results(completionRequest).listen((CompletionResult r) {
       switch (++count) {
         case 1:
-          computer1.assertCalls(context, source, 0, searchEngine);
-          computer2.assertCalls(context, source, 0, searchEngine);
+          contributor1.assertCalls(context, source, 0, searchEngine);
+          contributor2.assertCalls(context, source, 0, searchEngine);
           expect(r.last, isFalse);
           expect(r.suggestions, hasLength(1));
           expect(r.suggestions, contains(suggestion1));
           resolveLibrary();
           break;
         case 2:
-          computer1.assertFull(0);
-          computer2.assertFull(1);
+          contributor1.assertFull(0);
+          contributor2.assertFull(1);
           expect(r.last, isTrue);
           expect(r.suggestions, hasLength(2));
           expect(r.suggestions, contains(suggestion1));
@@ -115,17 +115,17 @@
   }
 
   test_compute_fastOnly() {
-    computer1 = new MockCompletionComputer(suggestion1, null);
-    computer2 = new MockCompletionComputer(suggestion2, null);
-    manager.computers = [computer1, computer2];
+    contributor1 = new MockCompletionContributor(suggestion1, null);
+    contributor2 = new MockCompletionContributor(suggestion2, null);
+    manager.contributors = [contributor1, contributor2];
     int count = 0;
     bool done = false;
     CompletionRequest completionRequest = new CompletionRequest(0, perf);
     manager.results(completionRequest).listen((CompletionResult r) {
       switch (++count) {
         case 1:
-          computer1.assertCalls(context, source, 0, searchEngine);
-          computer2.assertCalls(context, source, 0, searchEngine);
+          contributor1.assertCalls(context, source, 0, searchEngine);
+          contributor2.assertCalls(context, source, 0, searchEngine);
           expect(r.last, isTrue);
           expect(r.suggestions, hasLength(2));
           expect(r.suggestions, contains(suggestion1));
@@ -152,14 +152,14 @@
   }
 }
 
-class MockCompletionComputer extends DartCompletionComputer {
+class MockCompletionContributor extends DartCompletionContributor {
   final CompletionSuggestion fastSuggestion;
   final CompletionSuggestion fullSuggestion;
   int fastCount = 0;
   int fullCount = 0;
   DartCompletionRequest request;
 
-  MockCompletionComputer(this.fastSuggestion, this.fullSuggestion);
+  MockCompletionContributor(this.fastSuggestion, this.fullSuggestion);
 
   assertCalls(AnalysisContext context, Source source, int offset,
       SearchEngine searchEngine) {
diff --git a/pkg/analysis_server/test/services/completion/completion_target_test.dart b/pkg/analysis_server/test/services/completion/completion_target_test.dart
index 0bf95cf..e673466 100644
--- a/pkg/analysis_server/test/services/completion/completion_target_test.dart
+++ b/pkg/analysis_server/test/services/completion/completion_target_test.dart
@@ -138,6 +138,30 @@
     assertTarget('}', '{}');
   }
 
+  test_FormalParameter_partialType() {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName
+    addTestSource('foo(b.^ f) { }');
+    assertTarget('f', 'b.f');
+  }
+
+  test_FormalParameter_partialType2() {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName
+    addTestSource('foo(b.z^ f) { }');
+    assertTarget('z', 'b.z');
+  }
+
+  test_FormalParameter_partialType3() {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName
+    addTestSource('foo(b.^) { }');
+    assertTarget('', 'b.');
+  }
+
+  test_FormalParameterList() {
+    // Token  FormalParameterList  FunctionExpression
+    addTestSource('foo(^) { }');
+    assertTarget(')', '()');
+  }
+
   test_FunctionDeclaration_inLineComment() {
     // Comment  CompilationUnit
     addTestSource('''
diff --git a/pkg/analysis_server/test/services/completion/completion_test_util.dart b/pkg/analysis_server/test/services/completion/completion_test_util.dart
index 40d31a8..e2af4d8 100644
--- a/pkg/analysis_server/test/services/completion/completion_test_util.dart
+++ b/pkg/analysis_server/test/services/completion/completion_test_util.dart
@@ -11,10 +11,11 @@
 import 'package:analysis_server/src/protocol.dart' hide Element, ElementKind;
 import 'package:analysis_server/src/services/completion/common_usage_computer.dart';
 import 'package:analysis_server/src/services/completion/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/completion_target.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_cache.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/completion/imported_computer.dart';
-import 'package:analysis_server/src/services/completion/invocation_computer.dart';
+import 'package:analysis_server/src/services/completion/imported_reference_contributor.dart';
+import 'package:analysis_server/src/services/completion/prefixed_element_contributor.dart';
 import 'package:analysis_server/src/services/index/index.dart';
 import 'package:analysis_server/src/services/index/local_memory_index.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
@@ -35,7 +36,7 @@
 abstract class AbstractCompletionTest extends AbstractContextTest {
   Index index;
   SearchEngineImpl searchEngine;
-  DartCompletionComputer computer;
+  DartCompletionContributor contributor;
   String testFile = '/completionTest.dart';
   Source testSource;
   CompilationUnit testUnit;
@@ -130,46 +131,6 @@
     return cs;
   }
 
-  void assertSuggestArgumentList(
-      List<String> paramNames, List<String> paramTypes) {
-    CompletionSuggestionKind csKind = CompletionSuggestionKind.ARGUMENT_LIST;
-    CompletionSuggestion cs = getSuggest(csKind: csKind);
-    if (cs == null) {
-      failedCompletion('expected completion $csKind', request.suggestions);
-    }
-    assertSuggestArgumentList_params(
-        paramNames, paramTypes, cs.parameterNames, cs.parameterTypes);
-    expect(cs.relevance, DART_RELEVANCE_HIGH);
-  }
-
-  void assertSuggestArgumentList_params(List<String> expectedNames,
-      List<String> expectedTypes, List<String> actualNames,
-      List<String> actualTypes) {
-    if (actualNames != null &&
-        actualNames.length == expectedNames.length &&
-        actualTypes != null &&
-        actualTypes.length == expectedTypes.length) {
-      int index = 0;
-      while (index < expectedNames.length) {
-        if (actualNames[index] != expectedNames[index] ||
-            actualTypes[index] != expectedTypes[index]) {
-          break;
-        }
-        ++index;
-      }
-      if (index == expectedNames.length) {
-        return;
-      }
-    }
-    StringBuffer msg = new StringBuffer();
-    msg.writeln('Argument list not the same');
-    msg.writeln('  Expected names: $expectedNames');
-    msg.writeln('           found: $actualNames');
-    msg.writeln('  Expected types: $expectedTypes');
-    msg.writeln('           found: $actualTypes');
-    fail(msg.toString());
-  }
-
   CompletionSuggestion assertSuggestClass(String name,
       {int relevance: DART_RELEVANCE_DEFAULT,
       CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
@@ -320,7 +281,7 @@
   CompletionSuggestion assertSuggestLibraryPrefix(String prefix,
       [int relevance = DART_RELEVANCE_DEFAULT,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION]) {
-    // Library prefix should only be suggested by ImportedComputer
+    // Library prefix should only be suggested by ImportedReferenceContributor
     return assertNotSuggested(prefix);
   }
 
@@ -349,7 +310,7 @@
   CompletionSuggestion assertSuggestNamedConstructor(
       String name, String returnType, [int relevance = DART_RELEVANCE_DEFAULT,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION]) {
-    if (computer is InvocationComputer) {
+    if (contributor is PrefixedElementContributor) {
       CompletionSuggestion cs =
           assertSuggest(name, csKind: kind, relevance: relevance);
       protocol.Element element = cs.element;
@@ -412,7 +373,7 @@
 
   void assertSuggestTopLevelVarGetterSetter(String name, String returnType,
       [int relevance = DART_RELEVANCE_DEFAULT]) {
-    if (computer is ImportedComputer) {
+    if (contributor is ImportedReferenceContributor) {
       assertSuggestGetter(name, returnType);
       assertSuggestSetter(name);
     } else {
@@ -423,7 +384,7 @@
   bool computeFast() {
     _computeFastCalled = true;
     _completionManager = new DartCompletionManager(context, searchEngine,
-        testSource, cache, [computer], new CommonUsageComputer({}));
+        testSource, cache, [contributor], new CommonUsageComputer({}));
     var result = _completionManager.computeFast(request);
     expect(request.replacementOffset, isNotNull);
     expect(request.replacementLength, isNotNull);
@@ -435,7 +396,7 @@
       expect(computeFast(), isFalse);
     }
     resolve(fullAnalysis);
-    return computer.computeFull(request).then(assertFunction);
+    return contributor.computeFull(request).then(assertFunction);
   }
 
   void failedCompletion(String message,
@@ -519,8 +480,8 @@
               context.getResolvedCompilationUnit(testSource, library);
           if (unit != null) {
             request.unit = unit;
-            request.node =
-                new NodeLocator.con1(completionOffset).searchWithin(unit);
+            request.target =
+                new CompletionTarget.forOffset(unit, completionOffset);
             resolved = true;
             if (!fullAnalysis) {
               break;
@@ -541,21 +502,21 @@
     super.setUp();
     index = createLocalMemoryIndex();
     searchEngine = new SearchEngineImpl(index);
-    setUpComputer();
+    setUpContributor();
   }
 
-  void setUpComputer();
+  void setUpContributor();
 }
 
 /**
- * Common tests for `ImportedTypeComputerTest`, `InvocationComputerTest`,
- * and `LocalComputerTest`.
+ * Common tests for `ImportedTypeContributorTest`, `InvocationContributorTest`,
+ * and `LocalContributorTest`.
  */
 abstract class AbstractSelectorSuggestionTest extends AbstractCompletionTest {
 
   /**
-   * Assert that the ImportedComputer uses cached results to produce identical
-   * suggestions to the original set of suggestions.
+   * Assert that the ImportedReferenceContributor uses cached results
+   * to produce identical suggestions to the original set of suggestions.
    */
   void assertCachedCompute(_) {
     // Subclasses override
@@ -564,7 +525,7 @@
   CompletionSuggestion assertSuggestImportedClass(String name,
       {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
       int relevance: DART_RELEVANCE_DEFAULT}) {
-    if (computer is ImportedComputer) {
+    if (contributor is ImportedReferenceContributor) {
       return assertSuggestClass(name, relevance: relevance, kind: kind);
     } else {
       return assertNotSuggested(name);
@@ -592,7 +553,7 @@
       String name, String returnType, [bool isDeprecated = false,
       int relevance = DART_RELEVANCE_DEFAULT,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION]) {
-    if (computer is ImportedComputer) {
+    if (contributor is ImportedReferenceContributor) {
       return assertSuggestFunctionTypeAlias(
           name, returnType, isDeprecated, relevance, kind);
     } else {
@@ -620,7 +581,7 @@
   CompletionSuggestion assertSuggestImportedTopLevelVar(
       String name, String returnType, [int relevance = DART_RELEVANCE_DEFAULT,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION]) {
-    if (computer is ImportedComputer) {
+    if (contributor is ImportedReferenceContributor) {
       return assertSuggestTopLevelVar(name, returnType, relevance, kind);
     } else {
       return assertNotSuggested(name);
@@ -629,7 +590,7 @@
 
   CompletionSuggestion assertSuggestInvocationClass(String name,
       [int relevance = DART_RELEVANCE_DEFAULT]) {
-    if (computer is InvocationComputer) {
+    if (contributor is PrefixedElementContributor) {
       return assertSuggestClass(name, relevance: relevance);
     } else {
       return assertNotSuggested(name);
@@ -644,7 +605,7 @@
   CompletionSuggestion assertSuggestInvocationGetter(
       String name, String returnType,
       {int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false}) {
-    if (computer is InvocationComputer) {
+    if (contributor is PrefixedElementContributor) {
       return assertSuggestGetter(name, returnType,
           relevance: relevance, isDeprecated: isDeprecated);
     } else {
@@ -655,7 +616,7 @@
   CompletionSuggestion assertSuggestInvocationMethod(
       String name, String declaringType, String returnType,
       [int relevance = DART_RELEVANCE_DEFAULT]) {
-    if (computer is InvocationComputer) {
+    if (contributor is PrefixedElementContributor) {
       return assertSuggestMethod(name, declaringType, returnType,
           relevance: relevance);
     } else {
@@ -665,7 +626,7 @@
 
   CompletionSuggestion assertSuggestInvocationSetter(String name,
       [int relevance = DART_RELEVANCE_DEFAULT]) {
-    if (computer is InvocationComputer) {
+    if (contributor is PrefixedElementContributor) {
       return assertSuggestSetter(name);
     } else {
       return assertNotSuggested(name);
@@ -675,7 +636,7 @@
   CompletionSuggestion assertSuggestInvocationTopLevelVar(
       String name, String returnType,
       [int relevance = DART_RELEVANCE_DEFAULT]) {
-    if (computer is InvocationComputer) {
+    if (contributor is PrefixedElementContributor) {
       return assertSuggestTopLevelVar(name, returnType, relevance);
     } else {
       return assertNotSuggested(name);
@@ -1210,7 +1171,7 @@
       export "dart:math" hide max;
       class A {int x;}
       @deprecated D1() {int x;}
-      class _B { }''');
+      class _B {boo() { partBoo() {}} }''');
     addSource('/testCD.dart', '''
       String T1;
       var _T2;
@@ -1232,7 +1193,7 @@
       int T5;
       var _T6;
       String get T7 => 'hello';
-      set T8(int value) { }
+      set T8(int value) { partT8() {} }
       Z D2() {int x;}
       class X {
         int get clog => 8;
@@ -1259,10 +1220,12 @@
       // Don't suggest locals out of scope
       assertNotSuggested('r');
       assertNotSuggested('x');
+      assertNotSuggested('partT8');
 
       assertSuggestImportedClass('A');
       assertNotSuggested('_B');
       assertSuggestImportedClass('C');
+      assertNotSuggested('partBoo');
       // hidden element suggested as low relevance
       // but imported results are partially filtered
       //assertSuggestImportedClass('D', COMPLETION_RELEVANCE_LOW);
@@ -1282,7 +1245,7 @@
       //    'num',
       //    false,
       //    COMPLETION_RELEVANCE_LOW);
-      if (computer is ImportedComputer) {
+      if (contributor is ImportedReferenceContributor) {
         // TODO(danrubel) should be top level var suggestion
         assertSuggestGetter('T1', 'String');
       }
@@ -1298,6 +1261,9 @@
       assertSuggestLocalSetter('blog');
       // TODO (danrubel) suggest HtmlElement as low relevance
       assertNotSuggested('HtmlElement');
+      assertSuggestImportedClass('Uri');
+      assertNotSuggested('parseIPv6Address');
+      assertNotSuggested('parseHex');
     });
   }
 
@@ -1385,7 +1351,7 @@
     // Block  BlockFunctionBody  MethodDeclaration  ClassDeclaration
     addSource('/testB.dart', '''
       lib B;
-      class F { var f1; f2() { } get f3 => 0; set f4(fx) { } }
+      class F { var f1; f2() { } get f3 => 0; set f4(fx) { } var _pf; }
       class E extends F { var e1; e2() { } }
       class I { int i1; i2() { } }
       class M { var m1; int m2() { } }''');
@@ -1438,6 +1404,58 @@
     });
   }
 
+  test_Block_local_function() {
+    addSource('/testAB.dart', '''
+      export "dart:math" hide max;
+      class A {int x;}
+      @deprecated D1() {int x;}
+      class _B {boo() { partBoo() {}} }''');
+    addSource('/testCD.dart', '''
+      String T1;
+      var _T2;
+      class C { }
+      class D { }''');
+    addSource('/testEEF.dart', '''
+      class EE { }
+      class F { }''');
+    addSource('/testG.dart', 'class G { }');
+    addSource('/testH.dart', '''
+      class H { }
+      int T3;
+      var _T4;'''); // not imported
+    addTestSource('''
+      import "/testAB.dart";
+      import "/testCD.dart" hide D;
+      import "/testEEF.dart" show EE;
+      import "/testG.dart" as g;
+      int T5;
+      var _T6;
+      String get T7 => 'hello';
+      set T8(int value) { partT8() {} }
+      Z D2() {int x;}
+      class X {
+        int get clog => 8;
+        set blog(value) { }
+        a() {
+          var f;
+          localF(int arg1) { }
+          {var x;}
+          p^ var r;
+        }
+        void b() { }}
+      class Z { }''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset - 1);
+      expect(request.replacementLength, 1);
+
+      assertNotSuggested('partT8');
+      assertNotSuggested('partBoo');
+      assertNotSuggested('parseIPv6Address');
+      assertNotSuggested('parseHex');
+    });
+  }
+
   test_Block_unimported() {
     addSource('/testAB.dart', 'class Foo { }');
     addTestSource('class C {foo(){F^}}');
@@ -1545,6 +1563,33 @@
     });
   }
 
+  test_CatchClause_onType() {
+    // TypeName  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} on ^ {}}}');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
+      assertSuggestLocalClass('A');
+      assertSuggestImportedClass('Object');
+      assertNotSuggested('a');
+      assertNotSuggested('x');
+    });
+  }
+
+  test_CatchClause_onType_noBrackets() {
+    // TypeName  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} on ^}}');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
+      assertSuggestLocalClass('A');
+      assertSuggestImportedClass('Object');
+      assertNotSuggested('x');
+    });
+  }
+
   test_CatchClause_typed() {
     // Block  CatchClause  TryStatement
     addTestSource('class A {a() {try{var x;} on E catch (e) {^}}}');
@@ -2060,11 +2105,11 @@
     return computeFull((bool result) {
       expect(request.replacementOffset, completionOffset);
       expect(request.replacementLength, 0);
-      assertSuggestLocalFunction('foo', null);
-      assertSuggestLocalMethod('a', 'A', null);
+      assertNotSuggested('foo');
+      assertNotSuggested('a');
       assertSuggestLocalClass('A');
       assertSuggestImportedClass('String');
-      assertSuggestImportedFunction('identical', 'bool');
+      assertNotSuggested('identical');
       assertNotSuggested('bar');
     });
   }
@@ -2432,7 +2477,7 @@
       expect(request.replacementLength, 0);
       assertNotSuggested('Object');
       // TODO(danrubel) should return top level var rather than getter
-      if (computer is ImportedComputer) {
+      if (contributor is ImportedReferenceContributor) {
         //assertSuggestImportedTopLevelVar('T1', 'int');
         assertSuggestGetter('T1', 'int');
       }
@@ -2467,7 +2512,7 @@
       expect(request.replacementLength, 0);
       assertSuggestImportedClass('Object');
       // TODO(danrubel) should return top level var rather than getter
-      if (computer is ImportedComputer) {
+      if (contributor is ImportedReferenceContributor) {
         //assertSuggestImportedTopLevelVar('T1', 'int');
         assertSuggestGetter('T1', 'int');
       }
@@ -2624,7 +2669,7 @@
       assertSuggestImportedFunction('nowIsIt', null);
       assertNotSuggested('T1');
       // TODO (danrubel) this really should be TopLevelVar not getter/setter
-      if (computer is ImportedComputer) {
+      if (contributor is ImportedReferenceContributor) {
         assertSuggestGetter('newT1', 'int');
       }
       assertNotSuggested('z');
@@ -2682,7 +2727,7 @@
       expect(request.replacementLength, 0);
       assertSuggestImportedClass('Object');
       // TODO(danrubel) Should be top level variable
-      if (computer is ImportedComputer) {
+      if (contributor is ImportedReferenceContributor) {
         assertSuggestGetter('T1', 'int');
         // assertSuggestImportedTopLevelVar('T1', 'int');
       }
@@ -2715,7 +2760,7 @@
       expect(request.replacementOffset, completionOffset - 1);
       expect(request.replacementLength, 1);
       // TODO(danrubel) Should be top level variable
-      if (computer is ImportedComputer) {
+      if (contributor is ImportedReferenceContributor) {
         assertSuggestGetter('T1', 'int');
         // assertSuggestImportedTopLevelVar('T1', 'int');
       }
@@ -2742,7 +2787,7 @@
       expect(request.replacementOffset, completionOffset - 1);
       expect(request.replacementLength, 1);
       // TODO(danrubel) Should be top level variable
-      if (computer is ImportedComputer) {
+      if (contributor is ImportedReferenceContributor) {
         assertSuggestGetter('T1', 'int');
         // assertSuggestImportedTopLevelVar('T1', 'int');
       }
@@ -3238,6 +3283,60 @@
     });
   }
 
+  test_PrefixedIdentifier_library_typesOnly() {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName
+    addSource('/testB.dart', '''
+      lib B;
+      var T1;
+      class X { }
+      class Y { }''');
+    addTestSource('''
+      import "/testB.dart" as b;
+      var T2;
+      class A { }
+      foo(b.^ f) {}''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
+      assertSuggestInvocationClass('X');
+      assertSuggestInvocationClass('Y');
+      assertNotSuggested('T1');
+      assertNotSuggested('T2');
+      assertNotSuggested('Object');
+      assertNotSuggested('b');
+      assertNotSuggested('A');
+      assertNotSuggested('==');
+    });
+  }
+
+  test_PrefixedIdentifier_library_typesOnly2() {
+    // SimpleIdentifier  PrefixedIdentifier  TypeName
+    addSource('/testB.dart', '''
+      lib B;
+      var T1;
+      class X { }
+      class Y { }''');
+    addTestSource('''
+      import "/testB.dart" as b;
+      var T2;
+      class A { }
+      foo(b.^) {}''');
+    computeFast();
+    return computeFull((bool result) {
+      expect(request.replacementOffset, completionOffset);
+      expect(request.replacementLength, 0);
+      assertSuggestInvocationClass('X');
+      assertSuggestInvocationClass('Y');
+      assertNotSuggested('T1');
+      assertNotSuggested('T2');
+      assertNotSuggested('Object');
+      assertNotSuggested('b');
+      assertNotSuggested('A');
+      assertNotSuggested('==');
+    });
+  }
+
   test_PrefixedIdentifier_parameter() {
     // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
     addSource('/testB.dart', '''
@@ -3416,6 +3515,26 @@
     });
   }
 
+  test_PropertyAccess_noTarget() {
+    // SimpleIdentifier  PropertyAccess  ExpressionStatement
+    addSource('/testAB.dart', 'class Foo { }');
+    addTestSource('class C {foo(){.^}}');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
+  test_PropertyAccess_noTarget2() {
+    // SimpleIdentifier  PropertyAccess  ExpressionStatement
+    addSource('/testAB.dart', 'class Foo { }');
+    addTestSource('main() {.^}');
+    computeFast();
+    return computeFull((bool result) {
+      assertNoSuggestions();
+    });
+  }
+
   test_PropertyAccess_selector() {
     // SimpleIdentifier  PropertyAccess  ExpressionStatement  Block
     addTestSource('class A {a() {"hello".length.^}}');
diff --git a/pkg/analysis_server/test/services/completion/imported_computer_test.dart b/pkg/analysis_server/test/services/completion/imported_reference_contributor_test.dart
similarity index 94%
rename from pkg/analysis_server/test/services/completion/imported_computer_test.dart
rename to pkg/analysis_server/test/services/completion/imported_reference_contributor_test.dart
index fd323e2..7551979 100644
--- a/pkg/analysis_server/test/services/completion/imported_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/imported_reference_contributor_test.dart
@@ -10,7 +10,7 @@
 import 'package:analysis_server/src/services/completion/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_cache.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/completion/imported_computer.dart';
+import 'package:analysis_server/src/services/completion/imported_reference_contributor.dart';
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -23,11 +23,11 @@
 
 main() {
   groupSep = ' | ';
-  runReflectiveTests(ImportedComputerTest);
+  runReflectiveTests(ImportedReferenceContributorTest);
 }
 
 @reflectiveTest
-class ImportedComputerTest extends AbstractSelectorSuggestionTest {
+class ImportedReferenceContributorTest extends AbstractSelectorSuggestionTest {
   void assertCached(String completion) {
     DartCompletionCache cache = request.cache;
     if (!isCached(cache.importedTypeSuggestions, completion) &&
@@ -39,12 +39,12 @@
   }
 
   /**
-   * Assert that the ImportedComputer uses cached results to produce identical
-   * suggestions to the original set of suggestions.
+   * Assert that the ImportedReferenceContributor uses cached results
+   * to produce identical suggestions to the original set of suggestions.
    */
   @override
   assertCachedCompute(_) {
-    if (!(computer as ImportedComputer).shouldWaitForLowPrioritySuggestions) {
+    if (!(contributor as ImportedReferenceContributor).shouldWaitForLowPrioritySuggestions) {
       return null;
     }
     expect(request.unit.element, isNotNull);
@@ -58,7 +58,7 @@
     /*
      * Calculate a new completion at the same location
      */
-    setUpComputer();
+    setUpContributor();
     int replacementOffset = request.replacementOffset;
     int replacementLength = request.replacementLength;
     request = new DartCompletionRequest(context, searchEngine, testSource,
@@ -98,7 +98,7 @@
       // Results from cache might need to be adjusted
       // if target is a function argument in an argument list
       resolve(false);
-      return computer.computeFull(request).then((bool result) {
+      return contributor.computeFull(request).then((bool result) {
         expect(result, isTrue);
         expect(request.unit.element, isNotNull);
         assertResultsFromCache(oldSuggestions);
@@ -174,8 +174,9 @@
       suggestions.any((CompletionSuggestion s) => s.completion == completion);
 
   @override
-  void setUpComputer() {
-    computer = new ImportedComputer(shouldWaitForLowPrioritySuggestions: true);
+  void setUpContributor() {
+    contributor = new ImportedReferenceContributor(
+        shouldWaitForLowPrioritySuggestions: true);
   }
 
   @override
@@ -221,6 +222,18 @@
       assertNotCached('e1');
       assertNotCached('i2');
       assertNotCached('m1');
+      assertNotCached('_pf');
+    });
+  }
+
+  test_internal_sdk_libs() {
+    addTestSource('main() {p^}');
+    computeFast();
+    return computeFull((bool result) {
+      assertSuggest('print');
+      assertSuggest('pow', relevance: DART_RELEVANCE_LOW);
+      // Do not suggest completions from internal SDK library
+      assertNotSuggested('printToConsole');
     });
   }
 
@@ -254,11 +267,12 @@
       Z D2() {int x;}
       class X {a() {var f; {var x;} ^ var r;} void b() { }}
       class Z { }''');
-    (computer as ImportedComputer).shouldWaitForLowPrioritySuggestions = false;
+    ImportedReferenceContributor contributor = this.contributor;
+    contributor.shouldWaitForLowPrioritySuggestions = false;
     computeFast();
     return computeFull((bool result) {
       assertSuggestImportedClass('C');
-      // Assert computer does not wait for or include low priority results
+      // Assert contributor does not wait for or include low priority results
       // from non-imported libraries unless instructed to do so.
       assertNotSuggested('H');
     });
@@ -657,7 +671,7 @@
     computeFast();
     return computeFull((bool result) {
       assertSuggestImportedClass('ClassInLocalContext');
-      // Assert computer does not include results from 2nd context.
+      // Assert contributor does not include results from 2nd context.
       assertNotSuggested('ClassFromAnotherContext');
     });
   }
diff --git a/pkg/analysis_server/test/services/completion/keyword_computer_test.dart b/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
similarity index 60%
rename from pkg/analysis_server/test/services/completion/keyword_computer_test.dart
rename to pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
index e044d9f..a7d881a 100644
--- a/pkg/analysis_server/test/services/completion/keyword_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/keyword_contributor_test.dart
@@ -6,7 +6,7 @@
 
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/completion/keyword_computer.dart';
+import 'package:analysis_server/src/services/completion/keyword_contributor.dart';
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:unittest/unittest.dart';
 
@@ -15,11 +15,65 @@
 
 main() {
   groupSep = ' | ';
-  runReflectiveTests(KeywordComputerTest);
+  runReflectiveTests(KeywordContributorTest);
 }
 
 @reflectiveTest
-class KeywordComputerTest extends AbstractCompletionTest {
+class KeywordContributorTest extends AbstractCompletionTest {
+  static const List<Keyword> CLASS_BODY_KEYWORDS = const [
+    Keyword.CONST,
+    Keyword.DYNAMIC,
+    Keyword.FACTORY,
+    Keyword.FINAL,
+    Keyword.GET,
+    Keyword.OPERATOR,
+    Keyword.SET,
+    Keyword.STATIC,
+    Keyword.VAR,
+    Keyword.VOID
+  ];
+
+  static const List<Keyword> DECLARATION_KEYWORDS = const [
+    Keyword.ABSTRACT,
+    Keyword.CLASS,
+    Keyword.CONST,
+    Keyword.DYNAMIC,
+    Keyword.FINAL,
+    Keyword.TYPEDEF,
+    Keyword.VAR,
+    Keyword.VOID
+  ];
+
+  static const List<Keyword> DIRECTIVE_AND_DECLARATION_KEYWORDS = const [
+    Keyword.ABSTRACT,
+    Keyword.CLASS,
+    Keyword.CONST,
+    Keyword.DYNAMIC,
+    Keyword.EXPORT,
+    Keyword.FINAL,
+    Keyword.IMPORT,
+    Keyword.PART,
+    Keyword.TYPEDEF,
+    Keyword.VAR,
+    Keyword.VOID
+  ];
+
+  static const List<Keyword> DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS =
+      const [
+    Keyword.ABSTRACT,
+    Keyword.CLASS,
+    Keyword.CONST,
+    Keyword.DYNAMIC,
+    Keyword.EXPORT,
+    Keyword.FINAL,
+    Keyword.IMPORT,
+    Keyword.LIBRARY,
+    Keyword.PART,
+    Keyword.TYPEDEF,
+    Keyword.VAR,
+    Keyword.VOID
+  ];
+
   static const List<Keyword> IN_BLOCK_IN_CLASS = const [
     Keyword.ASSERT,
     Keyword.CASE,
@@ -63,7 +117,7 @@
   void assertSuggestKeywords(Iterable<Keyword> expectedKeywords,
       [int relevance = DART_RELEVANCE_KEYWORD]) {
     Set<Keyword> actualKeywords = new Set<Keyword>();
-    request.suggestions.forEach((CompletionSuggestion s) {
+    for (CompletionSuggestion s in request.suggestions) {
       if (s.kind == CompletionSuggestionKind.KEYWORD) {
         Keyword k = Keyword.keywords[s.completion];
         if (k == null) {
@@ -73,13 +127,8 @@
             fail('Duplicate keyword suggested: ${s.completion}');
           }
         }
-        expect(s.relevance, equals(relevance), reason: k.toString());
-        expect(s.selectionOffset, equals(s.completion.length));
-        expect(s.selectionLength, equals(0));
-        expect(s.isDeprecated, equals(false));
-        expect(s.isPotential, equals(false));
       }
-    });
+    }
     if (expectedKeywords.any((k) => k is String)) {
       StringBuffer msg = new StringBuffer();
       msg.writeln('Expected set should be:');
@@ -97,69 +146,47 @@
       _appendKeywords(msg, actualKeywords);
       fail(msg.toString());
     }
+    for (CompletionSuggestion s in request.suggestions) {
+      if (s.kind == CompletionSuggestionKind.KEYWORD) {
+        Keyword k = Keyword.keywords[s.completion];
+        expect(s.relevance, equals(relevance), reason: k.toString());
+        expect(s.selectionOffset, equals(s.completion.length));
+        expect(s.selectionLength, equals(0));
+        expect(s.isDeprecated, equals(false));
+        expect(s.isPotential, equals(false));
+      }
+    }
   }
 
   @override
-  void setUpComputer() {
-    computer = new KeywordComputer();
+  void setUpContributor() {
+    contributor = new KeywordContributor();
   }
 
   test_after_class() {
     addTestSource('class A {} ^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.FINAL,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(DECLARATION_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   test_after_class2() {
     addTestSource('class A {} c^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.FINAL,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(DECLARATION_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   test_after_import() {
-    addTestSource('import foo; ^');
+    addTestSource('import "foo"; ^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.EXPORT,
-      Keyword.FINAL,
-      Keyword.IMPORT,
-      Keyword.PART,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(
+        DIRECTIVE_AND_DECLARATION_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   test_after_import2() {
-    addTestSource('import foo; c^');
+    addTestSource('import "foo"; c^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.EXPORT,
-      Keyword.FINAL,
-      Keyword.IMPORT,
-      Keyword.PART,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(
+        DIRECTIVE_AND_DECLARATION_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   test_before_import() {
@@ -174,26 +201,36 @@
   }
 
   test_class() {
-    addTestSource('class A ^');
-    expect(computeFast(), isTrue);
-    assertSuggestKeywords(
-        [Keyword.EXTENDS, Keyword.IMPLEMENTS], DART_RELEVANCE_HIGH);
-  }
-
-  test_class2() {
-    addTestSource('class A e^');
-    expect(computeFast(), isTrue);
-    assertSuggestKeywords(
-        [Keyword.EXTENDS, Keyword.IMPLEMENTS], DART_RELEVANCE_HIGH);
-  }
-
-  test_class3() {
     addTestSource('class A e^ { }');
     expect(computeFast(), isTrue);
     assertSuggestKeywords(
         [Keyword.EXTENDS, Keyword.IMPLEMENTS], DART_RELEVANCE_HIGH);
   }
 
+  test_class_body() {
+    addTestSource('class A {^}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(CLASS_BODY_KEYWORDS);
+  }
+
+  test_class_body_beginning() {
+    addTestSource('class A {^ var foo;}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(CLASS_BODY_KEYWORDS);
+  }
+
+  test_class_body_between() {
+    addTestSource('class A {var bar; ^ var foo;}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(CLASS_BODY_KEYWORDS);
+  }
+
+  test_class_body_end() {
+    addTestSource('class A {var foo; ^}');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(CLASS_BODY_KEYWORDS);
+  }
+
   test_class_extends() {
     addTestSource('class A extends foo ^');
     expect(computeFast(), isTrue);
@@ -255,6 +292,27 @@
     assertSuggestKeywords([]);
   }
 
+  test_class_noBody() {
+    addTestSource('class A ^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [Keyword.EXTENDS, Keyword.IMPLEMENTS], DART_RELEVANCE_HIGH);
+  }
+
+  test_class_noBody2() {
+    addTestSource('class A e^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [Keyword.EXTENDS, Keyword.IMPLEMENTS], DART_RELEVANCE_HIGH);
+  }
+
+  test_class_noBody3() {
+    addTestSource('class A e^ String foo;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords(
+        [Keyword.EXTENDS, Keyword.IMPLEMENTS], DART_RELEVANCE_HIGH);
+  }
+
   test_class_with() {
     addTestSource('class A extends foo with bar ^');
     expect(computeFast(), isTrue);
@@ -282,18 +340,8 @@
   test_empty() {
     addTestSource('^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.EXPORT,
-      Keyword.FINAL,
-      Keyword.IMPORT,
-      Keyword.LIBRARY,
-      Keyword.PART,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(
+        DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   test_function_body_inClass_constructorInitializer() {
@@ -356,37 +404,101 @@
     assertSuggestKeywords(IN_BLOCK_NOT_IN_CLASS);
   }
 
-  test_in_class() {
-    addTestSource('class A {^}');
+  test_import() {
+    addTestSource('import "foo" deferred as foo ^;');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.CONST,
-      Keyword.DYNAMIC,
-      Keyword.FACTORY,
-      Keyword.FINAL,
-      Keyword.GET,
-      Keyword.OPERATOR,
-      Keyword.SET,
-      Keyword.STATIC,
-      Keyword.VAR,
-      Keyword.VOID
-    ]);
+    assertSuggestKeywords([], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_as() {
+    addTestSource('import "foo" deferred ^;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_as2() {
+    addTestSource('import "foo" deferred a^;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_as3() {
+    addTestSource('import "foo" deferred a^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred() {
+    addTestSource('import "foo" ^ as foo;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred2() {
+    addTestSource('import "foo" d^ as foo;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred3() {
+    addTestSource('import "foo" d^ show foo;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS, Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred4() {
+    addTestSource('import "foo" d^ hide foo;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS, Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred5() {
+    addTestSource('import "foo" d^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS, Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred6() {
+    addTestSource('import "foo" d^ import');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS, Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred_not() {
+    addTestSource('import "foo" as foo ^;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred_as() {
+    addTestSource('import "foo" ^;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS, Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred_as2() {
+    addTestSource('import "foo" d^;');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS, Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred_as3() {
+    addTestSource('import "foo" ^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS, Keyword.DEFERRED], DART_RELEVANCE_HIGH);
+  }
+
+  test_import_deferred_as4() {
+    addTestSource('import "foo" d^');
+    expect(computeFast(), isTrue);
+    assertSuggestKeywords([Keyword.AS, Keyword.DEFERRED], DART_RELEVANCE_HIGH);
   }
 
   test_library() {
     addTestSource('library foo;^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.EXPORT,
-      Keyword.FINAL,
-      Keyword.IMPORT,
-      Keyword.PART,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(
+        DIRECTIVE_AND_DECLARATION_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   test_library_name() {
@@ -410,50 +522,22 @@
   test_part_of() {
     addTestSource('part of foo;^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.EXPORT,
-      Keyword.FINAL,
-      Keyword.IMPORT,
-      Keyword.PART,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(
+        DIRECTIVE_AND_DECLARATION_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   test_partial_class() {
     addTestSource('cl^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.EXPORT,
-      Keyword.FINAL,
-      Keyword.IMPORT,
-      Keyword.LIBRARY,
-      Keyword.PART,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(
+        DIRECTIVE_DECLARATION_AND_LIBRARY_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   test_partial_class2() {
     addTestSource('library a; cl^');
     expect(computeFast(), isTrue);
-    assertSuggestKeywords([
-      Keyword.ABSTRACT,
-      Keyword.CLASS,
-      Keyword.CONST,
-      Keyword.EXPORT,
-      Keyword.FINAL,
-      Keyword.IMPORT,
-      Keyword.PART,
-      Keyword.TYPEDEF,
-      Keyword.VAR
-    ], DART_RELEVANCE_HIGH);
+    assertSuggestKeywords(
+        DIRECTIVE_AND_DECLARATION_KEYWORDS, DART_RELEVANCE_HIGH);
   }
 
   void _appendKeywords(StringBuffer msg, Iterable<Keyword> keywords) {
diff --git a/pkg/analysis_server/test/services/completion/local_computer_test.dart b/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
similarity index 96%
rename from pkg/analysis_server/test/services/completion/local_computer_test.dart
rename to pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
index e0aca46..0fe8047 100644
--- a/pkg/analysis_server/test/services/completion/local_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/local_reference_contributor_test.dart
@@ -6,7 +6,7 @@
 
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/completion/local_computer.dart';
+import 'package:analysis_server/src/services/completion/local_reference_contributor.dart';
 import 'package:unittest/unittest.dart';
 
 import '../../reflective_tests.dart';
@@ -14,11 +14,11 @@
 
 main() {
   groupSep = ' | ';
-  runReflectiveTests(LocalComputerTest);
+  runReflectiveTests(LocalReferenceContributorTest);
 }
 
 @reflectiveTest
-class LocalComputerTest extends AbstractSelectorSuggestionTest {
+class LocalReferenceContributorTest extends AbstractSelectorSuggestionTest {
   @override
   CompletionSuggestion assertSuggestLocalClass(String name,
       {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
@@ -94,7 +94,7 @@
   CompletionSuggestion assertSuggestLocalVariable(
       String name, String returnType,
       {int relevance: DART_RELEVANCE_LOCAL_VARIABLE}) {
-    // Local variables should only be suggested by LocalComputer
+    // Local variables should only be suggested by LocalReferenceContributor
     CompletionSuggestion cs = assertSuggest(name,
         csKind: CompletionSuggestionKind.INVOCATION, relevance: relevance);
     expect(cs.returnType, returnType != null ? returnType : 'dynamic');
@@ -145,8 +145,23 @@
   }
 
   @override
-  void setUpComputer() {
-    computer = new LocalComputer();
+  void setUpContributor() {
+    contributor = new LocalReferenceContributor();
+  }
+
+  test_missing_params_function() {
+    addTestSource('int f1{} main(){f^}');
+    expect(computeFast(), isTrue);
+  }
+
+  test_missing_params_method() {
+    addTestSource('class C1{int f1{} main(){f^}}');
+    expect(computeFast(), isTrue);
+  }
+
+  test_missing_params_constructor() {
+    addTestSource('class C1{C1{} main(){C^}}');
+    expect(computeFast(), isTrue);
   }
 
   test_break_ignores_outer_functions_using_closure() {
diff --git a/pkg/analysis_server/test/services/completion/optype_test.dart b/pkg/analysis_server/test/services/completion/optype_test.dart
index a2634b1..ff74539 100644
--- a/pkg/analysis_server/test/services/completion/optype_test.dart
+++ b/pkg/analysis_server/test/services/completion/optype_test.dart
@@ -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.
 
-library test.services.completion.computer.dart.optype;
+library test.services.completion.contributor.dart.optype;
 
 import 'package:analysis_server/src/services/completion/completion_target.dart';
 import 'package:analysis_server/src/services/completion/optype.dart';
@@ -42,23 +42,20 @@
     visitor = new OpType.forCompletion(completionTarget, offset);
   }
 
-  void assertOpType({bool invocation: false, bool returnValue: false,
+  void assertOpType({bool prefixed: false, bool returnValue: false,
       bool typeNames: false, bool voidReturn: false, bool statementLabel: false,
       bool caseLabel: false, bool constructors: false}) {
-    expect(visitor.includeInvocationSuggestions, equals(invocation),
-        reason: 'invocation');
-    expect(visitor.includeReturnValueSuggestions, equals(returnValue),
+    expect(visitor.includeReturnValueSuggestions, returnValue,
         reason: 'returnValue');
-    expect(visitor.includeTypeNameSuggestions, equals(typeNames),
-        reason: 'typeNames');
-    expect(visitor.includeVoidReturnSuggestions, equals(voidReturn),
+    expect(visitor.includeTypeNameSuggestions, typeNames, reason: 'typeNames');
+    expect(visitor.includeVoidReturnSuggestions, voidReturn,
         reason: 'voidReturn');
-    expect(visitor.includeStatementLabelSuggestions, equals(statementLabel),
+    expect(visitor.includeStatementLabelSuggestions, statementLabel,
         reason: 'statementLabel');
-    expect(visitor.includeCaseLabelSuggestions, equals(caseLabel),
-        reason: 'caseLabel');
-    expect(visitor.includeConstructorSuggestions, equals(constructors),
+    expect(visitor.includeCaseLabelSuggestions, caseLabel, reason: 'caseLabel');
+    expect(visitor.includeConstructorSuggestions, constructors,
         reason: 'constructors');
+    expect(visitor.isPrefixed, prefixed, reason: 'prefixed');
   }
 
   test_Annotation() {
@@ -80,6 +77,12 @@
     assertOpType(returnValue: true, typeNames: true);
   }
 
+  test_ArgumentList_prefixedIdentifier() {
+    // SimpleIdentifier  PrefixedIdentifier  ArgumentList
+    addTestSource('void main() {expect(aa.^)}');
+    assertOpType(returnValue: true, typeNames: true, prefixed: true);
+  }
+
   test_AsExpression() {
     // SimpleIdentifier  TypeName  AsExpression
     addTestSource('class A {var b; X _c; foo() {var a; (a as ^).foo();}');
@@ -230,19 +233,20 @@
       // looks like a cascade to the parser
       // but the user is trying to get completions for a non-cascade
       main() {A a; a.^.z}''');
-    assertOpType(invocation: true);
+    assertOpType(
+        returnValue: true, typeNames: true, voidReturn: true, prefixed: true);
   }
 
   test_CascadeExpression_selector2() {
     // SimpleIdentifier  PropertyAccess  CascadeExpression  ExpressionStatement
     addTestSource('main() {A a; a..^z}');
-    assertOpType(invocation: true);
+    assertOpType(returnValue: true, voidReturn: true, prefixed: true);
   }
 
   test_CascadeExpression_selector2_withTrailingReturn() {
     // PropertyAccess  CascadeExpression  ExpressionStatement  Block
     addTestSource('main() {A a; a..^ return}');
-    assertOpType(invocation: true);
+    assertOpType(returnValue: true, voidReturn: true, prefixed: true);
   }
 
   test_CascadeExpression_target() {
@@ -251,6 +255,18 @@
     assertOpType(returnValue: true, typeNames: true, voidReturn: true);
   }
 
+  test_CatchClause_onType() {
+    // TypeName  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} on ^ {}}}');
+    assertOpType(typeNames: true);
+  }
+
+  test_CatchClause_onType_noBrackets() {
+    // TypeName  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} on ^}}');
+    assertOpType(typeNames: true);
+  }
+
   test_CatchClause_typed() {
     // Block  CatchClause  TryStatement
     addTestSource('class A {a() {try{var x;} on E catch (e) {^}}}');
@@ -332,7 +348,7 @@
     // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
     // InstanceCreationExpression
     addTestSource('main() {new X.^}');
-    assertOpType(invocation: true);
+    assertOpType(constructors: true, prefixed: true);
   }
 
   test_ConstructorName_name_resolved() {
@@ -346,14 +362,14 @@
     // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
     // InstanceCreationExpression
     addTestSource('main() {new String.fr^omCharCodes([]);}', resolved: true);
-    assertOpType(invocation: true);
+    assertOpType(constructors: true, prefixed: true);
   }
 
   test_ConstructorName_unresolved() {
     // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
     // InstanceCreationExpression
     addTestSource('main() {new String.fr^omCharCodes([]);}');
-    assertOpType(invocation: true);
+    assertOpType(constructors: true, prefixed: true);
   }
 
   test_Continue_after_label() {
@@ -475,10 +491,28 @@
     assertOpType(typeNames: true);
   }
 
+  test_FormalParameter_partialType() {
+    // FormalParameterList MethodDeclaration
+    addTestSource('class A {a(b.^ f) { }}');
+    assertOpType(returnValue: true, typeNames: true, prefixed: true);
+  }
+
+  test_FormalParameter_partialType2() {
+    // FormalParameterList MethodDeclaration
+    addTestSource('class A {a(b.z^ f) { }}');
+    assertOpType(returnValue: true, typeNames: true, prefixed: true);
+  }
+
+  test_FormalParameter_partialType3() {
+    // FormalParameterList MethodDeclaration
+    addTestSource('class A {a(b.^) { }}');
+    assertOpType(returnValue: true, typeNames: true, prefixed: true);
+  }
+
   test_FormalParameterList() {
     // FormalParameterList MethodDeclaration
     addTestSource('class A {a(^) { }}');
-    assertOpType(returnValue: true, typeNames: true);
+    assertOpType(typeNames: true);
   }
 
   test_ForStatement_condition() {
@@ -696,7 +730,7 @@
   test_IfStatement_invocation() {
     // SimpleIdentifier  PrefixIdentifier  IfStatement
     addTestSource('main() {var a; if (a.^) something}');
-    assertOpType(invocation: true);
+    assertOpType(returnValue: true, typeNames: true, prefixed: true);
   }
 
   test_ImplementsClause() {
@@ -762,7 +796,7 @@
   test_InterpolationExpression_prefix_selector() {
     // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
     addTestSource('main() {String name; print("hello \${name.^}");}');
-    assertOpType(invocation: true);
+    assertOpType(returnValue: true, typeNames: true, prefixed: true);
   }
 
   test_InterpolationExpression_prefix_target() {
@@ -991,7 +1025,8 @@
         // no semicolon between completion point and next statement
         set _s2(I x) {x.^ m(null);}
       }''');
-    assertOpType(invocation: true);
+    assertOpType(
+        returnValue: true, typeNames: true, voidReturn: true, prefixed: true);
   }
 
   test_PostfixExpression() {
@@ -1003,13 +1038,15 @@
   test_PrefixedIdentifier_class_const() {
     // SimpleIdentifier PrefixedIdentifier ExpressionStatement Block
     addTestSource('main() {A.^}');
-    assertOpType(invocation: true);
+    assertOpType(
+        returnValue: true, typeNames: true, voidReturn: true, prefixed: true);
   }
 
   test_PrefixedIdentifier_class_imported() {
     // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
     addTestSource('main() {A a; a.^}');
-    assertOpType(invocation: true);
+    assertOpType(
+        returnValue: true, typeNames: true, voidReturn: true, prefixed: true);
   }
 
   test_PrefixedIdentifier_prefix() {
@@ -1021,13 +1058,33 @@
   test_PropertyAccess_expression() {
     // SimpleIdentifier  MethodInvocation  PropertyAccess  ExpressionStatement
     addTestSource('class A {a() {"hello".to^String().length}}');
-    assertOpType(invocation: true);
+    assertOpType(
+        returnValue: true, typeNames: true, voidReturn: true, prefixed: true);
+  }
+
+  test_PropertyAccess_noTarget() {
+    // SimpleIdentifier  PropertyAccess  ExpressionStatement
+    addTestSource('main() {.^}');
+    assertOpType();
+  }
+
+  test_PropertyAccess_noTarget2() {
+    // SimpleIdentifier  PropertyAccess  CascadeExpressions
+    addTestSource('main() {.^.}');
+    assertOpType();
+  }
+
+  test_PropertyAccess_noTarget3() {
+    // SimpleIdentifier  PropertyAccess  CascadeExpressions
+    addTestSource('main() {..^}');
+    assertOpType();
   }
 
   test_PropertyAccess_selector() {
     // SimpleIdentifier  PropertyAccess  ExpressionStatement  Block
     addTestSource('class A {a() {"hello".length.^}}');
-    assertOpType(invocation: true);
+    assertOpType(
+        returnValue: true, typeNames: true, voidReturn: true, prefixed: true);
   }
 
   test_ReturnStatement() {
@@ -1039,7 +1096,7 @@
   test_SimpleFormalParameter() {
     // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
     addTestSource('mth() { PNGS.sort((String a, Str^) => a.compareTo(b)); }');
-    assertOpType(returnValue: true, typeNames: true);
+    assertOpType(typeNames: true);
   }
 
   test_SwitchCase() {
@@ -1062,16 +1119,16 @@
         // no semicolon between completion point and next statement
         set s1(I x) {} set _s2(I x) {this.^ m(null);}
       }''');
-    assertOpType(invocation: true);
+    assertOpType(returnValue: true, voidReturn: true, prefixed: true);
   }
 
   test_ThisExpression_constructor() {
-    // MethodInvocation  ExpressionStatement  Block
+    // SimpleIdentifier  PropertyAccess  ExpressionStatement
     addTestSource('''
       class A implements I {
         A() {this.^}
       }''');
-    assertOpType(invocation: true);
+    assertOpType(returnValue: true, voidReturn: true, prefixed: true);
   }
 
   test_ThrowExpression() {
diff --git a/pkg/analysis_server/test/services/completion/invocation_computer_test.dart b/pkg/analysis_server/test/services/completion/prefixed_element_contributor_test.dart
similarity index 95%
rename from pkg/analysis_server/test/services/completion/invocation_computer_test.dart
rename to pkg/analysis_server/test/services/completion/prefixed_element_contributor_test.dart
index 16fcb6ec..790d1ca 100644
--- a/pkg/analysis_server/test/services/completion/invocation_computer_test.dart
+++ b/pkg/analysis_server/test/services/completion/prefixed_element_contributor_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:analysis_server/src/protocol.dart';
 import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/completion/invocation_computer.dart';
+import 'package:analysis_server/src/services/completion/prefixed_element_contributor.dart';
 import 'package:unittest/unittest.dart';
 
 import '../../reflective_tests.dart';
@@ -16,11 +16,11 @@
 
 main() {
   groupSep = ' | ';
-  runReflectiveTests(InvocationComputerTest);
+  runReflectiveTests(PrefixedElementContributorTest);
 }
 
 @reflectiveTest
-class InvocationComputerTest extends AbstractSelectorSuggestionTest {
+class PrefixedElementContributorTest extends AbstractSelectorSuggestionTest {
   @override
   CompletionSuggestion assertSuggestInvocationField(String name, String type,
       {int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false}) {
@@ -70,8 +70,8 @@
   }
 
   @override
-  void setUpComputer() {
-    computer = new InvocationComputer();
+  void setUpContributor() {
+    contributor = new PrefixedElementContributor();
   }
 
   test_generic_field() {
@@ -142,6 +142,7 @@
     addTestSource('import "dart:async" as bar; foo() {bar.^}');
     return computeFull((bool result) {
       assertSuggestClass('Future');
+      assertNotSuggested('loadLibrary');
     });
   }
 
@@ -153,6 +154,15 @@
     });
   }
 
+  test_libraryPrefix_deferred() {
+    // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
+    addTestSource('import "dart:async" deferred as bar; foo() {bar.^}');
+    return computeFull((bool result) {
+      assertSuggestClass('Future');
+      assertSuggestFunction('loadLibrary', 'void');
+    });
+  }
+
   test_local() {
     addTestSource('foo() {String x = "bar"; x.^}');
     return computeFull((bool result) {
diff --git a/pkg/analysis_server/test/services/completion/test_all.dart b/pkg/analysis_server/test/services/completion/test_all.dart
index 269e8c0..f7c58bc 100644
--- a/pkg/analysis_server/test/services/completion/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/test_all.dart
@@ -6,16 +6,16 @@
 
 import 'package:unittest/unittest.dart';
 
-import 'arglist_computer_test.dart' as arglist_test;
-import 'combinator_computer_test.dart' as combinator_test;
+import 'arglist_contributor_test.dart' as arglist_test;
+import 'combinator_contributor_test.dart' as combinator_test;
 import 'common_usage_computer_test.dart' as common_usage_computer_test;
 import 'completion_computer_test.dart' as completion_computer_test;
 import 'completion_manager_test.dart' as completion_manager_test;
 import 'completion_target_test.dart' as completion_target_test;
-import 'imported_computer_test.dart' as imported_test;
-import 'invocation_computer_test.dart' as invocation_test;
-import 'keyword_computer_test.dart' as keyword_test;
-import 'local_computer_test.dart' as local_test;
+import 'imported_reference_contributor_test.dart' as imported_test;
+import 'prefixed_element_contributor_test.dart' as invocation_test;
+import 'keyword_contributor_test.dart' as keyword_test;
+import 'local_reference_contributor_test.dart' as local_test;
 import 'optype_test.dart' as optype_test;
 
 /// Utility for manually running all tests.
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart
index 52764fe..a7d8534 100644
--- a/pkg/analysis_server/test/services/correction/assist_test.dart
+++ b/pkg/analysis_server/test/services/correction/assist_test.dart
@@ -1290,6 +1290,28 @@
 ''');
   }
 
+  void test_convertToIsNotEmpty_wrong_noBang() {
+    verifyNoTestUnitErrors = false;
+    resolveTestUnit('''
+main(String str) {
+  ~str.isEmpty;
+}
+''');
+    assertNoAssistAt('isEmpty;', AssistKind.CONVERT_INTO_IS_NOT_EMPTY);
+  }
+
+  void test_convertToIsNotEmpty_wrong_noIsNotEmpty() {
+    resolveTestUnit('''
+class A {
+  bool get isEmpty => false;
+}
+main(A a) {
+  !a.isEmpty;
+}
+''');
+    assertNoAssistAt('isEmpty;', AssistKind.CONVERT_INTO_IS_NOT_EMPTY);
+  }
+
   void test_convertToIsNotEmpty_wrong_notInPrefixExpression() {
     resolveTestUnit('''
 main(String str) {
@@ -1308,16 +1330,120 @@
     assertNoAssistAt('isEven;', AssistKind.CONVERT_INTO_IS_NOT_EMPTY);
   }
 
-  void test_convertToIsNotEmpty_wrote_noIsNotEmpty() {
+  void test_encapsulateField_BAD_alreadyPrivate() {
     resolveTestUnit('''
 class A {
-  bool get isEmpty => false;
+  int _test = 42;
 }
 main(A a) {
-  !a.isEmpty;
+  print(a._test);
 }
 ''');
-    assertNoAssistAt('isEmpty;', AssistKind.CONVERT_INTO_IS_NOT_EMPTY);
+    assertNoAssistAt('_test =', AssistKind.ENCAPSULATE_FIELD);
+  }
+
+  void test_encapsulateField_BAD_final() {
+    resolveTestUnit('''
+class A {
+  final int test = 42;
+}
+''');
+    assertNoAssistAt('test =', AssistKind.ENCAPSULATE_FIELD);
+  }
+
+  void test_encapsulateField_BAD_multipleFields() {
+    resolveTestUnit('''
+class A {
+  int aaa, bbb, ccc;
+}
+main(A a) {
+  print(a.bbb);
+}
+''');
+    assertNoAssistAt('bbb, ', AssistKind.ENCAPSULATE_FIELD);
+  }
+
+  void test_encapsulateField_BAD_notOnName() {
+    resolveTestUnit('''
+class A {
+  int test = 1 + 2 + 3;
+}
+''');
+    assertNoAssistAt('+ 2', AssistKind.ENCAPSULATE_FIELD);
+  }
+
+  void test_encapsulateField_BAD_parseError() {
+    verifyNoTestUnitErrors = false;
+    resolveTestUnit('''
+class A {
+  int; // marker
+}
+main(A a) {
+  print(a.test);
+}
+''');
+    assertNoAssistAt('; // marker', AssistKind.ENCAPSULATE_FIELD);
+  }
+
+  void test_encapsulateField_BAD_static() {
+    resolveTestUnit('''
+class A {
+  static int test = 42;
+}
+''');
+    assertNoAssistAt('test =', AssistKind.ENCAPSULATE_FIELD);
+  }
+
+  void test_encapsulateField_OK_hasType() {
+    resolveTestUnit('''
+class A {
+  int test = 42;
+  A(this.test);
+}
+main(A a) {
+  print(a.test);
+}
+''');
+    assertHasAssistAt('test = 42', AssistKind.ENCAPSULATE_FIELD, '''
+class A {
+  int _test = 42;
+
+  int get test => _test;
+
+  void set test(int test) {
+    _test = test;
+  }
+  A(this._test);
+}
+main(A a) {
+  print(a.test);
+}
+''');
+  }
+
+  void test_encapsulateField_OK_noType() {
+    resolveTestUnit('''
+class A {
+  var test = 42;
+}
+main(A a) {
+  print(a.test);
+}
+''');
+    assertHasAssistAt('test = 42', AssistKind.ENCAPSULATE_FIELD, '''
+class A {
+  var _test = 42;
+
+  get test => _test;
+
+  void set test(test) {
+    _test = test;
+  }
+}
+main(A a) {
+  print(a.test);
+}
+''');
   }
 
   void test_exchangeBinaryExpressionArguments_OK_compare() {
@@ -2324,6 +2450,19 @@
 ''');
   }
 
+  void test_removeTypeAnnotation_classField_OK_final() {
+    resolveTestUnit('''
+class A {
+  final int v = 1;
+}
+''');
+    assertHasAssistAt('v = ', AssistKind.REMOVE_TYPE_ANNOTATION, '''
+class A {
+  final v = 1;
+}
+''');
+  }
+
   void test_removeTypeAnnotation_localVariable_OK() {
     resolveTestUnit('''
 main() {
@@ -2337,6 +2476,32 @@
 ''');
   }
 
+  void test_removeTypeAnnotation_localVariable_OK_const() {
+    resolveTestUnit('''
+main() {
+  const int v = 1;
+}
+''');
+    assertHasAssistAt('int ', AssistKind.REMOVE_TYPE_ANNOTATION, '''
+main() {
+  const v = 1;
+}
+''');
+  }
+
+  void test_removeTypeAnnotation_localVariable_OK_final() {
+    resolveTestUnit('''
+main() {
+  final int v = 1;
+}
+''');
+    assertHasAssistAt('int ', AssistKind.REMOVE_TYPE_ANNOTATION, '''
+main() {
+  final v = 1;
+}
+''');
+  }
+
   void test_removeTypeAnnotation_topLevelVariable_OK() {
     resolveTestUnit('''
 int V = 1;
@@ -2346,6 +2511,15 @@
 ''');
   }
 
+  void test_removeTypeAnnotation_topLevelVariable_OK_final() {
+    resolveTestUnit('''
+final int V = 1;
+''');
+    assertHasAssistAt('int ', AssistKind.REMOVE_TYPE_ANNOTATION, '''
+final V = 1;
+''');
+  }
+
   void test_replaceConditionalWithIfElse_OK_assignment() {
     resolveTestUnit('''
 main() {
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index aa12e4d..6589220 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -421,6 +421,22 @@
     _assertLinkedGroup(change.linkedEditGroups[0], ['named(int ', 'named(1']);
   }
 
+  void test_createConstructorForFinalFields_inTopLevelMethod() {
+    resolveTestUnit('''
+main() {
+  final int v;
+}
+''');
+    assertNoFix(FixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS);
+  }
+
+  void test_createConstructorForFinalFields_topLevelField() {
+    resolveTestUnit('''
+final int v;
+''');
+    assertNoFix(FixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS);
+  }
+
   void test_createConstructorSuperExplicit() {
     resolveTestUnit('''
 class A {
@@ -2396,6 +2412,17 @@
 ''');
   }
 
+  void test_noException_1() {
+    resolveTestUnit('''
+main(p) {
+  p i s Null;
+}''');
+    List<AnalysisError> errors = context.computeErrors(testSource);
+    for (var error in errors) {
+      computeFixes(testUnit, error);
+    }
+  }
+
   void test_removeParentheses_inGetterDeclaration() {
     resolveTestUnit('''
 class A {
diff --git a/pkg/analysis_server/test/services/index/store/codec_test.dart b/pkg/analysis_server/test/services/index/store/codec_test.dart
index 1ad0e42..b02f669 100644
--- a/pkg/analysis_server/test/services/index/store/codec_test.dart
+++ b/pkg/analysis_server/test/services/index/store/codec_test.dart
@@ -8,7 +8,6 @@
 import 'package:analysis_server/src/services/index/store/codec.dart';
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:unittest/unittest.dart';
 
 import '../../../abstract_single_unit.dart';
@@ -72,6 +71,289 @@
     codec = new ElementCodec(stringCodec);
   }
 
+  void test_encode_CompilationUnitElement() {
+    addSource('/my_part.dart', '''
+part of my_lib;
+''');
+    resolveTestUnit('''
+library my_lib;
+part 'my_part.dart';
+''');
+    // defining unit
+    {
+      Element element = testLibraryElement.definingCompilationUnit;
+      expect(element.source.fullName, '/test.dart');
+      int id1 = codec.encode1(element);
+      int id2 = codec.encode2(element);
+      int id3 = codec.encode3(element);
+      expect(id1, isNonNegative);
+      expect(id2, element.nameOffset);
+      expect(id3, ElementKind.COMPILATION_UNIT.ordinal);
+      // decode
+      Element element2 = codec.decode(context, id1, id2, id3);
+      expect(element2, element);
+    }
+    // part
+    {
+      Element element = testLibraryElement.parts[0];
+      expect(element.source.fullName, '/my_part.dart');
+      int id1 = codec.encode1(element);
+      int id2 = codec.encode2(element);
+      int id3 = codec.encode3(element);
+      expect(id1, isNonNegative);
+      expect(id2, element.nameOffset);
+      expect(id3, ElementKind.COMPILATION_UNIT.ordinal);
+      // decode
+      Element element2 = codec.decode(context, id1, id2, id3);
+      expect(element2, element);
+    }
+  }
+
+  void test_encode_ConstructorElement_default_real() {
+    resolveTestUnit('''
+class A {
+  A();
+}
+''');
+    ClassElement classA = findElement('A');
+    ConstructorElement element = classA.constructors[0];
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, isNonNegative);
+    expect(id2, classA.nameOffset);
+    expect(id3, -100);
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, element);
+  }
+
+  void test_encode_ConstructorElement_default_synthetic() {
+    resolveTestUnit('''
+class A {
+}
+''');
+    ClassElement classA = findElement('A');
+    ConstructorElement element = classA.constructors[0];
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, isNonNegative);
+    expect(id2, classA.nameOffset);
+    expect(id3, -100);
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, element);
+  }
+
+  void test_encode_ConstructorElement_named_real() {
+    resolveTestUnit('''
+class A {
+  A.aaa();
+  A.bbb();
+}
+''');
+    ClassElement classA = findElement('A');
+    // A.aaa()
+    {
+      ConstructorElement element = classA.getNamedConstructor('aaa');
+      int id1 = codec.encode1(element);
+      int id2 = codec.encode2(element);
+      int id3 = codec.encode3(element);
+      expect(id1, isNonNegative);
+      expect(id2, classA.nameOffset);
+      expect(id3, -100);
+      // decode
+      Element element2 = codec.decode(context, id1, id2, id3);
+      expect(element2, element);
+    }
+    // A.bbb()
+    {
+      ConstructorElement element = classA.getNamedConstructor('bbb');
+      int id1 = codec.encode1(element);
+      int id2 = codec.encode2(element);
+      int id3 = codec.encode3(element);
+      expect(id1, isNonNegative);
+      expect(id2, classA.nameOffset);
+      expect(id3, -101);
+      // decode
+      Element element2 = codec.decode(context, id1, id2, id3);
+      expect(element2, element);
+    }
+  }
+
+  void test_encode_ConstructorElement_named_synthetic() {
+    resolveTestUnit('''
+class A {
+  A.aaa();
+  A.bbb();
+}
+class M {}
+class X = A with M;
+''');
+    ClassElement classX = findElement('X');
+    // X.aaa()
+    {
+      ConstructorElement element = classX.getNamedConstructor('aaa');
+      int id1 = codec.encode1(element);
+      int id2 = codec.encode2(element);
+      int id3 = codec.encode3(element);
+      expect(id1, isNonNegative);
+      expect(id2, classX.nameOffset);
+      expect(id3, -100);
+      // decode
+      Element element2 = codec.decode(context, id1, id2, id3);
+      expect(element2, element);
+    }
+    // X.bbb()
+    {
+      ConstructorElement element = classX.getNamedConstructor('bbb');
+      int id1 = codec.encode1(element);
+      int id2 = codec.encode2(element);
+      int id3 = codec.encode3(element);
+      expect(id1, isNonNegative);
+      expect(id2, classX.nameOffset);
+      expect(id3, -101);
+      // decode
+      Element element2 = codec.decode(context, id1, id2, id3);
+      expect(element2, element);
+    }
+  }
+
+  void test_encode_getter_real() {
+    resolveTestUnit('''
+class A {
+  int get test => 42;
+}
+''');
+    PropertyAccessorElement element = findElement('test', ElementKind.GETTER);
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, isNonNegative);
+    expect(id2, element.nameOffset);
+    expect(id3, ElementKind.GETTER.ordinal);
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, element);
+  }
+
+  void test_encode_getter_synthetic() {
+    resolveTestUnit('''
+class A {
+  int test;
+}
+''');
+    FieldElement field = findElement('test', ElementKind.FIELD);
+    PropertyAccessorElement element = field.getter;
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, isNonNegative);
+    expect(id2, element.nameOffset);
+    expect(id3, ElementKind.GETTER.ordinal);
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, element);
+  }
+
+  void test_encode_LibraryElement() {
+    resolveTestUnit('''
+class A {
+  test() {}
+}
+''');
+    Element element = testLibraryElement;
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, isNonNegative);
+    expect(id2, element.nameOffset);
+    expect(id3, ElementKind.LIBRARY.ordinal);
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, element);
+  }
+
+  void test_encode_MethodElement() {
+    resolveTestUnit('''
+class A {
+  test() {}
+}
+''');
+    Element element = findElement('test');
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, isNonNegative);
+    expect(id2, element.nameOffset);
+    expect(id3, ElementKind.METHOD.ordinal);
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, element);
+  }
+
+  void test_encode_NameElement() {
+    Element element = new NameElement('test');
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, -1);
+    expect(id2, isNonNegative);
+    expect(id3, ElementKind.NAME.ordinal);
+  }
+
+  void test_encode_nullLibraryElement() {
+    resolveTestUnit('''
+test() {}
+''');
+    Element element = findElement('test');
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    context.setContents(testSource, '');
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, isNull);
+  }
+
+  void test_encode_setter_real() {
+    resolveTestUnit('''
+class A {
+  void set test(x) {}
+}
+''');
+    PropertyAccessorElement element = findElement('test=', ElementKind.SETTER);
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, isNonNegative);
+    expect(id2, element.nameOffset);
+    expect(id3, ElementKind.SETTER.ordinal);
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, element);
+  }
+
+  void test_encode_setter_synthetic() {
+    resolveTestUnit('''
+class A {
+  int test;
+}
+''');
+    FieldElement field = findElement('test', ElementKind.FIELD);
+    PropertyAccessorElement element = field.setter;
+    int id1 = codec.encode1(element);
+    int id2 = codec.encode2(element);
+    int id3 = codec.encode3(element);
+    expect(id1, isNonNegative);
+    expect(id2, element.nameOffset);
+    expect(id3, ElementKind.SETTER.ordinal);
+    // decode
+    Element element2 = codec.decode(context, id1, id2, id3);
+    expect(element2, element);
+  }
+
   void test_encodeHash_notLocal() {
     resolveTestUnit('''
 class A {
@@ -95,140 +377,6 @@
     expect(id_fooA == id_fooB, isTrue);
     expect(id_fooA == id_bar, isFalse);
   }
-
-  void test_field() {
-    resolveTestUnit('''
-class A {
-  int field;
-}
-''');
-    FieldElement field = findElement('field', ElementKind.FIELD);
-    PropertyAccessorElement getter = field.getter;
-    PropertyAccessorElement setter = field.setter;
-    {
-      int id = codec.encode(getter, false);
-      expect(codec.decode(context, id), getter);
-    }
-    {
-      int id = codec.encode(setter, false);
-      expect(codec.decode(context, id), setter);
-    }
-    {
-      int id = codec.encode(field, false);
-      expect(codec.decode(context, id), field);
-    }
-  }
-
-  void test_filePackage_uriMix() {
-    MethodElement buildMethodElement(Source source) {
-      CompilationUnitElementImpl unitElement =
-          new CompilationUnitElementImpl('file.dart');
-      LibraryElementImpl libraryElement =
-          new LibraryElementImpl(null, 'lib', 0);
-      ClassElementImpl classElement = new ClassElementImpl('A', 0);
-      MethodElementImpl methodElement = new MethodElementImpl('m', 0);
-      unitElement.source = source;
-      libraryElement.definingCompilationUnit = unitElement;
-      unitElement.types = [classElement];
-      classElement.methods = [methodElement];
-      return methodElement;
-    }
-    // file:
-    int fileId;
-    {
-      Source source = new _TestSource('/my/file.dart', 'file:///my/file.dart');
-      var methodElement = buildMethodElement(source);
-      fileId = codec.encode(methodElement, true);
-    }
-    // package:
-    int packageId;
-    {
-      Source source =
-          new _TestSource('/my/file.dart', 'package:my_pkg/file.dart');
-      var methodElement = buildMethodElement(source);
-      packageId = codec.encode(methodElement, true);
-    }
-    // should be the same
-    expect(packageId, fileId);
-  }
-
-  void test_localLocalVariable() {
-    resolveTestUnit('''
-main() {
-  {
-    foo() {
-      int bar; // A
-    }
-  }
-  {
-    foo() {
-      int bar; // B
-    }
-  }
-}
-''');
-    {
-      LocalVariableElement element = findNodeElementAtString('bar; // A', null);
-      int id = codec.encode(element, false);
-      expect(codec.decode(context, id), element);
-    }
-    {
-      LocalVariableElement element = findNodeElementAtString('bar; // B', null);
-      int id = codec.encode(element, false);
-      expect(codec.decode(context, id), element);
-    }
-    // check strings, "foo" as a single string, no "foo@17" or "bar@35"
-    expect(stringCodec.nameToIndex, hasLength(4));
-    expect(stringCodec.nameToIndex, containsPair('file:///test.dart', 0));
-    expect(stringCodec.nameToIndex, containsPair('main', 1));
-    expect(stringCodec.nameToIndex, containsPair('foo', 2));
-    expect(stringCodec.nameToIndex, containsPair('bar', 3));
-  }
-
-  void test_localVariable() {
-    resolveTestUnit('''
-main() {
-  {
-    int foo; // A
-  }
-  {
-    int foo; // B
-  }
-}
-''');
-    {
-      LocalVariableElement element = findNodeElementAtString('foo; // A', null);
-      int id = codec.encode(element, false);
-      expect(codec.decode(context, id), element);
-    }
-    {
-      LocalVariableElement element = findNodeElementAtString('foo; // B', null);
-      int id = codec.encode(element, false);
-      expect(codec.decode(context, id), element);
-    }
-    // check strings, "foo" as a single string, no "foo@21" or "foo@47"
-    expect(stringCodec.nameToIndex, hasLength(3));
-    expect(stringCodec.nameToIndex, containsPair('file:///test.dart', 0));
-    expect(stringCodec.nameToIndex, containsPair('main', 1));
-    expect(stringCodec.nameToIndex, containsPair('foo', 2));
-  }
-
-  void test_notLocal() {
-    resolveTestUnit('''
-main() {
-  int foo;
-}
-''');
-    LocalVariableElement element = findElement('foo');
-    int id = codec.encode(element, false);
-    expect(codec.encode(element, false), id);
-    expect(codec.decode(context, id), element);
-    // check strings
-    expect(stringCodec.nameToIndex, hasLength(3));
-    expect(stringCodec.nameToIndex, containsPair('file:///test.dart', 0));
-    expect(stringCodec.nameToIndex, containsPair('main', 1));
-    expect(stringCodec.nameToIndex, containsPair('foo', 2));
-  }
 }
 
 @reflectiveTest
@@ -258,12 +406,3 @@
     expect(codec.decode(idB), 'bbb');
   }
 }
-
-class _TestSource implements Source {
-  final String fullName;
-  final String encoding;
-
-  _TestSource(this.fullName, this.encoding);
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/analysis_server/test/services/index/store/split_store_test.dart b/pkg/analysis_server/test/services/index/store/split_store_test.dart
index 1bb66fb..28352ae 100644
--- a/pkg/analysis_server/test/services/index/store/split_store_test.dart
+++ b/pkg/analysis_server/test/services/index/store/split_store_test.dart
@@ -172,15 +172,12 @@
     Future putFuture;
     {
       // prepare relations
-      int elementIdA = 0;
-      int elementIdB = 1;
-      int elementIdC = 2;
       int relationshipId = relationshipCodec.encode(relationship);
       RelationKeyData key =
-          new RelationKeyData.forData(elementIdA, relationshipId);
+          new RelationKeyData.forData(0, 1, 2, relationshipId);
       List<LocationData> locations = [
-        new LocationData.forData(elementIdB, 1, 10, 2),
-        new LocationData.forData(elementIdC, 2, 20, 3)
+        new LocationData.forData(3, 4, 5, 1, 10, 2),
+        new LocationData.forData(6, 7, 8, 2, 20, 3)
       ];
       Map<RelationKeyData, List<LocationData>> relations = {key: locations};
       // prepare Node
@@ -236,10 +233,14 @@
   }
 
   Element _mockElement() {
-    int elementId = nextElementId++;
+    int id1 = nextElementId++;
+    int id2 = nextElementId++;
+    int id3 = nextElementId++;
     Element element = new MockElement();
-    when(elementCodec.encode(element, anyBool)).thenReturn(elementId);
-    when(elementCodec.decode(context, elementId)).thenReturn(element);
+    when(elementCodec.encode1(element)).thenReturn(id1);
+    when(elementCodec.encode2(element)).thenReturn(id2);
+    when(elementCodec.encode3(element)).thenReturn(id3);
+    when(elementCodec.decode(context, id1, id2, id3)).thenReturn(element);
     return element;
   }
 }
@@ -300,15 +301,12 @@
     Relationship relationship = Relationship.getRelationship('my-relationship');
     // record
     {
-      int elementIdA = 0;
-      int elementIdB = 1;
-      int elementIdC = 2;
       int relationshipId = relationshipCodec.encode(relationship);
       RelationKeyData key =
-          new RelationKeyData.forData(elementIdA, relationshipId);
+          new RelationKeyData.forData(0, 1, 2, relationshipId);
       List<LocationData> locations = [
-        new LocationData.forData(elementIdB, 1, 10, 2),
-        new LocationData.forData(elementIdC, 2, 20, 3)
+        new LocationData.forData(3, 4, 5, 1, 10, 2),
+        new LocationData.forData(6, 7, 8, 2, 20, 3)
       ];
       node.relations = {key: locations};
     }
@@ -320,10 +318,14 @@
   }
 
   Element _mockElement() {
-    int elementId = nextElementId++;
+    int id1 = nextElementId++;
+    int id2 = nextElementId++;
+    int id3 = nextElementId++;
     Element element = new MockElement();
-    when(elementCodec.encode(element, anyBool)).thenReturn(elementId);
-    when(elementCodec.decode(context, elementId)).thenReturn(element);
+    when(elementCodec.encode1(element)).thenReturn(id1);
+    when(elementCodec.encode2(element)).thenReturn(id2);
+    when(elementCodec.encode3(element)).thenReturn(id3);
+    when(elementCodec.decode(context, id1, id2, id3)).thenReturn(element);
     return element;
   }
 }
@@ -336,8 +338,8 @@
 
   void test_newForData() {
     Element element = new MockElement();
-    when(elementCodec.decode(context, 0)).thenReturn(element);
-    LocationData locationData = new LocationData.forData(0, 1, 2, 0);
+    when(elementCodec.decode(context, 11, 12, 13)).thenReturn(element);
+    LocationData locationData = new LocationData.forData(11, 12, 13, 1, 2, 0);
     Location location = locationData.getLocation(context, elementCodec);
     expect(location.element, element);
     expect(location.offset, 1);
@@ -349,8 +351,10 @@
   void test_newForObject() {
     // prepare Element
     Element element = new MockElement();
-    when(elementCodec.encode(element, anyBool)).thenReturn(42);
-    when(elementCodec.decode(context, 42)).thenReturn(element);
+    when(elementCodec.encode1(element)).thenReturn(11);
+    when(elementCodec.encode2(element)).thenReturn(12);
+    when(elementCodec.encode3(element)).thenReturn(13);
+    when(elementCodec.decode(context, 11, 12, 13)).thenReturn(element);
     // create
     Location location = new Location(element, 1, 2);
     LocationData locationData =
@@ -358,7 +362,8 @@
     // touch 'hashCode'
     locationData.hashCode;
     // ==
-    expect(locationData == new LocationData.forData(42, 1, 2, 2), isTrue);
+    expect(
+        locationData == new LocationData.forData(11, 12, 13, 1, 2, 2), isTrue);
     // getLocation()
     {
       Location newLocation = locationData.getLocation(context, elementCodec);
@@ -368,7 +373,7 @@
     }
     // no Element - no Location
     {
-      when(elementCodec.decode(context, 42)).thenReturn(null);
+      when(elementCodec.decode(context, 11, 12, 13)).thenReturn(null);
       Location newLocation = locationData.getLocation(context, elementCodec);
       expect(newLocation, isNull);
     }
@@ -417,24 +422,25 @@
   StringCodec stringCodec = new StringCodec();
 
   void test_newFromData() {
-    RelationKeyData keyData = new RelationKeyData.forData(1, 2);
+    RelationKeyData keyData = new RelationKeyData.forData(11, 12, 13, 2);
     // equals
     expect(keyData == this, isFalse);
-    expect(keyData == new RelationKeyData.forData(10, 20), isFalse);
+    expect(keyData == new RelationKeyData.forData(11, 12, 13, 20), isFalse);
     expect(keyData == keyData, isTrue);
-    expect(keyData == new RelationKeyData.forData(1, 2), isTrue);
+    expect(keyData == new RelationKeyData.forData(11, 12, 13, 2), isTrue);
   }
 
   void test_newFromObjects() {
     // prepare Element
     Element element;
-    int elementId = 2;
     {
       element = new MockElement();
       ElementLocation location = new ElementLocationImpl.con3(['foo', 'bar']);
       when(element.location).thenReturn(location);
       when(context.getElement(location)).thenReturn(element);
-      when(elementCodec.encode(element, anyBool)).thenReturn(elementId);
+      when(elementCodec.encode1(element)).thenReturn(11);
+      when(elementCodec.encode2(element)).thenReturn(12);
+      when(elementCodec.encode3(element)).thenReturn(13);
     }
     // prepare relationship
     Relationship relationship = Relationship.getRelationship('my-relationship');
@@ -447,9 +453,9 @@
     keyData.hashCode;
     // equals
     expect(keyData == this, isFalse);
-    expect(keyData == new RelationKeyData.forData(10, 20), isFalse);
+    expect(keyData == new RelationKeyData.forData(11, 12, 13, 20), isFalse);
     expect(keyData == keyData, isTrue);
-    expect(keyData == new RelationKeyData.forData(elementId, relationshipId),
+    expect(keyData == new RelationKeyData.forData(11, 12, 13, relationshipId),
         isTrue);
   }
 }
@@ -457,29 +463,20 @@
 @reflectiveTest
 class _SplitIndexStoreTest {
   AnalysisContext contextA = new MockAnalysisContext('contextA');
-
   AnalysisContext contextB = new MockAnalysisContext('contextB');
-
   AnalysisContext contextC = new MockAnalysisContext('contextC');
 
   Element elementA = new MockElement('elementA');
   Element elementB = new MockElement('elementB');
-
   Element elementC = new MockElement('elementC');
   Element elementD = new MockElement('elementD');
-  ElementLocation elementLocationA =
-      new ElementLocationImpl.con3(['/home/user/sourceA.dart', 'ClassA']);
-  ElementLocation elementLocationB =
-      new ElementLocationImpl.con3(['/home/user/sourceB.dart', 'ClassB']);
-  ElementLocation elementLocationC =
-      new ElementLocationImpl.con3(['/home/user/sourceC.dart', 'ClassC']);
-  ElementLocation elementLocationD =
-      new ElementLocationImpl.con3(['/home/user/sourceD.dart', 'ClassD']);
+
   HtmlElement htmlElementA = new MockHtmlElement();
   HtmlElement htmlElementB = new MockHtmlElement();
   LibraryElement libraryElement = new MockLibraryElement();
   Source librarySource = new MockSource('librarySource');
   CompilationUnitElement libraryUnitElement = new MockCompilationUnitElement();
+  ElementCodec elementCodec = new MockElementCodec();
   MemoryNodeManager nodeManager = new MemoryNodeManager();
   Relationship relationship = Relationship.getRelationship('test-relationship');
   Source sourceA = new MockSource('sourceA');
@@ -493,14 +490,27 @@
   CompilationUnitElement unitElementD = new MockCompilationUnitElement();
 
   void setUp() {
+    nodeManager.elementCodec = elementCodec;
     store = new SplitIndexStore(nodeManager);
+    when(elementCodec.encode1(elementA)).thenReturn(11);
+    when(elementCodec.encode2(elementA)).thenReturn(12);
+    when(elementCodec.encode3(elementA)).thenReturn(13);
+    when(elementCodec.encode1(elementB)).thenReturn(21);
+    when(elementCodec.encode2(elementB)).thenReturn(22);
+    when(elementCodec.encode3(elementB)).thenReturn(23);
+    when(elementCodec.encode1(elementC)).thenReturn(31);
+    when(elementCodec.encode2(elementC)).thenReturn(32);
+    when(elementCodec.encode3(elementC)).thenReturn(33);
+    when(elementCodec.encode1(elementD)).thenReturn(41);
+    when(elementCodec.encode2(elementD)).thenReturn(42);
+    when(elementCodec.encode3(elementD)).thenReturn(43);
+    when(elementCodec.decode(contextA, 11, 12, 13)).thenReturn(elementA);
+    when(elementCodec.decode(contextA, 21, 22, 23)).thenReturn(elementB);
+    when(elementCodec.decode(contextA, 31, 32, 33)).thenReturn(elementC);
+    when(elementCodec.decode(contextA, 41, 42, 43)).thenReturn(elementD);
     when(contextA.isDisposed).thenReturn(false);
     when(contextB.isDisposed).thenReturn(false);
     when(contextC.isDisposed).thenReturn(false);
-    when(contextA.getElement(elementLocationA)).thenReturn(elementA);
-    when(contextA.getElement(elementLocationB)).thenReturn(elementB);
-    when(contextA.getElement(elementLocationC)).thenReturn(elementC);
-    when(contextA.getElement(elementLocationD)).thenReturn(elementD);
     when(librarySource.fullName).thenReturn('/home/user/librarySource.dart');
     when(sourceA.fullName).thenReturn('/home/user/sourceA.dart');
     when(sourceB.fullName).thenReturn('/home/user/sourceB.dart');
@@ -510,10 +520,6 @@
     when(elementB.context).thenReturn(contextA);
     when(elementC.context).thenReturn(contextA);
     when(elementD.context).thenReturn(contextA);
-    when(elementA.location).thenReturn(elementLocationA);
-    when(elementB.location).thenReturn(elementLocationB);
-    when(elementC.location).thenReturn(elementLocationC);
-    when(elementD.location).thenReturn(elementLocationD);
     when(elementA.enclosingElement).thenReturn(unitElementA);
     when(elementB.enclosingElement).thenReturn(unitElementB);
     when(elementC.enclosingElement).thenReturn(unitElementC);
@@ -555,8 +561,9 @@
       store.aboutToIndexDart(contextA, libraryUnitElement);
       store.doneIndex();
     }
-    return store.getRelationships(elementA, relationship).then(
-        (List<Location> locations) {
+    return store
+        .getRelationships(elementA, relationship)
+        .then((List<Location> locations) {
       assertLocations(locations, []);
     });
   }
@@ -622,8 +629,9 @@
       store.doneIndex();
     }
     // "A" and "B" locations
-    return store.getRelationships(elementA, relationship).then(
-        (List<Location> locations) {
+    return store
+        .getRelationships(elementA, relationship)
+        .then((List<Location> locations) {
       assertLocations(locations, [locationA, locationB]);
     });
   }
@@ -714,8 +722,9 @@
       store.recordRelationship(elementA, relationship, locationB);
       store.doneIndex();
     }
-    return store.getRelationships(elementA, relationship).then(
-        (List<Location> locations) {
+    return store
+        .getRelationships(elementA, relationship)
+        .then((List<Location> locations) {
       assertLocations(locations, [locationA, locationB]);
     });
   }
@@ -725,8 +734,9 @@
     store.aboutToIndexDart(contextA, unitElementA);
     store.recordRelationship(elementA, relationship, locationA);
     store.doneIndex();
-    return store.getRelationships(elementA, relationship).then(
-        (List<Location> locations) {
+    return store
+        .getRelationships(elementA, relationship)
+        .then((List<Location> locations) {
       assertLocations(locations, [locationA]);
     });
   }
@@ -738,8 +748,9 @@
     store.recordRelationship(elementA, relationship, locationA);
     store.recordRelationship(elementA, relationship, locationB);
     store.doneIndex();
-    return store.getRelationships(elementA, relationship).then(
-        (List<Location> locations) {
+    return store
+        .getRelationships(elementA, relationship)
+        .then((List<Location> locations) {
       assertLocations(locations, [locationA, locationB]);
     });
   }
@@ -804,8 +815,9 @@
     }).then((_) {
       // remove "librarySource"
       store.removeSource(contextA, librarySource);
-      return store.getRelationships(elementA, relationship).then(
-          (List<Location> locations) {
+      return store
+          .getRelationships(elementA, relationship)
+          .then((List<Location> locations) {
         assertLocations(locations, []);
       });
     });
@@ -842,8 +854,9 @@
     }).then((_) {
       // remove "A" source
       store.removeSource(contextA, sourceA);
-      return store.getRelationships(elementA, relationship).then(
-          (List<Location> locations) {
+      return store
+          .getRelationships(elementA, relationship)
+          .then((List<Location> locations) {
         assertLocations(locations, [locationB, locationC]);
       });
     });
@@ -870,8 +883,9 @@
     }).then((_) {
       // remove "librarySource"
       store.removeSources(contextA, new SingleSourceContainer(librarySource));
-      return store.getRelationships(elementA, relationship).then(
-          (List<Location> locations) {
+      return store
+          .getRelationships(elementA, relationship)
+          .then((List<Location> locations) {
         assertLocations(locations, []);
       });
     });
@@ -912,8 +926,8 @@
   }
 
   void test_universe_aboutToIndex() {
-    when(contextA.getElement(elementLocationA)).thenReturn(elementA);
-    when(contextB.getElement(elementLocationB)).thenReturn(elementB);
+    when(elementCodec.decode(contextA, 11, 12, 13)).thenReturn(elementA);
+    when(elementCodec.decode(contextB, 21, 22, 23)).thenReturn(elementB);
     {
       store.aboutToIndexDart(contextA, unitElementA);
       store.recordTopLevelDeclaration(elementA);
@@ -941,8 +955,8 @@
   }
 
   void test_universe_clear() {
-    when(contextA.getElement(elementLocationA)).thenReturn(elementA);
-    when(contextB.getElement(elementLocationB)).thenReturn(elementB);
+    when(elementCodec.decode(contextA, 11, 12, 13)).thenReturn(elementA);
+    when(elementCodec.decode(contextB, 21, 22, 23)).thenReturn(elementB);
     {
       store.aboutToIndexDart(contextA, unitElementA);
       store.recordTopLevelDeclaration(elementA);
@@ -967,8 +981,8 @@
   }
 
   void test_universe_removeContext() {
-    when(contextA.getElement(elementLocationA)).thenReturn(elementA);
-    when(contextB.getElement(elementLocationB)).thenReturn(elementB);
+    when(elementCodec.decode(contextA, 11, 12, 13)).thenReturn(elementA);
+    when(elementCodec.decode(contextB, 21, 22, 23)).thenReturn(elementB);
     {
       store.aboutToIndexDart(contextA, unitElementA);
       store.recordTopLevelDeclaration(elementA);
@@ -993,8 +1007,8 @@
   }
 
   void test_universe_removeSource() {
-    when(contextA.getElement(elementLocationA)).thenReturn(elementA);
-    when(contextB.getElement(elementLocationB)).thenReturn(elementB);
+    when(elementCodec.decode(contextA, 11, 12, 13)).thenReturn(elementA);
+    when(elementCodec.decode(contextB, 21, 22, 23)).thenReturn(elementB);
     {
       store.aboutToIndexDart(contextA, unitElementA);
       store.recordTopLevelDeclaration(elementA);
diff --git a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
index bec57bd..68ec6ec 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
@@ -384,7 +384,31 @@
     return _assertFinalConditionsError("Parameter 'dup' already exists");
   }
 
-  test_bad_parameterName_inUse() async {
+  test_bad_parameterName_inUse_function() async {
+    indexTestUnit('''
+main() {
+  int v1 = 1;
+  int v2 = 2;
+// start
+  f(v1, v2);
+// end
+}
+f(a, b) {}
+''');
+    _createRefactoringForStartEndComments();
+    // update parameters
+    await refactoring.checkInitialConditions();
+    {
+      List<RefactoringMethodParameter> parameters = _getParametersCopy();
+      expect(parameters, hasLength(2));
+      parameters[0].name = 'f';
+      refactoring.parameters = parameters;
+    }
+    return _assertFinalConditionsError(
+        "'f' is already used as a name in the selected code");
+  }
+
+  test_bad_parameterName_inUse_localVariable() async {
     indexTestUnit('''
 main() {
   int v1 = 1;
@@ -407,6 +431,32 @@
         "'a' is already used as a name in the selected code");
   }
 
+  test_bad_parameterName_inUse_method() async {
+    indexTestUnit('''
+class A {
+  main() {
+    int v1 = 1;
+    int v2 = 2;
+  // start
+    m(v1, v2);
+  // end
+  }
+  m(a, b) {}
+}
+''');
+    _createRefactoringForStartEndComments();
+    // update parameters
+    await refactoring.checkInitialConditions();
+    {
+      List<RefactoringMethodParameter> parameters = _getParametersCopy();
+      expect(parameters, hasLength(2));
+      parameters[0].name = 'm';
+      refactoring.parameters = parameters;
+    }
+    return _assertFinalConditionsError(
+        "'m' is already used as a name in the selected code");
+  }
+
   test_bad_selectionEndsInSomeNode() {
     indexTestUnit('''
 main() {
@@ -1137,6 +1187,29 @@
 ''');
   }
 
+  test_singleExpression_hasAwait() {
+    indexTestUnit('''
+import 'dart:async';
+Future<int> getValue() => 42;
+main() async {
+  int v = await getValue();
+  print(v);
+}
+''');
+    _createRefactoringForString('await getValue()');
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+import 'dart:async';
+Future<int> getValue() => 42;
+main() async {
+  int v = await res();
+  print(v);
+}
+
+Future<int> res() async => await getValue();
+''');
+  }
+
   test_singleExpression_ignore_assignmentLeftHandSize() {
     indexTestUnit('''
 main() {
@@ -2091,6 +2164,133 @@
     await assertRefactoringConditionsOK();
   }
 
+  test_statements_hasAwait_dynamicReturnType() {
+    indexTestUnit('''
+import 'dart:async';
+Future getValue() => 42;
+main() async {
+// start
+  var v = await getValue();
+// end
+  print(v);
+}
+''');
+    _createRefactoringForStartEndComments();
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+import 'dart:async';
+Future getValue() => 42;
+main() async {
+// start
+  var v = await res();
+// end
+  print(v);
+}
+
+Future res() async {
+  var v = await getValue();
+  return v;
+}
+''');
+  }
+
+  test_statements_hasAwait_expression() {
+    indexTestUnit('''
+import 'dart:async';
+Future<int> getValue() => 42;
+main() async {
+// start
+  int v = await getValue();
+  v += 2;
+// end
+  print(v);
+}
+''');
+    _createRefactoringForStartEndComments();
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+import 'dart:async';
+Future<int> getValue() => 42;
+main() async {
+// start
+  int v = await res();
+// end
+  print(v);
+}
+
+Future<int> res() async {
+  int v = await getValue();
+  v += 2;
+  return v;
+}
+''');
+  }
+
+  test_statements_hasAwait_forEach() {
+    indexTestUnit('''
+import 'dart:async';
+Stream<int> getValueStream() => null;
+main() async {
+// start
+  int sum = 0;
+  await for (int v in getValueStream()) {
+    sum += v;
+  }
+// end
+  print(sum);
+}
+''');
+    _createRefactoringForStartEndComments();
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+import 'dart:async';
+Stream<int> getValueStream() => null;
+main() async {
+// start
+  int sum = await res();
+// end
+  print(sum);
+}
+
+Future<int> res() async {
+  int sum = 0;
+  await for (int v in getValueStream()) {
+    sum += v;
+  }
+  return sum;
+}
+''');
+  }
+
+  test_statements_hasAwait_voidReturnType() {
+    indexTestUnit('''
+import 'dart:async';
+Future<int> getValue() => 42;
+main() async {
+// start
+  int v = await getValue();
+  print(v);
+// end
+}
+''');
+    _createRefactoringForStartEndComments();
+    // apply refactoring
+    return _assertSuccessfulRefactoring('''
+import 'dart:async';
+Future<int> getValue() => 42;
+main() async {
+// start
+  await res();
+// end
+}
+
+Future res() async {
+  int v = await getValue();
+  print(v);
+}
+''');
+  }
+
   test_statements_inSwitchMember() {
     indexTestUnit('''
 class A {
@@ -2213,6 +2413,24 @@
 ''');
   }
 
+  test_statements_parameters_noLocalVariableConflict() async {
+    indexTestUnit('''
+int f(int x) {
+  int y = x + 1;
+// start
+  if (y % 2 == 0) {
+    int y = x + 2;
+    return y;
+  } else {
+    return y;
+  }
+// end
+}
+''');
+    _createRefactoringForStartEndComments();
+    await assertRefactoringConditionsOK();
+  }
+
   test_statements_return_last() {
     indexTestUnit('''
 main() {
diff --git a/pkg/analysis_server/test/services/refactoring/inline_local_test.dart b/pkg/analysis_server/test/services/refactoring/inline_local_test.dart
index 8e8b6ab..2a3c104 100644
--- a/pkg/analysis_server/test/services/refactoring/inline_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/inline_local_test.dart
@@ -257,6 +257,29 @@
 ''');
   }
 
+  test_OK_intoStringInterpolation_string_multiLineIntoMulti_leadingSpaces() {
+    indexTestUnit(r"""
+main() {
+  String a = '''\ \
+a
+a''';
+  String b = '''
+$a
+bbb''';
+}
+""");
+    _createRefactoring('a =');
+    // validate change
+    return assertSuccessfulRefactoring(r"""
+main() {
+  String b = '''
+a
+a
+bbb''';
+}
+""");
+  }
+
   test_OK_intoStringInterpolation_string_multiLineIntoMulti_unixEOL() {
     indexTestUnit(r"""
 main() {
@@ -511,6 +534,42 @@
 ''');
   }
 
+  test_OK_parenthesis_intoIndexExpression_index() {
+    indexTestUnit('''
+main() {
+  var items = [];
+  var test = 1 + 2;
+  items[test] * 5;
+}
+''');
+    _createRefactoring('test =');
+    // validate change
+    return assertSuccessfulRefactoring('''
+main() {
+  var items = [];
+  items[1 + 2] * 5;
+}
+''');
+  }
+
+  test_OK_parenthesis_intoParenthesizedExpression() {
+    indexTestUnit('''
+f(m, x, y) {
+  int test = x as int;
+  m[test] = y;
+  return m[test];
+}
+''');
+    _createRefactoring('test =');
+    // validate change
+    return assertSuccessfulRefactoring('''
+f(m, x, y) {
+  m[x as int] = y;
+  return m[x as int];
+}
+''');
+  }
+
   test_OK_parenthesis_negate_intoNegate() {
     indexTestUnit('''
 main() {
diff --git a/pkg/analysis_server/test/services/refactoring/rename_import_test.dart b/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
index b2a54c6..fdf4be9 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
@@ -66,6 +66,50 @@
 ''');
   }
 
+  test_createChange_add_interpolationExpression_hasCurlyBrackets() {
+    indexTestUnit(r'''
+import 'dart:async';
+main() {
+  Future f;
+  print('Future type: ${Future}');
+}
+''');
+    // configure refactoring
+    _createRefactoring("import 'dart:async");
+    expect(refactoring.refactoringName, 'Rename Import Prefix');
+    refactoring.newName = 'newName';
+    // validate change
+    return assertSuccessfulRefactoring(r'''
+import 'dart:async' as newName;
+main() {
+  newName.Future f;
+  print('Future type: ${newName.Future}');
+}
+''');
+  }
+
+  test_createChange_add_interpolationExpression_noCurlyBrackets() {
+    indexTestUnit(r'''
+import 'dart:async';
+main() {
+  Future f;
+  print('Future type: $Future');
+}
+''');
+    // configure refactoring
+    _createRefactoring("import 'dart:async");
+    expect(refactoring.refactoringName, 'Rename Import Prefix');
+    refactoring.newName = 'newName';
+    // validate change
+    return assertSuccessfulRefactoring(r'''
+import 'dart:async' as newName;
+main() {
+  newName.Future f;
+  print('Future type: ${newName.Future}');
+}
+''');
+  }
+
   test_createChange_change_className() {
     indexTestUnit('''
 import 'dart:math' as test;
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index fa512df..87c9949 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -1,4 +1,3 @@
-
 <html>
   <head>
     <meta charset="UTF-8"/>
@@ -6,7 +5,7 @@
   </head>
   <body>
     <h1>Analysis Server API Specification</h1>
-    <h1 style="color:#999999">Version <version>1.5.0</version></h1>
+    <h1 style="color:#999999">Version <version>1.6.0</version></h1>
     <p>
       This document contains a specification of the API provided by the
       analysis server.  The API in this document is currently under
@@ -1935,7 +1934,7 @@
         <object>
           <field name="enableAsync" optional="true">
             <ref>bool</ref>
-            <p><b><i>Deprecated</i></b>/<p>
+            <p><b><i>Deprecated</i></b></p>
             <p>
               True if the client wants to enable support for the
               proposed async feature.
@@ -1943,7 +1942,7 @@
           </field>
           <field name="enableDeferredLoading" optional="true">
             <ref>bool</ref>
-            <p><b><i>Deprecated</i></b>/<p>
+            <p><b><i>Deprecated</i></b></p>
             <p>
               True if the client wants to enable support for the
               proposed deferred loading feature.
@@ -1951,12 +1950,19 @@
           </field>
           <field name="enableEnums" optional="true">
             <ref>bool</ref>
-            <p><b><i>Deprecated</i></b>/<p>
+            <p><b><i>Deprecated</i></b></p>
             <p>
               True if the client wants to enable support for the
               proposed enum feature.
             </p>
           </field>
+          <field name="enableNullAwareOperators" optional="true">
+            <ref>bool</ref>
+            <p>
+              True if the client wants to enable support for the
+              proposed "null aware operators" feature.
+            </p>
+          </field>
           <field name="generateDart2jsHints" optional="true">
             <ref>bool</ref>
             <p>
@@ -3127,6 +3133,13 @@
             </p>
           </value>
           <value>
+            <code>INVALID_ANALYSIS_ROOT</code>
+            <p>
+              A path passed as an argument to a request (such as
+              analysis.reanalyze) is required to be an analysis root, but isn't.
+            </p>
+          </value>
+          <value>
             <code>INVALID_EXECUTION_CONTEXT</code>
             <p>
               The context root used to create an execution context does not
@@ -3223,6 +3236,13 @@
             </p>
           </value>
           <value>
+            <code>UNKNOWN_SOURCE</code>
+            <p>
+              The analysis server was requested to perform an action
+              on a source that does not exist.
+            </p>
+          </value>
+          <value>
             <code>UNSUPPORTED_FEATURE</code>
             <p>
               The analysis server was requested to perform an action
diff --git a/pkg/analyzer/lib/options.dart b/pkg/analyzer/lib/options.dart
index 1f7543e..06aaa84 100644
--- a/pkg/analyzer/lib/options.dart
+++ b/pkg/analyzer/lib/options.dart
@@ -27,6 +27,11 @@
   final bool displayVersion;
 
   /**
+   * Whether to enable null-aware operators (DEP 9).
+   */
+  final bool enableNullAwareOperators;
+
+  /**
    * Whether to strictly follow the specification when generating warnings on
    * "call" methods (fixes dartbug.com/21938).
    */
@@ -86,6 +91,7 @@
         this.definedVariables = definedVariables,
         disableHints = args['no-hints'],
         displayVersion = args['version'],
+        enableNullAwareOperators = args['enable-null-aware-operators'],
         enableStrictCallChecks = args['enable-strict-call-checks'],
         enableTypeChecks = args['enable_type_checks'],
         ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
@@ -213,6 +219,11 @@
           defaultsTo: false,
           negatable: false,
           hide: true)
+      ..addFlag('enable-null-aware-operators',
+          help: 'Enable support for null-aware operators (DEP 9)',
+          defaultsTo: false,
+          negatable: false,
+          hide: true)
       ..addFlag('enable-strict-call-checks',
           help: 'Fix issue 21938',
           defaultsTo: false,
diff --git a/pkg/analyzer/lib/src/analyzer_impl.dart b/pkg/analyzer/lib/src/analyzer_impl.dart
index 173d18a..1ecfd83 100644
--- a/pkg/analyzer/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer/lib/src/analyzer_impl.dart
@@ -211,6 +211,7 @@
     AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
     contextOptions.cacheSize = _MAX_CACHE_SIZE;
     contextOptions.hint = !options.disableHints;
+    contextOptions.enableNullAwareOperators = options.enableNullAwareOperators;
     contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
     contextOptions.analyzeFunctionBodiesPredicate =
         _analyzeFunctionBodiesPredicate;
diff --git a/pkg/analyzer/lib/src/generated/ast.dart b/pkg/analyzer/lib/src/generated/ast.dart
index f202e83..909400d 100644
--- a/pkg/analyzer/lib/src/generated/ast.dart
+++ b/pkg/analyzer/lib/src/generated/ast.dart
@@ -497,7 +497,7 @@
    * then return the parameter element representing the parameter to which the
    * value of the given expression will be bound. Otherwise, return `null`.
    */
-  @deprecated // Use "expression.propagatedParameterElement"
+  @deprecated // Use "expression.staticParameterElement"
   ParameterElement getStaticParameterElementFor(Expression expression) {
     return _getStaticParameterElementFor(expression);
   }
@@ -865,7 +865,7 @@
    * representing the parameter to which the value of the right operand will be
    * bound. Otherwise, return `null`.
    */
-  @deprecated // Use "expression.propagatedParameterElement"
+  @deprecated // Use "expression.staticParameterElement"
   ParameterElement get staticParameterElementForRightHandSide {
     return _staticParameterElementForRightHandSide;
   }
@@ -1432,7 +1432,7 @@
 
   @override
   MethodInvocation visitMethodInvocation(MethodInvocation node) =>
-      new MethodInvocation(cloneNode(node.target), cloneToken(node.period),
+      new MethodInvocation(cloneNode(node.target), cloneToken(node.operator),
           cloneNode(node.methodName), cloneNode(node.argumentList));
 
   @override
@@ -2323,7 +2323,7 @@
   bool visitMethodInvocation(MethodInvocation node) {
     MethodInvocation other = _other as MethodInvocation;
     return isEqualNodes(node.target, other.target) &&
-        isEqualTokens(node.period, other.period) &&
+        isEqualTokens(node.operator, other.operator) &&
         isEqualNodes(node.methodName, other.methodName) &&
         isEqualNodes(node.argumentList, other.argumentList);
   }
@@ -3344,7 +3344,7 @@
    * representing the parameter to which the value of the right operand will be
    * bound. Otherwise, return `null`.
    */
-  @deprecated // Use "expression.propagatedParameterElement"
+  @deprecated // Use "expression.staticParameterElement"
   ParameterElement get staticParameterElementForRightOperand {
     return _staticParameterElementForRightOperand;
   }
@@ -3995,7 +3995,7 @@
  * >     [ImplementsClause]?
  * >     '{' [ClassMember]* '}'
  */
-class ClassDeclaration extends CompilationUnitMember {
+class ClassDeclaration extends NamedCompilationUnitMember {
   /**
    * The 'abstract' keyword, or `null` if the keyword was absent.
    */
@@ -4007,11 +4007,6 @@
   Token classKeyword;
 
   /**
-   * The name of the class being declared.
-   */
-  SimpleIdentifier _name;
-
-  /**
    * The type parameters for the class, or `null` if the class does not have any
    * type parameters.
    */
@@ -4071,8 +4066,7 @@
       TypeParameterList typeParameters, ExtendsClause extendsClause,
       WithClause withClause, ImplementsClause implementsClause,
       this.leftBracket, List<ClassMember> members, this.rightBracket)
-      : super(comment, metadata) {
-    _name = _becomeParentOf(name);
+      : super(comment, metadata, name) {
     _typeParameters = _becomeParentOf(typeParameters);
     _extendsClause = _becomeParentOf(extendsClause);
     _withClause = _becomeParentOf(withClause);
@@ -4146,18 +4140,6 @@
   NodeList<ClassMember> get members => _members;
 
   /**
-   * Return the name of the class being declared.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the class being declared to the given [identifier].
-   */
-  void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-
-  /**
    * Return the native clause for this class, or `null` if the class does not
    * have a native clause.
    */
@@ -4295,11 +4277,6 @@
  */
 class ClassTypeAlias extends TypeAlias {
   /**
-   * The name of the class being declared.
-   */
-  SimpleIdentifier _name;
-
-  /**
    * The type parameters for the class, or `null` if the class does not have any
    * type parameters.
    */
@@ -4344,8 +4321,7 @@
       SimpleIdentifier name, TypeParameterList typeParameters, this.equals,
       this.abstractKeyword, TypeName superclass, WithClause withClause,
       ImplementsClause implementsClause, Token semicolon)
-      : super(comment, metadata, keyword, semicolon) {
-    _name = _becomeParentOf(name);
+      : super(comment, metadata, keyword, name, semicolon) {
     _typeParameters = _becomeParentOf(typeParameters);
     _superclass = _becomeParentOf(superclass);
     _withClause = _becomeParentOf(withClause);
@@ -4387,18 +4363,6 @@
   bool get isAbstract => abstractKeyword != null;
 
   /**
-   * Return the name of the class being declared.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the class being declared to the given [identifier].
-   */
-  void set name(SimpleIdentifier name) {
-    _name = _becomeParentOf(name);
-  }
-
-  /**
    * Return the name of the superclass of the class being declared.
    */
   TypeName get superclass => _superclass;
@@ -4843,7 +4807,8 @@
 }
 
 /**
- * A node that declares a name within the scope of a compilation unit.
+ * A node that declares one or more names within the scope of a compilation
+ * unit.
  *
  * > compilationUnitMember ::=
  * >     [ClassDeclaration]
@@ -5061,9 +5026,7 @@
         // numeric, string, boolean, or {@code null}
         if (leftOperand is bool && rightOperand is bool) {
           return leftOperand != rightOperand;
-        } else if (leftOperand is int && rightOperand is int) {
-          return leftOperand != rightOperand;
-        } else if (leftOperand is double && rightOperand is double) {
+        } else if (leftOperand is num && rightOperand is num) {
           return leftOperand != rightOperand;
         } else if (leftOperand is String && rightOperand is String) {
           return leftOperand != rightOperand;
@@ -5087,25 +5050,19 @@
         // numeric, string, boolean, or {@code null}
         if (leftOperand is bool && rightOperand is bool) {
           return leftOperand == rightOperand;
-        } else if (leftOperand is int && rightOperand is int) {
-          return leftOperand == rightOperand;
-        } else if (leftOperand is double && rightOperand is double) {
+        } else if (leftOperand is num && rightOperand is num) {
           return leftOperand == rightOperand;
         } else if (leftOperand is String && rightOperand is String) {
           return leftOperand == rightOperand;
         }
       } else if (node.operator.type == TokenType.GT) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand.compareTo(rightOperand) > 0;
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand.compareTo(rightOperand) > 0;
         }
       } else if (node.operator.type == TokenType.GT_EQ) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand.compareTo(rightOperand) >= 0;
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand.compareTo(rightOperand) >= 0;
         }
       } else if (node.operator.type == TokenType.GT_GT) {
@@ -5115,16 +5072,12 @@
         }
       } else if (node.operator.type == TokenType.LT) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand.compareTo(rightOperand) < 0;
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand.compareTo(rightOperand) < 0;
         }
       } else if (node.operator.type == TokenType.LT_EQ) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand.compareTo(rightOperand) <= 0;
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand.compareTo(rightOperand) <= 0;
         }
       } else if (node.operator.type == TokenType.LT_LT) {
@@ -5134,52 +5087,32 @@
         }
       } else if (node.operator.type == TokenType.MINUS) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand - rightOperand;
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand - rightOperand;
         }
       } else if (node.operator.type == TokenType.PERCENT) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand.remainder(rightOperand);
-        } else if (leftOperand is double && rightOperand is double) {
-          return leftOperand % rightOperand;
         }
       } else if (node.operator.type == TokenType.PLUS) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand + rightOperand;
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand + rightOperand;
         }
       } else if (node.operator.type == TokenType.STAR) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand * rightOperand;
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand * rightOperand;
         }
       } else if (node.operator.type == TokenType.SLASH) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          if (rightOperand != 0) {
-            return leftOperand ~/ rightOperand;
-          } else {
-            return leftOperand.toDouble() / rightOperand.toDouble();
-          }
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand / rightOperand;
         }
       } else if (node.operator.type == TokenType.TILDE_SLASH) {
         // numeric or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          if (rightOperand != 0) {
-            return leftOperand ~/ rightOperand;
-          } else {
-            return 0;
-          }
-        } else if (leftOperand is double && rightOperand is double) {
+        if (leftOperand is num && rightOperand is num) {
           return leftOperand ~/ rightOperand;
         }
       } else {}
@@ -5201,11 +5134,7 @@
   @override
   Object visitInterpolationExpression(InterpolationExpression node) {
     Object value = node.expression.accept(this);
-    if (value == null ||
-        value is bool ||
-        value is String ||
-        value is int ||
-        value is double) {
+    if (value == null || value is bool || value is String || value is num) {
       return value;
     }
     return NOT_A_CONSTANT;
@@ -5278,9 +5207,7 @@
       } else if (node.operator.type == TokenType.MINUS) {
         if (operand == null) {
           return null;
-        } else if (operand is int) {
-          return -operand;
-        } else if (operand is double) {
+        } else if (operand is num) {
           return -operand;
         }
       } else {}
@@ -5347,6 +5274,18 @@
 }
 
 /**
+ * Object representing a "const" instance creation expression, and its
+ * evaluation result.  This is used as the AnalysisTarget for constant
+ * evaluation of instance creation expressions.
+ */
+class ConstantInstanceCreationHandle {
+  /**
+   * The result of evaluating the constant.
+   */
+  EvaluationResultImpl evaluationResult;
+}
+
+/**
  * A constructor declaration.
  *
  * > constructorDeclaration ::=
@@ -5897,8 +5836,8 @@
 }
 
 /**
- * A node that represents the declaration of a name. Each declared name is
- * visible within a name scope.
+ * A node that represents the declaration of one or more names. Each declared
+ * name is visible within a name scope.
  */
 abstract class Declaration extends AnnotatedNode {
   /**
@@ -6626,18 +6565,13 @@
  * > enumType ::=
  * >     metadata 'enum' [SimpleIdentifier] '{' [SimpleIdentifier] (',' [SimpleIdentifier])* (',')? '}'
  */
-class EnumDeclaration extends CompilationUnitMember {
+class EnumDeclaration extends NamedCompilationUnitMember {
   /**
    * The 'enum' keyword.
    */
   Token enumKeyword;
 
   /**
-   * The name of the enumeration.
-   */
-  SimpleIdentifier _name;
-
-  /**
    * The left curly bracket.
    */
   Token leftBracket;
@@ -6661,8 +6595,7 @@
   EnumDeclaration(Comment comment, List<Annotation> metadata, this.enumKeyword,
       SimpleIdentifier name, this.leftBracket,
       List<EnumConstantDeclaration> constants, this.rightBracket)
-      : super(comment, metadata) {
-    _name = _becomeParentOf(name);
+      : super(comment, metadata, name) {
     _constants = new NodeList<EnumConstantDeclaration>(this, constants);
   }
 
@@ -6705,18 +6638,6 @@
     enumKeyword = token;
   }
 
-  /**
-   * Return the name of the enumeration.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the enumeration to the given [name].
-   */
-  void set name(SimpleIdentifier name) {
-    _name = _becomeParentOf(name);
-  }
-
   @override
   accept(AstVisitor visitor) => visitor.visitEnumDeclaration(this);
 
@@ -7932,7 +7853,7 @@
  * > functionSignature ::=
  * >     [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList]
  */
-class FunctionDeclaration extends CompilationUnitMember {
+class FunctionDeclaration extends NamedCompilationUnitMember {
   /**
    * The token representing the 'external' keyword, or `null` if this is not an
    * external function.
@@ -7951,11 +7872,6 @@
   Token propertyKeyword;
 
   /**
-   * The name of the function, or `null` if the function is not named.
-   */
-  SimpleIdentifier _name;
-
-  /**
    * The function expression being wrapped.
    */
   FunctionExpression _functionExpression;
@@ -7971,9 +7887,8 @@
   FunctionDeclaration(Comment comment, List<Annotation> metadata,
       this.externalKeyword, TypeName returnType, this.propertyKeyword,
       SimpleIdentifier name, FunctionExpression functionExpression)
-      : super(comment, metadata) {
+      : super(comment, metadata, name) {
     _returnType = _becomeParentOf(returnType);
-    _name = _becomeParentOf(name);
     _functionExpression = _becomeParentOf(functionExpression);
   }
 
@@ -8032,18 +7947,6 @@
       (propertyKeyword as KeywordToken).keyword == Keyword.SET;
 
   /**
-   * Return the name of the function, or `null` if the function is not named.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the function to the given [identifier].
-   */
-  void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-
-  /**
    * Return the return type of the function, or `null` if no return type was
    * declared.
    */
@@ -8336,11 +8239,6 @@
   TypeName _returnType;
 
   /**
-   * The name of the function type being declared.
-   */
-  SimpleIdentifier _name;
-
-  /**
    * The type parameters for the function type, or `null` if the function type
    * does not have any type parameters.
    */
@@ -8362,9 +8260,8 @@
       TypeName returnType, SimpleIdentifier name,
       TypeParameterList typeParameters, FormalParameterList parameters,
       Token semicolon)
-      : super(comment, metadata, keyword, semicolon) {
+      : super(comment, metadata, keyword, name, semicolon) {
     _returnType = _becomeParentOf(returnType);
-    _name = _becomeParentOf(name);
     _typeParameters = _becomeParentOf(typeParameters);
     _parameters = _becomeParentOf(parameters);
   }
@@ -8383,18 +8280,6 @@
       _name != null ? (_name.staticElement as FunctionTypeAliasElement) : null;
 
   /**
-   * Return the name of the function type being declared.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the function type being declared to the given [name].
-   */
-  void set name(SimpleIdentifier name) {
-    _name = _becomeParentOf(name);
-  }
-
-  /**
    * Return the parameters associated with the function type.
    */
   FormalParameterList get parameters => _parameters;
@@ -8606,7 +8491,7 @@
 
   @override
   R visitClassDeclaration(ClassDeclaration node) =>
-      visitCompilationUnitMember(node);
+      visitNamedCompilationUnitMember(node);
 
   R visitClassMember(ClassMember node) => visitDeclaration(node);
 
@@ -8676,7 +8561,7 @@
 
   @override
   R visitEnumDeclaration(EnumDeclaration node) =>
-      visitCompilationUnitMember(node);
+      visitNamedCompilationUnitMember(node);
 
   @override
   R visitExportDirective(ExportDirective node) => visitNamespaceDirective(node);
@@ -8715,7 +8600,7 @@
 
   @override
   R visitFunctionDeclaration(FunctionDeclaration node) =>
-      visitCompilationUnitMember(node);
+      visitNamedCompilationUnitMember(node);
 
   @override
   R visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
@@ -8801,6 +8686,9 @@
   @override
   R visitMethodInvocation(MethodInvocation node) => visitExpression(node);
 
+  R visitNamedCompilationUnitMember(NamedCompilationUnitMember node) =>
+      visitCompilationUnitMember(node);
+
   @override
   R visitNamedExpression(NamedExpression node) => visitExpression(node);
 
@@ -8919,7 +8807,7 @@
   @override
   R visitTryStatement(TryStatement node) => visitStatement(node);
 
-  R visitTypeAlias(TypeAlias node) => visitCompilationUnitMember(node);
+  R visitTypeAlias(TypeAlias node) => visitNamedCompilationUnitMember(node);
 
   @override
   R visitTypeArgumentList(TypeArgumentList node) => visitNode(node);
@@ -10007,7 +9895,7 @@
   @override
   MethodInvocation visitMethodInvocation(MethodInvocation node) {
     MethodInvocation copy = new MethodInvocation(_cloneNode(node.target),
-        _mapToken(node.period), _cloneNode(node.methodName),
+        _mapToken(node.operator), _cloneNode(node.methodName),
         _cloneNode(node.argumentList));
     copy.propagatedType = node.propagatedType;
     copy.staticType = node.staticType;
@@ -10663,9 +10551,10 @@
   ConstructorElement staticElement;
 
   /**
-   * The result of evaluating this expression, if it is constant.
+   * The [ConstantInstanceCreationHandle] holding the result of evaluating this
+   * expression, if it is constant.
    */
-  EvaluationResultImpl evaluationResult;
+  ConstantInstanceCreationHandle constantHandle;
 
   /**
    * Initialize a newly created instance creation expression.
@@ -10713,6 +10602,16 @@
   Token get endToken => _argumentList.endToken;
 
   /**
+   * The result of evaluating this expression, if it is constant.
+   */
+  EvaluationResultImpl get evaluationResult {
+    if (constantHandle != null) {
+      return constantHandle.evaluationResult;
+    }
+    return null;
+  }
+
+  /**
    * Return `true` if this creation expression is used to invoke a constant
    * constructor.
    */
@@ -10898,15 +10797,8 @@
    * Return the offset of the after-last contents character.
    */
   int get contentsEnd {
-    int end = contents.end;
     String lexeme = contents.lexeme;
-    if (StringUtilities.endsWith3(lexeme, 0x22, 0x22, 0x22) ||
-        StringUtilities.endsWith3(lexeme, 0x27, 0x27, 0x27)) {
-      end -= 3;
-    } else {
-      end -= 1;
-    }
-    return end;
+    return offset + new StringLexemeHelper(lexeme, true, true).end;
   }
 
   /**
@@ -10915,16 +10807,7 @@
   int get contentsOffset {
     int offset = contents.offset;
     String lexeme = contents.lexeme;
-    if (lexeme.codeUnitAt(0) == 0x72) {
-      offset += 1;
-    }
-    if (StringUtilities.startsWith3(lexeme, offset, 0x22, 0x22, 0x22) ||
-        StringUtilities.startsWith3(lexeme, offset, 0x27, 0x27, 0x27)) {
-      offset += 3;
-    } else {
-      offset += 1;
-    }
-    return offset;
+    return offset + new StringLexemeHelper(lexeme, true, true).start;
   }
 
   @override
@@ -11798,10 +11681,12 @@
   Expression _target;
 
   /**
-   * The period that separates the target from the method name, or `null` if
-   * there is no target.
+   * The operator that separates the target from the method name, or `null`
+   * if there is no target. In an ordinary method invocation this will be a
+   * period ('.'). In a cascade section this will be the cascade operator
+   * ('..').
    */
-  Token period;
+  Token operator;
 
   /**
    * The name of the method being invoked.
@@ -11814,11 +11699,11 @@
   ArgumentList _argumentList;
 
   /**
-   * Initialize a newly created method invocation. The [target] and [period] can
-   * be `null` if there is no target.
+   * Initialize a newly created method invocation. The [target] and [operator]
+   * can be `null` if there is no target.
    */
-  MethodInvocation(Expression target, this.period, SimpleIdentifier methodName,
-      ArgumentList argumentList) {
+  MethodInvocation(Expression target, this.operator,
+      SimpleIdentifier methodName, ArgumentList argumentList) {
     _target = _becomeParentOf(target);
     _methodName = _becomeParentOf(methodName);
     _argumentList = _becomeParentOf(argumentList);
@@ -11840,8 +11725,8 @@
   Token get beginToken {
     if (_target != null) {
       return _target.beginToken;
-    } else if (period != null) {
-      return period;
+    } else if (operator != null) {
+      return operator;
     }
     return _methodName.beginToken;
   }
@@ -11849,7 +11734,7 @@
   @override
   Iterable get childEntities => new ChildEntities()
     ..add(_target)
-    ..add(period)
+    ..add(operator)
     ..add(_methodName)
     ..add(_argumentList);
 
@@ -11862,7 +11747,7 @@
    * that is a [CascadeExpression].
    */
   bool get isCascaded =>
-      period != null && period.type == TokenType.PERIOD_PERIOD;
+      operator != null && operator.type == TokenType.PERIOD_PERIOD;
 
   /**
    * Return the name of the method being invoked.
@@ -11876,6 +11761,30 @@
     _methodName = _becomeParentOf(identifier);
   }
 
+  /**
+   * The operator that separates the target from the method name, or `null`
+   * if there is no target. In an ordinary method invocation this will be a
+   * period ('.'). In a cascade section this will be the cascade operator
+   * ('..').
+   *
+   * Deprecated: use [operator] instead.
+   */
+  @deprecated
+  Token get period => operator;
+
+  /**
+   * The operator that separates the target from the method name, or `null`
+   * if there is no target. In an ordinary method invocation this will be a
+   * period ('.'). In a cascade section this will be the cascade operator
+   * ('..').
+   *
+   * Deprecated: use [operator] instead.
+   */
+  @deprecated
+  void set period(Token value) {
+    operator = value;
+  }
+
   @override
   int get precedence => 15;
 
@@ -11929,6 +11838,39 @@
 }
 
 /**
+ * A node that declares a single name within the scope of a compilation unit.
+ */
+abstract class NamedCompilationUnitMember extends CompilationUnitMember {
+  /**
+   * The name of the member being declared.
+   */
+  SimpleIdentifier _name;
+
+  /**
+   * Initialize a newly created compilation unit member with the given [name].
+   * Either or both of the [comment] and [metadata] can be `null` if the member
+   * does not have the corresponding attribute.
+   */
+  NamedCompilationUnitMember(
+      Comment comment, List<Annotation> metadata, SimpleIdentifier name)
+      : super(comment, metadata) {
+    _name = _becomeParentOf(name);
+  }
+
+  /**
+   * Return the name of the member being declared.
+   */
+  SimpleIdentifier get name => _name;
+
+  /**
+   * Set the name of the member being declared to the given [identifier].
+   */
+  void set name(SimpleIdentifier identifier) {
+    _name = _becomeParentOf(identifier);
+  }
+}
+
+/**
  * An expression that has a name associated with it. They are used in method
  * invocations when there are named parameters.
  *
@@ -16505,58 +16447,22 @@
   Iterable get childEntities => new ChildEntities()..add(literal);
 
   @override
-  int get contentsEnd {
-    return contentsOffset + value.length;
-  }
+  int get contentsEnd => offset + _helper.end;
 
   @override
-  int get contentsOffset {
-    int contentsOffset = 0;
-    if (isRaw) {
-      contentsOffset += 1;
-    }
-    if (isMultiline) {
-      contentsOffset += 3;
-    } else {
-      contentsOffset += 1;
-    }
-    return offset + contentsOffset;
-  }
+  int get contentsOffset => offset + _helper.start;
 
   @override
   Token get endToken => literal;
 
   @override
-  bool get isMultiline {
-    String lexeme = literal.lexeme;
-    if (lexeme.length < 3) {
-      return false;
-    }
-    // skip 'r'
-    int offset = 0;
-    if (isRaw) {
-      offset = 1;
-    }
-    // check prefix
-    return StringUtilities.startsWith3(lexeme, offset, 0x22, 0x22, 0x22) ||
-        StringUtilities.startsWith3(lexeme, offset, 0x27, 0x27, 0x27);
-  }
+  bool get isMultiline => _helper.isMultiline;
 
   @override
-  bool get isRaw => literal.lexeme.codeUnitAt(0) == 0x72;
+  bool get isRaw => _helper.isRaw;
 
   @override
-  bool get isSingleQuoted {
-    String lexeme = literal.lexeme;
-    if (lexeme.isEmpty) {
-      return false;
-    }
-    int codeZero = lexeme.codeUnitAt(0);
-    if (codeZero == 0x72) {
-      return lexeme.length > 1 && lexeme.codeUnitAt(1) == 0x27;
-    }
-    return codeZero == 0x27;
-  }
+  bool get isSingleQuoted => _helper.isSingleQuoted;
 
   @override
   bool get isSynthetic => literal.isSynthetic;
@@ -16573,6 +16479,10 @@
     _value = StringUtilities.intern(_value);
   }
 
+  StringLexemeHelper get _helper {
+    return new StringLexemeHelper(literal.lexeme, true, true);
+  }
+
   @override
   accept(AstVisitor visitor) => visitor.visitSimpleStringLiteral(this);
 
@@ -16602,6 +16512,7 @@
 
   /**
    * Return the offset of the first contents character.
+   * If the string is multiline, then leading whitespaces are skipped.
    */
   int get contentsOffset;
 
@@ -16696,24 +16607,18 @@
   Token get endToken => _elements.endToken;
 
   @override
-  bool get isMultiline {
-    InterpolationString element = _elements.first;
-    String lexeme = element.contents.lexeme;
-    if (lexeme.length < 3) {
-      return false;
-    }
-    return StringUtilities.startsWith3(lexeme, 0, 0x22, 0x22, 0x22) ||
-        StringUtilities.startsWith3(lexeme, 0, 0x27, 0x27, 0x27);
-  }
+  bool get isMultiline => _firstHelper.isMultiline;
 
   @override
   bool get isRaw => false;
 
   @override
-  bool get isSingleQuoted {
+  bool get isSingleQuoted => _firstHelper.isSingleQuoted;
+
+  StringLexemeHelper get _firstHelper {
     InterpolationString lastString = _elements.first;
     String lexeme = lastString.contents.lexeme;
-    return StringUtilities.startsWithChar(lexeme, 0x27);
+    return new StringLexemeHelper(lexeme, true, false);
   }
 
   @override
@@ -16731,6 +16636,101 @@
 }
 
 /**
+ * A helper for analyzing string lexemes.
+ */
+class StringLexemeHelper {
+  final String lexeme;
+  final bool isFirst;
+  final bool isLast;
+
+  bool isRaw = false;
+  bool isSingleQuoted = false;
+  bool isMultiline = false;
+  int start = 0;
+  int end;
+
+  StringLexemeHelper(this.lexeme, this.isFirst, this.isLast) {
+    if (isFirst) {
+      isRaw = StringUtilities.startsWithChar(lexeme, 0x72);
+      if (isRaw) {
+        start++;
+      }
+      if (StringUtilities.startsWith3(lexeme, start, 0x27, 0x27, 0x27)) {
+        isSingleQuoted = true;
+        isMultiline = true;
+        start += 3;
+        start = _trimInitialWhitespace(start);
+      } else if (StringUtilities.startsWith3(lexeme, start, 0x22, 0x22, 0x22)) {
+        isSingleQuoted = false;
+        isMultiline = true;
+        start += 3;
+        start = _trimInitialWhitespace(start);
+      } else if (start < lexeme.length && lexeme.codeUnitAt(start) == 0x27) {
+        isSingleQuoted = true;
+        isMultiline = false;
+        start++;
+      } else if (start < lexeme.length && lexeme.codeUnitAt(start) == 0x22) {
+        isSingleQuoted = false;
+        isMultiline = false;
+        start++;
+      }
+    }
+    end = lexeme.length;
+    if (isLast) {
+      if (start + 3 <= end &&
+          (StringUtilities.endsWith3(lexeme, 0x22, 0x22, 0x22) ||
+              StringUtilities.endsWith3(lexeme, 0x27, 0x27, 0x27))) {
+        end -= 3;
+      } else if (start + 1 <= end &&
+          (StringUtilities.endsWithChar(lexeme, 0x22) ||
+              StringUtilities.endsWithChar(lexeme, 0x27))) {
+        end -= 1;
+      }
+    }
+  }
+
+  /**
+   * Given the [lexeme] for a multi-line string whose content begins at the
+   * given [start] index, return the index of the first character that is
+   * included in the value of the string. According to the specification:
+   *
+   * If the first line of a multiline string consists solely of the whitespace
+   * characters defined by the production WHITESPACE 20.1), possibly prefixed
+   * by \, then that line is ignored, including the new line at its end.
+   */
+  int _trimInitialWhitespace(int start) {
+    int length = lexeme.length;
+    int index = start;
+    while (index < length) {
+      int currentChar = lexeme.codeUnitAt(index);
+      if (currentChar == 0x0D) {
+        if (index + 1 < length && lexeme.codeUnitAt(index + 1) == 0x0A) {
+          return index + 2;
+        }
+        return index + 1;
+      } else if (currentChar == 0x0A) {
+        return index + 1;
+      } else if (currentChar == 0x5C) {
+        if (index + 1 >= length) {
+          return start;
+        }
+        currentChar = lexeme.codeUnitAt(index + 1);
+        if (currentChar != 0x0D &&
+            currentChar != 0x0A &&
+            currentChar != 0x09 &&
+            currentChar != 0x20) {
+          return start;
+        }
+      } else if (currentChar != 0x09 && currentChar != 0x20) {
+        return start;
+      }
+      index++;
+    }
+    return start;
+  }
+}
+
+/**
  * A string literal expression.
  *
  * > stringLiteral ::=
@@ -18105,7 +18105,10 @@
     if (node.isCascaded) {
       _writer.print("..");
     } else {
-      _visitNodeWithSuffix(node.target, ".");
+      if (node.target != null) {
+        node.target.accept(this);
+        _writer.print(node.operator.lexeme);
+      }
     }
     _visitNode(node.methodName);
     _visitNode(node.argumentList);
@@ -18194,7 +18197,7 @@
       _writer.print("..");
     } else {
       _visitNode(node.target);
-      _writer.print('.');
+      _writer.print(node.operator.lexeme);
     }
     _visitNode(node.propertyName);
     return null;
@@ -18672,7 +18675,7 @@
  * >     classTypeAlias
  * >   | functionTypeAlias
  */
-abstract class TypeAlias extends CompilationUnitMember {
+abstract class TypeAlias extends NamedCompilationUnitMember {
   /**
    * The token representing the 'typedef' keyword.
    */
@@ -18689,8 +18692,8 @@
    * attribute.
    */
   TypeAlias(Comment comment, List<Annotation> metadata, this.typedefKeyword,
-      this.semicolon)
-      : super(comment, metadata);
+      SimpleIdentifier name, this.semicolon)
+      : super(comment, metadata, name);
 
   @override
   Token get endToken => semicolon;
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index c5b413d..7c866c1 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -144,6 +144,48 @@
 }
 
 /**
+ * An [AstCloner] that copies the necessary information from the AST to allow
+ * constants to be evaluated.
+ */
+class ConstantAstCloner extends AstCloner {
+  ConstantAstCloner() : super(true);
+
+  @override
+  InstanceCreationExpression visitInstanceCreationExpression(
+      InstanceCreationExpression node) {
+    InstanceCreationExpression expression =
+        super.visitInstanceCreationExpression(node);
+    expression.constantHandle = node.constantHandle;
+    return expression;
+  }
+
+  @override
+  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    RedirectingConstructorInvocation invocation =
+        super.visitRedirectingConstructorInvocation(node);
+    invocation.staticElement = node.staticElement;
+    return invocation;
+  }
+
+  @override
+  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
+    SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
+    identifier.staticElement = node.staticElement;
+    return identifier;
+  }
+
+  @override
+  SuperConstructorInvocation visitSuperConstructorInvocation(
+      SuperConstructorInvocation node) {
+    SuperConstructorInvocation invocation =
+        super.visitSuperConstructorInvocation(node);
+    invocation.staticElement = node.staticElement;
+    return invocation;
+  }
+}
+
+/**
  * Instances of the class `ConstantEvaluator` evaluate constant expressions to
  * produce their compile-time value. According to the Dart Language
  * Specification:
@@ -240,8 +282,8 @@
    * A table mapping constant variable elements to the declarations of those
    * variables.
    */
-  final HashMap<VariableElement, VariableDeclaration> variableMap =
-      new HashMap<VariableElement, VariableDeclaration>();
+  final HashMap<PotentiallyConstVariableElement, VariableDeclaration> variableMap =
+      new HashMap<PotentiallyConstVariableElement, VariableDeclaration>();
 
   /**
    * A table mapping constant constructors to the declarations of those
@@ -294,9 +336,8 @@
     super.visitVariableDeclaration(node);
     Expression initializer = node.initializer;
     if (initializer != null && node.isConst) {
-      VariableElement element = node.element;
-      if (element != null) {
-        variableMap[element] = node;
+      if (node.element != null) {
+        variableMap[node.element as PotentiallyConstVariableElement] = node;
       }
     }
     return null;
@@ -365,7 +406,7 @@
   /**
    * A table mapping constant variables to the declarations of those variables.
    */
-  HashMap<VariableElement, VariableDeclaration> _variableDeclarationMap;
+  HashMap<PotentiallyConstVariableElement, VariableDeclaration> _variableDeclarationMap;
 
   /**
    * A table mapping constant constructors to the declarations of those
@@ -440,8 +481,19 @@
       referenceGraph.addNode(declaration);
       declaration.initializer.accept(referenceFinder);
     });
-    constructorDeclarationMap.forEach((ConstructorElement element,
+    constructorDeclarationMap.forEach((ConstructorElementImpl element,
         ConstructorDeclaration declaration) {
+      element.isCycleFree = false;
+      ConstructorElement redirectedConstructor =
+          _getConstRedirectedConstructor(element);
+      if (redirectedConstructor != null) {
+        ConstructorElement redirectedConstructorBase =
+            _getConstructorBase(redirectedConstructor);
+        ConstructorDeclaration redirectedConstructorDeclaration =
+            findConstructorDeclaration(redirectedConstructorBase);
+        referenceGraph.addEdge(declaration, redirectedConstructorDeclaration);
+        return;
+      }
       ReferenceFinder referenceFinder = new ReferenceFinder(declaration,
           referenceGraph, _variableDeclarationMap, constructorDeclarationMap);
       referenceGraph.addNode(declaration);
@@ -488,7 +540,6 @@
       if (constructor == null) {
         continue;
       }
-      constructor = _followConstantRedirectionChain(constructor);
       ConstructorDeclaration declaration =
           findConstructorDeclaration(constructor);
       // An instance creation expression depends both on the constructor and
@@ -600,18 +651,20 @@
   void _computeValueFor(AstNode constNode) {
     beforeComputeValue(constNode);
     if (constNode is VariableDeclaration) {
-      VariableDeclaration declaration = constNode;
-      VariableElement element = declaration.element;
+      VariableElement element = constNode.element;
       RecordingErrorListener errorListener = new RecordingErrorListener();
       ErrorReporter errorReporter =
           new ErrorReporter(errorListener, element.source);
       DartObjectImpl dartObject =
-          declaration.initializer.accept(createConstantVisitor(errorReporter));
+          (element as PotentiallyConstVariableElement).constantInitializer
+              .accept(createConstantVisitor(errorReporter));
       if (dartObject != null) {
         if (!_runtimeTypeMatch(dartObject, element.type)) {
-          errorReporter.reportErrorForNode(
-              CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
-              declaration, [dartObject.type, element.type]);
+          errorReporter.reportErrorForElement(
+              CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, element, [
+            dartObject.type,
+            element.type
+          ]);
         }
       }
       (element as VariableElementImpl).evaluationResult =
@@ -623,7 +676,8 @@
         // Couldn't resolve the constructor so we can't compute a value.
         // No problem - the error has already been reported.
         // But we still need to store an evaluation result.
-        expression.evaluationResult = new EvaluationResultImpl.con1(null);
+        expression.constantHandle.evaluationResult =
+            new EvaluationResultImpl.con1(null);
         return;
       }
       RecordingErrorListener errorListener = new RecordingErrorListener();
@@ -635,16 +689,17 @@
       DartObjectImpl result = _evaluateConstructorCall(constNode,
           expression.argumentList.arguments, constructor, constantVisitor,
           errorReporter);
-      expression.evaluationResult =
+      expression.constantHandle.evaluationResult =
           new EvaluationResultImpl.con2(result, errorListener.errors);
     } else if (constNode is ConstructorDeclaration) {
-      ConstructorDeclaration declaration = constNode;
-      NodeList<ConstructorInitializer> initializers = declaration.initializers;
-      ConstructorElementImpl constructor =
-          declaration.element as ConstructorElementImpl;
-      constructor.constantInitializers =
-          new ConstantValueComputer_InitializerCloner()
-              .cloneNodeList(initializers);
+      // 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.
+      ConstructorElementImpl constructor = constNode.element;
+      constructor.isCycleFree = true;
     } else if (constNode is FormalParameter) {
       if (constNode is DefaultFormalParameter) {
         DefaultFormalParameter parameter = constNode;
@@ -742,6 +797,14 @@
   DartObjectImpl _evaluateConstructorCall(AstNode node,
       NodeList<Expression> arguments, ConstructorElement constructor,
       ConstantVisitor constantVisitor, ErrorReporter errorReporter) {
+    if (!_getConstructorBase(constructor).isCycleFree) {
+      // It's not safe to evaluate this constructor, so bail out.
+      // TODO(paulberry): ensure that a reasonable error message is produced
+      // in this case, as well as other cases involving constant expression
+      // circularities (e.g. "compile-time constant expression depends on
+      // itself")
+      return new DartObjectImpl.validWithUnknownValue(constructor.returnType);
+    }
     int argumentCount = arguments.length;
     List<DartObjectImpl> argumentValues =
         new List<DartObjectImpl>(argumentCount);
@@ -819,11 +882,10 @@
       // In the former case, the best we can do is consider it an unknown value.
       // In the latter case, the error has already been reported, so considering
       // it an unknown value will suppress further errors.
-      return constantVisitor._validWithUnknownValue(definingClass);
+      return new DartObjectImpl.validWithUnknownValue(definingClass);
     }
     beforeGetConstantInitializers(constructor);
-    ConstructorElementImpl constructorBase =
-        _getConstructorBase(constructor) as ConstructorElementImpl;
+    ConstructorElementImpl constructorBase = _getConstructorBase(constructor);
     List<ConstructorInitializer> initializers =
         constructorBase.constantInitializers;
     if (initializers == null) {
@@ -832,7 +894,7 @@
       // const instance using a non-const constructor, or the node we're
       // visiting is involved in a cycle).  The error has already been reported,
       // so consider it an unknown value to suppress further errors.
-      return constantVisitor._validWithUnknownValue(definingClass);
+      return new DartObjectImpl.validWithUnknownValue(definingClass);
     }
     HashMap<String, DartObjectImpl> fieldMap =
         new HashMap<String, DartObjectImpl>();
@@ -985,34 +1047,22 @@
       ConstructorElement constructor) {
     HashSet<ConstructorElement> constructorsVisited =
         new HashSet<ConstructorElement>();
-    while (constructor.isFactory) {
-      if (identical(
-          constructor.enclosingElement.type, typeProvider.symbolType)) {
-        // The dart:core.Symbol has a const factory constructor that redirects
-        // to dart:_internal.Symbol.  That in turn redirects to an external
-        // const constructor, which we won't be able to evaluate.
-        // So stop following the chain of redirections at dart:core.Symbol, and
-        // let [evaluateInstanceCreationExpression] handle it specially.
-        break;
-      }
-      constructorsVisited.add(constructor);
+    while (true) {
       ConstructorElement redirectedConstructor =
-          constructor.redirectedConstructor;
+          _getConstRedirectedConstructor(constructor);
       if (redirectedConstructor == null) {
-        // This can happen if constructor is an external factory constructor.
         break;
-      }
-      if (!redirectedConstructor.isConst) {
-        // Delegating to a non-const constructor--this is not allowed (and
-        // is checked elsewhere--see
-        // [ErrorVerifier.checkForRedirectToNonConstConstructor()]).
-        break;
-      }
-      if (constructorsVisited.contains(redirectedConstructor)) {
-        // Cycle in redirecting factory constructors--this is not allowed
-        // and is checked elsewhere--see
-        // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
-        break;
+      } else {
+        ConstructorElement constructorBase = _getConstructorBase(constructor);
+        constructorsVisited.add(constructorBase);
+        ConstructorElement redirectedConstructorBase =
+            _getConstructorBase(redirectedConstructor);
+        if (constructorsVisited.contains(redirectedConstructorBase)) {
+          // Cycle in redirecting factory constructors--this is not allowed
+          // and is checked elsewhere--see
+          // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
+          break;
+        }
       }
       constructor = redirectedConstructor;
     }
@@ -1029,7 +1079,39 @@
     // TODO(brianwilkerson) Implement this.
   }
 
-  ConstructorElement _getConstructorBase(ConstructorElement constructor) {
+  /**
+   * If [constructor] redirects to another const constructor, return the
+   * const constructor it redirects to.  Otherwise return `null`.
+   */
+  ConstructorElement _getConstRedirectedConstructor(
+      ConstructorElement constructor) {
+    if (!constructor.isFactory) {
+      return null;
+    }
+    if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
+      // The dart:core.Symbol has a const factory constructor that redirects
+      // to dart:_internal.Symbol.  That in turn redirects to an external
+      // const constructor, which we won't be able to evaluate.
+      // So stop following the chain of redirections at dart:core.Symbol, and
+      // let [evaluateInstanceCreationExpression] handle it specially.
+      return null;
+    }
+    ConstructorElement redirectedConstructor =
+        constructor.redirectedConstructor;
+    if (redirectedConstructor == null) {
+      // This can happen if constructor is an external factory constructor.
+      return null;
+    }
+    if (!redirectedConstructor.isConst) {
+      // Delegating to a non-const constructor--this is not allowed (and
+      // is checked elsewhere--see
+      // [ErrorVerifier.checkForRedirectToNonConstConstructor()]).
+      return null;
+    }
+    return redirectedConstructor;
+  }
+
+  ConstructorElementImpl _getConstructorBase(ConstructorElement constructor) {
     while (constructor is ConstructorMember) {
       constructor = (constructor as ConstructorMember).baseElement;
     }
@@ -1060,51 +1142,6 @@
 }
 
 /**
- * An [AstCloner] that copies the necessary information from the AST to allow
- * const constructor initializers to be evaluated.
- */
-class ConstantValueComputer_InitializerCloner extends AstCloner {
-  // TODO(brianwilkerson) Investigate replacing uses of this class with uses of
-  // AstCloner and ResolutionCopier.
-
-  ConstantValueComputer_InitializerCloner() : super(true);
-
-  @override
-  InstanceCreationExpression visitInstanceCreationExpression(
-      InstanceCreationExpression node) {
-    InstanceCreationExpression expression =
-        super.visitInstanceCreationExpression(node);
-    expression.evaluationResult = node.evaluationResult;
-    return expression;
-  }
-
-  @override
-  RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    RedirectingConstructorInvocation invocation =
-        super.visitRedirectingConstructorInvocation(node);
-    invocation.staticElement = node.staticElement;
-    return invocation;
-  }
-
-  @override
-  SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
-    SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
-    identifier.staticElement = node.staticElement;
-    return identifier;
-  }
-
-  @override
-  SuperConstructorInvocation visitSuperConstructorInvocation(
-      SuperConstructorInvocation node) {
-    SuperConstructorInvocation invocation =
-        super.visitSuperConstructorInvocation(node);
-    invocation.staticElement = node.staticElement;
-    return invocation;
-  }
-}
-
-/**
  * A visitor used to evaluate constant expressions to produce their compile-time
  * value. According to the Dart Language Specification: <blockquote> A constant
  * expression is one of the following:
@@ -1334,7 +1371,7 @@
     }
     ParameterizedType thenType = thenResult.type;
     ParameterizedType elseType = elseResult.type;
-    return _validWithUnknownValue(
+    return new DartObjectImpl.validWithUnknownValue(
         thenType.getLeastUpperBound(elseType) as InterfaceType);
   }
 
@@ -1628,7 +1665,9 @@
         }
         return new DartObjectImpl(functionType, new FunctionState(function));
       }
-    } else if (element is ClassElement || element is FunctionTypeAliasElement) {
+    } else if (element is ClassElement ||
+        element is FunctionTypeAliasElement ||
+        element is DynamicElementImpl) {
       return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
     }
     // TODO(brianwilkerson) Figure out which error to report.
@@ -1636,22 +1675,6 @@
     return null;
   }
 
-  DartObjectImpl _validWithUnknownValue(InterfaceType type) {
-    if (type.element.library.isDartCore) {
-      String typeName = type.name;
-      if (typeName == "bool") {
-        return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
-      } else if (typeName == "double") {
-        return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
-      } else if (typeName == "int") {
-        return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
-      } else if (typeName == "String") {
-        return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
-      }
-    }
-    return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
-  }
-
   /**
    * Return the value of the given [expression], or a representation of 'null'
    * if the expression cannot be evaluated.
@@ -2101,6 +2124,25 @@
    */
   DartObjectImpl(this.type, this._state);
 
+  /**
+   * Create an object to represent an unknown value.
+   */
+  factory DartObjectImpl.validWithUnknownValue(InterfaceType type) {
+    if (type.element.library.isDartCore) {
+      String typeName = type.name;
+      if (typeName == "bool") {
+        return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
+      } else if (typeName == "double") {
+        return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
+      } else if (typeName == "int") {
+        return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
+      } else if (typeName == "String") {
+        return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
+      }
+    }
+    return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
+  }
+
   @override
   bool get boolValue {
     if (_state is BoolState) {
@@ -4764,7 +4806,7 @@
   /**
    * A table mapping constant variables to the declarations of those variables.
    */
-  final HashMap<VariableElement, VariableDeclaration> _variableDeclarationMap;
+  final HashMap<PotentiallyConstVariableElement, VariableDeclaration> _variableDeclarationMap;
 
   /**
    * A table mapping constant constructors to the declarations of those
@@ -5027,6 +5069,9 @@
   String get typeName => "Type";
 
   @override
+  Element get value => _element;
+
+  @override
   bool operator ==(Object object) =>
       object is TypeState && (_element == object._element);
 
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 082415c..9c94c92 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -89,12 +89,13 @@
   int internalHashCode(List<DartType> visitedTypes) => hashCode;
 
   @override
-  bool internalIsMoreSpecificThan(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) => true;
+  bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions,
+      Set<Element> typeExpansions, bool withDynamic = false,
+      Set<Element> visitedElements]) => true;
 
   @override
-  bool internalIsSubtypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true;
+  bool isSubtypeOf(DartType type,
+      [Set<Element> thisExpansions, Set<Element> typeExpansions]) => true;
 
   @override
   bool isSupertypeOf(DartType type) => false;
@@ -225,7 +226,7 @@
    * so parsing and resolving will be performed.
    */
   @override
-  AstNode get node;
+  NamedCompilationUnitMember get node;
 
   /**
    * Return the superclass of this class, or `null` if the class represents the
@@ -701,7 +702,7 @@
   }
 
   @override
-  AstNode get node {
+  NamedCompilationUnitMember get node {
     if (isEnum) {
       return getNodeMatching((node) => node is EnumDeclaration);
     } else {
@@ -1493,7 +1494,7 @@
 /**
  * A [FieldElement] for a 'const' field that has an initializer.
  */
-class ConstFieldElementImpl extends FieldElementImpl {
+class ConstFieldElementImpl extends FieldElementImpl with ConstVariableElement {
   /**
    * The result of evaluating this variable's initializer.
    */
@@ -1523,16 +1524,23 @@
  * A [LocalVariableElement] for a local 'const' variable that has an
  * initializer.
  */
-class ConstLocalVariableElementImpl extends LocalVariableElementImpl {
+class ConstLocalVariableElementImpl extends LocalVariableElementImpl
+    with ConstVariableElement {
   /**
    * The result of evaluating this variable's initializer.
    */
   EvaluationResultImpl _result;
 
   /**
+   * Initialize a newly created local variable element to have the given [name]
+   * and [offset].
+   */
+  ConstLocalVariableElementImpl(String name, int offset) : super(name, offset);
+
+  /**
    * Initialize a newly created local variable element to have the given [name].
    */
-  ConstLocalVariableElementImpl(Identifier name) : super.forNode(name);
+  ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);
 
   @override
   EvaluationResultImpl get evaluationResult => _result;
@@ -1629,6 +1637,12 @@
   int nameEnd;
 
   /**
+   * True if this constructor has been found by constant evaluation to be free
+   * of redirect cycles, and is thus safe to evaluate.
+   */
+  bool isCycleFree = false;
+
+  /**
    * Initialize a newly created constructor element to have the given [name] and
    * [offset].
    */
@@ -1826,7 +1840,8 @@
  * A [TopLevelVariableElement] for a top-level 'const' variable that has an
  * initializer.
  */
-class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl {
+class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl
+    with ConstVariableElement {
   /**
    * The result of evaluating this variable's initializer.
    */
@@ -1848,6 +1863,30 @@
 }
 
 /**
+ * Mixin used by elements that represent constant variables and have
+ * initializers.
+ *
+ * Note that in correct Dart code, all constant variables must have
+ * initializers.  However, analyzer also needs to handle incorrect Dart code,
+ * in which case there might be some constant variables that lack initializers.
+ * This interface is only used for constant variables that have initializers.
+ *
+ * This class is not intended to be part of the public API for analyzer.
+ */
+abstract class ConstVariableElement implements PotentiallyConstVariableElement {
+  /**
+   * If this element represents a constant variable, and it has an initializer,
+   * a copy of the initializer for the constant.  Otherwise `null`.
+   *
+   * Note that in correct Dart code, all constant variables must have
+   * initializers.  However, analyzer also needs to handle incorrect Dart code,
+   * in which case there might be some constant variables that lack
+   * initializers.
+   */
+  Expression constantInitializer;
+}
+
+/**
  * The type associated with elements in the element model.
  */
 abstract class DartType {
@@ -2071,8 +2110,9 @@
   int internalHashCode(List<DartType> visitedTypes) => hashCode;
 
   @override
-  bool internalIsMoreSpecificThan(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
+  bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions,
+      Set<Element> typeExpansions, bool withDynamic = false,
+      Set<Element> visitedElements]) {
     // T is S
     if (identical(this, type)) {
       return true;
@@ -2082,8 +2122,8 @@
   }
 
   @override
-  bool internalIsSubtypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true;
+  bool isSubtypeOf(DartType type,
+      [Set<Element> thisExpansions, Set<Element> typeExpansions]) => true;
 
   @override
   bool isSupertypeOf(DartType type) => true;
@@ -3732,7 +3772,7 @@
  * A concrete implementation of a [FieldElement].
  */
 class FieldElementImpl extends PropertyInducingElementImpl
-    implements FieldElement {
+    with PotentiallyConstVariableElement implements FieldElement {
   /**
    * An empty list of field elements.
    */
@@ -4769,8 +4809,20 @@
   }
 
   @override
-  bool internalIsMoreSpecificThan(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
+  bool isAssignableTo(DartType type,
+      [Set<Element> thisExpansions, Set<Element> typeExpansions]) {
+    // A function type T may be assigned to a function type S, written T <=> S,
+    // iff T <: S.
+    return isSubtypeOf(type, thisExpansions, typeExpansions);
+  }
+
+  @override
+  bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions,
+      Set<Element> typeExpansions, bool withDynamic = false,
+      Set<Element> visitedElements]) {
+    // Note: visitedElements is only used for breaking recursion in the type
+    // hierarchy; we don't use it when recursing into the function type.
+
     // trivial base cases
     if (type == null) {
       return false;
@@ -4779,9 +4831,6 @@
         type.isDartCoreFunction ||
         type.isObject) {
       return true;
-    } else if (type is UnionType) {
-      return (type as UnionTypeImpl).internalUnionTypeIsLessSpecificThan(
-          this, withDynamic, visitedTypePairs);
     } else if (type is! FunctionType) {
       return false;
     } else if (this == type) {
@@ -4789,106 +4838,129 @@
     }
     FunctionType t = this;
     FunctionType s = type as FunctionType;
-    List<DartType> tTypes = t.normalParameterTypes;
-    List<DartType> tOpTypes = t.optionalParameterTypes;
-    List<DartType> sTypes = s.normalParameterTypes;
-    List<DartType> sOpTypes = s.optionalParameterTypes;
-    // If one function has positional and the other has named parameters,
-    // return false.
-    if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
-        (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
-      return false;
+    if (thisExpansions == null) {
+      thisExpansions = new HashSet<Element>();
+    } else if (thisExpansions.contains(this.element)) {
+      // [this] contains a reference to itself, which is illegal (and is
+      // checked elsewhere).  To avoid cascading errors, consider T to be a
+      // subtype of S.
+      return true;
     }
-    // named parameters case
-    if (t.namedParameterTypes.length > 0) {
-      // check that the number of required parameters are equal, and check that
-      // every t_i is more specific than every s_i
-      if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
+    if (typeExpansions == null) {
+      typeExpansions = new HashSet<Element>();
+    } else if (typeExpansions.contains(type.element)) {
+      // [type] contains a reference to itself, which is illegal (and is
+      // checked elsewhere).  To avoid cascading errors, consider T to be a
+      // subtype of S.
+      return true;
+    }
+    thisExpansions.add(this.element);
+    typeExpansions.add(type.element);
+    try {
+      List<DartType> tTypes = t.normalParameterTypes;
+      List<DartType> tOpTypes = t.optionalParameterTypes;
+      List<DartType> sTypes = s.normalParameterTypes;
+      List<DartType> sOpTypes = s.optionalParameterTypes;
+      // If one function has positional and the other has named parameters,
+      // return false.
+      if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
+          (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
         return false;
-      } else if (t.normalParameterTypes.length > 0) {
-        for (int i = 0; i < tTypes.length; i++) {
-          if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2(
-              sTypes[i], withDynamic, visitedTypePairs)) {
+      }
+      // named parameters case
+      if (t.namedParameterTypes.length > 0) {
+        // check that the number of required parameters are equal, and check that
+        // every t_i is more specific than every s_i
+        if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
+          return false;
+        } else if (t.normalParameterTypes.length > 0) {
+          for (int i = 0; i < tTypes.length; i++) {
+            if (!(tTypes[i] as TypeImpl).isMoreSpecificThan(
+                sTypes[i], thisExpansions, typeExpansions, withDynamic)) {
+              return false;
+            }
+          }
+        }
+        Map<String, DartType> namedTypesT = t.namedParameterTypes;
+        Map<String, DartType> namedTypesS = s.namedParameterTypes;
+        // if k >= m is false, return false: the passed function type has more
+        // named parameter types than this
+        if (namedTypesT.length < namedTypesS.length) {
+          return false;
+        }
+        // Loop through each element in S verifying that T has a matching
+        // parameter name and that the corresponding type is more specific then
+        // the type in S.
+        for (String keyS in namedTypesS.keys) {
+          DartType typeT = namedTypesT[keyS];
+          if (typeT == null) {
+            return false;
+          }
+          if (!(typeT as TypeImpl).isMoreSpecificThan(
+              namedTypesS[keyS], thisExpansions, typeExpansions, withDynamic)) {
             return false;
           }
         }
-      }
-      Map<String, DartType> namedTypesT = t.namedParameterTypes;
-      Map<String, DartType> namedTypesS = s.namedParameterTypes;
-      // if k >= m is false, return false: the passed function type has more
-      // named parameter types than this
-      if (namedTypesT.length < namedTypesS.length) {
+      } else if (s.namedParameterTypes.length > 0) {
         return false;
-      }
-      // Loop through each element in S verifying that T has a matching
-      // parameter name and that the corresponding type is more specific then
-      // the type in S.
-      for (String keyS in namedTypesS.keys) {
-        DartType typeT = namedTypesT[keyS];
-        if (typeT == null) {
-          return false;
-        }
-        if (!(typeT as TypeImpl).isMoreSpecificThan2(
-            namedTypesS[keyS], withDynamic, visitedTypePairs)) {
-          return false;
-        }
-      }
-    } else if (s.namedParameterTypes.length > 0) {
-      return false;
-    } else {
-      // positional parameter case
-      int tArgLength = tTypes.length + tOpTypes.length;
-      int sArgLength = sTypes.length + sOpTypes.length;
-      // Check that the total number of parameters in t is greater than or equal
-      // to the number of parameters in s and that the number of required
-      // parameters in s is greater than or equal to the number of required
-      // parameters in t.
-      if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
-        return false;
-      }
-      if (tOpTypes.length == 0 && sOpTypes.length == 0) {
-        // No positional arguments, don't copy contents to new array
-        for (int i = 0; i < sTypes.length; i++) {
-          if (!(tTypes[i] as TypeImpl).isMoreSpecificThan2(
-              sTypes[i], withDynamic, visitedTypePairs)) {
-            return false;
-          }
-        }
       } else {
-        // Else, we do have positional parameters, copy required and positional
-        // parameter types into arrays to do the compare (for loop below).
-        List<DartType> tAllTypes = new List<DartType>(sArgLength);
-        for (int i = 0; i < tTypes.length; i++) {
-          tAllTypes[i] = tTypes[i];
+        // positional parameter case
+        int tArgLength = tTypes.length + tOpTypes.length;
+        int sArgLength = sTypes.length + sOpTypes.length;
+        // Check that the total number of parameters in t is greater than or equal
+        // to the number of parameters in s and that the number of required
+        // parameters in s is greater than or equal to the number of required
+        // parameters in t.
+        if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
+          return false;
         }
-        for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
-          tAllTypes[i] = tOpTypes[j];
-        }
-        List<DartType> sAllTypes = new List<DartType>(sArgLength);
-        for (int i = 0; i < sTypes.length; i++) {
-          sAllTypes[i] = sTypes[i];
-        }
-        for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
-          sAllTypes[i] = sOpTypes[j];
-        }
-        for (int i = 0; i < sAllTypes.length; i++) {
-          if (!(tAllTypes[i] as TypeImpl).isMoreSpecificThan2(
-              sAllTypes[i], withDynamic, visitedTypePairs)) {
-            return false;
+        if (tOpTypes.length == 0 && sOpTypes.length == 0) {
+          // No positional arguments, don't copy contents to new array
+          for (int i = 0; i < sTypes.length; i++) {
+            if (!(tTypes[i] as TypeImpl).isMoreSpecificThan(
+                sTypes[i], thisExpansions, typeExpansions, withDynamic)) {
+              return false;
+            }
+          }
+        } else {
+          // Else, we do have positional parameters, copy required and positional
+          // parameter types into arrays to do the compare (for loop below).
+          List<DartType> tAllTypes = new List<DartType>(sArgLength);
+          for (int i = 0; i < tTypes.length; i++) {
+            tAllTypes[i] = tTypes[i];
+          }
+          for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
+            tAllTypes[i] = tOpTypes[j];
+          }
+          List<DartType> sAllTypes = new List<DartType>(sArgLength);
+          for (int i = 0; i < sTypes.length; i++) {
+            sAllTypes[i] = sTypes[i];
+          }
+          for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
+            sAllTypes[i] = sOpTypes[j];
+          }
+          for (int i = 0; i < sAllTypes.length; i++) {
+            if (!(tAllTypes[i] as TypeImpl).isMoreSpecificThan(
+                sAllTypes[i], thisExpansions, typeExpansions, withDynamic)) {
+              return false;
+            }
           }
         }
       }
+      DartType tRetType = t.returnType;
+      DartType sRetType = s.returnType;
+      return sRetType.isVoid ||
+          (tRetType as TypeImpl).isMoreSpecificThan(
+              sRetType, thisExpansions, typeExpansions, withDynamic);
+    } finally {
+      thisExpansions.remove(this.element);
+      typeExpansions.remove(type.element);
     }
-    DartType tRetType = t.returnType;
-    DartType sRetType = s.returnType;
-    return sRetType.isVoid ||
-        (tRetType as TypeImpl).isMoreSpecificThan2(
-            sRetType, withDynamic, visitedTypePairs);
   }
 
   @override
-  bool internalIsSubtypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
+  bool isSubtypeOf(DartType type,
+      [Set<Element> thisExpansions, Set<Element> typeExpansions]) {
     // trivial base cases
     if (type == null) {
       return false;
@@ -4897,9 +4969,6 @@
         type.isDartCoreFunction ||
         type.isObject) {
       return true;
-    } else if (type is UnionType) {
-      return (type as UnionTypeImpl).internalUnionTypeIsSuperTypeOf(
-          this, visitedTypePairs);
     } else if (type is! FunctionType) {
       return false;
     } else if (this == type) {
@@ -4907,113 +4976,127 @@
     }
     FunctionType t = this;
     FunctionType s = type as FunctionType;
-    List<DartType> tTypes = t.normalParameterTypes;
-    List<DartType> tOpTypes = t.optionalParameterTypes;
-    List<DartType> sTypes = s.normalParameterTypes;
-    List<DartType> sOpTypes = s.optionalParameterTypes;
-    // If one function has positional and the other has named parameters,
-    // return false.
-    if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
-        (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
-      return false;
+    if (thisExpansions == null) {
+      thisExpansions = new HashSet<Element>();
+    } else if (thisExpansions.contains(this.element)) {
+      // [this] contains a reference to itself, which is illegal (and is
+      // checked elsewhere).  To avoid cascading errors, consider T to be a
+      // subtype of S.
+      return true;
     }
-    // named parameters case
-    if (t.namedParameterTypes.length > 0) {
-      // check that the number of required parameters are equal,
-      // and check that every t_i is assignable to every s_i
-      if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
+    if (typeExpansions == null) {
+      typeExpansions = new HashSet<Element>();
+    } else if (typeExpansions.contains(type.element)) {
+      // [type] contains a reference to itself, which is illegal (and is
+      // checked elsewhere).  To avoid cascading errors, consider T to be a
+      // subtype of S.
+      return true;
+    }
+    thisExpansions.add(this.element);
+    typeExpansions.add(type.element);
+    try {
+      List<DartType> tTypes = t.normalParameterTypes;
+      List<DartType> tOpTypes = t.optionalParameterTypes;
+      List<DartType> sTypes = s.normalParameterTypes;
+      List<DartType> sOpTypes = s.optionalParameterTypes;
+      // If one function has positional and the other has named parameters,
+      // return false.
+      if ((sOpTypes.length > 0 && t.namedParameterTypes.length > 0) ||
+          (tOpTypes.length > 0 && s.namedParameterTypes.length > 0)) {
         return false;
-      } else if (t.normalParameterTypes.length > 0) {
-        for (int i = 0; i < tTypes.length; i++) {
-          if (!(tTypes[i] as TypeImpl).isAssignableTo2(
-              sTypes[i], visitedTypePairs)) {
+      }
+      // named parameters case
+      if (t.namedParameterTypes.length > 0) {
+        // check that the number of required parameters are equal,
+        // and check that every t_i is assignable to every s_i
+        if (t.normalParameterTypes.length != s.normalParameterTypes.length) {
+          return false;
+        } else if (t.normalParameterTypes.length > 0) {
+          for (int i = 0; i < tTypes.length; i++) {
+            if (!(tTypes[i] as TypeImpl).isAssignableTo(
+                sTypes[i], thisExpansions, typeExpansions)) {
+              return false;
+            }
+          }
+        }
+        Map<String, DartType> namedTypesT = t.namedParameterTypes;
+        Map<String, DartType> namedTypesS = s.namedParameterTypes;
+        // if k >= m is false, return false: the passed function type has more
+        // named parameter types than this
+        if (namedTypesT.length < namedTypesS.length) {
+          return false;
+        }
+        // Loop through each element in S verifying that T has a matching
+        // parameter name and that the corresponding type is assignable to the
+        // type in S.
+        for (String keyS in namedTypesS.keys) {
+          DartType typeT = namedTypesT[keyS];
+          if (typeT == null) {
+            return false;
+          }
+          if (!(typeT as TypeImpl).isAssignableTo(
+              namedTypesS[keyS], thisExpansions, typeExpansions)) {
             return false;
           }
         }
-      }
-      Map<String, DartType> namedTypesT = t.namedParameterTypes;
-      Map<String, DartType> namedTypesS = s.namedParameterTypes;
-      // if k >= m is false, return false: the passed function type has more
-      // named parameter types than this
-      if (namedTypesT.length < namedTypesS.length) {
+      } else if (s.namedParameterTypes.length > 0) {
         return false;
-      }
-      // Loop through each element in S verifying that T has a matching
-      // parameter name and that the corresponding type is assignable to the
-      // type in S.
-      for (String keyS in namedTypesS.keys) {
-        DartType typeT = namedTypesT[keyS];
-        if (typeT == null) {
-          return false;
-        }
-        if (!(typeT as TypeImpl).isAssignableTo2(
-            namedTypesS[keyS], visitedTypePairs)) {
-          return false;
-        }
-      }
-    } else if (s.namedParameterTypes.length > 0) {
-      return false;
-    } else {
-      // positional parameter case
-      int tArgLength = tTypes.length + tOpTypes.length;
-      int sArgLength = sTypes.length + sOpTypes.length;
-      // Check that the total number of parameters in t is greater than or equal
-      // to the number of parameters in s and that the number of required
-      // parameters in s is greater than or equal to the number of required
-      // parameters in t.
-      if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
-        return false;
-      }
-      if (tOpTypes.length == 0 && sOpTypes.length == 0) {
-        // No positional arguments, don't copy contents to new array
-        for (int i = 0; i < sTypes.length; i++) {
-          if (!(tTypes[i] as TypeImpl).isAssignableTo2(
-              sTypes[i], visitedTypePairs)) {
-            return false;
-          }
-        }
       } else {
-        // Else, we do have positional parameters, copy required and positional
-        // parameter types into arrays to do the compare (for loop below).
-        List<DartType> tAllTypes = new List<DartType>(sArgLength);
-        for (int i = 0; i < tTypes.length; i++) {
-          tAllTypes[i] = tTypes[i];
+        // positional parameter case
+        int tArgLength = tTypes.length + tOpTypes.length;
+        int sArgLength = sTypes.length + sOpTypes.length;
+        // Check that the total number of parameters in t is greater than or
+        // equal to the number of parameters in s and that the number of
+        // required parameters in s is greater than or equal to the number of
+        // required parameters in t.
+        if (tArgLength < sArgLength || sTypes.length < tTypes.length) {
+          return false;
         }
-        for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
-          tAllTypes[i] = tOpTypes[j];
-        }
-        List<DartType> sAllTypes = new List<DartType>(sArgLength);
-        for (int i = 0; i < sTypes.length; i++) {
-          sAllTypes[i] = sTypes[i];
-        }
-        for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
-          sAllTypes[i] = sOpTypes[j];
-        }
-        for (int i = 0; i < sAllTypes.length; i++) {
-          if (!(tAllTypes[i] as TypeImpl).isAssignableTo2(
-              sAllTypes[i], visitedTypePairs)) {
-            return false;
+        if (tOpTypes.length == 0 && sOpTypes.length == 0) {
+          // No positional arguments, don't copy contents to new array
+          for (int i = 0; i < sTypes.length; i++) {
+            if (!(tTypes[i] as TypeImpl).isAssignableTo(
+                sTypes[i], thisExpansions, typeExpansions)) {
+              return false;
+            }
+          }
+        } else {
+          // Else, we do have positional parameters, copy required and
+          // positional parameter types into arrays to do the compare (for loop
+          // below).
+          List<DartType> tAllTypes = new List<DartType>(sArgLength);
+          for (int i = 0; i < tTypes.length; i++) {
+            tAllTypes[i] = tTypes[i];
+          }
+          for (int i = tTypes.length, j = 0; i < sArgLength; i++, j++) {
+            tAllTypes[i] = tOpTypes[j];
+          }
+          List<DartType> sAllTypes = new List<DartType>(sArgLength);
+          for (int i = 0; i < sTypes.length; i++) {
+            sAllTypes[i] = sTypes[i];
+          }
+          for (int i = sTypes.length, j = 0; i < sArgLength; i++, j++) {
+            sAllTypes[i] = sOpTypes[j];
+          }
+          for (int i = 0; i < sAllTypes.length; i++) {
+            if (!(tAllTypes[i] as TypeImpl).isAssignableTo(
+                sAllTypes[i], thisExpansions, typeExpansions)) {
+              return false;
+            }
           }
         }
       }
+      DartType tRetType = t.returnType;
+      DartType sRetType = s.returnType;
+      return sRetType.isVoid ||
+          (tRetType as TypeImpl).isAssignableTo(
+              sRetType, thisExpansions, typeExpansions);
+    } finally {
+      thisExpansions.remove(this.element);
+      typeExpansions.remove(type.element);
     }
-    DartType tRetType = t.returnType;
-    DartType sRetType = s.returnType;
-    return sRetType.isVoid ||
-        (tRetType as TypeImpl).isAssignableTo2(sRetType, visitedTypePairs);
   }
 
-  /**
-   * Return `true` if this type is assignable to the given [type]. A function
-   * type <i>T</i> may be assigned to a function type <i>S</i>, written <i>T</i>
-   * &hArr; <i>S</i>, iff <i>T</i> <: <i>S</i> (Function Types section of spec).
-   * Note that this is more restrictive than the "may be assigned to" rule for
-   * interface types.
-   */
-  @override
-  bool isAssignableTo(DartType type) =>
-      isSubtypeOf2(type, new HashSet<TypeImpl_TypePair>());
-
   @override
   FunctionTypeImpl substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes) {
@@ -6086,111 +6169,6 @@
   int internalHashCode(List<DartType> visitedTypes) => hashCode;
 
   @override
-  bool internalIsMoreSpecificThan(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
-    //
-    // S is dynamic.
-    // The test to determine whether S is dynamic is done here because dynamic
-    // is not an instance of InterfaceType.
-    //
-    if (type.isDynamic) {
-      return true;
-    } else if (type is UnionType) {
-      return (type as UnionTypeImpl).internalUnionTypeIsLessSpecificThan(
-          this, withDynamic, visitedTypePairs);
-    } else if (type is! InterfaceType) {
-      return false;
-    }
-    return _isMoreSpecificThan(type as InterfaceType,
-        new HashSet<ClassElement>(), withDynamic, visitedTypePairs);
-  }
-
-  @override
-  bool internalIsSubtypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
-    //
-    // T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S
-    //
-    if (type.isDynamic) {
-      return true;
-    } else if (type is TypeParameterType) {
-      return false;
-    } else if (type is UnionType) {
-      return (type as UnionTypeImpl).internalUnionTypeIsSuperTypeOf(
-          this, visitedTypePairs);
-    } else if (type is FunctionType) {
-      // This implementation assumes transitivity
-      // for function type subtyping on the RHS, but a literal reading
-      // of the spec does not specify this. More precisely:
-      // if T <: F1 and F1 <: F2 and F1 and F2 are function types,
-      // then we assume T <: F2.
-      //
-      // From the Function Types section of the spec:
-      //
-      //   If a type I includes an instance method named call(), and the type of
-      //   call() is the function type F, then I is considered to be a
-      //   subtype of F.
-      //
-      // However, the section on Interface Types says
-      //
-      //   T is a subtype of S, written T <: S, iff [bottom/dynamic]T << S.
-      //
-      // after giving rules for << (pronounced "more specific than").
-      // However, the "only if" direction of the "iff" in the definition of <:
-      // seems to be contradicted by the special case <: rule quoted from the
-      // Function Types section: I see no rule for << which tells us that
-      // I << F if I has call() at type F.
-      //
-      // After defining <: , the spec then
-      // emphasizes that unlike the relation <<, the relation <: is not
-      // transitive in general:
-      //
-      //   Note that <: is not a partial order on types, it is only binary
-      //   relation on types.
-      //   This is because <: is not transitive.
-      //   If it was, the subtype rule would have a cycle.
-      //
-      //   For example: List <: List<String> and List<int> <: List,
-      //   but List<int> is not a subtype of List<String>.
-      //   Although <: is not a partial order on types, it does contain a
-      //   partial order, namely <<.
-      //   This means that, barring raw types, intuition about classical subtype
-      //   rules does apply.
-      //
-      // There is no other occurrence of the word "raw" in relation to types in
-      // the spec that I can find, but presumably it's a reference to
-      //
-      //   http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html
-      //
-      // so e.g. non-generic types are never raw. As pointed out by paulberry,
-      // it's not clear whether a type like T<int, dynamic> should be considered
-      // raw or not. On the one hand, it doesn't correspond to a
-      // "raw"-in-the-Java-sense occurrence of T, which would instead
-      // be T<dynamic, dynamic>; on the other hand, it's treated differently
-      // by <: and << when occurring on the left hand side.
-      ClassElement element = this.element;
-      InheritanceManager manager = new InheritanceManager(element.library);
-      FunctionType callType = manager.lookupMemberType(this, "call");
-      if (callType != null) {
-        // A more literal reading of the spec would give something like
-        //
-        //  return callType.equals(type)
-        //
-        // here, but that causes 101 errors in the external tests
-        // (tools/test.py --mode release --compiler dartanalyzer --runtime none)
-        return callType.isSubtypeOf(type);
-      }
-      return false;
-    } else if (type is! InterfaceType) {
-      return false;
-    } else if (this == type) {
-      return true;
-    }
-    return _isSubtypeOf(
-        type as InterfaceType, new HashSet<ClassElement>(), visitedTypePairs);
-  }
-
-  @override
   bool isDirectSupertypeOf(InterfaceType type) {
     InterfaceType i = this;
     InterfaceType j = type;
@@ -6239,6 +6217,109 @@
   }
 
   @override
+  bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions,
+      Set<Element> typeExpansions, bool withDynamic = false,
+      Set<Element> visitedElements]) {
+    //
+    // S is dynamic.
+    // The test to determine whether S is dynamic is done here because dynamic
+    // is not an instance of InterfaceType.
+    //
+    if (type.isDynamic) {
+      return true;
+    }
+    //
+    // A type T is more specific than a type S, written T << S,
+    // if one of the following conditions is met:
+    //
+    // Reflexivity: T is S.
+    //
+    if (this == type) {
+      return true;
+    }
+    if (type is InterfaceType) {
+      //
+      // T is bottom. (This case is handled by the class BottomTypeImpl.)
+      //
+      // Direct supertype: S is a direct supertype of T.
+      //
+      if (type.isDirectSupertypeOf(this)) {
+        return true;
+      }
+      //
+      // Covariance: T is of the form I<T1, ..., Tn> and S is of the form
+      // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n.
+      //
+      ClassElement tElement = this.element;
+      ClassElement sElement = type.element;
+      if (tElement == sElement) {
+        List<DartType> tArguments = typeArguments;
+        List<DartType> sArguments = type.typeArguments;
+        if (tArguments.length != sArguments.length) {
+          return false;
+        }
+        for (int i = 0; i < tArguments.length; i++) {
+          if (!(tArguments[i] as TypeImpl).isMoreSpecificThan(
+              sArguments[i], thisExpansions, typeExpansions, withDynamic)) {
+            return false;
+          }
+        }
+        return true;
+      }
+    }
+    //
+    // Transitivity: T << U and U << S.
+    //
+    // First check for infinite loops
+    if (element == null) {
+      return false;
+    }
+    if (visitedElements == null) {
+      visitedElements = new HashSet<ClassElement>();
+    } else if (visitedElements.contains(element)) {
+      return false;
+    }
+    visitedElements.add(element);
+    try {
+      // Iterate over all of the types U that are more specific than T because
+      // they are direct supertypes of T and return true if any of them are more
+      // specific than S.
+      InterfaceTypeImpl supertype = superclass;
+      if (supertype != null &&
+          supertype.isMoreSpecificThan(type, thisExpansions, typeExpansions,
+              withDynamic, visitedElements)) {
+        return true;
+      }
+      for (InterfaceTypeImpl interfaceType in interfaces) {
+        if (interfaceType.isMoreSpecificThan(type, thisExpansions,
+            typeExpansions, withDynamic, visitedElements)) {
+          return true;
+        }
+      }
+      for (InterfaceTypeImpl mixinType in mixins) {
+        if (mixinType.isMoreSpecificThan(type, thisExpansions, typeExpansions,
+            withDynamic, visitedElements)) {
+          return true;
+        }
+      }
+      // If a type I includes an instance method named `call`, and the type of
+      // `call` is the function type F, then I is considered to be more specific
+      // than F.
+      MethodElement callMethod = getMethod('call');
+      if (callMethod != null && !callMethod.isStatic) {
+        FunctionTypeImpl callType = callMethod.type;
+        if (callType.isMoreSpecificThan(type, thisExpansions, typeExpansions,
+            withDynamic, visitedElements)) {
+          return true;
+        }
+      }
+      return false;
+    } finally {
+      visitedElements.remove(element);
+    }
+  }
+
+  @override
   ConstructorElement lookUpConstructor(
       String constructorName, LibraryElement library) {
     // prepare base ConstructorElement
@@ -6404,145 +6485,6 @@
       substitute2(argumentTypes, typeArguments);
 
   /**
-   * Return `true` if the given element has an instance method named 'call'.
-   */
-  bool _hasCallMethod(ClassElement elementT) {
-    MethodElement method = elementT.lookUpMethod(
-        FunctionElement.CALL_METHOD_NAME, elementT.library);
-    return method != null && !method.isStatic;
-  }
-
-  bool _isMoreSpecificThan(InterfaceType s,
-      HashSet<ClassElement> visitedClasses, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
-    //
-    // A type T is more specific than a type S, written T << S,
-    // if one of the following conditions is met:
-    //
-    // Reflexivity: T is S.
-    //
-    if (this == s) {
-      return true;
-    }
-    //
-    // T is bottom. (This case is handled by the class BottomTypeImpl.)
-    //
-    // Direct supertype: S is a direct supertype of T.
-    //
-    if (s.isDirectSupertypeOf(this)) {
-      return true;
-    }
-    //
-    // Covariance: T is of the form I<T1, ..., Tn> and S is of the form
-    // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n.
-    //
-    ClassElement tElement = this.element;
-    ClassElement sElement = s.element;
-    if (tElement == sElement) {
-      List<DartType> tArguments = typeArguments;
-      List<DartType> sArguments = s.typeArguments;
-      if (tArguments.length != sArguments.length) {
-        return false;
-      }
-      for (int i = 0; i < tArguments.length; i++) {
-        if (!(tArguments[i] as TypeImpl).isMoreSpecificThan2(
-            sArguments[i], withDynamic, visitedTypePairs)) {
-          return false;
-        }
-      }
-      return true;
-    }
-    //
-    // Transitivity: T << U and U << S.
-    //
-    // First check for infinite loops
-    ClassElement element = this.element;
-    if (element == null || visitedClasses.contains(element)) {
-      return false;
-    }
-    visitedClasses.add(element);
-    // Iterate over all of the types U that are more specific than T because
-    // they are direct supertypes of T and return true if any of them are more
-    // specific than S.
-    InterfaceType supertype = superclass;
-    if (supertype != null &&
-        (supertype as InterfaceTypeImpl)._isMoreSpecificThan(
-            s, visitedClasses, withDynamic, visitedTypePairs)) {
-      return true;
-    }
-    for (InterfaceType interfaceType in interfaces) {
-      if ((interfaceType as InterfaceTypeImpl)._isMoreSpecificThan(
-          s, visitedClasses, withDynamic, visitedTypePairs)) {
-        return true;
-      }
-    }
-    for (InterfaceType mixinType in mixins) {
-      if ((mixinType as InterfaceTypeImpl)._isMoreSpecificThan(
-          s, visitedClasses, withDynamic, visitedTypePairs)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  bool _isSubtypeOf(InterfaceType type, HashSet<ClassElement> visitedClasses,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
-    InterfaceType typeT = this;
-    InterfaceType typeS = type;
-    ClassElement elementT = element;
-    if (elementT == null || visitedClasses.contains(elementT)) {
-      return false;
-    }
-    visitedClasses.add(elementT);
-    if (typeT == typeS) {
-      return true;
-    } else if (elementT == typeS.element) {
-      // For each of the type arguments return true if all type args from T is
-      // a subtype of all types from S.
-      List<DartType> typeTArgs = typeT.typeArguments;
-      List<DartType> typeSArgs = typeS.typeArguments;
-      if (typeTArgs.length != typeSArgs.length) {
-        // This case covers the case where two objects are being compared that
-        // have a different number of parameterized types.
-        return false;
-      }
-      for (int i = 0; i < typeTArgs.length; i++) {
-        // Recursively call isSubtypeOf the type arguments and return false if
-        // the T argument is not a subtype of the S argument.
-        if (!(typeTArgs[i] as TypeImpl).isSubtypeOf2(
-            typeSArgs[i], visitedTypePairs)) {
-          return false;
-        }
-      }
-      return true;
-    } else if (typeS.isDartCoreFunction && _hasCallMethod(elementT)) {
-      return true;
-    }
-    InterfaceType supertype = superclass;
-    // The type is Object, return false.
-    if (supertype != null &&
-        (supertype as InterfaceTypeImpl)._isSubtypeOf(
-            typeS, visitedClasses, visitedTypePairs)) {
-      return true;
-    }
-    List<InterfaceType> interfaceTypes = interfaces;
-    for (InterfaceType interfaceType in interfaceTypes) {
-      if ((interfaceType as InterfaceTypeImpl)._isSubtypeOf(
-          typeS, visitedClasses, visitedTypePairs)) {
-        return true;
-      }
-    }
-    List<InterfaceType> mixinTypes = mixins;
-    for (InterfaceType mixinType in mixinTypes) {
-      if ((mixinType as InterfaceTypeImpl)._isSubtypeOf(
-          typeS, visitedClasses, visitedTypePairs)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
    * Return the length of the longest inheritance path from the given [type] to
    * Object.
    *
@@ -6780,7 +6722,7 @@
   bool get isDartCore;
 
   /**
-   * Return `true` if this library is the dart:core library.
+   * Return `true` if this library is part of the SDK.
    */
   bool get isInSdk;
 
@@ -6824,6 +6766,11 @@
   List<LibraryElement> get visibleLibraries;
 
   /**
+   * Return the element at the given [offset], maybe `null` if no such element.
+   */
+  Element getElementAt(int offset);
+
+  /**
    * Return a list containing all of the imports that share the given [prefix],
    * or an empty array if there are no such imports.
    */
@@ -6893,6 +6840,11 @@
   FunctionElement _loadLibraryFunction;
 
   /**
+   * A map from offsets to elements of this library at these offsets.
+   */
+  final Map<int, Element> _offsetToElementMap = new HashMap<int, Element>();
+
+  /**
    * The export [Namespace] of this library, `null` if it has not been
    * computed yet.
    */
@@ -7167,6 +7119,13 @@
   @override
   accept(ElementVisitor visitor) => visitor.visitLibraryElement(this);
 
+  /**
+   * This method is invoked after this library was incrementally resolved.
+   */
+  void afterIncrementalResolution() {
+    _offsetToElementMap.clear();
+  }
+
   @override
   ElementImpl getChild(String identifier) {
     if ((_definingCompilationUnit as CompilationUnitElementImpl).identifier ==
@@ -7192,6 +7151,14 @@
   }
 
   @override
+  Element getElementAt(int offset) {
+    if (_offsetToElementMap.isEmpty) {
+      accept(new _BuildOffsetToElementMap(_offsetToElementMap));
+    }
+    return _offsetToElementMap[offset];
+  }
+
+  @override
   List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) {
     int count = _imports.length;
     List<ImportElement> importList = new List<ImportElement>();
@@ -7335,7 +7302,7 @@
  * A concrete implementation of a [LocalVariableElement].
  */
 class LocalVariableElementImpl extends VariableElementImpl
-    implements LocalVariableElement {
+    with PotentiallyConstVariableElement implements LocalVariableElement {
   /**
    * An empty list of field elements.
    */
@@ -7677,8 +7644,6 @@
 
   @override
   void appendTo(StringBuffer buffer) {
-    buffer.write(enclosingElement.displayName);
-    buffer.write(".");
     buffer.write(displayName);
     super.appendTo(buffer);
   }
@@ -8527,6 +8492,27 @@
 }
 
 /**
+ * Interface used by elements that might represent constant variables.
+ *
+ * This class may be used as a mixin in the case where [constInitializer] is
+ * known to return null.
+ *
+ * This class is not intended to be part of the public API for analyzer.
+ */
+abstract class PotentiallyConstVariableElement {
+  /**
+   * If this element represents a constant variable, and it has an initializer,
+   * a copy of the initializer for the constant.  Otherwise `null`.
+   *
+   * Note that in correct Dart code, all constant variables must have
+   * initializers.  However, analyzer also needs to handle incorrect Dart code,
+   * in which case there might be some constant variables that lack
+   * initializers.
+   */
+  Expression get constantInitializer => null;
+}
+
+/**
  * A prefix used to import one or more libraries into another library.
  */
 abstract class PrefixElement implements Element {
@@ -9307,7 +9293,7 @@
  * A concrete implementation of a [TopLevelVariableElement].
  */
 class TopLevelVariableElementImpl extends PropertyInducingElementImpl
-    implements TopLevelVariableElement {
+    with PotentiallyConstVariableElement implements TopLevelVariableElement {
   /**
    * An empty list of top-level variable elements.
    */
@@ -9410,118 +9396,68 @@
 
   int internalHashCode(List<DartType> visitedTypes);
 
-  bool internalIsMoreSpecificThan(
-      DartType type, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs);
-
-  bool internalIsSubtypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs);
-
-  @override
-  bool isAssignableTo(DartType type) =>
-      isAssignableTo2(type, new HashSet<TypeImpl_TypePair>());
-
   /**
-   * Return `true` if this type is assignable to the given [type]. A type
-   * <i>T</i> may be assigned to a type <i>S</i>, written <i>T</i> &hArr;
-   * <i>S</i>, iff either <i>T</i> <: <i>S</i> or <i>S</i> <: <i>T</i>
-   * (Interface Types section of spec).
+   * Return `true` if this type is assignable to the given [type] (written in
+   * the spec as "T <=> S", where T=[this] and S=[type]).
    *
-   * The given set of [visitedTypePairs] of types (T1, T2), where each pair
-   * indicates that we invoked this method because we are in the process of
-   * answering the question of whether T1 is a subtype of T2, is used to prevent
-   * infinite loops.
+   * The sets [thisExpansions] and [typeExpansions], if given, are the sets of
+   * function type aliases that have been expanded so far in the process of
+   * reaching [this] and [type], respectively.  These are used to avoid
+   * infinite regress when analyzing invalid code; since the language spec
+   * forbids a typedef from referring to itself directly or indirectly, we can
+   * use these as sets of function type aliases that don't need to be expanded.
    */
-  bool isAssignableTo2(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
-    // Strictness matters for union types on the LHS, but not for union types
-    // on the RHS.
-    if (this is UnionType) {
-      if (AnalysisEngine.instance.strictUnionTypes) {
-        // *Every* element on the LHS must be assignable to the RHS.
-        // We recursively fall into the next case when the RHS is also a union:
-        // the order here is important!
-        for (DartType left in (this as UnionType).elements) {
-          // Would have to cast to [TypeImpl] to call the [visitedTypePairs]
-          // version here.
-          if (!left.isAssignableTo(type)) {
-            return false;
-          }
-        }
-        return true;
-      } else {
-        // *Some* element on the LHS must be assignable to the RHS.
-        for (DartType left in (this as UnionType).elements) {
-          // Would have to cast to [TypeImpl] to call the [visitedTypePairs]
-          // version here.
-          if (left.isAssignableTo(type)) {
-            return true;
-          }
-        }
-        return false;
-      }
-    } else if (type is UnionType) {
-      // The LHS, which is not a union, must be assignable to *some* element
-      // on the RHS.
-      for (DartType right in type.elements) {
-        if (this.isAssignableTo2(right, visitedTypePairs)) {
-          return true;
-        }
-      }
-      return false;
-    } else {
-      // For non union types we use the language spec definition of [<=>].
-      return isSubtypeOf2(type, visitedTypePairs) ||
-          (type as TypeImpl).isSubtypeOf2(this, visitedTypePairs);
-    }
+  @override
+  bool isAssignableTo(TypeImpl type,
+      [Set<Element> thisExpansions, Set<Element> typeExpansions]) {
+    // An interface type T may be assigned to a type S, written T <=> S, iff
+    // either T <: S or S <: T.
+    return isSubtypeOf(type, thisExpansions, typeExpansions) ||
+        type.isSubtypeOf(this, typeExpansions, thisExpansions);
   }
 
+  /**
+   * Return `true` if this type is more specific than the given [type] (written
+   * in the spec as "T << S", where T=[this] and S=[type]).
+   *
+   * The sets [thisExpansions] and [typeExpansions], if given, are the sets of
+   * function type aliases that have been expanded so far in the process of
+   * reaching [this] and [type], respectively.  These are used to avoid
+   * infinite regress when analyzing invalid code; since the language spec
+   * forbids a typedef from referring to itself directly or indirectly, we can
+   * use these as sets of function type aliases that don't need to be expanded.
+   *
+   * If [withDynamic] is `true`, then "dynamic" should be considered as a
+   * subtype of any type (as though "dynamic" had been replaced with bottom).
+   *
+   * The set [visitedElements], if given, is the set of classes and type
+   * parameters that have been visited so far while examining the class
+   * hierarchy of [this].  This is used to avoid infinite regress when
+   * analyzing invalid code; since the language spec forbids loops in the class
+   * hierarchy, we can use this as a set of classes that don't need to be
+   * examined when walking the class hierarchy.
+   */
   @override
-  bool isMoreSpecificThan(DartType type) =>
-      isMoreSpecificThan2(type, false, new HashSet<TypeImpl_TypePair>());
+  bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions,
+      Set<Element> typeExpansions, bool withDynamic = false,
+      Set<Element> visitedElements]);
 
   /**
-   * Return `true` if this type is more specific than the given [type]. If
-   * [withDynamic] is `true`, then "dynamic" should be considered as a subtype
-   * of any type.
+   * Return `true` if this type is a subtype of the given [type] (written in
+   * the spec as "T <: S", where T=[this] and S=[type]).
    *
-   * The given set of [visitedTypePairs] of types (T1, T2), where each pair
-   * indicates that we invoked this method because we are in the process of
-   * answering the question of whether T1 is a subtype of T2, is used to prevent
-   * infinite loops.
+   * The sets [thisExpansions] and [typeExpansions], if given, are the sets of
+   * function type aliases that have been expanded so far in the process of
+   * reaching [this] and [type], respectively.  These are used to avoid
+   * infinite regress when analyzing invalid code; since the language spec
+   * forbids a typedef from referring to itself directly or indirectly, we can
+   * use these as sets of function type aliases that don't need to be expanded.
    */
-  bool isMoreSpecificThan2(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
-    // If the visitedTypePairs already has the pair (this, type), return false
-    TypeImpl_TypePair typePair = new TypeImpl_TypePair(this, type);
-    if (!visitedTypePairs.add(typePair)) {
-      return false;
-    }
-    bool result =
-        internalIsMoreSpecificThan(type, withDynamic, visitedTypePairs);
-    visitedTypePairs.remove(typePair);
-    return result;
-  }
-
   @override
-  bool isSubtypeOf(DartType type) =>
-      isSubtypeOf2(type, new HashSet<TypeImpl_TypePair>());
-
-  /**
-   * Return `true` if this type is a subtype of the given [type].
-   *
-   * The given set of [visitedTypePairs] of types (T1, T2), where each pair
-   * indicates that we invoked this method because we are in the process of
-   * answering the question of whether T1 is a subtype of T2, is used to prevent
-   * infinite loops.
-   */
-  bool isSubtypeOf2(DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
-    // If the visitedTypePairs already has the pair (this, type), return false
-    TypeImpl_TypePair typePair = new TypeImpl_TypePair(this, type);
-    if (!visitedTypePairs.add(typePair)) {
-      return false;
-    }
-    bool result = internalIsSubtypeOf(type, visitedTypePairs);
-    visitedTypePairs.remove(typePair);
-    return result;
+  bool isSubtypeOf(DartType type,
+      [Set<Element> thisExpansions, Set<Element> typeExpansions]) {
+    // For non-function types, T <: S iff [_|_/dynamic]T << S.
+    return isMoreSpecificThan(type, thisExpansions, typeExpansions, true);
   }
 
   @override
@@ -9581,66 +9517,6 @@
 }
 
 /**
- * A pair of types, used to prevent infinite recursion when performing certain
- * computations.
- */
-class TypeImpl_TypePair {
-  /**
-   * The first type in the pair.
-   */
-  final DartType _firstType;
-
-  /**
-   * The second type in the pair.
-   */
-  final DartType _secondType;
-
-  /**
-   * The hash code of the pair. This is cached on first access in order to
-   * improve performance.
-   */
-  int _cachedHashCode;
-
-  /**
-   * Initialize a newly created pair of types to have the given [_firstType] and
-   * [_secondType].
-   */
-  TypeImpl_TypePair(this._firstType, this._secondType);
-
-  @override
-  int get hashCode {
-    if (_cachedHashCode == null) {
-      int firstHashCode = 0;
-      if (_firstType != null) {
-        Element firstElement = _firstType.element;
-        firstHashCode = firstElement == null ? 0 : firstElement.hashCode;
-      }
-      int secondHashCode = 0;
-      if (_secondType != null) {
-        Element secondElement = _secondType.element;
-        secondHashCode = secondElement == null ? 0 : secondElement.hashCode;
-      }
-      _cachedHashCode = firstHashCode + secondHashCode;
-    }
-    return _cachedHashCode;
-  }
-
-  @override
-  bool operator ==(Object object) {
-    if (identical(object, this)) {
-      return true;
-    }
-    if (object is TypeImpl_TypePair) {
-      TypeImpl_TypePair typePair = object;
-      return _firstType == typePair._firstType &&
-          _secondType != null &&
-          _secondType == typePair._secondType;
-    }
-    return false;
-  }
-}
-
-/**
  * A type parameter.
  */
 abstract class TypeParameterElement implements Element {
@@ -9748,8 +9624,9 @@
   int internalHashCode(List<DartType> visitedTypes) => hashCode;
 
   @override
-  bool internalIsMoreSpecificThan(
-      DartType s, bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
+  bool isMoreSpecificThan(DartType s, [Set<Element> thisExpansions,
+      Set<Element> typeExpansions, bool withDynamic = false,
+      Set<Element> visitedElements]) {
     //
     // A type T is more specific than a type S, written T << S,
     // if one of the following conditions is met:
@@ -9764,33 +9641,10 @@
     if (s.isDynamic) {
       return true;
     }
-    return _isMoreSpecificThan(
-        s, new HashSet<DartType>(), withDynamic, visitedTypePairs);
-  }
-
-  @override
-  bool internalIsSubtypeOf(
-          DartType type, Set<TypeImpl_TypePair> visitedTypePairs) =>
-      isMoreSpecificThan2(type, true, new HashSet<TypeImpl_TypePair>());
-
-  @override
-  DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes) {
-    int length = parameterTypes.length;
-    for (int i = 0; i < length; i++) {
-      if (parameterTypes[i] == this) {
-        return argumentTypes[i];
-      }
-    }
-    return this;
-  }
-
-  bool _isMoreSpecificThan(DartType s, Set<DartType> visitedTypes,
-      bool withDynamic, Set<TypeImpl_TypePair> visitedTypePairs) {
     //
     // T is a type parameter and S is the upper bound of T.
     //
-    DartType bound = element.bound;
+    TypeImpl bound = element.bound;
     if (s == bound) {
       return true;
     }
@@ -9807,20 +9661,39 @@
     //
     // Transitivity: T << U and U << S.
     //
-    if (bound is TypeParameterTypeImpl) {
-      TypeParameterTypeImpl boundTypeParameter = bound;
-      // First check for infinite loops
-      if (visitedTypes.contains(bound)) {
-        return false;
-      }
-      visitedTypes.add(bound);
-      // Then check upper bound.
-      return boundTypeParameter._isMoreSpecificThan(
-          s, visitedTypes, withDynamic, visitedTypePairs);
+    // First check for infinite loops
+    if (element == null) {
+      return false;
     }
-    // Check interface type.
-    return (bound as TypeImpl).isMoreSpecificThan2(
-        s, withDynamic, visitedTypePairs);
+    if (visitedElements == null) {
+      visitedElements = new HashSet<Element>();
+    } else if (visitedElements.contains(element)) {
+      return false;
+    }
+    visitedElements.add(element);
+    try {
+      return bound.isMoreSpecificThan(
+          s, thisExpansions, typeExpansions, withDynamic, visitedElements);
+    } finally {
+      visitedElements.remove(element);
+    }
+  }
+
+  @override
+  bool isSubtypeOf(DartType type,
+          [Set<Element> thisExpansions, Set<Element> typeExpansions]) =>
+      isMoreSpecificThan(type, thisExpansions, typeExpansions, true);
+
+  @override
+  DartType substitute2(
+      List<DartType> argumentTypes, List<DartType> parameterTypes) {
+    int length = parameterTypes.length;
+    for (int i = 0; i < length; i++) {
+      if (parameterTypes[i] == this) {
+        return argumentTypes[i];
+      }
+    }
+    return this;
   }
 
   /**
@@ -9893,8 +9766,9 @@
   int internalHashCode(List<DartType> visitedTypes) => hashCode;
 
   @override
-  bool internalIsMoreSpecificThan(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
+  bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions,
+      Set<Element> typeExpansions, bool withDynamic = false,
+      Set<Element> visitedElements]) {
     // T is S
     if (identical(this, type)) {
       return true;
@@ -9904,8 +9778,8 @@
   }
 
   @override
-  bool internalIsSubtypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs) => true;
+  bool isSubtypeOf(DartType type,
+      [Set<Element> thisExpansions, Set<Element> typeExpansions]) => true;
 
   @override
   bool isSupertypeOf(DartType type) => true;
@@ -9924,221 +9798,6 @@
 }
 
 /**
- * A union of other types. Union types are "flattened" in the sense that a union
- * type never contains another union type.
- */
-abstract class UnionType implements DartType {
-  /**
-   * Return an immutable view of the types in this union type.
-   */
-  Set<DartType> get elements;
-}
-
-/**
- * In addition to the methods of the `UnionType` interface we add a factory
- * method `union` for building unions.
- */
-class UnionTypeImpl extends TypeImpl implements UnionType {
-  /**
-   * The types in this union.
-   */
-  final Set<DartType> _types;
-
-  /**
-   * This constructor should only be called by the `union` factory: it does not
-   * check that its argument [types] contains no union types.
-   */
-  UnionTypeImpl(this._types) : super(null, null);
-
-  @override
-  String get displayName {
-    StringBuffer buffer = new StringBuffer();
-    String prefix = "{";
-    for (DartType t in _types) {
-      buffer.write(prefix);
-      buffer.write(t.displayName);
-      prefix = ",";
-    }
-    buffer.write("}");
-    return buffer.toString();
-  }
-
-  @override
-  Set<DartType> get elements => _types;
-
-  @override
-  int get hashCode => _types.hashCode;
-
-  @override
-  bool operator ==(Object other) {
-    if (other == null || other is! UnionType) {
-      return false;
-    } else if (identical(this, other)) {
-      return true;
-    } else {
-      return javaSetEquals(_types, (other as UnionType).elements);
-    }
-  }
-
-  @override
-  void appendTo(StringBuffer buffer, Set<DartType> visitedTypes) {
-    if (!visitedTypes.add(this)) {
-      buffer.write(name == null ? '...' : name);
-      return;
-    }
-    String prefix = "{";
-    for (DartType type in _types) {
-      buffer.write(prefix);
-      (type as TypeImpl).appendTo(buffer, visitedTypes);
-      prefix = ",";
-    }
-    buffer.write("}");
-  }
-
-  @override
-  bool internalEquals(Object object, Set<ElementPair> visitedElementPairs) =>
-      this == object;
-
-  @override
-  int internalHashCode(List<DartType> visitedTypes) => hashCode;
-
-  @override
-  bool internalIsMoreSpecificThan(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
-    // What version of subtyping do we want? See discussion below in
-    // [internalIsSubtypeOf].
-    if (AnalysisEngine.instance.strictUnionTypes) {
-      // The less unsound version: all.
-      for (DartType t in _types) {
-        if (!(t as TypeImpl).internalIsMoreSpecificThan(
-            type, withDynamic, visitedTypePairs)) {
-          return false;
-        }
-      }
-      return true;
-    } else {
-      // The more unsound version: any.
-      for (DartType t in _types) {
-        if ((t as TypeImpl).internalIsMoreSpecificThan(
-            type, withDynamic, visitedTypePairs)) {
-          return true;
-        }
-      }
-      return false;
-    }
-  }
-
-  @override
-  bool internalIsSubtypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
-    if (AnalysisEngine.instance.strictUnionTypes) {
-      // The less unsound version: all.
-      //
-      // For this version to make sense we also need to redefine assignment
-      // compatibility [<=>].
-      // See discussion above.
-      for (DartType t in _types) {
-        if (!(t as TypeImpl).internalIsSubtypeOf(type, visitedTypePairs)) {
-          return false;
-        }
-      }
-      return true;
-    } else {
-      // The more unsound version: any.
-      for (DartType t in _types) {
-        if ((t as TypeImpl).internalIsSubtypeOf(type, visitedTypePairs)) {
-          return true;
-        }
-      }
-      return false;
-    }
-  }
-
-  /**
-   * The more-specific-than test for union types on the RHS is uniform in
-   * non-union LHSs. So, other `TypeImpl`s can call this method to implement
-   * [internalIsMoreSpecificThan] for union types.
-   */
-  bool internalUnionTypeIsLessSpecificThan(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) {
-    // This implementation does not make sense when [type] is a union type,
-    // at least for the "less unsound" version of [internalIsMoreSpecificThan]
-    // above.
-    if (type is UnionType) {
-      throw new IllegalArgumentException("Only non-union types are supported.");
-    }
-    for (DartType t in _types) {
-      if ((type as TypeImpl).internalIsMoreSpecificThan(
-          t, withDynamic, visitedTypePairs)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * The supertype test for union types is uniform in non-union subtypes. So,
-   * other `TypeImpl`s can call this method to implement `internalIsSubtypeOf`
-   * for union types.
-   */
-  bool internalUnionTypeIsSuperTypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
-    // This implementation does not make sense when [type] is a union type,
-    // at least for the "less unsound" version of [internalIsSubtypeOf] above.
-    if (type is UnionType) {
-      throw new IllegalArgumentException("Only non-union types are supported.");
-    }
-    for (DartType t in _types) {
-      if ((type as TypeImpl).internalIsSubtypeOf(t, visitedTypePairs)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @override
-  DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes) {
-    List<DartType> out = new List<DartType>();
-    for (DartType t in _types) {
-      out.add(t.substitute2(argumentTypes, parameterTypes));
-    }
-    return union(out);
-  }
-
-  /**
-   * Return the union of the given [types]. Any unions in the [types] will be
-   * flattened in the returned union. If there is only one type after flattening
-   * then it will be returned directly, instead of a singleton union. Nulls are
-   * discarded, unless all types are null, in which case an exception is raised.
-   */
-  static DartType union(List<DartType> types) {
-    Set<DartType> set = new HashSet<DartType>();
-    for (DartType t in types) {
-      if (t is UnionType) {
-        set.addAll(t.elements);
-      } else {
-        if (t != null) {
-          set.add(t);
-        }
-      }
-    }
-    if (set.length == 0) {
-      // TODO(collinsn): better to return [null] here? The use case is e.g.
-      //
-      //   union(null, null) ==> null;
-      //
-      // instead of raising an exception.
-      throw new IllegalArgumentException("No known use case for empty unions.");
-    } else if (set.length == 1) {
-      return set.first;
-    } else {
-      return new UnionTypeImpl(set);
-    }
-  }
-}
-
-/**
  * An element included into a library using some URI.
  */
 abstract class UriReferencedElement implements Element {
@@ -10214,6 +9873,22 @@
   bool get isFinal;
 
   /**
+   * Return `true` if this variable is potentially mutated somewhere in a
+   * closure. This information is only available for local variables (including
+   * parameters) and only after the compilation unit containing the variable has
+   * been resolved.
+   */
+  bool get isPotentiallyMutatedInClosure;
+
+  /**
+   * Return `true` if this variable is potentially mutated somewhere in its
+   * scope. This information is only available for local variables (including
+   * parameters) and only after the compilation unit containing the variable has
+   * been resolved.
+   */
+  bool get isPotentiallyMutatedInScope;
+
+  /**
    * Return the resolved [VariableDeclaration] node that declares this
    * [VariableElement].
    *
@@ -10314,20 +9989,10 @@
   @override
   bool get isFinal => hasModifier(Modifier.FINAL);
 
-  /**
-   * Return `true` if this variable is potentially mutated somewhere in a
-   * closure. This information is only available for local variables (including
-   * parameters) and only after the compilation unit containing the variable has
-   * been resolved.
-   */
+  @override
   bool get isPotentiallyMutatedInClosure => false;
 
-  /**
-   * Return `true` if this variable is potentially mutated somewhere in its
-   * scope. This information is only available for local variables (including
-   * parameters) and only after the compilation unit containing the variable has
-   * been resolved.
-   */
+  @override
   bool get isPotentiallyMutatedInScope => false;
 
   @override
@@ -10380,6 +10045,14 @@
   bool get isFinal => baseElement.isFinal;
 
   @override
+  bool get isPotentiallyMutatedInClosure =>
+      baseElement.isPotentiallyMutatedInClosure;
+
+  @override
+  bool get isPotentiallyMutatedInScope =>
+      baseElement.isPotentiallyMutatedInScope;
+
+  @override
   VariableDeclaration get node => baseElement.node;
 
   @override
@@ -10439,16 +10112,13 @@
   int internalHashCode(List<DartType> visitedTypes) => hashCode;
 
   @override
-  bool internalIsMoreSpecificThan(DartType type, bool withDynamic,
-      Set<TypeImpl_TypePair> visitedTypePairs) => isSubtypeOf(type);
+  bool isMoreSpecificThan(DartType type, [Set<Element> thisExpansions,
+      Set<Element> typeExpansions, bool withDynamic = false,
+      Set<Element> visitedElements]) => isSubtypeOf(type);
 
   @override
-  bool internalIsSubtypeOf(
-      DartType type, Set<TypeImpl_TypePair> visitedTypePairs) {
-    if (type is UnionType) {
-      return (type as UnionTypeImpl).internalUnionTypeIsSuperTypeOf(
-          this, visitedTypePairs);
-    }
+  bool isSubtypeOf(DartType type,
+      [Set<Element> thisExpansions, Set<Element> typeExpansions]) {
     // The only subtype relations that pertain to void are therefore:
     // void <: void (by reflexivity)
     // bottom <: void (as bottom is a subtype of all types).
@@ -10460,3 +10130,21 @@
   VoidTypeImpl substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes) => this;
 }
+
+/**
+ * A visitor that visit all the elements recursively and fill the given [map].
+ */
+class _BuildOffsetToElementMap extends GeneralizingElementVisitor {
+  final Map<int, Element> map;
+
+  _BuildOffsetToElementMap(this.map);
+
+  @override
+  void visitElement(Element element) {
+    int offset = element.nameOffset;
+    if (offset != -1) {
+      map[offset] = element;
+    }
+    super.visitElement(element);
+  }
+}
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
index d29787e..4c5acae 100644
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ b/pkg/analyzer/lib/src/generated/element_handle.dart
@@ -803,6 +803,9 @@
   List<LibraryElement> get visibleLibraries => actualElement.visibleLibraries;
 
   @override
+  Element getElementAt(int offset) => actualElement.getElementAt(offset);
+
+  @override
   List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) =>
       actualElement.getImportsWithPrefix(prefixElement);
 
@@ -1072,6 +1075,14 @@
   bool get isFinal => actualElement.isFinal;
 
   @override
+  bool get isPotentiallyMutatedInClosure =>
+      actualElement.isPotentiallyMutatedInClosure;
+
+  @override
+  bool get isPotentiallyMutatedInScope =>
+      actualElement.isPotentiallyMutatedInScope;
+
+  @override
   VariableDeclaration get node => actualElement.node;
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index afdf322..9009aae 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -146,7 +146,8 @@
   Object visitAssignmentExpression(AssignmentExpression node) {
     sc.Token operator = node.operator;
     sc.TokenType operatorType = operator.type;
-    if (operatorType != sc.TokenType.EQ) {
+    if (operatorType != sc.TokenType.EQ &&
+        operatorType != sc.TokenType.QUESTION_QUESTION_EQ) {
       operatorType = _operatorFromCompoundAssignment(operatorType);
       Expression leftHandSide = node.leftHandSide;
       if (leftHandSide != null) {
@@ -592,10 +593,12 @@
       propagatedType = _getPropagatedType(target);
       //
       // If this method invocation is of the form 'C.m' where 'C' is a class,
-      // then we don't call resolveInvokedElement(..) which walks up the class
-      // hierarchy, instead we just look for the member in the type only.
+      // then we don't call resolveInvokedElement(...) which walks up the class
+      // hierarchy, instead we just look for the member in the type only.  This
+      // does not apply to conditional method invocation (i.e. 'C?.m(...)').
       //
-      ClassElementImpl typeReference = getTypeReference(target);
+      bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
+      ClassElementImpl typeReference = getTypeReference(target, isConditional);
       if (typeReference != null) {
         staticElement =
             propagatedElement = _resolveElement(typeReference, methodName);
@@ -636,15 +639,6 @@
     if (_enableHints && errorCode == null && staticElement == null) {
       // The method lookup may have failed because there were multiple
       // incompatible choices. In this case we don't want to generate a hint.
-      if (propagatedElement == null && propagatedType is UnionType) {
-        // TODO(collinsn): an improvement here is to make the propagated type
-        // of the method call the union of the propagated types of all possible
-        // calls.
-        if (_lookupMethods(target, propagatedType, methodName.name).length >
-            1) {
-          return null;
-        }
-      }
       errorCode = _checkForInvocationError(target, false, propagatedElement);
       if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
         ClassElement classElementContext = null;
@@ -854,7 +848,7 @@
     // Otherwise, the prefix is really an expression that happens to be a simple
     // identifier and this is really equivalent to a property access node.
     //
-    _resolvePropertyAccess(prefix, identifier);
+    _resolvePropertyAccess(prefix, identifier, false);
     return null;
   }
 
@@ -910,7 +904,8 @@
       return null;
     }
     SimpleIdentifier propertyName = node.propertyName;
-    _resolvePropertyAccess(target, propertyName);
+    _resolvePropertyAccess(target, propertyName,
+        node.operator.type == sc.TokenType.QUESTION_PERIOD);
     return null;
   }
 
@@ -1719,13 +1714,6 @@
       }
       return _lookUpMethodInInterfaces(
           interfaceType, false, methodName, new HashSet<ClassElement>());
-    } else if (type is UnionType) {
-      // TODO (collinsn): I want [computeMergedExecutableElement] to be general
-      // and work with functions, methods, constructors, and property accessors.
-      // However, I won't be able to assume it returns [MethodElement] here
-      // then.
-      return _maybeMergeExecutableElements(
-          _lookupMethods(target, type, methodName)) as MethodElement;
     }
     return null;
   }
@@ -1781,35 +1769,6 @@
   }
 
   /**
-   * Look up all methods with the given [methodName] that are defined on the
-   * given union [type].
-   */
-  Set<ExecutableElement> _lookupMethods(
-      Expression target, UnionType type, String methodName) {
-    Set<ExecutableElement> methods = new HashSet<ExecutableElement>();
-    bool allElementsHaveMethod = true;
-    for (DartType t in type.elements) {
-      MethodElement m = _lookUpMethod(target, t, methodName);
-      if (m != null) {
-        methods.add(m);
-      } else {
-        allElementsHaveMethod = false;
-      }
-    }
-    // For strict union types we require that all types in the union define the
-    // method.
-    if (AnalysisEngine.instance.strictUnionTypes) {
-      if (allElementsHaveMethod) {
-        return methods;
-      } else {
-        return new Set<ExecutableElement>();
-      }
-    } else {
-      return methods;
-    }
-  }
-
-  /**
    * Look up the setter with the given [setterName] in the given [type]. Return
    * the element representing the setter that was found, or `null` if there is
    * no setter with the given name. The [target] is the target of the
@@ -2385,7 +2344,7 @@
    */
   Element _resolveInvokedElementWithTarget(
       Expression target, DartType targetType, SimpleIdentifier methodName) {
-    if (targetType is InterfaceType || targetType is UnionType) {
+    if (targetType is InterfaceType) {
       Element element = _lookUpMethod(target, targetType, methodName.name);
       if (element == null) {
         //
@@ -2442,17 +2401,18 @@
   }
 
   void _resolvePropertyAccess(
-      Expression target, SimpleIdentifier propertyName) {
+      Expression target, SimpleIdentifier propertyName, bool isConditional) {
     DartType staticType = _getStaticType(target);
     DartType propagatedType = _getPropagatedType(target);
     Element staticElement = null;
     Element propagatedElement = null;
     //
     // If this property access is of the form 'C.m' where 'C' is a class,
-    // then we don't call resolveProperty(..) which walks up the class
-    // hierarchy, instead we just look for the member in the type only.
+    // then we don't call resolveProperty(...) which walks up the class
+    // hierarchy, instead we just look for the member in the type only.  This
+    // does not apply to conditional property accesses (i.e. 'C?.m').
     //
-    ClassElementImpl typeReference = getTypeReference(target);
+    ClassElementImpl typeReference = getTypeReference(target, isConditional);
     if (typeReference != null) {
       // TODO(brianwilkerson) Why are we setting the propagated element here?
       // It looks wrong.
@@ -2481,12 +2441,6 @@
             _shouldReportMissingMember(propagatedType, propagatedElement) &&
             !_memberFoundInSubclass(
                 propagatedType.element, propertyName.name, false, true);
-    // TODO(collinsn): add support for errors on union types by extending
-    // [lookupGetter] and [lookupSetter] in analogy with the earlier
-    // [lookupMethod] extensions.
-    if (propagatedType is UnionType) {
-      shouldReportMissingMember_propagated = false;
-    }
     if (shouldReportMissingMember_static ||
         shouldReportMissingMember_propagated) {
       DartType staticOrPropagatedType =
@@ -2700,10 +2654,12 @@
   /**
    * Checks whether the given [expression] is a reference to a class. If it is
    * then the element representing the class is returned, otherwise `null` is
-   * returned.
+   * returned.  [isConditional] indicates whether [expression] is to the left
+   * of a '?.' opertator.
    */
-  static ClassElementImpl getTypeReference(Expression expression) {
-    if (expression is Identifier) {
+  static ClassElementImpl getTypeReference(
+      Expression expression, bool isConditional) {
+    if (!isConditional && expression is Identifier) {
       Element staticElement = expression.staticElement;
       if (staticElement is ClassElementImpl) {
         return staticElement;
@@ -2713,80 +2669,6 @@
   }
 
   /**
-   * Helper function for `maybeMergeExecutableElements` that does the actual
-   * merging. The [elementArrayToMerge] is the non-empty list of elements to
-   * merge.
-   */
-  static ExecutableElement _computeMergedExecutableElement(
-      List<ExecutableElement> elementArrayToMerge) {
-    // Flatten methods structurally. Based on
-    // [InheritanceManager.computeMergedExecutableElement] and
-    // [InheritanceManager.createSyntheticExecutableElement].
-    //
-    // However, the approach we take here is much simpler, but expected to work
-    // well in the common case. It degrades gracefully in the uncommon case,
-    // by computing the type [dynamic] for the method, preventing any
-    // hints from being generated (TODO: not done yet).
-    //
-    // The approach is: we require that each [ExecutableElement] has the
-    // same shape: the same number of required, optional positional, and
-    // optional named parameters, in the same positions, and with the named
-    // parameters in the same order. We compute a type by unioning pointwise.
-    ExecutableElement e_0 = elementArrayToMerge[0];
-    List<ParameterElement> ps_0 = e_0.parameters;
-    List<ParameterElementImpl> ps_out =
-        new List<ParameterElementImpl>(ps_0.length);
-    for (int j = 0; j < ps_out.length; j++) {
-      ps_out[j] = new ParameterElementImpl(ps_0[j].name, 0);
-      ps_out[j].synthetic = true;
-      ps_out[j].type = ps_0[j].type;
-      ps_out[j].parameterKind = ps_0[j].parameterKind;
-    }
-    DartType r_out = e_0.returnType;
-    for (int i = 1; i < elementArrayToMerge.length; i++) {
-      ExecutableElement e_i = elementArrayToMerge[i];
-      r_out = UnionTypeImpl.union([r_out, e_i.returnType]);
-      List<ParameterElement> ps_i = e_i.parameters;
-      // Each function must have the same number of params.
-      if (ps_0.length != ps_i.length) {
-        return null;
-        // TODO (collinsn): return an element representing [dynamic] here
-        // instead.
-      } else {
-        // Each function must have the same kind of params, with the same names,
-        // in the same order.
-        for (int j = 0; j < ps_i.length; j++) {
-          if (ps_0[j].parameterKind != ps_i[j].parameterKind ||
-              !identical(ps_0[j].name, ps_i[j].name)) {
-            return null;
-          } else {
-            // The output parameter type is the union of the input parameter
-            // types.
-            ps_out[j].type =
-                UnionTypeImpl.union([ps_out[j].type, ps_i[j].type]);
-          }
-        }
-      }
-    }
-    // TODO (collinsn): this code should work for functions and methods,
-    // so we may want [FunctionElementImpl]
-    // instead here in some cases?
-    // And then there are constructors and property accessors.
-    // Maybe the answer is to create a new subclass of [ExecutableElementImpl]
-    // which is used for merged executable elements, in analogy with
-    // [MultiplyInheritedMethodElementImpl] and
-    // [MultiplyInheritedPropertyAcessorElementImpl].
-    ExecutableElementImpl e_out = new MethodElementImpl(e_0.name, 0);
-    e_out.synthetic = true;
-    e_out.returnType = r_out;
-    e_out.parameters = ps_out;
-    e_out.type = new FunctionTypeImpl.con1(e_out);
-    // Get NPE in [toString()] w/o this.
-    e_out.enclosingElement = e_0.enclosingElement;
-    return e_out;
-  }
-
-  /**
    * Return `true` if the given [identifier] is the return type of a constructor
    * declaration.
    */
@@ -2832,25 +2714,6 @@
     }
     return false;
   }
-
-  /**
-   * Return a method representing the merge of the given [elements]. The type of
-   * the merged element is the component-wise union of the types of the given
-   * elements. If not all input elements have the same shape then `null` is
-   * returned.
-   */
-  static ExecutableElement _maybeMergeExecutableElements(
-      Set<ExecutableElement> elements) {
-    List<ExecutableElement> elementArrayToMerge = new List.from(elements);
-    if (elementArrayToMerge.length == 0) {
-      return null;
-    } else if (elementArrayToMerge.length == 1) {
-      // If all methods are equal, don't bother building a new one.
-      return elementArrayToMerge[0];
-    } else {
-      return _computeMergedExecutableElement(elementArrayToMerge);
-    }
-  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index f2f12c6..4cd2f615 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -13,6 +13,7 @@
 
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/generated/incremental_resolution_validator.dart';
+import 'package:analyzer/src/plugin/engine_plugin.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/task/task_dart.dart';
 
@@ -35,7 +36,6 @@
 import 'source.dart';
 import 'utilities_collection.dart';
 import 'utilities_general.dart';
-import 'package:analyzer/src/plugin/engine_plugin.dart';
 
 /**
  * Used by [AnalysisOptions] to allow function bodies to be analyzed in some
@@ -1018,6 +1018,11 @@
   TypeResolverVisitorFactory typeResolverVisitorFactory;
 
   /**
+   * A factory to override how [LibraryResolver] is created.
+   */
+  LibraryResolverFactory libraryResolverFactory;
+
+  /**
    * Initialize a newly created analysis context.
    */
   AnalysisContextImpl() {
@@ -1043,6 +1048,8 @@
         this._options.dart2jsHint != options.dart2jsHint ||
         (this._options.hint && !options.hint) ||
         this._options.preserveComments != options.preserveComments ||
+        this._options.enableNullAwareOperators !=
+            options.enableNullAwareOperators ||
         this._options.enableStrictCallChecks != options.enableStrictCallChecks;
     int cacheSize = options.cacheSize;
     if (this._options.cacheSize != cacheSize) {
@@ -1068,6 +1075,7 @@
     this._options.generateImplicitErrors = options.generateImplicitErrors;
     this._options.generateSdkErrors = options.generateSdkErrors;
     this._options.dart2jsHint = options.dart2jsHint;
+    this._options.enableNullAwareOperators = options.enableNullAwareOperators;
     this._options.enableStrictCallChecks = options.enableStrictCallChecks;
     this._options.hint = options.hint;
     this._options.incremental = options.incremental;
@@ -1105,6 +1113,13 @@
       for (int i = 0; i < count; i++) {
         _priorityOrder[i] = sources[i];
       }
+      // Ensure entries for every priority source.
+      for (var source in _priorityOrder) {
+        SourceEntry entry = _getReadableSourceEntry(source);
+        if (entry == null) {
+          _createSourceEntry(source, false);
+        }
+      }
     }
   }
 
@@ -4663,7 +4678,7 @@
       Stopwatch perfCounter = new Stopwatch()..start();
       PoorMansIncrementalResolver resolver = new PoorMansIncrementalResolver(
           typeProvider, unitSource, dartEntry, oldUnit,
-          analysisOptions.incrementalApi);
+          analysisOptions.incrementalApi, analysisOptions);
       bool success = resolver.resolve(newCode);
       AnalysisEngine.instance.instrumentationService.logPerformance(
           AnalysisPerformanceKind.INCREMENTAL, perfCounter,
@@ -5724,17 +5739,6 @@
    */
   final PartitionManager partitionManager = new PartitionManager();
 
-  /**
-   * A flag indicating whether union types should be used.
-   */
-  bool enableUnionTypes = false;
-
-  /**
-   * A flag indicating whether union types should have strict semantics. This
-   * option has no effect when `enabledUnionTypes` is `false`.
-   */
-  bool strictUnionTypes = false;
-
   AnalysisEngine._();
 
   /**
@@ -5994,6 +5998,11 @@
   bool get enableEnum;
 
   /**
+   * Return `true` to enable null-aware operators (DEP 9).
+   */
+  bool get enableNullAwareOperators;
+
+  /**
    * Return `true` to strictly follow the specification when generating
    * warnings on "call" methods (fixes dartbug.com/21938).
    */
@@ -6087,6 +6096,11 @@
   bool dart2jsHint = true;
 
   /**
+   * A flag indicating whether null-aware operators should be parsed (DEP 9).
+   */
+  bool enableNullAwareOperators = false;
+
+  /**
    * A flag indicating whether analysis is to strictly follow the specification
    * when generating warnings on "call" methods (fixes dartbug.com/21938).
    */
@@ -6151,6 +6165,7 @@
     analyzeFunctionBodiesPredicate = options.analyzeFunctionBodiesPredicate;
     cacheSize = options.cacheSize;
     dart2jsHint = options.dart2jsHint;
+    enableNullAwareOperators = options.enableNullAwareOperators;
     enableStrictCallChecks = options.enableStrictCallChecks;
     generateImplicitErrors = options.generateImplicitErrors;
     generateSdkErrors = options.generateSdkErrors;
@@ -8954,8 +8969,8 @@
     // Produce an updated token stream
     CharacterReader reader = new CharSequenceReader(cache.newContents);
     BooleanErrorListener errorListener = new BooleanErrorListener();
-    IncrementalScanner scanner =
-        new IncrementalScanner(cache.source, reader, errorListener);
+    IncrementalScanner scanner = new IncrementalScanner(
+        cache.source, reader, errorListener, context.analysisOptions);
     scanner.rescan(cache.resolvedUnit.beginToken, cache.offset, cache.oldLength,
         cache.newLength);
     if (errorListener.errorReported) {
@@ -9021,6 +9036,11 @@
   TypeResolverVisitorFactory get typeResolverVisitorFactory;
 
   /**
+   * A factory to override how [LibraryResolver] is created.
+   */
+  LibraryResolverFactory get libraryResolverFactory;
+
+  /**
    * Add the given [source] with the given [information] to this context.
    */
   void addSourceInfo(Source source, SourceEntry information);
@@ -9402,10 +9422,14 @@
     UriValidationCode code = directive.validate();
     if (code == null) {
       String encodedUriContent = Uri.encodeFull(uriContent);
-      Source source =
-          context.sourceFactory.resolveUri(librarySource, encodedUriContent);
-      directive.source = source;
-      return source;
+      try {
+        Source source =
+            context.sourceFactory.resolveUri(librarySource, encodedUriContent);
+        directive.source = source;
+        return source;
+      } on JavaIOException {
+        code = UriValidationCode.INVALID_URI;
+      }
     }
     if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
       return null;
@@ -9544,7 +9568,8 @@
       ht.Token token = scanner.tokenize();
       _lineInfo = new LineInfo(scanner.lineStarts);
       RecordingErrorListener errorListener = new RecordingErrorListener();
-      _unit = new ht.HtmlParser(source, errorListener).parse(token, _lineInfo);
+      _unit = new ht.HtmlParser(source, errorListener, context.analysisOptions)
+          .parse(token, _lineInfo);
       _unit.accept(new RecursiveXmlVisitor_ParseHtmlTask_internalPerform(
           this, errorListener));
       _errors = errorListener.getErrorsForSource(source);
@@ -10439,7 +10464,10 @@
 
   @override
   void internalPerform() {
-    _resolver = new LibraryResolver(context);
+    LibraryResolverFactory resolverFactory = context.libraryResolverFactory;
+    _resolver = resolverFactory == null
+        ? new LibraryResolver(context)
+        : resolverFactory(context);
     _resolver.resolveLibrary(librarySource, true);
   }
 }
@@ -10777,6 +10805,8 @@
         Scanner scanner = new Scanner(
             source, new CharSequenceReader(_content), errorListener);
         scanner.preserveComments = context.analysisOptions.preserveComments;
+        scanner.enableNullAwareOperators =
+            context.analysisOptions.enableNullAwareOperators;
         _tokenStream = scanner.tokenize();
         _lineInfo = new LineInfo(scanner.lineStarts);
         _errors = errorListener.getErrorsForSource(source);
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 6ba42dc..9a83ed4 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -704,8 +704,8 @@
    * value.
    */
   static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_BOOL', "An expression of type 'bool' was expected");
+      const CompileTimeErrorCode('CONST_EVAL_TYPE_BOOL',
+          "In constant expressions, operand(s) of this operator must be of type 'bool'");
 
   /**
    * 12.11.2 Const: An expression of one of the forms e1 == e2 or e1 != e2 where
@@ -714,7 +714,7 @@
    */
   static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL_NUM_STRING =
       const CompileTimeErrorCode('CONST_EVAL_TYPE_BOOL_NUM_STRING',
-          "An expression of type 'bool', 'num', 'String' or 'null' was expected");
+          "In constant expressions, operands of this operator must be of type 'bool', 'num', 'String' or 'null'");
 
   /**
    * 12.11.2 Const: An expression of one of the forms ~e, e1 ^ e2, e1 & e2,
@@ -722,8 +722,8 @@
    * that evaluate to an integer value or to null.
    */
   static const CompileTimeErrorCode CONST_EVAL_TYPE_INT =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_INT', "An expression of type 'int' was expected");
+      const CompileTimeErrorCode('CONST_EVAL_TYPE_INT',
+          "In constant expressions, operand(s) of this operator must be of type 'int'");
 
   /**
    * 12.11.2 Const: An expression of one of the forms e, e1 + e2, e1 - e2, e1 *
@@ -732,8 +732,8 @@
    * value or to null.
    */
   static const CompileTimeErrorCode CONST_EVAL_TYPE_NUM =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_NUM', "An expression of type 'num' was expected");
+      const CompileTimeErrorCode('CONST_EVAL_TYPE_NUM',
+          "In constant expressions, operand(s) of this operator must be of type 'num'");
 
   /**
    * 12.11.2 Const: It is a compile-time error if evaluation of a constant
@@ -2474,8 +2474,16 @@
    */
   void reportErrorForElement(
       ErrorCode errorCode, Element element, List<Object> arguments) {
-    reportErrorForOffset(
-        errorCode, element.nameOffset, element.displayName.length, arguments);
+    String displayName = element.displayName;
+    int length = 0;
+    if (displayName != null) {
+      length = displayName.length;
+    } else if (element is ImportElement) {
+      length = 6; // 'import'.length
+    } else if (element is ExportElement) {
+      length = 6; // 'export'.length
+    }
+    reportErrorForOffset(errorCode, element.nameOffset, length, arguments);
   }
 
   /**
@@ -3734,6 +3742,16 @@
       'ASSIGNMENT_TO_METHOD', "Methods cannot be assigned a value");
 
   /**
+   * 12.18 Assignment: It is as static warning if an assignment of the form
+   * <i>v = e</i> occurs inside a top level or static function (be it function,
+   * method, getter, or setter) or variable initializer and there is neither a
+   * local variable declaration with name <i>v</i> nor setter declaration with
+   * name <i>v=</i> in the lexical scope enclosing the assignment.
+   */
+  static const StaticWarningCode ASSIGNMENT_TO_TYPE = const StaticWarningCode(
+      'ASSIGNMENT_TO_TYPE', "Types cannot be assigned a value");
+
+  /**
    * 13.9 Switch: It is a static warning if the last statement of the statement
    * sequence <i>s<sub>k</sub></i> is not a break, continue, return or throw
    * statement.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 74c14ae..9bfb167 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -270,14 +270,7 @@
     _isInStaticMethod = false;
     _boolType = _typeProvider.boolType;
     _intType = _typeProvider.intType;
-    _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = <InterfaceType>[
-      _typeProvider.nullType,
-      _typeProvider.numType,
-      _intType,
-      _typeProvider.doubleType,
-      _boolType,
-      _typeProvider.stringType
-    ];
+    _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = _typeProvider.nonSubtypableTypes;
   }
 
   @override
@@ -309,7 +302,8 @@
     sc.TokenType operatorType = node.operator.type;
     Expression lhs = node.leftHandSide;
     Expression rhs = node.rightHandSide;
-    if (operatorType == sc.TokenType.EQ) {
+    if (operatorType == sc.TokenType.EQ ||
+        operatorType == sc.TokenType.QUESTION_QUESTION_EQ) {
       _checkForInvalidAssignment(lhs, rhs);
     } else {
       _checkForInvalidCompoundAssignment(node, lhs, rhs);
@@ -863,7 +857,9 @@
     Expression target = node.realTarget;
     SimpleIdentifier methodName = node.methodName;
     if (target != null) {
-      ClassElement typeReference = ElementResolver.getTypeReference(target);
+      bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
+      ClassElement typeReference =
+          ElementResolver.getTypeReference(target, isConditional);
       _checkForStaticAccessToInstanceMember(typeReference, methodName);
       _checkForInstanceAccessToStaticMember(typeReference, methodName);
     } else {
@@ -900,7 +896,7 @@
   Object visitPrefixedIdentifier(PrefixedIdentifier node) {
     if (node.parent is! Annotation) {
       ClassElement typeReference =
-          ElementResolver.getTypeReference(node.prefix);
+          ElementResolver.getTypeReference(node.prefix, false);
       SimpleIdentifier name = node.identifier;
       _checkForStaticAccessToInstanceMember(typeReference, name);
       _checkForInstanceAccessToStaticMember(typeReference, name);
@@ -923,8 +919,9 @@
 
   @override
   Object visitPropertyAccess(PropertyAccess node) {
+    bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
     ClassElement typeReference =
-        ElementResolver.getTypeReference(node.realTarget);
+        ElementResolver.getTypeReference(node.realTarget, isConditional);
     SimpleIdentifier propertyName = node.propertyName;
     _checkForStaticAccessToInstanceMember(typeReference, propertyName);
     _checkForInstanceAccessToStaticMember(typeReference, propertyName);
@@ -2003,6 +2000,13 @@
           StaticWarningCode.ASSIGNMENT_TO_METHOD, expression);
       return true;
     }
+    if (element is ClassElement ||
+        element is FunctionTypeAliasElement ||
+        element is TypeParameterElement) {
+      _errorReporter.reportErrorForNode(
+          StaticWarningCode.ASSIGNMENT_TO_TYPE, expression);
+      return true;
+    }
     return false;
   }
 
diff --git a/pkg/analyzer/lib/src/generated/html.dart b/pkg/analyzer/lib/src/generated/html.dart
index c8cc1d3..c6ad0e0 100644
--- a/pkg/analyzer/lib/src/generated/html.dart
+++ b/pkg/analyzer/lib/src/generated/html.dart
@@ -11,7 +11,7 @@
 
 import 'ast.dart';
 import 'element.dart';
-import 'engine.dart' show AnalysisEngine;
+import 'engine.dart' show AnalysisOptions, AnalysisEngine;
 import 'error.dart' show AnalysisErrorListener;
 import 'java_core.dart';
 import 'java_engine.dart';
@@ -388,13 +388,16 @@
    */
   final AnalysisErrorListener _errorListener;
 
+  final AnalysisOptions _options;
+
   /**
    * Construct a parser for the specified source.
    *
-   * @param source the source being parsed
-   * @param errorListener the error listener to which errors will be reported
+   * [source] is the source being parsed.  [_errorListener] is the error
+   * listener to which errors will be reported.  [_options] is the analysis
+   * options which should be used for parsing.
    */
-  HtmlParser(Source source, this._errorListener) : super(source);
+  HtmlParser(Source source, this._errorListener, this._options) : super(source);
 
   @override
   XmlAttributeNode createAttributeNode(Token name, Token equals, Token value) =>
@@ -413,6 +416,7 @@
       LineInfo_Location location = _lineInfo.getLocation(contentOffset);
       sc.Scanner scanner = new sc.Scanner(source,
           new sc.SubSequenceReader(contents, contentOffset), _errorListener);
+      scanner.enableNullAwareOperators = _options.enableNullAwareOperators;
       scanner.setSourceStart(location.lineNumber, location.columnNumber);
       sc.Token firstToken = scanner.tokenize();
       Parser parser = new Parser(source, _errorListener);
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index ea6aac7..1e9b61d 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 import 'dart:math' as math;
 
+import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/services/lint.dart';
 
 import 'ast.dart';
@@ -184,14 +185,9 @@
         ? _enclosingClass.unnamedConstructor
         : _enclosingClass.getNamedConstructor(constructorName.name);
     _processElement(element);
+    _assertEquals(node.constKeyword != null, element.isConst);
+    _assertEquals(node.factoryKeyword != null, element.isFactory);
     _assertCompatibleParameters(node.parameters, element.parameters);
-    // TODO(scheglov) debug null Location
-    if (element != null) {
-      if (element.context == null || element.source == null) {
-        logger.log(
-            'Bad constructor element $element for $node in ${node.parent}');
-      }
-    }
     // matches, update the existing element
     ExecutableElement newElement = node.element;
     node.element = element;
@@ -807,7 +803,7 @@
   /**
    * The element for the library containing the compilation unit being resolved.
    */
-  LibraryElement _definingLibrary;
+  LibraryElementImpl _definingLibrary;
 
   /**
    * The [DartEntry] corresponding to the source being resolved.
@@ -883,12 +879,16 @@
       }
       // resolve
       _resolveReferences(rootNode);
+      _computeConstants(rootNode);
+      _resolveErrors = errorListener.getErrorsForSource(_source);
       // verify
       _verify(rootNode);
       _context.invalidateLibraryHints(_librarySource);
       _generateLints(rootNode);
       // update entry errors
       _updateEntry();
+      // notify library
+      _definingLibrary.afterIncrementalResolution();
       // OK
       return true;
     } finally {
@@ -958,6 +958,27 @@
       node is TopLevelVariableDeclaration;
 
   /**
+   * Compute a value for all of the constants in the given [node].
+   */
+  void _computeConstants(AstNode node) {
+    // compute values
+    {
+      CompilationUnit unit = node.getAncestor((n) => n is CompilationUnit);
+      ConstantValueComputer computer =
+          new ConstantValueComputer(_typeProvider, _context.declaredVariables);
+      computer.add(unit);
+      computer.computeValues();
+    }
+    // validate
+    {
+      ErrorReporter errorReporter = new ErrorReporter(errorListener, _source);
+      ConstantVerifier constantVerifier =
+          new ConstantVerifier(errorReporter, _definingLibrary, _typeProvider);
+      node.accept(constantVerifier);
+    }
+  }
+
+  /**
    * Starting at [node], find the smallest AST node that can be resolved
    * independently of any other nodes. Return the node that was found.
    *
@@ -1041,8 +1062,6 @@
         visitor.initForIncrementalResolution();
         node.accept(visitor);
       }
-      // remember errors
-      _resolveErrors = errorListener.getErrorsForSource(_source);
     } finally {
       timer.stop('resolve references');
     }
@@ -1143,6 +1162,7 @@
   final Source _unitSource;
   final DartEntry _entry;
   final CompilationUnit _oldUnit;
+  final AnalysisOptions _options;
   CompilationUnitElement _unitElement;
 
   int _updateOffset;
@@ -1154,7 +1174,7 @@
   List<AnalysisError> _newParseErrors = <AnalysisError>[];
 
   PoorMansIncrementalResolver(this._typeProvider, this._unitSource, this._entry,
-      this._oldUnit, bool resolveApiChanges) {
+      this._oldUnit, bool resolveApiChanges, this._options) {
     _resolveApiChanges = resolveApiChanges;
   }
 
@@ -1223,9 +1243,9 @@
         }
         // Find nodes covering the "old" and "new" token ranges.
         AstNode oldNode =
-            _findNodeCovering(_oldUnit, beginOffsetOld, endOffsetOld);
+            _findNodeCovering(_oldUnit, beginOffsetOld, endOffsetOld - 1);
         AstNode newNode =
-            _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew);
+            _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew - 1);
         logger.log(() => 'oldNode: $oldNode');
         logger.log(() => 'newNode: $newNode');
         // Try to find the smallest common node, a FunctionBody currently.
@@ -1237,6 +1257,12 @@
           for (int i = 0; i < length; i++) {
             AstNode oldParent = oldParents[i];
             AstNode newParent = newParents[i];
+            if (oldParent is ConstructorInitializer ||
+                newParent is ConstructorInitializer) {
+              logger.log('Failure: changes in constant constructor initializers'
+                  ' may cause external changes in constant objects.');
+              return false;
+            }
             if (oldParent is FunctionDeclaration &&
                     newParent is FunctionDeclaration ||
                 oldParent is MethodDeclaration &&
@@ -1367,6 +1393,7 @@
     RecordingErrorListener errorListener = new RecordingErrorListener();
     CharSequenceReader reader = new CharSequenceReader(code);
     Scanner scanner = new Scanner(_unitSource, reader, errorListener);
+    scanner.enableNullAwareOperators = _options.enableNullAwareOperators;
     Token token = scanner.tokenize();
     _newScanErrors = errorListener.errors;
     return token;
diff --git a/pkg/analyzer/lib/src/generated/incremental_scanner.dart b/pkg/analyzer/lib/src/generated/incremental_scanner.dart
index d5a3984..eed2545 100644
--- a/pkg/analyzer/lib/src/generated/incremental_scanner.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_scanner.dart
@@ -6,6 +6,8 @@
 
 import "dart:math" as math;
 
+import 'package:analyzer/src/generated/engine.dart';
+
 import 'error.dart';
 import 'scanner.dart';
 import 'source.dart';
@@ -35,6 +37,8 @@
    */
   final AnalysisErrorListener errorListener;
 
+  final AnalysisOptions _options;
+
   /**
    * A map from tokens that were copied to the copies of the tokens.
    */
@@ -62,8 +66,10 @@
    * Initialize a newly created scanner to scan characters within the given
    * [source]. The content of the source can be read using the given [reader].
    * Any errors that are found will be reported to the given [errorListener].
+   * [_options] will determine how scanning is to be performed.
    */
-  IncrementalScanner(this.source, this.reader, this.errorListener);
+  IncrementalScanner(
+      this.source, this.reader, this.errorListener, this._options);
 
   /**
    * Return a map from tokens that were copied to the copies of the tokens.
@@ -218,6 +224,7 @@
   Token _scanRange(int start, int end) {
     Scanner scanner = new Scanner(
         source, new CharacterRangeReader(reader, start, end), errorListener);
+    scanner.enableNullAwareOperators = _options.enableNullAwareOperators;
     return scanner.tokenize();
   }
 
diff --git a/pkg/analyzer/lib/src/generated/java_core.dart b/pkg/analyzer/lib/src/generated/java_core.dart
index 4f67072..9a0185a 100644
--- a/pkg/analyzer/lib/src/generated/java_core.dart
+++ b/pkg/analyzer/lib/src/generated/java_core.dart
@@ -25,12 +25,14 @@
  */
 String formatList(String pattern, List<Object> arguments) {
   if (arguments == null || arguments.isEmpty) {
+    assert(!pattern.contains(new RegExp(r'\{(\d+)\}')));
     return pattern;
   }
   return pattern.replaceAllMapped(new RegExp(r'\{(\d+)\}'), (match) {
     String indexStr = match.group(1);
     int index = int.parse(indexStr);
     Object arg = arguments[index];
+    assert(arg != null);
     return arg != null ? arg.toString() : null;
   });
 }
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 4a4823f..0358613 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -694,7 +694,7 @@
   @override
   AstNode visitConditionalExpression(ConditionalExpression node) {
     if (identical(_oldNode, node.condition)) {
-      return _parser.parseLogicalOrExpression();
+      return _parser.parseIfNullExpression();
     } else if (identical(_oldNode, node.thenExpression)) {
       return _parser.parseExpressionWithoutCascade();
     } else if (identical(_oldNode, node.elseExpression)) {
@@ -2715,10 +2715,10 @@
    * parsed.
    *
    *     conditionalExpression ::=
-   *         logicalOrExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)?
+   *         ifNullExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)?
    */
   Expression parseConditionalExpression() {
-    Expression condition = parseLogicalOrExpression();
+    Expression condition = parseIfNullExpression();
     if (!_matches(TokenType.QUESTION)) {
       return condition;
     }
@@ -3045,6 +3045,22 @@
   }
 
   /**
+   * Parse an if-null expression.  Return the if-null expression that was
+   * parsed.
+   *
+   *     ifNullExpression ::= logicalOrExpression ('??' logicalOrExpression)*
+   */
+  Expression parseIfNullExpression() {
+    Expression expression = parseLogicalOrExpression();
+    while (_matches(TokenType.QUESTION_QUESTION)) {
+      Token operator = getAndAdvance();
+      expression = new BinaryExpression(
+          expression, operator, parseLogicalOrExpression());
+    }
+    return expression;
+  }
+
+  /**
    * Parse an implements clause. Return the implements clause that was parsed.
    *
    *     implementsClause ::=
@@ -3430,46 +3446,22 @@
 
   /**
    * Return the content of a string with the given literal representation. The
-   * [lexeme] is the literal representation of the string. The flag [first] is
-   * `true` if this is the first token in a string literal. The flag [last] is
+   * [lexeme] is the literal representation of the string. The flag [isFirst] is
+   * `true` if this is the first token in a string literal. The flag [isLast] is
    * `true` if this is the last token in a string literal.
    */
-  String _computeStringValue(String lexeme, bool first, bool last) {
-    bool isRaw = false;
-    int start = 0;
-    if (first) {
-      if (StringUtilities.startsWith4(lexeme, 0, 0x72, 0x22, 0x22, 0x22) ||
-          StringUtilities.startsWith4(lexeme, 0, 0x72, 0x27, 0x27, 0x27)) {
-        isRaw = true;
-        start += 4;
-      } else if (StringUtilities.startsWith2(lexeme, 0, 0x72, 0x22) ||
-          StringUtilities.startsWith2(lexeme, 0, 0x72, 0x27)) {
-        isRaw = true;
-        start += 2;
-      } else if (StringUtilities.startsWith3(lexeme, 0, 0x22, 0x22, 0x22) ||
-          StringUtilities.startsWith3(lexeme, 0, 0x27, 0x27, 0x27)) {
-        start += 3;
-      } else if (StringUtilities.startsWithChar(lexeme, 0x22) ||
-          StringUtilities.startsWithChar(lexeme, 0x27)) {
-        start += 1;
-      }
-    }
-    int end = lexeme.length;
-    if (last) {
-      if (StringUtilities.endsWith3(lexeme, 0x22, 0x22, 0x22) ||
-          StringUtilities.endsWith3(lexeme, 0x27, 0x27, 0x27)) {
-        end -= 3;
-      } else if (StringUtilities.endsWithChar(lexeme, 0x22) ||
-          StringUtilities.endsWithChar(lexeme, 0x27)) {
-        end -= 1;
-      }
-    }
-    if (end - start + 1 < 0) {
+  String _computeStringValue(String lexeme, bool isFirst, bool isLast) {
+    StringLexemeHelper helper = new StringLexemeHelper(lexeme, isFirst, isLast);
+    int start = helper.start;
+    int end = helper.end;
+    bool stringEndsAfterStart = end >= start;
+    assert(stringEndsAfterStart);
+    if (!stringEndsAfterStart) {
       AnalysisEngine.instance.logger.logError(
-          "Internal error: computeStringValue($lexeme, $first, $last)");
+          "Internal error: computeStringValue($lexeme, $isFirst, $isLast)");
       return "";
     }
-    if (isRaw) {
+    if (helper.isRaw) {
       return lexeme.substring(start, end);
     }
     StringBuffer buffer = new StringBuffer();
@@ -3599,12 +3591,16 @@
    *
    *     assignableExpression ::=
    *         primary (arguments* assignableSelector)+
-   *       | 'super' assignableSelector
+   *       | 'super' unconditionalAssignableSelector
    *       | identifier
    *
-   *     assignableSelector ::=
+   *     unconditionalAssignableSelector ::=
    *         '[' expression ']'
    *       | '.' identifier
+   *
+   *     assignableSelector ::=
+   *         unconditionalAssignableSelector
+   *       | '?.' identifier
    */
   void _ensureAssignable(Expression expression) {
     if (expression != null && !expression.isAssignable) {
@@ -4163,13 +4159,13 @@
    *
    *     assignableExpression ::=
    *         primary (arguments* assignableSelector)+
-   *       | 'super' assignableSelector
+   *       | 'super' unconditionalAssignableSelector
    *       | identifier
    */
   Expression _parseAssignableExpression(bool primaryAllowed) {
     if (_matchesKeyword(Keyword.SUPER)) {
       return _parseAssignableSelector(
-          new SuperExpression(getAndAdvance()), false);
+          new SuperExpression(getAndAdvance()), false, allowConditional: false);
     }
     //
     // A primary expression can start with an identifier. We resolve the
@@ -4219,13 +4215,19 @@
    * Parse an assignable selector. The [prefix] is the expression preceding the
    * selector. The [optional] is `true` if the selector is optional. Return the
    * assignable selector that was parsed, or the original prefix if there was no
-   * assignable selector.
+   * assignable selector.  If [allowConditional] is false, then the '?.'
+   * operator will still be parsed, but a parse error will be generated.
    *
-   *     assignableSelector ::=
+   *     unconditionalAssignableSelector ::=
    *         '[' expression ']'
    *       | '.' identifier
+   *
+   *     assignableSelector ::=
+   *         unconditionalAssignableSelector
+   *       | '?.' identifier
    */
-  Expression _parseAssignableSelector(Expression prefix, bool optional) {
+  Expression _parseAssignableSelector(Expression prefix, bool optional,
+      {bool allowConditional: true}) {
     if (_matches(TokenType.OPEN_SQUARE_BRACKET)) {
       Token leftBracket = getAndAdvance();
       bool wasInInitializer = _inInitializer;
@@ -4238,9 +4240,14 @@
       } finally {
         _inInitializer = wasInInitializer;
       }
-    } else if (_matches(TokenType.PERIOD)) {
-      Token period = getAndAdvance();
-      return new PropertyAccess(prefix, period, parseSimpleIdentifier());
+    } else if (_matches(TokenType.PERIOD) ||
+        _matches(TokenType.QUESTION_PERIOD)) {
+      if (_matches(TokenType.QUESTION_PERIOD) && !allowConditional) {
+        _reportErrorForCurrentToken(
+            ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [_currentToken.lexeme]);
+      }
+      Token operator = getAndAdvance();
+      return new PropertyAccess(prefix, operator, parseSimpleIdentifier());
     } else {
       if (!optional) {
         // Report the missing selector.
@@ -5672,8 +5679,9 @@
         }
         Token functionDefinition = getAndAdvance();
         if (_matchesKeyword(Keyword.RETURN)) {
-          _reportErrorForToken(
-              ParserErrorCode.UNEXPECTED_TOKEN, getAndAdvance());
+          _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
+              [_currentToken.lexeme]);
+          _advance();
         }
         Expression expression = parseExpression2();
         Token semicolon = null;
@@ -5748,6 +5756,9 @@
       } else {
         _reportErrorForCurrentToken(
             ParserErrorCode.MISSING_FUNCTION_PARAMETERS);
+        parameters = new FormalParameterList(
+            _createSyntheticToken(TokenType.OPEN_PAREN), null, null, null,
+            _createSyntheticToken(TokenType.CLOSE_PAREN));
       }
     } else if (_matches(TokenType.OPEN_PAREN)) {
       _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
@@ -5941,7 +5952,7 @@
    * associated with the directive. Return the import directive that was parsed.
    *
    *     importDirective ::=
-   *         metadata 'import' stringLiteral ('as' identifier)? combinator*';'
+   *         metadata 'import' stringLiteral (deferred)? ('as' identifier)? combinator*';'
    */
   ImportDirective _parseImportDirective(CommentAndMetadata commentAndMetadata) {
     Token importKeyword = _expectKeyword(Keyword.IMPORT);
@@ -5958,6 +5969,21 @@
     } else if (deferredToken != null) {
       _reportErrorForCurrentToken(
           ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT);
+    } else if (!_matches(TokenType.SEMICOLON) &&
+        !_matchesString(_SHOW) &&
+        !_matchesString(_HIDE)) {
+      Token nextToken = _peek();
+      if (_tokenMatchesKeyword(nextToken, Keyword.AS) ||
+          _tokenMatchesString(nextToken, _SHOW) ||
+          _tokenMatchesString(nextToken, _HIDE)) {
+        _reportErrorForCurrentToken(
+            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken]);
+        _advance();
+        if (_matchesKeyword(Keyword.AS)) {
+          asToken = getAndAdvance();
+          prefix = parseSimpleIdentifier();
+        }
+      }
     }
     List<Combinator> combinators = _parseCombinators();
     Token semicolon = _expectSemicolon();
@@ -6675,6 +6701,7 @@
     Expression operand = _parseAssignableExpression(true);
     if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
         _matches(TokenType.PERIOD) ||
+        _matches(TokenType.QUESTION_PERIOD) ||
         _matches(TokenType.OPEN_PAREN)) {
       do {
         if (_matches(TokenType.OPEN_PAREN)) {
@@ -6691,6 +6718,7 @@
         }
       } while (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
           _matches(TokenType.PERIOD) ||
+          _matches(TokenType.QUESTION_PERIOD) ||
           _matches(TokenType.OPEN_PAREN));
       return operand;
     }
@@ -6707,7 +6735,7 @@
    *
    *     primary ::=
    *         thisExpression
-   *       | 'super' assignableSelector
+   *       | 'super' unconditionalAssignableSelector
    *       | functionExpression
    *       | literal
    *       | identifier
@@ -6729,8 +6757,10 @@
     if (_matchesKeyword(Keyword.THIS)) {
       return new ThisExpression(getAndAdvance());
     } else if (_matchesKeyword(Keyword.SUPER)) {
+      // TODO(paulberry): verify with Gilad that "super" must be followed by
+      // unconditionalAssignableSelector in this case.
       return _parseAssignableSelector(
-          new SuperExpression(getAndAdvance()), false);
+          new SuperExpression(getAndAdvance()), false, allowConditional: false);
     } else if (_matchesKeyword(Keyword.NULL)) {
       return new NullLiteral(getAndAdvance());
     } else if (_matchesKeyword(Keyword.FALSE)) {
@@ -7823,7 +7853,18 @@
     } else if (!_tokenMatches(token, TokenType.PERIOD)) {
       return token;
     }
-    return _skipSimpleIdentifier(token.next);
+    token = token.next;
+    Token nextToken = _skipSimpleIdentifier(token);
+    if (nextToken != null) {
+      return nextToken;
+    } else if (_tokenMatches(token, TokenType.CLOSE_PAREN) ||
+        _tokenMatches(token, TokenType.COMMA)) {
+      // If the `id.` is followed by something that cannot produce a valid
+      // structure then assume this is a prefixed identifier but missing the
+      // trailing identifier
+      return token;
+    }
+    return null;
   }
 
   /**
@@ -9983,7 +10024,7 @@
   bool visitMethodInvocation(MethodInvocation node) {
     MethodInvocation toNode = this._toNode as MethodInvocation;
     if (_and(_isEqualNodes(node.target, toNode.target),
-        _isEqualTokens(node.period, toNode.period),
+        _isEqualTokens(node.operator, toNode.operator),
         _isEqualNodes(node.methodName, toNode.methodName),
         _isEqualNodes(node.argumentList, toNode.argumentList))) {
       toNode.propagatedType = node.propagatedType;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 7f95837..d9cc380 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -35,6 +35,8 @@
 typedef void ImplicitConstructorBuilderCallback(ClassElement classElement,
     ClassElement superclassElement, void computation());
 
+typedef LibraryResolver LibraryResolverFactory(AnalysisContext context);
+
 typedef ResolverVisitor ResolverVisitorFactory(
     Library library, Source source, TypeProvider typeProvider);
 
@@ -2846,6 +2848,14 @@
   }
 
   @override
+  Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+    if (node.isConst) {
+      node.constantHandle = new ConstantInstanceCreationHandle();
+    }
+    return super.visitInstanceCreationExpression(node);
+  }
+
+  @override
   Object visitLabeledStatement(LabeledStatement node) {
     bool onSwitchStatement = node.statement is SwitchStatement;
     for (Label label in node.labels) {
@@ -3064,17 +3074,15 @@
       SimpleIdentifier variableName = node.name;
       LocalVariableElementImpl variable;
       if (isConst && hasInitializer) {
-        variable = new ConstLocalVariableElementImpl(variableName);
+        variable = new ConstLocalVariableElementImpl.forNode(variableName);
       } else {
         variable = new LocalVariableElementImpl.forNode(variableName);
       }
       element = variable;
       Block enclosingBlock = node.getAncestor((node) => node is Block);
-      int functionEnd = node.offset + node.length;
-      int blockEnd = enclosingBlock.offset + enclosingBlock.length;
       // TODO(brianwilkerson) This isn't right for variables declared in a for
       // loop.
-      variable.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
+      variable.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
       _currentHolder.addLocalVariable(variable);
       variableName.staticElement = element;
     } else {
@@ -4344,6 +4352,256 @@
 }
 
 /**
+ * A visitor that visits ASTs and fills [UsedImportedElements].
+ */
+class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor {
+  final LibraryElement library;
+  final UsedImportedElements usedElements = new UsedImportedElements();
+
+  GatherUsedImportedElementsVisitor(this.library);
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    _visitMetadata(node.metadata);
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    _visitMetadata(node.metadata);
+  }
+
+  @override
+  void visitLibraryDirective(LibraryDirective node) {
+    _visitMetadata(node.metadata);
+  }
+
+  @override
+  void visitPrefixedIdentifier(PrefixedIdentifier node) {
+    // If the prefixed identifier references some A.B, where A is a library
+    // prefix, then we can lookup the associated ImportDirective in
+    // prefixElementMap and remove it from the unusedImports list.
+    SimpleIdentifier prefixIdentifier = node.prefix;
+    Element element = prefixIdentifier.staticElement;
+    if (element is PrefixElement) {
+      usedElements.prefixes.add(element);
+      return;
+    }
+    // Otherwise, pass the prefixed identifier element and name onto
+    // visitIdentifier.
+    _visitIdentifier(element, prefixIdentifier.name);
+  }
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    _visitIdentifier(node.staticElement, node.name);
+  }
+
+  void _visitIdentifier(Element element, String name) {
+    if (element == null) {
+      return;
+    }
+    // If the element is multiply defined then call this method recursively for
+    // each of the conflicting elements.
+    if (element is MultiplyDefinedElement) {
+      MultiplyDefinedElement multiplyDefinedElement = element;
+      for (Element elt in multiplyDefinedElement.conflictingElements) {
+        _visitIdentifier(elt, name);
+      }
+      return;
+    } else if (element is PrefixElement) {
+      usedElements.prefixes.add(element);
+      return;
+    } else if (element.enclosingElement is! CompilationUnitElement) {
+      // Identifiers that aren't a prefix element and whose enclosing element
+      // isn't a CompilationUnit are ignored- this covers the case the
+      // identifier is a relative-reference, a reference to an identifier not
+      // imported by this library.
+      return;
+    }
+    // Ignore if an unknown library.
+    LibraryElement containingLibrary = element.library;
+    if (containingLibrary == null) {
+      return;
+    }
+    // Ignore if a local element.
+    if (library == containingLibrary) {
+      return;
+    }
+    // Remember the element.
+    usedElements.elements.add(element);
+  }
+
+  /**
+   * Given some [NodeList] of [Annotation]s, ensure that the identifiers are visited by
+   * this visitor. Specifically, this covers the cases where AST nodes don't have their identifiers
+   * visited by this visitor, but still need their annotations visited.
+   *
+   * @param annotations the list of annotations to visit
+   */
+  void _visitMetadata(NodeList<Annotation> annotations) {
+    int count = annotations.length;
+    for (int i = 0; i < count; i++) {
+      annotations[i].accept(this);
+    }
+  }
+}
+
+/**
+ * An [AstVisitor] that fills [UsedLocalElements].
+ */
+class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor {
+  final UsedLocalElements usedElements = new UsedLocalElements();
+
+  final LibraryElement _enclosingLibrary;
+  ClassElement _enclosingClass;
+  ExecutableElement _enclosingExec;
+
+  GatherUsedLocalElementsVisitor(this._enclosingLibrary);
+
+  @override
+  visitCatchClause(CatchClause node) {
+    SimpleIdentifier exceptionParameter = node.exceptionParameter;
+    SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
+    if (exceptionParameter != null) {
+      Element element = exceptionParameter.staticElement;
+      usedElements.addCatchException(element);
+      if (stackTraceParameter != null || node.onKeyword == null) {
+        usedElements.addElement(element);
+      }
+    }
+    if (stackTraceParameter != null) {
+      Element element = stackTraceParameter.staticElement;
+      usedElements.addCatchStackTrace(element);
+    }
+    super.visitCatchClause(node);
+  }
+
+  @override
+  visitClassDeclaration(ClassDeclaration node) {
+    ClassElement enclosingClassOld = _enclosingClass;
+    try {
+      _enclosingClass = node.element;
+      super.visitClassDeclaration(node);
+    } finally {
+      _enclosingClass = enclosingClassOld;
+    }
+  }
+
+  @override
+  visitFunctionDeclaration(FunctionDeclaration node) {
+    ExecutableElement enclosingExecOld = _enclosingExec;
+    try {
+      _enclosingExec = node.element;
+      super.visitFunctionDeclaration(node);
+    } finally {
+      _enclosingExec = enclosingExecOld;
+    }
+  }
+
+  @override
+  visitFunctionExpression(FunctionExpression node) {
+    if (node.parent is! FunctionDeclaration) {
+      usedElements.addElement(node.element);
+    }
+    super.visitFunctionExpression(node);
+  }
+
+  @override
+  visitMethodDeclaration(MethodDeclaration node) {
+    ExecutableElement enclosingExecOld = _enclosingExec;
+    try {
+      _enclosingExec = node.element;
+      super.visitMethodDeclaration(node);
+    } finally {
+      _enclosingExec = enclosingExecOld;
+    }
+  }
+
+  @override
+  visitSimpleIdentifier(SimpleIdentifier node) {
+    if (node.inDeclarationContext()) {
+      return;
+    }
+    Element element = node.staticElement;
+    bool isIdentifierRead = _isReadIdentifier(node);
+    if (element is LocalVariableElement) {
+      if (isIdentifierRead) {
+        usedElements.addElement(element);
+      }
+    } else {
+      _useIdentifierElement(node);
+      if (element == null ||
+          element is! LocalElement && !identical(element, _enclosingExec)) {
+        usedElements.members.add(node.name);
+        if (isIdentifierRead) {
+          usedElements.readMembers.add(node.name);
+        }
+      }
+    }
+  }
+
+  @override
+  visitTypeName(TypeName node) {
+    _useIdentifierElement(node.name);
+  }
+
+  /**
+   * Marks an [Element] of [node] as used in the library.
+   */
+  void _useIdentifierElement(Identifier node) {
+    Element element = node.staticElement;
+    if (element == null) {
+      return;
+    }
+    // check if a local element
+    if (!identical(element.library, _enclosingLibrary)) {
+      return;
+    }
+    // ignore references to an element from itself
+    if (identical(element, _enclosingClass)) {
+      return;
+    }
+    if (identical(element, _enclosingExec)) {
+      return;
+    }
+    // ignore places where the element is not actually used
+    if (node.parent is TypeName) {
+      AstNode parent2 = node.parent.parent;
+      if (parent2 is IsExpression) {
+        return;
+      }
+      // We need to instantiate/extend/implement a class to actually use it.
+      // OTOH, function type aliases are used to define closure structures.
+      if (parent2 is VariableDeclarationList && element is ClassElement) {
+        return;
+      }
+    }
+    // OK
+    usedElements.addElement(element);
+  }
+
+  static bool _isReadIdentifier(SimpleIdentifier node) {
+    // not reading at all
+    if (!node.inGetterContext()) {
+      return false;
+    }
+    // check if useless reading
+    AstNode parent = node.parent;
+    if (parent.parent is ExpressionStatement &&
+        (parent is PrefixExpression ||
+            parent is PostfixExpression ||
+            parent is AssignmentExpression && parent.leftHandSide == node)) {
+      // v++;
+      // ++v;
+      // v += 2;
+      return false;
+    }
+    // OK
+    return true;
+  }
+}
+
+/**
  * Instances of the class `HintGenerator` traverse a library's worth of dart code at a time to
  * generate hints over the set of sources.
  *
@@ -4358,7 +4616,7 @@
 
   LibraryElement _library;
 
-  ImportsVerifier _importsVerifier;
+  GatherUsedImportedElementsVisitor _usedImportedElementsVisitor;
 
   bool _enableDart2JSHints = false;
 
@@ -4367,47 +4625,47 @@
    */
   InheritanceManager _manager;
 
-  _GatherUsedElementsVisitor _usedElementsVisitor;
+  GatherUsedLocalElementsVisitor _usedLocalElementsVisitor;
 
   HintGenerator(this._compilationUnits, this._context, this._errorListener) {
     _library = _compilationUnits[0].element.library;
-    _importsVerifier = new ImportsVerifier(_library);
+    _usedImportedElementsVisitor =
+        new GatherUsedImportedElementsVisitor(_library);
     _enableDart2JSHints = _context.analysisOptions.dart2jsHint;
     _manager = new InheritanceManager(_compilationUnits[0].element.library);
-    _usedElementsVisitor = new _GatherUsedElementsVisitor(_library);
+    _usedLocalElementsVisitor = new GatherUsedLocalElementsVisitor(_library);
   }
 
   void generateForLibrary() {
     PerformanceStatistics.hints.makeCurrentWhile(() {
-      for (int i = 0; i < _compilationUnits.length; i++) {
-        CompilationUnitElement element = _compilationUnits[i].element;
+      for (CompilationUnit unit in _compilationUnits) {
+        CompilationUnitElement element = unit.element;
         if (element != null) {
-          if (i == 0) {
-            _importsVerifier.inDefiningCompilationUnit = true;
-            _generateForCompilationUnit(_compilationUnits[i], element.source);
-            _importsVerifier.inDefiningCompilationUnit = false;
-          } else {
-            _generateForCompilationUnit(_compilationUnits[i], element.source);
-          }
+          _generateForCompilationUnit(unit, element.source);
         }
       }
-      ErrorReporter definingCompilationUnitErrorReporter = new ErrorReporter(
-          _errorListener, _compilationUnits[0].element.source);
-      _importsVerifier
-          .generateDuplicateImportHints(definingCompilationUnitErrorReporter);
-      _importsVerifier
-          .generateUnusedImportHints(definingCompilationUnitErrorReporter);
-      _library.accept(new _UnusedElementsVerifier(
-          _errorListener, _usedElementsVisitor.usedElements));
+      CompilationUnit definingUnit = _compilationUnits[0];
+      ErrorReporter definingUnitErrorReporter =
+          new ErrorReporter(_errorListener, definingUnit.element.source);
+      {
+        ImportsVerifier importsVerifier = new ImportsVerifier();
+        importsVerifier.addImports(definingUnit);
+        importsVerifier
+            .removeUsedElements(_usedImportedElementsVisitor.usedElements);
+        importsVerifier.generateDuplicateImportHints(definingUnitErrorReporter);
+        importsVerifier.generateUnusedImportHints(definingUnitErrorReporter);
+      }
+      _library.accept(new UnusedLocalElementsVerifier(
+          _errorListener, _usedLocalElementsVisitor.usedElements));
     });
   }
 
   void _generateForCompilationUnit(CompilationUnit unit, Source source) {
     ErrorReporter errorReporter = new ErrorReporter(_errorListener, source);
-    unit.accept(_importsVerifier);
+    unit.accept(_usedImportedElementsVisitor);
     // dead code analysis
     unit.accept(new DeadCodeVerifier(errorReporter));
-    unit.accept(_usedElementsVisitor);
+    unit.accept(_usedLocalElementsVisitor);
     // dart2js analysis
     if (_enableDart2JSHints) {
       unit.accept(new Dart2JSVerifier(errorReporter));
@@ -4415,7 +4673,7 @@
     // Dart best practices
     unit.accept(
         new BestPracticesVerifier(errorReporter, _context.typeProvider));
-    unit.accept(new OverrideVerifier(_manager, errorReporter));
+    unit.accept(new OverrideVerifier(errorReporter, _manager));
     // Find to-do comments
     new ToDoFinder(errorReporter).findIn(unit);
     // pub analysis
@@ -5191,19 +5449,7 @@
  * While this class does not yet have support for an "Organize Imports" action, this logic built up
  * in this class could be used for such an action in the future.
  */
-class ImportsVerifier extends RecursiveAstVisitor<Object> {
-  /**
-   * This is set to `true` if the current compilation unit which is being visited is the
-   * defining compilation unit for the library, its value can be set with
-   * [setInDefiningCompilationUnit].
-   */
-  bool _inDefiningCompilationUnit = false;
-
-  /**
-   * The current library.
-   */
-  LibraryElement _currentLibrary;
-
+class ImportsVerifier /*extends RecursiveAstVisitor<Object>*/ {
   /**
    * A list of [ImportDirective]s that the current library imports, as identifiers are visited
    * by this visitor and an import has been identified as being used by the library, the
@@ -5212,13 +5458,13 @@
    *
    * See [ImportsVerifier.generateUnusedImportErrors].
    */
-  List<ImportDirective> _unusedImports;
+  final List<ImportDirective> _unusedImports = <ImportDirective>[];
 
   /**
    * After the list of [unusedImports] has been computed, this list is a proper subset of the
    * unused imports that are listed more than once.
    */
-  List<ImportDirective> _duplicateImports;
+  final List<ImportDirective> _duplicateImports = <ImportDirective>[];
 
   /**
    * This is a map between the set of [LibraryElement]s that the current library imports, and
@@ -5231,7 +5477,8 @@
    * will need to be used to compute the correct [ImportDirective] being used, see
    * [namespaceMap].
    */
-  HashMap<LibraryElement, List<ImportDirective>> _libraryMap;
+  final HashMap<LibraryElement, List<ImportDirective>> _libraryMap =
+      new HashMap<LibraryElement, List<ImportDirective>>();
 
   /**
    * In cases where there is more than one import directive per library element, this mapping is
@@ -5239,7 +5486,8 @@
    * [Namespace] for each of the imports to do lookups in the same way that they are done from
    * the [ElementResolver].
    */
-  HashMap<ImportDirective, Namespace> _namespaceMap;
+  final HashMap<ImportDirective, Namespace> _namespaceMap =
+      new HashMap<ImportDirective, Namespace>();
 
   /**
    * This is a map between prefix elements and the import directives from which they are derived. In
@@ -5251,25 +5499,71 @@
    * it is possible to have an unreported unused import in situations where two imports use the same
    * prefix and at least one import directive is used.
    */
-  HashMap<PrefixElement, List<ImportDirective>> _prefixElementMap;
+  final HashMap<PrefixElement, List<ImportDirective>> _prefixElementMap =
+      new HashMap<PrefixElement, List<ImportDirective>>();
 
-  /**
-   * Create a new instance of the [ImportsVerifier].
-   *
-   * @param errorReporter the error reporter
-   */
-  ImportsVerifier(LibraryElement library) {
-    this._currentLibrary = library;
-    this._unusedImports = new List<ImportDirective>();
-    this._duplicateImports = new List<ImportDirective>();
-    this._libraryMap = new HashMap<LibraryElement, List<ImportDirective>>();
-    this._namespaceMap = new HashMap<ImportDirective, Namespace>();
-    this._prefixElementMap =
-        new HashMap<PrefixElement, List<ImportDirective>>();
-  }
-
-  void set inDefiningCompilationUnit(bool inDefiningCompilationUnit) {
-    this._inDefiningCompilationUnit = inDefiningCompilationUnit;
+  void addImports(CompilationUnit node) {
+    for (Directive directive in node.directives) {
+      if (directive is ImportDirective) {
+        ImportDirective importDirective = directive;
+        LibraryElement libraryElement = importDirective.uriElement;
+        if (libraryElement != null) {
+          _unusedImports.add(importDirective);
+          //
+          // Initialize prefixElementMap
+          //
+          if (importDirective.asKeyword != null) {
+            SimpleIdentifier prefixIdentifier = importDirective.prefix;
+            if (prefixIdentifier != null) {
+              Element element = prefixIdentifier.staticElement;
+              if (element is PrefixElement) {
+                PrefixElement prefixElementKey = element;
+                List<ImportDirective> list =
+                    _prefixElementMap[prefixElementKey];
+                if (list == null) {
+                  list = new List<ImportDirective>();
+                  _prefixElementMap[prefixElementKey] = list;
+                }
+                list.add(importDirective);
+              }
+              // TODO (jwren) Can the element ever not be a PrefixElement?
+            }
+          }
+          //
+          // Initialize libraryMap: libraryElement -> importDirective
+          //
+          _putIntoLibraryMap(libraryElement, importDirective);
+          //
+          // For this new addition to the libraryMap, also recursively add any
+          // exports from the libraryElement.
+          //
+          _addAdditionalLibrariesForExports(
+              libraryElement, importDirective, new List<LibraryElement>());
+        }
+      }
+    }
+    if (_unusedImports.length > 1) {
+      // order the list of unusedImports to find duplicates in faster than
+      // O(n^2) time
+      List<ImportDirective> importDirectiveArray =
+          new List<ImportDirective>.from(_unusedImports);
+      importDirectiveArray.sort(ImportDirective.COMPARATOR);
+      ImportDirective currentDirective = importDirectiveArray[0];
+      for (int i = 1; i < importDirectiveArray.length; i++) {
+        ImportDirective nextDirective = importDirectiveArray[i];
+        if (ImportDirective.COMPARATOR(currentDirective, nextDirective) == 0) {
+          // Add either the currentDirective or nextDirective depending on which
+          // comes second, this guarantees that the first of the duplicates
+          // won't be highlighted.
+          if (currentDirective.offset < nextDirective.offset) {
+            _duplicateImports.add(nextDirective);
+          } else {
+            _duplicateImports.add(currentDirective);
+          }
+        }
+        currentDirective = nextDirective;
+      }
+    }
   }
 
   /**
@@ -5310,128 +5604,52 @@
     }
   }
 
-  @override
-  Object visitCompilationUnit(CompilationUnit node) {
-    if (_inDefiningCompilationUnit) {
-      NodeList<Directive> directives = node.directives;
-      for (Directive directive in directives) {
-        if (directive is ImportDirective) {
-          ImportDirective importDirective = directive;
-          LibraryElement libraryElement = importDirective.uriElement;
-          if (libraryElement != null) {
-            _unusedImports.add(importDirective);
-            //
-            // Initialize prefixElementMap
-            //
-            if (importDirective.asKeyword != null) {
-              SimpleIdentifier prefixIdentifier = importDirective.prefix;
-              if (prefixIdentifier != null) {
-                Element element = prefixIdentifier.staticElement;
-                if (element is PrefixElement) {
-                  PrefixElement prefixElementKey = element;
-                  List<ImportDirective> list =
-                      _prefixElementMap[prefixElementKey];
-                  if (list == null) {
-                    list = new List<ImportDirective>();
-                    _prefixElementMap[prefixElementKey] = list;
-                  }
-                  list.add(importDirective);
-                }
-                // TODO (jwren) Can the element ever not be a PrefixElement?
-              }
-            }
-            //
-            // Initialize libraryMap: libraryElement -> importDirective
-            //
-            _putIntoLibraryMap(libraryElement, importDirective);
-            //
-            // For this new addition to the libraryMap, also recursively add any
-            // exports from the libraryElement.
-            //
-            _addAdditionalLibrariesForExports(
-                libraryElement, importDirective, new List<LibraryElement>());
-          }
-        }
-      }
-    }
-    // If there are no imports in this library, don't visit the identifiers in
-    // the library- there can be no unused imports.
+  /**
+   * Remove elements from [_unusedImports] using the given [usedElements].
+   */
+  void removeUsedElements(UsedImportedElements usedElements) {
+    // Stop if all the imports are known to be used.
     if (_unusedImports.isEmpty) {
-      return null;
+      return;
     }
-    if (_unusedImports.length > 1) {
-      // order the list of unusedImports to find duplicates in faster than
-      // O(n^2) time
-      List<ImportDirective> importDirectiveArray =
-          new List.from(_unusedImports);
-      importDirectiveArray.sort(ImportDirective.COMPARATOR);
-      ImportDirective currentDirective = importDirectiveArray[0];
-      for (int i = 1; i < importDirectiveArray.length; i++) {
-        ImportDirective nextDirective = importDirectiveArray[i];
-        if (ImportDirective.COMPARATOR(currentDirective, nextDirective) == 0) {
-          // Add either the currentDirective or nextDirective depending on which
-          // comes second, this guarantees that the first of the duplicates
-          // won't be highlighted.
-          if (currentDirective.offset < nextDirective.offset) {
-            _duplicateImports.add(nextDirective);
-          } else {
-            _duplicateImports.add(currentDirective);
-          }
-        }
-        currentDirective = nextDirective;
-      }
-    }
-    return super.visitCompilationUnit(node);
-  }
-
-  @override
-  Object visitExportDirective(ExportDirective node) {
-    _visitMetadata(node.metadata);
-    return null;
-  }
-
-  @override
-  Object visitImportDirective(ImportDirective node) {
-    _visitMetadata(node.metadata);
-    return null;
-  }
-
-  @override
-  Object visitLibraryDirective(LibraryDirective node) {
-    _visitMetadata(node.metadata);
-    return null;
-  }
-
-  @override
-  Object visitPrefixedIdentifier(PrefixedIdentifier node) {
-    if (_unusedImports.isEmpty) {
-      return null;
-    }
-    // If the prefixed identifier references some A.B, where A is a library
-    // prefix, then we can lookup the associated ImportDirective in
-    // prefixElementMap and remove it from the unusedImports list.
-    SimpleIdentifier prefixIdentifier = node.prefix;
-    Element element = prefixIdentifier.staticElement;
-    if (element is PrefixElement) {
-      List<ImportDirective> importDirectives = _prefixElementMap[element];
+    // Process import prefixes.
+    for (PrefixElement prefix in usedElements.prefixes) {
+      List<ImportDirective> importDirectives = _prefixElementMap[prefix];
       if (importDirectives != null) {
         for (ImportDirective importDirective in importDirectives) {
           _unusedImports.remove(importDirective);
         }
       }
-      return null;
     }
-    // Otherwise, pass the prefixed identifier element and name onto
-    // visitIdentifier.
-    return _visitIdentifier(element, prefixIdentifier.name);
-  }
-
-  @override
-  Object visitSimpleIdentifier(SimpleIdentifier node) {
-    if (_unusedImports.isEmpty) {
-      return null;
+    // Process top-level elements.
+    for (Element element in usedElements.elements) {
+      // Stop if all the imports are known to be used.
+      if (_unusedImports.isEmpty) {
+        return;
+      }
+      // Prepare import directives for this library.
+      LibraryElement library = element.library;
+      List<ImportDirective> importsLibrary = _libraryMap[library];
+      if (importsLibrary == null) {
+        continue;
+      }
+      // If there is only one import directive for this library, then it must be
+      // the directive that this element is imported with, remove it from the
+      // unusedImports list.
+      if (importsLibrary.length == 1) {
+        ImportDirective usedImportDirective = importsLibrary[0];
+        _unusedImports.remove(usedImportDirective);
+        continue;
+      }
+      // Otherwise, find import directives using namespaces.
+      String name = element.displayName;
+      for (ImportDirective importDirective in importsLibrary) {
+        Namespace namespace = _computeNamespace(importDirective);
+        if (namespace != null && namespace.get(name) != null) {
+          _unusedImports.remove(importDirective);
+        }
+      }
     }
-    return _visitIdentifier(node.staticElement, node.name);
   }
 
   /**
@@ -5488,79 +5706,6 @@
     }
     importList.add(importDirective);
   }
-
-  Object _visitIdentifier(Element element, String name) {
-    if (element == null) {
-      return null;
-    }
-    // If the element is multiply defined then call this method recursively for
-    // each of the conflicting elements.
-    if (element is MultiplyDefinedElement) {
-      MultiplyDefinedElement multiplyDefinedElement = element;
-      for (Element elt in multiplyDefinedElement.conflictingElements) {
-        _visitIdentifier(elt, name);
-      }
-      return null;
-    } else if (element is PrefixElement) {
-      List<ImportDirective> importDirectives = _prefixElementMap[element];
-      if (importDirectives != null) {
-        for (ImportDirective importDirective in importDirectives) {
-          _unusedImports.remove(importDirective);
-        }
-      }
-      return null;
-    } else if (element.enclosingElement is! CompilationUnitElement) {
-      // Identifiers that aren't a prefix element and whose enclosing element
-      // isn't a CompilationUnit are ignored- this covers the case the
-      // identifier is a relative-reference, a reference to an identifier not
-      // imported by this library.
-      return null;
-    }
-    LibraryElement containingLibrary = element.library;
-    if (containingLibrary == null) {
-      return null;
-    }
-    // If the element is declared in the current library, return.
-    if (_currentLibrary == containingLibrary) {
-      return null;
-    }
-    List<ImportDirective> importsFromSameLibrary =
-        _libraryMap[containingLibrary];
-    if (importsFromSameLibrary == null) {
-      return null;
-    }
-    if (importsFromSameLibrary.length == 1) {
-      // If there is only one import directive for this library, then it must be
-      // the directive that this element is imported with, remove it from the
-      // unusedImports list.
-      ImportDirective usedImportDirective = importsFromSameLibrary[0];
-      _unusedImports.remove(usedImportDirective);
-    } else {
-      // Otherwise, for each of the imported directives, use the namespaceMap to
-      for (ImportDirective importDirective in importsFromSameLibrary) {
-        // Get the namespace for this import
-        Namespace namespace = _computeNamespace(importDirective);
-        if (namespace != null && namespace.get(name) != null) {
-          _unusedImports.remove(importDirective);
-        }
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Given some [NodeList] of [Annotation]s, ensure that the identifiers are visited by
-   * this visitor. Specifically, this covers the cases where AST nodes don't have their identifiers
-   * visited by this visitor, but still need their annotations visited.
-   *
-   * @param annotations the list of annotations to visit
-   */
-  void _visitMetadata(NodeList<Annotation> annotations) {
-    int count = annotations.length;
-    for (int i = 0; i < count; i++) {
-      annotations[i].accept(this);
-    }
-  }
 }
 
 /**
@@ -7542,6 +7687,11 @@
   TypeProvider _typeProvider;
 
   /**
+   * The object used to access the types from the core library.
+   */
+  TypeProvider get typeProvider => _typeProvider;
+
+  /**
    * A table mapping library sources to the information being maintained for those libraries.
    */
   HashMap<Source, Library> _libraryMap = new HashMap<Source, Library>();
@@ -7677,7 +7827,7 @@
     // method and punt the decision to the clients.
     //
     //if (analyzeAll) {
-    _resolveReferencesAndTypes();
+    resolveReferencesAndTypes();
     //} else {
     //  resolveReferencesAndTypes(targetLibrary);
     //}
@@ -7758,7 +7908,7 @@
     // method and punt the decision to the clients.
     //
     //if (analyzeAll) {
-    _resolveReferencesAndTypes();
+    resolveReferencesAndTypes();
     //} else {
     //  resolveReferencesAndTypes(targetLibrary);
     //}
@@ -8326,7 +8476,7 @@
    * @throws AnalysisException if any of the identifiers could not be resolved or if any of the
    *           libraries could not have their types analyzed
    */
-  void _resolveReferencesAndTypes() {
+  void resolveReferencesAndTypes() {
     for (Library library in _librariesInCycles) {
       _resolveReferencesAndTypesInLibrary(library);
     }
@@ -9494,22 +9644,22 @@
  */
 class OverrideVerifier extends RecursiveAstVisitor<Object> {
   /**
-   * The inheritance manager used to find overridden methods.
-   */
-  final InheritanceManager _manager;
-
-  /**
    * The error reporter used to report errors.
    */
   final ErrorReporter _errorReporter;
 
   /**
+   * The inheritance manager used to find overridden methods.
+   */
+  final InheritanceManager _manager;
+
+  /**
    * Initialize a newly created verifier to look for inappropriate uses of the override annotation.
    *
-   * @param manager the inheritance manager used to find overridden methods
    * @param errorReporter the error reporter used to report errors
+   * @param manager the inheritance manager used to find overridden methods
    */
-  OverrideVerifier(this._manager, this._errorReporter);
+  OverrideVerifier(this._errorReporter, this._manager);
 
   @override
   Object visitMethodDeclaration(MethodDeclaration node) {
@@ -10087,12 +10237,12 @@
   /**
    * The object used to resolve the element associated with the current node.
    */
-  ElementResolver _elementResolver;
+  ElementResolver elementResolver;
 
   /**
    * The object used to compute the type associated with the current node.
    */
-  StaticTypeAnalyzer _typeAnalyzer;
+  StaticTypeAnalyzer typeAnalyzer;
 
   /**
    * The class element representing the class containing the current node,
@@ -10157,8 +10307,8 @@
       StaticTypeAnalyzerFactory typeAnalyzerFactory})
       : super.con1(library, source, typeProvider) {
     this._inheritanceManager = library.inheritanceManager;
-    this._elementResolver = new ElementResolver(this);
-    this._typeAnalyzer = typeAnalyzer != null
+    this.elementResolver = new ElementResolver(this);
+    this.typeAnalyzer = typeAnalyzer != null
         ? typeAnalyzer
         : (typeAnalyzerFactory != null
             ? typeAnalyzerFactory(this)
@@ -10180,8 +10330,8 @@
       AnalysisErrorListener errorListener)
       : super.con2(definingLibrary, source, typeProvider, errorListener) {
     this._inheritanceManager = inheritanceManager;
-    this._elementResolver = new ElementResolver(this);
-    this._typeAnalyzer = new StaticTypeAnalyzer(this);
+    this.elementResolver = new ElementResolver(this);
+    this.typeAnalyzer = new StaticTypeAnalyzer(this);
   }
 
   /**
@@ -10200,8 +10350,8 @@
       : super.con3(
           definingLibrary, source, typeProvider, nameScope, errorListener) {
     this._inheritanceManager = new InheritanceManager(definingLibrary);
-    this._elementResolver = new ElementResolver(this);
-    this._typeAnalyzer = new StaticTypeAnalyzer(this);
+    this.elementResolver = new ElementResolver(this);
+    this.typeAnalyzer = new StaticTypeAnalyzer(this);
   }
 
   /**
@@ -10215,14 +10365,10 @@
       ResolvableLibrary library, Source source, TypeProvider typeProvider)
       : super.con4(library, source, typeProvider) {
     this._inheritanceManager = library.inheritanceManager;
-    this._elementResolver = new ElementResolver(this);
-    this._typeAnalyzer = new StaticTypeAnalyzer(this);
+    this.elementResolver = new ElementResolver(this);
+    this.typeAnalyzer = new StaticTypeAnalyzer(this);
   }
 
-  get elementResolver_J2DAccessor => _elementResolver;
-
-  set elementResolver_J2DAccessor(__v) => _elementResolver = __v;
-
   /**
    * Return the element representing the function containing the current node, or `null` if
    * the current node is not contained in a function.
@@ -10231,14 +10377,6 @@
    */
   ExecutableElement get enclosingFunction => _enclosingFunction;
 
-  get labelScope_J2DAccessor => _labelScope;
-
-  set labelScope_J2DAccessor(__v) => _labelScope = __v;
-
-  get nameScope_J2DAccessor => _nameScope;
-
-  set nameScope_J2DAccessor(__v) => _nameScope = __v;
-
   /**
    * Return the object keeping track of which elements have had their types overridden.
    *
@@ -10253,10 +10391,6 @@
    */
   TypePromotionManager get promoteManager => _promoteManager;
 
-  get typeAnalyzer_J2DAccessor => _typeAnalyzer;
-
-  set typeAnalyzer_J2DAccessor(__v) => _typeAnalyzer = __v;
-
   /**
    * Return the propagated element associated with the given expression whose type can be
    * overridden, or `null` if there is no element whose type can be overridden.
@@ -10351,7 +10485,9 @@
       Expression expression, DartType potentialType, bool allowPrecisionLoss) {
     VariableElement element = getOverridableStaticElement(expression);
     if (element != null) {
-      overrideVariable(element, potentialType, allowPrecisionLoss);
+      DartType newBestType =
+          overrideVariable(element, potentialType, allowPrecisionLoss);
+      recordPropagatedTypeIfBetter(expression, newBestType);
     }
     element = getOverridablePropagatedElement(expression);
     if (element != null) {
@@ -10367,16 +10503,19 @@
    * @param potentialType the potential type of the element
    * @param allowPrecisionLoss true if `potentialType` is allowed to be less precise than the
    *          current best type
+   *
+   * Return a new better [DartType], or `null` if [potentialType] is not better
+   * than the current [element] type.
    */
-  void overrideVariable(VariableElement element, DartType potentialType,
+  DartType overrideVariable(VariableElement element, DartType potentialType,
       bool allowPrecisionLoss) {
     if (potentialType == null || potentialType.isBottom) {
-      return;
+      return null;
     }
     DartType currentType = _overrideManager.getBestType(element);
 
     if (potentialType == currentType) {
-      return;
+      return null;
     }
 
     // If we aren't allowing precision loss then the third and fourth conditions
@@ -10415,7 +10554,44 @@
 //            potentialType;
 //      }
       _overrideManager.setType(element, potentialType);
+      return potentialType;
     }
+    return null;
+  }
+
+  /**
+   * If the given [type] is valid, strongly more specific than the
+   * existing static type of the given [expression], record it as a propagated
+   * type of the given [expression]. Otherwise, reset it to `null`.
+   *
+   * If [hasOldPropagatedType] is `true` then the existing propagated type
+   * should also is checked.
+   */
+  void recordPropagatedTypeIfBetter(Expression expression, DartType type,
+      [bool hasOldPropagatedType = false]) {
+    // Ensure that propagated type invalid.
+    if (type == null || type.isDynamic || type.isBottom) {
+      if (!hasOldPropagatedType) {
+        expression.propagatedType = null;
+      }
+      return;
+    }
+    // Ensure that propagated type is more specific than the static type.
+    DartType staticType = expression.staticType;
+    if (type == staticType || !type.isMoreSpecificThan(staticType)) {
+      expression.propagatedType = null;
+      return;
+    }
+    // Ensure that the new propagated type is more specific than the old one.
+    if (hasOldPropagatedType) {
+      DartType oldPropagatedType = expression.propagatedType;
+      if (oldPropagatedType != null &&
+          !type.isMoreSpecificThan(oldPropagatedType)) {
+        return;
+      }
+    }
+    // OK
+    expression.propagatedType = type;
   }
 
   @override
@@ -10488,8 +10664,8 @@
       safelyVisit(leftOperand);
       safelyVisit(rightOperand);
     }
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -10511,8 +10687,8 @@
     // We do not visit the label because it needs to be visited in the context
     // of the statement.
     //
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -10531,13 +10707,13 @@
     ClassElement outerType = enclosingClass;
     try {
       enclosingClass = node.element;
-      _typeAnalyzer.thisType =
+      typeAnalyzer.thisType =
           enclosingClass == null ? null : enclosingClass.type;
       super.visitClassDeclaration(node);
-      node.accept(_elementResolver);
-      node.accept(_typeAnalyzer);
+      node.accept(elementResolver);
+      node.accept(typeAnalyzer);
     } finally {
-      _typeAnalyzer.thisType = outerType == null ? null : outerType.type;
+      typeAnalyzer.thisType = outerType == null ? null : outerType.type;
       enclosingClass = outerType;
       _enclosingClassDeclaration = null;
     }
@@ -10560,10 +10736,9 @@
     // Continue the class resolution.
     //
     enclosingClass = node.element;
-    _typeAnalyzer.thisType =
-        enclosingClass == null ? null : enclosingClass.type;
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    typeAnalyzer.thisType = enclosingClass == null ? null : enclosingClass.type;
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
   }
 
   @override
@@ -10587,8 +10762,8 @@
     // We do not visit the identifier because it needs to be visited in the
     // context of the reference.
     //
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -10628,8 +10803,8 @@
     } finally {
       _overrideManager.exitScope();
     }
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -10668,8 +10843,8 @@
         _overrideManager.exitScope();
       }
     }
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     bool thenIsAbrupt = _isAbruptTerminationExpression(thenExpression);
     bool elseIsAbrupt = _isAbruptTerminationExpression(elseExpression);
     if (elseIsAbrupt && !thenIsAbrupt) {
@@ -10691,6 +10866,9 @@
     } finally {
       _enclosingFunction = outerFunction;
     }
+    ConstructorElementImpl constructor = node.element;
+    constructor.constantInitializers =
+        new ConstantAstCloner().cloneNodeList(node.initializers);
     return null;
   }
 
@@ -10701,8 +10879,8 @@
     // to be visited in the context of the constructor field initializer node.
     //
     safelyVisit(node.expression);
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -10713,8 +10891,8 @@
     // or the name, because it needs to be visited in the context of the
     // constructor name.
     //
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -10724,8 +10902,8 @@
     // We do not visit the label because it needs to be visited in the context
     // of the statement.
     //
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -10842,8 +11020,8 @@
         _overrideManager.exitScope();
       }
     }
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
   }
 
   @override
@@ -10907,10 +11085,10 @@
   @override
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     safelyVisit(node.function);
-    node.accept(_elementResolver);
+    node.accept(elementResolver);
     _inferFunctionExpressionsParametersTypes(node.argumentList);
     safelyVisit(node.argumentList);
-    node.accept(_typeAnalyzer);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -10974,8 +11152,8 @@
         _overrideManager.exitScope();
       }
     }
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     // Join overrides.
     bool thenIsAbrupt = _isAbruptTerminationStatement(thenStatement);
     bool elseIsAbrupt = _isAbruptTerminationStatement(elseStatement);
@@ -10986,13 +11164,11 @@
       _propagateFalseState(condition);
       _overrideManager.applyOverrides(elseOverrides);
     } else if (!thenIsAbrupt && !elseIsAbrupt) {
-      if (AnalysisEngine.instance.enableUnionTypes) {
-        List<Map<VariableElement, DartType>> perBranchOverrides =
-            new List<Map<VariableElement, DartType>>();
-        perBranchOverrides.add(thenOverrides);
-        perBranchOverrides.add(elseOverrides);
-        _overrideManager.joinOverrides(perBranchOverrides);
-      }
+      List<Map<VariableElement, DartType>> perBranchOverrides =
+          new List<Map<VariableElement, DartType>>();
+      perBranchOverrides.add(thenOverrides);
+      perBranchOverrides.add(elseOverrides);
+      _overrideManager.mergeOverrides(perBranchOverrides);
     }
     return null;
   }
@@ -11022,18 +11198,18 @@
     // because it needs to be visited in the context of the invocation.
     //
     safelyVisit(node.target);
-    node.accept(_elementResolver);
+    node.accept(elementResolver);
     _inferFunctionExpressionsParametersTypes(node.argumentList);
     safelyVisit(node.argumentList);
-    node.accept(_typeAnalyzer);
+    node.accept(typeAnalyzer);
     return null;
   }
 
   @override
   Object visitNode(AstNode node) {
     node.visitChildren(this);
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -11044,8 +11220,8 @@
     // be visited in the context of the prefix.
     //
     safelyVisit(node.prefix);
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -11056,8 +11232,8 @@
     // to be visited in the context of the property access node.
     //
     safelyVisit(node.target);
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -11070,8 +11246,8 @@
     // invocation.
     //
     safelyVisit(node.argumentList);
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -11086,8 +11262,8 @@
     // invocation.
     //
     safelyVisit(node.argumentList);
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -11131,6 +11307,16 @@
   Object visitTypeName(TypeName node) => null;
 
   @override
+  Object visitVariableDeclaration(VariableDeclaration node) {
+    super.visitVariableDeclaration(node);
+    if (node.element.isConst && node.initializer != null) {
+      (node.element as ConstVariableElement).constantInitializer =
+          new ConstantAstCloner().cloneNode(node.initializer);
+    }
+    return null;
+  }
+
+  @override
   Object visitWhileStatement(WhileStatement node) {
     // Note: since we don't call the base class, we have to maintain
     // _implicitLabelScope ourselves.
@@ -11154,8 +11340,8 @@
     }
     // TODO(brianwilkerson) If the loop can only be exited because the condition
     // is false, then propagateFalseState(condition);
-    node.accept(_elementResolver);
-    node.accept(_typeAnalyzer);
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
     return null;
   }
 
@@ -11397,7 +11583,7 @@
     VariableElement element = getPromotionStaticElement(expression);
     if (element != null) {
       // may be mutated somewhere in closure
-      if ((element as VariableElementImpl).isPotentiallyMutatedInClosure) {
+      if (element.isPotentiallyMutatedInClosure) {
         return;
       }
       // prepare current variable type
@@ -11748,7 +11934,7 @@
   /**
    * The scope used to resolve identifiers.
    */
-  Scope _nameScope;
+  Scope nameScope;
 
   /**
    * The object used to access the types from the core library.
@@ -11764,7 +11950,7 @@
    * The scope used to resolve labels for `break` and `continue` statements, or
    * `null` if no labels have been defined in the current context.
    */
-  LabelScope _labelScope;
+  LabelScope labelScope;
 
   /**
    * The class containing the AST nodes being visited,
@@ -11783,7 +11969,7 @@
     this._definingLibrary = library.libraryElement;
     LibraryScope libraryScope = library.libraryScope;
     this._errorListener = libraryScope.errorListener;
-    this._nameScope = libraryScope;
+    this.nameScope = libraryScope;
   }
 
   /**
@@ -11800,7 +11986,7 @@
       this.typeProvider, AnalysisErrorListener errorListener) {
     this._definingLibrary = definingLibrary;
     this._errorListener = errorListener;
-    this._nameScope = new LibraryScope(definingLibrary, errorListener);
+    this.nameScope = new LibraryScope(definingLibrary, errorListener);
   }
 
   /**
@@ -11818,7 +12004,7 @@
       this.typeProvider, Scope nameScope, AnalysisErrorListener errorListener) {
     this._definingLibrary = definingLibrary;
     this._errorListener = errorListener;
-    this._nameScope = nameScope;
+    this.nameScope = nameScope;
   }
 
   /**
@@ -11833,7 +12019,7 @@
     this._definingLibrary = library.libraryElement;
     LibraryScope libraryScope = library.libraryScope;
     this._errorListener = libraryScope.errorListener;
-    this._nameScope = libraryScope;
+    this.nameScope = libraryScope;
   }
 
   /**
@@ -11850,27 +12036,13 @@
   ImplicitLabelScope get implicitLabelScope => _implicitLabelScope;
 
   /**
-   * Return the label scope in which the current node is being resolved.
-   *
-   * @return the label scope in which the current node is being resolved
-   */
-  LabelScope get labelScope => _labelScope;
-
-  /**
-   * Return the name scope in which the current node is being resolved.
-   *
-   * @return the name scope in which the current node is being resolved
-   */
-  Scope get nameScope => _nameScope;
-
-  /**
    * Replaces the current [Scope] with the enclosing [Scope].
    *
    * @return the enclosing [Scope].
    */
   Scope popNameScope() {
-    _nameScope = _nameScope.enclosingScope;
-    return _nameScope;
+    nameScope = nameScope.enclosingScope;
+    return nameScope;
   }
 
   /**
@@ -11879,9 +12051,9 @@
    * @return the new [Scope].
    */
   Scope pushNameScope() {
-    Scope newScope = new EnclosedScope(_nameScope);
-    _nameScope = newScope;
-    return _nameScope;
+    Scope newScope = new EnclosedScope(nameScope);
+    nameScope = newScope;
+    return nameScope;
   }
 
   /**
@@ -11937,14 +12109,14 @@
 
   @override
   Object visitBlock(Block node) {
-    Scope outerScope = _nameScope;
+    Scope outerScope = nameScope;
     try {
-      EnclosedScope enclosedScope = new EnclosedScope(_nameScope);
+      EnclosedScope enclosedScope = new EnclosedScope(nameScope);
       _hideNamesDefinedInBlock(enclosedScope, node);
-      _nameScope = enclosedScope;
+      nameScope = enclosedScope;
       super.visitBlock(node);
     } finally {
-      _nameScope = outerScope;
+      nameScope = outerScope;
     }
     return null;
   }
@@ -11965,17 +12137,17 @@
   Object visitCatchClause(CatchClause node) {
     SimpleIdentifier exception = node.exceptionParameter;
     if (exception != null) {
-      Scope outerScope = _nameScope;
+      Scope outerScope = nameScope;
       try {
-        _nameScope = new EnclosedScope(_nameScope);
-        _nameScope.define(exception.staticElement);
+        nameScope = new EnclosedScope(nameScope);
+        nameScope.define(exception.staticElement);
         SimpleIdentifier stackTrace = node.stackTraceParameter;
         if (stackTrace != null) {
-          _nameScope.define(stackTrace.staticElement);
+          nameScope.define(stackTrace.staticElement);
         }
         super.visitCatchClause(node);
       } finally {
-        _nameScope = outerScope;
+        nameScope = outerScope;
       }
     } else {
       super.visitCatchClause(node);
@@ -11986,7 +12158,7 @@
   @override
   Object visitClassDeclaration(ClassDeclaration node) {
     ClassElement classElement = node.element;
-    Scope outerScope = _nameScope;
+    Scope outerScope = nameScope;
     try {
       if (classElement == null) {
         AnalysisEngine.instance.logger.logInformation(
@@ -11997,16 +12169,16 @@
         ClassElement outerClass = enclosingClass;
         try {
           enclosingClass = node.element;
-          _nameScope = new TypeParameterScope(_nameScope, classElement);
+          nameScope = new TypeParameterScope(nameScope, classElement);
           visitClassDeclarationInScope(node);
-          _nameScope = new ClassScope(_nameScope, classElement);
+          nameScope = new ClassScope(nameScope, classElement);
           visitClassMembersInScope(node);
         } finally {
           enclosingClass = outerClass;
         }
       }
     } finally {
-      _nameScope = outerScope;
+      nameScope = outerScope;
     }
     return null;
   }
@@ -12028,14 +12200,14 @@
 
   @override
   Object visitClassTypeAlias(ClassTypeAlias node) {
-    Scope outerScope = _nameScope;
+    Scope outerScope = nameScope;
     try {
       ClassElement element = node.element;
-      _nameScope =
-          new ClassScope(new TypeParameterScope(_nameScope, element), element);
+      nameScope =
+          new ClassScope(new TypeParameterScope(nameScope, element), element);
       super.visitClassTypeAlias(node);
     } finally {
-      _nameScope = outerScope;
+      nameScope = outerScope;
     }
     return null;
   }
@@ -12043,7 +12215,7 @@
   @override
   Object visitConstructorDeclaration(ConstructorDeclaration node) {
     ConstructorElement constructorElement = node.element;
-    Scope outerScope = _nameScope;
+    Scope outerScope = nameScope;
     try {
       if (constructorElement == null) {
         StringBuffer buffer = new StringBuffer();
@@ -12058,11 +12230,11 @@
         AnalysisEngine.instance.logger.logInformation(buffer.toString(),
             new CaughtException(new AnalysisException(), null));
       } else {
-        _nameScope = new FunctionScope(_nameScope, constructorElement);
+        nameScope = new FunctionScope(nameScope, constructorElement);
       }
       super.visitConstructorDeclaration(node);
     } finally {
-      _nameScope = outerScope;
+      nameScope = outerScope;
     }
     return null;
   }
@@ -12071,7 +12243,7 @@
   Object visitDeclaredIdentifier(DeclaredIdentifier node) {
     VariableElement element = node.element;
     if (element != null) {
-      _nameScope.define(element);
+      nameScope.define(element);
     }
     super.visitDeclaredIdentifier(node);
     return null;
@@ -12092,14 +12264,14 @@
 
   @override
   Object visitForEachStatement(ForEachStatement node) {
-    Scope outerNameScope = _nameScope;
+    Scope outerNameScope = nameScope;
     ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
     try {
-      _nameScope = new EnclosedScope(_nameScope);
+      nameScope = new EnclosedScope(nameScope);
       _implicitLabelScope = _implicitLabelScope.nest(node);
       visitForEachStatementInScope(node);
     } finally {
-      _nameScope = outerNameScope;
+      nameScope = outerNameScope;
       _implicitLabelScope = outerImplicitScope;
     }
     return null;
@@ -12130,26 +12302,26 @@
     // scope.  Note: we must not do this if the parent is a
     // FunctionTypedFormalParameter, because in that case we aren't finished
     // resolving the full function signature, just a part of it.
-    if (_nameScope is FunctionScope &&
+    if (nameScope is FunctionScope &&
         node.parent is! FunctionTypedFormalParameter) {
-      (_nameScope as FunctionScope).defineParameters();
+      (nameScope as FunctionScope).defineParameters();
     }
-    if (_nameScope is FunctionTypeScope) {
-      (_nameScope as FunctionTypeScope).defineParameters();
+    if (nameScope is FunctionTypeScope) {
+      (nameScope as FunctionTypeScope).defineParameters();
     }
     return null;
   }
 
   @override
   Object visitForStatement(ForStatement node) {
-    Scope outerNameScope = _nameScope;
+    Scope outerNameScope = nameScope;
     ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
     try {
-      _nameScope = new EnclosedScope(_nameScope);
+      nameScope = new EnclosedScope(nameScope);
       _implicitLabelScope = _implicitLabelScope.nest(node);
       visitForStatementInScope(node);
     } finally {
-      _nameScope = outerNameScope;
+      nameScope = outerNameScope;
       _implicitLabelScope = outerImplicitScope;
     }
     return null;
@@ -12175,20 +12347,20 @@
     ExecutableElement functionElement = node.element;
     if (functionElement != null &&
         functionElement.enclosingElement is! CompilationUnitElement) {
-      _nameScope.define(functionElement);
+      nameScope.define(functionElement);
     }
-    Scope outerScope = _nameScope;
+    Scope outerScope = nameScope;
     try {
       if (functionElement == null) {
         AnalysisEngine.instance.logger.logInformation(
             "Missing element for top-level function ${node.name.name} in ${definingLibrary.source.fullName}",
             new CaughtException(new AnalysisException(), null));
       } else {
-        _nameScope = new FunctionScope(_nameScope, functionElement);
+        nameScope = new FunctionScope(nameScope, functionElement);
       }
       super.visitFunctionDeclaration(node);
     } finally {
-      _nameScope = outerScope;
+      nameScope = outerScope;
     }
     return null;
   }
@@ -12199,7 +12371,7 @@
       // We have already created a function scope and don't need to do so again.
       super.visitFunctionExpression(node);
     } else {
-      Scope outerScope = _nameScope;
+      Scope outerScope = nameScope;
       try {
         ExecutableElement functionElement = node.element;
         if (functionElement == null) {
@@ -12220,11 +12392,11 @@
           AnalysisEngine.instance.logger.logInformation(buffer.toString(),
               new CaughtException(new AnalysisException(), null));
         } else {
-          _nameScope = new FunctionScope(_nameScope, functionElement);
+          nameScope = new FunctionScope(nameScope, functionElement);
         }
         super.visitFunctionExpression(node);
       } finally {
-        _nameScope = outerScope;
+        nameScope = outerScope;
       }
     }
     return null;
@@ -12232,12 +12404,12 @@
 
   @override
   Object visitFunctionTypeAlias(FunctionTypeAlias node) {
-    Scope outerScope = _nameScope;
+    Scope outerScope = nameScope;
     try {
-      _nameScope = new FunctionTypeScope(_nameScope, node.element);
+      nameScope = new FunctionTypeScope(nameScope, node.element);
       super.visitFunctionTypeAlias(node);
     } finally {
-      _nameScope = outerScope;
+      nameScope = outerScope;
     }
     return null;
   }
@@ -12256,14 +12428,14 @@
     try {
       super.visitLabeledStatement(node);
     } finally {
-      _labelScope = outerScope;
+      labelScope = outerScope;
     }
     return null;
   }
 
   @override
   Object visitMethodDeclaration(MethodDeclaration node) {
-    Scope outerScope = _nameScope;
+    Scope outerScope = nameScope;
     try {
       ExecutableElement methodElement = node.element;
       if (methodElement == null) {
@@ -12271,11 +12443,11 @@
             "Missing element for method ${node.name.name} in ${definingLibrary.source.fullName}",
             new CaughtException(new AnalysisException(), null));
       } else {
-        _nameScope = new FunctionScope(_nameScope, methodElement);
+        nameScope = new FunctionScope(nameScope, methodElement);
       }
       super.visitMethodDeclaration(node);
     } finally {
-      _nameScope = outerScope;
+      nameScope = outerScope;
     }
     return null;
   }
@@ -12292,12 +12464,12 @@
       // own scope.
       visitBlock(node);
     } else if (node != null) {
-      Scope outerNameScope = _nameScope;
+      Scope outerNameScope = nameScope;
       try {
-        _nameScope = new EnclosedScope(_nameScope);
+        nameScope = new EnclosedScope(nameScope);
         node.accept(this);
       } finally {
-        _nameScope = outerNameScope;
+        nameScope = outerNameScope;
       }
     }
   }
@@ -12305,31 +12477,31 @@
   @override
   Object visitSwitchCase(SwitchCase node) {
     node.expression.accept(this);
-    Scope outerNameScope = _nameScope;
+    Scope outerNameScope = nameScope;
     try {
-      _nameScope = new EnclosedScope(_nameScope);
+      nameScope = new EnclosedScope(nameScope);
       node.statements.accept(this);
     } finally {
-      _nameScope = outerNameScope;
+      nameScope = outerNameScope;
     }
     return null;
   }
 
   @override
   Object visitSwitchDefault(SwitchDefault node) {
-    Scope outerNameScope = _nameScope;
+    Scope outerNameScope = nameScope;
     try {
-      _nameScope = new EnclosedScope(_nameScope);
+      nameScope = new EnclosedScope(nameScope);
       node.statements.accept(this);
     } finally {
-      _nameScope = outerNameScope;
+      nameScope = outerNameScope;
     }
     return null;
   }
 
   @override
   Object visitSwitchStatement(SwitchStatement node) {
-    LabelScope outerScope = _labelScope;
+    LabelScope outerScope = labelScope;
     ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
     try {
       _implicitLabelScope = _implicitLabelScope.nest(node);
@@ -12337,13 +12509,13 @@
         for (Label label in member.labels) {
           SimpleIdentifier labelName = label.label;
           LabelElement labelElement = labelName.staticElement as LabelElement;
-          _labelScope =
-              new LabelScope(_labelScope, labelName.name, member, labelElement);
+          labelScope =
+              new LabelScope(labelScope, labelName.name, member, labelElement);
         }
       }
       super.visitSwitchStatement(node);
     } finally {
-      _labelScope = outerScope;
+      labelScope = outerScope;
       _implicitLabelScope = outerImplicitScope;
     }
     return null;
@@ -12356,7 +12528,7 @@
         node.parent.parent is! FieldDeclaration) {
       VariableElement element = node.element;
       if (element != null) {
-        _nameScope.define(element);
+        nameScope.define(element);
       }
     }
     return null;
@@ -12382,12 +12554,12 @@
    * @return the scope that was in effect before the new scopes were added
    */
   LabelScope _addScopesFor(NodeList<Label> labels, AstNode node) {
-    LabelScope outerScope = _labelScope;
+    LabelScope outerScope = labelScope;
     for (Label label in labels) {
       SimpleIdentifier labelNameNode = label.label;
       String labelName = labelNameNode.name;
       LabelElement labelElement = labelNameNode.staticElement as LabelElement;
-      _labelScope = new LabelScope(_labelScope, labelName, node, labelElement);
+      labelScope = new LabelScope(labelScope, labelName, node, labelElement);
     }
     return outerScope;
   }
@@ -12646,7 +12818,7 @@
   /**
    * The current override scope, or `null` if no scope has been entered.
    */
-  TypeOverrideManager_TypeOverrideScope _currentScope;
+  TypeOverrideManager_TypeOverrideScope currentScope;
 
   /**
    * Apply a set of overrides that were previously captured.
@@ -12654,10 +12826,10 @@
    * @param overrides the overrides to be applied
    */
   void applyOverrides(Map<VariableElement, DartType> overrides) {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       throw new IllegalStateException("Cannot apply overrides without a scope");
     }
-    _currentScope.applyOverrides(overrides);
+    currentScope.applyOverrides(overrides);
   }
 
   /**
@@ -12667,11 +12839,11 @@
    * @return the overrides in the current scope
    */
   Map<VariableElement, DartType> captureLocalOverrides() {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       throw new IllegalStateException(
           "Cannot capture local overrides without a scope");
     }
-    return _currentScope.captureLocalOverrides();
+    return currentScope.captureLocalOverrides();
   }
 
   /**
@@ -12683,28 +12855,28 @@
    */
   Map<VariableElement, DartType> captureOverrides(
       VariableDeclarationList variableList) {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       throw new IllegalStateException(
           "Cannot capture overrides without a scope");
     }
-    return _currentScope.captureOverrides(variableList);
+    return currentScope.captureOverrides(variableList);
   }
 
   /**
    * Enter a new override scope.
    */
   void enterScope() {
-    _currentScope = new TypeOverrideManager_TypeOverrideScope(_currentScope);
+    currentScope = new TypeOverrideManager_TypeOverrideScope(currentScope);
   }
 
   /**
    * Exit the current override scope.
    */
   void exitScope() {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       throw new IllegalStateException("No scope to exit");
     }
-    _currentScope = _currentScope._outerScope;
+    currentScope = currentScope._outerScope;
   }
 
   /**
@@ -12727,83 +12899,28 @@
    * @return the overridden type of the given element
    */
   DartType getType(Element element) {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       return null;
     }
-    return _currentScope.getType(element);
+    return currentScope.getType(element);
   }
 
   /**
-   * Update overrides assuming `perBranchOverrides` is the collection of per-branch overrides
-   * for *all* branches flowing into a join point. If a variable is updated in each per-branch
-   * override, then its type before the branching is ignored. Otherwise, its type before the
-   * branching is merged with all updates in the branches.
+   * Update overrides assuming [perBranchOverrides] is the collection of
+   * per-branch overrides for *all* branches flowing into a join point.
    *
-   * Although this method would do the right thing for a single set of overrides, we require there
-   * to be at least two override sets. Instead use `applyOverrides` for to apply a single set.
-   *
-   * For example, for the code
-   *
-   * <pre>
-   *   if (c) {
-   *     ...
-   *   } else {
-   *     ...
-   *   }
-   * </pre>
-   * the `perBranchOverrides` would include overrides for the then and else branches, and for
-   * the code
-   *
-   * <pre>
-   *   ...
-   *   while(c) {
-   *     ...
-   *   }
-   * </pre>
-   * the `perBranchOverrides` would include overrides for before the loop and for the loop
-   * body.
-   *
-   * @param perBranchOverrides one set of overrides for each (at least two) branch flowing into the
-   *          join point
+   * If a variable type in any of branches is not the same as its type before
+   * the branching, then its propagated type is reset to `null`.
    */
-  void joinOverrides(List<Map<VariableElement, DartType>> perBranchOverrides) {
-    if (perBranchOverrides.length < 2) {
-      throw new IllegalArgumentException(
-          "There is no point in joining zero or one override sets.");
-    }
-    Set<VariableElement> allElements = new HashSet<VariableElement>();
-    Set<VariableElement> commonElements =
-        new HashSet<VariableElement>.from(perBranchOverrides[0].keys.toSet());
-    for (Map<VariableElement, DartType> os in perBranchOverrides) {
-      // Union: elements updated in some branch.
-      allElements.addAll(os.keys.toSet());
-      // Intersection: elements updated in all branches.
-      commonElements.retainAll(os.keys.toSet());
-    }
-    Set<VariableElement> uncommonElements = allElements;
-    // Difference: elements updated in some but not all branches.
-    uncommonElements.removeAll(commonElements);
-    Map<VariableElement, DartType> joinOverrides =
-        new HashMap<VariableElement, DartType>();
-    // The common elements were updated in all branches, so their type
-    // before branching can be ignored.
-    for (VariableElement e in commonElements) {
-      joinOverrides[e] = perBranchOverrides[0][e];
-      for (Map<VariableElement, DartType> os in perBranchOverrides) {
-        joinOverrides[e] = UnionTypeImpl.union([joinOverrides[e], os[e]]);
-      }
-    }
-    // The uncommon elements were updated in some but not all branches,
-    // so they may still have the type they had before branching.
-    for (VariableElement e in uncommonElements) {
-      joinOverrides[e] = getBestType(e);
-      for (Map<VariableElement, DartType> os in perBranchOverrides) {
-        if (os.containsKey(e)) {
-          joinOverrides[e] = UnionTypeImpl.union([joinOverrides[e], os[e]]);
+  void mergeOverrides(List<Map<VariableElement, DartType>> perBranchOverrides) {
+    for (Map<VariableElement, DartType> branch in perBranchOverrides) {
+      branch.forEach((VariableElement variable, DartType branchType) {
+        DartType currentType = currentScope.getType(variable);
+        if (currentType != branchType) {
+          currentScope.resetType(variable);
         }
-      }
+      });
     }
-    applyOverrides(joinOverrides);
   }
 
   /**
@@ -12813,10 +12930,10 @@
    * @param type the overridden type of the given element
    */
   void setType(VariableElement element, DartType type) {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       throw new IllegalStateException("Cannot override without a scope");
     }
-    _currentScope.setType(element, type);
+    currentScope.setType(element, type);
   }
 }
 
@@ -12893,9 +13010,12 @@
    * @return the overridden type of the given element
    */
   DartType getType(Element element) {
+    if (element is PropertyAccessorElement) {
+      element = (element as PropertyAccessorElement).variable;
+    }
     DartType type = _overridenTypes[element];
-    if (type == null && element is PropertyAccessorElement) {
-      type = _overridenTypes[element.variable];
+    if (_overridenTypes.containsKey(element)) {
+      return type;
     }
     if (type != null) {
       return type;
@@ -12906,6 +13026,13 @@
   }
 
   /**
+   * Clears the overridden type of the given [element].
+   */
+  void resetType(VariableElement element) {
+    _overridenTypes[element] = null;
+  }
+
+  /**
    * Set the overridden type of the given element to the given type
    *
    * @param element the element whose type might have been overridden
@@ -12955,28 +13082,28 @@
   /**
    * The current promotion scope, or `null` if no scope has been entered.
    */
-  TypePromotionManager_TypePromoteScope _currentScope;
+  TypePromotionManager_TypePromoteScope currentScope;
 
   /**
    * Returns the elements with promoted types.
    */
-  Iterable<Element> get promotedElements => _currentScope.promotedElements;
+  Iterable<Element> get promotedElements => currentScope.promotedElements;
 
   /**
    * Enter a new promotions scope.
    */
   void enterScope() {
-    _currentScope = new TypePromotionManager_TypePromoteScope(_currentScope);
+    currentScope = new TypePromotionManager_TypePromoteScope(currentScope);
   }
 
   /**
    * Exit the current promotion scope.
    */
   void exitScope() {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       throw new IllegalStateException("No scope to exit");
     }
-    _currentScope = _currentScope._outerScope;
+    currentScope = currentScope._outerScope;
   }
 
   /**
@@ -13000,10 +13127,10 @@
    * @return the promoted type of the given element
    */
   DartType getType(Element element) {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       return null;
     }
-    return _currentScope.getType(element);
+    return currentScope.getType(element);
   }
 
   /**
@@ -13013,10 +13140,10 @@
    * @param type the promoted type of the given element
    */
   void setType(Element element, DartType type) {
-    if (_currentScope == null) {
+    if (currentScope == null) {
       throw new IllegalStateException("Cannot promote without a scope");
     }
-    _currentScope.setType(element, type);
+    currentScope.setType(element, type);
   }
 }
 
@@ -13085,43 +13212,31 @@
 abstract class TypeProvider {
   /**
    * Return the type representing the built-in type 'bool'.
-   *
-   * @return the type representing the built-in type 'bool'
    */
   InterfaceType get boolType;
 
   /**
    * Return the type representing the type 'bottom'.
-   *
-   * @return the type representing the type 'bottom'
    */
   DartType get bottomType;
 
   /**
    * Return the type representing the built-in type 'Deprecated'.
-   *
-   * @return the type representing the built-in type 'Deprecated'
    */
   InterfaceType get deprecatedType;
 
   /**
    * Return the type representing the built-in type 'double'.
-   *
-   * @return the type representing the built-in type 'double'
    */
   InterfaceType get doubleType;
 
   /**
    * Return the type representing the built-in type 'dynamic'.
-   *
-   * @return the type representing the built-in type 'dynamic'
    */
   DartType get dynamicType;
 
   /**
    * Return the type representing the built-in type 'Function'.
-   *
-   * @return the type representing the built-in type 'Function'
    */
   InterfaceType get functionType;
 
@@ -13142,8 +13257,6 @@
 
   /**
    * Return the type representing the built-in type 'int'.
-   *
-   * @return the type representing the built-in type 'int'
    */
   InterfaceType get intType;
 
@@ -13159,15 +13272,17 @@
 
   /**
    * Return the type representing the built-in type 'List'.
-   *
-   * @return the type representing the built-in type 'List'
    */
   InterfaceType get listType;
 
   /**
+   * Return a list containing all of the types that cannot be either extended or
+   * implemented.
+   */
+  List<InterfaceType> get nonSubtypableTypes;
+
+  /**
    * Return the type representing the built-in type 'Map'.
-   *
-   * @return the type representing the built-in type 'Map'
    */
   InterfaceType get mapType;
 
@@ -13178,29 +13293,21 @@
 
   /**
    * Return the type representing the built-in type 'Null'.
-   *
-   * @return the type representing the built-in type 'null'
    */
   InterfaceType get nullType;
 
   /**
    * Return the type representing the built-in type 'num'.
-   *
-   * @return the type representing the built-in type 'num'
    */
   InterfaceType get numType;
 
   /**
    * Return the type representing the built-in type 'Object'.
-   *
-   * @return the type representing the built-in type 'Object'
    */
   InterfaceType get objectType;
 
   /**
    * Return the type representing the built-in type 'StackTrace'.
-   *
-   * @return the type representing the built-in type 'StackTrace'
    */
   InterfaceType get stackTraceType;
 
@@ -13216,22 +13323,16 @@
 
   /**
    * Return the type representing the built-in type 'String'.
-   *
-   * @return the type representing the built-in type 'String'
    */
   InterfaceType get stringType;
 
   /**
    * Return the type representing the built-in type 'Symbol'.
-   *
-   * @return the type representing the built-in type 'Symbol'
    */
   InterfaceType get symbolType;
 
   /**
    * Return the type representing the built-in type 'Type'.
-   *
-   * @return the type representing the built-in type 'Type'
    */
   InterfaceType get typeType;
 
@@ -13435,6 +13536,16 @@
   InterfaceType get mapType => _mapType;
 
   @override
+  List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[
+    nullType,
+    numType,
+    intType,
+    doubleType,
+    boolType,
+    stringType
+  ];
+
+  @override
   DartObjectImpl get nullObject {
     if (_nullObject == null) {
       _nullObject = new DartObjectImpl(nullType, NullState.NULL_STATE);
@@ -14737,6 +14848,260 @@
 }
 
 /**
+ * Instances of the class [UnusedLocalElementsVerifier] traverse an element
+ * structure looking for cases of [HintCode.UNUSED_ELEMENT],
+ * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc.
+ */
+class UnusedLocalElementsVerifier extends RecursiveElementVisitor {
+  /**
+   * The error listener to which errors will be reported.
+   */
+  final AnalysisErrorListener _errorListener;
+
+  /**
+   * The elements know to be used.
+   */
+  final UsedLocalElements _usedElements;
+
+  /**
+   * Create a new instance of the [UnusedLocalElementsVerifier].
+   */
+  UnusedLocalElementsVerifier(this._errorListener, this._usedElements);
+
+  @override
+  visitClassElement(ClassElement element) {
+    if (!_isUsedElement(element)) {
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
+        element.kind.displayName,
+        element.displayName
+      ]);
+    }
+    super.visitClassElement(element);
+  }
+
+  @override
+  visitFieldElement(FieldElement element) {
+    if (!_isReadMember(element)) {
+      _reportErrorForElement(
+          HintCode.UNUSED_FIELD, element, [element.displayName]);
+    }
+    super.visitFieldElement(element);
+  }
+
+  @override
+  visitFunctionElement(FunctionElement element) {
+    if (!_isUsedElement(element)) {
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
+        element.kind.displayName,
+        element.displayName
+      ]);
+    }
+    super.visitFunctionElement(element);
+  }
+
+  @override
+  visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
+    if (!_isUsedElement(element)) {
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
+        element.kind.displayName,
+        element.displayName
+      ]);
+    }
+    super.visitFunctionTypeAliasElement(element);
+  }
+
+  @override
+  visitLocalVariableElement(LocalVariableElement element) {
+    if (!_isUsedElement(element) && !_isNamedUnderscore(element)) {
+      HintCode errorCode;
+      if (_usedElements.isCatchException(element)) {
+        errorCode = HintCode.UNUSED_CATCH_CLAUSE;
+      } else if (_usedElements.isCatchStackTrace(element)) {
+        errorCode = HintCode.UNUSED_CATCH_STACK;
+      } else {
+        errorCode = HintCode.UNUSED_LOCAL_VARIABLE;
+      }
+      _reportErrorForElement(errorCode, element, [element.displayName]);
+    }
+  }
+
+  @override
+  visitMethodElement(MethodElement element) {
+    if (!_isUsedMember(element)) {
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
+        element.kind.displayName,
+        element.displayName
+      ]);
+    }
+    super.visitMethodElement(element);
+  }
+
+  @override
+  visitPropertyAccessorElement(PropertyAccessorElement element) {
+    if (!_isUsedMember(element)) {
+      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
+        element.kind.displayName,
+        element.displayName
+      ]);
+    }
+    super.visitPropertyAccessorElement(element);
+  }
+
+  bool _isNamedUnderscore(LocalVariableElement element) {
+    String name = element.name;
+    if (name != null) {
+      for (int index = name.length - 1; index >= 0; --index) {
+        if (name.codeUnitAt(index) != 0x5F) {
+          // 0x5F => '_'
+          return false;
+        }
+      }
+      return true;
+    }
+    return false;
+  }
+
+  bool _isReadMember(Element element) {
+    if (element.isPublic) {
+      return true;
+    }
+    if (element.isSynthetic) {
+      return true;
+    }
+    return _usedElements.readMembers.contains(element.displayName);
+  }
+
+  bool _isUsedElement(Element element) {
+    if (element.isSynthetic) {
+      return true;
+    }
+    if (element is LocalVariableElement ||
+        element is FunctionElement && !element.isStatic) {
+      // local variable or function
+    } else {
+      if (element.isPublic) {
+        return true;
+      }
+    }
+    return _usedElements.elements.contains(element);
+  }
+
+  bool _isUsedMember(Element element) {
+    if (element.isPublic) {
+      return true;
+    }
+    if (element.isSynthetic) {
+      return true;
+    }
+    if (_usedElements.members.contains(element.displayName)) {
+      return true;
+    }
+    return _usedElements.elements.contains(element);
+  }
+
+  void _reportErrorForElement(
+      ErrorCode errorCode, Element element, List<Object> arguments) {
+    if (element != null) {
+      _errorListener.onError(new AnalysisError.con2(element.source,
+          element.nameOffset, element.displayName.length, errorCode,
+          arguments));
+    }
+  }
+}
+
+/**
+ * A container with information about used imports prefixes and used imported
+ * elements.
+ */
+class UsedImportedElements {
+  /**
+   * The set of referenced [PrefixElement]s.
+   */
+  final Set<PrefixElement> prefixes = new HashSet<PrefixElement>();
+
+  /**
+   * The set of referenced top-level [Element]s.
+   */
+  final Set<Element> elements = new HashSet<Element>();
+}
+
+/**
+ * A container with sets of used [Element]s.
+ * All these elements are defined in a single compilation unit or a library.
+ */
+class UsedLocalElements {
+  /**
+   * Resolved, locally defined elements that are used or potentially can be
+   * used.
+   */
+  final HashSet<Element> elements = new HashSet<Element>();
+
+  /**
+   * [LocalVariableElement]s that represent exceptions in [CatchClause]s.
+   */
+  final HashSet<LocalVariableElement> catchExceptionElements =
+      new HashSet<LocalVariableElement>();
+
+  /**
+   * [LocalVariableElement]s that represent stack traces in [CatchClause]s.
+   */
+  final HashSet<LocalVariableElement> catchStackTraceElements =
+      new HashSet<LocalVariableElement>();
+
+  /**
+   * Names of resolved or unresolved class members that are referenced in the
+   * library.
+   */
+  final HashSet<String> members = new HashSet<String>();
+
+  /**
+   * Names of resolved or unresolved class members that are read in the
+   * library.
+   */
+  final HashSet<String> readMembers = new HashSet<String>();
+
+  UsedLocalElements();
+
+  factory UsedLocalElements.merge(List<UsedLocalElements> parts) {
+    UsedLocalElements result = new UsedLocalElements();
+    for (UsedLocalElements part in parts) {
+      result.elements.addAll(part.elements);
+      result.catchExceptionElements.addAll(part.catchExceptionElements);
+      result.catchStackTraceElements.addAll(part.catchStackTraceElements);
+      result.members.addAll(part.members);
+      result.readMembers.addAll(part.readMembers);
+    }
+    return result;
+  }
+
+  void addCatchException(LocalVariableElement element) {
+    if (element != null) {
+      catchExceptionElements.add(element);
+    }
+  }
+
+  void addCatchStackTrace(LocalVariableElement element) {
+    if (element != null) {
+      catchStackTraceElements.add(element);
+    }
+  }
+
+  void addElement(Element element) {
+    if (element != null) {
+      elements.add(element);
+    }
+  }
+
+  bool isCatchException(LocalVariableElement element) {
+    return catchExceptionElements.contains(element);
+  }
+
+  bool isCatchStackTrace(LocalVariableElement element) {
+    return catchStackTraceElements.contains(element);
+  }
+}
+
+/**
  * Instances of the class `VariableResolverVisitor` are used to resolve
  * [SimpleIdentifier]s to local variables and formal parameters.
  */
@@ -14962,179 +15327,6 @@
   Object visitNode(AstNode node) => node.accept(builder);
 }
 
-class _GatherUsedElementsVisitor extends RecursiveAstVisitor {
-  final _UsedElements usedElements = new _UsedElements();
-
-  final LibraryElement _enclosingLibrary;
-  ClassElement _enclosingClass;
-  ExecutableElement _enclosingExec;
-
-  _GatherUsedElementsVisitor(this._enclosingLibrary);
-
-  @override
-  visitCatchClause(CatchClause node) {
-    SimpleIdentifier exceptionParameter = node.exceptionParameter;
-    SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
-    if (exceptionParameter != null) {
-      Element element = exceptionParameter.staticElement;
-      usedElements.addCatchException(element);
-      if (stackTraceParameter != null || node.onKeyword == null) {
-        _useElement(element);
-      }
-    }
-    if (stackTraceParameter != null) {
-      Element element = stackTraceParameter.staticElement;
-      usedElements.addCatchStackTrace(element);
-    }
-    super.visitCatchClause(node);
-  }
-
-  @override
-  visitClassDeclaration(ClassDeclaration node) {
-    ClassElement enclosingClassOld = _enclosingClass;
-    try {
-      _enclosingClass = node.element;
-      super.visitClassDeclaration(node);
-    } finally {
-      _enclosingClass = enclosingClassOld;
-    }
-  }
-
-  @override
-  visitFunctionDeclaration(FunctionDeclaration node) {
-    ExecutableElement enclosingExecOld = _enclosingExec;
-    try {
-      _enclosingExec = node.element;
-      super.visitFunctionDeclaration(node);
-    } finally {
-      _enclosingExec = enclosingExecOld;
-    }
-  }
-
-  @override
-  visitFunctionExpression(FunctionExpression node) {
-    if (node.parent is! FunctionDeclaration) {
-      _useElement(node.element);
-    }
-    super.visitFunctionExpression(node);
-  }
-
-  @override
-  visitMethodDeclaration(MethodDeclaration node) {
-    ExecutableElement enclosingExecOld = _enclosingExec;
-    try {
-      _enclosingExec = node.element;
-      super.visitMethodDeclaration(node);
-    } finally {
-      _enclosingExec = enclosingExecOld;
-    }
-  }
-
-  @override
-  visitSimpleIdentifier(SimpleIdentifier node) {
-    if (node.inDeclarationContext()) {
-      return;
-    }
-    Element element = node.staticElement;
-    bool isIdentifierRead = _isReadIdentifier(node);
-    if (element is LocalVariableElement) {
-      if (isIdentifierRead) {
-        _useElement(element);
-      }
-//    } else if (element is PropertyAccessorElement &&
-//        element.isSynthetic &&
-//        element.isPrivate) {
-//      PropertyInducingElement variable = element.variable;
-//      if (node.inGetterContext()) {
-//        AstNode parent = node.parent;
-//        if (parent.parent is ExpressionStatement &&
-//            (parent is PrefixExpression ||
-//             parent is PostfixExpression ||
-//             parent is AssignmentExpression && parent.leftHandSide == node)) {
-//          // f++;
-//          // ++f;
-//          // f += 2;
-//        } else {
-//          _useElement(variable);
-//        }
-//      }
-    } else {
-      _useIdentifierElement(node);
-      if (element == null ||
-          element is! LocalElement && !identical(element, _enclosingExec)) {
-        usedElements.members.add(node.name);
-        if (isIdentifierRead) {
-          usedElements.readMembers.add(node.name);
-        }
-      }
-    }
-  }
-
-  @override
-  visitTypeName(TypeName node) {
-    _useIdentifierElement(node.name);
-  }
-
-  _useElement(Element element) {
-    if (element != null) {
-      usedElements.elements.add(element);
-    }
-  }
-
-  /**
-   * Marks an [Element] of [node] as used in the library.
-   */
-  void _useIdentifierElement(Identifier node) {
-    Element element = node.staticElement;
-    if (element == null) {
-      return;
-    }
-    // check if a local element
-    if (!identical(element.library, _enclosingLibrary)) {
-      return;
-    }
-    // ignore references to an element from itself
-    if (identical(element, _enclosingClass)) {
-      return;
-    }
-    if (identical(element, _enclosingExec)) {
-      return;
-    }
-    // ignore places where the element is not actually used
-    if (node.parent is TypeName) {
-      AstNode parent2 = node.parent.parent;
-      if (parent2 is IsExpression) {
-        return;
-      }
-      if (parent2 is VariableDeclarationList) {
-        return;
-      }
-    }
-    // OK
-    _useElement(element);
-  }
-
-  static bool _isReadIdentifier(SimpleIdentifier node) {
-    // not reading at all
-    if (!node.inGetterContext()) {
-      return false;
-    }
-    // check if useless reading
-    AstNode parent = node.parent;
-    if (parent.parent is ExpressionStatement &&
-        (parent is PrefixExpression ||
-            parent is PostfixExpression ||
-            parent is AssignmentExpression && parent.leftHandSide == node)) {
-      // v++;
-      // ++v;
-      // v += 2;
-      return false;
-    }
-    // OK
-    return true;
-  }
-}
-
 class _ResolverVisitor_isVariableAccessedInClosure
     extends RecursiveAstVisitor<Object> {
   final Element variable;
@@ -15224,192 +15416,3 @@
   @override
   Object visitWithClause(WithClause node) => null;
 }
-
-/**
- * Instances of the class [_UnusedElementsVerifier] traverse an element
- * structure looking for cases of [HintCode.UNUSED_ELEMENT] and
- * [HintCode.UNUSED_LOCAL_VARIABLE].
- */
-class _UnusedElementsVerifier extends RecursiveElementVisitor {
-  /**
-   * The error listener to which errors will be reported.
-   */
-  final AnalysisErrorListener _errorListener;
-
-  /**
-   * The elements know to be used.
-   */
-  final _UsedElements _usedElements;
-
-  /**
-   * Create a new instance of the [_UnusedElementsVerifier].
-   */
-  _UnusedElementsVerifier(this._errorListener, this._usedElements);
-
-  @override
-  visitClassElement(ClassElement element) {
-    if (!_isUsedElement(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
-    }
-    super.visitClassElement(element);
-  }
-
-  @override
-  visitFieldElement(FieldElement element) {
-    if (!_isReadMember(element)) {
-      _reportErrorForElement(
-          HintCode.UNUSED_FIELD, element, [element.displayName]);
-    }
-    super.visitFieldElement(element);
-  }
-
-  @override
-  visitFunctionElement(FunctionElement element) {
-    if (!_isUsedElement(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
-    }
-    super.visitFunctionElement(element);
-  }
-
-  @override
-  visitLocalVariableElement(LocalVariableElement element) {
-    if (!_isUsedElement(element)) {
-      HintCode errorCode;
-      if (_usedElements.isCatchException(element)) {
-        errorCode = HintCode.UNUSED_CATCH_CLAUSE;
-      } else if (_usedElements.isCatchStackTrace(element)) {
-        errorCode = HintCode.UNUSED_CATCH_STACK;
-      } else {
-        errorCode = HintCode.UNUSED_LOCAL_VARIABLE;
-      }
-      _reportErrorForElement(errorCode, element, [element.displayName]);
-    }
-  }
-
-  @override
-  visitMethodElement(MethodElement element) {
-    if (!_isUsedMember(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
-    }
-    super.visitMethodElement(element);
-  }
-
-  @override
-  visitPropertyAccessorElement(PropertyAccessorElement element) {
-    if (!_isUsedMember(element)) {
-      _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
-        element.kind.displayName,
-        element.displayName
-      ]);
-    }
-    super.visitPropertyAccessorElement(element);
-  }
-
-  bool _isReadMember(Element element) {
-    if (element.isPublic) {
-      return true;
-    }
-    if (element.isSynthetic) {
-      return true;
-    }
-    return _usedElements.readMembers.contains(element.displayName);
-  }
-
-  bool _isUsedElement(Element element) {
-    if (element.isSynthetic) {
-      return true;
-    }
-    if (element is LocalVariableElement ||
-        element is FunctionElement && !element.isStatic) {
-      // local variable or function
-    } else {
-      if (element.isPublic) {
-        return true;
-      }
-    }
-    return _usedElements.elements.contains(element);
-  }
-
-  bool _isUsedMember(Element element) {
-    if (element.isPublic) {
-      return true;
-    }
-    if (element.isSynthetic) {
-      return true;
-    }
-    if (_usedElements.members.contains(element.displayName)) {
-      return true;
-    }
-    return _usedElements.elements.contains(element);
-  }
-
-  void _reportErrorForElement(
-      ErrorCode errorCode, Element element, List<Object> arguments) {
-    if (element != null) {
-      _errorListener.onError(new AnalysisError.con2(element.source,
-          element.nameOffset, element.displayName.length, errorCode,
-          arguments));
-    }
-  }
-}
-
-class _UsedElements {
-  /**
-   * Resolved, locally defined elements that are used or potentially can be
-   * used.
-   */
-  final HashSet<Element> elements = new HashSet<Element>();
-
-  /**
-   * [LocalVariableElement]s that represent exceptions in [CatchClause]s.
-   */
-  final HashSet<LocalVariableElement> catchExceptionElements =
-      new HashSet<LocalVariableElement>();
-
-  /**
-   * [LocalVariableElement]s that represent stack traces in [CatchClause]s.
-   */
-  final HashSet<LocalVariableElement> catchStackTraceElements =
-      new HashSet<LocalVariableElement>();
-
-  /**
-   * Names of resolved or unresolved class members that are referenced in the
-   * library.
-   */
-  final HashSet<String> members = new HashSet<String>();
-
-  /**
-   * Names of resolved or unresolved class members that are read in the
-   * library.
-   */
-  final HashSet<String> readMembers = new HashSet<String>();
-
-  void addCatchException(LocalVariableElement element) {
-    if (element != null) {
-      catchExceptionElements.add(element);
-    }
-  }
-
-  void addCatchStackTrace(LocalVariableElement element) {
-    if (element != null) {
-      catchStackTraceElements.add(element);
-    }
-  }
-
-  bool isCatchException(LocalVariableElement element) {
-    return catchExceptionElements.contains(element);
-  }
-
-  bool isCatchStackTrace(LocalVariableElement element) {
-    return catchStackTraceElements.contains(element);
-  }
-}
diff --git a/pkg/analyzer/lib/src/generated/scanner.dart b/pkg/analyzer/lib/src/generated/scanner.dart
index 2731610..d7bc236 100644
--- a/pkg/analyzer/lib/src/generated/scanner.dart
+++ b/pkg/analyzer/lib/src/generated/scanner.dart
@@ -723,6 +723,12 @@
   bool _hasUnmatchedGroups = false;
 
   /**
+   * A flag indicating whether null-aware operators ('?.', '??', and '??=')
+   * should be tokenized.
+   */
+  bool enableNullAwareOperators = false;
+
+  /**
    * Initialize a newly created scanner to scan characters from the given
    * [source]. The given character [_reader] will be used to read the characters
    * in the source. The given [_errorListener] will be informed of any errors
@@ -777,140 +783,179 @@
   int bigSwitch(int next) {
     _beginToken();
     if (next == 0xD) {
+      // '\r'
       next = _reader.advance();
       if (next == 0xA) {
+        // '\n'
         next = _reader.advance();
       }
       recordStartOfLine();
       return next;
     } else if (next == 0xA) {
+      // '\n'
       next = _reader.advance();
       recordStartOfLine();
       return next;
     } else if (next == 0x9 || next == 0x20) {
+      // '\t' || ' '
       return _reader.advance();
     }
     if (next == 0x72) {
+      // 'r'
       int peek = _reader.peek();
       if (peek == 0x22 || peek == 0x27) {
+        // '"' || "'"
         int start = _reader.offset;
         return _tokenizeString(_reader.advance(), start, true);
       }
     }
     if (0x61 <= next && next <= 0x7A) {
+      // 'a'-'z'
       return _tokenizeKeywordOrIdentifier(next, true);
     }
     if ((0x41 <= next && next <= 0x5A) || next == 0x5F || next == 0x24) {
+      // 'A'-'Z' || '_' || '$'
       return _tokenizeIdentifier(next, _reader.offset, true);
     }
     if (next == 0x3C) {
+      // '<'
       return _tokenizeLessThan(next);
     }
     if (next == 0x3E) {
+      // '>'
       return _tokenizeGreaterThan(next);
     }
     if (next == 0x3D) {
+      // '='
       return _tokenizeEquals(next);
     }
     if (next == 0x21) {
+      // '!'
       return _tokenizeExclamation(next);
     }
     if (next == 0x2B) {
+      // '+'
       return _tokenizePlus(next);
     }
     if (next == 0x2D) {
+      // '-'
       return _tokenizeMinus(next);
     }
     if (next == 0x2A) {
+      // '*'
       return _tokenizeMultiply(next);
     }
     if (next == 0x25) {
+      // '%'
       return _tokenizePercent(next);
     }
     if (next == 0x26) {
+      // '&'
       return _tokenizeAmpersand(next);
     }
     if (next == 0x7C) {
+      // '|'
       return _tokenizeBar(next);
     }
     if (next == 0x5E) {
+      // '^'
       return _tokenizeCaret(next);
     }
     if (next == 0x5B) {
+      // '['
       return _tokenizeOpenSquareBracket(next);
     }
     if (next == 0x7E) {
+      // '~'
       return _tokenizeTilde(next);
     }
     if (next == 0x5C) {
+      // '\\'
       _appendTokenOfType(TokenType.BACKSLASH);
       return _reader.advance();
     }
     if (next == 0x23) {
+      // '#'
       return _tokenizeTag(next);
     }
     if (next == 0x28) {
+      // '('
       _appendBeginToken(TokenType.OPEN_PAREN);
       return _reader.advance();
     }
     if (next == 0x29) {
+      // ')'
       _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
       return _reader.advance();
     }
     if (next == 0x2C) {
+      // ','
       _appendTokenOfType(TokenType.COMMA);
       return _reader.advance();
     }
     if (next == 0x3A) {
+      // ':'
       _appendTokenOfType(TokenType.COLON);
       return _reader.advance();
     }
     if (next == 0x3B) {
+      // ';'
       _appendTokenOfType(TokenType.SEMICOLON);
       return _reader.advance();
     }
     if (next == 0x3F) {
-      _appendTokenOfType(TokenType.QUESTION);
-      return _reader.advance();
+      // '?'
+      return _tokenizeQuestion();
     }
     if (next == 0x5D) {
+      // ']'
       _appendEndToken(
           TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET);
       return _reader.advance();
     }
     if (next == 0x60) {
+      // '`'
       _appendTokenOfType(TokenType.BACKPING);
       return _reader.advance();
     }
     if (next == 0x7B) {
+      // '{'
       _appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
       return _reader.advance();
     }
     if (next == 0x7D) {
+      // '}'
       _appendEndToken(
           TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
       return _reader.advance();
     }
     if (next == 0x2F) {
+      // '/'
       return _tokenizeSlashOrComment(next);
     }
     if (next == 0x40) {
+      // '@'
       _appendTokenOfType(TokenType.AT);
       return _reader.advance();
     }
     if (next == 0x22 || next == 0x27) {
+      // '"' || "'"
       return _tokenizeString(next, _reader.offset, false);
     }
     if (next == 0x2E) {
+      // '.'
       return _tokenizeDotOrNumber(next);
     }
     if (next == 0x30) {
+      // '0'
       return _tokenizeHexOrNumber(next);
     }
     if (0x31 <= next && next <= 0x39) {
+      // '1'-'9'
       return _tokenizeNumber(next);
     }
     if (next == -1) {
+      // EOF
       return -1;
     }
     _reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
@@ -1616,6 +1661,30 @@
     }
   }
 
+  int _tokenizeQuestion() {
+    // ? ?. ?? ??=
+    int next = _reader.advance();
+    if (enableNullAwareOperators && next == 0x2E) {
+      // '.'
+      _appendTokenOfType(TokenType.QUESTION_PERIOD);
+      return _reader.advance();
+    } else if (enableNullAwareOperators && next == 0x3F) {
+      // '?'
+      next = _reader.advance();
+      if (next == 0x3D) {
+        // '='
+        _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ);
+        return _reader.advance();
+      } else {
+        _appendTokenOfType(TokenType.QUESTION_QUESTION);
+        return next;
+      }
+    } else {
+      _appendTokenOfType(TokenType.QUESTION);
+      return next;
+    }
+  }
+
   int _tokenizeSingleLineComment(int next) {
     while (true) {
       next = _reader.advance();
@@ -2120,7 +2189,7 @@
    * A value used to indicate that the token type is an additive operator.
    */
   static const TokenClass ADDITIVE_OPERATOR =
-      const TokenClass('ADDITIVE_OPERATOR', 12);
+      const TokenClass('ADDITIVE_OPERATOR', 13);
 
   /**
    * A value used to indicate that the token type is an assignment operator.
@@ -2132,19 +2201,19 @@
    * A value used to indicate that the token type is a bitwise-and operator.
    */
   static const TokenClass BITWISE_AND_OPERATOR =
-      const TokenClass('BITWISE_AND_OPERATOR', 10);
+      const TokenClass('BITWISE_AND_OPERATOR', 11);
 
   /**
    * A value used to indicate that the token type is a bitwise-or operator.
    */
   static const TokenClass BITWISE_OR_OPERATOR =
-      const TokenClass('BITWISE_OR_OPERATOR', 8);
+      const TokenClass('BITWISE_OR_OPERATOR', 9);
 
   /**
    * A value used to indicate that the token type is a bitwise-xor operator.
    */
   static const TokenClass BITWISE_XOR_OPERATOR =
-      const TokenClass('BITWISE_XOR_OPERATOR', 9);
+      const TokenClass('BITWISE_XOR_OPERATOR', 10);
 
   /**
    * A value used to indicate that the token type is a cascade operator.
@@ -2162,49 +2231,55 @@
    * A value used to indicate that the token type is an equality operator.
    */
   static const TokenClass EQUALITY_OPERATOR =
-      const TokenClass('EQUALITY_OPERATOR', 6);
+      const TokenClass('EQUALITY_OPERATOR', 7);
+
+  /**
+   * A value used to indicate that the token type is an if-null operator.
+   */
+  static const TokenClass IF_NULL_OPERATOR =
+      const TokenClass('IF_NULL_OPERATOR', 4);
 
   /**
    * A value used to indicate that the token type is a logical-and operator.
    */
   static const TokenClass LOGICAL_AND_OPERATOR =
-      const TokenClass('LOGICAL_AND_OPERATOR', 5);
+      const TokenClass('LOGICAL_AND_OPERATOR', 6);
 
   /**
    * A value used to indicate that the token type is a logical-or operator.
    */
   static const TokenClass LOGICAL_OR_OPERATOR =
-      const TokenClass('LOGICAL_OR_OPERATOR', 4);
+      const TokenClass('LOGICAL_OR_OPERATOR', 5);
 
   /**
    * A value used to indicate that the token type is a multiplicative operator.
    */
   static const TokenClass MULTIPLICATIVE_OPERATOR =
-      const TokenClass('MULTIPLICATIVE_OPERATOR', 13);
+      const TokenClass('MULTIPLICATIVE_OPERATOR', 14);
 
   /**
    * A value used to indicate that the token type is a relational operator.
    */
   static const TokenClass RELATIONAL_OPERATOR =
-      const TokenClass('RELATIONAL_OPERATOR', 7);
+      const TokenClass('RELATIONAL_OPERATOR', 8);
 
   /**
    * A value used to indicate that the token type is a shift operator.
    */
   static const TokenClass SHIFT_OPERATOR =
-      const TokenClass('SHIFT_OPERATOR', 11);
+      const TokenClass('SHIFT_OPERATOR', 12);
 
   /**
    * A value used to indicate that the token type is a unary operator.
    */
   static const TokenClass UNARY_POSTFIX_OPERATOR =
-      const TokenClass('UNARY_POSTFIX_OPERATOR', 15);
+      const TokenClass('UNARY_POSTFIX_OPERATOR', 16);
 
   /**
    * A value used to indicate that the token type is a unary operator.
    */
   static const TokenClass UNARY_PREFIX_OPERATOR =
-      const TokenClass('UNARY_PREFIX_OPERATOR', 14);
+      const TokenClass('UNARY_PREFIX_OPERATOR', 15);
 
   /**
    * The name of the token class.
@@ -2386,6 +2461,15 @@
   static const TokenType QUESTION =
       const TokenType('QUESTION', TokenClass.CONDITIONAL_OPERATOR, "?");
 
+  static const TokenType QUESTION_PERIOD = const TokenType(
+      'QUESTION_PERIOD', TokenClass.UNARY_POSTFIX_OPERATOR, '?.');
+
+  static const TokenType QUESTION_QUESTION =
+      const TokenType('QUESTION_QUESTION', TokenClass.IF_NULL_OPERATOR, '??');
+
+  static const TokenType QUESTION_QUESTION_EQ = const TokenType(
+      'QUESTION_QUESTION_EQ', TokenClass.ASSIGNMENT_OPERATOR, '??=');
+
   static const TokenType SEMICOLON =
       const TokenType('SEMICOLON', TokenClass.NO_CLASS, ";");
 
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index af157bb..b853626 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -6,6 +6,8 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/src/generated/scanner.dart';
+
 import 'ast.dart';
 import 'element.dart';
 import 'java_engine.dart';
@@ -151,10 +153,15 @@
       DartType overrideType = staticType;
       DartType propagatedType = rightHandSide.propagatedType;
       if (propagatedType != null) {
-        _recordPropagatedTypeIfBetter(node, propagatedType);
+        _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
         overrideType = propagatedType;
       }
       _resolver.overrideExpression(node.leftHandSide, overrideType, true);
+    } else if (operator == sc.TokenType.QUESTION_QUESTION_EQ) {
+      // The static type of a compound assignment using ??= is the least upper
+      // bound of the static types of the LHS and RHS.
+      _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide);
+      return null;
     } else {
       ExecutableElement staticMethodElement = node.staticElement;
       DartType staticType = _computeStaticReturnType(staticMethodElement);
@@ -163,7 +170,7 @@
       if (!identical(propagatedMethodElement, staticMethodElement)) {
         DartType propagatedType =
             _computeStaticReturnType(propagatedMethodElement);
-        _recordPropagatedTypeIfBetter(node, propagatedType);
+        _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
       }
     }
     return null;
@@ -187,7 +194,7 @@
     DartType propagatedExpressionType = node.expression.propagatedType;
     DartType propagatedType =
         flattenFutures(_typeProvider, propagatedExpressionType);
-    _recordPropagatedTypeIfBetter(node, propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     return null;
   }
 
@@ -230,6 +237,14 @@
    */
   @override
   Object visitBinaryExpression(BinaryExpression node) {
+    if (node.operator.type == TokenType.QUESTION_QUESTION) {
+      // Evaluation of an if-null expresion e of the form e1 ?? e2 is
+      // equivalent to the evaluation of the expression
+      // ((x) => x == null ? e2 : x)(e1).  The static type of e is the least
+      // upper bound of the static type of e1 and the static type of e2.
+      _analyzeLeastUpperBound(node, node.leftOperand, node.rightOperand);
+      return null;
+    }
     ExecutableElement staticMethodElement = node.staticElement;
     DartType staticType = _computeStaticReturnType(staticMethodElement);
     staticType = _refineBinaryExpressionType(node, staticType);
@@ -238,7 +253,7 @@
     if (!identical(propagatedMethodElement, staticMethodElement)) {
       DartType propagatedType =
           _computeStaticReturnType(propagatedMethodElement);
-      _recordPropagatedTypeIfBetter(node, propagatedType);
+      _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     }
     return null;
   }
@@ -261,7 +276,7 @@
   @override
   Object visitCascadeExpression(CascadeExpression node) {
     _recordStaticType(node, _getStaticType(node.target));
-    _recordPropagatedTypeIfBetter(node, node.target.propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, node.target.propagatedType);
     return null;
   }
 
@@ -276,34 +291,7 @@
    */
   @override
   Object visitConditionalExpression(ConditionalExpression node) {
-    DartType staticThenType = _getStaticType(node.thenExpression);
-    DartType staticElseType = _getStaticType(node.elseExpression);
-    if (staticThenType == null) {
-      // TODO(brianwilkerson) Determine whether this can still happen.
-      staticThenType = _dynamicType;
-    }
-    if (staticElseType == null) {
-      // TODO(brianwilkerson) Determine whether this can still happen.
-      staticElseType = _dynamicType;
-    }
-    DartType staticType = staticThenType.getLeastUpperBound(staticElseType);
-    if (staticType == null) {
-      staticType = _dynamicType;
-    }
-    _recordStaticType(node, staticType);
-    DartType propagatedThenType = node.thenExpression.propagatedType;
-    DartType propagatedElseType = node.elseExpression.propagatedType;
-    if (propagatedThenType != null || propagatedElseType != null) {
-      if (propagatedThenType == null) {
-        propagatedThenType = staticThenType;
-      }
-      if (propagatedElseType == null) {
-        propagatedElseType = staticElseType;
-      }
-      DartType propagatedType =
-          propagatedThenType.getLeastUpperBound(propagatedElseType);
-      _recordPropagatedTypeIfBetter(node, propagatedType);
-    }
+    _analyzeLeastUpperBound(node, node.thenExpression, node.elseExpression);
     return null;
   }
 
@@ -400,7 +388,7 @@
     DartType functionPropagatedType = node.function.propagatedType;
     if (functionPropagatedType is FunctionType) {
       DartType propagatedType = functionPropagatedType.returnType;
-      _recordPropagatedTypeIfBetter(node, propagatedType);
+      _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     }
     return null;
   }
@@ -419,7 +407,7 @@
       MethodElement propagatedMethodElement = node.propagatedElement;
       if (!identical(propagatedMethodElement, staticMethodElement)) {
         DartType propagatedType = _computeArgumentType(propagatedMethodElement);
-        _recordPropagatedTypeIfBetter(node, propagatedType);
+        _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
       }
     } else {
       ExecutableElement staticMethodElement = node.staticElement;
@@ -429,7 +417,7 @@
       if (!identical(propagatedMethodElement, staticMethodElement)) {
         DartType propagatedType =
             _computeStaticReturnType(propagatedMethodElement);
-        _recordPropagatedTypeIfBetter(node, propagatedType);
+        _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
       }
     }
     return null;
@@ -455,11 +443,11 @@
         if ("tag" == constructorName) {
           DartType returnType = _getFirstArgumentAsTypeWithMap(
               library, node.argumentList, _HTML_ELEMENT_TO_CLASS_MAP);
-          _recordPropagatedTypeIfBetter(node, returnType);
+          _resolver.recordPropagatedTypeIfBetter(node, returnType);
         } else {
           DartType returnType = _getElementNameAsType(
               library, constructorName, _HTML_ELEMENT_TO_CLASS_MAP);
-          _recordPropagatedTypeIfBetter(node, returnType);
+          _resolver.recordPropagatedTypeIfBetter(node, returnType);
         }
       }
     }
@@ -598,7 +586,7 @@
       DartType staticType = variable.type;
       _recordStaticType(methodNameNode, staticType);
       DartType propagatedType = _overrideManager.getType(variable);
-      _recordPropagatedTypeIfBetter(methodNameNode, propagatedType);
+      _resolver.recordPropagatedTypeIfBetter(methodNameNode, propagatedType);
     }
     // Record static return type of the static element.
     DartType staticStaticType = _computeStaticReturnType(staticMethodElement);
@@ -606,7 +594,7 @@
     // Record propagated return type of the static element.
     DartType staticPropagatedType =
         _computePropagatedReturnType(staticMethodElement);
-    _recordPropagatedTypeIfBetter(node, staticPropagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, staticPropagatedType);
     // Check for special cases.
     bool needPropagatedType = true;
     String methodName = methodNameNode.name;
@@ -760,11 +748,13 @@
         // Record static return type of the propagated element.
         DartType propagatedStaticType =
             _computeStaticReturnType(propagatedElement);
-        _recordPropagatedTypeIfBetter(node, propagatedStaticType, true);
+        _resolver.recordPropagatedTypeIfBetter(
+            node, propagatedStaticType, true);
         // Record propagated return type of the propagated element.
         DartType propagatedPropagatedType =
             _computePropagatedReturnType(propagatedElement);
-        _recordPropagatedTypeIfBetter(node, propagatedPropagatedType, true);
+        _resolver.recordPropagatedTypeIfBetter(
+            node, propagatedPropagatedType, true);
       }
     }
     return null;
@@ -774,7 +764,7 @@
   Object visitNamedExpression(NamedExpression node) {
     Expression expression = node.expression;
     _recordStaticType(node, _getStaticType(expression));
-    _recordPropagatedTypeIfBetter(node, expression.propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, expression.propagatedType);
     return null;
   }
 
@@ -792,7 +782,7 @@
   Object visitParenthesizedExpression(ParenthesizedExpression node) {
     Expression expression = node.expression;
     _recordStaticType(node, _getStaticType(expression));
-    _recordPropagatedTypeIfBetter(node, expression.propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, expression.propagatedType);
     return null;
   }
 
@@ -835,7 +825,7 @@
       }
     }
     _recordStaticType(node, staticType);
-    _recordPropagatedTypeIfBetter(node, operand.propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, operand.propagatedType);
     return null;
   }
 
@@ -910,8 +900,8 @@
             overriddenType.isMoreSpecificThan(propagatedType))) {
       propagatedType = overriddenType;
     }
-    _recordPropagatedTypeIfBetter(prefixedIdentifier, propagatedType);
-    _recordPropagatedTypeIfBetter(node, propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(prefixedIdentifier, propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     return null;
   }
 
@@ -941,7 +931,7 @@
       if (!identical(propagatedMethodElement, staticMethodElement)) {
         DartType propagatedType =
             _computeStaticReturnType(propagatedMethodElement);
-        _recordPropagatedTypeIfBetter(node, propagatedType);
+        _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
       }
     }
     return null;
@@ -1015,8 +1005,8 @@
     } else {
       // TODO(brianwilkerson) Report this internal error.
     }
-    _recordPropagatedTypeIfBetter(propertyName, propagatedType);
-    _recordPropagatedTypeIfBetter(node, propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(propertyName, propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     return null;
   }
 
@@ -1114,7 +1104,7 @@
         propagatedType = overriddenType;
       }
     }
-    _recordPropagatedTypeIfBetter(node, propagatedType);
+    _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     return null;
   }
 
@@ -1188,7 +1178,7 @@
     if (initializer != null) {
       DartType rightType = initializer.bestType;
       SimpleIdentifier name = node.name;
-      _recordPropagatedTypeIfBetter(name, rightType);
+      _resolver.recordPropagatedTypeIfBetter(name, rightType);
       VariableElement element = name.staticElement as VariableElement;
       if (element != null) {
         _resolver.overrideVariable(element, rightType, true);
@@ -1198,6 +1188,42 @@
   }
 
   /**
+   * Set the static (propagated) type of [node] to be the least upper bound
+   * of the static (propagated) types of subexpressions [expr1] and [expr2].
+   */
+  void _analyzeLeastUpperBound(
+      Expression node, Expression expr1, Expression expr2) {
+    DartType staticType1 = _getStaticType(expr1);
+    DartType staticType2 = _getStaticType(expr2);
+    if (staticType1 == null) {
+      // TODO(brianwilkerson) Determine whether this can still happen.
+      staticType1 = _dynamicType;
+    }
+    if (staticType2 == null) {
+      // TODO(brianwilkerson) Determine whether this can still happen.
+      staticType2 = _dynamicType;
+    }
+    DartType staticType = staticType1.getLeastUpperBound(staticType2);
+    if (staticType == null) {
+      staticType = _dynamicType;
+    }
+    _recordStaticType(node, staticType);
+    DartType propagatedType1 = expr1.propagatedType;
+    DartType propagatedType2 = expr2.propagatedType;
+    if (propagatedType1 != null || propagatedType2 != null) {
+      if (propagatedType1 == null) {
+        propagatedType1 = staticType1;
+      }
+      if (propagatedType2 == null) {
+        propagatedType2 = staticType2;
+      }
+      DartType propagatedType =
+          propagatedType1.getLeastUpperBound(propagatedType2);
+      _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
+    }
+  }
+
+  /**
    * Record that the static type of the given node is the type of the second argument to the method
    * represented by the given element.
    *
@@ -1600,8 +1626,12 @@
     return parent is TypeName ||
         (parent is PrefixedIdentifier &&
             (parent.parent is TypeName || identical(parent.prefix, node))) ||
-        (parent is PropertyAccess && identical(parent.target, node)) ||
-        (parent is MethodInvocation && identical(node, parent.target));
+        (parent is PropertyAccess &&
+            identical(parent.target, node) &&
+            parent.operator.type == TokenType.PERIOD) ||
+        (parent is MethodInvocation &&
+            identical(node, parent.target) &&
+            parent.operator.type == TokenType.PERIOD);
   }
 
   /**
@@ -1617,41 +1647,6 @@
   }
 
   /**
-   * If the given [type] is valid, strongly more specific than the
-   * existing static type of the given [expression], record it as a propagated
-   * type of the given [expression]. Otherwise, reset it to `null`.
-   *
-   * If [hasOldPropagatedType] is `true` then the existing propagated type
-   * should also is checked.
-   */
-  void _recordPropagatedTypeIfBetter(Expression expression, DartType type,
-      [bool hasOldPropagatedType = false]) {
-    // Ensure that propagated type invalid.
-    if (type == null || type.isDynamic || type.isBottom) {
-      if (!hasOldPropagatedType) {
-        expression.propagatedType = null;
-      }
-      return;
-    }
-    // Ensure that propagated type is more specific than the static type.
-    DartType staticType = expression.staticType;
-    if (type == staticType || !type.isMoreSpecificThan(staticType)) {
-      expression.propagatedType = null;
-      return;
-    }
-    // Ensure that the new propagated type is more specific than the old one.
-    if (hasOldPropagatedType) {
-      DartType oldPropagatedType = expression.propagatedType;
-      if (oldPropagatedType != null &&
-          !type.isMoreSpecificThan(oldPropagatedType)) {
-        return;
-      }
-    }
-    // OK
-    expression.propagatedType = type;
-  }
-
-  /**
    * Given a function element and its body, compute and record the propagated return type of the
    * function.
    *
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
index fa46781..0be2aaa 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
@@ -622,8 +622,9 @@
       parameters, body);
 
   static MethodInvocation methodInvocation(Expression target, String methodName,
-      [List<Expression> arguments]) => new MethodInvocation(target,
-      target == null ? null : TokenFactory.tokenFromType(TokenType.PERIOD),
+      [List<Expression> arguments,
+      TokenType operator = TokenType.PERIOD]) => new MethodInvocation(target,
+      target == null ? null : TokenFactory.tokenFromType(operator),
       identifier3(methodName), argumentList(arguments));
 
   static MethodInvocation methodInvocation2(String methodName,
@@ -696,9 +697,9 @@
       Expression target, SimpleIdentifier propertyName) => new PropertyAccess(
       target, TokenFactory.tokenFromType(TokenType.PERIOD), propertyName);
 
-  static PropertyAccess propertyAccess2(
-      Expression target, String propertyName) => new PropertyAccess(target,
-      TokenFactory.tokenFromType(TokenType.PERIOD), identifier3(propertyName));
+  static PropertyAccess propertyAccess2(Expression target, String propertyName,
+      [TokenType operator = TokenType.PERIOD]) => new PropertyAccess(
+      target, TokenFactory.tokenFromType(operator), identifier3(propertyName));
 
   static RedirectingConstructorInvocation redirectingConstructorInvocation(
           [List<Expression> arguments]) =>
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 9fab12f..ebb0713 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -70,10 +70,6 @@
           [List<String> parameterNames]) =>
       classElement(typeName, objectType, parameterNames);
 
-  static ClassElementImpl classTypeAlias2(String typeName,
-          [List<String> parameterNames]) =>
-      classTypeAlias(typeName, objectType, parameterNames);
-
   static classTypeAlias(String typeName, InterfaceType superclassType,
       [List<String> parameterNames]) {
     ClassElementImpl element =
@@ -82,6 +78,10 @@
     return element;
   }
 
+  static ClassElementImpl classTypeAlias2(String typeName,
+          [List<String> parameterNames]) =>
+      classTypeAlias(typeName, objectType, parameterNames);
+
   static CompilationUnitElementImpl compilationUnit(String fileName) {
     Source source = new NonExistingSource(fileName, UriKind.FILE_URI);
     CompilationUnitElementImpl unit = new CompilationUnitElementImpl(fileName);
@@ -89,6 +89,9 @@
     return unit;
   }
 
+  static ConstLocalVariableElementImpl constLocalVariableElement(String name) =>
+      new ConstLocalVariableElementImpl(name, 0);
+
   static ConstructorElementImpl constructorElement(
       ClassElement definingClass, String name, bool isConst,
       [List<DartType> argumentTypes]) {
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 6824459..fe0c24b 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -159,6 +159,7 @@
         ElementFactory.namedParameter2("defaultValue", _boolType)
       ];
       fromEnvironment.factory = true;
+      fromEnvironment.isCycleFree = true;
       boolElement.constructors = <ConstructorElement>[fromEnvironment];
     }
     return _boolType;
@@ -330,6 +331,16 @@
   }
 
   @override
+  List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[
+    nullType,
+    numType,
+    intType,
+    doubleType,
+    boolType,
+    stringType
+  ];
+
+  @override
   DartObjectImpl get nullObject {
     if (_nullObject == null) {
       _nullObject = new DartObjectImpl(nullType, NullState.NULL_STATE);
@@ -421,6 +432,7 @@
         ElementFactory.namedParameter2("defaultValue", _stringType)
       ];
       fromEnvironment.factory = true;
+      fromEnvironment.isCycleFree = true;
       stringElement.constructors = <ConstructorElement>[fromEnvironment];
     }
     return _stringType;
@@ -433,6 +445,7 @@
       ConstructorElementImpl constructor = ElementFactory.constructorElement(
           symbolClass, null, true, [stringType]);
       constructor.factory = true;
+      constructor.isCycleFree = true;
       symbolClass.constructors = <ConstructorElement>[constructor];
       _symbolType = symbolClass.type;
     }
@@ -532,6 +545,7 @@
       ElementFactory.namedParameter2("defaultValue", _intType)
     ];
     fromEnvironment.factory = true;
+    fromEnvironment.isCycleFree = true;
     intElement.constructors = <ConstructorElement>[fromEnvironment];
     List<FieldElement> fields = <FieldElement>[
       ElementFactory.fieldElement("NAN", true, false, true, _doubleType),
diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
index d858b1a..3e63016 100644
--- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
@@ -67,7 +67,7 @@
     registerExtension(taskId, BuildDirectiveElementsTask.DESCRIPTOR);
     registerExtension(taskId, BuildEnumMemberElementsTask.DESCRIPTOR);
     registerExtension(taskId, BuildExportNamespaceTask.DESCRIPTOR);
-    registerExtension(taskId, BuildExportSourceClosureTask.DESCRIPTOR);
+    registerExtension(taskId, BuildSourceClosuresTask.DESCRIPTOR);
     registerExtension(taskId, BuildFunctionTypeAliasesTask.DESCRIPTOR);
     registerExtension(taskId, BuildLibraryElementTask.DESCRIPTOR);
     registerExtension(taskId, BuildPublicNamespaceTask.DESCRIPTOR);
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 59b9efe..93e2f08 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/generated/element.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
 import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/error_verifier.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -67,6 +68,15 @@
     new ListResultDescriptor<ClassElement>('CLASS_ELEMENTS', null);
 
 /**
+ * The element model associated with a single compilation unit.
+ *
+ * The result is only available for targets representing a Dart compilation unit.
+ */
+final ResultDescriptor<CompilationUnitElement> COMPILATION_UNIT_ELEMENT =
+    new ResultDescriptor<CompilationUnitElement>(
+        'COMPILATION_UNIT_ELEMENT', null);
+
+/**
  * The [ConstructorElement]s of a [ClassElement].
  */
 final ResultDescriptor<List<ConstructorElement>> CONSTRUCTORS =
@@ -85,6 +95,7 @@
 
 /**
  * The sources representing the export closure of a library.
+ * The [Source]s include only library sources, not their units.
  *
  * The result is only available for targets representing a Dart library.
  */
@@ -92,6 +103,26 @@
     new ListResultDescriptor<Source>('EXPORT_SOURCE_CLOSURE', null);
 
 /**
+ * The errors produced while generating hints a compilation unit.
+ *
+ * The list will be empty if there were no errors, but will not be `null`.
+ *
+ * The result is only available for targets representing a Dart compilation unit.
+ */
+final ResultDescriptor<List<AnalysisError>> HINTS =
+    new ResultDescriptor<List<AnalysisError>>(
+        'HINT_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS);
+
+/**
+ * The sources representing the import closure of a library.
+ * The [Source]s include only library sources, not their units.
+ *
+ * The result is only available for targets representing a Dart library.
+ */
+final ListResultDescriptor<Source> IMPORT_SOURCE_CLOSURE =
+    new ListResultDescriptor<Source>('IMPORT_SOURCE_CLOSURE', null);
+
+/**
  * The partial [LibraryElement] associated with a library.
  *
  * The [LibraryElement] and its [CompilationUnitElement]s are attached to each
@@ -148,14 +179,27 @@
     new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT5', null);
 
 /**
- * The partial [LibraryElement] associated with a library.
+ * The errors produced while parsing a compilation unit.
  *
- * Implicit constructors are built for every [ClassElement] requiring them.
+ * The list will be empty if there were no errors, but will not be `null`.
  *
- * The result is only available for targets representing a Dart library.
+ * The result is only available for targets representing a Dart compilation unit.
  */
-final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT6 =
-    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT6', null);
+final ResultDescriptor<List<AnalysisError>> PARSE_ERRORS =
+    new ResultDescriptor<List<AnalysisError>>(
+        'PARSE_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS);
+
+/**
+ * The errors produced while resolving references.
+ *
+ * The list will be empty if there were no errors, but will not be `null`.
+ *
+ * The result is only available for targets representing a unit.
+ */
+final ResultDescriptor<List<AnalysisError>> RESOLVE_REFERENCES_ERRORS =
+    new ResultDescriptor<List<AnalysisError>>(
+        'RESOLVE_REFERENCES_ERRORS', AnalysisError.NO_ERRORS,
+        contributesTo: DART_ERRORS);
 
 /**
  * The errors produced while resolving type names.
@@ -210,12 +254,56 @@
     new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT4', null);
 
 /**
+ * The partially resolved [CompilationUnit] associated with a unit.
+ *
+ * [RESOLVED_UNIT4] plus resolved local variables and formal parameters.
+ *
+ * The result is only available for targets representing a unit.
+ */
+final ResultDescriptor<CompilationUnit> RESOLVED_UNIT5 =
+    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT5', null);
+
+/**
+ * The errors produced while scanning a compilation unit.
+ *
+ * The list will be empty if there were no errors, but will not be `null`.
+ *
+ * The result is only available for targets representing a Dart compilation unit.
+ */
+final ResultDescriptor<List<AnalysisError>> SCAN_ERRORS =
+    new ResultDescriptor<List<AnalysisError>>(
+        'SCAN_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS);
+
+/**
  * The [TypeProvider] of the context.
  */
 final ResultDescriptor<TypeProvider> TYPE_PROVIDER =
     new ResultDescriptor<TypeProvider>('TYPE_PROVIDER', null);
 
 /**
+ * The [UsedImportedElements] of a [LibraryUnitTarget].
+ */
+final ResultDescriptor<UsedImportedElements> USED_IMPORTED_ELEMENTS =
+    new ResultDescriptor<UsedImportedElements>('USED_IMPORTED_ELEMENTS', null);
+
+/**
+ * The [UsedLocalElements] of a [LibraryUnitTarget].
+ */
+final ResultDescriptor<UsedLocalElements> USED_LOCAL_ELEMENTS =
+    new ResultDescriptor<UsedLocalElements>('USED_LOCAL_ELEMENTS', null);
+
+/**
+ * The errors produced while verifying a compilation unit.
+ *
+ * The list will be empty if there were no errors, but will not be `null`.
+ *
+ * The result is only available for targets representing a Dart compilation unit.
+ */
+final ResultDescriptor<List<AnalysisError>> VERIFY_ERRORS =
+    new ResultDescriptor<List<AnalysisError>>(
+        'VERIFY_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS);
+
+/**
  * A task that builds implicit constructors for a [ClassElement], or keeps
  * the existing explicit constructors if the class has them.
  */
@@ -889,77 +977,6 @@
 }
 
 /**
- * A task that builds [EXPORT_SOURCE_CLOSURE] of a library.
- */
-class BuildExportSourceClosureTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the input for [LIBRARY_ELEMENT3] of a library.
-   */
-  static const String LIBRARY2_ELEMENT_INPUT = 'LIBRARY2_ELEMENT_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'BuildExportSourceClosureTask', createTask, buildInputs,
-      <ResultDescriptor>[EXPORT_SOURCE_CLOSURE]);
-
-  BuildExportSourceClosureTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibraryElement library = getRequiredInput(LIBRARY2_ELEMENT_INPUT);
-    //
-    // Compute export closure.
-    //
-    Set<LibraryElement> libraries = new Set<LibraryElement>();
-    _buildExportClosure(libraries, library);
-    List<Source> sources = libraries.map((lib) => lib.source).toList();
-    //
-    // Record outputs.
-    //
-    outputs[EXPORT_SOURCE_CLOSURE] = sources;
-  }
-
-  /**
-   * 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 library [libSource].
-   */
-  static Map<String, TaskInput> buildInputs(Source libSource) {
-    return <String, TaskInput>{
-      LIBRARY2_ELEMENT_INPUT: LIBRARY_ELEMENT2.of(libSource)
-    };
-  }
-
-  /**
-   * Create a [BuildExportSourceClosureTask] based on the given [target] in
-   * the given [context].
-   */
-  static BuildExportSourceClosureTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new BuildExportSourceClosureTask(context, target);
-  }
-
-  /**
-   * Create a set representing the export closure of the given [library].
-   */
-  static void _buildExportClosure(
-      Set<LibraryElement> libraries, LibraryElement library) {
-    if (library != null && libraries.add(library)) {
-      for (ExportElement exportElement in library.exports) {
-        _buildExportClosure(libraries, exportElement.exportedLibrary);
-      }
-    }
-  }
-}
-
-/**
  * A task that builds [RESOLVED_UNIT3] for a unit.
  */
 class BuildFunctionTypeAliasesTask extends SourceBasedAnalysisTask {
@@ -1045,8 +1062,8 @@
 }
 
 /**
- * An artifitial task that does nothing except to force building constructors
- * for for the defining and part units of a library.
+ * This task finishes building [LIBRARY_ELEMENT] by forcing building
+ * constructors for classes in the defining and part units of a library.
  */
 class BuildLibraryConstructorsTask extends SourceBasedAnalysisTask {
   /**
@@ -1059,7 +1076,7 @@
    */
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
       'BuildLibraryConstructorsTask', createTask, buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT6]);
+      <ResultDescriptor>[LIBRARY_ELEMENT]);
 
   BuildLibraryConstructorsTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -1071,7 +1088,7 @@
   @override
   void internalPerform() {
     LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    outputs[LIBRARY_ELEMENT6] = library;
+    outputs[LIBRARY_ELEMENT] = library;
   }
 
   /**
@@ -1120,8 +1137,7 @@
     BUILD_LIBRARY_ERRORS,
     CLASS_ELEMENTS,
     LIBRARY_ELEMENT1,
-    IS_LAUNCHABLE,
-    HAS_HTML_IMPORT
+    IS_LAUNCHABLE
   ]);
 
   /**
@@ -1161,13 +1177,11 @@
       Source partSource = partUnit.element.source;
       partUnitMap[partSource] = partUnit;
     }
-    Source htmlSource = context.sourceFactory.forUri(DartSdk.DART_HTML);
     //
     // Update "part" directives.
     //
     LibraryIdentifier libraryNameNode = null;
     String partsLibraryName = _UNKNOWN_LIBRARY_NAME;
-    bool hasHtmlImport = false;
     bool hasPartDirective = false;
     FunctionElement entryPoint =
         _findEntryPoint(definingCompilationUnitElement);
@@ -1175,9 +1189,7 @@
     List<CompilationUnitElementImpl> sourcedCompilationUnits =
         <CompilationUnitElementImpl>[];
     for (Directive directive in definingCompilationUnit.directives) {
-      if (directive is ImportDirective) {
-        hasHtmlImport = hasHtmlImport || directive.source == htmlSource;
-      } else if (directive is LibraryDirective) {
+      if (directive is LibraryDirective) {
         if (libraryNameNode == null) {
           libraryNameNode = directive.name;
           directivesToResolve.add(directive);
@@ -1265,7 +1277,6 @@
     outputs[CLASS_ELEMENTS] = classElements;
     outputs[LIBRARY_ELEMENT1] = libraryElement;
     outputs[IS_LAUNCHABLE] = entryPoint != null;
-    outputs[HAS_HTML_IMPORT] = hasHtmlImport;
   }
 
   /**
@@ -1421,6 +1432,74 @@
 }
 
 /**
+ * A task that builds [IMPORT_SOURCE_CLOSURE] and [EXPORT_SOURCE_CLOSURE] of
+ * a library.
+ */
+class BuildSourceClosuresTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the import closure.
+   */
+  static const String IMPORT_CLOSURE_INPUT = 'IMPORT_CLOSURE_INPUT';
+
+  /**
+   * The name of the export closure.
+   */
+  static const String EXPORT_CLOSURE_INPUT = 'EXPORT_CLOSURE_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'BuildExportSourceClosureTask', createTask, buildInputs,
+      <ResultDescriptor>[
+    IMPORT_SOURCE_CLOSURE,
+    EXPORT_SOURCE_CLOSURE,
+    IS_CLIENT
+  ]);
+
+  BuildSourceClosuresTask(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    List<Source> importClosure = getRequiredInput(IMPORT_CLOSURE_INPUT);
+    List<Source> exportClosure = getRequiredInput(EXPORT_CLOSURE_INPUT);
+    Source htmlSource = context.sourceFactory.forUri(DartSdk.DART_HTML);
+    //
+    // Record outputs.
+    //
+    outputs[IMPORT_SOURCE_CLOSURE] = importClosure;
+    outputs[EXPORT_SOURCE_CLOSURE] = exportClosure;
+    outputs[IS_CLIENT] = importClosure.contains(htmlSource);
+  }
+
+  /**
+   * 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 library [libSource].
+   */
+  static Map<String, TaskInput> buildInputs(Source libSource) {
+    return <String, TaskInput>{
+      IMPORT_CLOSURE_INPUT: new _ImportSourceClosureTaskInput(libSource),
+      EXPORT_CLOSURE_INPUT: new _ExportSourceClosureTaskInput(libSource)
+    };
+  }
+
+  /**
+   * Create a [BuildSourceClosuresTask] based on the given [target] in
+   * the given [context].
+   */
+  static BuildSourceClosuresTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new BuildSourceClosuresTask(context, target);
+  }
+}
+
+/**
  * A task that builds [TYPE_PROVIDER] for a context.
  */
 class BuildTypeProviderTask extends SourceBasedAnalysisTask {
@@ -1586,6 +1665,238 @@
 }
 
 /**
+ * A task that builds [USED_IMPORTED_ELEMENTS] for a unit.
+ */
+class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [RESOLVED_UNIT] input.
+   */
+  static const String UNIT_INPUT = 'UNIT_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'GatherUsedImportedElementsTask', createTask, buildInputs,
+      <ResultDescriptor>[USED_IMPORTED_ELEMENTS]);
+
+  GatherUsedImportedElementsTask(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+    CompilationUnitElement unitElement = unit.element;
+    LibraryElement libraryElement = unitElement.library;
+    //
+    // Prepare used imported elements.
+    //
+    GatherUsedImportedElementsVisitor visitor =
+        new GatherUsedImportedElementsVisitor(libraryElement);
+    unit.accept(visitor);
+    //
+    // Record outputs.
+    //
+    outputs[USED_IMPORTED_ELEMENTS] = visitor.usedElements;
+  }
+
+  /**
+   * 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(LibraryUnitTarget target) {
+    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT.of(target)};
+  }
+
+  /**
+   * Create a [GatherUsedImportedElementsTask] based on the given [target] in
+   * the given [context].
+   */
+  static GatherUsedImportedElementsTask createTask(
+      AnalysisContext context, LibraryUnitTarget target) {
+    return new GatherUsedImportedElementsTask(context, target);
+  }
+}
+
+/**
+ * A task that builds [USED_LOCAL_ELEMENTS] for a unit.
+ */
+class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [RESOLVED_UNIT] input.
+   */
+  static const String UNIT_INPUT = 'UNIT_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'GatherUsedLocalElementsTask', createTask, buildInputs,
+      <ResultDescriptor>[USED_LOCAL_ELEMENTS]);
+
+  GatherUsedLocalElementsTask(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+    CompilationUnitElement unitElement = unit.element;
+    LibraryElement libraryElement = unitElement.library;
+    //
+    // Prepare used local elements.
+    //
+    GatherUsedLocalElementsVisitor visitor =
+        new GatherUsedLocalElementsVisitor(libraryElement);
+    unit.accept(visitor);
+    //
+    // Record outputs.
+    //
+    outputs[USED_LOCAL_ELEMENTS] = visitor.usedElements;
+  }
+
+  /**
+   * 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(LibraryUnitTarget target) {
+    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT.of(target)};
+  }
+
+  /**
+   * Create a [GatherUsedLocalElementsTask] based on the given [target] in
+   * the given [context].
+   */
+  static GatherUsedLocalElementsTask createTask(
+      AnalysisContext context, LibraryUnitTarget target) {
+    return new GatherUsedLocalElementsTask(context, target);
+  }
+}
+
+/**
+ * A task that generates [HINTS] for a unit.
+ */
+class GenerateHintsTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [RESOLVED_UNIT] input.
+   */
+  static const String UNIT_INPUT = 'UNIT_INPUT';
+
+  /**
+   * The name of a list of [USED_LOCAL_ELEMENTS] for each library unit input.
+   */
+  static const String USED_LOCAL_ELEMENTS_INPUT = 'USED_LOCAL_ELEMENTS';
+
+  /**
+   * The name of a list of [USED_IMPORTED_ELEMENTS] for each library unit input.
+   */
+  static const String USED_IMPORTED_ELEMENTS_INPUT = 'USED_IMPORTED_ELEMENTS';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'GenerateHintsTask', createTask, buildInputs, <ResultDescriptor>[HINTS]);
+
+  GenerateHintsTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    RecordingErrorListener errorListener = new RecordingErrorListener();
+    Source source = getRequiredSource();
+    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
+    //
+    // Prepare inputs.
+    //
+    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+    List<UsedImportedElements> usedImportedElementsList =
+        getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT);
+    List<UsedLocalElements> usedLocalElementsList =
+        getRequiredInput(USED_LOCAL_ELEMENTS_INPUT);
+    CompilationUnitElement unitElement = unit.element;
+    LibraryElement libraryElement = unitElement.library;
+    //
+    // Generate errors.
+    //
+    unit.accept(new DeadCodeVerifier(errorReporter));
+    // Verify imports.
+    {
+      ImportsVerifier verifier = new ImportsVerifier();
+      verifier.addImports(unit);
+      usedImportedElementsList.forEach(verifier.removeUsedElements);
+      verifier.generateDuplicateImportHints(errorReporter);
+      verifier.generateUnusedImportHints(errorReporter);
+    }
+    // Unused local elements.
+    {
+      UsedLocalElements usedElements =
+          new UsedLocalElements.merge(usedLocalElementsList);
+      UnusedLocalElementsVerifier visitor =
+          new UnusedLocalElementsVerifier(errorListener, usedElements);
+      unitElement.accept(visitor);
+    }
+    // Dart2js analysis.
+    if (context.analysisOptions.dart2jsHint) {
+      unit.accept(new Dart2JSVerifier(errorReporter));
+    }
+    // Dart best practices.
+    InheritanceManager inheritanceManager =
+        new InheritanceManager(libraryElement);
+    TypeProvider typeProvider = context.typeProvider;
+    unit.accept(new BestPracticesVerifier(errorReporter, typeProvider));
+    unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
+    // Find to-do comments.
+    new ToDoFinder(errorReporter).findIn(unit);
+    //
+    // Record outputs.
+    //
+    outputs[HINTS] = errorListener.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(LibraryUnitTarget target) {
+    Source libSource = target.library;
+    return <String, TaskInput>{
+      UNIT_INPUT: RESOLVED_UNIT.of(target),
+      USED_LOCAL_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) {
+        LibraryUnitTarget target = new LibraryUnitTarget(libSource, unit);
+        return USED_LOCAL_ELEMENTS.of(target);
+      }),
+      USED_IMPORTED_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) {
+        LibraryUnitTarget target = new LibraryUnitTarget(libSource, unit);
+        return USED_IMPORTED_ELEMENTS.of(target);
+      })
+    };
+  }
+
+  /**
+   * Create a [GenerateHintsTask] based on the given [target] in
+   * the given [context].
+   */
+  static GenerateHintsTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new GenerateHintsTask(context, target);
+  }
+}
+
+/**
  * A pair of a library [Source] and a unit [Source] in this library.
  */
 class LibraryUnitTarget implements AnalysisTarget {
@@ -1856,8 +2167,11 @@
   static Map<String, TaskInput> buildInputs(Source libSource) {
     return <String, TaskInput>{
       LIBRARY_INPUT: LIBRARY_ELEMENT4.of(libSource),
-      'resolvedUnits': UNITS.of(libSource).toMap((Source source) =>
-          RESOLVED_UNIT4.of(new LibraryUnitTarget(libSource, source)))
+      'resolvedUnits': IMPORT_SOURCE_CLOSURE
+          .of(libSource)
+          .toMapOf(UNITS)
+          .toFlattenList((Source library, Source unit) =>
+              RESOLVED_UNIT4.of(new LibraryUnitTarget(library, unit)))
     };
   }
 
@@ -1872,6 +2186,80 @@
 }
 
 /**
+ * A task that builds [RESOLVED_UNIT] for a unit.
+ */
+class ResolveReferencesTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [LIBRARY_ELEMENT] input.
+   */
+  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
+
+  /**
+   * The name of the [RESOLVED_UNIT5] input.
+   */
+  static const String UNIT_INPUT = 'UNIT_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'ResolveReferencesTask', createTask, buildInputs,
+      <ResultDescriptor>[RESOLVED_UNIT]);
+
+  ResolveReferencesTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    RecordingErrorListener errorListener = new RecordingErrorListener();
+    //
+    // Prepare inputs.
+    //
+    LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
+    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+    CompilationUnitElement unitElement = unit.element;
+    TypeProvider typeProvider = unitElement.context.typeProvider;
+    //
+    // Resolve references.
+    //
+    InheritanceManager inheritanceManager =
+        new InheritanceManager(libraryElement);
+    AstVisitor visitor = new ResolverVisitor.con2(libraryElement,
+        unitElement.source, typeProvider, inheritanceManager, errorListener);
+    unit.accept(visitor);
+    //
+    // Record outputs.
+    //
+    outputs[RESOLVE_REFERENCES_ERRORS] = errorListener.errors;
+    outputs[RESOLVED_UNIT] = unit;
+  }
+
+  /**
+   * Return a map from the names of the inputs of this kind of task to the task
+   * input descriptors describing those inputs for a task with the
+   * given [target].
+   */
+  static Map<String, TaskInput> buildInputs(LibraryUnitTarget target) {
+    return <String, TaskInput>{
+      LIBRARY_INPUT: LIBRARY_ELEMENT.of(target.library),
+      UNIT_INPUT: RESOLVED_UNIT5.of(target)
+    };
+  }
+
+  /**
+   * Create a [ResolveReferencesTask] based on the given [target] in
+   * the given [context].
+   */
+  static ResolveReferencesTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new ResolveReferencesTask(context, target);
+  }
+}
+
+/**
  * A task that builds [RESOLVED_UNIT4] for a unit.
  */
 class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
@@ -1938,6 +2326,79 @@
 }
 
 /**
+ * A task that builds [RESOLVED_UNIT5] for a unit.
+ */
+class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [LIBRARY_ELEMENT] input.
+   */
+  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
+
+  /**
+   * The name of the [RESOLVED_UNIT4] input.
+   */
+  static const String UNIT_INPUT = 'UNIT_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'ResolveVariableReferencesTask', createTask, buildInputs,
+      <ResultDescriptor>[RESOLVED_UNIT5]);
+
+  ResolveVariableReferencesTask(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    RecordingErrorListener errorListener = new RecordingErrorListener();
+    //
+    // Prepare inputs.
+    //
+    LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
+    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+    CompilationUnitElement unitElement = unit.element;
+    //
+    // Resolve local variables.
+    //
+    TypeProvider typeProvider = unitElement.context.typeProvider;
+    Scope nameScope = new LibraryScope(libraryElement, errorListener);
+    AstVisitor visitor = new VariableResolverVisitor.con2(libraryElement,
+        unitElement.source, typeProvider, nameScope, errorListener);
+    unit.accept(visitor);
+    //
+    // Record outputs.
+    //
+    outputs[RESOLVED_UNIT5] = 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(LibraryUnitTarget target) {
+    return <String, TaskInput>{
+      LIBRARY_INPUT: LIBRARY_ELEMENT.of(target.library),
+      UNIT_INPUT: RESOLVED_UNIT4.of(target)
+    };
+  }
+
+  /**
+   * Create a [ResolveVariableReferencesTask] based on the given [target] in
+   * the given [context].
+   */
+  static ResolveVariableReferencesTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new ResolveVariableReferencesTask(context, target);
+  }
+}
+
+/**
  * A task that scans the content of a file, producing a set of Dart tokens.
  */
 class ScanDartTask extends SourceBasedAnalysisTask {
@@ -1975,6 +2436,8 @@
     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] = errorListener.getErrorsForSource(source);
@@ -1997,3 +2460,155 @@
     return new ScanDartTask(context, target);
   }
 }
+
+/**
+ * A task that builds [VERIFY_ERRORS] for a unit.
+ */
+class VerifyUnitTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [RESOLVED_UNIT] input.
+   */
+  static const String UNIT_INPUT = 'UNIT_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('VerifyUnitTask',
+      createTask, buildInputs, <ResultDescriptor>[VERIFY_ERRORS]);
+
+  /**
+   * The [ErrorReporter] to report errors to.
+   */
+  ErrorReporter errorReporter;
+
+  VerifyUnitTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    RecordingErrorListener errorListener = new RecordingErrorListener();
+    Source source = getRequiredSource();
+    errorReporter = new ErrorReporter(errorListener, source);
+    TypeProvider typeProvider = context.typeProvider;
+    //
+    // Prepare inputs.
+    //
+    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+    CompilationUnitElement unitElement = unit.element;
+    LibraryElement libraryElement = unitElement.library;
+    //
+    // Use the ErrorVerifier to compute errors.
+    //
+    ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter,
+        libraryElement, typeProvider, new InheritanceManager(libraryElement));
+    unit.accept(errorVerifier);
+    //
+    // Record outputs.
+    //
+    outputs[VERIFY_ERRORS] = errorListener.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(LibraryUnitTarget target) {
+    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT.of(target)};
+  }
+
+  /**
+   * Create a [VerifyUnitTask] based on the given [target] in
+   * the given [context].
+   */
+  static VerifyUnitTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new VerifyUnitTask(context, target);
+  }
+}
+
+/**
+ * A [TaskInput] whose value is a list of library sources exported directly
+ * or indirectly by the target [Source].
+ */
+class _ExportSourceClosureTaskInput implements TaskInput<List<Source>> {
+  final Source target;
+
+  _ExportSourceClosureTaskInput(this.target);
+
+  @override
+  TaskInputBuilder<List<Source>> createBuilder() =>
+      new _SourceClosureTaskInputBuilder(target, _SourceClosureKind.EXPORT);
+}
+
+/**
+ * The kind of the source closure to build.
+ */
+enum _SourceClosureKind { IMPORT, EXPORT }
+
+/**
+ * A [TaskInput] whose value is a list of library sources imported directly
+ * or indirectly by the target [Source].
+ */
+class _ImportSourceClosureTaskInput implements TaskInput<List<Source>> {
+  final Source target;
+
+  _ImportSourceClosureTaskInput(this.target);
+
+  @override
+  TaskInputBuilder<List<Source>> createBuilder() =>
+      new _SourceClosureTaskInputBuilder(target, _SourceClosureKind.IMPORT);
+}
+
+/**
+ * A [TaskInputBuilder] to build values for [_ImportSourceClosureTaskInput].
+ */
+class _SourceClosureTaskInputBuilder implements TaskInputBuilder<List<Source>> {
+  final _SourceClosureKind kind;
+  final Set<LibraryElement> _libraries = new HashSet<LibraryElement>();
+  final Set<Source> _newSources = new HashSet<Source>();
+
+  Source currentTarget;
+
+  _SourceClosureTaskInputBuilder(Source librarySource, this.kind) {
+    _newSources.add(librarySource);
+  }
+
+  @override
+  ResultDescriptor get currentResult => LIBRARY_ELEMENT2;
+
+  @override
+  void set currentValue(LibraryElement library) {
+    if (_libraries.add(library)) {
+      if (kind == _SourceClosureKind.IMPORT) {
+        for (ImportElement importElement in library.imports) {
+          Source importedSource = importElement.importedLibrary.source;
+          _newSources.add(importedSource);
+        }
+      } else {
+        for (ExportElement exportElement in library.exports) {
+          Source importedSource = exportElement.exportedLibrary.source;
+          _newSources.add(importedSource);
+        }
+      }
+    }
+  }
+
+  @override
+  List<Source> get inputValue {
+    return _libraries.map((LibraryElement library) => library.source).toList();
+  }
+
+  @override
+  bool moveNext() {
+    if (_newSources.isEmpty) {
+      return false;
+    }
+    currentTarget = _newSources.first;
+    _newSources.remove(currentTarget);
+    return true;
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index 88df107..f077b3a 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -413,8 +413,46 @@
     while (childItem != null) {
       pendingItems.add(currentItem);
       currentItem = childItem;
+      if (_hasInfiniteTaskLoop()) {
+        currentItem = pendingItems.removeLast();
+        try {
+          throw new InfiniteTaskLoopException(childItem);
+        } on InfiniteTaskLoopException catch (exception, stackTrace) {
+          currentItem.exception = new CaughtException(exception, stackTrace);
+        }
+        return true;
+      }
       childItem = currentItem.gatherInputs(taskManager);
     }
     return true;
   }
+
+  /**
+   * Check to see whether the current work item is attempting to perform the
+   * same task on the same target as any of the pending work items. If it is,
+   * then throw an [InfiniteTaskLoopException].
+   */
+  bool _hasInfiniteTaskLoop() {
+    TaskDescriptor descriptor = currentItem.descriptor;
+    AnalysisTarget target = currentItem.target;
+    for (WorkItem item in pendingItems) {
+      if (item.descriptor == descriptor && item.target == target) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
+
+/**
+ * An exception indicating that an attempt was made to perform a task on a
+ * target while gathering the inputs to perform the same task for the same
+ * target.
+ */
+class InfiniteTaskLoopException extends AnalysisException {
+  /**
+   * Initialize a newly created exception to represent an attempt to perform
+   * the task for the target represented by the given [item].
+   */
+  InfiniteTaskLoopException(WorkItem item) : super('Infinite loop while performing task ${item.descriptor.name} for ${item.target}');
 }
diff --git a/pkg/analyzer/lib/src/task/general.dart b/pkg/analyzer/lib/src/task/general.dart
index 8e52537..8f88327 100644
--- a/pkg/analyzer/lib/src/task/general.dart
+++ b/pkg/analyzer/lib/src/task/general.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/model.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
 
 /**
  * A task that gets the contents of the source associated with an analysis
@@ -33,10 +34,14 @@
   @override
   internalPerform() {
     Source source = getRequiredSource();
-
-    TimestampedData<String> data = context.getContents(source);
-    outputs[CONTENT] = data.data;
-    outputs[MODIFICATION_TIME] = data.modificationTime;
+    try {
+      TimestampedData<String> data = context.getContents(source);
+      outputs[CONTENT] = data.data;
+      outputs[MODIFICATION_TIME] = data.modificationTime;
+    } catch (exception, stackTrace) {
+      throw new AnalysisException('Could not get contents of $source',
+          new CaughtException(exception, stackTrace));
+    }
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/task/inputs.dart b/pkg/analyzer/lib/src/task/inputs.dart
index a7b67df..27b48c5 100644
--- a/pkg/analyzer/lib/src/task/inputs.dart
+++ b/pkg/analyzer/lib/src/task/inputs.dart
@@ -41,12 +41,12 @@
     return (this as ListTaskInputImpl<AnalysisTarget>).toList(valueResult.of);
   }
 
-  TaskInput<Map<E, dynamic /*V*/ >> toMap(
+  MapTaskInput<E, dynamic /*V*/ > toMap(
       UnaryFunction<E, dynamic /*<V>*/ > mapper) {
     return new ListToMapTaskInput<E, dynamic /*V*/ >(this, mapper);
   }
 
-  TaskInput<Map<AnalysisTarget, dynamic /*V*/ >> toMapOf(
+  MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf(
       ResultDescriptor /*<V>*/ valueResult) {
     return (this as ListTaskInputImpl<AnalysisTarget>).toMap(valueResult.of);
   }
@@ -113,7 +113,8 @@
  * input to the task.
  */
 class ListToMapTaskInput<B, E>
-    extends _ListToCollectionTaskInput<B, E, Map<B, E>> {
+    extends _ListToCollectionTaskInput<B, E, Map<B, E>>
+    with MapTaskInputMixin<B, E> {
   /**
    * Initialize a result accessor to use the given [baseAccessor] to access a
    * list of values that can be passed to the given [generateTaskInputs] to
@@ -157,6 +158,125 @@
 }
 
 /**
+ * A mixin-ready implementation of [MapTaskInput].
+ */
+abstract class MapTaskInputMixin<K, V> implements MapTaskInput<K, V> {
+  TaskInput<List /*<E>*/ > toFlattenList(
+      BinaryFunction<K, dynamic /*element of V*/, dynamic /*<E>*/ > mapper) {
+    return new MapToFlattenListTaskInput<K, dynamic /*element of V*/, dynamic /*E*/ >(
+        this as MapTaskInput<K, List /*<element of V>*/ >, mapper);
+  }
+}
+
+/**
+ * A [TaskInput] that is computed by the following steps.
+ *
+ * First the [base] task input is used to compute a [Map]-valued result.
+ * The values of the [Map] must be [List]s.
+ *
+ * The given [mapper] is used to transform each key / value pair of the [Map]
+ * into task inputs.
+ *
+ * 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>> {
+  final MapTaskInput<K, List<V>> base;
+  final BinaryFunction<K, V, E> mapper;
+
+  MapToFlattenListTaskInput(this.base, this.mapper);
+
+  @override
+  TaskInputBuilder<List> createBuilder() {
+    return new MapToFlattenListTaskInputBuilder<K, V, E>(base, mapper);
+  }
+}
+
+/**
+ * The [TaskInputBuilder] for [MapToFlattenListTaskInput].
+ */
+class MapToFlattenListTaskInputBuilder<K, V, E>
+    implements TaskInputBuilder<List<E>> {
+  final MapTaskInput<K, List<V>> base;
+  final BinaryFunction<K, V, E> mapper;
+
+  TaskInputBuilder currentBuilder;
+  Map<K, List<V>> baseMap;
+  Iterator<K> keyIterator;
+  Iterator<V> valueIterator;
+
+  final List<E> inputValue = <E>[];
+
+  MapToFlattenListTaskInputBuilder(this.base, this.mapper) {
+    currentBuilder = base.createBuilder();
+  }
+
+  @override
+  ResultDescriptor get currentResult {
+    if (currentBuilder == null) {
+      return null;
+    }
+    return currentBuilder.currentResult;
+  }
+
+  AnalysisTarget get currentTarget {
+    if (currentBuilder == null) {
+      return null;
+    }
+    return currentBuilder.currentTarget;
+  }
+
+  @override
+  void set currentValue(Object value) {
+    if (currentBuilder == null) {
+      throw new StateError(
+          'Cannot set the result value when there is no current result');
+    }
+    currentBuilder.currentValue = value;
+  }
+
+  @override
+  bool moveNext() {
+    // Prepare base Map.
+    if (baseMap == null) {
+      if (currentBuilder.moveNext()) {
+        return true;
+      }
+      baseMap = currentBuilder.inputValue;
+      keyIterator = baseMap.keys.iterator;
+      // Done with this builder.
+      currentBuilder = null;
+    }
+    // Prepare the next result value.
+    if (currentBuilder != null) {
+      if (currentBuilder.moveNext()) {
+        return true;
+      }
+      // Add the result value for the current Map key/value.
+      E resultValue = currentBuilder.inputValue;
+      inputValue.add(resultValue);
+      // Done with this builder.
+      currentBuilder = null;
+    }
+    // Move to the next Map value.
+    if (valueIterator != null && valueIterator.moveNext()) {
+      K key = keyIterator.current;
+      V value = valueIterator.current;
+      currentBuilder = mapper(key, value).createBuilder();
+      return moveNext();
+    }
+    // Move to the next Map key.
+    if (keyIterator.moveNext()) {
+      K key = keyIterator.current;
+      valueIterator = baseMap[key].iterator;
+      return moveNext();
+    }
+    // No more Map values/keys to transform.
+    return false;
+  }
+}
+
+/**
  * An input to an [AnalysisTask] that is computed by accessing a single result
  * defined on a single target.
  */
diff --git a/pkg/analyzer/lib/task/dart.dart b/pkg/analyzer/lib/task/dart.dart
index 2918d20..8195549 100644
--- a/pkg/analyzer/lib/task/dart.dart
+++ b/pkg/analyzer/lib/task/dart.dart
@@ -12,15 +12,6 @@
 import 'package:analyzer/task/model.dart';
 
 /**
- * The element model associated with a single compilation unit.
- *
- * The result is only available for targets representing a Dart compilation unit.
- */
-final ResultDescriptor<CompilationUnitElement> COMPILATION_UNIT_ELEMENT =
-    new ResultDescriptor<CompilationUnitElement>(
-        'COMPILATION_UNIT_ELEMENT', null);
-
-/**
  * The analysis errors associated with a target.
  *
  * The value combines errors represented by multiple other results.
@@ -43,14 +34,6 @@
     new ListResultDescriptor<Source>('EXPORTED_LIBRARIES', Source.EMPTY_ARRAY);
 
 /**
- * A flag specifying whether a library imports 'dart:html'.
- *
- * The result is only available for targets representing a Dart library.
- */
-final ResultDescriptor<bool> HAS_HTML_IMPORT =
-    new ResultDescriptor<bool>('HAS_HTML_IMPORT', false);
-
-/**
  * The sources of the libraries that are imported into a library.
  *
  * Not `null`.
@@ -74,6 +57,15 @@
     new ListResultDescriptor<Source>('INCLUDED_PARTS', Source.EMPTY_ARRAY);
 
 /**
+ * A flag specifying whether a library is dependent on code that is only
+ * available in a client.
+ *
+ * The result is only available for targets representing a Dart library.
+ */
+final ResultDescriptor<bool> IS_CLIENT =
+    new ResultDescriptor<bool>('IS_CLIENT', false);
+
+/**
  * A flag specifying whether a library is launchable.
  *
  * The result is only available for targets representing a Dart library.
@@ -82,15 +74,12 @@
     new ResultDescriptor<bool>('IS_LAUNCHABLE', false);
 
 /**
- * The errors produced while parsing a compilation unit.
+ * The fully built [LibraryElement] associated with a library.
  *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for targets representing a Dart compilation unit.
+ * The result is only available for targets representing a Dart library.
  */
-final ResultDescriptor<List<AnalysisError>> PARSE_ERRORS =
-    new ResultDescriptor<List<AnalysisError>>(
-        'PARSE_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS);
+final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT =
+    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT', null);
 
 /**
  * The compilation unit AST produced while parsing a compilation unit.
@@ -103,15 +92,12 @@
     new ResultDescriptor<CompilationUnit>('PARSED_UNIT', null);
 
 /**
- * The errors produced while scanning a compilation unit.
+ * The resolved [CompilationUnit] associated with a unit.
  *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for targets representing a Dart compilation unit.
+ * The result is only available for targets representing a unit.
  */
-final ResultDescriptor<List<AnalysisError>> SCAN_ERRORS =
-    new ResultDescriptor<List<AnalysisError>>(
-        'SCAN_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS);
+final ResultDescriptor<CompilationUnit> RESOLVED_UNIT =
+    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT', null);
 
 /**
  * The token stream produced while scanning a compilation unit.
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index 4da15af..973f24e 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -12,6 +12,11 @@
 import 'package:analyzer/src/task/model.dart';
 
 /**
+ * A function that converts the given [key] and [value] into a [TaskInput].
+ */
+typedef TaskInput<E> BinaryFunction<K, V, E>(K key, V value);
+
+/**
  * A function that takes an analysis [context] and an analysis [target] and
  * returns an analysis task. Such functions are passed to a [TaskDescriptor] to
  * be used to create the described task.
@@ -292,7 +297,7 @@
    * elements of this input and whose values are the result of passing the
    * corresponding key to the [mapper] function.
    */
-  TaskInput<Map<E, dynamic /*V*/ >> toMap(
+  MapTaskInput<E, dynamic /*V*/ > toMap(
       UnaryFunction<E, dynamic /*<V>*/ > mapper);
 
   /**
@@ -300,11 +305,27 @@
    * elements of this input and whose values are the [valueResult]'s associated
    * with those elements.
    */
-  TaskInput<Map<AnalysisTarget, dynamic /*V*/ >> toMapOf(
+  MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf(
       ResultDescriptor /*<V>*/ valueResult);
 }
 
 /**
+ * A description of an input with a [Map] based values.
+ *
+ * Clients are not expected to subtype this class.
+ */
+abstract class MapTaskInput<K, V> extends TaskInput<Map<K, V>> {
+  /**
+   * [V] must be a [List].
+   * Return a task input that can be used to compute a list whose elements are
+   * the result of passing keys [K] and the corresponding elements of [V] to
+   * the [mapper] function.
+   */
+  TaskInput<List /*<E>*/ > toFlattenList(
+      BinaryFunction<K, dynamic /*element of V*/, dynamic /*<E>*/ > mapper);
+}
+
+/**
  * A description of an analysis result that can be computed by an [AnalysisTask].
  *
  * Clients are not expected to subtype this class.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 8ac7743..b5cde46 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.25.0-dev.2
+version: 0.24.3
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
@@ -7,7 +7,6 @@
   sdk: '>=0.8.10+6 <2.0.0'
 dependencies:
   args: '>=0.12.1 <0.13.0'
-  logging: '>=0.9.0 <0.10.0'
   path: '>=0.9.0 <2.0.0'
   watcher: '>=0.9.0 <0.10.0'
 dev_dependencies:
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 23959e4..a45e012 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -126,9 +126,8 @@
   }
 
   void test_tokenize_directive_xml() {
-    _tokenize("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>", <Object>[
-      "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
-    ]);
+    _tokenize("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>",
+        <Object>["<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"]);
   }
 
   void test_tokenize_directives_incomplete_with_newline() {
@@ -932,10 +931,11 @@
     return constructorInvocations;
   }
 
-  Map<VariableElement, VariableDeclaration> _findVariableDeclarations() {
+  Map<PotentiallyConstVariableElement, VariableDeclaration> _findVariableDeclarations() {
     ConstantFinder finder = new ConstantFinder();
     _node.accept(finder);
-    Map<VariableElement, VariableDeclaration> variableMap = finder.variableMap;
+    Map<PotentiallyConstVariableElement, VariableDeclaration> variableMap =
+        finder.variableMap;
     expect(variableMap, isNotNull);
     return variableMap;
   }
@@ -2284,6 +2284,26 @@
     errorListener.assertNoErrors();
   }
 
+  void test_visitSimpleIdentifier_className() {
+    CompilationUnit compilationUnit = resolveSource('''
+const a = C;
+class C {}
+''');
+    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
+    expect(result.type, typeProvider.typeType);
+    ClassElement element = result.value;
+    expect(element.name, 'C');
+  }
+
+  void test_visitSimpleIdentifier_dynamic() {
+    CompilationUnit compilationUnit = resolveSource('''
+const a = dynamic;
+''');
+    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
+    expect(result.type, typeProvider.typeType);
+    expect(result.value, typeProvider.dynamicType.element);
+  }
+
   void test_visitSimpleIdentifier_inEnvironment() {
     CompilationUnit compilationUnit = resolveSource(r'''
 const a = b;
@@ -5706,10 +5726,9 @@
     String firstTypeParameterName = "A";
     String secondTypeParameterName = "B";
     TypeAlias typeAlias = AstFactory.typeAlias(null, aliasName, AstFactory
-        .typeParameterList([
-      firstTypeParameterName,
-      secondTypeParameterName
-    ]), AstFactory.formalParameterList());
+            .typeParameterList(
+                [firstTypeParameterName, secondTypeParameterName]),
+        AstFactory.formalParameterList());
     typeAlias.accept(builder);
     List<FunctionTypeAliasElement> aliases = holder.typeAliases;
     expect(aliases, hasLength(1));
@@ -6421,6 +6440,31 @@
     expect(new ErrorReporter(listener, source), isNotNull);
   }
 
+  void test_reportErrorForElement_named() {
+    DartType type = createType("/test1.dart", "A");
+    ClassElement element = type.element;
+    GatheringErrorListener listener = new GatheringErrorListener();
+    ErrorReporter reporter = new ErrorReporter(listener, element.source);
+    reporter.reportErrorForElement(
+        StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER,
+        element, ['A']);
+    AnalysisError error = listener.errors[0];
+    expect(error.offset, element.nameOffset);
+  }
+
+  void test_reportErrorForElement_unnamed() {
+    ImportElementImpl element =
+        ElementFactory.importFor(ElementFactory.library(null, ''), null);
+    GatheringErrorListener listener = new GatheringErrorListener();
+    ErrorReporter reporter = new ErrorReporter(
+        listener, new NonExistingSource("/test.dart", UriKind.FILE_URI));
+    reporter.reportErrorForElement(
+        StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER,
+        element, ['A']);
+    AnalysisError error = listener.errors[0];
+    expect(error.offset, element.nameOffset);
+  }
+
   void test_reportTypeErrorForNode_differentNames() {
     DartType firstType = createType("/test1.dart", "A");
     DartType secondType = createType("/test2.dart", "B");
@@ -7394,9 +7438,8 @@
 </html>""");
     _validate(htmlUnit, [
       _t4("html", [
-        _t4("body", [
-          _t("script", _a(["type", "'application/dart'"]), scriptBody)
-        ])
+        _t4("body",
+            [_t("script", _a(["type", "'application/dart'"]), scriptBody)])
       ])
     ]);
   }
@@ -7408,8 +7451,9 @@
     ht.Token token = scanner.tokenize();
     LineInfo lineInfo = new LineInfo(scanner.lineStarts);
     GatheringErrorListener errorListener = new GatheringErrorListener();
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     ht.HtmlUnit unit =
-        new ht.HtmlParser(null, errorListener).parse(token, lineInfo);
+        new ht.HtmlParser(null, errorListener, options).parse(token, lineInfo);
     errorListener.assertNoErrors();
     return unit;
   }
@@ -7464,9 +7508,8 @@
     // ht.XmlTagNode.getContent() does not include whitespace
     // between '<' and '>' at this time
     _validate(htmlUnit, [
-      _t3("html", "\n<pa=\"b\">blat \n </p>\n", [
-        _t("p", _a(["a", "\"b\""]), "blat \n ")
-      ])
+      _t3("html", "\n<pa=\"b\">blat \n </p>\n",
+          [_t("p", _a(["a", "\"b\""]), "blat \n ")])
     ]);
   }
   void test_parse_content_none() {
@@ -7806,7 +7849,7 @@
 @reflectiveTest
 class ReferenceFinderTest extends EngineTestCase {
   DirectedGraph<AstNode> _referenceGraph;
-  Map<VariableElement, VariableDeclaration> _variableDeclarationMap;
+  Map<PotentiallyConstVariableElement, VariableDeclaration> _variableDeclarationMap;
   Map<ConstructorElement, ConstructorDeclaration> _constructorDeclarationMap;
   VariableDeclaration _head;
   AstNode _tail;
@@ -7814,7 +7857,7 @@
   void setUp() {
     _referenceGraph = new DirectedGraph<AstNode>();
     _variableDeclarationMap =
-        new HashMap<VariableElement, VariableDeclaration>();
+        new HashMap<PotentiallyConstVariableElement, VariableDeclaration>();
     _constructorDeclarationMap =
         new HashMap<ConstructorElement, ConstructorDeclaration>();
     _head = AstFactory.variableDeclaration("v1");
@@ -7937,8 +7980,8 @@
     VariableDeclaration variableDeclaration =
         AstFactory.variableDeclaration(name);
     _tail = variableDeclaration;
-    VariableElementImpl variableElement =
-        ElementFactory.localVariableElement2(name);
+    ConstLocalVariableElementImpl variableElement =
+        ElementFactory.constLocalVariableElement(name);
     variableElement.const3 = isConst;
     AstFactory.variableDeclarationList2(
         isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]);
diff --git a/pkg/analyzer/test/generated/ast_test.dart b/pkg/analyzer/test/generated/ast_test.dart
index 51ad0ca..64ead75 100644
--- a/pkg/analyzer/test/generated/ast_test.dart
+++ b/pkg/analyzer/test/generated/ast_test.dart
@@ -264,14 +264,12 @@
 
   void test_binary_divide_double() {
     Object value = _getConstantValue("3.2 / 2.3");
-    EngineTestCase.assertInstanceOf((obj) => obj is double, double, value);
-    expect(value as double, 3.2 / 2.3);
+    expect(value, 3.2 / 2.3);
   }
 
   void test_binary_divide_integer() {
     Object value = _getConstantValue("3 / 2");
-    EngineTestCase.assertInstanceOf((obj) => obj is int, int, value);
-    expect(value as int, 1);
+    expect(value, 1.5);
   }
 
   void test_binary_equal_boolean() {
@@ -337,14 +335,12 @@
 
   void test_binary_minus_double() {
     Object value = _getConstantValue("3.2 - 2.3");
-    EngineTestCase.assertInstanceOf((obj) => obj is double, double, value);
-    expect(value as double, 3.2 - 2.3);
+    expect(value, 3.2 - 2.3);
   }
 
   void test_binary_minus_integer() {
     Object value = _getConstantValue("3 - 2");
-    EngineTestCase.assertInstanceOf((obj) => obj is int, int, value);
-    expect(value as int, 1);
+    expect(value, 1);
   }
 
   void test_binary_notEqual_boolean() {
@@ -374,26 +370,22 @@
 
   void test_binary_plus_double() {
     Object value = _getConstantValue("2.3 + 3.2");
-    EngineTestCase.assertInstanceOf((obj) => obj is double, double, value);
-    expect(value as double, 2.3 + 3.2);
+    expect(value, 2.3 + 3.2);
   }
 
   void test_binary_plus_integer() {
     Object value = _getConstantValue("2 + 3");
-    EngineTestCase.assertInstanceOf((obj) => obj is int, int, value);
-    expect(value as int, 5);
+    expect(value, 5);
   }
 
   void test_binary_remainder_double() {
     Object value = _getConstantValue("3.2 % 2.3");
-    EngineTestCase.assertInstanceOf((obj) => obj is double, double, value);
-    expect(value as double, 3.2 % 2.3);
+    expect(value, 3.2 % 2.3);
   }
 
   void test_binary_remainder_integer() {
     Object value = _getConstantValue("8 % 3");
-    EngineTestCase.assertInstanceOf((obj) => obj is int, int, value);
-    expect(value as int, 2);
+    expect(value, 2);
   }
 
   void test_binary_rightShift() {
@@ -404,14 +396,12 @@
 
   void test_binary_times_double() {
     Object value = _getConstantValue("2.3 * 3.2");
-    EngineTestCase.assertInstanceOf((obj) => obj is double, double, value);
-    expect(value as double, 2.3 * 3.2);
+    expect(value, 2.3 * 3.2);
   }
 
   void test_binary_times_integer() {
     Object value = _getConstantValue("2 * 3");
-    EngineTestCase.assertInstanceOf((obj) => obj is int, int, value);
-    expect(value as int, 6);
+    expect(value, 6);
   }
 
   void test_binary_truncatingDivide_double() {
@@ -463,14 +453,12 @@
 
   void test_literal_number_double() {
     Object value = _getConstantValue("3.45");
-    EngineTestCase.assertInstanceOf((obj) => obj is double, double, value);
-    expect(value as double, 3.45);
+    expect(value, 3.45);
   }
 
   void test_literal_number_integer() {
     Object value = _getConstantValue("42");
-    EngineTestCase.assertInstanceOf((obj) => obj is int, int, value);
-    expect(value as int, 42);
+    expect(value, 42);
   }
 
   void test_literal_string_adjacent() {
@@ -511,14 +499,12 @@
 
   void test_unary_negated_double() {
     Object value = _getConstantValue("-42.3");
-    EngineTestCase.assertInstanceOf((obj) => obj is double, double, value);
-    expect(value as double, -42.3);
+    expect(value, -42.3);
   }
 
   void test_unary_negated_integer() {
     Object value = _getConstantValue("-42");
-    EngineTestCase.assertInstanceOf((obj) => obj is int, int, value);
-    expect(value as int, -42);
+    expect(value, -42);
   }
 
   Object _getConstantValue(String source) =>
@@ -1172,9 +1158,8 @@
 
   void test_isQualified_inMethodInvocation_withTarget() {
     MethodInvocation invocation = AstFactory.methodInvocation(
-        AstFactory.identifier3("target"), "test", [
-      AstFactory.identifier3("arg0")
-    ]);
+        AstFactory.identifier3("target"), "test",
+        [AstFactory.identifier3("arg0")]);
     SimpleIdentifier identifier = invocation.methodName;
     expect(identifier.isQualified, isTrue);
   }
@@ -1281,19 +1266,26 @@
     expect(new SimpleStringLiteral(
         TokenFactory.tokenFromString("'X'"), "X").contentsEnd, 2);
     expect(new SimpleStringLiteral(
-        TokenFactory.tokenFromString("\"X\""), "X").contentsEnd, 2);
+        TokenFactory.tokenFromString('"X"'), "X").contentsEnd, 2);
+
     expect(new SimpleStringLiteral(
-        TokenFactory.tokenFromString("\"\"\"X\"\"\""), "X").contentsEnd, 4);
+        TokenFactory.tokenFromString('"""X"""'), "X").contentsEnd, 4);
     expect(new SimpleStringLiteral(
         TokenFactory.tokenFromString("'''X'''"), "X").contentsEnd, 4);
     expect(new SimpleStringLiteral(
+        TokenFactory.tokenFromString("'''  \nX'''"), "X").contentsEnd, 7);
+
+    expect(new SimpleStringLiteral(
         TokenFactory.tokenFromString("r'X'"), "X").contentsEnd, 3);
     expect(new SimpleStringLiteral(
-        TokenFactory.tokenFromString("r\"X\""), "X").contentsEnd, 3);
+        TokenFactory.tokenFromString('r"X"'), "X").contentsEnd, 3);
+
     expect(new SimpleStringLiteral(
-        TokenFactory.tokenFromString("r\"\"\"X\"\"\""), "X").contentsEnd, 5);
+        TokenFactory.tokenFromString('r"""X"""'), "X").contentsEnd, 5);
     expect(new SimpleStringLiteral(
         TokenFactory.tokenFromString("r'''X'''"), "X").contentsEnd, 5);
+    expect(new SimpleStringLiteral(
+        TokenFactory.tokenFromString("r'''  \nX'''"), "X").contentsEnd, 8);
   }
 
   void test_contentsOffset() {
@@ -1313,6 +1305,11 @@
         TokenFactory.tokenFromString("r\"\"\"X\"\"\""), "X").contentsOffset, 4);
     expect(new SimpleStringLiteral(
         TokenFactory.tokenFromString("r'''X'''"), "X").contentsOffset, 4);
+    // leading whitespace
+    expect(new SimpleStringLiteral(
+        TokenFactory.tokenFromString("''' \ \nX''"), "X").contentsOffset, 6);
+    expect(new SimpleStringLiteral(
+        TokenFactory.tokenFromString('r""" \ \nX"""'), "X").contentsOffset, 7);
   }
 
   void test_isMultiline() {
@@ -1880,9 +1877,8 @@
   }
 
   void test_visitCompilationUnit_directive_declaration() {
-    _assertSource("library l; var a;", AstFactory.compilationUnit4([
-      AstFactory.libraryDirective2("l")
-    ], [
+    _assertSource("library l; var a;", AstFactory.compilationUnit4(
+        [AstFactory.libraryDirective2("l")], [
       AstFactory.topLevelVariableDeclaration2(
           Keyword.VAR, [AstFactory.variableDeclaration("a")])
     ]));
@@ -1912,9 +1908,8 @@
 
   void test_visitCompilationUnit_script_directives_declarations() {
     _assertSource("!#/bin/dartvm library l; var a;", AstFactory
-        .compilationUnit8("!#/bin/dartvm", [
-      AstFactory.libraryDirective2("l")
-    ], [
+        .compilationUnit8("!#/bin/dartvm", [AstFactory.libraryDirective2("l")],
+            [
       AstFactory.topLevelVariableDeclaration2(
           Keyword.VAR, [AstFactory.variableDeclaration("a")])
     ]));
@@ -2308,9 +2303,8 @@
 
   void test_visitForStatement_cu() {
     _assertSource("for (; c; u) {}", AstFactory.forStatement(null,
-        AstFactory.identifier3("c"), [
-      AstFactory.identifier3("u")
-    ], AstFactory.block()));
+        AstFactory.identifier3("c"), [AstFactory.identifier3("u")],
+        AstFactory.block()));
   }
 
   void test_visitForStatement_e() {
@@ -2326,16 +2320,14 @@
 
   void test_visitForStatement_ecu() {
     _assertSource("for (e; c; u) {}", AstFactory.forStatement(
-        AstFactory.identifier3("e"), AstFactory.identifier3("c"), [
-      AstFactory.identifier3("u")
-    ], AstFactory.block()));
+        AstFactory.identifier3("e"), AstFactory.identifier3("c"),
+        [AstFactory.identifier3("u")], AstFactory.block()));
   }
 
   void test_visitForStatement_eu() {
     _assertSource("for (e;; u) {}", AstFactory.forStatement(
-        AstFactory.identifier3("e"), null, [
-      AstFactory.identifier3("u")
-    ], AstFactory.block()));
+        AstFactory.identifier3("e"), null, [AstFactory.identifier3("u")],
+        AstFactory.block()));
   }
 
   void test_visitForStatement_i() {
@@ -2347,26 +2339,24 @@
 
   void test_visitForStatement_ic() {
     _assertSource("for (var i; c;) {}", AstFactory.forStatement2(AstFactory
-        .variableDeclarationList2(Keyword.VAR, [
-      AstFactory.variableDeclaration("i")
-    ]), AstFactory.identifier3("c"), null, AstFactory.block()));
+            .variableDeclarationList2(
+                Keyword.VAR, [AstFactory.variableDeclaration("i")]),
+        AstFactory.identifier3("c"), null, AstFactory.block()));
   }
 
   void test_visitForStatement_icu() {
     _assertSource("for (var i; c; u) {}", AstFactory.forStatement2(AstFactory
-        .variableDeclarationList2(Keyword.VAR, [
-      AstFactory.variableDeclaration("i")
-    ]), AstFactory.identifier3("c"), [
-      AstFactory.identifier3("u")
-    ], AstFactory.block()));
+            .variableDeclarationList2(
+                Keyword.VAR, [AstFactory.variableDeclaration("i")]),
+        AstFactory.identifier3("c"), [AstFactory.identifier3("u")],
+        AstFactory.block()));
   }
 
   void test_visitForStatement_iu() {
     _assertSource("for (var i;; u) {}", AstFactory.forStatement2(AstFactory
-        .variableDeclarationList2(
-            Keyword.VAR, [AstFactory.variableDeclaration("i")]), null, [
-      AstFactory.identifier3("u")
-    ], AstFactory.block()));
+            .variableDeclarationList2(
+                Keyword.VAR, [AstFactory.variableDeclaration("i")]), null,
+        [AstFactory.identifier3("u")], AstFactory.block()));
   }
 
   void test_visitForStatement_u() {
@@ -2489,9 +2479,8 @@
 
   void test_visitImportDirective_combinator() {
     _assertSource("import 'a.dart' show A;", AstFactory.importDirective3(
-        "a.dart", null, [
-      AstFactory.showCombinator([AstFactory.identifier3("A")])
-    ]));
+        "a.dart", null,
+        [AstFactory.showCombinator([AstFactory.identifier3("A")])]));
   }
 
   void test_visitImportDirective_combinators() {
@@ -2519,9 +2508,8 @@
 
   void test_visitImportDirective_prefix_combinator() {
     _assertSource("import 'a.dart' as p show A;", AstFactory.importDirective3(
-        "a.dart", "p", [
-      AstFactory.showCombinator([AstFactory.identifier3("A")])
-    ]));
+        "a.dart", "p",
+        [AstFactory.showCombinator([AstFactory.identifier3("A")])]));
   }
 
   void test_visitImportDirective_prefix_combinators() {
@@ -2779,6 +2767,11 @@
     _assertSource("@deprecated m() {}", declaration);
   }
 
+  void test_visitMethodInvocation_conditional() {
+    _assertSource("t?.m()", AstFactory.methodInvocation(
+        AstFactory.identifier3("t"), "m", null, TokenType.QUESTION_PERIOD));
+  }
+
   void test_visitMethodInvocation_noTarget() {
     _assertSource("m()", AstFactory.methodInvocation2("m"));
   }
@@ -2865,6 +2858,11 @@
         "a.b", AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"));
   }
 
+  void test_visitPropertyAccess_conditional() {
+    _assertSource("a?.b", AstFactory.propertyAccess2(
+        AstFactory.identifier3("a"), "b", TokenType.QUESTION_PERIOD));
+  }
+
   void test_visitRedirectingConstructorInvocation_named() {
     _assertSource(
         "this.c()", AstFactory.redirectingConstructorInvocation2("c"));
@@ -2952,9 +2950,9 @@
   }
 
   void test_visitSwitchCase_singleLabel() {
-    _assertSource("l1: case a: {}", AstFactory.switchCase2([
-      AstFactory.label2("l1")
-    ], AstFactory.identifier3("a"), [AstFactory.block()]));
+    _assertSource("l1: case a: {}", AstFactory.switchCase2(
+        [AstFactory.label2("l1")], AstFactory.identifier3("a"),
+        [AstFactory.block()]));
   }
 
   void test_visitSwitchDefault_multipleLabels() {
@@ -3032,9 +3030,9 @@
 
   void test_visitTryStatement_catchFinally() {
     _assertSource("try {} on E {} finally {}", AstFactory.tryStatement3(
-        AstFactory.block(), [
-      AstFactory.catchClause3(AstFactory.typeName4("E"))
-    ], AstFactory.block()));
+        AstFactory.block(),
+        [AstFactory.catchClause3(AstFactory.typeName4("E"))],
+        AstFactory.block()));
   }
 
   void test_visitTryStatement_finally() {
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 0ee4698..7b293a8 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -636,9 +636,8 @@
   void test_builtInIdentifierAsTypeParameterName() {
     Source source = addSource("class A<as> {}");
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME]);
     verify([source]);
   }
 
@@ -984,9 +983,8 @@
 }
 const a = new A();''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
   }
 
@@ -1012,9 +1010,8 @@
 final a = const A();
 const C = a.m;''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
   }
 
@@ -1147,27 +1144,24 @@
   const C = p;
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
   }
 
   void test_constInitializedWithNonConstValue_missingConstInListLiteral() {
     Source source = addSource("const List L = [0];");
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
   }
 
   void test_constInitializedWithNonConstValue_missingConstInMapLiteral() {
     Source source = addSource("const Map M = {'a' : 0};");
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE]);
     verify([source]);
   }
 
@@ -1219,9 +1213,8 @@
   const {const A() : 0};
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
   }
 
@@ -1241,9 +1234,8 @@
   const {B.a : 0};
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
   }
 
@@ -1261,9 +1253,8 @@
   var m = const { const A(): 42 };
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
   }
 
@@ -1280,9 +1271,8 @@
   const {const B() : 0};
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS]);
     verify([source]);
   }
 
@@ -1441,9 +1431,8 @@
   return const A();
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT]);
     verify([source]);
   }
 
@@ -1458,18 +1447,16 @@
   void test_defaultValueInFunctionTypedParameter_named() {
     Source source = addSource("f(g({p: null})) {}");
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
     verify([source]);
   }
 
   void test_defaultValueInFunctionTypedParameter_optional() {
     Source source = addSource("f(g([p = null])) {}");
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
     verify([source]);
   }
 
@@ -1911,9 +1898,8 @@
   A() : x = 0, x = 1 {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS]);
     verify([source]);
   }
 
@@ -1953,9 +1939,8 @@
   A(this.x) : x = 1 {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER]);
     verify([source]);
   }
 
@@ -2006,9 +1991,8 @@
   A() : this.named(), x = 42;
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
     verify([source]);
   }
 
@@ -2020,9 +2004,8 @@
   A() : x = 42, this.named();
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
     verify([source]);
   }
 
@@ -2034,9 +2017,8 @@
   A(this.x) : this.named();
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR]);
     verify([source]);
   }
 
@@ -2047,9 +2029,8 @@
   A() : x = 0, x = 0 {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS]);
     verify([source]);
   }
 
@@ -2068,9 +2049,8 @@
   A(this.x) : x = 0 {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER]);
     verify([source]);
   }
 
@@ -2603,9 +2583,8 @@
   A(this.x) {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
     verify([source]);
   }
 
@@ -2618,9 +2597,8 @@
   B(this.x) {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
     verify([source]);
   }
 
@@ -2630,9 +2608,8 @@
   A([this.x]) {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
     verify([source]);
   }
 
@@ -2643,9 +2620,8 @@
   A(this.x) {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD]);
     verify([source]);
   }
 
@@ -3673,9 +3649,8 @@
   A.b() {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS]);
     verify([source]);
   }
 
@@ -3766,9 +3741,8 @@
 }
 ''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
   }
 
@@ -3785,9 +3759,8 @@
 }
 ''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
   }
 
@@ -3822,9 +3795,8 @@
 }
 ''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
   }
 
@@ -3840,9 +3812,8 @@
 }
 ''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
   }
 
@@ -4714,6 +4685,23 @@
     verify([source]);
   }
 
+  void test_recursiveFactoryRedirect_diverging() {
+    // Analysis should terminate even though the redirections don't reach a
+    // fixed point.  (C<int> redirects to C<C<int>>, then to C<C<C<int>>>, and
+    // so on).
+    Source source = addSource('''
+class C<T> {
+  const factory C() = C<C<T>>;
+}
+main() {
+  const C<int>();
+}
+''');
+    resolve(source);
+    assertErrors(source, [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]);
+    verify([source]);
+  }
+
   void test_recursiveFactoryRedirect_generic() {
     Source source = addSource(r'''
 class A<T> implements B<T> {
@@ -4905,9 +4893,8 @@
   void test_recursiveInterfaceInheritanceBaseCaseWith() {
     Source source = addSource("class M = Object with M;");
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_WITH]);
     verify([source]);
   }
 
@@ -4917,9 +4904,8 @@
   A() : this.noSuchConstructor();
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]);
   }
 
   void test_redirectGenerativeToNonGenerativeConstructor() {
@@ -5265,8 +5251,7 @@
     resolve(source);
     assertErrors(source, [
       CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
-      StaticTypeWarningCode.RETURN_OF_INVALID_TYPE
+      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
     ]);
     verify([source]);
   }
@@ -5405,9 +5390,8 @@
   B() : super();
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
   }
 
@@ -5420,9 +5404,8 @@
   B();
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT]);
     verify([source]);
   }
 
@@ -5501,9 +5484,8 @@
   operator -(a, b) {}
 }''');
     resolve(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS
-    ]);
+    assertErrors(source,
+        [CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS]);
     verify([source]);
     reset();
   }
diff --git a/pkg/analyzer/test/generated/element_test.dart b/pkg/analyzer/test/generated/element_test.dart
index 70509b3..7156161 100644
--- a/pkg/analyzer/test/generated/element_test.dart
+++ b/pkg/analyzer/test/generated/element_test.dart
@@ -29,7 +29,6 @@
   runReflectiveTests(FunctionTypeImplTest);
   runReflectiveTests(InterfaceTypeImplTest);
   runReflectiveTests(TypeParameterTypeImplTest);
-  runReflectiveTests(UnionTypeImplTest);
   runReflectiveTests(VoidTypeImplTest);
   runReflectiveTests(ClassElementImplTest);
   runReflectiveTests(CompilationUnitElementImplTest);
@@ -2634,8 +2633,9 @@
   }
 
   void test_isAssignableTo_void() {
+    InterfaceTypeImpl intType = _typeProvider.intType;
     expect(
-        VoidTypeImpl.instance.isAssignableTo(_typeProvider.intType), isFalse);
+        VoidTypeImpl.instance.isAssignableTo(intType), isFalse);
   }
 
   void test_isDirectSupertypeOf_extends() {
@@ -3750,203 +3750,6 @@
 }
 
 @reflectiveTest
-class UnionTypeImplTest extends EngineTestCase {
-  ClassElement _classA;
-
-  InterfaceType _typeA;
-
-  ClassElement _classB;
-
-  InterfaceType _typeB;
-
-  DartType _uA;
-
-  DartType _uB;
-
-  DartType _uAB;
-
-  DartType _uBA;
-
-  List<DartType> _us;
-
-  @override
-  void setUp() {
-    super.setUp();
-    _classA = ElementFactory.classElement2("A");
-    _typeA = _classA.type;
-    _classB = ElementFactory.classElement("B", _typeA);
-    _typeB = _classB.type;
-    _uA = UnionTypeImpl.union([_typeA]);
-    _uB = UnionTypeImpl.union([_typeB]);
-    _uAB = UnionTypeImpl.union([_typeA, _typeB]);
-    _uBA = UnionTypeImpl.union([_typeB, _typeA]);
-    _us = <DartType>[_uA, _uB, _uAB, _uBA];
-  }
-
-  void test_emptyUnionsNotAllowed() {
-    try {
-      UnionTypeImpl.union([]);
-    } on IllegalArgumentException {
-      return;
-    }
-    fail("Expected illegal argument exception.");
-  }
-
-  void test_equality_beingASubtypeOfAnElementIsNotSufficient() {
-    // Non-equal if some elements are different
-    expect(_uAB == _uA, isFalse);
-  }
-
-  void test_equality_insertionOrderDoesntMatter() {
-    // Insertion order doesn't matter, only sets of elements
-    expect(_uAB == _uBA, isTrue);
-    expect(_uBA == _uAB, isTrue);
-  }
-
-  void test_equality_reflexivity() {
-    for (DartType u in _us) {
-      expect(u == u, isTrue);
-    }
-  }
-
-  void test_equality_singletonsCollapse() {
-    expect(_typeA == _uA, isTrue);
-    expect(_uA == _typeA, isTrue);
-  }
-
-  void test_isMoreSpecificThan_allElementsOnLHSAreSubtypesOfSomeElementOnRHS() {
-    // Unions are subtypes when all elements are subtypes
-    expect(_uAB.isMoreSpecificThan(_uA), isTrue);
-    expect(_uAB.isMoreSpecificThan(_typeA), isTrue);
-  }
-
-  void test_isMoreSpecificThan_element() {
-    // Elements of union are sub types
-    expect(_typeA.isMoreSpecificThan(_uAB), isTrue);
-    expect(_typeB.isMoreSpecificThan(_uAB), isTrue);
-  }
-
-  void test_isMoreSpecificThan_notSubtypeOfAnyElement() {
-    // Types that are not subtypes of elements are not subtypes
-    expect(_typeA.isMoreSpecificThan(_uB), isFalse);
-  }
-
-  void test_isMoreSpecificThan_reflexivity() {
-    for (DartType u in _us) {
-      expect(u.isMoreSpecificThan(u), isTrue);
-    }
-  }
-
-  void test_isMoreSpecificThan_someElementOnLHSIsNotASubtypeOfAnyElementOnRHS() {
-    // Unions are subtypes when some element is a subtype
-    expect(_uAB.isMoreSpecificThan(_uB), isTrue);
-    expect(_uAB.isMoreSpecificThan(_typeB), isTrue);
-  }
-
-  void test_isMoreSpecificThan_subtypeOfSomeElement() {
-    // Subtypes of elements are sub types
-    expect(_typeB.isMoreSpecificThan(_uA), isTrue);
-  }
-
-  void test_isSubtypeOf_allElementsOnLHSAreSubtypesOfSomeElementOnRHS() {
-    // Unions are subtypes when all elements are subtypes
-    expect(_uAB.isSubtypeOf(_uA), isTrue);
-    expect(_uAB.isSubtypeOf(_typeA), isTrue);
-  }
-
-  void test_isSubtypeOf_element() {
-    // Elements of union are sub types
-    expect(_typeA.isSubtypeOf(_uAB), isTrue);
-    expect(_typeB.isSubtypeOf(_uAB), isTrue);
-  }
-
-  void test_isSubtypeOf_notSubtypeOfAnyElement() {
-    // Types that are not subtypes of elements are not subtypes
-    expect(_typeA.isSubtypeOf(_uB), isFalse);
-  }
-
-  void test_isSubtypeOf_reflexivity() {
-    for (DartType u in _us) {
-      expect(u.isSubtypeOf(u), isTrue);
-    }
-  }
-
-  void test_isSubtypeOf_someElementOnLHSIsNotASubtypeOfAnyElementOnRHS() {
-    // Unions are subtypes when some element is a subtype
-    expect(_uAB.isSubtypeOf(_uB), isTrue);
-    expect(_uAB.isSubtypeOf(_typeB), isTrue);
-  }
-
-  void test_isSubtypeOf_subtypeOfSomeElement() {
-    // Subtypes of elements are sub types
-    expect(_typeB.isSubtypeOf(_uA), isTrue);
-  }
-
-  void test_nestedUnionsCollapse() {
-    UnionType u = UnionTypeImpl.union([_uAB, _typeA]) as UnionType;
-    for (DartType t in u.elements) {
-      if (t is UnionType) {
-        fail("Expected only non-union types but found $t!");
-      }
-    }
-  }
-
-  void test_noLossage() {
-    UnionType u = UnionTypeImpl
-        .union([_typeA, _typeB, _typeB, _typeA, _typeB, _typeB]) as UnionType;
-    Set<DartType> elements = u.elements;
-    expect(elements.contains(_typeA), isTrue);
-    expect(elements.contains(_typeB), isTrue);
-    expect(elements.length == 2, isTrue);
-  }
-
-  void test_substitute() {
-    // Based on [InterfaceTypeImplTest.test_substitute_equal].
-    ClassElement classAE = ElementFactory.classElement2("A", ["E"]);
-    InterfaceType typeAE = classAE.type;
-    List<DartType> args = [_typeB];
-    List<DartType> params = [classAE.typeParameters[0].type];
-    DartType typeAESubbed = typeAE.substitute2(args, params);
-    expect(typeAE == typeAESubbed, isFalse);
-    expect(UnionTypeImpl.union([_typeA, typeAESubbed]),
-        UnionTypeImpl.union([_typeA, typeAE]).substitute2(args, params));
-  }
-
-  void test_toString_pair() {
-    String s = _uAB.toString();
-    expect(s == "{A,B}" || s == "{B,A}", isTrue);
-    expect(_uAB.displayName, s);
-  }
-
-  void test_toString_singleton() {
-    // Singleton unions collapse to the the single type.
-    expect(_uA.toString(), "A");
-  }
-
-  void test_unionTypeIsLessSpecificThan_function() {
-    // Based on
-    // [FunctionTypeImplTest.test_isAssignableTo_normalAndPositionalArgs].
-    ClassElement a = ElementFactory.classElement2("A");
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
-    DartType uAT = UnionTypeImpl.union([_uA, t]);
-    expect(t.isMoreSpecificThan(uAT), isTrue);
-    expect(t.isMoreSpecificThan(_uAB), isFalse);
-  }
-
-  void test_unionTypeIsSuperTypeOf_function() {
-    // Based on
-    // [FunctionTypeImplTest.test_isAssignableTo_normalAndPositionalArgs].
-    ClassElement a = ElementFactory.classElement2("A");
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
-    DartType uAT = UnionTypeImpl.union([_uA, t]);
-    expect(t.isSubtypeOf(uAT), isTrue);
-    expect(t.isSubtypeOf(_uAB), isFalse);
-  }
-}
-
-@reflectiveTest
 class VoidTypeImplTest extends EngineTestCase {
   /**
    * Reference {code VoidTypeImpl.getInstance()}.
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index 52b8c40..2ecb8d8 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -2221,6 +2221,7 @@
       options.analyzeFunctionBodies = booleanValue;
       options.cacheSize = i;
       options.dart2jsHint = booleanValue;
+      options.enableNullAwareOperators = booleanValue;
       options.enableStrictCallChecks = booleanValue;
       options.generateImplicitErrors = booleanValue;
       options.generateSdkErrors = booleanValue;
@@ -2231,6 +2232,7 @@
       expect(copy.analyzeFunctionBodies, options.analyzeFunctionBodies);
       expect(copy.cacheSize, options.cacheSize);
       expect(copy.dart2jsHint, options.dart2jsHint);
+      expect(copy.enableNullAwareOperators, options.enableNullAwareOperators);
       expect(copy.enableStrictCallChecks, options.enableStrictCallChecks);
       expect(copy.generateImplicitErrors, options.generateImplicitErrors);
       expect(copy.generateSdkErrors, options.generateSdkErrors);
@@ -2335,7 +2337,8 @@
     DartEntry entry = new DartEntry();
     expect(entry.allErrors, hasLength(0));
     entry.setValue(SourceEntry.CONTENT_ERRORS, <AnalysisError>[
-      new AnalysisError.con1(source, ScannerErrorCode.UNABLE_GET_CONTENT)
+      new AnalysisError.con1(
+          source, ScannerErrorCode.UNABLE_GET_CONTENT, ['exception details'])
     ]);
     entry.setValue(DartEntry.SCAN_ERRORS, <AnalysisError>[
       new AnalysisError.con1(
@@ -4539,6 +4542,13 @@
   AstVisitor getVisitor() => null;
 }
 
+class MockSourceFactory extends SourceFactory {
+  MockSourceFactory() : super([]);
+  Source resolveUri(Source containingSource, String containedUri) {
+    throw new JavaIOException();
+  }
+}
+
 @reflectiveTest
 class ParseDartTaskTest extends EngineTestCase {
   void test_accept() {
@@ -4627,6 +4637,26 @@
         new ParseDartTaskTestTV_perform_validateDirectives(context, source));
   }
 
+  void test_resolveDirective_dartUri() {
+    GatheringErrorListener listener = new GatheringErrorListener();
+    ImportDirective directive = AstFactory.importDirective3('dart:core', null);
+    AnalysisContext context = AnalysisContextFactory.contextWithCore();
+    Source source =
+        ParseDartTask.resolveDirective(context, null, directive, listener);
+    expect(source, isNotNull);
+  }
+
+  void test_resolveDirective_exception() {
+    GatheringErrorListener listener = new GatheringErrorListener();
+    ImportDirective directive = AstFactory.importDirective3('dart:core', null);
+    AnalysisContext context = new AnalysisContextImpl();
+    context.sourceFactory = new MockSourceFactory();
+    Source source =
+        ParseDartTask.resolveDirective(context, null, directive, listener);
+    expect(source, isNull);
+    expect(listener.errors, hasLength(1));
+  }
+
   /**
    * Create and return a task that will parse the given content from the given source in the given
    * context.
@@ -5464,6 +5494,11 @@
     return null;
   }
   @override
+  LibraryResolverFactory get libraryResolverFactory {
+    fail("Unexpected invocation of getLibraryResolverFactory");
+    return null;
+  }
+  @override
   ResolverVisitorFactory get resolverVisitorFactory {
     fail("Unexpected invocation of getResolverVisitorFactory");
     return null;
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 8b664f9..0d4c7ee 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -305,6 +305,66 @@
 ''');
   }
 
+  void test_false_constructor_keywordConst_add() {
+    _assertDoesNotMatch(r'''
+class A {
+  A();
+}
+''', r'''
+class A {
+  const A();
+}
+''');
+  }
+
+  void test_false_constructor_keywordConst_remove() {
+    _assertDoesNotMatch(r'''
+class A {
+  const A();
+}
+''', r'''
+class A {
+  A();
+}
+''');
+  }
+
+  void test_false_constructor_keywordFactory_add() {
+    _assertDoesNotMatch(r'''
+class A {
+  A();
+  A.foo() {
+    return new A();
+  }
+}
+''', r'''
+class A {
+  A();
+  factory A.foo() {
+    return new A();
+  }
+}
+''');
+  }
+
+  void test_false_constructor_keywordFactory_remove() {
+    _assertDoesNotMatch(r'''
+class A {
+  A();
+  factory A.foo() {
+    return new A();
+  }
+}
+''', r'''
+class A {
+  A();
+  A.foo() {
+    return new A();
+  }
+}
+''');
+  }
+
   void test_false_constructor_parameters_list_add() {
     _assertDoesNotMatch(r'''
 class A {
@@ -2810,6 +2870,23 @@
     _resetWithIncremental(true);
   }
 
+  void test_computeConstants() {
+    _resolveUnit(r'''
+int f() => 0;
+main() {
+  const x = f();
+  print(x + 1);
+}
+''');
+    _updateAndValidate(r'''
+int f() => 0;
+main() {
+  const x = f();
+  print(x + 2);
+}
+''');
+  }
+
   void test_dartDoc_beforeField() {
     _resolveUnit(r'''
 class A {
@@ -3121,6 +3198,29 @@
 ''');
   }
 
+  void test_false_constConstructor_initializer() {
+    _resolveUnit(r'''
+class C {
+  final int x;
+  const C(this.x);
+  const C.foo() : x = 0;
+}
+main() {
+  const {const C(0): 0, const C.foo(): 1};
+}
+''');
+    _updateAndValidate(r'''
+class C {
+  final int x;
+  const C(this.x);
+  const C.foo() : x = 1;
+}
+main() {
+  const {const C(0): 0, const C.foo(): 1};
+}
+''', expectedSuccess: false);
+  }
+
   void test_false_topLevelFunction_name() {
     _resolveUnit(r'''
 a() {}
diff --git a/pkg/analyzer/test/generated/incremental_scanner_test.dart b/pkg/analyzer/test/generated/incremental_scanner_test.dart
index c0b4365..7307dfb 100644
--- a/pkg/analyzer/test/generated/incremental_scanner_test.dart
+++ b/pkg/analyzer/test/generated/incremental_scanner_test.dart
@@ -4,6 +4,7 @@
 
 library engine.incremental_scanner_test;
 
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/incremental_scanner.dart';
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -220,13 +221,6 @@
     expect(_incrementalScanner.hasNonWhitespaceChange, isTrue);
   }
 
-  void test_insert_periodAndIdentifier() {
-    // "a + b;"
-    // "a + b.x;"
-    _scan("a + b", "", ".x", ";");
-    _assertTokens(2, 5, ["a", "+", "b", ".", "x", ";"]);
-  }
-
   void test_insert_period_afterIdentifier() {
     // "a + b;"
     // "a + b.;"
@@ -265,6 +259,13 @@
     expect(_incrementalScanner.hasNonWhitespaceChange, isTrue);
   }
 
+  void test_insert_periodAndIdentifier() {
+    // "a + b;"
+    // "a + b.x;"
+    _scan("a + b", "", ".x", ";");
+    _assertTokens(2, 5, ["a", "+", "b", ".", "x", ";"]);
+  }
+
   void test_insert_splitIdentifier() {
     // "cob;"
     // "cow.b;"
@@ -498,8 +499,9 @@
     // Incrementally scan the modified contents.
     //
     GatheringErrorListener incrementalListener = new GatheringErrorListener();
-    _incrementalScanner = new IncrementalScanner(
-        source, new CharSequenceReader(modifiedContents), incrementalListener);
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    _incrementalScanner = new IncrementalScanner(source,
+        new CharSequenceReader(modifiedContents), incrementalListener, options);
     _incrementalTokens = _incrementalScanner.rescan(
         _originalTokens, replaceStart, removed.length, added.length);
     //
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 1120177..25ba9fa 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
+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';
@@ -933,6 +934,15 @@
     verify([source]);
   }
 
+  void test_const_dynamic() {
+    Source source = addSource('''
+const Type d = dynamic;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_constConstructorWithNonConstSuper_explicit() {
     Source source = addSource(r'''
 class A {
@@ -2298,6 +2308,36 @@
     verify([source]);
   }
 
+  void test_invalidAssignment_ifNullAssignment_compatibleType() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    Source source = addSource('''
+void f(int i) {
+  num n;
+  n ??= i;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_invalidAssignment_ifNullAssignment_sameType() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    Source source = addSource('''
+void f(int i) {
+  int j;
+  j ??= i;
+}
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_invalidAssignment_implicitlyImplementFunctionViaCall_1() {
     // 18341
     //
@@ -4893,6 +4933,21 @@
     verify([source]);
   }
 
+  void test_undefinedGetter_typeLiteral_conditionalAccess() {
+    // When applied to a type literal, the conditional access operator '?.' can
+    // be used to access instance getters of Type.
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    Source source = addSource('''
+class A {}
+f() => A?.hashCode;
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_undefinedGetter_typeSubstitution() {
     Source source = addSource(r'''
 class A<E> {
@@ -4968,6 +5023,21 @@
     // A call to verify(source) fails as '(() => null)()' isn't resolved.
   }
 
+  void test_undefinedMethod_typeLiteral_conditionalAccess() {
+    // When applied to a type literal, the conditional access operator '?.' can
+    // be used to access instance methods of Type.
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    Source source = addSource('''
+class A {}
+f() => A?.toString();
+''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_undefinedOperator_index() {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 648ea6b..514c0d7 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/incremental_scanner.dart';
 import 'package:analyzer/src/generated/parser.dart';
@@ -316,6 +317,13 @@
     }
   }
 
+  void test_conditionalExpression_precedence_ifNullExpression() {
+    _enableNullAwareOperators = true;
+    ConditionalExpression expression = parseExpression('a ?? b ? y : z');
+    EngineTestCase.assertInstanceOf((obj) => obj is BinaryExpression,
+        BinaryExpression, expression.condition);
+  }
+
   void test_conditionalExpression_precedence_logicalOrExpression() {
     ConditionalExpression expression = parseExpression("a | b ? y : z");
     EngineTestCase.assertInstanceOf((obj) => obj is BinaryExpression,
@@ -359,6 +367,27 @@
         BinaryExpression, expression.leftOperand);
   }
 
+  void test_ifNullExpression() {
+    _enableNullAwareOperators = true;
+    BinaryExpression expression = parseExpression('x ?? y ?? z');
+    EngineTestCase.assertInstanceOf((obj) => obj is BinaryExpression,
+        BinaryExpression, expression.leftOperand);
+  }
+
+  void test_ifNullExpression_precedence_logicalOr_left() {
+    _enableNullAwareOperators = true;
+    BinaryExpression expression = parseExpression('x || y ?? z');
+    EngineTestCase.assertInstanceOf((obj) => obj is BinaryExpression,
+        BinaryExpression, expression.leftOperand);
+  }
+
+  void test_ifNullExpression_precendce_logicalOr_right() {
+    _enableNullAwareOperators = true;
+    BinaryExpression expression = parseExpression('x ?? y || z');
+    EngineTestCase.assertInstanceOf((obj) => obj is BinaryExpression,
+        BinaryExpression, expression.rightOperand);
+  }
+
   void test_logicalAndExpression() {
     BinaryExpression expression = parseExpression("x && y && z");
     EngineTestCase.assertInstanceOf((obj) => obj is BinaryExpression,
@@ -1166,8 +1195,9 @@
   }
 
   void test_getterInFunction_block_noReturnType() {
-    ParserTestCase.parseStatement(
+    FunctionDeclarationStatement statement = ParserTestCase.parseStatement(
         "get x { return _x; }", [ParserErrorCode.GETTER_IN_FUNCTION]);
+    expect(statement.functionDeclaration.functionExpression.parameters, isNull);
   }
 
   void test_getterInFunction_block_returnType() {
@@ -1272,6 +1302,18 @@
         [ParserErrorCode.INVALID_OPERATOR]);
   }
 
+  void test_invalidOperatorAfterSuper_assignableExpression() {
+    _enableNullAwareOperators = true;
+    parse3('parseAssignableExpression', <Object>[false], 'super?.v',
+        [ParserErrorCode.INVALID_OPERATOR_FOR_SUPER]);
+  }
+
+  void test_invalidOperatorAfterSuper_primaryExpression() {
+    _enableNullAwareOperators = true;
+    parse4('parsePrimaryExpression', 'super?.v',
+        [ParserErrorCode.INVALID_OPERATOR_FOR_SUPER]);
+  }
+
   void test_invalidOperatorForSuper() {
     parse4("parseUnaryExpression", "++super",
         [ParserErrorCode.INVALID_OPERATOR_FOR_SUPER]);
@@ -1456,13 +1498,17 @@
   }
 
   void test_missingFunctionParameters_topLevel_void_block() {
-    ParserTestCase.parseCompilationUnit(
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(
         "void f { return x;}", [ParserErrorCode.MISSING_FUNCTION_PARAMETERS]);
+    FunctionDeclaration funct = unit.declarations[0];
+    expect(funct.functionExpression.parameters, hasLength(0));
   }
 
   void test_missingFunctionParameters_topLevel_void_expression() {
-    ParserTestCase.parseCompilationUnit(
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(
         "void f => x;", [ParserErrorCode.MISSING_FUNCTION_PARAMETERS]);
+    FunctionDeclaration funct = unit.declarations[0];
+    expect(funct.functionExpression.parameters, hasLength(0));
   }
 
   void test_missingIdentifier_afterOperator() {
@@ -1525,8 +1571,9 @@
   }
 
   void test_missingMethodParameters_void_block() {
-    parse3("parseClassMember", <Object>["C"], "void m {} }",
-        [ParserErrorCode.MISSING_METHOD_PARAMETERS]);
+    MethodDeclaration method = parse3("parseClassMember", <Object>["C"],
+        "void m {} }", [ParserErrorCode.MISSING_METHOD_PARAMETERS]);
+    expect(method.parameters, hasLength(0));
   }
 
   void test_missingMethodParameters_void_expression() {
@@ -1828,6 +1875,12 @@
     ]);
   }
 
+  void test_topLevel_getter() {
+    FunctionDeclaration funct = parse3("parseCompilationUnitMember",
+        <Object>[emptyCommentAndMetadata()], "get x => 7;");
+    expect(funct.functionExpression.parameters, isNull);
+  }
+
   void test_topLevelOperator_withoutType() {
     parse3("parseCompilationUnitMember", <Object>[emptyCommentAndMetadata()],
         "operator +(bool x, bool y) => x | y;",
@@ -1888,6 +1941,70 @@
         "int x; ; int y;", [ParserErrorCode.UNEXPECTED_TOKEN]);
   }
 
+  void test_unterminatedString_at_eof() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    ParserTestCase.parseCompilationUnit(r'''
+void main() {
+  var x = "''', [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+  }
+
+  void test_unterminatedString_at_eol() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    ParserTestCase.parseCompilationUnit(r'''
+void main() {
+  var x = "
+;
+}
+''', [ScannerErrorCode.UNTERMINATED_STRING_LITERAL]);
+  }
+
+  void test_unterminatedString_multiline_at_eof_3_quotes() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    ParserTestCase.parseCompilationUnit(r'''
+void main() {
+  var x = """''', [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+  }
+
+  void test_unterminatedString_multiline_at_eof_4_quotes() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    ParserTestCase.parseCompilationUnit(r'''
+void main() {
+  var x = """"''', [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+  }
+
+  void test_unterminatedString_multiline_at_eof_5_quotes() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    ParserTestCase.parseCompilationUnit(r'''
+void main() {
+  var x = """""''', [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+  }
+
   void test_useOfUnaryPlusOperator() {
     SimpleIdentifier expression = parse4(
         "parseUnaryExpression", "+x", [ParserErrorCode.MISSING_IDENTIFIER]);
@@ -2360,8 +2477,9 @@
     // Incrementally parse the modified contents.
     //
     GatheringErrorListener incrementalListener = new GatheringErrorListener();
-    IncrementalScanner incrementalScanner = new IncrementalScanner(
-        source, new CharSequenceReader(modifiedContents), incrementalListener);
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    IncrementalScanner incrementalScanner = new IncrementalScanner(source,
+        new CharSequenceReader(modifiedContents), incrementalListener, options);
     Token incrementalTokens = incrementalScanner.rescan(
         originalTokens, replaceStart, removed.length, added.length);
     expect(incrementalTokens, isNotNull);
@@ -2399,6 +2517,12 @@
   static bool parseFunctionBodies = true;
 
   /**
+   * If non-null, this value is used to override the default value of
+   * [Scanner.enableNullAwareOperators] before scanning.
+   */
+  bool _enableNullAwareOperators;
+
+  /**
    * Return a CommentAndMetadata object with the given values that can be used for testing.
    *
    * @param comment the comment to be wrapped in the object
@@ -2441,6 +2565,9 @@
     //
     Scanner scanner =
         new Scanner(null, new CharSequenceReader(source), listener);
+    if (_enableNullAwareOperators != null) {
+      scanner.enableNullAwareOperators = _enableNullAwareOperators;
+    }
     Token tokenStream = scanner.tokenize();
     listener.setLineInfo(new TestSource(), scanner.lineStarts);
     //
@@ -2574,6 +2701,9 @@
     GatheringErrorListener listener = new GatheringErrorListener();
     Scanner scanner =
         new Scanner(null, new CharSequenceReader(source), listener);
+    if (_enableNullAwareOperators != null) {
+      scanner.enableNullAwareOperators = _enableNullAwareOperators;
+    }
     listener.setLineInfo(new TestSource(), scanner.lineStarts);
     Token token = scanner.tokenize();
     Parser parser = createParser(listener);
@@ -3139,6 +3269,36 @@
     parseExpression("m(f() => 0);", [ParserErrorCode.EXPECTED_TOKEN]);
   }
 
+  void test_importDirectivePartial_as() {
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(
+        "import 'b.dart' d as b;",
+        [ParserErrorCode.UNEXPECTED_TOKEN]);
+    ImportDirective importDirective = unit.childEntities.first;
+    expect(importDirective.asKeyword, isNotNull);
+    expect(unit.directives, hasLength(1));
+    expect(unit.declarations, hasLength(0));
+  }
+
+  void test_importDirectivePartial_show() {
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(
+        "import 'b.dart' d show foo;",
+        [ParserErrorCode.UNEXPECTED_TOKEN]);
+    ImportDirective importDirective = unit.childEntities.first;
+    expect(importDirective.combinators, hasLength(1));
+    expect(unit.directives, hasLength(1));
+    expect(unit.declarations, hasLength(0));
+  }
+
+  void test_importDirectivePartial_hide() {
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(
+        "import 'b.dart' d hide foo;",
+        [ParserErrorCode.UNEXPECTED_TOKEN]);
+    ImportDirective importDirective = unit.childEntities.first;
+    expect(importDirective.combinators, hasLength(1));
+    expect(unit.directives, hasLength(1));
+    expect(unit.declarations, hasLength(0));
+  }
+
   void test_incomplete_conditionalExpression() {
     parseExpression("x ? 0", [
       ParserErrorCode.EXPECTED_TOKEN,
@@ -4469,6 +4629,15 @@
     ParserTestCase.parseCompilationUnit("class C { C() : a = \"\${(){}}\"; }");
   }
 
+  void test_import_as_show() {
+    ParserTestCase.parseCompilationUnit("import 'dart:math' as M show E;");
+  }
+
+  void test_import_show_hide() {
+    ParserTestCase.parseCompilationUnit(
+        "import 'import1_lib.dart' show hide, show hide ugly;");
+  }
+
   void test_isFunctionDeclaration_nameButNoReturn_block() {
     expect(_isFunctionDeclaration("f() {}"), isTrue);
   }
@@ -4769,7 +4938,7 @@
     PropertyAccess propertyAccess =
         parse("parseAssignableExpression", <Object>[false], "(x).y");
     expect(propertyAccess.target, isNotNull);
-    expect(propertyAccess.operator, isNotNull);
+    expect(propertyAccess.operator.type, TokenType.PERIOD);
     expect(propertyAccess.propertyName, isNotNull);
   }
 
@@ -4782,6 +4951,15 @@
     expect(expression.rightBracket, isNotNull);
   }
 
+  void test_parseAssignableExpression_expression_question_dot() {
+    _enableNullAwareOperators = true;
+    PropertyAccess propertyAccess =
+        parse("parseAssignableExpression", <Object>[false], "(x)?.y");
+    expect(propertyAccess.target, isNotNull);
+    expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
   void test_parseAssignableExpression_identifier() {
     SimpleIdentifier identifier =
         parse("parseAssignableExpression", <Object>[false], "x");
@@ -4805,6 +4983,7 @@
         parse("parseAssignableExpression", <Object>[false], "x.y");
     expect(propertyAccess.target, isNotNull);
     expect(propertyAccess.operator, isNotNull);
+    expect(propertyAccess.operator.type, TokenType.PERIOD);
     expect(propertyAccess.propertyName, isNotNull);
   }
 
@@ -4817,6 +4996,15 @@
     expect(expression.rightBracket, isNotNull);
   }
 
+  void test_parseAssignableExpression_identifier_question_dot() {
+    _enableNullAwareOperators = true;
+    PropertyAccess propertyAccess =
+        parse("parseAssignableExpression", <Object>[false], "x?.y");
+    expect(propertyAccess.target, isNotNull);
+    expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
   void test_parseAssignableExpression_super_dot() {
     PropertyAccess propertyAccess =
         parse("parseAssignableExpression", <Object>[false], "super.y");
@@ -4839,7 +5027,7 @@
   void test_parseAssignableSelector_dot() {
     PropertyAccess selector =
         parse("parseAssignableSelector", <Object>[null, true], ".x");
-    expect(selector.operator, isNotNull);
+    expect(selector.operator.type, TokenType.PERIOD);
     expect(selector.propertyName, isNotNull);
   }
 
@@ -4859,6 +5047,14 @@
     expect(selector, isNotNull);
   }
 
+  void test_parseAssignableSelector_question_dot() {
+    _enableNullAwareOperators = true;
+    PropertyAccess selector =
+        parse("parseAssignableSelector", <Object>[null, true], "?.x");
+    expect(selector.operator.type, TokenType.QUESTION_PERIOD);
+    expect(selector.propertyName, isNotNull);
+  }
+
   void test_parseAwaitExpression() {
     AwaitExpression expression = parse4("parseAwaitExpression", "await x;");
     expect(expression.awaitKeyword, isNotNull);
@@ -4996,7 +5192,7 @@
     MethodInvocation section = parse4("parseCascadeSection", "..a(b).c(d)");
     EngineTestCase.assertInstanceOf(
         (obj) => obj is MethodInvocation, MethodInvocation, section.target);
-    expect(section.period, isNotNull);
+    expect(section.operator, isNotNull);
     expect(section.methodName, isNotNull);
     expect(section.argumentList, isNotNull);
     expect(section.argumentList.arguments, hasLength(1));
@@ -5037,7 +5233,7 @@
   void test_parseCascadeSection_pa() {
     MethodInvocation section = parse4("parseCascadeSection", "..a(b)");
     expect(section.target, isNull);
-    expect(section.period, isNotNull);
+    expect(section.operator, isNotNull);
     expect(section.methodName, isNotNull);
     expect(section.argumentList, isNotNull);
     expect(section.argumentList.arguments, hasLength(1));
@@ -5365,6 +5561,7 @@
     expect(method.name, isNotNull);
     expect(method.operatorKeyword, isNull);
     expect(method.body, isNotNull);
+    expect(method.parameters, isNull);
   }
 
   void test_parseClassMember_method_external() {
@@ -7154,6 +7351,46 @@
     expect(parameterList.rightParenthesis, isNotNull);
   }
 
+  void test_parseFormalParameterList_prefixedType() {
+    FormalParameterList parameterList =
+        parse4("parseFormalParameterList", "(io.File f)");
+    expect(parameterList.leftParenthesis, isNotNull);
+    expect(parameterList.leftDelimiter, isNull);
+    expect(parameterList.parameters, hasLength(1));
+    expect(parameterList.parameters[0].toSource(), 'io.File f');
+    expect(parameterList.rightDelimiter, isNull);
+    expect(parameterList.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_prefixedType_partial() {
+    FormalParameterList parameterList = parse4("parseFormalParameterList",
+        "(io.)", [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(parameterList.leftParenthesis, isNotNull);
+    expect(parameterList.leftDelimiter, isNull);
+    expect(parameterList.parameters, hasLength(1));
+    expect(parameterList.parameters[0].toSource(), 'io. ');
+    expect(parameterList.rightDelimiter, isNull);
+    expect(parameterList.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_prefixedType_partial2() {
+    FormalParameterList parameterList = parse4("parseFormalParameterList",
+        "(io.,a)", [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(parameterList.leftParenthesis, isNotNull);
+    expect(parameterList.leftDelimiter, isNull);
+    expect(parameterList.parameters, hasLength(2));
+    expect(parameterList.parameters[0].toSource(), 'io. ');
+    expect(parameterList.parameters[1].toSource(), 'a');
+    expect(parameterList.rightDelimiter, isNull);
+    expect(parameterList.rightParenthesis, isNotNull);
+  }
+
   void test_parseForStatement_each_await() {
     ForEachStatement statement =
         parse4("parseForStatement", "await for (element in list) {}");
@@ -8435,6 +8672,16 @@
   void test_parsePostfixExpression_none_methodInvocation() {
     MethodInvocation expression = parse4("parsePostfixExpression", "a.m()");
     expect(expression.target, isNotNull);
+    expect(expression.operator.type, TokenType.PERIOD);
+    expect(expression.methodName, isNotNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void test_parsePostfixExpression_none_methodInvocation_question_dot() {
+    _enableNullAwareOperators = true;
+    MethodInvocation expression = parse4('parsePostfixExpression', 'a?.m()');
+    expect(expression.target, isNotNull);
+    expect(expression.operator.type, TokenType.QUESTION_PERIOD);
     expect(expression.methodName, isNotNull);
     expect(expression.argumentList, isNotNull);
   }
@@ -8822,6 +9069,23 @@
     expect((secondString as SimpleStringLiteral).value, "b");
   }
 
+  void test_parseStringLiteral_endsWithInterpolation() {
+    StringLiteral literal = parse4('parseStringLiteral', r"'x$y'");
+    expect(literal, new isInstanceOf<StringInterpolation>());
+    StringInterpolation interpolation = literal;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], new isInstanceOf<InterpolationString>());
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, 'x');
+    expect(
+        interpolation.elements[1], new isInstanceOf<InterpolationExpression>());
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, new isInstanceOf<SimpleIdentifier>());
+    expect(interpolation.elements[2], new isInstanceOf<InterpolationString>());
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, '');
+  }
+
   void test_parseStringLiteral_interpolated() {
     StringInterpolation literal =
         parse4("parseStringLiteral", "'a \${b} c \$this d'");
@@ -8834,12 +9098,173 @@
     expect(elements[4] is InterpolationString, isTrue);
   }
 
+  void test_parseStringLiteral_multiline_encodedSpace() {
+    SimpleStringLiteral literal =
+        parse4("parseStringLiteral", "'''\\x20\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, " \na");
+  }
+
+  void test_parseStringLiteral_multiline_endsWithInterpolation() {
+    StringLiteral literal = parse4('parseStringLiteral', r"'''x$y'''");
+    expect(literal, new isInstanceOf<StringInterpolation>());
+    StringInterpolation interpolation = literal;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], new isInstanceOf<InterpolationString>());
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, 'x');
+    expect(
+        interpolation.elements[1], new isInstanceOf<InterpolationExpression>());
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, new isInstanceOf<SimpleIdentifier>());
+    expect(interpolation.elements[2], new isInstanceOf<InterpolationString>());
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, '');
+  }
+
+  void test_parseStringLiteral_multiline_escapedBackslash() {
+    SimpleStringLiteral literal = parse4("parseStringLiteral", "'''\\\\\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "\\\na");
+  }
+
+  void test_parseStringLiteral_multiline_escapedBackslash_raw() {
+    SimpleStringLiteral literal =
+        parse4("parseStringLiteral", "r'''\\\\\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "\\\\\na");
+  }
+
+  void test_parseStringLiteral_multiline_escapedEolMarker() {
+    SimpleStringLiteral literal = parse4("parseStringLiteral", "'''\\\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_escapedEolMarker_raw() {
+    SimpleStringLiteral literal = parse4("parseStringLiteral", "r'''\\\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_escapedSpaceAndEolMarker() {
+    SimpleStringLiteral literal =
+        parse4("parseStringLiteral", "'''\\ \\\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_escapedSpaceAndEolMarker_raw() {
+    SimpleStringLiteral literal =
+        parse4("parseStringLiteral", "r'''\\ \\\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_escapedTab() {
+    SimpleStringLiteral literal = parse4("parseStringLiteral", "'''\\t\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "\t\na");
+  }
+
+  void test_parseStringLiteral_multiline_escapedTab_raw() {
+    SimpleStringLiteral literal = parse4("parseStringLiteral", "r'''\\t\na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "\\t\na");
+  }
+
+  void test_parseStringLiteral_multiline_quoteAfterInterpolation() {
+    StringLiteral literal = parse4('parseStringLiteral', r"""'''$x'y'''""");
+    expect(literal, new isInstanceOf<StringInterpolation>());
+    StringInterpolation interpolation = literal;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], new isInstanceOf<InterpolationString>());
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, '');
+    expect(
+        interpolation.elements[1], new isInstanceOf<InterpolationExpression>());
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, new isInstanceOf<SimpleIdentifier>());
+    expect(interpolation.elements[2], new isInstanceOf<InterpolationString>());
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, "'y");
+  }
+
+  void test_parseStringLiteral_multiline_startsWithInterpolation() {
+    StringLiteral literal = parse4('parseStringLiteral', r"'''${x}y'''");
+    expect(literal, new isInstanceOf<StringInterpolation>());
+    StringInterpolation interpolation = literal;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], new isInstanceOf<InterpolationString>());
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, '');
+    expect(
+        interpolation.elements[1], new isInstanceOf<InterpolationExpression>());
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, new isInstanceOf<SimpleIdentifier>());
+    expect(interpolation.elements[2], new isInstanceOf<InterpolationString>());
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, 'y');
+  }
+
+  void test_parseStringLiteral_multiline_twoSpaces() {
+    SimpleStringLiteral literal = parse4("parseStringLiteral", "'''  \na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_twoSpaces_raw() {
+    SimpleStringLiteral literal = parse4("parseStringLiteral", "r'''  \na'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_untrimmed() {
+    SimpleStringLiteral literal = parse4("parseStringLiteral", "''' a\nb'''");
+    expect(literal.literal, isNotNull);
+    expect(literal.value, " a\nb");
+  }
+
+  void test_parseStringLiteral_quoteAfterInterpolation() {
+    StringLiteral literal = parse4('parseStringLiteral', r"""'$x"'""");
+    expect(literal, new isInstanceOf<StringInterpolation>());
+    StringInterpolation interpolation = literal;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], new isInstanceOf<InterpolationString>());
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, '');
+    expect(
+        interpolation.elements[1], new isInstanceOf<InterpolationExpression>());
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, new isInstanceOf<SimpleIdentifier>());
+    expect(interpolation.elements[2], new isInstanceOf<InterpolationString>());
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, '"');
+  }
+
   void test_parseStringLiteral_single() {
     SimpleStringLiteral literal = parse4("parseStringLiteral", "'a'");
     expect(literal.literal, isNotNull);
     expect(literal.value, "a");
   }
 
+  void test_parseStringLiteral_startsWithInterpolation() {
+    StringLiteral literal = parse4('parseStringLiteral', r"'${x}y'");
+    expect(literal, new isInstanceOf<StringInterpolation>());
+    StringInterpolation interpolation = literal;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], new isInstanceOf<InterpolationString>());
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, '');
+    expect(
+        interpolation.elements[1], new isInstanceOf<InterpolationExpression>());
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, new isInstanceOf<SimpleIdentifier>());
+    expect(interpolation.elements[2], new isInstanceOf<InterpolationString>());
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, 'y');
+  }
+
   void test_parseSuperConstructorInvocation_named() {
     SuperConstructorInvocation invocation =
         parse4("parseSuperConstructorInvocation", "super.a()");
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 539bf0d..7b173af 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -365,6 +365,8 @@
         currentOptions.dart2jsHint != options.dart2jsHint ||
         (currentOptions.hint && !options.hint) ||
         currentOptions.preserveComments != options.preserveComments ||
+        currentOptions.enableNullAwareOperators !=
+            options.enableNullAwareOperators ||
         currentOptions.enableStrictCallChecks != options.enableStrictCallChecks;
     if (needsRecompute) {
       fail(
@@ -1857,7 +1859,7 @@
     library.libraryElement = _definingLibrary;
     _visitor = new ResolverVisitor.con1(library, source, _typeProvider);
     try {
-      return _visitor.elementResolver_J2DAccessor as ElementResolver;
+      return _visitor.elementResolver;
     } catch (exception) {
       throw new IllegalArgumentException(
           "Could not create resolver", exception);
@@ -1916,16 +1918,16 @@
    */
   void _resolveInClass(AstNode node, ClassElement enclosingClass) {
     try {
-      Scope outerScope = _visitor.nameScope_J2DAccessor as Scope;
+      Scope outerScope = _visitor.nameScope;
       try {
         _visitor.enclosingClass = enclosingClass;
         EnclosedScope innerScope = new ClassScope(
             new TypeParameterScope(outerScope, enclosingClass), enclosingClass);
-        _visitor.nameScope_J2DAccessor = innerScope;
+        _visitor.nameScope = innerScope;
         node.accept(_resolver);
       } finally {
         _visitor.enclosingClass = null;
-        _visitor.nameScope_J2DAccessor = outerScope;
+        _visitor.nameScope = outerScope;
       }
     } catch (exception) {
       throw new IllegalArgumentException("Could not resolve node", exception);
@@ -1958,7 +1960,7 @@
    */
   void _resolveNode(AstNode node, [List<Element> definedElements]) {
     try {
-      Scope outerScope = _visitor.nameScope_J2DAccessor as Scope;
+      Scope outerScope = _visitor.nameScope;
       try {
         EnclosedScope innerScope = new EnclosedScope(outerScope);
         if (definedElements != null) {
@@ -1966,10 +1968,10 @@
             innerScope.define(element);
           }
         }
-        _visitor.nameScope_J2DAccessor = innerScope;
+        _visitor.nameScope = innerScope;
         node.accept(_resolver);
       } finally {
-        _visitor.nameScope_J2DAccessor = outerScope;
+        _visitor.nameScope = outerScope;
       }
     } catch (exception) {
       throw new IllegalArgumentException("Could not resolve node", exception);
@@ -1987,7 +1989,7 @@
   void _resolveStatement(
       Statement statement, LabelElementImpl labelElement, AstNode labelTarget) {
     try {
-      LabelScope outerScope = _visitor.labelScope_J2DAccessor as LabelScope;
+      LabelScope outerScope = _visitor.labelScope;
       try {
         LabelScope innerScope;
         if (labelElement == null) {
@@ -1996,10 +1998,10 @@
           innerScope = new LabelScope(
               outerScope, labelElement.name, labelTarget, labelElement);
         }
-        _visitor.labelScope_J2DAccessor = innerScope;
+        _visitor.labelScope = innerScope;
         statement.accept(_resolver);
       } finally {
-        _visitor.labelScope_J2DAccessor = outerScope;
+        _visitor.labelScope = outerScope;
       }
     } catch (exception) {
       throw new IllegalArgumentException("Could not resolve node", exception);
@@ -2207,29 +2209,6 @@
     verify([source]);
   }
 
-  void test_argumentTypeNotAssignable_unionTypeMethodMerge() {
-    enableUnionTypes(false);
-    Source source = addSource(r'''
-class A {
-  int m(int x) => 0;
-}
-class B {
-  String m(String x) => '0';
-}
-f(A a, B b) {
-  var ab;
-  if (0 < 1) {
-    ab = a;
-  } else {
-    ab = b;
-  }
-  ab.m(0.5);
-}''');
-    resolve(source);
-    assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
-    verify([source]);
-  }
-
   void test_deadCode_deadBlock_conditionalElse() {
     Source source = addSource(r'''
 f() {
@@ -2658,27 +2637,6 @@
     verify([source]);
   }
 
-  void test_deprecatedAnnotationUse_deprecatedMethodCalledOnUnionType() {
-    enableUnionTypes(false);
-    Source source = addSource(r'''
-class A {
-  @deprecated f() => 0;
-}
-class B extends A {}
-main(A a, B b) {
-  var x;
-  if (0 < 1) {
-    x = a;
-  } else {
-    x = b;
-  }
-  x.f(); // Here [x] has type [{A,B}] but we still want the deprecation warning.
-}''');
-    resolve(source);
-    assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
-    verify([source]);
-  }
-
   void test_deprecatedAnnotationUse_export() {
     Source source = addSource("export 'deprecated_library.dart';");
     addNamedSource("/deprecated_library.dart", r'''
@@ -3137,28 +3095,6 @@
     assertErrors(source, [HintCode.UNDEFINED_METHOD]);
   }
 
-  void test_undefinedMethod_unionType_noSuchMethod() {
-    enableUnionTypes(false);
-    Source source = addSource(r'''
-class A {
-  int m(int x) => 0;
-}
-class B {
-  String m() => '0';
-}
-f(A a, B b) {
-  var ab;
-  if (0 < 1) {
-    ab = a;
-  } else {
-    ab = b;
-  }
-  ab.n();
-}''');
-    resolve(source);
-    assertErrors(source, [HintCode.UNDEFINED_METHOD]);
-  }
-
   void test_undefinedOperator_binaryExpression() {
     Source source = addSource(r'''
 class A {}
@@ -3325,50 +3261,6 @@
     verify([source]);
   }
 
-  void test_unusedElement_class_inClassMember() {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {
-  static staticMethod() {
-    new _A();
-  }
-  instanceMethod() {
-    new _A();
-  }
-}
-''');
-    resolve(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  void test_unusedElement_class_inConstructorName() {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {
-  _A() {}
-  _A.named() {}
-}
-''');
-    resolve(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  void test_unusedElement_class_isExpression() {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {}
-main(p) {
-  if (p is _A) {
-  }
-}
-''');
-    resolve(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
   void test_unusedElement_class_isUsed_extends() {
     enableUnusedElement = true;
     Source source = addSource(r'''
@@ -3431,7 +3323,51 @@
     verify([source]);
   }
 
-  void test_unusedElement_class_noReference() {
+  void test_unusedElement_class_notUsed_inClassMember() {
+    enableUnusedElement = true;
+    Source source = addSource(r'''
+class _A {
+  static staticMethod() {
+    new _A();
+  }
+  instanceMethod() {
+    new _A();
+  }
+}
+''');
+    resolve(source);
+    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
+    verify([source]);
+  }
+
+  void test_unusedElement_class_notUsed_inConstructorName() {
+    enableUnusedElement = true;
+    Source source = addSource(r'''
+class _A {
+  _A() {}
+  _A.named() {}
+}
+''');
+    resolve(source);
+    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
+    verify([source]);
+  }
+
+  void test_unusedElement_class_notUsed_isExpression() {
+    enableUnusedElement = true;
+    Source source = addSource(r'''
+class _A {}
+main(p) {
+  if (p is _A) {
+  }
+}
+''');
+    resolve(source);
+    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
+    verify([source]);
+  }
+
+  void test_unusedElement_class_notUsed_noReference() {
     enableUnusedElement = true;
     Source source = addSource(r'''
 class _A {}
@@ -3442,7 +3378,7 @@
     verify([source]);
   }
 
-  void test_unusedElement_class_variableDeclaration() {
+  void test_unusedElement_class_notUsed_variableDeclaration() {
     enableUnusedElement = true;
     Source source = addSource(r'''
 class _A {}
@@ -3457,6 +3393,29 @@
     verify([source]);
   }
 
+  void test_unusedElement_enum_isUsed_fieldReference() {
+    enableUnusedElement = true;
+    Source source = addSource(r'''
+enum _MyEnum {A, B, C}
+main() {
+  print(_MyEnum.B);
+}''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_unusedElement_enum_notUsed_noReference() {
+    enableUnusedElement = true;
+    Source source = addSource(r'''
+enum _MyEnum {A, B, C}
+main() {
+}''');
+    resolve(source);
+    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
+    verify([source]);
+  }
+
   void test_unusedElement_functionLocal_isUsed_closure() {
     enableUnusedElement = true;
     Source source = addSource(r'''
@@ -3570,6 +3529,40 @@
     verify([source]);
   }
 
+  void test_unusedElement_functionTypeAlias_isUsed_reference() {
+    enableUnusedElement = true;
+    Source source = addSource(r'''
+typedef _F(a, b);
+main(_F f) {
+}''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_unusedElement_functionTypeAlias_isUsed_variableDeclaration() {
+    enableUnusedElement = true;
+    Source source = addSource(r'''
+typedef _F(a, b);
+class A {
+  _F f;
+}''');
+    resolve(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_unusedElement_functionTypeAlias_notUsed_noReference() {
+    enableUnusedElement = true;
+    Source source = addSource(r'''
+typedef _F(a, b);
+main() {
+}''');
+    resolve(source);
+    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
+    verify([source]);
+  }
+
   void test_unusedElement_getter_isUsed_invocation_implicitThis() {
     enableUnusedElement = true;
     Source source = addSource(r'''
@@ -4218,6 +4211,21 @@
     verify([source]);
   }
 
+  void test_unusedLocalVariable_inFor_underscore_ignored() {
+    enableUnusedLocalVariable = true;
+    Source source = addSource(r'''
+main() {
+  for (var _ in [1,2,3]) {
+    for (var __ in [4,5,6]) {
+      // do something
+    }
+  }
+}''');
+    resolve(source);
+    assertErrors(source);
+    verify([source]);
+  }
+
   void test_unusedLocalVariable_inFunction() {
     enableUnusedLocalVariable = true;
     Source source = addSource(r'''
@@ -6532,21 +6540,6 @@
     verify([source]);
   }
 
-  void test_issue20904BuggyTypePromotionAtIfJoin_2() {
-    // https://code.google.com/p/dart/issues/detail?id=20904
-    enableUnionTypes(false);
-    Source source = addSource(r'''
-f(var message) {
-  if (message is Function) {
-    message = '';
-  }
-  int s = message;
-}''');
-    resolve(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   void test_issue20904BuggyTypePromotionAtIfJoin_3() {
     // https://code.google.com/p/dart/issues/detail?id=20904
     Source source = addSource(r'''
@@ -7731,16 +7724,6 @@
     return library;
   }
 
-  /**
-   * Enable optionally strict union types for the current test.
-   *
-   * @param strictUnionTypes `true` if union types should be strict.
-   */
-  void enableUnionTypes(bool strictUnionTypes) {
-    AnalysisEngine.instance.enableUnionTypes = true;
-    AnalysisEngine.instance.strictUnionTypes = strictUnionTypes;
-  }
-
   Expression findTopLevelConstantExpression(
           CompilationUnit compilationUnit, String name) =>
       findTopLevelDeclaration(compilationUnit, name).initializer;
@@ -7766,10 +7749,6 @@
    */
   void reset() {
     analysisContext2 = AnalysisContextFactory.contextWithCore();
-    // These defaults are duplicated for the editor in
-    // editor/tools/plugins/com.google.dart.tools.core/.options .
-    AnalysisEngine.instance.enableUnionTypes = false;
-    AnalysisEngine.instance.strictUnionTypes = false;
   }
 
   /**
@@ -9875,6 +9854,24 @@
     _listener.assertNoErrors();
   }
 
+  void test_visitAssignmentExpression_compoundIfNull_differentTypes() {
+    // double d; d ??= 0
+    Expression node = AstFactory.assignmentExpression(
+        _resolvedVariable(_typeProvider.doubleType, 'd'),
+        TokenType.QUESTION_QUESTION_EQ, _resolvedInteger(0));
+    expect(_analyze(node), same(_typeProvider.numType));
+    _listener.assertNoErrors();
+  }
+
+  void test_visitAssignmentExpression_compoundIfNull_sameTypes() {
+    // int i; i ??= 0
+    Expression node = AstFactory.assignmentExpression(
+        _resolvedVariable(_typeProvider.intType, 'i'),
+        TokenType.QUESTION_QUESTION_EQ, _resolvedInteger(0));
+    expect(_analyze(node), same(_typeProvider.intType));
+    _listener.assertNoErrors();
+  }
+
   void test_visitAssignmentExpression_simple() {
     // i = 0
     InterfaceType intType = _typeProvider.intType;
@@ -9916,6 +9913,14 @@
     _listener.assertNoErrors();
   }
 
+  void test_visitBinaryExpression_ifNull() {
+    // 1 ?? 1.5
+    Expression node = AstFactory.binaryExpression(
+        _resolvedInteger(1), TokenType.QUESTION_QUESTION, _resolvedDouble(1.5));
+    expect(_analyze(node), same(_typeProvider.numType));
+    _listener.assertNoErrors();
+  }
+
   void test_visitBinaryExpression_logicalAnd() {
     // false && true
     Expression node = AstFactory.binaryExpression(
@@ -10915,7 +10920,7 @@
     _visitor = new ResolverVisitor.con1(library, source, _typeProvider);
     _visitor.overrideManager.enterScope();
     try {
-      return _visitor.typeAnalyzer_J2DAccessor as StaticTypeAnalyzer;
+      return _visitor.typeAnalyzer;
     } catch (exception) {
       throw new IllegalArgumentException(
           "Could not create analyzer", exception);
@@ -12592,21 +12597,6 @@
     expect(variableName.propagatedType, same(typeA));
   }
 
-  void test_issue20904BuggyTypePromotionAtIfJoin_2() {
-    // https://code.google.com/p/dart/issues/detail?id=20904
-    enableUnionTypes(false);
-    String code = r'''
-f(var message) {
-  if (message is Function) {
-    message = '';
-  }
-  message; // marker
-}''';
-    DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType;
-    expect(typeProvider.stringType == t, isFalse);
-    expect(typeProvider.functionType == t, isFalse);
-  }
-
   void test_issue20904BuggyTypePromotionAtIfJoin_5() {
     // https://code.google.com/p/dart/issues/detail?id=20904
     //
@@ -12749,6 +12739,62 @@
     expect(typeArguments[1], same(typeProvider.dynamicType));
   }
 
+  void test_mergePropagatedTypes_afterIfThen_different() {
+    String code = r'''
+main() {
+  var v = 0;
+  if (v != null) {
+    v = '';
+  }
+  return v;
+}''';
+    {
+      SimpleIdentifier identifier = _findMarkedIdentifier(code, "v;");
+      expect(identifier.propagatedType, null);
+    }
+    {
+      SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = '';");
+      expect(identifier.propagatedType, typeProvider.stringType);
+    }
+  }
+
+  void test_mergePropagatedTypes_afterIfThen_same() {
+    _assertTypeOfMarkedExpression(r'''
+main() {
+  var v = 1;
+  if (v != null) {
+    v = 2;
+  }
+  return v; // marker
+}''', null, typeProvider.intType);
+  }
+
+  void test_mergePropagatedTypes_afterIfThenElse_different() {
+    _assertTypeOfMarkedExpression(r'''
+main() {
+  var v = 1;
+  if (v != null) {
+    v = 2;
+  } else {
+    v = '3';
+  }
+  return v; // marker
+}''', null, null);
+  }
+
+  void test_mergePropagatedTypes_afterIfThenElse_same() {
+    _assertTypeOfMarkedExpression(r'''
+main() {
+  var v = 1;
+  if (v != null) {
+    v = 2;
+  } else {
+    v = 3;
+  }
+  return v; // marker
+}''', null, typeProvider.intType);
+  }
+
   void test_mergePropagatedTypesAtJoinPoint_4() {
     // https://code.google.com/p/dart/issues/detail?id=19929
     _assertTypeOfMarkedExpression(r'''
@@ -12764,34 +12810,6 @@
 }''', null, typeProvider.intType);
   }
 
-  void test_mergePropagatedTypesAtJoinPoint_6() {
-    // https://code.google.com/p/dart/issues/detail?id=19929
-    //
-    // Labeled [break]s are unsafe for the purposes of
-    // [isAbruptTerminationStatement].
-    //
-    // This is tricky: the [break] jumps back above the [if], making
-    // it into a loop of sorts. The [if] type-propagation code assumes
-    // that [break] does not introduce a loop.
-    enableUnionTypes(false);
-    String code = r'''
-f() {
-  var x = 0;
-  var c = false;
-  L: 
-  if (c) {
-  } else {
-    x = '';
-    c = true;
-    break L;
-  }
-  x; // marker
-}''';
-    DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType;
-    expect(typeProvider.intType.isSubtypeOf(t), isTrue);
-    expect(typeProvider.stringType.isSubtypeOf(t), isTrue);
-  }
-
   void test_mutatedOutsideScope() {
     // https://code.google.com/p/dart/issues/detail?id=22732
     Source source = addSource(r'''
@@ -13007,9 +13025,7 @@
     if (expectedStaticType != null) {
       expect(identifier.staticType, expectedStaticType);
     }
-    if (expectedPropagatedType != null) {
-      expect(identifier.propagatedType, expectedPropagatedType);
-    }
+    expect(identifier.propagatedType, expectedPropagatedType);
   }
 
   /**
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index b65bd51..3531847 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -170,6 +170,12 @@
 
 @reflectiveTest
 class ScannerTest {
+  /**
+   * If non-null, this value is used to override the default value of
+   * [Scanner.enableNullAwareOperators] before scanning.
+   */
+  bool _enableNullAwareOperators;
+
   void fail_incomplete_string_interpolation() {
     // https://code.google.com/p/dart/issues/detail?id=18073
     _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9,
@@ -720,6 +726,21 @@
     _assertToken(TokenType.QUESTION, "?");
   }
 
+  void test_question_dot() {
+    _enableNullAwareOperators = true;
+    _assertToken(TokenType.QUESTION_PERIOD, "?.");
+  }
+
+  void test_question_question() {
+    _enableNullAwareOperators = true;
+    _assertToken(TokenType.QUESTION_QUESTION, "??");
+  }
+
+  void test_question_question_eq() {
+    _enableNullAwareOperators = true;
+    _assertToken(TokenType.QUESTION_QUESTION_EQ, "??=");
+  }
+
   void test_scriptTag_withArgs() {
     _assertToken(TokenType.SCRIPT_TAG, "#!/bin/dart -debug");
   }
@@ -1208,6 +1229,9 @@
   Token _scanWithListener(String source, GatheringErrorListener listener) {
     Scanner scanner =
         new Scanner(null, new CharSequenceReader(source), listener);
+    if (_enableNullAwareOperators != null) {
+      scanner.enableNullAwareOperators = _enableNullAwareOperators;
+    }
     Token result = scanner.tokenize();
     listener.setLineInfo(new TestSource(), scanner.lineStarts);
     return result;
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 019c07e..0282d99 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -355,6 +355,21 @@
     verify([source]);
   }
 
+  void test_invalidAssignment_ifNullAssignment() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    Source source = addSource('''
+void f(int i) {
+  double d;
+  d ??= i;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+    verify([source]);
+  }
+
   void test_invalidAssignment_instanceVariable() {
     Source source = addSource(r'''
 class A {
@@ -668,29 +683,6 @@
     verify([source]);
   }
 
-  void test_notEnoughRequiredArguments_mergedUnionTypeMethod() {
-    enableUnionTypes(false);
-    Source source = addSource(r'''
-class A {
-  int m(int x) => 0;
-}
-class B {
-  String m(String x) => '0';
-}
-f(A a, B b) {
-  var ab;
-  if (0 < 1) {
-    ab = a;
-  } else {
-    ab = b;
-  }
-  ab.m();
-}''');
-    resolve(source);
-    assertErrors(source, [StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
-    verify([source]);
-  }
-
   void test_returnOfInvalidType_async_future_int_mismatches_future_null() {
     Source source = addSource('''
 import 'dart:async';
@@ -1382,6 +1374,22 @@
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
   }
 
+  void test_undefinedGetter_static_conditionalAccess() {
+    // The conditional access operator '?.' cannot be used to access static
+    // fields.
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    Source source = addSource('''
+class A {
+  static var x;
+}
+var a = A?.x;
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
+  }
+
   void test_undefinedGetter_void() {
     Source source = addSource(r'''
 class T {
@@ -1534,6 +1542,22 @@
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
   }
 
+  void test_undefinedMethod_static_conditionalAccess() {
+    // The conditional access operator '?.' cannot be used to access static
+    // methods.
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    Source source = addSource('''
+class A {
+  static void m() {}
+}
+f() { A?.m(); }
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]);
+  }
+
   void test_undefinedOperator_indexBoth() {
     Source source = addSource(r'''
 class A {}
@@ -1610,6 +1634,22 @@
     assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
   }
 
+  void test_undefinedSetter_static_conditionalAccess() {
+    // The conditional access operator '?.' cannot be used to access static
+    // fields.
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableNullAwareOperators = true;
+    resetWithOptions(options);
+    Source source = addSource('''
+class A {
+  static var x;
+}
+f() { A?.x = 1; }
+''');
+    resolve(source);
+    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
+  }
+
   void test_undefinedSetter_void() {
     Source source = addSource(r'''
 class T {
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 0ad381f..6df4785 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -598,6 +598,17 @@
     verify([source]);
   }
 
+  void test_assignmentToClass() {
+    Source source = addSource('''
+class C {}
+main() {
+  C = null;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
+  }
+
   void test_assignmentToConst_instanceVariable() {
     Source source = addSource(r'''
 class A {
@@ -646,6 +657,17 @@
     verify([source]);
   }
 
+  void test_assignmentToEnumType() {
+    Source source = addSource('''
+enum E { e }
+main() {
+  E = null;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
+  }
+
   void test_assignmentToFinal_instanceVariable() {
     Source source = addSource(r'''
 class A {
@@ -825,6 +847,29 @@
     verify([source]);
   }
 
+  void test_assignmentToTypedef() {
+    Source source = addSource('''
+typedef void F();
+main() {
+  F = null;
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
+  }
+
+  void test_assignmentToTypeParameter() {
+    Source source = addSource('''
+class C<T> {
+  f() {
+    T = null;
+  }
+}
+''');
+    resolve(source);
+    assertErrors(source, [StaticWarningCode.ASSIGNMENT_TO_TYPE]);
+  }
+
   void test_caseBlockNotTerminated() {
     Source source = addSource(r'''
 f(int p) {
diff --git a/pkg/analyzer/test/src/mock_sdk.dart b/pkg/analyzer/test/src/mock_sdk.dart
index 6716801..7cadfcc 100644
--- a/pkg/analyzer/test/src/mock_sdk.dart
+++ b/pkg/analyzer/test/src/mock_sdk.dart
@@ -98,6 +98,11 @@
 external bool identical(Object a, Object b);
 
 void print(Object object) {}
+
+class _Override {
+  const _Override();
+}
+const Object override = const _Override();
 ''');
 
   static const _MockSdkLibrary LIB_ASYNC = const _MockSdkLibrary('dart:async',
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index c03b51d..6ddf3d9 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -35,17 +35,23 @@
   runReflectiveTests(BuildCompilationUnitElementTaskTest);
   runReflectiveTests(BuildDirectiveElementsTaskTest);
   runReflectiveTests(BuildEnumMemberElementsTaskTest);
-  runReflectiveTests(BuildExportSourceClosureTaskTest);
+  runReflectiveTests(BuildSourceClosuresTaskTest);
   runReflectiveTests(BuildExportNamespaceTaskTest);
   runReflectiveTests(BuildFunctionTypeAliasesTaskTest);
   runReflectiveTests(BuildLibraryConstructorsTaskTest);
   runReflectiveTests(BuildLibraryElementTaskTest);
   runReflectiveTests(BuildPublicNamespaceTaskTest);
   runReflectiveTests(BuildTypeProviderTaskTest);
+  runReflectiveTests(GatherUsedImportedElementsTaskTest);
+  runReflectiveTests(GatherUsedLocalElementsTaskTest);
+  runReflectiveTests(GenerateHintsTaskTest);
   runReflectiveTests(ParseDartTaskTest);
   runReflectiveTests(ResolveUnitTypeNamesTaskTest);
   runReflectiveTests(ResolveLibraryTypeNamesTaskTest);
+  runReflectiveTests(ResolveReferencesTaskTest);
+  runReflectiveTests(ResolveVariableReferencesTaskTest);
   runReflectiveTests(ScanDartTaskTest);
+  runReflectiveTests(VerifyUnitTaskTest);
 }
 
 @reflectiveTest
@@ -614,48 +620,6 @@
 }
 
 @reflectiveTest
-class BuildExportSourceClosureTaskTest extends _AbstractDartTaskTest {
-  test_perform() {
-    Source sourceA = _newSource('/a.dart', '''
-library lib_a;
-export 'b.dart';
-''');
-    Source sourceB = _newSource('/b.dart', '''
-library lib_b;
-export 'b.dart';
-''');
-    Source sourceC = _newSource('/c.dart', '''
-library lib_c;
-export 'a.dart';
-''');
-    Source sourceD = _newSource('/d.dart', '''
-library lib_d;
-''');
-    // a.dart
-    {
-      _computeResult(sourceA, EXPORT_SOURCE_CLOSURE);
-      expect(task, new isInstanceOf<BuildExportSourceClosureTask>());
-      List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
-      expect(closure, unorderedEquals([sourceA, sourceB]));
-    }
-    // c.dart
-    {
-      _computeResult(sourceC, EXPORT_SOURCE_CLOSURE);
-      expect(task, new isInstanceOf<BuildExportSourceClosureTask>());
-      List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
-      expect(closure, unorderedEquals([sourceA, sourceB, sourceC]));
-    }
-    // d.dart
-    {
-      _computeResult(sourceD, EXPORT_SOURCE_CLOSURE);
-      expect(task, new isInstanceOf<BuildExportSourceClosureTask>());
-      List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
-      expect(closure, unorderedEquals([sourceD]));
-    }
-  }
-}
-
-@reflectiveTest
 class BuildFunctionTypeAliasesTaskTest extends _AbstractDartTaskTest {
   test_perform() {
     Source source = _newSource('/test.dart', '''
@@ -712,9 +676,9 @@
 class C1 = B with M1;
 class C3 = B with M2;
 ''');
-    _computeResult(source, LIBRARY_ELEMENT6);
+    _computeResult(source, LIBRARY_ELEMENT);
     expect(task, new isInstanceOf<BuildLibraryConstructorsTask>());
-    LibraryElement libraryElement = outputs[LIBRARY_ELEMENT6];
+    LibraryElement libraryElement = outputs[LIBRARY_ELEMENT];
     // C1
     {
       ClassElement classElement = libraryElement.getType('C2');
@@ -782,11 +746,10 @@
 part of lib;
 '''
     });
-    expect(outputs, hasLength(5));
+    expect(outputs, hasLength(4));
     // simple outputs
     expect(outputs[BUILD_LIBRARY_ERRORS], isEmpty);
     expect(outputs[IS_LAUNCHABLE], isFalse);
-    expect(outputs[HAS_HTML_IMPORT], isFalse);
     // LibraryElement output
     expect(libraryElement, isNotNull);
     expect(libraryElement.entryPoint, isNull);
@@ -910,15 +873,6 @@
     _assertErrorsWithCodes([CompileTimeErrorCode.PART_OF_NON_PART]);
   }
 
-  test_perform_hasHtmlImport() {
-    _performBuildTask({
-      '/lib.dart': '''
-import 'dart:html';
-'''
-    });
-    expect(outputs[HAS_HTML_IMPORT], isTrue);
-  }
-
   test_perform_isLaunchable_inDefiningUnit() {
     _performBuildTask({
       '/lib.dart': '''
@@ -1057,6 +1011,132 @@
 }
 
 @reflectiveTest
+class BuildSourceClosuresTaskTest extends _AbstractDartTaskTest {
+  test_perform_exportClosure() {
+    Source sourceA = _newSource('/a.dart', '''
+library lib_a;
+export 'b.dart';
+''');
+    Source sourceB = _newSource('/b.dart', '''
+library lib_b;
+export 'c.dart';
+''');
+    Source sourceC = _newSource('/c.dart', '''
+library lib_c;
+export 'a.dart';
+''');
+    Source sourceD = _newSource('/d.dart', '''
+library lib_d;
+''');
+    // a.dart
+    {
+      _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);
+      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);
+      expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+      List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
+      expect(closure, unorderedEquals([sourceD]));
+    }
+  }
+
+  test_perform_importClosure() {
+    Source sourceA = _newSource('/a.dart', '''
+library lib_a;
+import 'b.dart';
+''');
+    Source sourceB = _newSource('/b.dart', '''
+library lib_b;
+import 'c.dart';
+''');
+    Source sourceC = _newSource('/c.dart', '''
+library lib_c;
+import 'a.dart';
+''');
+    Source sourceD = _newSource('/d.dart', '''
+library lib_d;
+''');
+    Source coreSource = context.sourceFactory.resolveUri(null, 'dart:core');
+    // a.dart
+    {
+      _computeResult(sourceA, IMPORT_SOURCE_CLOSURE);
+      expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+      List<Source> closure = outputs[IMPORT_SOURCE_CLOSURE];
+      expect(closure, contains(sourceA));
+      expect(closure, contains(sourceB));
+      expect(closure, contains(sourceC));
+      expect(closure, contains(coreSource));
+    }
+    // c.dart
+    {
+      _computeResult(sourceC, IMPORT_SOURCE_CLOSURE);
+      expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+      List<Source> closure = outputs[IMPORT_SOURCE_CLOSURE];
+      expect(closure, contains(sourceA));
+      expect(closure, contains(sourceB));
+      expect(closure, contains(sourceC));
+      expect(closure, contains(coreSource));
+    }
+    // d.dart
+    {
+      _computeResult(sourceD, IMPORT_SOURCE_CLOSURE);
+      expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+      List<Source> closure = outputs[IMPORT_SOURCE_CLOSURE];
+      expect(closure, contains(sourceD));
+      expect(closure, contains(coreSource));
+    }
+  }
+
+  test_perform_isClient_false() {
+    Source sourceA = _newSource('/a.dart', '''
+library lib_a;
+import 'b.dart';
+''');
+    _newSource('/b.dart', '''
+library lib_b;
+''');
+    _computeResult(sourceA, IS_CLIENT);
+    expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+    expect(outputs[IS_CLIENT], isFalse);
+  }
+
+  test_perform_isClient_true_direct() {
+    Source sourceA = _newSource('/a.dart', '''
+library lib_a;
+import 'dart:html';
+''');
+    _computeResult(sourceA, IS_CLIENT);
+    expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+    expect(outputs[IS_CLIENT], isTrue);
+  }
+
+  test_perform_isClient_true_indirect() {
+    Source sourceA = _newSource('/a.dart', '''
+library lib_a;
+import 'b.dart';
+''');
+    _newSource('/b.dart', '''
+library lib_b;
+import 'dart:html';
+''');
+    _computeResult(sourceA, IS_CLIENT);
+    expect(task, new isInstanceOf<BuildSourceClosuresTask>());
+    expect(outputs[IS_CLIENT], isTrue);
+  }
+}
+
+@reflectiveTest
 class BuildTypeProviderTaskTest extends _AbstractDartTaskTest {
   test_perform() {
     _computeResult(AnalysisContextTarget.request, TYPE_PROVIDER);
@@ -1071,6 +1151,281 @@
 }
 
 @reflectiveTest
+class GatherUsedImportedElementsTaskTest extends _AbstractDartTaskTest {
+  UsedImportedElements usedElements;
+  Set<String> usedElementNames;
+
+  test_perform() {
+    _newSource('/a.dart', r'''
+library lib_a;
+class A {}
+''');
+    _newSource('/b.dart', r'''
+library lib_b;
+class B {}
+''');
+    Source source = _newSource('/test.dart', r'''
+import 'a.dart';
+import 'b.dart';
+main() {
+  new A();
+}''');
+    _computeUsedElements(source);
+    // validate
+    expect(usedElementNames, unorderedEquals(['A']));
+  }
+
+  void _computeUsedElements(Source source) {
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, USED_IMPORTED_ELEMENTS);
+    expect(task, new isInstanceOf<GatherUsedImportedElementsTask>());
+    usedElements = outputs[USED_IMPORTED_ELEMENTS];
+    usedElementNames = usedElements.elements.map((e) => e.name).toSet();
+  }
+}
+
+@reflectiveTest
+class GatherUsedLocalElementsTaskTest extends _AbstractDartTaskTest {
+  UsedLocalElements usedElements;
+  Set<String> usedElementNames;
+
+  test_perform_localVariable() {
+    Source source = _newSource('/test.dart', r'''
+main() {
+  var v1 = 1;
+  var v2 = 2;
+  print(v2);
+}''');
+    _computeUsedElements(source);
+    // validate
+    expect(usedElementNames, unorderedEquals(['v2']));
+  }
+
+  test_perform_method() {
+    Source source = _newSource('/test.dart', r'''
+class A {
+  _m1() {}
+  _m2() {}
+}
+
+main(A a, p) {
+  a._m2();
+  p._m3();
+}
+''');
+    _computeUsedElements(source);
+    // validate
+    expect(usedElementNames, unorderedEquals(['A', 'a', 'p', '_m2']));
+    expect(usedElements.members, unorderedEquals(['_m2', '_m3']));
+  }
+
+  void _computeUsedElements(Source source) {
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, USED_LOCAL_ELEMENTS);
+    expect(task, new isInstanceOf<GatherUsedLocalElementsTask>());
+    usedElements = outputs[USED_LOCAL_ELEMENTS];
+    usedElementNames = usedElements.elements.map((e) => e.name).toSet();
+  }
+}
+
+@reflectiveTest
+class GenerateHintsTaskTest extends _AbstractDartTaskTest {
+  test_perform_bestPractices_missingReturn() {
+    Source source = _newSource('/test.dart', '''
+int main() {
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.MISSING_RETURN]);
+  }
+
+  test_perform_dart2js() {
+    Source source = _newSource('/test.dart', '''
+main(p) {
+  if (p is double) {
+    print('double');
+  }
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.IS_DOUBLE]);
+  }
+
+  test_perform_deadCode() {
+    Source source = _newSource('/test.dart', '''
+main() {
+  if (false) {
+    print('how?');
+  }
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.DEAD_CODE]);
+  }
+
+  test_perform_imports_duplicateImport() {
+    _newSource('/a.dart', r'''
+library lib_a;
+class A {}
+''');
+    Source source = _newSource('/test.dart', r'''
+import 'a.dart';
+import 'a.dart';
+main() {
+  new A();
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.DUPLICATE_IMPORT]);
+  }
+
+  test_perform_imports_unusedImport_one() {
+    _newSource('/a.dart', r'''
+library lib_a;
+class A {}
+''');
+    _newSource('/b.dart', r'''
+library lib_b;
+class B {}
+''');
+    Source source = _newSource('/test.dart', r'''
+import 'a.dart';
+import 'b.dart';
+main() {
+  new A();
+}''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.UNUSED_IMPORT]);
+  }
+
+  test_perform_imports_unusedImport_zero() {
+    _newSource('/a.dart', r'''
+library lib_a;
+class A {}
+''');
+    Source source = _newSource('/test.dart', r'''
+import 'a.dart';
+main() {
+  new A();
+}''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertNoErrors();
+  }
+
+  test_perform_overrideVerifier() {
+    Source source = _newSource('/test.dart', '''
+class A {}
+class B {
+  @override
+  m() {}
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(
+        <ErrorCode>[HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD]);
+  }
+
+  test_perform_todo() {
+    Source source = _newSource('/test.dart', '''
+main() {
+  // TODO(developer) foo bar
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(<ErrorCode>[TodoCode.TODO]);
+  }
+
+  test_perform_unusedLocalElements_class() {
+    Source source = _newSource('/test.dart', '''
+class _A {}
+class _B {}
+main() {
+  new _A();
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_perform_unusedLocalElements_localVariable() {
+    Source source = _newSource('/test.dart', '''
+main() {
+  var v = 42;
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener
+        .assertErrorsWithCodes(<ErrorCode>[HintCode.UNUSED_LOCAL_VARIABLE]);
+  }
+
+  test_perform_unusedLocalElements_method() {
+    Source source = _newSource('/my_lib.dart', '''
+library my_lib;
+part 'my_part.dart';
+class A {
+  _ma() {}
+  _mb() {}
+  _mc() {}
+}
+''');
+    _newSource('/my_part.dart', '''
+part of my_lib;
+
+f(A a) {
+  a._mb();
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, HINTS);
+    expect(task, new isInstanceOf<GenerateHintsTask>());
+    // validate
+    _fillErrorListener(HINTS);
+    errorListener.assertErrorsWithCodes(
+        <ErrorCode>[HintCode.UNUSED_ELEMENT, HintCode.UNUSED_ELEMENT]);
+  }
+}
+
+@reflectiveTest
 class ParseDartTaskTest extends _AbstractDartTaskTest {
   test_buildInputs() {
     Map<String, TaskInput> inputs = ParseDartTask.buildInputs(emptySource);
@@ -1194,6 +1549,99 @@
       expect(classC.supertype.displayName, 'A');
     }
   }
+
+  test_perform_deep() {
+    Source sourceA = _newSource('/a.dart', '''
+library a;
+import 'b.dart';
+class A extends B {}
+''');
+    _newSource('/b.dart', '''
+library b;
+import 'c.dart';
+part 'b2.dart';
+class B extends B2 {}
+''');
+    _newSource('/b2.dart', '''
+part of b;
+class B2 extends C {}
+''');
+    _newSource('/c.dart', '''
+library c;
+class C {}
+''');
+    _computeResult(sourceA, LIBRARY_ELEMENT5);
+    expect(task, new isInstanceOf<ResolveLibraryTypeNamesTask>());
+    // validate
+    LibraryElement library = outputs[LIBRARY_ELEMENT5];
+    {
+      ClassElement clazz = library.getType('A');
+      expect(clazz.displayName, 'A');
+      clazz = clazz.supertype.element;
+      expect(clazz.displayName, 'B');
+      clazz = clazz.supertype.element;
+      expect(clazz.displayName, 'B2');
+      clazz = clazz.supertype.element;
+      expect(clazz.displayName, 'C');
+      clazz = clazz.supertype.element;
+      expect(clazz.displayName, 'Object');
+      expect(clazz.supertype, isNull);
+    }
+  }
+}
+
+@reflectiveTest
+class ResolveReferencesTaskTest extends _AbstractDartTaskTest {
+  test_perform() {
+    Source source = _newSource('/test.dart', '''
+class A {
+  m() {}
+}
+main(A a) {
+  a.m();
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    // prepare unit and "a.m()" invocation
+    CompilationUnit unit;
+    MethodInvocation invocation;
+    {
+      _computeResult(target, RESOLVED_UNIT1);
+      unit = outputs[RESOLVED_UNIT1];
+      // walk the AST
+      FunctionDeclaration function = unit.declarations[1];
+      BlockFunctionBody body = function.functionExpression.body;
+      ExpressionStatement statement = body.block.statements[0];
+      invocation = statement.expression;
+      // not resolved yet
+      expect(invocation.methodName.staticElement, isNull);
+    }
+    // fully resolve
+    {
+      _computeResult(target, RESOLVED_UNIT);
+      expect(task, new isInstanceOf<ResolveReferencesTask>());
+      expect(outputs[RESOLVED_UNIT], same(outputs[RESOLVED_UNIT]));
+      // a.m() is resolved now
+      expect(invocation.methodName.staticElement, isNotNull);
+    }
+  }
+
+  test_perform_errors() {
+    Source source = _newSource('/test.dart', '''
+class A {
+}
+main(A a) {
+  a.unknownMethod();
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, RESOLVED_UNIT);
+    expect(task, new isInstanceOf<ResolveReferencesTask>());
+    // validate
+    _fillErrorListener(RESOLVE_REFERENCES_ERRORS);
+    errorListener.assertErrorsWithCodes(
+        <ErrorCode>[StaticTypeWarningCode.UNDEFINED_METHOD]);
+  }
 }
 
 @reflectiveTest
@@ -1240,6 +1688,69 @@
 }
 
 @reflectiveTest
+class ResolveVariableReferencesTaskTest extends _AbstractDartTaskTest {
+  /**
+   * Verify that the mutated states of the given [variable] correspond to the
+   * [mutatedInClosure] and [mutatedInScope] matchers.
+   */
+  void expectMutated(VariableElement variable, Matcher mutatedInClosure,
+      Matcher mutatedInScope) {
+    expect(variable.isPotentiallyMutatedInClosure, mutatedInClosure);
+    expect(variable.isPotentiallyMutatedInScope, mutatedInScope);
+  }
+
+  test_perform_local() {
+    Source source = _newSource('/test.dart', '''
+main() {
+  var v1 = 1;
+  var v2 = 1;
+  var v3 = 1;
+  var v4 = 1;
+  v2 = 2;
+  v4 = 2;
+  localFunction() {
+    v3 = 3;
+    v4 = 3;
+  }
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, RESOLVED_UNIT5);
+    expect(task, new isInstanceOf<ResolveVariableReferencesTask>());
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT5];
+    FunctionElement main = unit.element.functions[0];
+    expectMutated(main.localVariables[0], isFalse, isFalse);
+    expectMutated(main.localVariables[1], isFalse, isTrue);
+    expectMutated(main.localVariables[2], isTrue, isTrue);
+    expectMutated(main.localVariables[3], isTrue, isTrue);
+  }
+
+  test_perform_parameter() {
+    Source source = _newSource('/test.dart', '''
+main(p1, p2, p3, p4) {
+  p2 = 2;
+  p4 = 2;
+  localFunction() {
+    p3 = 3;
+    p4 = 3;
+  }
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, RESOLVED_UNIT5);
+    expect(task, new isInstanceOf<ResolveVariableReferencesTask>());
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT5];
+    FunctionElement main = unit.element.functions[0];
+    expectMutated(main.parameters[0], isFalse, isFalse);
+    expectMutated(main.parameters[1], isFalse, isTrue);
+    expectMutated(main.parameters[2], isTrue, isTrue);
+    expectMutated(main.parameters[3], isTrue, isTrue);
+  }
+}
+
+@reflectiveTest
 class ScanDartTaskTest extends _AbstractDartTaskTest {
   test_buildInputs() {
     Map<String, TaskInput> inputs = ScanDartTask.buildInputs(emptySource);
@@ -1294,6 +1805,26 @@
   }
 }
 
+@reflectiveTest
+class VerifyUnitTaskTest extends _AbstractDartTaskTest {
+  test_perform_verifyError() {
+    Source source = _newSource('/test.dart', '''
+main() {
+  if (42) {
+    print('Not bool!');
+  }
+}
+''');
+    LibraryUnitTarget target = new LibraryUnitTarget(source, source);
+    _computeResult(target, VERIFY_ERRORS);
+    expect(task, new isInstanceOf<VerifyUnitTask>());
+    // validate
+    _fillErrorListener(VERIFY_ERRORS);
+    errorListener.assertErrorsWithCodes(
+        <ErrorCode>[StaticTypeWarningCode.NON_BOOL_CONDITION]);
+  }
+}
+
 class _AbstractDartTaskTest extends EngineTestCase {
   MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
   Source emptySource;
@@ -1330,13 +1861,19 @@
     taskManager.addTaskDescriptor(BuildLibraryElementTask.DESCRIPTOR);
     taskManager.addTaskDescriptor(BuildPublicNamespaceTask.DESCRIPTOR);
     taskManager.addTaskDescriptor(BuildDirectiveElementsTask.DESCRIPTOR);
-    taskManager.addTaskDescriptor(BuildExportSourceClosureTask.DESCRIPTOR);
+    taskManager.addTaskDescriptor(BuildSourceClosuresTask.DESCRIPTOR);
     taskManager.addTaskDescriptor(BuildExportNamespaceTask.DESCRIPTOR);
-    taskManager.addTaskDescriptor(BuildTypeProviderTask.DESCRIPTOR);
     taskManager.addTaskDescriptor(BuildEnumMemberElementsTask.DESCRIPTOR);
     taskManager.addTaskDescriptor(BuildFunctionTypeAliasesTask.DESCRIPTOR);
+    taskManager.addTaskDescriptor(BuildTypeProviderTask.DESCRIPTOR);
+    taskManager.addTaskDescriptor(GatherUsedImportedElementsTask.DESCRIPTOR);
+    taskManager.addTaskDescriptor(GatherUsedLocalElementsTask.DESCRIPTOR);
+    taskManager.addTaskDescriptor(GenerateHintsTask.DESCRIPTOR);
     taskManager.addTaskDescriptor(ResolveUnitTypeNamesTask.DESCRIPTOR);
     taskManager.addTaskDescriptor(ResolveLibraryTypeNamesTask.DESCRIPTOR);
+    taskManager.addTaskDescriptor(ResolveReferencesTask.DESCRIPTOR);
+    taskManager.addTaskDescriptor(ResolveVariableReferencesTask.DESCRIPTOR);
+    taskManager.addTaskDescriptor(VerifyUnitTask.DESCRIPTOR);
     // prepare AnalysisDriver
     analysisDriver = new AnalysisDriver(taskManager, context);
   }
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index 17e55db..093a91f 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -260,6 +260,35 @@
     expect(driver.performAnalysisTask(), false);
   }
 
+  test_performAnalysisTask_infiniteLoop() {
+    AnalysisTarget target = new TestSource();
+    ResultDescriptor resultA = new ResultDescriptor('resultA', -1);
+    ResultDescriptor resultB = new ResultDescriptor('resultB', -2);
+    // configure tasks
+    TestAnalysisTask task1;
+    TestAnalysisTask task2;
+    TaskDescriptor descriptor1 = new TaskDescriptor(
+        'task1', (context, target) => task1, (target) => {
+      'inputB': new SimpleTaskInput<int>(target, resultB)
+    }, [resultA]);
+    TaskDescriptor descriptor2 = new TaskDescriptor('task2',
+        (context, target) => task2, (target) => {
+      'inputA': new SimpleTaskInput<int>(target, resultA)
+    }, [resultB]);
+    task1 = new TestAnalysisTask(context, target, descriptor: descriptor1);
+    task2 = new TestAnalysisTask(context, target, descriptor: descriptor2);
+    manager.addTaskDescriptor(descriptor1);
+    manager.addTaskDescriptor(descriptor2);
+    context.explicitTargets.add(target);
+    manager.addGeneralResult(resultB);
+    // prepare work order
+    expect(driver.performAnalysisTask(), true);
+    expect(driver.performAnalysisTask(), true);
+    CaughtException exception = context.getCacheEntry(target).exception;
+    expect(exception, isNotNull);
+    expect(exception.exception, new isInstanceOf<InfiniteTaskLoopException>());
+  }
+
   test_performWorkItem_exceptionInTask() {
     AnalysisTarget target = new TestSource();
     ResultDescriptor result = new ResultDescriptor('result', null);
@@ -545,6 +574,10 @@
       baseContext.refactoringUnsafeSources;
 
   @override
+  LibraryResolverFactory get libraryResolverFactory =>
+      baseContext.libraryResolverFactory;
+
+  @override
   ResolverVisitorFactory get resolverVisitorFactory =>
       baseContext.resolverVisitorFactory;
 
diff --git a/pkg/analyzer/test/src/task/general_test.dart b/pkg/analyzer/test/src/task/general_test.dart
index 664a2d6..a043c84 100644
--- a/pkg/analyzer/test/src/task/general_test.dart
+++ b/pkg/analyzer/test/src/task/general_test.dart
@@ -66,6 +66,16 @@
     expect(task.outputs[CONTENT], 'foo');
     expect(task.outputs[MODIFICATION_TIME], 42);
   }
+
+  void test_perform_exception() {
+    AnalysisContext context = new _MockContext();
+    Source target = new TestSource();
+    GetContentTask task = new GetContentTask(context, target);
+    when(context.getContents(target)).thenThrow('My exception!');
+    task.perform();
+    expect(task.caughtException, isNotNull);
+    expect(task.outputs, isEmpty);
+  }
 }
 
 class _MockContext extends TypedMock implements AnalysisContext {
diff --git a/pkg/analyzer2dart/lib/src/cps_generator.dart b/pkg/analyzer2dart/lib/src/cps_generator.dart
index fbb0ee0..2360c16 100644
--- a/pkg/analyzer2dart/lib/src/cps_generator.dart
+++ b/pkg/analyzer2dart/lib/src/cps_generator.dart
@@ -55,8 +55,7 @@
   }

 

   @override

-  ir.ExecutableDefinition visitConstructorElement(

-      analyzer.ConstructorElement element) {

+  ir.RootNode visitConstructorElement(analyzer.ConstructorElement element) {

     CpsGeneratingVisitor visitor = new CpsGeneratingVisitor(converter, element);

     if (!element.isFactory) {

       ConstructorDeclaration constructorDeclaration = node;

@@ -96,8 +95,8 @@
     return withBuilder(

         new DartIrBuilder(DART_CONSTANT_SYSTEM,

                           element,

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

-                          new NullCapturedVariables()),

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

+                          new Set<dart2js.Local>()),

         () {

       irBuilder.buildFunctionHeader(

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

@@ -115,8 +114,8 @@
     return withBuilder(

         new DartIrBuilder(DART_CONSTANT_SYSTEM,

                           element,

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

-                          new NullCapturedVariables()),

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

+                          new Set<dart2js.Local>()),

         () {

       irBuilder.buildFieldInitializerHeader();

       ir.Primitive initializer = build(node.initializer);

@@ -130,8 +129,8 @@
     return withBuilder(

         new DartIrBuilder(DART_CONSTANT_SYSTEM,

                           element,

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

-                          new NullCapturedVariables()),

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

+                          new Set<dart2js.Local>()),

         () {

       irBuilder.buildFunctionHeader(

           function.parameters.map(converter.convertElement));

@@ -586,7 +585,3 @@
         catchClauseInfos: catchClauseInfos);

   }

 }

-

-class NullCapturedVariables extends DartCapturedVariables {

-  NullCapturedVariables() : super(null);

-}

diff --git a/pkg/analyzer2dart/lib/src/modely.dart b/pkg/analyzer2dart/lib/src/modely.dart
index 493b58d..e69d5f0 100644
--- a/pkg/analyzer2dart/lib/src/modely.dart
+++ b/pkg/analyzer2dart/lib/src/modely.dart
@@ -169,9 +169,6 @@
   }
 
   @override
-  void setFixedBackendName(String name) => unsupported('setFixedBackendName');
-
-  @override
   void setNative(String name) => unsupported('setNative');
 
   String toString() => '$kind($name)';
@@ -723,7 +720,8 @@
     with AnalyzableElementY,
          AstElementY,
          TopLevelElementMixin,
-         VariableElementMixin
+         VariableElementMixin,
+         MemberElementMixin
     implements dart2js.FieldElement {
 
   analyzer.TopLevelVariableElement get element => super.element;
@@ -813,7 +811,8 @@
     with AnalyzableElementY,
          AstElementY,
          FunctionElementMixin,
-         ClassMemberMixin
+         ClassMemberMixin,
+         MemberElementMixin
     implements dart2js.ConstructorElement {
 
   analyzer.ConstructorElement get element => super.element;
@@ -830,6 +829,10 @@
   @override
   bool get isRedirectingFactory => false;
 
+  // TODO(johnniwinther): Support redirecting generative constructors.
+  @override
+  bool get isRedirectingGenerative => false;
+
   @override
   bool get isStatic => false;
 
@@ -860,7 +863,8 @@
     with AnalyzableElementY,
          AstElementY,
          FunctionElementMixin,
-         ClassMemberMixin
+         ClassMemberMixin,
+         MemberElementMixin
     implements dart2js.MethodElement {
 
   analyzer.MethodElement get element => super.element;
@@ -887,3 +891,7 @@
   @override
   get nestedClosures => unsupported('nestedClosures');
 }
+
+abstract class MemberElementMixin implements dart2js.MemberElement {
+  dart2js.Name get memberName => new dart2js.Name(name, library);
+}
\ No newline at end of file
diff --git a/pkg/analyzer2dart/test/end2end_data.dart b/pkg/analyzer2dart/test/end2end_data.dart
index b1cb1db..2ad4598 100644
--- a/pkg/analyzer2dart/test/end2end_data.dart
+++ b/pkg/analyzer2dart/test/end2end_data.dart
@@ -256,6 +256,14 @@
   print(a);
   return a;
 }
+''', '''
+main() {
+  var a;
+  print(0);
+  a = "";
+  print(a);
+  return a;
+}
 '''),
 
     const TestSpec('''
@@ -275,6 +283,12 @@
   print(a);
   return a;
 }
+''', '''
+main(a) {
+  a = a ? "" : a;
+  print(a);
+  return a;
+}
 '''),
   ]),
 
@@ -741,12 +755,10 @@
 }
 ''', '''
 main(a) {
-  var v0 = a.iterator, i;
+  var v0 = a.iterator;
   while (v0.moveNext()) {
-    i = v0.current;
-    print(i);
-    i = 0;
-    print(i);
+    print(v0.current);
+    print(0);
   }
 }
 '''),
diff --git a/pkg/analyzer2dart/test/sexpr_test.dart b/pkg/analyzer2dart/test/sexpr_test.dart
index 9450ced..2c8da58 100644
--- a/pkg/analyzer2dart/test/sexpr_test.dart
+++ b/pkg/analyzer2dart/test/sexpr_test.dart
@@ -42,7 +42,7 @@
   void checkOutput(String elementName,
                    dart2js.Element element,
                    String expectedOutput) {
-    ExecutableDefinition ir = convertedWorld.getIr(element);
+    RootNode ir = convertedWorld.getIr(element);
     if (expectedOutput == null) {
       expect(ir, isNull,
           reason: "\nInput:\n${result.input}\n"
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 175ca25..4aaa293 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -93,7 +93,7 @@
 // TODO(ahe): These classes continuously cause problems.  We need to
 // find a more general solution.
 class ClosureFieldElement extends ElementX
-    implements VariableElement, CapturedVariable {
+    implements FieldElement, CapturedVariable {
   /// The [BoxLocal] or [LocalElement] being accessed through the field.
   final Local local;
 
@@ -146,6 +146,9 @@
   accept(ElementVisitor visitor) => visitor.visitClosureFieldElement(this);
 
   Element get analyzableElement => closureClass.methodElement.analyzableElement;
+
+  @override
+  List<FunctionElement> get nestedClosures => const <FunctionElement>[];
 }
 
 // TODO(ahe): These classes continuously cause problems.  We need to find
@@ -226,7 +229,7 @@
 // TODO(ngeoffray, ahe): These classes continuously cause problems.  We need to
 // find a more general solution.
 class BoxFieldElement extends ElementX
-    implements TypedElement, CapturedVariable {
+    implements TypedElement, CapturedVariable, FieldElement {
   final BoxLocal box;
 
   BoxFieldElement(String name, this.variableElement, BoxLocal box)
@@ -240,6 +243,33 @@
   final VariableElement variableElement;
 
   accept(ElementVisitor visitor) => visitor.visitBoxFieldElement(this);
+
+  @override
+  bool get hasNode => false;
+
+  @override
+  bool get hasResolvedAst => false;
+
+  @override
+  Expression get initializer {
+    throw new UnsupportedError("BoxFieldElement.initializer");
+  }
+
+  @override
+  MemberElement get memberContext => box.executableContext.memberContext;
+
+  @override
+  List<FunctionElement> get nestedClosures => const <FunctionElement>[];
+
+  @override
+  Node get node {
+    throw new UnsupportedError("BoxFieldElement.node");
+  }
+
+  @override
+  ResolvedAst get resolvedAst {
+    throw new UnsupportedError("BoxFieldElement.resolvedAst");
+  }
 }
 
 /// A local variable used encode the direct (uncaptured) references to [this].
@@ -254,7 +284,8 @@
 }
 
 /// Call method of a closure class.
-class SynthesizedCallMethodElementX extends BaseFunctionElementX {
+class SynthesizedCallMethodElementX extends BaseFunctionElementX
+    implements MethodElement {
   final LocalFunctionElement expression;
 
   SynthesizedCallMethodElementX(String name,
diff --git a/pkg/compiler/lib/src/common.dart b/pkg/compiler/lib/src/common.dart
index ff58374..65debcd 100644
--- a/pkg/compiler/lib/src/common.dart
+++ b/pkg/compiler/lib/src/common.dart
@@ -11,6 +11,7 @@
     TypeConstantValue;
 
 export 'dart2jslib.dart' show
+    CallStructure,
     CompilerTask,
     Compiler,
     ConstantEnvironment,
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 13d5d63..c6f1af4 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -444,7 +444,7 @@
               new DartString.literal(text))))];
     AstConstant constant = makeConstructedConstant(
         compiler, handler, context, node, type, compiler.symbolConstructor,
-        new Selector.callConstructor('', null, 1),
+        CallStructure.ONE_ARG,
         arguments, arguments);
     return new AstConstant(
         context, node, new SymbolConstantExpression(constant.value, text));
@@ -652,7 +652,7 @@
    */
   List<AstConstant> evaluateArgumentsToConstructor(
       Node node,
-      Selector selector,
+      CallStructure callStructure,
       Link<Node> arguments,
       FunctionElement target,
       {AstConstant compileArgument(Node node)}) {
@@ -664,7 +664,7 @@
     }
     target.computeSignature(compiler);
 
-    if (!selector.applies(target, compiler.world)) {
+    if (!callStructure.signatureApplies(target)) {
       String name = Elements.constructorNameForDiagnostics(
           target.enclosingClass.name, target.name);
       compiler.reportError(
@@ -676,10 +676,11 @@
           target.functionSignature.parameterCount,
           new ErroneousAstConstant(context, node));
     }
-    return selector.makeArgumentsList(arguments,
-                                      target,
-                                      compileArgument,
-                                      compileDefaultValue);
+    return callStructure.makeArgumentsList(
+        arguments,
+        target,
+        compileArgument,
+        compileDefaultValue);
   }
 
   AstConstant visitNewExpression(NewExpression node) {
@@ -706,7 +707,7 @@
     compiler.analyzeElement(constructor.declaration);
 
     InterfaceType type = elements.getType(node);
-    Selector selector = elements.getSelector(send);
+    CallStructure callStructure = elements.getSelector(send).callStructure;
 
     Map<Node, AstConstant> concreteArgumentMap =
         <Node, AstConstant>{};
@@ -721,7 +722,7 @@
 
     List<AstConstant> normalizedArguments =
         evaluateArgumentsToConstructor(
-          node, selector, send.arguments, constructor.implementation,
+          node, callStructure, send.arguments, constructor.implementation,
           compileArgument: (node) => concreteArgumentMap[node]);
     List<AstConstant> concreteArguments =
         concreteArgumentMap.values.toList();
@@ -732,11 +733,11 @@
 
       AstConstant createEvaluatedConstant(ConstantValue value) {
         return new AstConstant(
-            context, node, new ConstructedConstantExpresssion(
+            context, node, new ConstructedConstantExpression(
                 value,
                 type,
                 constructor,
-                elements.getSelector(send),
+                elements.getSelector(send).callStructure,
                 concreteArguments.map((e) => e.expression).toList()));
       }
 
@@ -811,7 +812,7 @@
     } else {
       return makeConstructedConstant(
           compiler, handler, context,
-          node, type, constructor, selector,
+          node, type, constructor, callStructure,
           concreteArguments, normalizedArguments);
     }
   }
@@ -823,12 +824,12 @@
       Node node,
       InterfaceType type,
       ConstructorElement constructor,
-      Selector selector,
+      CallStructure callStructure,
       List<AstConstant> concreteArguments,
       List<AstConstant> normalizedArguments) {
-    assert(invariant(node, selector.applies(constructor, compiler.world) ||
+    assert(invariant(node, callStructure.signatureApplies(constructor) ||
                      compiler.compilationFailed,
-        message: "Selector $selector does not apply to constructor "
+        message: "Call structure $callStructure does not apply to constructor "
                  "$constructor."));
 
     // The redirection chain of this element may not have been resolved through
@@ -850,13 +851,13 @@
         evaluator.buildFieldConstants(classElement);
 
     return new AstConstant(
-        context, node, new ConstructedConstantExpresssion(
+        context, node, new ConstructedConstantExpression(
             new ConstructedConstantValue(
                 constructedType,
                 fieldConstants.map((e) => e.value).toList()),
             type,
             constructor,
-            selector,
+            callStructure,
             concreteArguments.map((e) => e.expression).toList()));
   }
 
@@ -994,12 +995,12 @@
       Function compileArgument = (element) => definitions[element];
       Function compileConstant = handler.compileConstant;
       FunctionElement target = constructor.definingConstructor.implementation;
-      Selector.addForwardingElementArgumentsToList(constructor,
-                                                   compiledArguments,
-                                                   target,
-                                                   compileArgument,
-                                                   compileConstant,
-                                                   compiler.world);
+      CallStructure.addForwardingElementArgumentsToList(
+          constructor,
+          compiledArguments,
+          target,
+          compileArgument,
+          compileConstant);
       evaluateSuperOrRedirectSend(compiledArguments, target);
       return;
     }
@@ -1019,7 +1020,8 @@
           FunctionElement target = elements[call];
           List<AstConstant> compiledArguments =
               evaluateArgumentsToConstructor(
-                  call, elements.getSelector(call), call.arguments, target,
+                  call, elements.getSelector(call).callStructure,
+                  call.arguments, target,
                   compileArgument: evaluateConstant);
           evaluateSuperOrRedirectSend(compiledArguments, target);
           foundSuperOrRedirect = true;
@@ -1048,9 +1050,9 @@
         // If we do not find a default constructor, an error was reported
         // already and compilation will fail anyway. So just ignore that case.
         if (targetConstructor != null) {
-          Selector selector = new Selector.callDefaultConstructor();
           List<AstConstant> compiledArguments = evaluateArgumentsToConstructor(
-              functionNode, selector, const Link<Node>(), targetConstructor);
+              functionNode, CallStructure.NO_ARGS,
+              const Link<Node>(), targetConstructor);
           evaluateSuperOrRedirectSend(compiledArguments, targetConstructor);
         }
       }
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index dcaea59..5bd9aee 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -291,6 +291,7 @@
   bool get canHandleCompilationFailed;
 
   void onResolutionComplete() {}
+  void onTypeInferenceComplete() {}
 
   ItemCompilationContext createItemCompilationContext() {
     return new ItemCompilationContext();
@@ -362,7 +363,7 @@
   void registerRuntimeType(Enqueuer enqueuer, Registry registry) {}
 
   /// Call this to register a `noSuchMethod` implementation.
-  void registerNoSuchMethod(Element noSuchMethodElement) {}
+  void registerNoSuchMethod(FunctionElement noSuchMethodElement) {}
 
   /// Call this method to enable support for `noSuchMethod`.
   void enableNoSuchMethod(Enqueuer enqueuer) {}
@@ -1611,6 +1612,8 @@
 
     if (stopAfterTypeInference) return;
 
+    backend.onTypeInferenceComplete();
+
     log('Compiling...');
     phase = PHASE_COMPILING;
     // TODO(johnniwinther): Move these to [CodegenEnqueuer].
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index ef416fa..c24b66d 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -10,7 +10,7 @@
     Element,
     FunctionElement,
     VariableElement;
-import '../universe/universe.dart' show Selector;
+import '../universe/universe.dart' show CallStructure;
 import 'values.dart';
 
 /// An expression that is a compile-time constant.
@@ -97,18 +97,19 @@
 }
 
 /// Invocation of a const constructor.
-class ConstructedConstantExpresssion extends ConstantExpression {
+class ConstructedConstantExpression extends ConstantExpression {
   final ConstantValue value;
   final InterfaceType type;
   final FunctionElement target;
-  final Selector selector;
+  final CallStructure callStructure;
   final List<ConstantExpression> arguments;
 
-  ConstructedConstantExpresssion(this.value,
-                      this.type,
-                      this.target,
-                      this.selector,
-                      this.arguments) {
+  ConstructedConstantExpression(
+      this.value,
+      this.type,
+      this.target,
+      this.callStructure,
+      this.arguments) {
     assert(type.element == target.enclosingClass);
   }
 
@@ -274,7 +275,7 @@
   R visitPrimitive(PrimitiveConstantExpression exp, C context);
   R visitList(ListConstantExpression exp, C context);
   R visitMap(MapConstantExpression exp, C context);
-  R visitConstructed(ConstructedConstantExpresssion exp, C context);
+  R visitConstructed(ConstructedConstantExpression exp, C context);
   R visitConcatenate(ConcatenateConstantExpression exp, C context);
   R visitSymbol(SymbolConstantExpression exp, C context);
   R visitType(TypeConstantExpression exp, C context);
@@ -367,7 +368,7 @@
   }
 
   @override
-  void visitConstructed(ConstructedConstantExpresssion exp, [_]) {
+  void visitConstructed(ConstructedConstantExpression exp, [_]) {
     sb.write('const ');
     sb.write(exp.target.enclosingClass.name);
     if (exp.target.name != '') {
@@ -378,7 +379,7 @@
     sb.write('(');
     bool needsComma = false;
 
-    int namedOffset = exp.selector.positionalArgumentCount;
+    int namedOffset = exp.callStructure.positionalArgumentCount;
     for (int index = 0; index < namedOffset; index++) {
       if (needsComma) {
         sb.write(', ');
@@ -386,11 +387,11 @@
       visit(exp.arguments[index]);
       needsComma = true;
     }
-    for (int index = 0; index < exp.selector.namedArgumentCount; index++) {
+    for (int index = 0; index < exp.callStructure.namedArgumentCount; index++) {
       if (needsComma) {
         sb.write(', ');
       }
-      sb.write(exp.selector.namedArguments[index]);
+      sb.write(exp.callStructure.namedArguments[index]);
       sb.write(': ');
       visit(exp.arguments[namedOffset + index]);
       needsComma = true;
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 deffab4..5f35a3f 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -13,7 +13,8 @@
 import '../tree/tree.dart' as ast;
 import '../closure.dart' hide ClosureScope;
 import 'cps_ir_nodes.dart' as ir;
-import 'cps_ir_builder_task.dart' show DartCapturedVariables;
+import 'cps_ir_builder_task.dart' show DartCapturedVariables,
+    GlobalProgramInformation;
 
 /// A mapping from variable elements to their compile-time values.
 ///
@@ -43,6 +44,17 @@
         index2variable = new List<Local>.from(other.index2variable),
         index2value = new List<ir.Primitive>.from(other.index2value);
 
+  /// Construct an environment that is shaped like another one but with a
+  /// fresh parameter for each variable.
+  ///
+  /// The mapping from elements to indexes is shared, not copied.
+  Environment.fresh(Environment other)
+      : variable2index = other.variable2index,
+        index2variable = new List<Local>.from(other.index2variable),
+        index2value = other.index2variable.map((Local local) {
+          return new ir.Parameter(local);
+        }).toList();
+
   get length => index2variable.length;
 
   ir.Primitive operator [](int index) => index2value[index];
@@ -61,6 +73,14 @@
     index2value.add(value);
   }
 
+  void discard(int count) {
+    assert(count <= index2variable.length);
+    // The map from variables to their index are shared, so we cannot remove
+    // the mapping in `variable2index`.
+    index2variable.length -= count;
+    index2value.length -= count;
+  }
+
   ir.Primitive lookup(Local element) {
     assert(invariant(element, variable2index.containsKey(element),
                      message: "Unknown variable: $element."));
@@ -91,57 +111,41 @@
   }
 }
 
-/// A class to collect breaks or continues.
-///
-/// When visiting a potential target of breaks or continues, any breaks or
-/// continues are collected by a JumpCollector and processed later, on demand.
-/// The site of the break or continue is represented by a continuation
-/// invocation that will have its target and arguments filled in later.
-///
-/// The environment of the builder at that point is captured and should not
-/// be subsequently mutated until the jump is resolved.
-class JumpCollector {
+/// The abstract base class of objects that emit jumps to a continuation and
+/// give a handle to the continuation and its environment.
+abstract class JumpCollector {
   final JumpTarget target;
-  final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[];
-  final List<Environment> _environments = <Environment>[];
-  final List<Iterable<LocalVariableElement>> boxedTryVariables =
+
+  ir.Continuation _continuation = null;
+  final Environment _continuationEnvironment;
+
+  final List<Iterable<LocalVariableElement>> _boxedTryVariables =
       <Iterable<LocalVariableElement>>[];
 
-  JumpCollector(this.target);
+  JumpCollector(this._continuationEnvironment, this.target);
 
-  bool get isEmpty => _invocations.isEmpty;
-  int get length => _invocations.length;
-  List<ir.InvokeContinuation> get invocations => _invocations;
-  List<Environment> get environments => _environments;
+  /// True if the collector has not recorded any jumps to its continuation.
+  bool get isEmpty;
 
-  void addJump(IrBuilder builder) {
-    // Unbox all variables that were boxed on entry to try blocks between the
-    // jump and the target.
-    for (Iterable<LocalVariableElement> boxedOnEntry in boxedTryVariables) {
-      for (LocalVariableElement variable in boxedOnEntry) {
-        assert(builder.isInMutableVariable(variable));
-        ir.Primitive value = builder.buildLocalGet(variable);
-        builder.environment.update(variable, value);
-      }
-    }
-    ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized();
-    builder.add(invoke);
-    _invocations.add(invoke);
-    _environments.add(builder.environment);
-    builder._current = null;
-    // TODO(kmillikin): Can we set builder.environment to null to make it
-    // less likely to mutate it?
-  }
+  /// The continuation encapsulated by this collector.
+  ir.Continuation get continuation;
+
+  /// The compile-time environment to be used for translating code in the body
+  /// of the continuation.
+  Environment get environment;
+
+  /// Emit a jump to the continuation for a given [IrBuilder].
+  void addJump(IrBuilder builder);
 
   /// Add a set of variables that were boxed on entry to a try block.
   ///
-  /// Jumps from a try block to targets outside have to unbox the variables
-  /// that were boxed on entry before invoking the target continuation.  Call
-  /// this function before translating a try block and call [leaveTry] after
-  /// translating it.
+  /// All jumps from a try block to targets outside have to unbox the
+  /// variables that were boxed on entry before invoking the target
+  /// continuation.  Call this function before translating a try block and
+  /// call [leaveTry] after translating it.
   void enterTry(Iterable<LocalVariableElement> boxedOnEntry) {
     // The boxed variables are maintained as a stack to make leaving easy.
-    boxedTryVariables.add(boxedOnEntry);
+    _boxedTryVariables.add(boxedOnEntry);
   }
 
   /// Remove the most recently added set of variables boxed on entry to a try
@@ -150,7 +154,172 @@
   /// Call [enterTry] before translating a try block and call this function
   /// after translating it.
   void leaveTry() {
-    boxedTryVariables.removeLast();
+    _boxedTryVariables.removeLast();
+  }
+
+  void _buildTryExit(IrBuilder builder) {
+    for (Iterable<LocalVariableElement> boxedOnEntry in _boxedTryVariables) {
+      for (LocalVariableElement variable in boxedOnEntry) {
+        assert(builder.isInMutableVariable(variable));
+        ir.Primitive value = builder.buildLocalGet(variable);
+        builder.environment.update(variable, value);
+      }
+    }
+  }
+}
+
+/// A class to collect 'forward' jumps.
+///
+/// A forward jump to a continuation in the sense of the CPS translation is
+/// a jump where the jump is emitted before any code in the body of the
+/// continuation is translated.  They have the property that continuation
+/// parameters and the environment for the translation of the body can be
+/// determined based on the invocations, before translating the body.  A
+/// [ForwardJumpCollector] can encapsulate a continuation where all the
+/// jumps are forward ones.
+///
+/// Examples of forward jumps in the translation are join points of
+/// if-then-else and breaks from loops.
+///
+/// The implementation strategy is that the collector collects invocation
+/// sites and the environments at those sites.  Then it constructs a
+/// continuation 'on demand' after all the jumps are seen.  It determines
+/// continuation parameters, the environment for the translation of code in
+/// the continuation body, and the arguments at the invocation site only
+/// after all the jumps to the continuation are seen.
+class ForwardJumpCollector extends JumpCollector {
+  final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[];
+  final List<Environment> _invocationEnvironments = <Environment>[];
+
+  /// Construct a collector with a given base environment.
+  ///
+  /// The base environment is the one in scope at the site that the
+  /// 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);
+
+  bool get isEmpty => _invocations.isEmpty;
+
+  ir.Continuation get continuation {
+    if (_continuation == null) _setContinuation();
+    return _continuation;
+  }
+
+  Environment get environment {
+    if (_continuation == null) _setContinuation();
+    return _continuationEnvironment;
+  }
+
+  void addJump(IrBuilder builder) {
+    assert(_continuation == null);
+    _buildTryExit(builder);
+    ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized();
+    builder.add(invoke);
+    _invocations.add(invoke);
+    _invocationEnvironments.add(builder.environment);
+    builder._current = null;
+    // TODO(kmillikin): Can we set builder.environment to null to make it
+    // less likely to mutate it?
+  }
+
+  void _setContinuation() {
+    assert(_continuation == null);
+    // We have seen all invocations of this continuation, and recorded the
+    // environment in effect at each invocation site.
+
+    // Compute the union of the assigned variables reaching the continuation.
+    //
+    // There is a continuation parameter for each environment variable
+    // that has a different value (from the environment in scope at the
+    // continuation binding) on some path.  `_environment` is initially a copy
+    // of the environment in scope at the continuation binding.  Compute the
+    // continuation parameters and add them to `_environment` so it will become
+    // the one in scope for the continuation body.
+    List<ir.Parameter> parameters = <ir.Parameter>[];
+    if (_invocationEnvironments.isNotEmpty) {
+      int length = _continuationEnvironment.length;
+      for (int varIndex = 0; varIndex < length; ++varIndex) {
+        for (Environment invocationEnvironment in _invocationEnvironments) {
+          assert(invocationEnvironment.sameDomain(length,
+                                                  _continuationEnvironment));
+          if (invocationEnvironment[varIndex] !=
+              _continuationEnvironment[varIndex]) {
+            ir.Parameter parameter = new ir.Parameter(
+                _continuationEnvironment.index2variable[varIndex]);
+            _continuationEnvironment.index2value[varIndex] = parameter;
+            parameters.add(parameter);
+            break;
+          }
+        }
+      }
+    }
+    _continuation = new ir.Continuation(parameters);
+
+    // Compute the intersection of the parameters with the environments at
+    // each continuation invocation.  Initialize the invocations.
+    for (int jumpIndex = 0; jumpIndex < _invocations.length; ++jumpIndex) {
+      Environment invocationEnvironment = _invocationEnvironments[jumpIndex];
+      List<ir.Reference> arguments = <ir.Reference>[];
+      int varIndex = 0;
+      for (ir.Parameter parameter in parameters) {
+        varIndex =
+            _continuationEnvironment.index2value.indexOf(parameter, varIndex);
+        arguments.add(new ir.Reference(invocationEnvironment[varIndex]));
+      }
+      ir.InvokeContinuation invocation = _invocations[jumpIndex];
+      invocation.continuation = new ir.Reference(_continuation);
+      invocation.arguments = arguments;
+    }
+  }
+}
+
+/// A class to collect 'backward' jumps.
+///
+/// A backward jump to a continuation in the sense of the CPS translation is
+/// a jump where some code in the body of the continuation is translated
+/// before the jump is emitted.  They have the property that the
+/// continuation parameters and the environment for the translation of the
+/// body must be determined before emitting all the invocations.  A
+/// [BackwardJumpCollector] can ecapsulate a continuation where some jumps
+/// are backward ones.
+///
+/// Examples of backward jumps in the translation are the recursive
+/// invocations of loop continuations.
+///
+/// The implementation strategy is that the collector inserts a continuation
+/// parameter for each variable in scope at the entry to the continuation,
+/// before emitting any jump to the continuation.  When a jump is added, it
+/// is given an argument for each continuation parameter.
+class BackwardJumpCollector extends JumpCollector {
+  /// Construct a collector with a given base environment.
+  ///
+  /// The base environment is the one in scope at the site that the
+  /// 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) {
+    List<ir.Parameter> parameters =
+        new List<ir.Parameter>.from(_continuationEnvironment.index2value);
+    _continuation = new ir.Continuation(parameters, isRecursive: true);
+  }
+
+  bool isEmpty = true;
+
+  ir.Continuation get continuation => _continuation;
+  Environment get environment => _continuationEnvironment;
+
+  void addJump(IrBuilder builder) {
+    assert(_continuation.parameters.length <= builder.environment.length);
+    isEmpty = false;
+    _buildTryExit(builder);
+    builder.add(new ir.InvokeContinuation(_continuation,
+        builder.environment.index2value.take(_continuation.parameters.length)
+            .toList(),
+        isRecursive: true));
+    builder._current = null;
   }
 }
 
@@ -247,17 +416,6 @@
 abstract class IrBuilder {
   IrBuilder _makeInstance();
 
-  // TODO(johnniwinther): Remove this from the [IrBuilder].
-  /// A map from TryStatements in the AST to their analysis information.
-  ///
-  /// This includes which variables should be copied into [ir.MutableVariable]s
-  /// on entry to the try and copied out on exit.
-  Map<ast.TryStatement, TryStatementInfo> get tryStatements;
-
-  /// The set of local variables that will spend their lifetime as
-  /// [ir.MutableVariable]s due to being captured by a nested function.
-  Set<Local> get mutableCapturedVariables;
-
   /// True if [local] should currently be accessed from a [ir.MutableVariable].
   bool isInMutableVariable(Local local);
 
@@ -308,7 +466,7 @@
 
   /// Add the given function parameter to the IR, and bind it in the environment
   /// or put it in its box, if necessary.
-  void _createFunctionParameter(ParameterElement parameterElement);
+  void _createFunctionParameter(Local parameterElement);
   void _createThisParameter();
 
   /// Creates an access to the receiver from the current (or enclosing) method.
@@ -365,14 +523,17 @@
 
   /// Construct a delimited visitor for visiting a subtree.
   ///
-  /// The delimited visitor has its own compile-time environment mapping
-  /// local variables to their values, which is initially a copy of the parent
-  /// environment.  It has its own context for building an IR expression, so
-  /// the built expression is not plugged into the parent's context.
-  IrBuilder makeDelimitedBuilder() {
+  /// 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 = new Environment.from(environment);
+        ..environment = env != null ? env : new Environment.from(environment);
   }
 
   /// Construct a builder for making constructor field initializers.
@@ -383,22 +544,6 @@
         ..environment = new Environment.from(environment);
   }
 
-  /// Construct a visitor for a recursive continuation.
-  ///
-  /// The recursive continuation builder has fresh parameters (i.e. SSA phis)
-  /// for all the local variables in the parent, because the invocation sites
-  /// of the continuation are not all known when the builder is created.  The
-  /// recursive invocations will be passed values for all the local variables,
-  /// which may be eliminated later if they are redundant---if they take on
-  /// the same value at all invocation sites.
-  IrBuilder makeRecursiveBuilder() {
-    IrBuilder inner = _makeInstance()
-        ..state = state
-        ..environment = new Environment.empty();
-    environment.index2variable.forEach(inner.createLocalParameter);
-    return inner;
-  }
-
   /// Construct a builder for an inner function.
   IrBuilder makeInnerFunctionBuilder(ExecutableElement currentElement) {
     IrBuilderDelimitedState innerState =
@@ -416,7 +561,7 @@
     _enterScope(closureScope);
   }
 
-  List<ir.Primitive> buildFunctionHeader(Iterable<ParameterElement> parameters,
+  List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters,
                                         {ClosureScope closureScope,
                                          ClosureEnvironment env}) {
     _createThisParameter();
@@ -500,11 +645,9 @@
   }
 
   ir.Primitive _buildInvokeCall(ir.Primitive target,
-                                 Selector selector,
-                                 List<ir.Definition> arguments) {
-    Selector callSelector = new Selector.callClosure(
-        selector.argumentCount,
-        selector.namedArguments);
+                                Selector selector,
+                                List<ir.Definition> arguments) {
+    Selector callSelector = new Selector.callClosureFrom(selector);
     return _buildInvokeDynamic(target, callSelector, arguments);
   }
 
@@ -551,7 +694,7 @@
   ir.Primitive buildListLiteral(InterfaceType type,
                                 Iterable<ir.Primitive> values) {
     assert(isOpen);
-    return addPrimitive(new ir.LiteralList(type, values));
+    return addPrimitive(new ir.LiteralList(type, values.toList()));
   }
 
   /// Creates a non-constant map literal of the provided [type] and with the
@@ -573,13 +716,12 @@
   }
 
   /// Creates a conditional expression with the provided [condition] where the
-  /// then and else expression are created through the [buildThenExpression] and
-  /// [buildElseExpression] functions, respectively.
+  /// then and else expression are created through the [buildThenExpression]
+  /// and [buildElseExpression] functions, respectively.
   ir.Primitive buildConditional(
       ir.Primitive condition,
       ir.Primitive buildThenExpression(IrBuilder builder),
       ir.Primitive buildElseExpression(IrBuilder builder)) {
-
     assert(isOpen);
 
     // The then and else expressions are delimited.
@@ -590,16 +732,24 @@
 
     // Treat the values of the subexpressions as named values in the
     // environment, so they will be treated as arguments to the join-point
-    // continuation.
+    // continuation.  We know the environments are the right size because
+    // 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 jumps = new JumpCollector(null);
-    jumps.addJump(thenBuilder);
-    jumps.addJump(elseBuilder);
-    ir.Continuation joinContinuation =
-        createJoin(environment.length + 1, jumps);
+    JumpCollector join = new ForwardJumpCollector(environment);
+    thenBuilder.jumpTo(join);
+    elseBuilder.jumpTo(join);
 
     // Build the term
     //   let cont join(x, ..., result) = [] in
@@ -611,15 +761,17 @@
     ir.Continuation elseContinuation = new ir.Continuation([]);
     thenContinuation.body = thenBuilder._root;
     elseContinuation.body = elseBuilder._root;
-    add(new ir.LetCont(joinContinuation,
+    add(new ir.LetCont(join.continuation,
             new ir.LetCont.many(<ir.Continuation>[thenContinuation,
                                                   elseContinuation],
                 new ir.Branch(new ir.IsTrue(condition),
                               thenContinuation,
                               elseContinuation))));
+    environment = join.environment;
+    environment.discard(1);
     return (thenValue == elseValue)
         ? thenValue
-        : joinContinuation.parameters.last;
+        : join.continuation.parameters.last;
   }
 
   /**
@@ -635,13 +787,13 @@
   }
 
   ir.SuperInitializer makeSuperInitializer(ConstructorElement target,
-                                           List<ir.RunnableBody> arguments,
+                                           List<ir.Body> arguments,
                                            Selector selector) {
     return new ir.SuperInitializer(target, arguments, selector);
   }
 
   ir.FieldInitializer makeFieldInitializer(FieldElement element,
-                                           ir.RunnableBody body) {
+                                           ir.Body body) {
     return new ir.FieldInitializer(element, body);
   }
 
@@ -651,18 +803,18 @@
     if (initializer == null) {
       return new ir.FieldDefinition.withoutInitializer(state.currentElement);
     } else {
-      ir.RunnableBody body = makeRunnableBody(initializer);
+      ir.Body body = makeBody(initializer);
       return new ir.FieldDefinition(state.currentElement, body);
     }
   }
 
-  ir.RunnableBody makeRunnableBody([ir.Primitive value]) {
+  ir.Body makeBody([ir.Primitive value]) {
     if (value == null) {
       _ensureReturn();
     } else {
       buildReturn(value);
     }
-    return new ir.RunnableBody(_root, state.returnContinuation);
+    return new ir.Body(_root, state.returnContinuation);
   }
 
   /// Create a [ir.FunctionDefinition] for [element] using [_root] as the body.
@@ -679,9 +831,9 @@
           message: "Local constants for abstract method $element: "
                    "${state.localConstants}"));
       return new ir.FunctionDefinition.abstract(
-          element, state.thisParameter, state.functionParameters, defaults);
+          element, state.functionParameters, defaults);
     } else {
-      ir.RunnableBody body = makeRunnableBody();
+      ir.Body body = makeBody();
       return new ir.FunctionDefinition(
           element, state.thisParameter, state.functionParameters, body,
           state.localConstants, defaults);
@@ -705,7 +857,7 @@
   ir.ConstructorDefinition makeConstructorDefinition(
       List<ConstantExpression> defaults, List<ir.Initializer> initializers) {
     FunctionElement element = state.currentElement;
-    ir.RunnableBody body = makeRunnableBody();
+    ir.Body body = makeBody();
     return new ir.ConstructorDefinition(
         element, state.thisParameter, state.functionParameters, body, initializers,
         state.localConstants, defaults);
@@ -829,11 +981,7 @@
   ir.Primitive buildConstructorInvocation(FunctionElement element,
                                           Selector selector,
                                           DartType type,
-                                          List<ir.Primitive> arguments) {
-    assert(isOpen);
-    return _continueWithExpression(
-        (k) => new ir.InvokeConstructor(type, element, selector, k, arguments));
-  }
+                                          List<ir.Primitive> arguments);
 
   /// Create a string concatenation of the [arguments].
   ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments) {
@@ -890,16 +1038,15 @@
                           thenContinuation,
                           elseContinuation));
 
-    ir.Continuation joinContinuation;  // Null if there is no join.
+    JumpCollector join;  // Null if there is no join.
     if (thenBuilder.isOpen && elseBuilder.isOpen) {
       // There is a join-point continuation.  Build the term
       // 'let cont join(x, ...) = [] in Result' and plug invocations of the
       // join-point continuation into the then and else continuations.
-      JumpCollector jumps = new JumpCollector(null);
-      jumps.addJump(thenBuilder);
-      jumps.addJump(elseBuilder);
-      joinContinuation = createJoin(environment.length, jumps);
-      result = new ir.LetCont(joinContinuation, result);
+      join = new ForwardJumpCollector(environment);
+      thenBuilder.jumpTo(join);
+      elseBuilder.jumpTo(join);
+      result = new ir.LetCont(join.continuation, result);
     }
 
     // The then or else term root could be null, but not both.  If there is
@@ -913,7 +1060,7 @@
     elseContinuation.body = elseBuilder._root;
 
     add(result);
-    if (joinContinuation == null) {
+    if (join == null) {
       // At least one subexpression is closed.
       if (thenBuilder.isOpen) {
         if (thenBuilder._root != null) _current = thenBuilder._current;
@@ -924,43 +1071,21 @@
       } else {
         _current = null;
       }
+    } else {
+      environment = join.environment;
     }
   }
 
-  void jumpTo(ir.Continuation continuation) {
-    assert(isOpen);
-    assert(environment.length >= continuation.parameters.length);
-    ir.InvokeContinuation jump = new ir.InvokeContinuation.uninitialized();
-    jump.continuation = new ir.Reference(continuation);
-    jump.arguments = new List<ir.Reference>.generate(
-        continuation.parameters.length, (i) {
-      return new ir.Reference(environment[i]);
-    });
-    add(jump);
-    _current = null;
+  void jumpTo(JumpCollector collector) {
+    collector.addJump(this);
   }
 
-  /// Invoke a join-point continuation that contains arguments for all local
-  /// variables.
-  ///
-  /// Given the continuation and a list of uninitialized invocations, fill
-  /// in each invocation with the continuation and appropriate arguments.
-  void invokeFullJoin(ir.Continuation join,
-                      JumpCollector jumps,
-                      {recursive: false}) {
-    // TODO(kmillikin): If the JumpCollector collected open IrBuilders instead
-    // of pairs of invocations and environments, we could use IrBuilder.jumpTo
-    // here --- the code is almost the same.
-    join.isRecursive = recursive;
-    for (int i = 0; i < jumps.length; ++i) {
-      Environment currentEnvironment = jumps.environments[i];
-      ir.InvokeContinuation invoke = jumps.invocations[i];
-      invoke.continuation = new ir.Reference(join);
-      invoke.arguments = new List<ir.Reference>.generate(
-          join.parameters.length,
-          (i) => new ir.Reference(currentEnvironment[i]));
-      invoke.isRecursive = recursive;
-    }
+  void addRecursiveContinuation(BackwardJumpCollector collector) {
+    assert(environment.length == collector.environment.length);
+    add(new ir.LetCont(collector.continuation,
+            new ir.InvokeContinuation(collector.continuation,
+                                      environment.index2value)));
+    environment = collector.environment;
   }
 
   /// Creates a for loop in which the initializer, condition, body, update are
@@ -994,7 +1119,7 @@
     // [[initializer]];
     // let cont loop(x, ...) =
     //     let prim cond = [[condition]] in
-    //     let cont break() = [[successor]] in
+    //     let cont break(x, ...) = [[successor]] in
     //     let cont exit() = break(v, ...) in
     //     let cont body() =
     //         _enterForLoopBody();
@@ -1012,28 +1137,33 @@
     // statement occurs in the exit continuation).  If there is only one
     // invocation of the continue continuation (i.e., no continues in the
     // body), the continue continuation is inlined in the body.
-
     _enterForLoopInitializer(closureScope, loopVariables);
-
     buildInitializer(this);
 
-    IrBuilder condBuilder = makeRecursiveBuilder();
-    ir.Primitive condition = buildCondition(condBuilder);
+    JumpCollector loop = new BackwardJumpCollector(environment);
+    addRecursiveContinuation(loop);
+
+    ir.Primitive condition = buildCondition(this);
     if (condition == null) {
       // If the condition is empty then the body is entered unconditionally.
-      condition = condBuilder.buildBooleanLiteral(true);
+      condition = buildBooleanLiteral(true);
     }
+    JumpCollector breakCollector =
+        new ForwardJumpCollector(environment, target: target);
 
-    JumpCollector breakCollector = new JumpCollector(target);
-    JumpCollector continueCollector = new JumpCollector(target);
-    state.breakCollectors.add(breakCollector);
-    state.continueCollectors.add(continueCollector);
-
-    IrBuilder outerBodyBuilder = condBuilder.makeDelimitedBuilder();
+    // Use a pair of builders for the body, one for the entry code if any
+    // and one for the body itself.  We only decide whether to insert a
+    // continue continuation until after translating the body and there is no
+    // way to insert such a continuation between the entry code and the body
+    // if they are translated together.
+    IrBuilder outerBodyBuilder = makeDelimitedBuilder();
     outerBodyBuilder._enterForLoopBody(closureScope, loopVariables);
+    JumpCollector continueCollector =
+        new ForwardJumpCollector(outerBodyBuilder.environment, target: target);
 
     IrBuilder innerBodyBuilder = outerBodyBuilder.makeDelimitedBuilder();
-
+    state.breakCollectors.add(breakCollector);
+    state.continueCollectors.add(continueCollector);
     buildBody(innerBodyBuilder);
     assert(state.breakCollectors.last == breakCollector);
     assert(state.continueCollectors.last == continueCollector);
@@ -1043,17 +1173,34 @@
     // The binding of the continue continuation should occur as late as
     // possible, that is, at the nearest common ancestor of all the continue
     // sites in the body.  However, that is difficult to compute here, so it
-    // is instead placed just outside the body of the body continuation.
+    // is instead placed just outside the translation of the loop body.  In
+    // the case where there are no continues in the body, the updates are
+    // translated immediately after the body.
     bool hasContinues = !continueCollector.isEmpty;
-    IrBuilder updateBuilder = hasContinues
-        ? outerBodyBuilder.makeRecursiveBuilder()
-        : innerBodyBuilder;
+    IrBuilder updateBuilder;
+    if (hasContinues) {
+      if (innerBodyBuilder.isOpen) innerBodyBuilder.jumpTo(continueCollector);
+      updateBuilder = makeDelimitedBuilder(continueCollector.environment);
+    } else {
+      updateBuilder = innerBodyBuilder;
+    }
     updateBuilder._enterForLoopUpdate(closureScope, loopVariables);
     buildUpdate(updateBuilder);
+    if (updateBuilder.isOpen) updateBuilder.jumpTo(loop);
+    // Connect the inner and outer body builders.  This is done only after
+    // it is guaranteed that the updateBuilder has a non-empty term.
+    if (hasContinues) {
+      outerBodyBuilder.add(new ir.LetCont(continueCollector.continuation,
+          innerBodyBuilder._root));
+      continueCollector.continuation.body = updateBuilder._root;
+    } else {
+      outerBodyBuilder.add(innerBodyBuilder._root);
+    }
 
-    // Create body entry and loop exit continuations and a branch to them.
-    ir.Continuation bodyContinuation = new ir.Continuation([]);
+    // Create loop exit and body entry continuations and a branch to them.
     ir.Continuation exitContinuation = new ir.Continuation([]);
+    ir.Continuation bodyContinuation = new ir.Continuation([]);
+    bodyContinuation.body = outerBodyBuilder._root;
     // Note the order of continuations: the first one is the one that will
     // be filled by LetCont.plug.
     ir.LetCont branch =
@@ -1063,57 +1210,19 @@
                           bodyContinuation,
                           exitContinuation));
     // If there are breaks in the body, then there must be a join-point
-    // continuation for the normal exit and the breaks.
+    // continuation for the normal exit and the breaks.  Otherwise, the
+    // successor is translated in the hole in the exit continuation.
     bool hasBreaks = !breakCollector.isEmpty;
-    ir.LetCont letJoin;
+    ir.LetCont letBreak;
     if (hasBreaks) {
-      letJoin = new ir.LetCont(null, branch);
-      condBuilder.add(letJoin);
-      condBuilder._current = branch;
+      IrBuilder exitBuilder = makeDelimitedBuilder();
+      exitBuilder.jumpTo(breakCollector);
+      exitContinuation.body = exitBuilder._root;
+      letBreak = new ir.LetCont(breakCollector.continuation, branch);
+      add(letBreak);
+      environment = breakCollector.environment;
     } else {
-      condBuilder.add(branch);
-    }
-    ir.Continuation continueContinuation;
-    if (hasContinues) {
-      // If there are continues in the body, we need a named continue
-      // continuation as a join point.
-      continueContinuation = new ir.Continuation(updateBuilder._parameters);
-      if (innerBodyBuilder.isOpen) continueCollector.addJump(innerBodyBuilder);
-      invokeFullJoin(continueContinuation, continueCollector);
-    }
-    ir.Continuation loopContinuation =
-        new ir.Continuation(condBuilder._parameters);
-    if (updateBuilder.isOpen) {
-      JumpCollector backEdges = new JumpCollector(null);
-      backEdges.addJump(updateBuilder);
-      invokeFullJoin(loopContinuation, backEdges, recursive: true);
-    }
-
-    // Fill in the body and possible continue continuation bodies.  Do this
-    // only after it is guaranteed that they are not empty.
-    if (hasContinues) {
-      continueContinuation.body = updateBuilder._root;
-      outerBodyBuilder.add(new ir.LetCont(continueContinuation,
-                                          innerBodyBuilder._root));
-    } else {
-      outerBodyBuilder.add(innerBodyBuilder._root);
-    }
-    bodyContinuation.body = outerBodyBuilder._root;
-
-    loopContinuation.body = condBuilder._root;
-    add(new ir.LetCont(loopContinuation,
-            new ir.InvokeContinuation(loopContinuation,
-                environment.index2value)));
-    if (hasBreaks) {
-      _current = branch;
-      environment = condBuilder.environment;
-      breakCollector.addJump(this);
-      letJoin.continuations =
-          <ir.Continuation>[createJoin(environment.length, breakCollector)];
-      _current = letJoin;
-    } else {
-      _current = condBuilder._current;
-      environment = condBuilder.environment;
+      add(branch);
     }
   }
 
@@ -1152,37 +1261,50 @@
     //   s;
     // }
 
-    // The condition and body are delimited.
-    IrBuilder condBuilder = makeRecursiveBuilder();
-
+    // Fill the current hole with:
+    // let prim expressionReceiver = [[e]] in
+    // let cont iteratorInvoked(iterator) =
+    //     [ ]
+    // in expressionReceiver.iterator () iteratorInvoked
     ir.Primitive expressionReceiver = buildExpression(this);
-    List<ir.Primitive> emptyArguments = new List<ir.Primitive>();
-
+    List<ir.Primitive> emptyArguments = <ir.Primitive>[];
     ir.Parameter iterator = new ir.Parameter(null);
     ir.Continuation iteratorInvoked = new ir.Continuation([iterator]);
     add(new ir.LetCont(iteratorInvoked,
         new ir.InvokeMethod(expressionReceiver,
-            new Selector.getter("iterator", null), iteratorInvoked,
+            new Selector.getter("iterator", null),
+            iteratorInvoked,
             emptyArguments)));
 
+    // Fill with:
+    // let cont loop(x, ...) =
+    //     let cont moveNextInvoked(condition) =
+    //         [ ]
+    //     in iterator.moveNext () moveNextInvoked
+    // in loop(v, ...)
+    JumpCollector loop = new BackwardJumpCollector(environment, target: target);
+    addRecursiveContinuation(loop);
     ir.Parameter condition = new ir.Parameter(null);
     ir.Continuation moveNextInvoked = new ir.Continuation([condition]);
-    condBuilder.add(new ir.LetCont(moveNextInvoked,
+    add(new ir.LetCont(moveNextInvoked,
         new ir.InvokeMethod(iterator,
             new Selector.call("moveNext", null, 0),
-            moveNextInvoked, emptyArguments)));
+            moveNextInvoked,
+            emptyArguments)));
 
-    JumpCollector breakCollector = new JumpCollector(target);
-    JumpCollector continueCollector = new JumpCollector(target);
-    state.breakCollectors.add(breakCollector);
-    state.continueCollectors.add(continueCollector);
-
-    IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder();
+    // As a delimited term, build:
+    // <<BODY>> =
+    //   _enterScope();
+    //   [[variableDeclaration]]
+    //   let cont currentInvoked(currentValue) =
+    //       [[a = currentValue]];
+    //       [ ]
+    //   in iterator.current () currentInvoked
+    IrBuilder bodyBuilder = makeDelimitedBuilder();
     bodyBuilder._enterScope(closureScope);
     if (buildVariableDeclaration != null) {
       buildVariableDeclaration(bodyBuilder);
     }
-
     ir.Parameter currentValue = new ir.Parameter(null);
     ir.Continuation currentInvoked = new ir.Continuation([currentValue]);
     bodyBuilder.add(new ir.LetCont(currentInvoked,
@@ -1201,15 +1323,27 @@
       bodyBuilder.buildDynamicSet(receiver, variableSelector, currentValue);
     }
 
+    // Translate the body in the hole in the delimited term above, and add
+    // a jump to the loop if control flow is live after the body.
+    JumpCollector breakCollector =
+        new ForwardJumpCollector(environment, target: target);
+    state.breakCollectors.add(breakCollector);
+    state.continueCollectors.add(loop);
     buildBody(bodyBuilder);
     assert(state.breakCollectors.last == breakCollector);
-    assert(state.continueCollectors.last == continueCollector);
+    assert(state.continueCollectors.last == loop);
     state.breakCollectors.removeLast();
     state.continueCollectors.removeLast();
+    if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop);
 
     // Create body entry and loop exit continuations and a branch to them.
-    ir.Continuation bodyContinuation = new ir.Continuation([]);
+    //
+    // let cont exit() = [ ]
+    //      and body() = <<BODY>>
+    // in branch condition (body, exit)
     ir.Continuation exitContinuation = new ir.Continuation([]);
+    ir.Continuation bodyContinuation = new ir.Continuation([]);
+    bodyContinuation.body = bodyBuilder._root;
     // Note the order of continuations: the first one is the one that will
     // be filled by LetCont.plug.
     ir.LetCont branch =
@@ -1219,37 +1353,19 @@
                           bodyContinuation,
                           exitContinuation));
     // If there are breaks in the body, then there must be a join-point
-    // continuation for the normal exit and the breaks.
+    // continuation for the normal exit and the breaks.  Otherwise, the
+    // successor is translated in the hole in the exit continuation.
     bool hasBreaks = !breakCollector.isEmpty;
-    ir.LetCont letJoin;
+    ir.LetCont letBreak;
     if (hasBreaks) {
-      letJoin = new ir.LetCont(null, branch);
-      condBuilder.add(letJoin);
-      condBuilder._current = branch;
+      IrBuilder exitBuilder = makeDelimitedBuilder();
+      exitBuilder.jumpTo(breakCollector);
+      exitContinuation.body = exitBuilder._root;
+      letBreak = new ir.LetCont(breakCollector.continuation, branch);
+      add(letBreak);
+      environment = breakCollector.environment;
     } else {
-      condBuilder.add(branch);
-    }
-    ir.Continuation loopContinuation =
-        new ir.Continuation(condBuilder._parameters);
-    if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder);
-    invokeFullJoin(
-        loopContinuation, continueCollector, recursive: true);
-    bodyContinuation.body = bodyBuilder._root;
-
-    loopContinuation.body = condBuilder._root;
-    add(new ir.LetCont(loopContinuation,
-            new ir.InvokeContinuation(loopContinuation,
-                                      environment.index2value)));
-    if (hasBreaks) {
-      _current = branch;
-      environment = condBuilder.environment;
-      breakCollector.addJump(this);
-      letJoin.continuations =
-          <ir.Continuation>[createJoin(environment.length, breakCollector)];
-      _current = letJoin;
-    } else {
-      _current = condBuilder._current;
-      environment = condBuilder.environment;
+      add(branch);
     }
   }
 
@@ -1271,34 +1387,39 @@
     //     let prim cond = [[condition]] in
     //     let cont break(x, ...) = [[successor]] in
     //     let cont exit() = break(v, ...)
-    //          and body() = [[body]]; continue(v, ...)
+    //          and body() =
+    //                _enterScope();
+    //                [[body]];
+    //                continue(v, ...)
     //     in branch cond (body, exit)
     // in continue(v, ...)
     //
     // If there are no breaks in the body, the break continuation is inlined
     // in the exit continuation (i.e., the translation of the successor
     // statement occurs in the exit continuation).
+    JumpCollector loop = new BackwardJumpCollector(environment, target: target);
+    addRecursiveContinuation(loop);
 
-    // The condition and body are delimited.
-    IrBuilder condBuilder = makeRecursiveBuilder();
-    ir.Primitive condition = buildCondition(condBuilder);
+    ir.Primitive condition = buildCondition(this);
 
-    JumpCollector breakCollector = new JumpCollector(target);
-    JumpCollector continueCollector = new JumpCollector(target);
-    state.breakCollectors.add(breakCollector);
-    state.continueCollectors.add(continueCollector);
+    JumpCollector breakCollector =
+        new ForwardJumpCollector(environment, target: target);
 
-    IrBuilder bodyBuilder = condBuilder.makeDelimitedBuilder();
+    IrBuilder bodyBuilder = makeDelimitedBuilder();
     bodyBuilder._enterScope(closureScope);
+    state.breakCollectors.add(breakCollector);
+    state.continueCollectors.add(loop);
     buildBody(bodyBuilder);
     assert(state.breakCollectors.last == breakCollector);
-    assert(state.continueCollectors.last == continueCollector);
+    assert(state.continueCollectors.last == loop);
     state.breakCollectors.removeLast();
     state.continueCollectors.removeLast();
+    if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop);
 
     // Create body entry and loop exit continuations and a branch to them.
-    ir.Continuation bodyContinuation = new ir.Continuation([]);
     ir.Continuation exitContinuation = new ir.Continuation([]);
+    ir.Continuation bodyContinuation = new ir.Continuation([]);
+    bodyContinuation.body = bodyBuilder._root;
     // Note the order of continuations: the first one is the one that will
     // be filled by LetCont.plug.
     ir.LetCont branch =
@@ -1308,36 +1429,19 @@
                           bodyContinuation,
                           exitContinuation));
     // If there are breaks in the body, then there must be a join-point
-    // continuation for the normal exit and the breaks.
+    // continuation for the normal exit and the breaks.  Otherwise, the
+    // successor is translated in the hole in the exit continuation.
     bool hasBreaks = !breakCollector.isEmpty;
-    ir.LetCont letJoin;
+    ir.LetCont letBreak;
     if (hasBreaks) {
-      letJoin = new ir.LetCont(null, branch);
-      condBuilder.add(letJoin);
-      condBuilder._current = branch;
+      IrBuilder exitBuilder = makeDelimitedBuilder();
+      exitBuilder.jumpTo(breakCollector);
+      exitContinuation.body = exitBuilder._root;
+      letBreak = new ir.LetCont(breakCollector.continuation, branch);
+      add(letBreak);
+      environment = breakCollector.environment;
     } else {
-      condBuilder.add(branch);
-    }
-    ir.Continuation loopContinuation =
-        new ir.Continuation(condBuilder._parameters);
-    if (bodyBuilder.isOpen) continueCollector.addJump(bodyBuilder);
-    invokeFullJoin(loopContinuation, continueCollector, recursive: true);
-    bodyContinuation.body = bodyBuilder._root;
-
-    loopContinuation.body = condBuilder._root;
-    add(new ir.LetCont(loopContinuation,
-            new ir.InvokeContinuation(loopContinuation,
-                                      environment.index2value)));
-    if (hasBreaks) {
-      _current = branch;
-      environment = condBuilder.environment;
-      breakCollector.addJump(this);
-      letJoin.continuations =
-          <ir.Continuation>[createJoin(environment.length, breakCollector)];
-      _current = letJoin;
-    } else {
-      _current = condBuilder._current;
-      environment = condBuilder.environment;
+      add(branch);
     }
   }
 
@@ -1365,99 +1469,66 @@
     //       in branch cond (repeat, exit)
     //   in [[body]]; continue(v, ...)
     // in loop(v, ...)
-    IrBuilder bodyBuilder = makeRecursiveBuilder();
-    IrBuilder continueBuilder = bodyBuilder.makeRecursiveBuilder();
+    IrBuilder loopBuilder = makeDelimitedBuilder();
+    JumpCollector loop =
+        new BackwardJumpCollector(loopBuilder.environment, target: target);
+    loopBuilder.addRecursiveContinuation(loop);
 
-    // Construct the continue continuation (i.e., the condition).
+    // Translate the body.
+    JumpCollector breakCollector =
+        new ForwardJumpCollector(environment, target: target);
+    JumpCollector continueCollector =
+        new ForwardJumpCollector(loopBuilder.environment, target: target);
+    IrBuilder bodyBuilder = loopBuilder.makeDelimitedBuilder();
+    bodyBuilder._enterScope(closureScope);
+    state.breakCollectors.add(breakCollector);
+    state.continueCollectors.add(continueCollector);
+    buildBody(bodyBuilder);
+    assert(state.breakCollectors.last == breakCollector);
+    assert(state.continueCollectors.last == continueCollector);
+    state.breakCollectors.removeLast();
+    state.continueCollectors.removeLast();
+    if (bodyBuilder.isOpen) bodyBuilder.jumpTo(continueCollector);
+
+    // Construct the body of the continue continuation (i.e., the condition).
     // <Continue> =
     // let prim cond = [[condition]] in
     //   let cont exit() = break(v, ...)
     //        and repeat() = loop(v, ...)
     //   in branch cond (repeat, exit)
+    IrBuilder continueBuilder = loopBuilder.makeDelimitedBuilder();
+    continueBuilder.environment = continueCollector.environment;
     ir.Primitive condition = buildCondition(continueBuilder);
-    // Use a delimited IrBuilder for the exit continuation's body so that
-    // we can capture the break with the body's break collector.
+
     ir.Continuation exitContinuation = new ir.Continuation([]);
     IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder();
+    exitBuilder.jumpTo(breakCollector);
+    exitContinuation.body = exitBuilder._root;
     ir.Continuation repeatContinuation = new ir.Continuation([]);
-    ir.InvokeContinuation invokeLoop =
-        new ir.InvokeContinuation.uninitialized(recursive: true);
-    invokeLoop.arguments =
-        continueBuilder.environment.index2value.map(
-            (ir.Primitive value) => new ir.Reference(value)).toList();
-    repeatContinuation.body = invokeLoop;
+    IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder();
+    repeatBuilder.jumpTo(loop);
+    repeatContinuation.body = repeatBuilder._root;
+
     continueBuilder.add(
         new ir.LetCont.many(<ir.Continuation>[exitContinuation,
                                               repeatContinuation],
             new ir.Branch(new ir.IsTrue(condition),
                           repeatContinuation,
                           exitContinuation)));
-    ir.Continuation continueContinuation =
-        new ir.Continuation(continueBuilder._parameters);
-    continueContinuation.body = continueBuilder._root;
+    continueCollector.continuation.body = continueBuilder._root;
 
     // Construct the loop continuation (i.e., the body and condition).
     // <Loop> =
     // let cont continue(x, ...) =
     //   <Continue>
     // in [[body]]; continue(v, ...)
-    JumpCollector breakCollector = new JumpCollector(target);
-    JumpCollector continueCollector = new JumpCollector(target);
-    state.breakCollectors.add(breakCollector);
-    state.continueCollectors.add(continueCollector);
-    bodyBuilder._enterScope(closureScope);
-    buildBody(bodyBuilder);
-    assert(state.breakCollectors.last == breakCollector);
-    assert(state.continueCollectors.last == continueCollector);
-    state.breakCollectors.removeLast();
-    state.continueCollectors.removeLast();
-    // Add the jump from the loop's exit to the break condition.  It is only
-    // here where the exitBuilder's root is non-null and we can set the
-    // exitContinuation's body.
-    breakCollector.addJump(exitBuilder);
-    exitContinuation.body = exitBuilder._root;
-    if (bodyBuilder.isOpen) {
-      continueCollector.addJump(bodyBuilder);
-    }
-    invokeFullJoin(continueContinuation, continueCollector, recursive: false);
-    ir.Continuation loopContinuation =
-        new ir.Continuation(bodyBuilder._parameters);
-    loopContinuation.isRecursive = true;
-    loopContinuation.body =
-        new ir.LetCont(continueContinuation, bodyBuilder._root);
-    invokeLoop.continuation =
-        new ir.Reference<ir.Continuation>(loopContinuation);
-    ir.LetCont letLoop =
-        new ir.LetCont(loopContinuation,
-            new ir.InvokeContinuation(loopContinuation,
-                                      environment.index2value));
+    loopBuilder.add(
+        new ir.LetCont(continueCollector.continuation,
+            bodyBuilder._root));
 
-    // Add the break condition.
-    ir.Continuation breakContinuation;
-    if (breakCollector.length == 1) {
-      // createJoin only works when there is more than one jump to a join-point
-      // continuation.  This is to potentially catch errors in the case that
-      // a join was intended and at least one jump is missing.  Unfortunately
-      // we have the explicit code below for the (common?) case that the
-      // only break from the do-while is the implicit one when the condition
-      // is false.
-      List<ir.Parameter> parameters = <ir.Parameter>[];
-      List<ir.Reference> arguments = <ir.Reference>[];
-      for (int i = 0; i < environment.length; ++i) {
-        ir.Parameter parameter =
-            new ir.Parameter(environment.index2variable[i]);
-        parameters.add(parameter);
-        environment.index2value[i] = parameter;
-        arguments.add(new ir.Reference(breakCollector.environments.first[i]));
-      }
-      breakContinuation = new ir.Continuation(parameters);
-      breakCollector.invocations.first.arguments = arguments;
-      breakCollector.invocations.first.continuation =
-          new ir.Reference(breakContinuation);
-    } else {
-      breakContinuation = createJoin(environment.length, breakCollector);
-    }
-    add(new ir.LetCont(breakContinuation, letLoop));
+    // And tie it all together.
+    add(new ir.LetCont(breakCollector.continuation, loopBuilder._root));
+    environment = breakCollector.environment;
   }
 
   /// Creates a try-statement.
@@ -1502,35 +1573,26 @@
     // 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 that are boxed due to being captured in a closure are boxed
     // for their entire lifetime, and so they do not need to be boxed on
-    // entry to any try block.  We check for them here because we can not
-    // identify all of them in the same pass where we identify the variables
-    // assigned in the try (the may be captured by a closure after the try
-    // statement).
-    Iterable<LocalVariableElement> boxedOnEntry =
-        tryStatementInfo.boxedOnEntry.where((LocalVariableElement variable) {
-      return !tryCatchBuilder.mutableCapturedVariables.contains(variable);
-    });
-    for (LocalVariableElement variable in boxedOnEntry) {
+    // entry to any try block.  They are not filtered out before this because
+    // we can not identify all of them in the same pass where we identify the
+    // variables assigned in the try (they may be captured by a closure after
+    // the try statement).
+    for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
       assert(!tryCatchBuilder.isInMutableVariable(variable));
       ir.Primitive value = tryCatchBuilder.buildLocalGet(variable);
       tryCatchBuilder.makeMutableVariable(variable);
       tryCatchBuilder.declareLocalVariable(variable, initialValue: value);
     }
 
-    IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
     IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
-    List<ir.Parameter> joinParameters =
-        new List<ir.Parameter>.generate(environment.length, (i) {
-      return new ir.Parameter(environment.index2variable[i]);
-    });
-    ir.Continuation joinContinuation = new ir.Continuation(joinParameters);
 
     void interceptJumps(JumpCollector collector) {
-      collector.enterTry(boxedOnEntry);
+      collector.enterTry(tryStatementInfo.boxedOnEntry);
     }
     void restoreJumps(JumpCollector collector) {
       collector.leaveTry();
@@ -1538,18 +1600,16 @@
     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);
-    if (tryBuilder.isOpen) {
-      for (LocalVariableElement variable in boxedOnEntry) {
-        assert(tryBuilder.isInMutableVariable(variable));
-        ir.Primitive value = tryBuilder.buildLocalGet(variable);
-        tryBuilder.environment.update(variable, value);
-      }
-      tryBuilder.jumpTo(joinContinuation);
-    }
 
-    for (LocalVariableElement variable in boxedOnEntry) {
+    IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
+    for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
       assert(catchBuilder.isInMutableVariable(variable));
       ir.Primitive value = catchBuilder.buildLocalGet(variable);
       // Note that we remove the variable from the set of mutable variables
@@ -1580,9 +1640,7 @@
         traceParameter = new ir.Parameter(null);
       }
       catchClauseInfo.buildCatchBlock(catchBuilder);
-      if (catchBuilder.isOpen) {
-        catchBuilder.jumpTo(joinContinuation);
-      }
+      if (catchBuilder.isOpen) catchBuilder.jumpTo(join);
       List<ir.Parameter> catchParameters =
           <ir.Parameter>[exceptionParameter, traceParameter];
       ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
@@ -1593,10 +1651,8 @@
       tryCatchBuilder._current = null;
     }
 
-    add(new ir.LetCont(joinContinuation, tryCatchBuilder._root));
-    for (int i = 0; i < environment.length; ++i) {
-      environment.index2value[i] = joinParameters[i];
-    }
+    add(new ir.LetCont(join.continuation, tryCatchBuilder._root));
+    environment = join.environment;
   }
 
   /// Create a return statement `return value;` or `return;` if [value] is
@@ -1637,48 +1693,28 @@
     }
   }
 
-
   /// Creates a labeled statement
   void buildLabeledStatement({SubbuildFunction buildBody,
                               JumpTarget target}) {
-    JumpCollector jumps = new JumpCollector(target);
-    state.breakCollectors.add(jumps);
+    JumpCollector join = new ForwardJumpCollector(environment, target: target);
     IrBuilder innerBuilder = makeDelimitedBuilder();
+    innerBuilder.state.breakCollectors.add(join);
     buildBody(innerBuilder);
-    state.breakCollectors.removeLast();
-    bool hasBreaks = !jumps.isEmpty;
-    ir.Continuation joinContinuation;
+    innerBuilder.state.breakCollectors.removeLast();
+    bool hasBreaks = !join.isEmpty;
     if (hasBreaks) {
-      if (innerBuilder.isOpen) {
-        jumps.addJump(innerBuilder);
-      }
-
-      // All jumps to the break continuation must be in the scope of the
-      // continuation's binding.  The continuation is bound just outside the
-      // body to satisfy this property without extra analysis.
-      // As a consequence, the break continuation needs parameters for all
-      // local variables in scope at the exit from the body.
-      List<ir.Parameter> parameters =
-          new List<ir.Parameter>.generate(environment.length, (i) {
-        return new ir.Parameter(environment.index2variable[i]);
-      });
-      joinContinuation = new ir.Continuation(parameters);
-      invokeFullJoin(joinContinuation, jumps, recursive: false);
-      add(new ir.LetCont(joinContinuation, innerBuilder._root));
-      for (int i = 0; i < environment.length; ++i) {
-        environment.index2value[i] = parameters[i];
-      }
+      if (innerBuilder.isOpen) innerBuilder.jumpTo(join);
+      add(new ir.LetCont(join.continuation, innerBuilder._root));
+      environment = join.environment;
+    } else if (innerBuilder._root != null) {
+      add(innerBuilder._root);
+      _current = innerBuilder._current;
+      environment = innerBuilder.environment;
     } else {
-      if (innerBuilder._root != null) {
-        add(innerBuilder._root);
-        _current = innerBuilder._current;
-        environment = innerBuilder.environment;
-      }
+      // The translation of the body did not emit any CPS term.
     }
-    return null;
   }
 
-
   // Build(BreakStatement L, C) = C[InvokeContinuation(...)]
   //
   // The continuation and arguments are filled in later after translating
@@ -1700,7 +1736,7 @@
     assert(isOpen);
     for (JumpCollector collector in collectors) {
       if (target == collector.target) {
-        collector.addJump(this);
+        jumpTo(collector);
         return true;
       }
     }
@@ -1768,7 +1804,6 @@
     // e0 || e1 is translated as if e0 ? true : (e1 == true).
     // The translation must convert both e0 and e1 to booleans and handle
     // local variable assignments in e1.
-
     IrBuilder rightBuilder = makeDelimitedBuilder();
     ir.Primitive rightValue = buildRightValue(rightBuilder);
     // A dummy empty target for the branch on the left subexpression branch.
@@ -1795,18 +1830,19 @@
     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 jumps = new JumpCollector(null);
-    jumps.addJump(emptyBuilder);
-    jumps.addJump(rightTrueBuilder);
-    jumps.addJump(rightFalseBuilder);
-    ir.Continuation joinContinuation =
-        createJoin(environment.length + 1, jumps);
+    JumpCollector join = new ForwardJumpCollector(environment);
+    emptyBuilder.jumpTo(join);
+    rightTrueBuilder.jumpTo(join);
+    rightFalseBuilder.jumpTo(join);
     ir.Continuation leftTrueContinuation = new ir.Continuation([]);
     ir.Continuation leftFalseContinuation = new ir.Continuation([]);
     ir.Continuation rightTrueContinuation = new ir.Continuation([]);
@@ -1831,120 +1867,17 @@
       leftFalseContinuation.body = emptyBuilder._root;
     }
 
-    add(new ir.LetCont(joinContinuation,
+    add(new ir.LetCont(join.continuation,
             new ir.LetCont.many(<ir.Continuation>[leftTrueContinuation,
                                                   leftFalseContinuation],
                 new ir.Branch(new ir.IsTrue(leftValue),
                               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 joinContinuation.parameters.last;
-  }
-
-  /// Create a non-recursive join-point continuation.
-  ///
-  /// Given the environment length at the join point and a list of
-  /// jumps that should reach the join point, create a join-point
-  /// continuation.  The join-point continuation has a parameter for each
-  /// variable that has different values reaching on different paths.
-  ///
-  /// The jumps are uninitialized [ir.InvokeContinuation] expressions.
-  /// They are filled in with the target continuation and appropriate
-  /// arguments.
-  ///
-  /// As a side effect, the environment of this builder is updated to include
-  /// the join-point continuation parameters.
-  ir.Continuation createJoin(int environmentLength, JumpCollector jumps) {
-    assert(jumps.length >= 2);
-
-    // Compute which values are identical on all paths reaching the join.
-    // Handle the common case of a pair of contexts efficiently.
-    Environment first = jumps.environments[0];
-    Environment second = jumps.environments[1];
-    assert(environmentLength <= first.length);
-    assert(environmentLength <= second.length);
-    assert(first.sameDomain(environmentLength, second));
-    // A running count of the join-point parameters.
-    int parameterCount = 0;
-    // The null elements of common correspond to required parameters of the
-    // join-point continuation.
-    List<ir.Primitive> common =
-        new List<ir.Primitive>.generate(environmentLength,
-            (i) {
-              ir.Primitive candidate = first[i];
-              if (second[i] == candidate) {
-                return candidate;
-              } else {
-                ++parameterCount;
-                return null;
-              }
-            });
-    // If there is already a parameter for each variable, the other
-    // environments do not need to be considered.
-    if (parameterCount < environmentLength) {
-      for (int i = 0; i < environmentLength; ++i) {
-        ir.Primitive candidate = common[i];
-        if (candidate == null) continue;
-        for (Environment current in jumps.environments.skip(2)) {
-          assert(environmentLength <= current.length);
-          assert(first.sameDomain(environmentLength, current));
-          if (candidate != current[i]) {
-            common[i] = null;
-            ++parameterCount;
-            break;
-          }
-        }
-        if (parameterCount >= environmentLength) break;
-      }
-    }
-
-    // Create the join point continuation.
-    List<ir.Parameter> parameters = <ir.Parameter>[];
-    parameters.length = parameterCount;
-    int index = 0;
-    for (int i = 0; i < environmentLength; ++i) {
-      if (common[i] == null) {
-        parameters[index++] = new ir.Parameter(first.index2variable[i]);
-      }
-    }
-    assert(index == parameterCount);
-    ir.Continuation join = new ir.Continuation(parameters);
-
-    // Fill in all the continuation invocations.
-    for (int i = 0; i < jumps.length; ++i) {
-      Environment currentEnvironment = jumps.environments[i];
-      ir.InvokeContinuation invoke = jumps.invocations[i];
-      // Sharing this.environment with one of the invocations will not do
-      // the right thing (this.environment has already been mutated).
-      List<ir.Reference> arguments = <ir.Reference>[];
-      arguments.length = parameterCount;
-      int index = 0;
-      for (int i = 0; i < environmentLength; ++i) {
-        if (common[i] == null) {
-          arguments[index++] = new ir.Reference(currentEnvironment[i]);
-        }
-      }
-      invoke.continuation = new ir.Reference(join);
-      invoke.arguments = arguments;
-    }
-
-    // Mutate this.environment to be the environment at the join point.  Do
-    // this after adding the continuation invocations, because this.environment
-    // might be collected by the jump collector and so the old environment
-    // values are needed for the continuation invocation.
-    //
-    // Iterate to environment.length because environmentLength includes values
-    // outside the environment which are 'phantom' variables used for the
-    // values of expressions like &&, ||, and ?:.
-    index = 0;
-    for (int i = 0; i < environment.length; ++i) {
-      if (common[i] == null) {
-        environment.index2value[i] = parameters[index++];
-      }
-    }
-
-    return join;
+    return join.continuation.parameters.last;
   }
 }
 
@@ -1954,9 +1887,6 @@
   final Map<Local, ir.MutableVariable> local2mutable =
       <Local, ir.MutableVariable>{};
 
-  // Move this to the IrBuilderVisitor.
-  final DartCapturedVariables capturedVariables;
-
   /// Creates a [MutableVariable] for the given local.
   void makeMutableVariable(Local local) {
     ir.MutableVariable variable =
@@ -1967,8 +1897,8 @@
   /// [MutableVariable]s that should temporarily be treated as registers.
   final Set<Local> registerizedMutableVariables = new Set<Local>();
 
-  DartIrBuilderSharedState(this.capturedVariables) {
-    capturedVariables.capturedVariables.forEach(makeMutableVariable);
+  DartIrBuilderSharedState(Set<Local> capturedVariables) {
+    capturedVariables.forEach(makeMutableVariable);
   }
 }
 
@@ -1987,19 +1917,11 @@
 
   DartIrBuilder(ConstantSystem constantSystem,
                 ExecutableElement currentElement,
-                DartCapturedVariables capturedVariables)
+                Set<Local> capturedVariables)
       : dartState = new DartIrBuilderSharedState(capturedVariables) {
     _init(constantSystem, currentElement);
   }
 
-  Map<ast.TryStatement, TryStatementInfo> get tryStatements {
-    return dartState.capturedVariables.tryStatements;
-  }
-
-  Set<Local> get mutableCapturedVariables {
-    return dartState.capturedVariables.capturedVariables;
-  }
-
   bool isInMutableVariable(Local local) {
     return dartState.local2mutable.containsKey(local) &&
            !dartState.registerizedMutableVariables.contains(local);
@@ -2070,7 +1992,7 @@
     }
   }
 
-  void _createFunctionParameter(ParameterElement parameterElement) {
+  void _createFunctionParameter(Local parameterElement) {
     ir.Parameter parameter = new ir.Parameter(parameterElement);
     _parameters.add(parameter);
     if (isInMutableVariable(parameterElement)) {
@@ -2169,6 +2091,16 @@
     return _buildInvokeSuper(target, selector, arguments);
   }
 
+  @override
+  ir.Primitive buildConstructorInvocation(FunctionElement element,
+                                          Selector selector,
+                                          DartType type,
+                                          List<ir.Primitive> arguments) {
+    assert(isOpen);
+    return _continueWithExpression(
+        (k) => new ir.InvokeConstructor(type, element, selector, k,
+            arguments));
+  }
 }
 
 /// State shared between JsIrBuilders within the same function.
@@ -2181,6 +2113,10 @@
 
   /// 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].
@@ -2189,11 +2125,13 @@
 /// variables are boxed as necessary using [CreateBox], [GetField], [SetField].
 class JsIrBuilder extends IrBuilder {
   final JsIrBuilderSharedState jsState;
+  final GlobalProgramInformation program;
 
-  IrBuilder _makeInstance() => new JsIrBuilder._blank(jsState);
-  JsIrBuilder._blank(this.jsState);
+  IrBuilder _makeInstance() => new JsIrBuilder._blank(program, jsState);
+  JsIrBuilder._blank(this.program, this.jsState);
 
-  JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement)
+  JsIrBuilder(this.program, ConstantSystem constantSystem,
+      ExecutableElement currentElement)
       : jsState = new JsIrBuilderSharedState() {
     _init(constantSystem, currentElement);
   }
@@ -2204,6 +2142,16 @@
   void makeMutableVariable(Local local) {}
   void removeMutableVariable(Local local) {}
 
+  void enterInitializers() {
+    assert(jsState.inInitializers == false);
+    jsState.inInitializers = true;
+  }
+
+  void leaveInitializers() {
+    assert(jsState.inInitializers == true);
+    jsState.inInitializers = false;
+  }
+
   void _enterClosureEnvironment(ClosureEnvironment env) {
     if (env == null) return;
 
@@ -2255,7 +2203,7 @@
     });
   }
 
-  void _createFunctionParameter(ParameterElement parameterElement) {
+  void _createFunctionParameter(Local parameterElement) {
     ir.Parameter parameter = new ir.Parameter(parameterElement);
     _parameters.add(parameter);
     state.functionParameters.add(parameter);
@@ -2310,7 +2258,8 @@
           : environment.lookup(field.local);
       arguments.add(value);
     }
-    return addPrimitive(new ir.CreateInstance(classElement, arguments));
+    return addPrimitive(
+        new ir.CreateInstance(classElement, arguments, const <ir.Primitive>[]));
   }
 
   /// Create a read access of [local].
@@ -2430,6 +2379,64 @@
       jsState.boxedVariables.addAll(closureScope.capturedVariables);
     }
   }
+
+  @override
+  ir.Primitive buildConstructorInvocation(ConstructorElement element,
+                                          Selector selector,
+                                          DartType type,
+                                          List<ir.Primitive> arguments) {
+    assert(isOpen);
+
+    ClassElement cls = element.enclosingClass;
+    if (program.requiresRuntimeTypesFor(cls)) {
+      InterfaceType interface = type;
+      Iterable<ir.Primitive> typeArguments =
+          interface.typeArguments.map((DartType argument) {
+        return type.treatAsRaw
+            ? buildNullLiteral()
+            : buildTypeExpression(argument);
+      });
+      arguments = new List<ir.Primitive>.from(arguments)
+          ..addAll(typeArguments);
+    }
+    return _continueWithExpression(
+        (k) => new ir.InvokeConstructor(type, element, selector, k,
+            arguments));
+  }
+
+  ir.Primitive buildTypeExpression(DartType type) {
+    if (type is TypeVariableType) {
+      return buildTypeVariableAccess(buildThis(), type);
+    } else {
+      assert(type is InterfaceType);
+      List<ir.Primitive> arguments = <ir.Primitive>[];
+      type.forEachTypeVariable((TypeVariableType variable) {
+        ir.Primitive value = buildTypeVariableAccess(buildThis(), variable);
+        arguments.add(value);
+      });
+      return addPrimitive(new ir.TypeExpression(type, arguments));
+    }
+  }
+
+  ir.Primitive buildTypeVariableAccess(ir.Primitive target,
+                                       TypeVariableType variable) {
+    ir.Parameter accessTypeArgumentParameter() {
+      for (int i = 0; i < environment.length; i++) {
+        Local local = environment.index2variable[i];
+        if (local is TypeInformationParameter &&
+            local.variable == variable.element) {
+          return environment.index2value[i];
+        }
+      }
+      throw 'unable to find constructor parameter for type variable $variable.';
+    }
+
+    if (jsState.inInitializers) {
+      return accessTypeArgumentParameter();
+    } else {
+      return addPrimitive(new ir.ReadTypeVariable(variable, target));
+    }
+  }
 }
 
 
@@ -2501,3 +2508,12 @@
                    this.stackTraceVariable,
                    this.buildCatchBlock});
 }
+
+/// Synthetic parameter to a JavaScript factory method that takes the type
+/// argument given for the type variable [variable].
+class TypeInformationParameter implements Local {
+  final TypeVariableElement variable;
+  final ExecutableElement executableContext;
+  TypeInformationParameter(this.variable, this.executableContext);
+  String get name => variable.name;
+}
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 f375244..289b230 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
@@ -19,7 +19,7 @@
 import '../resolution/operators.dart' as op;
 import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator;
 import '../tree/tree.dart' as ast;
-import '../universe/universe.dart' show SelectorKind;
+import '../universe/universe.dart' show SelectorKind, CallStructure;
 import 'cps_ir_nodes.dart' as ir;
 import 'cps_ir_builder.dart';
 
@@ -41,10 +41,11 @@
  * re-implemented to work directly on the IR.
  */
 class IrBuilderTask extends CompilerTask {
-  final Map<Element, ir.ExecutableDefinition> nodes =
-      <Element, ir.ExecutableDefinition>{};
+  final Map<Element, ir.RootNode> nodes = <Element, ir.RootNode>{};
   final bool generateSourceMap;
 
+  String bailoutMessage = null;
+
   IrBuilderTask(Compiler compiler, {this.generateSourceMap: true})
       : super(compiler);
 
@@ -52,12 +53,16 @@
 
   bool hasIr(Element element) => nodes.containsKey(element.implementation);
 
-  ir.ExecutableDefinition getIr(ExecutableElement element) {
+  ir.RootNode getIr(ExecutableElement element) {
     return nodes[element.implementation];
   }
 
-  ir.ExecutableDefinition buildNode(AstElement element) {
-    if (!canBuild(element)) return null;
+  ir.RootNode buildNode(AstElement element) {
+    bailoutMessage = null;
+    if (!canBuild(element)) {
+      bailoutMessage = 'unsupported element ${element.name}:${element.kind}';
+      return null;
+    }
 
     TreeElements elementsMapping = element.resolvedAst.elements;
     element = element.implementation;
@@ -72,12 +77,13 @@
               elementsMapping, compiler, sourceInformationBuilder)
           : new DartIrBuilderVisitor(
               elementsMapping, compiler, sourceInformationBuilder);
-      ir.ExecutableDefinition definition =
-            builder.buildExecutable(element);
-      if (definition != null) {
-        nodes[element] = definition;
+      ir.RootNode irNode = builder.buildExecutable(element);
+      if (irNode == null) {
+        bailoutMessage = builder.bailoutMessage;
+      } else {
+        nodes[element] = irNode;
       }
-      return definition;
+      return irNode;
     });
   }
 
@@ -130,11 +136,20 @@
          BaseImplementationOfDynamicsMixin<ir.Primitive, dynamic>,
          BaseImplementationOfConstantsMixin<ir.Primitive, dynamic>,
          BaseImplementationOfSuperIncDecsMixin<ir.Primitive, dynamic>,
+         BaseImplementationOfNewMixin<ir.Primitive, dynamic>,
          ErrorBulkMixin<ir.Primitive, dynamic>
     implements SemanticSendVisitor<ir.Primitive, dynamic> {
   final Compiler compiler;
   final SourceInformationBuilder sourceInformationBuilder;
 
+  /// A map from try statements in the source to analysis information about
+  /// them.
+  ///
+  /// 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;
+
   // In SSA terms, join-point continuation parameters are the phis and the
   // continuation invocation arguments are the corresponding phi inputs.  To
   // support name introduction and renaming for source level variables, we use
@@ -160,7 +175,9 @@
       : super(elements);
 
   @override
-  bulkHandleNode(ast.Node node, String message) => giveup(node, message);
+  bulkHandleNode(ast.Node node, String message, _) => giveup(node, message);
+
+  String bailoutMessage = null;
 
   @override
   ir.Primitive apply(ast.Node node, _) => node.accept(this);
@@ -169,11 +186,11 @@
   SemanticSendVisitor get sendVisitor => this;
 
   /**
-   * Builds the [ir.ExecutableDefinition] for an executable element. In case the
+   * Builds the [ir.RootNode] for an executable element. In case the
    * function uses features that cannot be expressed in the IR, this element
    * returns `null`.
    */
-  ir.ExecutableDefinition buildExecutable(ExecutableElement element);
+  ir.RootNode buildExecutable(ExecutableElement element);
 
   ClosureScope getClosureScopeForNode(ast.Node node);
   ClosureEnvironment getClosureEnvironment();
@@ -186,7 +203,7 @@
   ///
   /// For the Dart backend, returns [arguments].
   List<ir.Primitive> normalizeStaticArguments(
-      Selector selector,
+      CallStructure callStructure,
       FunctionElement target,
       List<ir.Primitive> arguments);
 
@@ -200,8 +217,8 @@
       Selector selector,
       List<ir.Primitive> arguments);
 
-  ir.FunctionDefinition _makeFunctionBody(FunctionElement element,
-                                          ast.FunctionExpression node) {
+  ir.RootNode _makeFunctionBody(FunctionElement element,
+                                ast.FunctionExpression node) {
     FunctionSignature signature = element.functionSignature;
     List<ParameterElement> parameters = [];
     signature.orderedForEachParameter(parameters.add);
@@ -246,7 +263,7 @@
           ir.Primitive value = irBuilder.buildLocalGet(parameterElement);
           result.add(irBuilder.makeFieldInitializer(
               initializingFormal.fieldElement,
-              irBuilder.makeRunnableBody(value)));
+              irBuilder.makeBody(value)));
         });
       }
     }
@@ -262,7 +279,7 @@
         FieldElement field = elements[initializer];
         withBuilder(irBuilder.makeInitializerBuilder(), () {
           ir.Primitive value = visit(initializer.arguments.head);
-          ir.RunnableBody body = irBuilder.makeRunnableBody(value);
+          ir.Body body = irBuilder.makeBody(value);
           result.add(irBuilder.makeFieldInitializer(field, body));
         });
       } else if (initializer is ast.Send) {
@@ -272,11 +289,11 @@
         }
         ConstructorElement constructor = elements[initializer].implementation;
         Selector selector = elements.getSelector(initializer);
-        List<ir.RunnableBody> arguments =
+        List<ir.Body> arguments =
             initializer.arguments.mapToList((ast.Node argument) {
           return withBuilder(irBuilder.makeInitializerBuilder(), () {
             ir.Primitive value = visit(argument);
-            return irBuilder.makeRunnableBody(value);
+            return irBuilder.makeBody(value);
           });
         });
         result.add(irBuilder.makeSuperInitializer(constructor,
@@ -302,7 +319,7 @@
         }
         Selector selector = new Selector.callDefaultConstructor();
         result.add(irBuilder.makeSuperInitializer(target,
-                                                  <ir.RunnableBody>[],
+                                                  <ir.Body>[],
                                                   selector));
       }
     }
@@ -462,7 +479,7 @@
 
   visitTryStatement(ast.TryStatement node) {
     // Try/catch is not yet implemented in the JS backend.
-    if (this.irBuilder.tryStatements == null) {
+    if (tryStatements == null) {
       return giveup(node, 'try/catch in the JS backend');
     }
     // Multiple catch blocks are not yet implemented.
@@ -494,7 +511,7 @@
     }
 
     irBuilder.buildTry(
-        tryStatementInfo: irBuilder.tryStatements[node],
+        tryStatementInfo: tryStatements[node],
         buildTryBlock: subbuild(node.tryBlock),
         catchClauseInfos: catchClauseInfos);
   }
@@ -641,8 +658,9 @@
   }
 
   @override
-  ir.Primitive handleConstantGet(ast.Send node,
-                                 ConstantExpression constant, _) {
+  ir.Primitive handleConstantGet(
+      ast.Node node,
+      ConstantExpression constant, _) {
     return irBuilder.buildConstantLiteral(constant);
   }
 
@@ -922,8 +940,10 @@
   ir.Primitive visitUnary(ast.Send node,
                           op.UnaryOperator operator, ast.Node expression, _) {
     // TODO(johnniwinther): Clean up the creation of selectors.
-    Selector selector =
-        new Selector(SelectorKind.OPERATOR, operator.selectorName, null, 0);
+    Selector selector = new Selector(
+        SelectorKind.OPERATOR,
+        new PublicName(operator.selectorName),
+        CallStructure.NO_ARGS);
     ir.Primitive receiver = translateReceiver(expression);
     return irBuilder.buildDynamicInvocation(receiver, selector, const []);
   }
@@ -935,8 +955,10 @@
       FunctionElement function,
       _) {
     // TODO(johnniwinther): Clean up the creation of selectors.
-    Selector selector =
-        new Selector(SelectorKind.OPERATOR, operator.selectorName, null, 0);
+    Selector selector = new Selector(
+        SelectorKind.OPERATOR,
+        new PublicName(operator.selectorName),
+        CallStructure.NO_ARGS);
     return irBuilder.buildSuperInvocation(function, selector, const []);
   }
 
@@ -952,9 +974,9 @@
   // semantic correlation between arguments and invocation.
   List<ir.Primitive> translateStaticArguments(ast.NodeList nodeList,
                                               Element element,
-                                              Selector selector) {
+                                              CallStructure callStructure) {
     List<ir.Primitive> arguments = nodeList.nodes.mapToList(visit);
-    return normalizeStaticArguments(selector, element, arguments);
+    return normalizeStaticArguments(callStructure, element, arguments);
   }
 
   ir.Primitive translateCallInvoke(ir.Primitive target,
@@ -1030,7 +1052,7 @@
       return giveup(node, 'handleStaticFunctionInvoke: foreign: $function');
     }
     return irBuilder.buildStaticInvocation(function, selector,
-        translateStaticArguments(arguments, function, selector),
+        translateStaticArguments(arguments, function, selector.callStructure),
         sourceInformation: sourceInformationBuilder.buildCall(node));
   }
 
@@ -1703,19 +1725,19 @@
         });
   }
 
-  ir.Primitive visitNewExpression(ast.NewExpression node) {
-    if (node.isConst) {
-      return translateConstant(node);
-    }
-    FunctionElement element = elements[node.send];
-    Selector selector = elements.getSelector(node.send);
-    DartType type = elements.getType(node);
-    ast.Node selectorNode = node.send.selector;
+  @override
+  ir.Primitive handleConstructorInvoke(
+      ast.NewExpression node,
+      ConstructorElement constructor,
+      DartType type,
+      ast.NodeList arguments,
+      Selector selector, _) {
     List<ir.Primitive> arguments =
         node.send.arguments.mapToList(visit, growable:false);
-    arguments = normalizeStaticArguments(selector, element, arguments);
+    arguments = normalizeStaticArguments(
+        selector.callStructure, constructor, arguments);
     return irBuilder.buildConstructorInvocation(
-        element, selector, type, arguments);
+        constructor, selector, type, arguments);
   }
 
   ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
@@ -1743,7 +1765,7 @@
     return irBuilder.buildConstantLiteral(getConstantForNode(node));
   }
 
-  ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) {
+  ir.RootNode nullIfGiveup(ir.RootNode action()) {
     try {
       return action();
     } catch(e, tr) {
@@ -1755,21 +1777,22 @@
   }
 
   void internalError(ast.Node node, String message) {
-    giveup(node);
+    giveup(node, message);
   }
 
   @override
   visitNode(ast.Node node) {
     internalError(node, "Unhandled node");
   }
+
+  dynamic giveup(ast.Node node, [String reason]) {
+    bailoutMessage = '($node): $reason';
+    throw ABORT_IRNODE_BUILDER;
+  }
 }
 
 final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
 
-dynamic giveup(ast.Node node, [String reason]) {
-  throw ABORT_IRNODE_BUILDER;
-}
-
 /// Classifies local variables and local functions as captured, if they
 /// are accessed from within a nested function.
 ///
@@ -1791,10 +1814,29 @@
   List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[];
   bool get inTryStatement => tryNestingStack.isNotEmpty;
 
+  String bailoutMessage = null;
+
+  giveup(ast.Node node, [String reason]) {
+    bailoutMessage = '($node): $reason';
+    throw ABORT_IRNODE_BUILDER;
+  }
+
   void markAsCaptured(Local local) {
     capturedVariables.add(local);
   }
 
+  analyze(ast.Node node) {
+    visit(node);
+    // Variables that are captured by a closure are boxed for their entire
+    // lifetime, so they never need to be boxed on entry to a try block.
+    // They are not filtered out before this because we cannot identify all
+    // of them in the same pass (they may be captured by a closure after the
+    // try statement).
+    for (TryStatementInfo info in tryStatements.values) {
+      info.boxedOnEntry.removeAll(capturedVariables);
+    }
+  }
+
   visit(ast.Node node) => node.accept(this);
 
   visitNode(ast.Node node) {
@@ -1920,14 +1962,25 @@
                        SourceInformationBuilder sourceInformationBuilder)
       : super(elements, compiler, sourceInformationBuilder);
 
-  DartIrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) {
-    DartCapturedVariables closures = new DartCapturedVariables(elements);
-    if (!element.isSynthesized) {
-      closures.visit(node);
-    }
+  DartIrBuilder makeIRBuilder(ExecutableElement element,
+                              Set<Local> capturedVariables) {
     return new DartIrBuilder(compiler.backend.constantSystem,
                              element,
-                             closures);
+                             capturedVariables);
+  }
+
+  DartCapturedVariables _analyzeCapturedVariables(ExecutableElement element,
+                                                  ast.Node node) {
+    DartCapturedVariables variables = new DartCapturedVariables(elements);
+    if (!element.isSynthesized) {
+      try {
+        variables.analyze(node);
+      } catch (e) {
+        bailoutMessage = variables.bailoutMessage;
+        rethrow;
+      }
+    }
+    return variables;
   }
 
   /// Recursively builds the IR for the given nested function.
@@ -1953,11 +2006,11 @@
   ClosureScope getClosureScopeForNode(ast.Node node) => null;
   ClosureEnvironment getClosureEnvironment() => null;
 
-  ir.ExecutableDefinition buildExecutable(ExecutableElement element) {
+  ir.RootNode buildExecutable(ExecutableElement element) {
     return nullIfGiveup(() {
       if (element is FieldElement) {
         return buildField(element);
-      } else if (element is FunctionElement) {
+      } else if (element is FunctionElement || element is ConstructorElement) {
         return buildFunction(element);
       } else {
         compiler.internalError(element, "Unexpected element type $element");
@@ -1976,7 +2029,10 @@
     assert(fieldDefinition != null);
     assert(elements[fieldDefinition] != null);
 
-    IrBuilder builder = makeIRBuilder(fieldDefinition, element);
+    DartCapturedVariables variables =
+        _analyzeCapturedVariables(element, fieldDefinition);
+    tryStatements = variables.tryStatements;
+    IrBuilder builder = makeIRBuilder(element, variables.capturedVariables);
 
     return withBuilder(builder, () {
       builder.buildFieldInitializerHeader(
@@ -1990,7 +2046,7 @@
     });
   }
 
-  ir.FunctionDefinition buildFunction(FunctionElement element) {
+  ir.RootNode buildFunction(FunctionElement element) {
     assert(invariant(element, element.isImplementation));
     ast.FunctionExpression node = element.node;
     if (element.asyncMarker != AsyncMarker.SYNC) {
@@ -2007,13 +2063,16 @@
       }
     }
 
-    IrBuilder builder = makeIRBuilder(node, element);
+    DartCapturedVariables variables =
+        _analyzeCapturedVariables(element, node);
+    tryStatements = variables.tryStatements;
+    IrBuilder builder = makeIRBuilder(element, variables.capturedVariables);
 
     return withBuilder(builder, () => _makeFunctionBody(element, node));
   }
 
   List<ir.Primitive> normalizeStaticArguments(
-      Selector selector,
+      CallStructure callStructure,
       FunctionElement target,
       List<ir.Primitive> arguments) {
     return arguments;
@@ -2035,6 +2094,21 @@
   }
 }
 
+/// The [IrBuilder]s view on the information about the program that has been
+/// computed in resolution and and type interence.
+class GlobalProgramInformation {
+  final Compiler _compiler;
+  JavaScriptBackend get _backend => _compiler.backend;
+
+  GlobalProgramInformation(this._compiler);
+
+  /// Returns [true], if the analysis could not determine that the type
+  /// arguments for the class [cls] are never used in the program.
+  bool requiresRuntimeTypesFor(ClassElement cls) {
+    return cls.typeVariables.isNotEmpty && _backend.classNeedsRti(cls);
+  }
+}
+
 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
 class JsIrBuilderVisitor extends IrBuilderVisitor {
   /// Promote the type of [irBuilder] to [JsIrBuilder].
@@ -2136,7 +2210,7 @@
                             scope.boxedLoopVariables);
   }
 
-  ir.ExecutableDefinition buildExecutable(ExecutableElement element) {
+  ir.RootNode buildExecutable(ExecutableElement element) {
     return nullIfGiveup(() {
       switch (element.kind) {
         case ElementKind.GENERATIVE_CONSTRUCTOR:
@@ -2180,6 +2254,13 @@
     return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
   }
 
+  JsIrBuilder getBuilderFor(Element element) {
+    return new JsIrBuilder(
+        new GlobalProgramInformation(compiler),
+        compiler.backend.constantSystem,
+        element);
+  }
+
   /// Builds the IR for a given constructor.
   ///
   /// 1. Evaluates all own or inherited field initializers.
@@ -2190,20 +2271,47 @@
     constructor = constructor.implementation;
     ClassElement classElement = constructor.enclosingClass.implementation;
 
-    JsIrBuilder builder =
-        new JsIrBuilder(compiler.backend.constantSystem, constructor);
+    JsIrBuilder builder = getBuilderFor(constructor);
+
+    final bool requiresTypeInformation =
+        builder.program.requiresRuntimeTypesFor(classElement);
 
     return withBuilder(builder, () {
       // Setup parameters and create a box if anything is captured.
-      List<ParameterElement> parameters = [];
-      constructor.functionSignature.orderedForEachParameter(parameters.add);
-      builder.buildFunctionHeader(parameters,
+      List<Local> parameters = <Local>[];
+      constructor.functionSignature.orderedForEachParameter(
+          (ParameterElement p) => parameters.add(p));
+
+      int firstTypeArgumentParameterIndex;
+
+      // If instances of the class may need runtime type information, we add a
+      // synthetic parameter for each type parameter.
+      if (requiresTypeInformation) {
+        firstTypeArgumentParameterIndex = parameters.length;
+        classElement.typeVariables.forEach((TypeVariableType variable) {
+          parameters.add(
+              new TypeInformationParameter(variable.element, constructor));
+        });
+      }
+
+      // Create IR parameters and setup the environment.
+      List<ir.Parameter> irParameters = builder.buildFunctionHeader(parameters,
           closureScope: getClosureScopeForFunction(constructor));
 
+      // Create a list of the values of all type argument parameters, if any.
+      List<ir.Primitive> typeInformation;
+      if (requiresTypeInformation) {
+        typeInformation = irParameters.sublist(firstTypeArgumentParameterIndex);
+      } else {
+        typeInformation = const <ir.Primitive>[];
+      }
+
       // -- Step 1: evaluate field initializers ---
       // Evaluate field initializers in constructor and super constructors.
+      irBuilder.enterInitializers();
       List<ConstructorElement> constructorList = <ConstructorElement>[];
       evaluateConstructorFieldInitializers(constructor, constructorList);
+      irBuilder.leaveInitializers();
 
       // All parameters in all constructors are now bound in the environment.
       // BoxLocals for captured parameters are also in the environment.
@@ -2221,8 +2329,10 @@
           // Native fields are initialized elsewhere.
         }
       }, includeSuperAndInjectedMembers: true);
-      ir.Primitive instance =
-          new ir.CreateInstance(classElement, instanceArguments);
+      ir.Primitive instance = new ir.CreateInstance(
+          classElement,
+          instanceArguments,
+          typeInformation);
       irBuilder.add(new ir.LetPrim(instance));
 
       // --- Step 3: call constructor bodies ---
@@ -2456,8 +2566,7 @@
         node,
         elements);
 
-    JsIrBuilder builder =
-        new JsIrBuilder(compiler.backend.constantSystem, body);
+    JsIrBuilder builder = getBuilderFor(body);
 
     return withBuilder(builder, () {
       irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body),
@@ -2479,8 +2588,7 @@
         element,
         node,
         elements);
-    IrBuilder builder =
-        new JsIrBuilder(compiler.backend.constantSystem, element);
+    IrBuilder builder = getBuilderFor(element);
     return withBuilder(builder, () => _makeFunctionBody(element, node));
   }
 
@@ -2495,7 +2603,7 @@
 
   /// Inserts default arguments and normalizes order of named arguments.
   List<ir.Primitive> normalizeStaticArguments(
-      Selector selector,
+      CallStructure callStructure,
       FunctionElement target,
       List<ir.Primitive> arguments) {
     target = target.implementation;
@@ -2528,7 +2636,7 @@
       // find them in [compiledNamedArguments]. If found, we use the
       // value in the temporary list, otherwise the default value.
       signature.orderedOptionalParameters.forEach((ParameterElement element) {
-        int nameIndex = selector.namedArguments.indexOf(element.name);
+        int nameIndex = callStructure.namedArguments.indexOf(element.name);
         if (nameIndex != -1) {
           int translatedIndex = offset + nameIndex;
           result.add(arguments[translatedIndex]);
@@ -2544,16 +2652,17 @@
   List<ir.Primitive> normalizeDynamicArguments(
       Selector selector,
       List<ir.Primitive> arguments) {
-    assert(arguments.length == selector.argumentCount);
+    CallStructure callStructure = selector.callStructure;
+    assert(arguments.length == callStructure.argumentCount);
     // Optimization: don't copy the argument list for trivial cases.
-    if (selector.namedArguments.isEmpty) return arguments;
+    if (callStructure.namedArguments.isEmpty) return arguments;
     List<ir.Primitive> result = <ir.Primitive>[];
-    for (int i=0; i < selector.positionalArgumentCount; i++) {
+    for (int i=0; i < callStructure.positionalArgumentCount; i++) {
       result.add(arguments[i]);
     }
-    for (String argName in selector.getOrderedNamedArguments()) {
-      int nameIndex = selector.namedArguments.indexOf(argName);
-      int translatedIndex = selector.positionalArgumentCount + nameIndex;
+    for (String argName in callStructure.getOrderedNamedArguments()) {
+      int nameIndex = callStructure.namedArguments.indexOf(argName);
+      int translatedIndex = callStructure.positionalArgumentCount + nameIndex;
       result.add(arguments[translatedIndex]);
     }
     return result;
@@ -2562,8 +2671,9 @@
   @override
   ir.Primitive buildReifyTypeVariable(ir.Primitive target,
                                       TypeVariableType variable) {
-    ir.Primitive typeArgument = new ir.ReadTypeVariable(variable, target);
-    irBuilder.add(new ir.LetPrim(typeArgument));
+    ir.Primitive typeArgument =
+        irBuilder.buildTypeVariableAccess(target, variable);
+
     ir.Primitive type = new ir.ReifyRuntimeType(typeArgument);
     irBuilder.add(new ir.LetPrim(type));
     return type;
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
index 0b115cb..e7a7d14 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
@@ -26,7 +26,7 @@
 ///
 class CheckCpsIntegrity extends RecursiveVisitor {
 
-  ExecutableDefinition topLevelNode;
+  RootNode topLevelNode;
 
   Set<Definition> seenDefinitions = new Set<Definition>();
   Map<Definition, Set<Reference>> seenReferences =
@@ -78,7 +78,7 @@
   }
 
   @override
-  visitRunnableBody(RunnableBody node) {
+  visitBody(Body node) {
     markAsSeen(node.returnContinuation);
     if (!node.returnContinuation.isReturnContinuation) {
       error('Return continuation with a body', node);
@@ -209,7 +209,7 @@
           '$sexpr\n';
   }
 
-  void check(ExecutableDefinition node) {
+  void check(RootNode node) {
     topLevelNode = node;
     visit(node);
 
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 d16fd8c..b0a305d 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -65,11 +65,6 @@
   /// binding originated.
   Entity hint;
 
-  /// Register in which the variable binding this primitive can be allocated.
-  /// Separate register spaces are used for primitives with different [element].
-  /// Assigned by [RegisterAllocator], is null before that phase.
-  int registerIndex;
-
   /// Use the given element as a hint for naming this primitive.
   ///
   /// Has no effect if this primitive already has a non-null [element].
@@ -214,7 +209,8 @@
 ///     child.parent = parent;
 ///     parent.body  = child;
 abstract class InteriorNode extends Node {
-  Expression body;
+  Expression get body;
+  void set body(Expression body);
 }
 
 /// Invoke a static function or static field getter/setter.
@@ -382,15 +378,11 @@
       : continuation = new Reference<Continuation>(cont),
         arguments = _referenceList(args) {
     assert(dart2js.invariant(target,
-        target.isErroneous || target.isConstructor,
-        message: "Constructor invocation target is not a constructor: "
-                 "$target."));
-    assert(dart2js.invariant(target,
         target.isErroneous ||
         type.isDynamic ||
         type.element == target.enclosingClass.declaration,
-        message: "Constructor invocation type ${type} does not match enclosing "
-                 "class of target ${target}."));
+        message: "Constructor invocation target is not a constructor: "
+                 "$target."));
   }
 
   accept(Visitor visitor) => visitor.visitInvokeConstructor(this);
@@ -506,13 +498,11 @@
   bool isRecursive;
 
   InvokeContinuation(Continuation cont, List<Primitive> args,
-                     {recursive: false})
+                     {this.isRecursive: false})
       : continuation = new Reference<Continuation>(cont),
-        arguments = _referenceList(args),
-        isRecursive = recursive {
-    assert(cont.parameters == null ||
-        cont.parameters.length == args.length);
-    if (recursive) cont.isRecursive = true;
+        arguments = _referenceList(args) {
+    assert(cont.parameters == null || cont.parameters.length == args.length);
+    if (isRecursive) cont.isRecursive = true;
   }
 
   /// A continuation invocation whose target and arguments will be filled
@@ -520,10 +510,9 @@
   ///
   /// Used as a placeholder for a jump whose target is not yet created
   /// (e.g., in the translation of break and continue).
-  InvokeContinuation.uninitialized({recursive: false})
+  InvokeContinuation.uninitialized({this.isRecursive: false})
       : continuation = null,
-        arguments = null,
-        isRecursive = recursive;
+        arguments = null;
 
   accept(Visitor visitor) => visitor.visitInvokeContinuation(this);
 }
@@ -597,7 +586,8 @@
   accept(Visitor visitor) => visitor.visitCreateBox(this);
 }
 
-/// Creates an instance of a class and initializes its fields.
+/// Creates an instance of a class and initializes its fields and runtime type
+/// information.
 class CreateInstance extends Primitive implements JsSpecificNode {
   final ClassElement classElement;
 
@@ -605,8 +595,17 @@
   /// The order corresponds to the order of fields on the class.
   final List<Reference<Primitive>> arguments;
 
-  CreateInstance(this.classElement, List<Primitive> arguments)
-      : this.arguments = _referenceList(arguments);
+  /// The runtime type information structure which contains the type arguments.
+  ///
+  /// May be `null` to indicate that no type information is needed because the
+  /// compiler determined that the type information for instances of this class
+  /// is not needed at runtime.
+  final List<Reference<Primitive>> typeInformation;
+
+  CreateInstance(this.classElement, List<Primitive> arguments,
+      List<Primitive> typeInformation)
+      : this.arguments = _referenceList(arguments),
+        this.typeInformation = _referenceList(typeInformation);
 
   accept(Visitor visitor) => visitor.visitCreateInstance(this);
 }
@@ -655,7 +654,7 @@
   final GenericType type;
   final List<Reference<Primitive>> values;
 
-  LiteralList(this.type, Iterable<Primitive> values)
+  LiteralList(this.type, List<Primitive> values)
       : this.values = _referenceList(values);
 
   accept(Visitor visitor) => visitor.visitLiteralList(this);
@@ -717,30 +716,39 @@
   int parent_index;
 
   // A continuation is recursive if it has any recursive invocations.
-  bool isRecursive = false;
+  bool isRecursive;
 
   bool get isReturnContinuation => body == null;
 
-  Continuation(this.parameters);
+  Continuation(this.parameters, {this.isRecursive: false});
 
   Continuation.retrn() : parameters = <Parameter>[new Parameter(null)];
 
   accept(Visitor visitor) => visitor.visitContinuation(this);
 }
 
-abstract class ExecutableDefinition implements Node {
-  RunnableBody get body;
+abstract class RootNode extends Node {
   Element get element;
 
-  applyPass(Pass pass);
+  /// True if there is no body for this root node.
+  ///
+  /// In some parts of the compiler, empty root nodes are used as placeholders
+  /// for abstract methods, external constructors, fields without initializers,
+  /// etc.
+  bool get isEmpty;
+
+  /// List of parameters, or an empty list if this is a field.
+  /// For fields, this list is immutable.
+  List<Definition> get parameters;
 }
 
 // This is basically a function definition with an empty parameter list and a
 // field element instead of a function element and no const declarations, and
 // never a getter or setter, though that's less important.
-class FieldDefinition extends Node implements ExecutableDefinition {
+class FieldDefinition extends RootNode implements DartSpecificNode {
   final FieldElement element;
-  RunnableBody body;
+  List<Definition> get parameters => const <Definition>[];
+  final Body body;
 
   FieldDefinition(this.element, this.body);
 
@@ -748,26 +756,8 @@
       : this.body = null;
 
   accept(Visitor visitor) => visitor.visitFieldDefinition(this);
-  applyPass(Pass pass) => pass.rewriteFieldDefinition(this);
 
-  /// `true` if this field has no initializer.
-  ///
-  /// If `true` [body] is `null`.
-  ///
-  /// This is different from a initializer that is `null`. Consider this class:
-  ///
-  ///     class Class {
-  ///       final field;
-  ///       Class.a(this.field);
-  ///       Class.b() : this.field = null;
-  ///       Class.c();
-  ///     }
-  ///
-  /// If `field` had an initializer, possibly `null`, constructors `Class.a` and
-  /// `Class.b` would be invalid, and since `field` has no initializer
-  /// constructor `Class.c` is invalid. We therefore need to distinguish the two
-  /// cases.
-  bool get hasInitializer => body != null;
+  bool get isEmpty => body == null;
 }
 
 /// Identifies a mutable variable.
@@ -781,22 +771,21 @@
   accept(Visitor v) => v.visitMutableVariable(this);
 }
 
-class RunnableBody extends InteriorNode {
+class Body extends InteriorNode {
   Expression body;
   final Continuation returnContinuation;
-  RunnableBody(this.body, this.returnContinuation);
-  accept(Visitor visitor) => visitor.visitRunnableBody(this);
+  Body(this.body, this.returnContinuation);
+  accept(Visitor visitor) => visitor.visitBody(this);
 }
 
 /// A function definition, consisting of parameters and a body.  The parameters
 /// include a distinguished continuation parameter (held by the body).
-class FunctionDefinition extends Node
-    implements ExecutableDefinition {
+class FunctionDefinition extends RootNode {
   final FunctionElement element;
   final Parameter thisParameter;
   /// Mixed list of [Parameter]s and [MutableVariable]s.
   final List<Definition> parameters;
-  final RunnableBody body;
+  final Body body;
   final List<ConstDeclaration> localConstants;
 
   /// Values for optional parameters.
@@ -810,26 +799,22 @@
       this.defaultParameterValues);
 
   FunctionDefinition.abstract(this.element,
-                              this.thisParameter,
                               this.parameters,
                               this.defaultParameterValues)
       : body = null,
+        thisParameter = null,
         localConstants = const <ConstDeclaration>[];
 
   accept(Visitor visitor) => visitor.visitFunctionDefinition(this);
-  applyPass(Pass pass) => pass.rewriteFunctionDefinition(this);
 
-  /// Returns `true` if this function is abstract or external.
-  ///
-  /// If `true`, [body] is `null` and [localConstants] is empty.
-  bool get isAbstract => body == null;
+  bool get isEmpty => body == null;
 }
 
 abstract class Initializer extends Node implements DartSpecificNode {}
 
 class FieldInitializer extends Initializer {
   final FieldElement element;
-  final RunnableBody body;
+  final Body body;
 
   FieldInitializer(this.element, this.body);
   accept(Visitor visitor) => visitor.visitFieldInitializer(this);
@@ -837,36 +822,46 @@
 
 class SuperInitializer extends Initializer {
   final ConstructorElement target;
-  final List<RunnableBody> arguments;
+  final List<Body> arguments;
   final Selector selector;
   SuperInitializer(this.target, this.arguments, this.selector);
   accept(Visitor visitor) => visitor.visitSuperInitializer(this);
 }
 
-class ConstructorDefinition extends FunctionDefinition {
+class ConstructorDefinition extends RootNode implements DartSpecificNode {
+  final ConstructorElement element;
+  final Parameter thisParameter;
+  /// Mixed list of [Parameter]s and [MutableVariable]s.
+  final List<Definition> parameters;
+  final Body body;
+  final List<ConstDeclaration> localConstants;
   final List<Initializer> initializers;
 
-  ConstructorDefinition(ConstructorElement element,
-                        Definition thisParameter, // only Dart
-                        List<Definition> parameters,
-                        RunnableBody body,
+  /// Values for optional parameters.
+  final List<ConstantExpression> defaultParameterValues;
+
+  ConstructorDefinition(this.element,
+                        this.thisParameter,
+                        this.parameters,
+                        this.body,
                         this.initializers,
-                        List<ConstDeclaration> localConstants,
-                        List<ConstantExpression> defaultParameterValues)
-  : super(element, thisParameter, parameters, body, localConstants,
-          defaultParameterValues);
+                        this.localConstants,
+                        this.defaultParameterValues);
 
   // 'Abstract' here means "has no body" and is used to represent external
   // constructors.
   ConstructorDefinition.abstract(
-      ConstructorElement element,
-      List<Definition> parameters,
-      List<ConstantExpression> defaultParameterValues)
-      : initializers = null,
-        super.abstract(element, null, parameters, defaultParameterValues);
+      this.element,
+      this.parameters,
+      this.defaultParameterValues)
+      : body = null,
+        initializers = null,
+        thisParameter = null,
+        localConstants = const <ConstDeclaration>[];
 
   accept(Visitor visitor) => visitor.visitConstructorDefinition(this);
-  applyPass(Pass pass) => pass.rewriteConstructorDefinition(this);
+
+  bool get isEmpty => body == null;
 }
 
 /// Converts the internal representation of a type to a Dart object of type
@@ -898,6 +893,28 @@
   accept(Visitor visitor) => visitor.visitReadTypeVariable(this);
 }
 
+/// Representation of a closed type (that is, a type without type variables).
+///
+/// The resulting value is constructed from [dartType] by replacing the type
+/// variables with consecutive values from [arguments], in the order generated
+/// by [DartType.forEachTypeVariable].  The type variables in [dartType] are
+/// treated as 'holes' in the term, which means that it must be ensured at
+/// construction, that duplicate occurences of a type variable in [dartType]
+/// are assigned the same value.
+class TypeExpression extends Primitive implements JsSpecificNode {
+  final DartType dartType;
+  final List<Reference<Primitive>> arguments;
+
+  TypeExpression(this.dartType,
+                 [List<Primitive> arguments = const <Primitive>[]])
+      : this.arguments = _referenceList(arguments);
+
+  @override
+  accept(Visitor visitor) {
+    return visitor.visitTypeExpression(this);
+  }
+}
+
 List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
   return definitions.map((e) => new Reference<Primitive>(e)).toList();
 }
@@ -911,7 +928,7 @@
   T visitFieldDefinition(FieldDefinition node);
   T visitFunctionDefinition(FunctionDefinition node);
   T visitConstructorDefinition(ConstructorDefinition node);
-  T visitRunnableBody(RunnableBody node);
+  T visitBody(Body node);
 
   // Initializers
   T visitFieldInitializer(FieldInitializer node);
@@ -960,6 +977,7 @@
   T visitCreateBox(CreateBox node);
   T visitReifyRuntimeType(ReifyRuntimeType node);
   T visitReadTypeVariable(ReadTypeVariable node);
+  T visitTypeExpression(TypeExpression node);
 }
 
 /// Recursively visits the entire CPS term, and calls abstract `process*`
@@ -971,9 +989,9 @@
 
   processReference(Reference ref) {}
 
-  processRunnableBody(RunnableBody node) {}
-  visitRunnableBody(RunnableBody node) {
-    processRunnableBody(node);
+  processBody(Body node) {}
+  visitBody(Body node) {
+    processBody(node);
     visit(node.returnContinuation);
     visit(node.body);
   }
@@ -981,7 +999,7 @@
   processFieldDefinition(FieldDefinition node) {}
   visitFieldDefinition(FieldDefinition node) {
     processFieldDefinition(node);
-    if (node.hasInitializer) {
+    if (node.body != null) {
       visit(node.body);
     }
   }
@@ -991,7 +1009,7 @@
     processFunctionDefinition(node);
     if (node.thisParameter != null) visit(node.thisParameter);
     node.parameters.forEach(visit);
-    if (!node.isAbstract) {
+    if (node.body != null) {
       visit(node.body);
     }
   }
@@ -1001,8 +1019,12 @@
     processConstructorDefinition(node);
     if (node.thisParameter != null) visit(node.thisParameter);
     node.parameters.forEach(visit);
-    node.initializers.forEach(visit);
-    visit(node.body);
+    if (node.initializers != null) {
+      node.initializers.forEach(visit);
+    }
+    if (node.body != null) {
+      visit(node.body);
+    }
   }
 
   processFieldInitializer(FieldInitializer node) {}
@@ -1199,6 +1221,7 @@
   visitCreateInstance(CreateInstance node) {
     processCreateInstance(node);
     node.arguments.forEach(processReference);
+    node.typeInformation.forEach(processReference);
   }
 
   processSetField(SetField node) {}
@@ -1231,273 +1254,11 @@
     processReadTypeVariable(node);
     processReference(node.target);
   }
-}
 
-/// Keeps track of currently unused register indices.
-class RegisterArray {
-  int nextIndex = 0;
-  final List<int> freeStack = <int>[];
-
-  /// Returns an index that is currently unused.
-  int makeIndex() {
-    if (freeStack.isEmpty) {
-      return nextIndex++;
-    } else {
-      return freeStack.removeLast();
-    }
-  }
-
-  void releaseIndex(int index) {
-    freeStack.add(index);
-  }
-}
-
-/// Assigns indices to each primitive in the IR such that primitives that are
-/// live simultaneously never get assigned the same index.
-/// This information is used by the dart tree builder to generate fewer
-/// redundant variables.
-/// Currently, the liveness analysis is very simple and is often inadequate
-/// for removing all of the redundant variables.
-class RegisterAllocator implements Visitor {
-  final dart2js.InternalErrorFunction internalError;
-
-  /// Separate register spaces for each source-level variable/parameter.
-  /// Note that null is used as key for primitives without hints.
-  final Map<Local, RegisterArray> elementRegisters = <Local, RegisterArray>{};
-
-  RegisterAllocator(this.internalError);
-
-  RegisterArray getRegisterArray(Local local) {
-    RegisterArray registers = elementRegisters[local];
-    if (registers == null) {
-      registers = new RegisterArray();
-      elementRegisters[local] = registers;
-    }
-    return registers;
-  }
-
-  void allocate(Primitive primitive) {
-    if (primitive.registerIndex == null) {
-      primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex();
-    }
-  }
-
-  void release(Primitive primitive) {
-    // Do not share indices for temporaries as this may obstruct inlining.
-    if (primitive.hint == null) return;
-    if (primitive.registerIndex != null) {
-      getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex);
-    }
-  }
-
-  void visit(Node node) => node.accept(this);
-
-  void visitReference(Reference reference) {
-    allocate(reference.definition);
-  }
-
-  void visitFieldDefinition(FieldDefinition node) {
-    if (node.hasInitializer) {
-      visit(node.body);
-    }
-  }
-
-  void visitRunnableBody(RunnableBody node) {
-    visit(node.body);
-  }
-
-  void visitFunctionDefinition(FunctionDefinition node) {
-    if (!node.isAbstract) {
-      visit(node.body);
-    }
-    // Assign indices to unused parameters.
-    for (Definition param in node.parameters) {
-      if (param is Primitive) {
-        allocate(param);
-      }
-    }
-  }
-
-  void visitConstructorDefinition(ConstructorDefinition node) {
-    if (!node.isAbstract) {
-      node.initializers.forEach(visit);
-      visit(node.body);
-    }
-    // Assign indices to unused parameters.
-    for (Definition param in node.parameters) {
-      if (param is Primitive) {
-        allocate(param);
-      }
-    }
-  }
-
-  void visitFieldInitializer(FieldInitializer node) {
-    visit(node.body.body);
-  }
-
-  void visitSuperInitializer(SuperInitializer node) {
-    node.arguments.forEach(visit);
-  }
-
-  void visitLetPrim(LetPrim node) {
-    visit(node.body);
-    release(node.primitive);
-    visit(node.primitive);
-  }
-
-  void visitLetCont(LetCont node) {
-    node.continuations.forEach(visit);
-    visit(node.body);
-  }
-
-  void visitLetHandler(LetHandler node) {
-    visit(node.handler);
-    // Handler parameters that were not used in the handler body will not have
-    // had register indexes assigned.  Assign them here, otherwise they will
-    // be eliminated later and they should not be (i.e., a catch clause that
-    // does not use the exception parameter should not have the exception
-    // parameter eliminated, because it would not be well-formed anymore).
-    // In any case release the parameter indexes because the parameters are
-    // not live in the try block.
-    node.handler.parameters.forEach((Parameter parameter) {
-      allocate(parameter);
-      release(parameter);
-    });
-    visit(node.body);
-  }
-
-  void visitLetMutable(LetMutable node) {
-    visit(node.body);
-    visitReference(node.value);
-  }
-
-  void visitInvokeStatic(InvokeStatic node) {
-    node.arguments.forEach(visitReference);
-  }
-
-  void visitInvokeContinuation(InvokeContinuation node) {
-    node.arguments.forEach(visitReference);
-  }
-
-  void visitInvokeMethod(InvokeMethod node) {
-    visitReference(node.receiver);
-    node.arguments.forEach(visitReference);
-  }
-
-  void visitInvokeMethodDirectly(InvokeMethodDirectly node) {
-    visitReference(node.receiver);
-    node.arguments.forEach(visitReference);
-  }
-
-  void visitInvokeConstructor(InvokeConstructor node) {
-    node.arguments.forEach(visitReference);
-  }
-
-  void visitConcatenateStrings(ConcatenateStrings node) {
-    node.arguments.forEach(visitReference);
-  }
-
-  void visitBranch(Branch node) {
-    visit(node.condition);
-  }
-
-  void visitLiteralList(LiteralList node) {
-    node.values.forEach(visitReference);
-  }
-
-  void visitLiteralMap(LiteralMap node) {
-    for (LiteralMapEntry entry in node.entries) {
-      visitReference(entry.key);
-      visitReference(entry.value);
-    }
-  }
-
-  void visitTypeOperator(TypeOperator node) {
-    visitReference(node.receiver);
-  }
-
-  void visitConstant(Constant node) {
-  }
-
-  void visitReifyTypeVar(ReifyTypeVar node) {
-  }
-
-  void visitCreateFunction(CreateFunction node) {
-    new RegisterAllocator(internalError).visit(node.definition);
-  }
-
-  void visitGetMutableVariable(GetMutableVariable node) {
-  }
-
-  void visitSetMutableVariable(SetMutableVariable node) {
-    visit(node.body);
-    visitReference(node.value);
-  }
-
-  void visitDeclareFunction(DeclareFunction node) {
-    new RegisterAllocator(internalError).visit(node.definition);
-    visit(node.body);
-  }
-
-  void visitParameter(Parameter node) {
-    // Parameters are handled differently depending on whether they are
-    // function parameters, continuation parameters, exception handler
-    // parameters, etc.  Thus we do not call visitParameter directly and
-    // handle them explicitly in their parent IR node.
-    internalError(dart2js.CURRENT_ELEMENT_SPANNABLE,
-                  'tried to allocate a parameter');
-  }
-
-  void visitMutableVariable(MutableVariable node) {}
-
-  void visitContinuation(Continuation node) {
-    visit(node.body);
-
-    // Arguments get allocated left-to-right, so we release parameters
-    // right-to-left. This increases the likelihood that arguments can be
-    // transferred without intermediate assignments.
-    for (int i = node.parameters.length - 1; i >= 0; --i) {
-      release(node.parameters[i]);
-    }
-  }
-
-  void visitIsTrue(IsTrue node) {
-    visitReference(node.value);
-  }
-
-  // JavaScript specific nodes.
-
-  void visitSetField(SetField node) {
-    visit(node.body);
-    visitReference(node.value);
-    visitReference(node.object);
-  }
-
-  void visitGetField(GetField node) {
-    visitReference(node.object);
-  }
-
-  void visitCreateBox(CreateBox node) {
-  }
-
-  void visitCreateInstance(CreateInstance node) {
-    node.arguments.forEach(visitReference);
-  }
-
-  void visitIdentical(Identical node) {
-    visitReference(node.left);
-    visitReference(node.right);
-  }
-
-  void visitInterceptor(Interceptor node) {
-    visitReference(node.input);
-  }
-
-  void visitReifyRuntimeType(ReifyRuntimeType node) {
-    visitReference(node.value);
-  }
-
-  void visitReadTypeVariable(ReadTypeVariable node) {
-    visitReference(node.target);
+  processTypeExpression(TypeExpression node) {}
+  @override
+  visitTypeExpression(TypeExpression node) {
+    processTypeExpression(node);
+    node.arguments.forEach(processReference);
   }
 }
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 3b71d9a..a645fb9 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
@@ -62,7 +62,7 @@
 
   String visitFieldDefinition(FieldDefinition node) {
     String name = node.element.name;
-    if (node.hasInitializer) {
+    if (node.body != null) {
       String body = visit(node.body);
       return '$indentation(FieldDefinition $name () return\n'
              '$body)';
@@ -111,7 +111,7 @@
     return '$indentation(SuperInitializer $target $selector (\n$arguments)';
   }
 
-  String visitRunnableBody(RunnableBody node) {
+  String visitBody(Body node) {
     namer.setReturnContinuation(node.returnContinuation);
     return indentBlock(() => visit(node.body));
   }
@@ -207,11 +207,21 @@
   }
 
   String visitInvokeConstructor(InvokeConstructor node) {
+    String className;
+    // TODO(karlklose): for illegal nodes constructed for tests or unresolved
+    // constructor calls in the DartBackend, we get an element with no enclosing
+    // class.  Clean this up by introducing a name field to the node and
+    // removing [ErroneousElement]s from the IR.
+    if (node.type != null) {
+      className = node.type.toString();
+    } else {
+      className = node.target.enclosingClass.name;
+    }
     String callName;
     if (node.target.name.isEmpty) {
-      callName = '${node.type}';
+      callName = '${className}';
     } else {
-      callName = '${node.type}.${node.target.name}';
+      callName = '${className}.${node.target.name}';
     }
     String cont = access(node.continuation);
     String args = formatArguments(node);
@@ -323,7 +333,8 @@
   String visitCreateInstance(CreateInstance node) {
     String className = node.classElement.name;
     String arguments = node.arguments.map(access).join(' ');
-    return '(CreateInstance $className ($arguments))';
+    String typeInformation = node.typeInformation.map(access).join(' ');
+    return '(CreateInstance $className ($arguments)$typeInformation)';
   }
 
   String visitIdentical(Identical node) {
@@ -343,6 +354,12 @@
   String visitReadTypeVariable(ReadTypeVariable node) {
     return '(ReadTypeVariable ${access(node.target)}.${node.variable})';
   }
+
+  @override
+  String visitTypeExpression(TypeExpression node) {
+    String args = node.arguments.map(access).join(', ');
+    return '(TypeExpression ${node.dartType.toString()} $args)';
+  }
 }
 
 class ConstantStringifier extends ConstantValueVisitor<String, Null> {
@@ -427,7 +444,9 @@
 
   String nameParameter(Parameter parameter) {
     assert(!_names.containsKey(parameter));
-    return _names[parameter] = parameter.hint.name;
+    String name =
+        parameter.hint != null ? parameter.hint.name : nameValue(parameter);
+    return _names[parameter] = name;
   }
 
   String nameMutableVariable(MutableVariable variable) {
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 74c4b1c..92b81e2 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -21,44 +21,50 @@
 
   visit(cps_ir.Node node) => node.accept(this);
 
-  void traceGraph(String name, cps_ir.ExecutableDefinition graph) {
+  void traceGraph(String name, cps_ir.RootNode node) {
+    if (node.isEmpty) return; // Don't bother printing an empty trace.
     tag("cfg", () {
       printProperty("name", name);
-      visit(graph);
+
+      names = new Names();
+      BlockCollector builder = new BlockCollector(names);
+      builder.visit(node);
+
+      for (Block block in builder.entries) {
+        printBlock(block, entryPointParameters: node.parameters);
+      }
+      for (Block block in builder.cont2block.values) {
+        printBlock(block);
+      }
+      names = null;
     });
   }
 
   // Temporary field used during tree walk
   Names names;
 
-  printDefinition(cps_ir.ExecutableDefinition node) {
-    names = new Names();
-    BlockCollector builder = new BlockCollector(names);
-    builder.visit(node);
-
-    for (Block block in builder.entries) {
-      printBlock(block);
-    }
-    for (Block block in builder.cont2block.values) {
-      printBlock(block);
-    }
-    names = null;
-  }
-
   visitFieldDefinition(cps_ir.FieldDefinition node) {
-    if (node.hasInitializer) {
-      printDefinition(node);
-    }
+    unexpectedNode(node);
   }
 
   visitFunctionDefinition(cps_ir.FunctionDefinition node) {
-    if (node.isAbstract) return;
-    printDefinition(node);
+    unexpectedNode(node);
   }
 
   visitConstructorDefinition(cps_ir.ConstructorDefinition node) {
-    if (node.isAbstract) return;
-    printDefinition(node);
+    unexpectedNode(node);
+  }
+
+  visitFieldInitializer(cps_ir.FieldInitializer node) {
+    unexpectedNode(node);
+  }
+
+  visitSuperInitializer(cps_ir.SuperInitializer node) {
+    unexpectedNode(node);
+  }
+
+  visitBody(cps_ir.Body node) {
+    unexpectedNode(node);
   }
 
   // Bodies and initializers are not visited.  They contain continuations which
@@ -68,15 +74,6 @@
     throw 'The IR tracer reached an unexpected IR instruction: $node';
   }
 
-  visitRunnableBody(cps_ir.RunnableBody node) {
-    unexpectedNode(node);
-  }
-  visitFieldInitializer(cps_ir.FieldInitializer node) {
-    unexpectedNode(node);
-  }
-  visitSuperInitializer(cps_ir.SuperInitializer node) {
-    unexpectedNode(node);
-  }
 
   int countUses(cps_ir.Definition definition) {
     int count = 0;
@@ -88,7 +85,9 @@
     return count;
   }
 
-  printBlock(Block block) {
+  /// If [entryPointParameters] is given, this block is an entry point
+  /// and [entryPointParameters] is the list of function parameters.
+  printBlock(Block block, {List<cps_ir.Definition> entryPointParameters}) {
     tag("block", () {
       printProperty("name", block.name);
       printProperty("from_bci", -1);
@@ -104,6 +103,10 @@
         });
       });
       tag("HIR", () {
+        if (entryPointParameters != null) {
+          String params = entryPointParameters.map(names.name).join(', ');
+          printStmt('x0', 'Entry ($params)');
+        }
         for (cps_ir.Parameter param in block.parameters) {
           String name = names.name(param);
           printStmt(name, "Parameter $name [useCount=${countUses(param)}]");
@@ -182,11 +185,12 @@
 
   visitInvokeConstructor(cps_ir.InvokeConstructor node) {
     String dummy = names.name(node);
+    String className = node.target.enclosingClass.name;
     String callName;
     if (node.target.name.isEmpty) {
-      callName = '${node.type}';
+      callName = '${className}';
     } else {
-      callName = '${node.type}.${node.target.name}';
+      callName = '${className}.${node.target.name}';
     }
     String args = node.arguments.map(formatReference).join(', ');
     String kont = formatReference(node.continuation);
@@ -308,7 +312,9 @@
   visitCreateInstance(cps_ir.CreateInstance node) {
     String className = node.classElement.name;
     String arguments = node.arguments.map(formatReference).join(', ');
-    return 'CreateInstance $className ($arguments)';
+    String typeInformation =
+        node.typeInformation.map(formatReference).join(', ');
+    return 'CreateInstance $className ($arguments) <$typeInformation>';
   }
 
   visitIdentical(cps_ir.Identical node) {
@@ -344,6 +350,12 @@
   visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) {
     return "ReifyRuntimeType ${formatReference(node.value)}";
   }
+
+  @override
+  visitTypeExpression(cps_ir.TypeExpression node) {
+    return "TypeExpression ${node.dartType} "
+        "${node.arguments.map(formatReference).join(', ')}";
+  }
 }
 
 /**
@@ -403,7 +415,7 @@
   final Map<cps_ir.Continuation, Block> cont2block =
       <cps_ir.Continuation, Block>{};
   final Set<Block> entries = new Set<Block>();
-  Block current_block;
+  Block currentBlock;
 
   Names names;
   BlockCollector(this.names);
@@ -420,9 +432,7 @@
   visit(cps_ir.Node node) => node.accept(this);
 
   visitFieldDefinition(cps_ir.FieldDefinition node) {
-    if (node.hasInitializer) {
-      visit(node.body);
-    }
+    visit(node.body);
   }
 
   visitFunctionDefinition(cps_ir.FunctionDefinition node) {
@@ -430,12 +440,13 @@
   }
 
   visitConstructorDefinition(cps_ir.ConstructorDefinition node) {
+    node.initializers.forEach(visit);
     visit(node.body);
   }
 
-  visitRunnableBody(cps_ir.RunnableBody node) {
-    current_block = new Block(names.name(node), [], node.body);
-    entries.add(current_block);
+  visitBody(cps_ir.Body node) {
+    currentBlock = new Block(names.name(node), [], node.body);
+    entries.add(currentBlock);
     visit(node.body);
   }
 
@@ -468,7 +479,7 @@
   void addEdgeToContinuation(cps_ir.Reference continuation) {
     cps_ir.Definition target = continuation.definition;
     if (target is cps_ir.Continuation && !target.isReturnContinuation) {
-      current_block.addEdgeTo(getBlock(target));
+      currentBlock.addEdgeTo(getBlock(target));
     }
   }
 
@@ -511,11 +522,11 @@
   visitBranch(cps_ir.Branch exp) {
     cps_ir.Continuation trueTarget = exp.trueContinuation.definition;
     if (!trueTarget.isReturnContinuation) {
-      current_block.addEdgeTo(getBlock(trueTarget));
+      currentBlock.addEdgeTo(getBlock(trueTarget));
     }
     cps_ir.Continuation falseTarget = exp.falseContinuation.definition;
     if (!falseTarget.isReturnContinuation) {
-      current_block.addEdgeTo(getBlock(falseTarget));
+      currentBlock.addEdgeTo(getBlock(falseTarget));
     }
   }
 
@@ -524,10 +535,10 @@
   }
 
   visitContinuation(cps_ir.Continuation c) {
-    var old_node = current_block;
-    current_block = getBlock(c);
+    var old_node = currentBlock;
+    currentBlock = getBlock(c);
     visit(c.body);
-    current_block = old_node;
+    currentBlock = old_node;
   }
 
   // Primitives and conditions are not visited when searching for blocks.
@@ -588,4 +599,9 @@
   visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) {
     unexpectedNode(node);
   }
+
+  @override
+  visitTypeExpression(cps_ir.TypeExpression node) {
+    unexpectedNode(node);
+  }
 }
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index 5fba01c..4db77c8 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -27,31 +27,7 @@
 /// An optimization pass over the CPS IR.
 abstract class Pass {
   /// Applies optimizations to root, rewriting it in the process.
-  void rewrite(ExecutableDefinition root) => root.applyPass(this);
-
-  void rewriteConstructorDefinition(ConstructorDefinition root);
-  void rewriteFunctionDefinition(FunctionDefinition root);
-  void rewriteFieldDefinition(FieldDefinition root);
+  void rewrite(RootNode root);
 
   String get passName;
 }
-
-abstract class PassMixin implements Pass {
-  void rewrite(ExecutableDefinition root) => root.applyPass(this);
-
-  void rewriteExecutableDefinition(ExecutableDefinition root);
-
-  void rewriteFunctionDefinition(FunctionDefinition root) {
-    if (root.isAbstract) return;
-    rewriteExecutableDefinition(root);
-  }
-
-  void rewriteConstructorDefinition(ConstructorDefinition root) {
-    if (root.isAbstract) return;
-    rewriteExecutableDefinition(root);
-  }
-  void rewriteFieldDefinition(FieldDefinition root) {
-    if (!root.hasInitializer) return;
-    rewriteExecutableDefinition(root);
-  }
-}
diff --git a/pkg/compiler/lib/src/cps_ir/redundant_phi.dart b/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
index b61e785..0fe59ba 100644
--- a/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
+++ b/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
@@ -12,13 +12,14 @@
 /// (except for feedback). Redundant parameters are removed from the
 /// continuation signature, all invocations, and replaced within the
 /// continuation body.
-class RedundantPhiEliminator extends RecursiveVisitor with PassMixin {
+class RedundantPhiEliminator extends RecursiveVisitor implements Pass {
   String get passName => 'Redundant phi elimination';
 
   final Set<Continuation> workSet = new Set<Continuation>();
 
   @override
-  void rewriteExecutableDefinition(final ExecutableDefinition root) {
+  void rewrite(RootNode root) {
+    if (root.isEmpty) return;
 
     // Set all parent pointers.
     new ParentVisitor().visit(root);
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index c3823ec..445838e 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -8,7 +8,7 @@
  * [ShrinkingReducer] applies shrinking reductions to CPS terms as described
  * in 'Compiling with Continuations, Continued' by Andrew Kennedy.
  */
-class ShrinkingReducer extends PassMixin {
+class ShrinkingReducer extends Pass {
   String get passName => 'Shrinking reductions';
 
   Set<_ReductionTask> _worklist;
@@ -17,7 +17,9 @@
 
   /// Applies shrinking reductions to root, mutating root in the process.
   @override
-  void rewriteExecutableDefinition(ExecutableDefinition root) {
+  void rewrite(RootNode root) {
+    if (root.isEmpty) return;
+
     _worklist = new Set<_ReductionTask>();
     _RedexVisitor redexVisitor = new _RedexVisitor(_worklist);
 
@@ -464,7 +466,7 @@
       Continuation cont = reference.definition;
       Node parent = cont.parent;
       // The parent might be the deleted sentinel, or it might be a
-      // RunnableBody if the continuation is the return continuation.
+      // Body if the continuation is the return continuation.
       if (parent is LetCont) {
         if (cont.isRecursive && cont.hasAtMostOneUse) {
           // Convert recursive to nonrecursive continuations.  If the
@@ -494,7 +496,7 @@
     });
   }
 
-  processRunnableBody(RunnableBody node) {
+  processBody(Body node) {
     node.returnContinuation.parent = node;
     node.body.parent = node;
   }
@@ -516,7 +518,7 @@
   }
 
   processSuperInitializer(SuperInitializer node) {
-    node.arguments.forEach((RunnableBody argument) => argument.parent = node);
+    node.arguments.forEach((Body argument) => argument.parent = node);
   }
 
   processLetPrim(LetPrim node) {
@@ -658,6 +660,7 @@
 
   processCreateInstance(CreateInstance node) {
     node.arguments.forEach((Reference ref) => ref.parent = node);
+    node.typeInformation.forEach((Reference ref) => ref.parent = node);
   }
 
   processCreateBox(CreateBox node) {
@@ -670,6 +673,10 @@
   processReadTypeVariable(ReadTypeVariable node) {
     node.target.parent = node;
   }
+
+  processTypeExpression(TypeExpression 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 bd723fc..234df38 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -67,6 +67,7 @@
   }
 
   @override
+  // TODO(karlklose): Do not base this on containsMask.
   bool areAssignable(TypeMask a, TypeMask b) {
     return a.containsMask(b, classWorld) || b.containsMask(a, classWorld);
   }
@@ -92,7 +93,7 @@
  * Implemented according to 'Constant Propagation with Conditional Branches'
  * by Wegman, Zadeck.
  */
-class TypePropagator<T> extends PassMixin {
+class TypePropagator<T> extends Pass {
   String get passName => 'Sparse constant propagation';
 
   final types.DartTypes _dartTypes;
@@ -111,7 +112,9 @@
       : _types = <Node, _AbstractValue>{};
 
   @override
-  void rewriteExecutableDefinition(ExecutableDefinition root) {
+  void rewrite(RootNode root) {
+    if (root.isEmpty) return;
+
     // Set all parent pointers.
     new ParentVisitor().visit(root);
 
@@ -149,7 +152,7 @@
 
   _TransformingVisitor(this.reachable, this.values, this.internalError);
 
-  void transform(ExecutableDefinition root) {
+  void transform(RootNode root) {
     visit(root);
   }
 
@@ -346,7 +349,7 @@
           new _AbstractValue<T>.unknown(typeSystem.dynamicType),
       this.typeSystem = typeSystem;
 
-  void analyze(ExecutableDefinition root) {
+  void analyze(RootNode root) {
     reachableNodes.clear();
     defWorkset.clear();
     nodeWorklist.clear();
@@ -416,9 +419,7 @@
   void visit(Node node) { node.accept(this); }
 
   void visitFieldDefinition(FieldDefinition node) {
-    if (node.hasInitializer) {
-      setReachable(node.body);
-    }
+    setReachable(node.body);
   }
 
   void visitFunctionDefinition(FunctionDefinition node) {
@@ -435,7 +436,7 @@
     setReachable(node.body);
   }
 
-  void visitRunnableBody(RunnableBody node) {
+  void visitBody(Body node) {
     setReachable(node.body);
   }
 
@@ -746,7 +747,7 @@
   void visitMutableVariable(MutableVariable node) {
     // [MutableVariable]s are bound either as parameters to
     // [FunctionDefinition]s, by [LetMutable], or by [DeclareFunction].
-    if (node.parent is FunctionDefinition) {
+    if (node.parent is RootNode) {
       // Just like immutable parameters, the values of mutable parameters are
       // never constant.
       // TODO(karlklose): remove reference to the element model.
@@ -768,14 +769,14 @@
     // TODO(karlklose): remove reference to the element model.
     T type = (source is ParameterElement) ? typeSystem.getParameterType(source)
         : typeSystem.dynamicType;
-    if (node.parent is FunctionDefinition) {
+    if (node.parent is RootNode) {
       // Functions may escape and thus their parameters must be non-constant.
       setValue(node, nonConst(type));
     } else if (node.parent is Continuation) {
       // Continuations on the other hand are local, and parameters can have
       // some other abstract value than non-constant.
     } else {
-      internalError(node.hint, "Unexpected parent of Parameter");
+      internalError(node.hint, "Unexpected parent of Parameter: ${node.parent}");
     }
   }
 
@@ -852,6 +853,13 @@
     // real constants of type [Type].
     setValue(node, nonConst());
   }
+
+  @override
+  visitTypeExpression(TypeExpression node) {
+    // TODO(karlklose): come up with a type marker for JS entities or switch to
+    // real constants of type [Type].
+    setValue(node, nonConst());
+  }
 }
 
 /// Represents the abstract value of a primitive value at some point in the
diff --git a/pkg/compiler/lib/src/dart2jslib.dart b/pkg/compiler/lib/src/dart2jslib.dart
index d52396c..2491ebc 100644
--- a/pkg/compiler/lib/src/dart2jslib.dart
+++ b/pkg/compiler/lib/src/dart2jslib.dart
@@ -46,6 +46,9 @@
 import 'patch_parser.dart';
 import 'resolution/class_members.dart' show MembersCreator;
 import 'resolution/resolution.dart';
+import 'resolution/semantic_visitor.dart';
+import 'resolution/send_structure.dart';
+import 'resolution/operators.dart' as op;
 import 'scanner/scannerlib.dart';
 import 'ssa/ssa.dart';
 import 'io/source_file.dart' show SourceFile;
@@ -65,7 +68,7 @@
                                       isBinaryOperator,
                                       isTernaryOperator,
                                       isMinusOperator;
-export 'universe/universe.dart' show Selector, TypedSelector;
+export 'universe/universe.dart' show CallStructure, Selector, TypedSelector;
 export 'util/util.dart'
     show Spannable,
          CURRENT_ELEMENT_SPANNABLE,
diff --git a/pkg/compiler/lib/src/dart_backend/backend.dart b/pkg/compiler/lib/src/dart_backend/backend.dart
index f2c6c71..409b61f 100644
--- a/pkg/compiler/lib/src/dart_backend/backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend.dart
@@ -131,12 +131,12 @@
 
   void codegen(CodegenWorkItem work) { }
 
-  static bool checkTreeIntegrity(tree_ir.ExecutableDefinition node) {
+  static bool checkTreeIntegrity(tree_ir.RootNode node) {
     new CheckTreeIntegrity().check(node);
     return true; // So this can be used from assert().
   }
 
-  static bool checkCpsIntegrity(cps_ir.ExecutableDefinition node) {
+  static bool checkCpsIntegrity(cps_ir.RootNode node) {
     new CheckCpsIntegrity().check(node);
     return true; // So this can be used from assert().
   }
@@ -145,16 +145,16 @@
   static ElementAst createElementAst(
        ElementAstCreationContext context,
        Element element,
-       cps_ir.ExecutableDefinition cpsDefinition) {
+       cps_ir.RootNode cpsRoot) {
     context.traceCompilation(element.name);
-    context.traceGraph('CPS builder', cpsDefinition);
-    assert(checkCpsIntegrity(cpsDefinition));
+    context.traceGraph('CPS builder', cpsRoot);
+    assert(checkCpsIntegrity(cpsRoot));
 
     // Transformations on the CPS IR.
     void applyCpsPass(cps_opt.Pass pass) {
-      pass.rewrite(cpsDefinition);
-      context.traceGraph(pass.passName, cpsDefinition);
-      assert(checkCpsIntegrity(cpsDefinition));
+      pass.rewrite(cpsRoot);
+      context.traceGraph(pass.passName, cpsRoot);
+      assert(checkCpsIntegrity(cpsRoot));
     }
 
     // TODO(karlklose): enable type propagation for dart2dart when constant
@@ -168,37 +168,32 @@
     applyCpsPass(new RedundantPhiEliminator());
     applyCpsPass(new ShrinkingReducer());
 
-    // Do not rewrite the IR after variable allocation.  Allocation
-    // makes decisions based on an approximation of IR variable live
-    // ranges that can be invalidated by transforming the IR.
-    new cps_ir.RegisterAllocator(context.internalError).visit(cpsDefinition);
-
     tree_builder.Builder builder =
         new tree_builder.Builder(context.internalError);
-    tree_ir.ExecutableDefinition treeDefinition = builder.build(cpsDefinition);
-    assert(treeDefinition != null);
-    context.traceGraph('Tree builder', treeDefinition);
-    assert(checkTreeIntegrity(treeDefinition));
+    tree_ir.RootNode treeRoot = builder.build(cpsRoot);
+    assert(treeRoot != null);
+    context.traceGraph('Tree builder', treeRoot);
+    assert(checkTreeIntegrity(treeRoot));
 
     // Transformations on the Tree IR.
     void applyTreePass(tree_opt.Pass pass) {
-      pass.rewrite(treeDefinition);
-      context.traceGraph(pass.passName, treeDefinition);
-      assert(checkTreeIntegrity(treeDefinition));
+      pass.rewrite(treeRoot);
+      context.traceGraph(pass.passName, treeRoot);
+      assert(checkTreeIntegrity(treeRoot));
     }
 
     applyTreePass(new StatementRewriter());
-    applyTreePass(new CopyPropagator());
+    applyTreePass(new VariableMerger());
     applyTreePass(new LoopRewriter());
     applyTreePass(new LogicalRewriter());
 
     // Backend-specific transformations.
-    new backend_ast_emitter.UnshadowParameters().unshadow(treeDefinition);
-    context.traceGraph('Unshadow parameters', treeDefinition);
+    new backend_ast_emitter.UnshadowParameters().unshadow(treeRoot);
+    context.traceGraph('Unshadow parameters', treeRoot);
 
     TreeElementMapping treeElements = new TreeElementMapping(element);
-    backend_ast.ExecutableDefinition backendAst =
-        backend_ast_emitter.emit(treeDefinition);
+    backend_ast.RootNode backendAst =
+        backend_ast_emitter.emit(treeRoot);
     Node frontend_ast = backend2frontend.emit(treeElements, backendAst);
     return new ElementAst(frontend_ast, treeElements);
 
@@ -225,9 +220,8 @@
         return new ElementAst(element.resolvedAst.node,
                               element.resolvedAst.elements);
       } else {
-        cps_ir.ExecutableDefinition definition =
-            compiler.irBuilder.getIr(element);
-        return createElementAst(context, element, definition);
+        cps_ir.RootNode irNode = compiler.irBuilder.getIr(element);
+        return createElementAst(context, element, irNode);
       }
     }
 
diff --git a/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart b/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
index 1508259..4131146 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
@@ -15,8 +15,8 @@
 import '../tree/tree.dart' as tree show Modifiers;
 
 /// Translates the dart_tree IR to Dart backend AST.
-ExecutableDefinition emit(tree.ExecutableDefinition definition) {
-  return new ASTEmitter().emit(definition, new BuilderContext<Statement>());
+RootNode emit(tree.RootNode root) {
+  return new ASTEmitter().emit(root);
 }
 
 // TODO(johnniwinther): Split into function/block state.
@@ -203,29 +203,25 @@
   Iterable<T> get statements => _statementBuffer;
 }
 
-
 /// Translates the dart_tree IR to Dart backend AST.
 /// An instance of this class should only be used once; a fresh emitter
 /// must be created for each function to be emitted.
 class ASTEmitter
-    extends tree.Visitor1<dynamic, Expression, BuilderContext<Statement>> {
+  extends tree.StatementVisitor1<dynamic, BuilderContext<Statement>>
+     with tree.ExpressionVisitor1<Expression, BuilderContext<Statement>>,
+          tree.RootVisitor1<RootNode, BuilderContext<Statement>>,
+          tree.InitializerVisitor1<Initializer, BuilderContext<Statement>> {
 
-  ExecutableDefinition emit(tree.ExecutableDefinition definition,
-                            BuilderContext<Statement> context) {
-    if (definition is tree.FieldDefinition) {
-      return emitField(definition, context);
-    } else if (definition is tree.ConstructorDefinition) {
-      return emitConstructor(definition, context);
-    }
-    assert(definition is tree.FunctionDefinition);
-    return emitFunction(definition, context);
+  RootNode emit(tree.RootNode node) {
+    return visitRootNode(node, new BuilderContext<Statement>());
   }
 
-  FieldDefinition emitField(tree.FieldDefinition definition,
-                            BuilderContext<Statement> context) {
+  @override
+  FieldDefinition visitFieldDefinition(tree.FieldDefinition definition,
+                                       BuilderContext<Statement> context) {
     context.currentElement = definition.element;
     Expression initializer;
-    if (definition.hasInitializer) {
+    if (!definition.isEmpty) {
       visitStatement(definition.body, context);
       List<Statement> bodyParts;
       for (tree.Variable variable in context.variableNames.keys) {
@@ -273,11 +269,14 @@
     return false;
   }
 
-  FunctionExpression emitConstructor(tree.ConstructorDefinition definition,
-                                     BuilderContext<Statement> context) {
+  @override
+  FunctionExpression visitConstructorDefinition(
+        tree.ConstructorDefinition definition,
+        BuilderContext<Statement> context) {
     context.currentElement = definition.element;
 
-    Parameters parameters = emitRootParameters(definition, context);
+    Parameters parameters = emitRootParameters(
+        definition, definition.defaultParameterValues, context);
 
     // Declare parameters.
     for (tree.Variable param in definition.parameters) {
@@ -286,13 +285,13 @@
       context.declaredVariables.add(param);
     }
 
-    List<Expression> initializers;
+    List<Initializer> initializers;
     Statement body;
 
-    if (!definition.isAbstract) {
+    if (!definition.isEmpty) {
       initializers =
           definition.initializers.map((tree.Initializer initializer) {
-        return visitExpression(initializer, context);
+        return visitInitializer(initializer, context);
       }).toList();
 
       context.firstStatement = definition.body;
@@ -344,11 +343,14 @@
         ..element = context.currentElement;
   }
 
-  FunctionExpression emitFunction(tree.FunctionDefinition definition,
-                                  BuilderContext<Statement> context) {
+  @override
+  FunctionExpression visitFunctionDefinition(
+        tree.FunctionDefinition definition,
+        BuilderContext<Statement> context) {
     context.currentElement = definition.element;
 
-    Parameters parameters = emitRootParameters(definition, context);
+    Parameters parameters = emitRootParameters(
+        definition, definition.defaultParameterValues, context);
 
     // Declare parameters.
     for (tree.Variable param in definition.parameters) {
@@ -358,7 +360,7 @@
     }
 
     Statement body;
-    if (definition.isAbstract) {
+    if (definition.isEmpty) {
       body = new EmptyStatement();
     } else {
       context.firstStatement = definition.body;
@@ -414,7 +416,8 @@
 
   /// Emits parameters that are not nested inside other parameters.
   /// Root parameters can have default values, while inner parameters cannot.
-  Parameters emitRootParameters(tree.FunctionDefinition function,
+  Parameters emitRootParameters(tree.RootNode function,
+                                List<ConstantExpression> defaults,
                                 BuilderContext<Statement> context) {
     FunctionType functionType = function.element.type;
     List<Parameter> required = TypeGenerator.createParameters(
@@ -427,7 +430,7 @@
             ? functionType.namedParameterTypes
             : functionType.optionalParameterTypes,
         context: context,
-        defaultValues: function.defaultParameterValues,
+        defaultValues: defaults,
         elements: function.parameters.skip(required.length)
             .map((p) => p.element));
     return new Parameters(required, optional, optionalParametersAreNamed);
@@ -519,7 +522,8 @@
     // that may occur in expression context, but could not be inlined anywhere.
     if (stmt.variable.element is FunctionElement &&
         stmt.value is tree.FunctionExpression &&
-        !context.declaredVariables.contains(stmt.variable)) {
+        !context.declaredVariables.contains(stmt.variable) &&
+        stmt.variable.writeCount == 1) {
       tree.FunctionExpression functionExp = stmt.value;
       FunctionExpression function =
           makeSubFunction(functionExp.definition, context);
@@ -876,7 +880,8 @@
 
   FunctionExpression makeSubFunction(tree.FunctionDefinition function,
                                      BuilderContext<Statement> context) {
-    return emit(function, new BuilderContext<Statement>.inner(context));
+    return visitFunctionDefinition(function,
+        new BuilderContext<Statement>.inner(context));
   }
 
   @override
@@ -920,14 +925,14 @@
   }
 
   @override
-  Expression visitFieldInitializer(tree.FieldInitializer node,
+  Initializer visitFieldInitializer(tree.FieldInitializer node,
                                    BuilderContext<Statement> context) {
     return new FieldInitializer(node.element,
         ensureExpression(buildInInitializerContext(node.body, context)));
   }
 
   @override
-  Expression visitSuperInitializer(tree.SuperInitializer node,
+  Initializer visitSuperInitializer(tree.SuperInitializer node,
                                    BuilderContext<Statement> context) {
     List<Argument> arguments = node.arguments.map((tree.Statement argument) {
       return ensureExpression(buildInInitializerContext(argument, context));
@@ -937,6 +942,11 @@
   }
 
   @override
+  Expression visitTypeExpression(tree.TypeExpression node, arg) {
+    throw '$node not supported by dart backend';
+  }
+
+  @override
   visitGetField(tree.GetField node, arg) => errorUnsupportedNode(node);
 
   @override
@@ -963,6 +973,7 @@
   errorUnsupportedNode(tree.JsSpecificNode node) {
     throw '$node not supported by dart backend';
   }
+
 }
 
 class TypeGenerator {
@@ -1153,14 +1164,14 @@
   }
 
   @override
-  Expression visitConstructed(ConstructedConstantExpresssion exp,
+  Expression visitConstructed(ConstructedConstantExpression exp,
                               BuilderContext<Statement> context) {
-    int positionalArgumentCount = exp.selector.positionalArgumentCount;
+    int positionalArgumentCount = exp.callStructure.positionalArgumentCount;
     List<Argument> args = new List<Argument>.generate(
         positionalArgumentCount,
         (i) => visit(exp.arguments[i], context));
-    for (int i = 0; i < exp.selector.namedArgumentCount; ++i) {
-      args.add(new NamedArgument(exp.selector.namedArguments[i],
+    for (int i = 0; i < exp.callStructure.namedArgumentCount; ++i) {
+      args.add(new NamedArgument(exp.callStructure.namedArguments[i],
           visit(exp.arguments[positionalArgumentCount + i], context)));
     }
 
@@ -1251,14 +1262,12 @@
   /// Parameters that are used in a context where it is shadowed.
   Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>();
 
-  void unshadow(tree.ExecutableDefinition definition) {
-    // Fields have no parameters.
-    if (definition is tree.FieldDefinition) return;
-    visitFunctionDefinition(definition);
+  void unshadow(tree.RootNode definition) {
+    if (definition.isEmpty) return;
+    unshadowFunction(definition);
   }
 
-  visitFunctionDefinition(tree.FunctionDefinition definition) {
-    if (definition.isAbstract) return;
+  void unshadowFunction(tree.RootNode definition) {
     var oldShadow = shadowedParameters;
     var oldEnvironment = environment;
     environment = new Map<String, tree.Variable>.from(environment);
@@ -1270,7 +1279,7 @@
       }
       environment[param.element.name] = param;
     }
-    visitStatement(definition.body);
+    definition.forEachBody(visitStatement);
     environment = oldEnvironment;
     shadowedParameters = oldShadow;
 
@@ -1280,8 +1289,9 @@
         tree.Variable newParam = new tree.Variable(definition.element,
             param.element);
         definition.parameters[i] = newParam;
-        definition.body = new tree.Assign(param, new tree.VariableUse(newParam),
-            definition.body);
+        definition.replaceEachBody((tree.Statement body) {
+          return new tree.Assign(param, new tree.VariableUse(newParam), body);
+        });
         newParam.writeCount = 1; // Being a parameter counts as a write.
         param.writeCount--; // Not a parameter anymore.
       }
@@ -1289,6 +1299,11 @@
   }
 
   @override
+  void visitInnerFunction(tree.FunctionDefinition definition) {
+    unshadowFunction(definition);
+  }
+
+  @override
   visitVariable(tree.Variable variable) {
     if (shadowedParameters.contains(variable)) {
       hasShadowedUse.add(variable);
diff --git a/pkg/compiler/lib/src/dart_backend/backend_ast_nodes.dart b/pkg/compiler/lib/src/dart_backend/backend_ast_nodes.dart
index ba21ccb..bc4867d 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_nodes.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_nodes.dart
@@ -26,11 +26,11 @@
   bool get assignable => false;
 }
 
-abstract class ExecutableDefinition extends Node {
+abstract class RootNode extends Node {
   elements.Element get element;
 }
 
-class FieldDefinition extends ExecutableDefinition {
+class FieldDefinition extends RootNode {
   final elements.Element element;
   final Expression initializer;
   FieldDefinition(this.element, this.initializer);
@@ -322,7 +322,7 @@
   SuperInitializer(this.target, this.arguments);
 }
 
-class FunctionExpression extends Expression implements ExecutableDefinition {
+class FunctionExpression extends Expression implements RootNode {
   final TypeAnnotation returnType;
   String name;
   final Parameters parameters;
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 9bf9121..8e29ca0 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
@@ -16,8 +16,8 @@
 
 /// Translates the backend AST to Dart frontend AST.
 tree.Node emit(dart2js.TreeElementMapping treeElements,
-               ExecutableDefinition definition) {
-  return new TreePrinter(treeElements).makeDefinition(definition);
+               RootNode root) {
+  return new TreePrinter(treeElements).makeDefinition(root);
 }
 
 /// If true, the unparser will insert a coment in front of every function
@@ -32,7 +32,7 @@
 
   TreePrinter([this.treeElements]);
 
-  tree.Node makeDefinition(ExecutableDefinition node) {
+  tree.Node makeDefinition(RootNode node) {
     if (node is FieldDefinition) {
       tree.Node definition;
       if (node.initializer == null) {
diff --git a/pkg/compiler/lib/src/dart_backend/dart_backend.dart b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
index 2d73044..fbc3437 100644
--- a/pkg/compiler/lib/src/dart_backend/dart_backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
@@ -20,8 +20,7 @@
 import '../tree_ir/tree_ir_nodes.dart' as tree_ir;
 import '../util/util.dart';
 import '../mirror_renamer/mirror_renamer.dart';
-import '../tree_ir/optimization/optimization.dart'
-    show LogicalRewriter, LoopRewriter, CopyPropagator, StatementRewriter;
+import '../tree_ir/optimization/optimization.dart';
 import '../tree_ir/optimization/optimization.dart' as tree_opt;
 import '../tree_ir/tree_ir_integrity.dart';
 import '../cps_ir/cps_ir_integrity.dart';
diff --git a/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart b/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
index 9f9a2b8..4d47c14 100644
--- a/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
+++ b/pkg/compiler/lib/src/dart_backend/placeholder_collector.dart
@@ -37,7 +37,7 @@
   DeclarationTypePlaceholder(this.typeNode, this.requiresVar);
 }
 
-class SendVisitor extends ResolvedVisitor {
+class SendVisitor extends OldResolvedVisitor {
   final PlaceholderCollector collector;
 
   SendVisitor(this.collector, TreeElements elements)
@@ -100,7 +100,7 @@
     }
   }
 
-  visitAssert(node) {
+  visitAssertSend(node) {
     visitStaticSend(node);
   }
 
@@ -134,7 +134,7 @@
     }
   }
 
-  internalError(String reason, {Node node}) {
+  internalError(Spannable node, String reason) {
     collector.internalError(reason, node: node);
   }
 
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index 4a8af6e..b845ffc 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -980,6 +980,9 @@
 abstract class MemberElement extends Element implements ExecutableElement {
   /// The local functions defined within this member.
   List<FunctionElement> get nestedClosures;
+
+  /// The name of this member taking privacy into account.
+  Name get memberName;
 }
 
 /// A function, variable or parameter defined in an executable context.
@@ -1223,6 +1226,9 @@
   /// constructor so its immediate redirection target is `null`.
   ConstructorElement get immediateRedirectionTarget;
 
+  /// Is `true` if this constructor is a redirecting generative constructor.
+  bool get isRedirectingGenerative;
+
   /// Is `true` if this constructor is a redirecting factory constructor.
   bool get isRedirectingFactory;
 
@@ -1250,8 +1256,8 @@
 }
 
 /// JavaScript backend specific element for the body of constructor.
-// TODO(johnniwinther): Remove this class for the element model.
-abstract class ConstructorBodyElement extends FunctionElement {
+// TODO(johnniwinther): Remove this class from the element model.
+abstract class ConstructorBodyElement extends MethodElement {
   FunctionElement get constructor;
 }
 
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 68ee1a4..a8cea0a 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -168,6 +168,8 @@
 
   LibraryElement get library => enclosingElement.library;
 
+  Name get memberName => new Name(name, library);
+
   LibraryElement get implementationLibrary {
     Element element = this;
     while (!identical(element.kind, ElementKind.LIBRARY)) {
@@ -305,6 +307,7 @@
   get executableContext => unsupported();
   get isExternal => unsupported();
 
+  bool get isRedirectingGenerative => unsupported();
   bool get isRedirectingFactory => unsupported();
 
   computeSignature(compiler) => unsupported();
@@ -341,6 +344,12 @@
       Element enclosing)
       : super(messageKind, messageArguments, name, enclosing);
 
+  bool get isRedirectingGenerative => false;
+
+  void set isRedirectingGenerative(_) {
+    throw new UnsupportedError("isRedirectingGenerative");
+  }
+
   bool get isRedirectingFactory => false;
 
   get definingElement {
@@ -1912,6 +1921,7 @@
 
 abstract class ConstructorElementX extends FunctionElementX
     implements ConstructorElement {
+  bool isRedirectingGenerative = false;
 
   ConstructorElementX(String name,
                       ElementKind kind,
diff --git a/pkg/compiler/lib/src/elements/names.dart b/pkg/compiler/lib/src/elements/names.dart
index 56f3bf1..38e0945 100644
--- a/pkg/compiler/lib/src/elements/names.dart
+++ b/pkg/compiler/lib/src/elements/names.dart
@@ -46,6 +46,8 @@
   /// privacy into account.
   bool isSimilarTo(Name other);
   int get similarHashCode;
+  
+  LibraryElement get library;
 }
 
 class PublicName implements Name {
@@ -72,6 +74,8 @@
   bool isSimilarTo(Name other) =>
       text == other.text && isSetter == other.isSetter;
   int get similarHashCode => text.hashCode + 11 * isSetter.hashCode;
+  
+  LibraryElement get library => null;
 
   String toString() => isSetter ? '$text=' : text;
 }
diff --git a/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
index 46cd386..5247fe3 100644
--- a/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/concrete_types_inferrer.dart
@@ -6,6 +6,7 @@
 
 import 'dart:collection' show Queue, IterableBase;
 import '../native/native.dart' as native;
+import '../closure.dart' show BoxFieldElement;
 import '../dart2jslib.dart' hide Selector, TypedSelector;
 import '../dart_types.dart' show DartType, TypeKind;
 import '../elements/elements.dart';
@@ -1773,7 +1774,7 @@
    */
   void ensureFieldInitialized(Element field) {
     // This is test is needed for fitering out BoxFieldElements.
-    if (field is FieldElement && inferredFieldTypes[field] == null) {
+    if (field is! BoxFieldElement && inferredFieldTypes[field] == null) {
       analyzeFieldInitialization(field);
     }
   }
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 6743561..a969baa 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -655,7 +655,7 @@
 }
 
 abstract class InferrerVisitor
-    <T, E extends MinimalInferrerEngine<T>> extends ResolvedVisitor<T> {
+    <T, E extends MinimalInferrerEngine<T>> extends NewResolvedVisitor<T> {
   final Compiler compiler;
   final AstElement analyzedElement;
   final TypeSystem<T> types;
@@ -719,7 +719,7 @@
 
   T visitFunctionExpression(FunctionExpression node);
 
-  T visitAssert(Send node) {
+  T visitAssertSend(Send node) {
     if (!compiler.enableUserAssertions) {
       return types.nullType;
     }
@@ -1229,7 +1229,7 @@
     return null;
   }
 
-  void internalError(String reason, {Node node}) {
+  void internalError(Spannable node, String reason) {
     compiler.internalError(node, reason);
   }
 
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index e23b1cf..9ea66a2 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -880,9 +880,9 @@
   @override
   js.Expression visitConditional(js.Conditional node) {
     if (!shouldTransform(node.then) && !shouldTransform(node.otherwise)) {
-      return withExpression(node.condition, (js.Expression condition) {
-        return js.js('# ? # : #', [condition, node.then, node.otherwise]);
-      }, store: false);
+      return js.js('# ? # : #', [visitExpression(node.condition),
+                                 visitExpression(node.then),
+                                 visitExpression(node.otherwise)]);
     }
     int thenLabel = newLabel("then");
     int joinLabel = newLabel("join");
@@ -969,10 +969,9 @@
     if (!shouldTransform(node)) {
       bool oldInsideUntranslatedBreakable = insideUntranslatedBreakable;
       insideUntranslatedBreakable = true;
-      withExpression(node.condition, (js.Expression condition) {
-        addStatement(js.js.statement('do {#} while (#)',
-                                     [node.body, condition]));
-      }, store: false);
+      addStatement(js.js.statement('do {#} while (#)',
+                                   [translateInBlock(node.body),
+                                    visitExpression(node.condition)]));
       insideUntranslatedBreakable = oldInsideUntranslatedBreakable;
       return;
     }
@@ -1348,7 +1347,8 @@
       for (js.SwitchClause clause in node.cases) {
         if (clause is js.Case) {
           labels[i] = newLabel("case");
-          clauses.add(new js.Case(clause.expression, gotoAndBreak(labels[i])));
+          clauses.add(new js.Case(visitExpression(clause.expression),
+                                  gotoAndBreak(labels[i])));
         } else if (clause is js.Default) {
           labels[i] = newLabel("default");
           clauses.add(new js.Default(gotoAndBreak(labels[i])));
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 3559724..6d1ead5 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -1115,6 +1115,11 @@
     rti.computeClassesNeedingRti();
   }
 
+  onTypeInferenceComplete() {
+    super.onTypeInferenceComplete();
+    noSuchMethodRegistry.onTypeInferenceComplete();
+  }
+
   void registerGetRuntimeTypeArgument(Registry registry) {
     enqueueInResolution(getGetRuntimeTypeArgument(), registry);
     enqueueInResolution(getGetTypeArgumentByIndex(), registry);
@@ -1216,7 +1221,7 @@
     enqueueClass(compiler.enqueuer.resolution, compiler.stringClass, registry);
   }
 
-  void registerNoSuchMethod(Element noSuchMethod) {
+  void registerNoSuchMethod(FunctionElement noSuchMethod) {
     noSuchMethodRegistry.registerNoSuchMethod(noSuchMethod);
   }
 
@@ -1399,6 +1404,7 @@
 
   int assembleProgram() {
     int programSize = emitter.assembleProgram();
+    noSuchMethodRegistry.emitDiagnostic();
     int totalMethodCount = generatedCode.length;
     if (totalMethodCount != preMirrorsMethodCount) {
       int mirrorCount = totalMethodCount - preMirrorsMethodCount;
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index f6c7e21..2fa219b 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -23,7 +23,8 @@
   }
 }
 
-class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
+class CodeGenerator extends tree_ir.StatementVisitor
+                    with tree_ir.ExpressionVisitor<js.Expression> {
   final CodegenRegistry registry;
 
   final Glue glue;
@@ -206,9 +207,10 @@
   @override
   js.Expression visitInvokeConstructor(tree_ir.InvokeConstructor node) {
     checkStaticTargetIsValid(node, node.target);
-
     if (node.constant != null) return giveup(node);
-    registry.registerInstantiatedClass(node.target.enclosingClass);
+
+    ClassElement instantiatedClass = node.target.enclosingClass;
+    registry.registerInstantiatedClass(instantiatedClass);
     Selector selector = node.selector;
     FunctionElement target = node.target;
     List<js.Expression> arguments = visitArguments(node.arguments);
@@ -500,9 +502,24 @@
 
   @override
   js.Expression visitCreateInstance(tree_ir.CreateInstance node) {
-    registry.registerInstantiatedClass(node.classElement);
-    return new js.New(glue.constructorAccess(node.classElement),
-                      node.arguments.map(visitExpression).toList());
+    ClassElement cls = node.classElement;
+    registry.registerInstantiatedClass(cls);
+    js.Expression instance = new js.New(
+        glue.constructorAccess(cls),
+        node.arguments.map(visitExpression).toList());
+
+    List<tree_ir.Expression> typeInformation = node.typeInformation;
+    assert(typeInformation.isEmpty ||
+        typeInformation.length == cls.typeVariables.length);
+    if (typeInformation.isNotEmpty) {
+      FunctionElement helper = glue.getAddRuntimeTypeInformation();
+      js.Expression typeArguments = new js.ArrayInitializer(
+          typeInformation.map(visitExpression).toList());
+      return buildStaticHelperInvocation(helper,
+          <js.Expression>[instance, typeArguments]);
+    } else {
+      return instance;
+    }
   }
 
   @override
@@ -555,6 +572,12 @@
     }
   }
 
+  @override
+  js.Expression visitTypeExpression(tree_ir.TypeExpression node) {
+    List<js.Expression> arguments =
+        node.arguments.map(visitExpression).toList(growable: false);
+    return glue.generateTypeRepresentation(node.dartType, arguments);
+  }
 
   // Dart-specific IR nodes
 
@@ -573,16 +596,6 @@
     return errorUnsupportedNode(node);
   }
 
-  @override
-  visitFieldInitializer(tree_ir.FieldInitializer node) {
-    return errorUnsupportedNode(node);
-  }
-
-  @override
-  visitSuperInitializer(tree_ir.SuperInitializer node) {
-    return errorUnsupportedNode(node);
-  }
-
   errorUnsupportedNode(tree_ir.DartSpecificNode node) {
     throw "Unsupported node in JS backend: $node";
   }
diff --git a/pkg/compiler/lib/src/js_backend/codegen/glue.dart b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
index 5dfd8de..642e136 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/glue.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
@@ -11,7 +11,7 @@
 import '../../constants/values.dart';
 import '../../elements/elements.dart';
 import '../../constants/expressions.dart';
-import '../../dart_types.dart' show TypeVariableType;
+import '../../dart_types.dart' show DartType, TypeVariableType;
 
 /// Encapsulates the dependencies of the function-compiler to the compiler,
 /// backend and emitter.
@@ -154,4 +154,18 @@
       return !_backend.rti.isTrivialSubstitution(subclass, cls);
     });
   }
+
+  FunctionElement getAddRuntimeTypeInformation() {
+    return _backend.getSetRuntimeTypeInfo();
+  }
+
+  js.Expression generateTypeRepresentation(DartType dartType,
+                                           List<js.Expression> arguments) {
+    int variableIndex = 0;
+    js.Expression representation = _backend.rti.getTypeRepresentation(
+        dartType,
+        (_) => arguments[variableIndex++]);
+    assert(variableIndex == arguments.length);
+    return representation;
+  }
 }
diff --git a/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart b/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart
index fcc772c..ecd3f59 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/js_tree_builder.dart
@@ -69,6 +69,7 @@
   Expression visitCreateInstance(cps_ir.CreateInstance node) {
     return new CreateInstance(
         node.classElement,
-        node.arguments.map(getVariableUse).toList());
+        node.arguments.map(getVariableUse).toList(growable: false),
+        node.typeInformation.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 db85809..a4ef0d9 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -108,7 +108,11 @@
 
     cps.FunctionDefinition cpsNode = irBuilderTask.buildNode(element);
     if (cpsNode == null) {
-      giveUp('unable to build cps definition of $element');
+      if (irBuilderTask.bailoutMessage == null) {
+        giveUp('unable to build cps definition of $element');
+      } else {
+        giveUp(irBuilderTask.bailoutMessage);
+      }
     }
     if (element.isInstanceMember && !element.isGenerativeConstructorBody) {
       Selector selector = new Selector.fromElement(cpsNode.element);
@@ -156,7 +160,7 @@
     }
   }
 
-  static bool checkCpsIntegrity(cps.ExecutableDefinition node) {
+  static bool checkCpsIntegrity(cps.RootNode node) {
     new CheckCpsIntegrity().check(node);
     return true; // So this can be used from assert().
   }
@@ -179,10 +183,6 @@
     applyCpsPass(new RedundantPhiEliminator());
     applyCpsPass(new ShrinkingReducer());
 
-    // Do not rewrite the IR after variable allocation.  Allocation
-    // makes decisions based on an approximation of IR variable live
-    // ranges that can be invalidated by transforming the IR.
-    new cps.RegisterAllocator(compiler.internalError).visit(cpsNode);
     return cpsNode;
   }
 
@@ -196,7 +196,7 @@
     return treeNode;
   }
 
-  static bool checkTreeIntegrity(tree_ir.ExecutableDefinition node) {
+  static bool checkTreeIntegrity(tree_ir.RootNode node) {
     new CheckTreeIntegrity().check(node);
     return true; // So this can be used from assert().
   }
@@ -209,7 +209,7 @@
     }
 
     applyTreePass(new StatementRewriter());
-    applyTreePass(new CopyPropagator());
+    applyTreePass(new VariableMerger());
     applyTreePass(new LoopRewriter());
     applyTreePass(new LogicalRewriter());
 
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 1dd4fc1..af5ac3b 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -496,23 +496,27 @@
    *
    * The resulting name is a *proposed name* and is never minified.
    */
-  String privateName(LibraryElement library, String originalName) {
+  String privateName(Name originalName) {
+    String text = originalName.text;
+
     // Public names are easy.
-    if (!isPrivateName(originalName)) return originalName;
+    if (!originalName.isPrivate) return text;
+
+    LibraryElement library = originalName.library;
 
     // The first library asking for a short private name wins.
     LibraryElement owner =
-        shortPrivateNameOwners.putIfAbsent(originalName, () => library);
+        shortPrivateNameOwners.putIfAbsent(text, () => library);
 
     if (owner == library) {
-      return originalName;
+      return text;
     } else {
       // 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\$${originalName}';
+      return '_$libraryName\$${text}';
     }
   }
 
@@ -558,9 +562,9 @@
   ///
   /// This is used for the annotated names of `call`, and for the proposed name
   /// for other instance methods.
-  List<String> callSuffixForSelector(Selector selector) {
-    List<String> suffixes = ['${selector.argumentCount}'];
-    suffixes.addAll(selector.getOrderedNamedArguments());
+  List<String> callSuffixForStructure(CallStructure callStructure) {
+    List<String> suffixes = ['${callStructure.argumentCount}'];
+    suffixes.addAll(callStructure.getOrderedNamedArguments());
     return suffixes;
   }
 
@@ -582,14 +586,13 @@
 
   /// Annotated name for the member being invoked by [selector].
   String invocationName(Selector selector) {
-    LibraryElement library = selector.library;
     switch (selector.kind) {
       case SelectorKind.GETTER:
-        String disambiguatedName = _disambiguateMember(library, selector.name);
+        String disambiguatedName = _disambiguateMember(selector.memberName);
         return deriveGetterName(disambiguatedName);
 
       case SelectorKind.SETTER:
-        String disambiguatedName = _disambiguateMember(library, selector.name);
+        String disambiguatedName = _disambiguateMember(selector.memberName);
         return deriveSetterName(disambiguatedName);
 
       case SelectorKind.OPERATOR:
@@ -599,13 +602,13 @@
         return disambiguatedName; // Operators are not annotated.
 
       case SelectorKind.CALL:
-        List<String> suffix = callSuffixForSelector(selector);
+        List<String> suffix = callSuffixForStructure(selector.callStructure);
         if (selector.name == Compiler.CALL_OPERATOR_NAME) {
           // Derive the annotated name for this variant of 'call'.
           return deriveCallMethodName(suffix);
         }
         String disambiguatedName =
-            _disambiguateMember(library, selector.name, suffix);
+            _disambiguateMember(selector.memberName, suffix);
         return disambiguatedName; // Methods other than call are not annotated.
 
       default:
@@ -625,9 +628,9 @@
    * Returns the disambiguated name for the given field, used for constructing
    * the getter and setter names.
    */
-  String fieldAccessorName(Element element) {
+  String fieldAccessorName(FieldElement element) {
     return element.isInstanceMember
-        ? _disambiguateMember(element.library, element.name)
+        ? _disambiguateMember(element.memberName)
         : _disambiguateGlobal(element);
   }
 
@@ -635,7 +638,7 @@
    * Returns name of the JavaScript property used to store a static or instance
    * field.
    */
-  String fieldPropertyName(Element element) {
+  String fieldPropertyName(FieldElement element) {
     return element.isInstanceMember
         ? instanceFieldPropertyName(element)
         : _disambiguateGlobal(element);
@@ -663,7 +666,7 @@
   /**
    * Returns the JavaScript property name used to store an instance field.
    */
-  String instanceFieldPropertyName(Element element) {
+  String instanceFieldPropertyName(FieldElement element) {
     ClassElement enclosingClass = element.enclosingClass;
 
     if (element.hasFixedBackendName) {
@@ -703,7 +706,7 @@
     // No superclass uses the disambiguated name as a property name, so we can
     // use it for this field. This generates nicer field names since otherwise
     // the field name would have to be mangled.
-    return _disambiguateMember(element.library, element.name);
+    return _disambiguateMember(element.memberName);
   }
 
   bool _isShadowingSuperField(Element element) {
@@ -717,10 +720,10 @@
   }
 
   /// Annotated name for the setter of [element].
-  String setterForElement(Element element) {
+  String 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.library, element.name);
+    String name = _disambiguateMember(element.memberName);
     return deriveSetterName(name);
   }
 
@@ -739,28 +742,19 @@
   }
 
   /// Annotated name for the getter of [element].
-  String getterForElement(Element element) {
+  String 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.library, element.name);
+    String name = _disambiguateMember(element.memberName);
     return deriveGetterName(name);
   }
 
-  /// Property name for the getter of an instance member with [originalName]
-  /// in [library].
-  ///
-  /// [library] may be `null` if [originalName] is known to be public.
-  String getterForMember(LibraryElement library, String originalName) {
-    String disambiguatedName = _disambiguateMember(library, originalName);
+  /// Property name for the getter of an instance member with [originalName].
+  String getterForMember(Name originalName) {
+    String disambiguatedName = _disambiguateMember(originalName);
     return deriveGetterName(disambiguatedName);
   }
 
-  /// Property name for the getter or a public instance member with
-  /// [originalName].
-  String getterForPublicMember(String originalName) {
-    return getterForMember(null, originalName);
-  }
-
   /// Disambiguated name for a compiler-owned global variable.
   ///
   /// The resulting name is unique within the global-member namespace.
@@ -822,23 +816,19 @@
   /// The resulting name, and its associated annotated names, are unique
   /// to the ([originalName], [suffixes]) pair within the instance-member
   /// namespace.
-  String _disambiguateMember(LibraryElement library,
-                             String originalName,
+  String _disambiguateMember(Name originalName,
                              [List<String> suffixes = const []]) {
-    // For private names, a library must be given.
-    assert(isPublicName(originalName) || library != null);
-
     // Build a string encoding the library name, if the name is private.
-    String libraryKey = isPrivateName(originalName)
-            ? _disambiguateGlobal(library)
+    String libraryKey = originalName.isPrivate
+            ? _disambiguateGlobal(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@${suffixes.join('@')}';
+    String key = '$libraryKey@${originalName.text}@${suffixes.join('@')}';
     String newName = userInstanceMembers[key];
     if (newName == null) {
-      String proposedName = privateName(library, originalName);
+      String proposedName = privateName(originalName);
       if (!suffixes.isEmpty) {
         // In the proposed name, separate the name parts by '$', because the
         // proposed name must be a valid identifier, but not necessarily unique.
diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
index 70a7936..547905d 100644
--- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
+++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
@@ -42,10 +42,15 @@
   /// The implementations that fall into category B, described above.
   final Set<FunctionElement> throwingImpls = new Set<FunctionElement>();
   /// The implementations that fall into category C, described above.
-  final Set<Element> otherImpls = new Set<Element>();
+  final Set<FunctionElement> otherImpls = new Set<FunctionElement>();
+
+  /// The implementations that fall into category C1
+  final Set<FunctionElement> complexNoReturnImpls = new Set<FunctionElement>();
+  /// The implementations that fall into category C2
+  final Set<FunctionElement> complexReturningImpls = new Set<FunctionElement>();
 
   /// The implementations that have not yet been categorized.
-  final Set<Element> _uncategorizedImpls = new Set<Element>();
+  final Set<FunctionElement> _uncategorizedImpls = new Set<FunctionElement>();
 
   final JavaScriptBackend _backend;
   final Compiler _compiler;
@@ -57,7 +62,7 @@
   bool get hasThrowingNoSuchMethod => throwingImpls.isNotEmpty;
   bool get hasComplexNoSuchMethod => otherImpls.isNotEmpty;
 
-  void registerNoSuchMethod(Element noSuchMethodElement) {
+  void registerNoSuchMethod(FunctionElement noSuchMethodElement) {
     _uncategorizedImpls.add(noSuchMethodElement);
   }
 
@@ -66,6 +71,35 @@
     _uncategorizedImpls.clear();
   }
 
+  /// Now that type inference is complete, split category C into two
+  /// subcategories: C1, those that have no return type, and C2, those
+  /// that have a return type.
+  void onTypeInferenceComplete() {
+    otherImpls.forEach(_subcategorizeOther);
+  }
+
+  /// Emits a diagnostic
+  void emitDiagnostic() {
+    throwingImpls.forEach((e) {
+        if (!_hasForwardingSyntax(e)) {
+          _compiler.reportHint(e,
+                               MessageKind.DIRECTLY_THROWING_NSM);
+        }
+      });
+    complexNoReturnImpls.forEach((e) {
+        if (!_hasForwardingSyntax(e)) {
+          _compiler.reportHint(e,
+                               MessageKind.COMPLEX_THROWING_NSM);
+        }
+      });
+    complexReturningImpls.forEach((e) {
+        if (!_hasForwardingSyntax(e)) {
+          _compiler.reportHint(e,
+                               MessageKind.COMPLEX_RETURNING_NSM);
+        }
+      });
+  }
+
   /// Returns [true] if the given element is a complex [noSuchMethod]
   /// implementation. An implementation is complex if it falls into
   /// category C, as described above.
@@ -74,54 +108,62 @@
     return otherImpls.contains(element);
   }
 
-  NsmCategory _categorizeImpl(Element noSuchMethodElement) {
-    assert(noSuchMethodElement.name == Compiler.NO_SUCH_METHOD);
-    if (defaultImpls.contains(noSuchMethodElement)) {
+  _subcategorizeOther(FunctionElement element) {
+    TypeMask returnType =
+        _compiler.typesTask.getGuaranteedReturnTypeOfElement(element);
+    if (returnType == const TypeMask.nonNullEmpty()) {
+      complexNoReturnImpls.add(element);
+    } else {
+      complexReturningImpls.add(element);
+    }
+  }
+
+  NsmCategory _categorizeImpl(FunctionElement element) {
+    assert(element.name == Compiler.NO_SUCH_METHOD);
+    if (defaultImpls.contains(element)) {
       return NsmCategory.DEFAULT;
     }
-    if (throwingImpls.contains(noSuchMethodElement)) {
+    if (throwingImpls.contains(element)) {
       return NsmCategory.THROWING;
     }
-    if (otherImpls.contains(noSuchMethodElement)) {
+    if (otherImpls.contains(element)) {
       return NsmCategory.OTHER;
     }
-    if (noSuchMethodElement is! FunctionElement ||
-        !_compiler.noSuchMethodSelector.signatureApplies(noSuchMethodElement)) {
-      otherImpls.add(noSuchMethodElement);
+    if (!_compiler.noSuchMethodSelector.signatureApplies(element)) {
+      otherImpls.add(element);
       return NsmCategory.OTHER;
     }
-    FunctionElement noSuchMethodFunc = noSuchMethodElement as FunctionElement;
-    if (_isDefaultNoSuchMethodImplementation(noSuchMethodFunc)) {
-      defaultImpls.add(noSuchMethodFunc);
+    if (_isDefaultNoSuchMethodImplementation(element)) {
+      defaultImpls.add(element);
       return NsmCategory.DEFAULT;
-    } else if (_hasForwardingSyntax(noSuchMethodFunc)) {
+    } else if (_hasForwardingSyntax(element)) {
       // If the implementation is 'noSuchMethod(x) => super.noSuchMethod(x);'
       // then it is in the same category as the super call.
-      Element superCall = noSuchMethodFunc.enclosingClass
+      Element superCall = element.enclosingClass
           .lookupSuperSelector(_compiler.noSuchMethodSelector);
       NsmCategory category = _categorizeImpl(superCall);
       switch(category) {
         case NsmCategory.DEFAULT:
-          defaultImpls.add(noSuchMethodFunc);
+          defaultImpls.add(element);
           break;
         case NsmCategory.THROWING:
-          throwingImpls.add(noSuchMethodFunc);
+          throwingImpls.add(element);
           break;
         case NsmCategory.OTHER:
-          otherImpls.add(noSuchMethodFunc);
+          otherImpls.add(element);
           break;
       }
       return category;
-    } else if (_hasThrowingSyntax(noSuchMethodFunc)) {
-      throwingImpls.add(noSuchMethodFunc);
+    } else if (_hasThrowingSyntax(element)) {
+      throwingImpls.add(element);
       return NsmCategory.THROWING;
     } else {
-      otherImpls.add(noSuchMethodFunc);
+      otherImpls.add(element);
       return NsmCategory.OTHER;
     }
   }
 
-  bool _isDefaultNoSuchMethodImplementation(Element element) {
+  bool _isDefaultNoSuchMethodImplementation(FunctionElement element) {
     ClassElement classElement = element.enclosingClass;
     return classElement == _compiler.objectClass
         || classElement == _backend.jsInterceptorClass
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 18d7f67..bf9a5f2 100644
--- a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
+++ b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
@@ -93,7 +93,7 @@
               typeVariableElement.node,
               typeVariableType,
               typeVariableConstructor,
-              new Selector.callConstructor('', null, 3),
+              const CallStructure.unnamed(3),
               arguments,
               arguments);
       ConstantValue value = constant.value;
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 8ff364d..aef381f 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -151,7 +151,7 @@
         new List.generate(selector.argumentCount, (i) => '\$$i');
 
     List<jsAst.Expression> argNames =
-        selector.getOrderedNamedArguments().map((String name) =>
+        selector.callStructure.getOrderedNamedArguments().map((String name) =>
             js.string(name)).toList();
 
     String methodName = selector.invocationMirrorMemberName;
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index 38c4cda..510933b 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -27,7 +27,8 @@
     ElementKind,
     FieldElement,
     ParameterElement,
-    TypeVariableElement;
+    TypeVariableElement,
+    MethodElement;
 
 import '../hash/sha1.dart' show Hasher;
 
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 41ddf84..cd1c967 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
@@ -48,7 +48,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.getterForPublicMember(Compiler.CALL_OPERATOR_NAME);
+      String name = namer.getterForMember(Selector.CALL_NAME);
       builder.addProperty(name, function);
     }
 
@@ -103,7 +103,7 @@
     bool fieldsAdded = false;
 
     for (Field field in fields) {
-      VariableElement fieldElement = field.element;
+      FieldElement fieldElement = field.element;
       String name = field.name;
       String accessorName = field.accessorName;
       bool needsGetter = field.needsGetter;
@@ -126,7 +126,7 @@
         }
         fieldMetadata.add(metadata);
         recordMangledField(fieldElement, accessorName,
-            namer.privateName(fieldElement.library, fieldElement.name));
+            namer.privateName(fieldElement.memberName));
         String fieldName = name;
         String fieldCode = '';
         String reflectionMarker = '';
@@ -376,7 +376,7 @@
     bool isInstantiated =
         compiler.codegenWorld.directlyInstantiatedClasses.contains(element);
 
-    void visitField(Element holder, VariableElement field) {
+    void visitField(Element holder, FieldElement field) {
       assert(invariant(element, field.isDeclaration));
       String name = field.name;
 
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 4624980..394a1ca 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
@@ -11,7 +11,7 @@
 class ContainerBuilder extends CodeEmitterHelper {
 
   void addMemberMethod(DartMethod method, ClassBuilder builder) {
-    FunctionElement member = method.element;
+    MethodElement member = method.element;
     String name = method.name;
     FunctionSignature parameters = member.functionSignature;
     jsAst.Expression code = method.code;
@@ -163,15 +163,14 @@
                 '"new ${Elements.reconstructConstructorName(member)}"');
       } else {
         reflectionName =
-            js.string(namer.privateName(member.library, member.name));
+            js.string(namer.privateName(member.memberName));
       }
       expressions
           ..add(reflectionName)
           ..addAll(task.metadataCollector
               .computeMetadata(member).map(js.number));
     } else if (isClosure && canBeApplied) {
-      expressions.add(js.string(namer.privateName(member.library,
-                                                  member.name)));
+      expressions.add(js.string(namer.privateName(member.memberName)));
     }
 
     jsAst.ArrayInitializer arrayInit =
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 0a8e2d1..4b2d79c 100644
--- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
@@ -337,8 +337,7 @@
   }
 
   String getReflectionNameInternal(elementOrSelector, String mangledName) {
-    String name =
-        namer.privateName(elementOrSelector.library, elementOrSelector.name);
+    String name = namer.privateName(elementOrSelector.memberName);
     if (elementOrSelector.isGetter) return name;
     if (elementOrSelector.isSetter) {
       if (!mangledName.startsWith(namer.setterPrefix)) return '$name=';
@@ -361,15 +360,13 @@
     if (elementOrSelector is Selector
         || elementOrSelector.isFunction
         || elementOrSelector.isConstructor) {
-      int requiredParameterCount;
-      int optionalParameterCount;
+      int positionalParameterCount;
       String namedArguments = '';
       bool isConstructor = false;
       if (elementOrSelector is Selector) {
-        Selector selector = elementOrSelector;
-        requiredParameterCount = selector.argumentCount;
-        optionalParameterCount = 0;
-        namedArguments = namedParametersAsReflectionNames(selector);
+        CallStructure callStructure = elementOrSelector.callStructure;
+        positionalParameterCount = callStructure.positionalArgumentCount;
+        namedArguments = namedParametersAsReflectionNames(callStructure);
       } else {
         FunctionElement function = elementOrSelector;
         if (function.isConstructor) {
@@ -377,34 +374,25 @@
           name = Elements.reconstructConstructorName(function);
         }
         FunctionSignature signature = function.functionSignature;
-        requiredParameterCount = signature.requiredParameterCount;
-        optionalParameterCount = signature.optionalParameterCount;
+        positionalParameterCount = signature.requiredParameterCount;
         if (signature.optionalParametersAreNamed) {
           var names = [];
           for (Element e in signature.optionalParameters) {
             names.add(e.name);
           }
-          Selector selector = new Selector.call(
-              function.name,
-              function.library,
-              requiredParameterCount,
-              names);
-          namedArguments = namedParametersAsReflectionNames(selector);
+          CallStructure callStructure =
+              new CallStructure(positionalParameterCount, names);
+          namedArguments = namedParametersAsReflectionNames(callStructure);
         } else {
-          // Named parameters are handled differently by mirrors.  For unnamed
+          // Named parameters are handled differently by mirrors. For unnamed
           // parameters, they are actually required if invoked
           // reflectively. Also, if you have a method c(x) and c([x]) they both
           // get the same mangled name, so they must have the same reflection
           // name.
-          requiredParameterCount += optionalParameterCount;
-          optionalParameterCount = 0;
+          positionalParameterCount += signature.optionalParameterCount;
         }
       }
-      String suffix =
-          // TODO(ahe): We probably don't need optionalParameterCount in the
-          // reflection name.
-          '$name:$requiredParameterCount:$optionalParameterCount'
-          '$namedArguments';
+      String suffix = '$name:$positionalParameterCount$namedArguments';
       return (isConstructor) ? 'new $suffix' : suffix;
     }
     Element element = elementOrSelector;
@@ -421,9 +409,9 @@
         'Do not know how to reflect on this $element.');
   }
 
-  String namedParametersAsReflectionNames(Selector selector) {
-    if (selector.getOrderedNamedArguments().isEmpty) return '';
-    String names = selector.getOrderedNamedArguments().join(':');
+  String namedParametersAsReflectionNames(CallStructure structure) {
+    if (structure.isUnnamed) return '';
+    String names = structure.getOrderedNamedArguments().join(':');
     return ':$names';
   }
 
@@ -528,19 +516,68 @@
         handler.getLazilyInitializedFieldsForEmission();
     if (!lazyFields.isEmpty) {
       needsLazyInitializer = true;
-      for (VariableElement element in Elements.sortedByPosition(lazyFields)) {
-        jsAst.Expression init =
-            buildLazilyInitializedStaticField(element, isolateProperties);
-        if (init == null) continue;
-        output.addBuffer(
-            jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask));
-        output.add("$N");
-      }
+      List<jsAst.Expression> laziesInfo = buildLaziesInfo(lazyFields);
+      jsAst.Statement code = js.statement('''
+      (function(lazies) {
+        if (#notInMinifiedMode) {
+          var descriptorLength = 4;
+        } else {
+          var descriptorLength = 3;
+        }
+
+        for (var i = 0; i < lazies.length; i += descriptorLength) {
+          var fieldName = lazies [i];
+          var getterName = lazies[i + 1];
+          var lazyValue = lazies[i + 2];
+          if (#notInMinifiedMode) {
+            var staticName = lazies[i + 3];
+          }
+
+          // We build the lazy-check here:
+          //   lazyInitializer(fieldName, getterName, lazyValue, staticName);
+          // 'staticName' is used for error reporting in non-minified mode.
+          // 'lazyValue' must be a closure that constructs the initial value.
+          if (#notInMinifiedMode) {
+            #lazy(fieldName, getterName, lazyValue, staticName);
+          } else {
+            #lazy(fieldName, getterName, lazyValue);
+          }
+        }
+      })(#laziesInfo)
+      ''', {'notInMinifiedMode': !compiler.enableMinification,
+            'laziesInfo': new jsAst.ArrayInitializer(laziesInfo),
+            'lazy': js(lazyInitializerName)});
+
+      output.addBuffer(
+          jsAst.prettyPrint(code, compiler, monitor: compiler.dumpInfoTask));
+      output.add("$N");
     }
   }
 
+  List<jsAst.Expression> buildLaziesInfo(List<VariableElement> lazies) {
+    List<jsAst.Expression> laziesInfo = <jsAst.Expression>[];
+    for (VariableElement element in Elements.sortedByPosition(lazies)) {
+      jsAst.Expression code = backend.generatedCode[element];
+      // The code is null if we ended up not needing the lazily
+      // initialized field after all because of constant folding
+      // before code generation.
+      if (code == null) continue;
+      if (compiler.enableMinification) {
+        laziesInfo.addAll([js.string(namer.globalPropertyName(element)),
+                           js.string(namer.lazyInitializerName(element)),
+                           code]);
+      } else {
+        laziesInfo.addAll([js.string(namer.globalPropertyName(element)),
+                           js.string(namer.lazyInitializerName(element)),
+                           code,
+                           js.string(element.name)]);
+      }
+    }
+    return laziesInfo;
+  }
+
   jsAst.Expression buildLazilyInitializedStaticField(
-      VariableElement element, String isolateProperties) {
+      VariableElement element, {String isolateProperties}) {
     jsAst.Expression code = backend.generatedCode[element];
     // The code is null if we ended up not needing the lazily
     // initialized field after all because of constant folding
@@ -548,16 +585,35 @@
     if (code == null) return null;
     // The code only computes the initial value. We build the lazy-check
     // here:
-    //   lazyInitializer(prototype, 'name', fieldName, getterName, initial);
+    //   lazyInitializer(fieldName, getterName, initial, name, prototype);
     // The name is used for error reporting. The 'initial' must be a
     // closure that constructs the initial value.
-    return js('#(#,#,#,#,#)',
-        [js(lazyInitializerName),
-            js(isolateProperties),
-            js.string(element.name),
-            js.string(namer.globalPropertyName(element)),
-            js.string(namer.lazyInitializerName(element)),
-            code]);
+    if (isolateProperties != null) {
+      // This is currently only used in incremental compilation to patch
+      // in new lazy values.
+      return js('#(#,#,#,#,#)',
+          [js(lazyInitializerName),
+           js.string(namer.globalPropertyName(element)),
+           js.string(namer.lazyInitializerName(element)),
+           code,
+           js.string(element.name),
+           isolateProperties]);
+    }
+
+    if (compiler.enableMinification) {
+      return js('#(#,#,#)',
+          [js(lazyInitializerName),
+           js.string(namer.globalPropertyName(element)),
+           js.string(namer.lazyInitializerName(element)),
+           code]);
+    } else {
+      return js('#(#,#,#,#)',
+          [js(lazyInitializerName),
+           js.string(namer.globalPropertyName(element)),
+           js.string(namer.lazyInitializerName(element)),
+           code,
+           js.string(element.name)]);
+    }
   }
 
   void emitMetadata(Program program, CodeOutput output) {
@@ -674,7 +730,6 @@
   }
 
   void emitInitFunction(CodeOutput output) {
-    String isolate = namer.currentIsolate;
     jsAst.Expression allClassesAccess =
         generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
     jsAst.Expression getTypeFromNameAccess =
@@ -700,37 +755,46 @@
         #finishedClasses = Object.create(null);
 
         if (#needsLazyInitializer) {
-          $lazyInitializerName = function (prototype, staticName, fieldName,
-                                           getterName, lazyValue) {
+          // [staticName] is only provided in non-minified mode. If missing, we 
+          // fall back to [fieldName]. Likewise, [prototype] is optional and 
+          // defaults to the isolateProperties object.
+          $lazyInitializerName = function (fieldName, getterName, lazyValue,
+                                           staticName, prototype) {
             if (!#lazies) #lazies = Object.create(null);
             #lazies[fieldName] = getterName;
 
+            // 'prototype' will be undefined except if we are doing an update
+            // during incremental compilation. In this case we put the lazy
+            // field directly on the isolate instead of the isolateProperties.
+            prototype = prototype || $isolateProperties;
             var sentinelUndefined = {};
             var sentinelInProgress = {};
             prototype[fieldName] = sentinelUndefined;
 
             prototype[getterName] = function () {
-              var result = $isolate[fieldName];
+              var result = this[fieldName];
               try {
                 if (result === sentinelUndefined) {
-                  $isolate[fieldName] = sentinelInProgress;
+                  this[fieldName] = sentinelInProgress;
 
                   try {
-                    result = $isolate[fieldName] = lazyValue();
+                    result = this[fieldName] = lazyValue();
                   } finally {
                     // Use try-finally, not try-catch/throw as it destroys the
                     // stack trace.
                     if (result === sentinelUndefined)
-                      $isolate[fieldName] = null;
+                      this[fieldName] = null;
                   }
                 } else {
                   if (result === sentinelInProgress)
-                    #cyclicThrow(staticName);
+                    // In minified mode, static name is not provided, so fall
+                    // back to the minified fieldName.
+                    #cyclicThrow(staticName || fieldName);
                 }
 
                 return result;
               } finally {
-                $isolate[getterName] = function() { return this[fieldName]; };
+                this[getterName] = function() { return this[fieldName]; };
               }
             }
           }
@@ -809,20 +873,6 @@
     }
   }
 
-  String get markerFun => 'markerFun';
-
-  void emitMarkerFun(CodeOutput output) {
-    jsAst.Statement markerFunStmt = js.statement('''
-      // This function is used to mark the end of the inheritance chain so that
-      // finishAddStubsHelper knows where to stop searching for deferred work.
-      // We have to put it at the top level so that we only get one instance of
-      // it even if we call parseReflectionData multiple times, e.g., due to 
-      // deferred loading.
-      function #() {}''', markerFun);
-    output.addBuffer(jsAst.prettyPrint(markerFunStmt, compiler));
-    output.add(N);
-  }
-
   void emitConvertToFastObjectFunction(CodeOutput output) {
     List<jsAst.Statement> debugCode = <jsAst.Statement>[];
     if (DEBUG_FAST_OBJECTS) {
@@ -1266,6 +1316,9 @@
     // constants to be set up.
     emitStaticNonFinalFieldInitializations(mainOutput, mainOutputUnit);
     interceptorEmitter.emitTypeToInterceptorMap(program, mainOutput);
+    if (compiler.enableMinification) {
+      mainOutput.add(';');
+    }
     emitLazilyInitializedStaticFields(mainOutput);
 
     mainOutput.add('\n');
@@ -1283,7 +1336,6 @@
 
     emitConvertToFastObjectFunction(mainOutput);
     emitConvertToSlowObjectFunction(mainOutput);
-    emitMarkerFun(mainOutput);
 
     for (String globalObject in Namer.reservedGlobalObjectNames) {
       mainOutput.add('$globalObject = convertToFastObject($globalObject)$N');
diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/nsm_emitter.dart
index 5f955f3..86ff20a 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
@@ -42,8 +42,8 @@
       }
 
       List<jsAst.Expression> argNames =
-               selector.getOrderedNamedArguments().map((String name) =>
-                   js.string(name)).toList();
+          selector.callStructure.getOrderedNamedArguments().map((String name) =>
+              js.string(name)).toList();
       int type = selector.invocationMirrorKind;
       if (!haveVeryFewNoSuchMemberHandlers &&
           isTrivialNsmHandler(type, argNames, selector, jsName) &&
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 86fdcd8..906afab 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
@@ -123,7 +123,6 @@
      'isTreeShakingDisabled': backend.isTreeShakingDisabled,
      'precompiled': precompiledAccess,
      'finishedClassesAccess': finishedClassesAccess,
-     'markerFun': emitter.markerFun,
      'needsMixinSupport': emitter.needsMixinSupport,
      'needsNativeSupport': program.needsNativeSupport,
      'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass),
@@ -405,7 +404,7 @@
           var prototype = constructor.prototype;
           prototype.constructor = constructor;
           prototype.#isObject = constructor;
-          prototype.#deferredAction = #markerFun;
+          prototype.#deferredAction = function() {};
           return;
         }
         finishClass(superclass);
@@ -418,21 +417,26 @@
         var constructor = allClasses[cls];
         var prototype = inheritFrom(constructor, superConstructor);
 
+        if (#needsMixinSupport) {
+          if (mixinPrototype) {
+            prototype.#deferredAction
+              = mixinDeferredActionHelper(mixinPrototype, prototype);
+          }
+        }
+
         if (#needsNativeSupport) {
           if (Object.prototype.hasOwnProperty.call(prototype, #specProperty)) {
             #nativeInfoHandler;
             // As native classes can come into existence without a constructor
             // call, we have to ensure that the class has been fully
             // initialized.
-            if (constructor.prototype.#deferredAction)
-              finishAddStubsHelper(constructor.prototype);
+            prototype.#deferredAction();
           }
         }
         // Interceptors (or rather their prototypes) are also used without
         // first instantiating them first.
-        if (prototype.#isInterceptorClass &&
-            constructor.prototype.#deferredAction) {
-          finishAddStubsHelper(constructor.prototype);
+        if (prototype.#isInterceptorClass) {
+          prototype.#deferredAction();
         }
       }
 
@@ -442,39 +446,70 @@
       for (var i = 0; i < properties.length; i++) finishClass(properties[i]);
     }
 
-
-    // For convenience, this method can be called with a prototype as argument
-    // or, if it was bound to an object, by invoking it as a method. Therefore,
-    // if prototype is undefined, this is used as prototype.
-    function finishAddStubsHelper(prototype) {
-      var prototype = prototype || this;
-      var object;
-      while (prototype.#deferredAction != #markerFun) {
-        if (prototype.hasOwnProperty(#deferredActionString)) {
-          delete prototype.#deferredAction; // Intended to make it slow, too.
-          var properties = Object.keys(prototype);
-          for (var index = 0; index < properties.length; index++) {
-            var property = properties[index];
-            var firstChar = property.charCodeAt(0);
-            var elem;
-            // We have to filter out some special properties that are used for
-            // metadata in descriptors. Currently, we filter everything that
-            // starts with + or *. This has to stay in sync with the special
-            // properties that are used by processClassData below.
-            if (property !== "${namer.classDescriptorProperty}" &&
-                property !== "$reflectableField" &&
-                firstChar !== 43 && // 43 is aka "+".
-                firstChar !== 42 && // 42 is aka "*"
-                (elem = prototype[property]) != null &&
-                elem.constructor === Array &&
-                property !== "<>") {
-              addStubs(prototype, elem, property, false, []);
-            }
-          }
-          convertToFastObject(prototype);
-        }
+    // Generic handler for deferred class setup. The handler updates the 
+    // prototype that it is installed on (it traverses the prototype chain
+    // of [this] to find itself) and then removes itself. It recurses by
+    // calling deferred handling again, which terminates on Object due to
+    // the final handler.
+    function finishAddStubsHelper() {
+      var prototype = this;
+      // Find the actual prototype that this handler is installed on.
+      while (!prototype.hasOwnProperty(#deferredActionString)) {
         prototype = prototype.__proto__;
       }
+      delete prototype.#deferredAction; // Intended to make it slow, too.
+      var properties = Object.keys(prototype);
+      for (var index = 0; index < properties.length; index++) {
+        var property = properties[index];
+        var firstChar = property.charCodeAt(0);
+        var elem;
+        // We have to filter out some special properties that are used for
+        // metadata in descriptors. Currently, we filter everything that
+        // starts with + or *. This has to stay in sync with the special
+        // properties that are used by processClassData below.
+        if (property !== "${namer.classDescriptorProperty}" &&
+            property !== "$reflectableField" &&
+            firstChar !== 43 && // 43 is aka "+".
+            firstChar !== 42 && // 42 is aka "*"
+            (elem = prototype[property]) != null &&
+            elem.constructor === Array &&
+            property !== "<>") {
+          addStubs(prototype, elem, property, false, []);
+        }
+      }
+      convertToFastObject(prototype);
+      prototype = prototype.__proto__;
+      // Call other handlers.
+      prototype.#deferredAction();
+    }
+
+    if (#needsMixinSupport) {
+      // Returns a deferred class setup handler that first invokes the
+      // handler on [mixinPrototype] and then resumes handling on
+      // [targetPrototype]. If [targetPrototype] already has a handler
+      // installed, the handler is preserved in the generated closure and
+      // thus can be safely overwritten.
+      function mixinDeferredActionHelper(mixinPrototype, targetPrototype) {
+        var chain;
+        if (targetPrototype.hasOwnProperty(#deferredActionString)) {
+          chain = targetPrototype.#deferredAction;
+        }
+        return function foo() {
+          var prototype = this;
+          // Find the actual prototype that this handler is installed on.
+          while (!prototype.hasOwnProperty(#deferredActionString)) {
+            prototype = prototype.__proto__;
+          }
+          if (chain) {
+            prototype.#deferredAction = chain;
+          } else {
+            delete prototype.#deferredAction;
+            convertToFastObject(prototype);
+          }
+          mixinPrototype.#deferredAction();
+          prototype.#deferredAction();
+        }
+      }
     }
 
     function processClassData(cls, descriptor, processedClasses) {
@@ -683,8 +718,10 @@
       if (#usesMangledNames) {
         var isReflectable = array.length > unmangledNameIndex;
         if (isReflectable) {
-          for (var i = 0; i < funcs.length; i++) {
-            funcs[i].$reflectableField = 1;
+          funcs[0].$reflectableField = 1;
+          funcs[0].$reflectionInfoField = array;
+          for (var i = 1; i < funcs.length; i++) {
+            funcs[i].$reflectableField = 2;
             funcs[i].$reflectionInfoField = array;
           }
           var mangledNames = isStatic ? #mangledGlobalNames : #mangledNames;
@@ -697,8 +734,8 @@
           if (isSetter) {
             reflectionName += "=";
           } else if (!isGetter) {
-            reflectionName += ":" + requiredParameterCount +
-              ":" + optionalParameterCount;
+            reflectionName += ":" + 
+                (requiredParameterCount + optionalParameterCount);
           }
           mangledNames[name] = reflectionName;
           funcs[0].$reflectionNameField = reflectionName;
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 9009784..7d5122b 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -38,21 +38,22 @@
   ParameterStubMethod generateParameterStub(FunctionElement member,
                                             Selector selector,
                                             Selector callSelector) {
+    CallStructure callStructure = selector.callStructure;
     FunctionSignature parameters = member.functionSignature;
-    int positionalArgumentCount = selector.positionalArgumentCount;
+    int positionalArgumentCount = callStructure.positionalArgumentCount;
     if (positionalArgumentCount == parameters.parameterCount) {
-      assert(selector.namedArgumentCount == 0);
+      assert(callStructure.isUnnamed);
       return null;
     }
-    if (parameters.optionalParametersAreNamed
-        && selector.namedArgumentCount == parameters.optionalParameterCount) {
+    if (parameters.optionalParametersAreNamed &&
+        callStructure.namedArgumentCount == parameters.optionalParameterCount) {
       // If the selector has the same number of named arguments as the element,
       // we don't need to add a stub. The call site will hit the method
       // directly.
       return null;
     }
     JavaScriptConstantCompiler handler = backend.constants;
-    List<String> names = selector.getOrderedNamedArguments();
+    List<String> names = callStructure.getOrderedNamedArguments();
 
     bool isInterceptedMethod = backend.isInterceptedMethod(member);
 
@@ -186,8 +187,8 @@
   // (1) foo$2(a, b) => MyClass.foo$4$c$d.call(this, a, b, null, null)
   // (2) foo$3$c(a, b, c) => MyClass.foo$4$c$d(this, a, b, c, null);
   // (3) foo$3$d(a, b, d) => MyClass.foo$4$c$d(this, a, b, null, d);
-  List<ParameterStubMethod> generateParameterStubs(FunctionElement member,
-                                                 {bool canTearOff: true}) {
+  List<ParameterStubMethod> generateParameterStubs(MethodElement member,
+                                                   {bool canTearOff: true}) {
     if (member.enclosingElement.isClosure) {
       ClosureClassElement cls = member.enclosingElement;
       if (cls.supertype.element == backend.boundClosureClass) {
@@ -243,9 +244,10 @@
     // Start with the callSelectors since they imply the generation of the
     // non-call version.
     for (Selector selector in callSelectors) {
-      Selector renamedSelector = new Selector.call(
-          member.name, member.library,
-          selector.argumentCount, selector.namedArguments);
+      Selector renamedSelector = new Selector(
+          SelectorKind.CALL,
+          member.memberName,
+          selector.callStructure);
       renamedCallSelectors.add(renamedSelector);
 
       if (!renamedSelector.appliesUnnamed(member, compiler.world)) continue;
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder.dart
index 829ad37..b2cb77f 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder.dart
@@ -24,7 +24,7 @@
     RuntimeTypeGenerator,
     TypeTestProperties;
 
-import '../elements/elements.dart' show ParameterElement;
+import '../elements/elements.dart' show ParameterElement, MethodElement;
 
 import '../universe/universe.dart' show Universe;
 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit;
@@ -371,7 +371,7 @@
     if (element == backend.closureClass) {
       // We add a special getter here to allow for tearing off a closure from
       // itself.
-      String name = namer.getterForPublicMember(Compiler.CALL_OPERATOR_NAME);
+      String name = namer.getterForMember(Selector.CALL_NAME);
       js.Fun function = js.js('function() { return this; }');
       callStubs.add(_buildStubMethod(name, function));
     }
@@ -485,7 +485,7 @@
     return optionalParameterDefaultValues;
   }
 
-  DartMethod _buildMethod(FunctionElement element) {
+  DartMethod _buildMethod(MethodElement element) {
     String name = namer.methodPropertyName(element);
     js.Expression code = backend.generatedCode[element];
 
@@ -578,7 +578,7 @@
     }
   }
 
-  List<ParameterStubMethod> _generateParameterStubs(FunctionElement element,
+  List<ParameterStubMethod> _generateParameterStubs(MethodElement element,
                                                     bool canTearOff) {
 
     if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[];
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 0d3ca81..3898e7d 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -6,13 +6,36 @@
 
 /// This class is a temporary work-around until we get a more powerful DartType.
 class SpecialType {
-final String name;
-const SpecialType._(this.name);
+  final String name;
+  const SpecialType._(this.name);
 
-/// The type Object, but no subtypes:
-static const JsObject = const SpecialType._('=Object');
+  /// The type Object, but no subtypes:
+  static const JsObject = const SpecialType._('=Object');
 
-int get hashCode => name.hashCode;
+  int get hashCode => name.hashCode;
+}
+
+/// Description of the exception behaviour of native code.
+///
+/// TODO(sra): Replace with something that better supports specialization on
+/// first argument properties.
+class NativeThrowBehavior {
+  static const NativeThrowBehavior NEVER = const NativeThrowBehavior._(0);
+  static const NativeThrowBehavior MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS =
+      const NativeThrowBehavior._(1);
+  static const NativeThrowBehavior MAY = const NativeThrowBehavior._(2);
+  static const NativeThrowBehavior MUST = const NativeThrowBehavior._(3);
+
+  final int _bits;
+  const NativeThrowBehavior._(this._bits);
+
+  String toString() {
+    if (this == NEVER) return 'never';
+    if (this == MAY) return 'may';
+    if (this == MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS) return 'null(1)';
+    if (this == MUST) return 'must';
+    return 'NativeThrowBehavior($_bits)';
+  }
 }
 
 /**
@@ -59,6 +82,23 @@
 
   final SideEffects sideEffects = new SideEffects.empty();
 
+  NativeThrowBehavior throwBehavior = NativeThrowBehavior.MAY;
+
+  bool isAllocation = false;
+  bool useGvn = false;
+
+  String toString() {
+    return 'NativeBehavior('
+        'returns: ${typesReturned}, '
+        'creates: ${typesInstantiated}, '
+        'sideEffects: ${sideEffects}, '
+        'throws: ${throwBehavior}'
+        '${isAllocation ? ", isAllocation" : ""}'
+        '${useGvn ? ", useGvn" : ""}'
+        ')';
+  }
+
+
   /// Processes the type specification string of a call to JS and stores the
   /// result in the [typesReturned] and [typesInstantiated]. It furthermore
   /// computes the side effects, and, if given, invokes [setSideEffects] with
@@ -66,19 +106,27 @@
   /// the [setSideEffects] method is not invoked.
   ///
   /// Two forms of the string is supported:
+  ///
   /// 1) A single type string of the form 'void', '', 'var' or 'T1|...|Tn'
   ///    which defines the types returned and for the later form also created by
   ///    the call to JS.
-  /// 2) A sequence of the form
-  ///    '<type-tag>:<type-string>;<effect-tag>:<effect-string>'
-  ///    where <type-tag> is either 'returns' or 'creates' and where
-  ///    <type-string> is a type string like in 1). The type string marked by
-  ///    'returns' defines the types returned and 'creates' defines the types
-  ///    created by the call to JS.
   ///
-  ///    The <effect-tag> is either 'effects' or 'depends' and
-  ///    <effect-string> is either 'all', 'none' or a comma-separated list of
-  ///    'no-index', 'no-instance', 'no-static'.
+  /// 2) A sequence of <tag>:<value> pairs of the following kinds
+  ///
+  ///        <type-tag>:<type-string>
+  ///        <effect-tag>:<effect-string>
+  ///        throws:<throws-string>
+  ///        gvn:<gvn-string>
+  ///        new:<new-string>
+  ///
+  ///    A <type-tag> is either 'returns' or 'creates' and <type-string> is a
+  ///    type string like in 1). The type string marked by 'returns' defines the
+  ///    types returned and 'creates' defines the types created by the call to
+  ///    JS.
+  ///
+  ///    An <effect-tag> is either 'effects' or 'depends' and <effect-string> is
+  ///    either 'all', 'none' or a comma-separated list of 'no-index',
+  ///    'no-instance', 'no-static'.
   ///
   ///    The flag 'all' indicates that the call affects/depends on every
   ///    side-effect. The flag 'none' indicates that the call does not affect
@@ -91,6 +139,20 @@
   ///    indicated with 'no-static'. The flags 'effects' and 'depends' must be
   ///    used in unison (either both are present or none is).
   ///
+  ///    The <throws-string> values are 'never', 'may', 'must', and 'null(1)'.
+  ///    The default if unspecified is 'may'. 'null(1)' means that the template
+  ///    expression throws if and only if the first template parameter is `null`
+  ///    or `undefined`.
+  ///    TODO(sra): Can we simplify to must/may/never and add null(1) by
+  ///    inspection as an orthogonal attribute?
+  ///
+  ///    <gvn-string> values are 'true' and 'false'. The default if unspecified
+  ///    is 'false'.
+  ///
+  ///    <new-string> values are 'true' and 'false'. The default if unspecified
+  ///    is 'false'. A 'true' value means that each evaluation returns a fresh
+  ///    (new) object that cannot be unaliased with existing objects.
+  ///
   ///    Each tag kind (including the 'type-tag's) can only occur once in the
   ///    sequence.
   ///
@@ -99,20 +161,37 @@
   /// the types defined by the specification string, and [objectType] and
   /// [nullType] define the types for `Object` and `Null`, respectively. The
   /// latter is used for the type strings of the form '' and 'var'.
-  // TODO(johnniwinther): Use ';' as a separator instead of a terminator.
+  /// [validTags] can be used to restrict which tags are accepted.
   static void processSpecString(
       DiagnosticListener listener,
       Spannable spannable,
       String specString,
-      {void setSideEffects(SideEffects newEffects),
+      {Iterable<String> validTags,
+       void setSideEffects(SideEffects newEffects),
+       void setThrows(NativeThrowBehavior throwKind),
+       void setIsAllocation(bool isAllocation),
+       void setUseGvn(bool useGvn),
        dynamic resolveType(String typeString),
-       List typesReturned, List typesInstantiated,
+       List typesReturned,
+       List typesInstantiated,
        objectType, nullType}) {
 
+
+    bool seenError = false;
+
+    void reportError(String message) {
+      seenError = true;
+      listener.reportError(spannable, MessageKind.GENERIC, {'text': message});
+    }
+
+    const List<String> knownTags = const [
+          'creates', 'returns', 'depends', 'effects',
+          'throws', 'gvn', 'new'];
+
     /// Resolve a type string of one of the three forms:
     /// *  'void' - in which case [onVoid] is called,
     /// *  '' or 'var' - in which case [onVar] is called,
-    /// *  'T1|...|Tn' - in which case [onType] is called for each Ti.
+    /// *  'T1|...|Tn' - in which case [onType] is called for each resolved Ti.
     void resolveTypesString(String typesString,
                             {onVoid(), onVar(), onType(type)}) {
       // Various things that are not in fact types.
@@ -129,131 +208,186 @@
         return;
       }
       for (final typeString in typesString.split('|')) {
-        onType(resolveType(typeString));
+        onType(resolveType(typeString.trim()));
       }
     }
 
-
-    if (specString.contains(':')) {
-      /// Find and remove a substring of the form 'tag:<string>;' from
-      /// [specString].
-      String getTagString(String tag) {
-        String marker = '$tag:';
-        int startPos = specString.indexOf(marker);
-        if (startPos == -1) return null;
-        int endPos = specString.indexOf(';', startPos);
-        if (endPos == -1) return null;
-        String typeString =
-            specString.substring(startPos + marker.length, endPos);
-        specString = '${specString.substring(0, startPos)}'
-                     '${specString.substring(endPos + 1)}'.trim();
-        return typeString;
-      }
-
-      String returns = getTagString('returns');
-      if (returns != null) {
-        resolveTypesString(returns, onVar: () {
-          typesReturned.add(objectType);
-          typesReturned.add(nullType);
-        }, onType: (type) {
-          typesReturned.add(type);
-        });
-      }
-
-      String creates = getTagString('creates');
-      if (creates != null) {
-        resolveTypesString(creates, onVoid: () {
-          listener.internalError(spannable,
-              "Invalid type string 'creates:$creates'");
-        }, onVar: () {
-          listener.internalError(spannable,
-              "Invalid type string 'creates:$creates'");
-        }, onType: (type) {
-          typesInstantiated.add(type);
-        });
-      }
-
-      String effects = getTagString('effects');
-      String depends = getTagString('depends');
-      if (effects != null && depends == null ||
-          effects == null && depends != null) {
-        listener.internalError(spannable,
-            "Invalid JS spec string. "
-            "'effects' and 'depends' must occur together.");
-      }
-
-      if (effects != null) {
-        SideEffects sideEffects = new SideEffects();
-        if (effects == "none") {
-          sideEffects.clearAllSideEffects();
-        } else if (effects == "all") {
-          // Don't do anything.
-        } else {
-          List<String> splitEffects = effects.split(",");
-          if (splitEffects.isEmpty) {
-            listener.internalError(spannable, "Missing side-effect flag.");
-          }
-          for (String effect in splitEffects) {
-            switch (effect) {
-              case "no-index":
-                sideEffects.clearChangesIndex();
-                break;
-              case "no-instance":
-                sideEffects.clearChangesInstanceProperty();
-                break;
-              case "no-static":
-                sideEffects.clearChangesStaticProperty();
-                break;
-              default:
-                listener.internalError(spannable,
-                    "Unrecognized side-effect flag: $effect.");
-            }
-          }
-        }
-
-        if (depends == "none") {
-          sideEffects.clearAllDependencies();
-        } else if (depends == "all") {
-          // Don't do anything.
-        } else {
-          List<String> splitDependencies = depends.split(",");
-          if (splitDependencies.isEmpty) {
-            listener.internalError(spannable,
-                                   "Missing side-effect dependency flag.");
-          }
-          for (String dependency in splitDependencies) {
-            switch (dependency) {
-              case "no-index":
-                sideEffects.clearDependsOnIndexStore();
-                break;
-              case "no-instance":
-                sideEffects.clearDependsOnInstancePropertyStore();
-                break;
-              case "no-static":
-                sideEffects.clearDependsOnStaticPropertyStore();
-                break;
-              default:
-                listener.internalError(spannable,
-                    "Unrecognized side-effect flag: $dependency.");
-            }
-          }
-        }
-
-        setSideEffects(sideEffects);
-      }
-
-      if (!specString.isEmpty) {
-        listener.internalError(spannable, "Invalid JS spec string.");
-      }
-    } else {
-      resolveTypesString(specString, onVar: () {
+    if (!specString.contains(';') && !specString.contains(':')) {
+      // Form (1), types or pseudo-types like 'void' and 'var'.
+      resolveTypesString(specString.trim(), onVar: () {
         typesReturned.add(objectType);
         typesReturned.add(nullType);
       }, onType: (type) {
         typesInstantiated.add(type);
         typesReturned.add(type);
       });
+      return;
     }
+
+    List<String> specs = specString.split(';')
+        .map((s) => s.trim())
+        .toList();
+    if (specs.last == "") specs.removeLast();  // Allow separator to terminate.
+
+    assert(validTags == null ||
+           (validTags.toSet()..removeAll(validTags)).isEmpty);
+    if (validTags == null) validTags = knownTags;
+
+    Map<String, String> values = <String, String>{};
+
+    for (String spec in specs) {
+      List<String> tagAndValue = spec.split(':');
+      if (tagAndValue.length != 2) {
+        reportError("Invalid <tag>:<value> pair '$spec'.");
+        continue;
+      }
+      String tag = tagAndValue[0].trim();
+      String value = tagAndValue[1].trim();
+
+      if (validTags.contains(tag)) {
+        if (values[tag] == null) {
+          values[tag] = value;
+        } else {
+          reportError("Duplicate tag '$tag'.");
+        }
+      } else {
+        if (knownTags.contains(tag)) {
+          reportError("Tag '$tag' is not valid here.");
+        } else {
+          reportError("Unknown tag '$tag'.");
+        }
+      }
+    }
+
+    // Enum-like tags are looked up in a map. True signature is:
+    //
+    //  T tagValueLookup<T>(String tag, Map<String, T> map);
+    //
+    dynamic tagValueLookup(String tag, Map<String, dynamic> map) {
+      String tagString = values[tag];
+      if (tagString == null) return null;
+      var value = map[tagString];
+      if (value == null) {
+        reportError("Unknown '$tag' specification: '$tagString'.");
+      }
+      return value;
+    }
+
+    String returns = values['returns'];
+    if (returns != null) {
+      resolveTypesString(returns, onVar: () {
+        typesReturned.add(objectType);
+        typesReturned.add(nullType);
+      }, onType: (type) {
+        typesReturned.add(type);
+      });
+    }
+
+    String creates = values['creates'];
+    if (creates != null) {
+      resolveTypesString(creates, onVoid: () {
+        reportError("Invalid type string 'creates:$creates'");
+      }, onVar: () {
+        reportError("Invalid type string 'creates:$creates'");
+      }, onType: (type) {
+        typesInstantiated.add(type);
+      });
+    }
+
+    const throwsOption = const <String, NativeThrowBehavior>{
+      'never': NativeThrowBehavior.NEVER,
+      'null(1)': NativeThrowBehavior.MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS,
+      'may': NativeThrowBehavior.MAY,
+      'must': NativeThrowBehavior.MUST };
+
+    const boolOptions = const<String, bool>{'true': true, 'false': false};
+
+    SideEffects sideEffects = processEffects(reportError,
+        values['effects'], values['depends']);
+    NativeThrowBehavior throwsKind = tagValueLookup('throws', throwsOption);
+    bool isAllocation = tagValueLookup('new', boolOptions);
+    bool useGvn = tagValueLookup('gvn', boolOptions);
+
+    if (isAllocation == true && useGvn == true) {
+      reportError("'new' and 'gvn' are incompatible");
+    }
+
+    if (seenError) return;  // Avoid callbacks.
+
+    // TODO(sra): Simplify [throwBehavior] using [sideEffects].
+
+    if (sideEffects != null) setSideEffects(sideEffects);
+    if (throwsKind != null) setThrows(throwsKind);
+    if (isAllocation != null) setIsAllocation(isAllocation);
+    if (useGvn != null) setUseGvn(useGvn);
+  }
+
+  static SideEffects processEffects(
+      void reportError(String message),
+      String effects,
+      String depends) {
+
+    if (effects == null && depends == null) return null;
+
+    if (effects == null || depends == null) {
+      reportError("'effects' and 'depends' must occur together.");
+      return null;
+    }
+
+    SideEffects sideEffects = new SideEffects();
+    if (effects == "none") {
+      sideEffects.clearAllSideEffects();
+    } else if (effects == "all") {
+      // Don't do anything.
+    } else {
+      List<String> splitEffects = effects.split(",");
+      if (splitEffects.isEmpty) {
+        reportError("Missing side-effect flag.");
+      }
+      for (String effect in splitEffects) {
+        switch (effect) {
+          case "no-index":
+            sideEffects.clearChangesIndex();
+            break;
+          case "no-instance":
+            sideEffects.clearChangesInstanceProperty();
+            break;
+          case "no-static":
+            sideEffects.clearChangesStaticProperty();
+            break;
+          default:
+            reportError("Unrecognized side-effect flag: '$effect'.");
+        }
+      }
+    }
+
+    if (depends == "none") {
+      sideEffects.clearAllDependencies();
+    } else if (depends == "all") {
+      // Don't do anything.
+    } else {
+      List<String> splitDependencies = depends.split(",");
+      if (splitDependencies.isEmpty) {
+        reportError("Missing side-effect dependency flag.");
+      }
+      for (String dependency in splitDependencies) {
+        switch (dependency) {
+          case "no-index":
+            sideEffects.clearDependsOnIndexStore();
+            break;
+          case "no-instance":
+            sideEffects.clearDependsOnInstancePropertyStore();
+            break;
+          case "no-static":
+            sideEffects.clearDependsOnStaticPropertyStore();
+            break;
+          default:
+            reportError("Unrecognized side-effect flag: '$dependency'.");
+        }
+      }
+    }
+
+    return sideEffects;
   }
 
   static NativeBehavior ofJsCall(Send jsCall, Compiler compiler, resolver) {
@@ -263,35 +397,40 @@
     //  'Type1|Type2'.  A union type.
     //  '=Object'.      A JavaScript Object, no subtype.
 
-    var argNodes = jsCall.arguments;
-    if (argNodes.isEmpty) {
-      compiler.internalError(jsCall, "JS expression has no type.");
-    }
-
-    var code = argNodes.tail.head;
-    if (code is !StringNode || code.isInterpolation) {
-      compiler.internalError(code, 'JS code must be a string literal.');
-    }
-
-    LiteralString specLiteral = argNodes.head.asLiteralString();
-    if (specLiteral == null) {
-      // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2').  It
-      // is not very satisfactory because it does not work for void, dynamic.
-      compiler.internalError(argNodes.head, "Unexpected JS first argument.");
-    }
-
     NativeBehavior behavior = new NativeBehavior();
-    behavior.codeTemplate =
-        js.js.parseForeignJS(code.dartString.slowToString());
 
-    String specString = specLiteral.dartString.slowToString();
+    var argNodes = jsCall.arguments;
+    if (argNodes.isEmpty || argNodes.tail.isEmpty) {
+      compiler.reportError(jsCall, MessageKind.GENERIC,
+          {'text': "JS expression takes two or more arguments."});
+      return behavior;
+    }
+
+    var specArgument = argNodes.head;
+    if (specArgument is !StringNode || specArgument.isInterpolation) {
+      compiler.reportError(specArgument, MessageKind.GENERIC,
+          {'text': "JS first argument must be a string literal."});
+      return behavior;
+    }
+
+    var codeArgument = argNodes.tail.head;
+    if (codeArgument is !StringNode || codeArgument.isInterpolation) {
+      compiler.reportError(codeArgument, MessageKind.GENERIC,
+          {'text': "JS second argument must be a string literal."});
+      return behavior;
+    }
+
+    behavior.codeTemplate =
+        js.js.parseForeignJS(codeArgument.dartString.slowToString());
+
+    String specString = specArgument.dartString.slowToString();
 
     dynamic resolveType(String typeString) {
       return _parseType(
           typeString,
           compiler,
-          (name) => resolver.resolveTypeFromString(specLiteral, name),
-          jsCall);
+          (name) => resolver.resolveTypeFromString(specArgument, name),
+          specArgument);
     }
 
     bool sideEffectsAreEncodedInSpecString = false;
@@ -301,14 +440,31 @@
       behavior.sideEffects.setTo(newEffects);
     }
 
-    processSpecString(compiler, jsCall,
-                      specString,
-                      setSideEffects: setSideEffects,
-                      resolveType: resolveType,
-                      typesReturned: behavior.typesReturned,
-                      typesInstantiated: behavior.typesInstantiated,
-                      objectType: compiler.objectClass.computeType(compiler),
-                      nullType: compiler.nullClass.computeType(compiler));
+    bool throwBehaviorFromSpecString = false;
+    void setThrows(NativeThrowBehavior throwBehavior) {
+      throwBehaviorFromSpecString = true;
+      behavior.throwBehavior = throwBehavior;
+    }
+
+    void setIsAllocation(bool isAllocation) {
+      behavior.isAllocation = isAllocation;
+    }
+
+    void setUseGvn(bool useGvn) {
+      behavior.useGvn = useGvn;
+    }
+
+    processSpecString(compiler, specArgument,
+        specString,
+        setSideEffects: setSideEffects,
+        setThrows: setThrows,
+        setIsAllocation: setIsAllocation,
+        setUseGvn: setUseGvn,
+        resolveType: resolveType,
+        typesReturned: behavior.typesReturned,
+        typesInstantiated: behavior.typesInstantiated,
+        objectType: compiler.objectClass.computeType(compiler),
+        nullType: compiler.nullClass.computeType(compiler));
 
     if (!sideEffectsAreEncodedInSpecString) {
       new SideEffectsVisitor(behavior.sideEffects)
@@ -336,7 +492,7 @@
     // We don't check the given name. That needs to be done at a later point.
     // This is, because we want to allow non-literals as names.
     if (argNodes.tail.isEmpty) {
-      compiler.internalError(jsGlobalCall, 'Embedded Global is missing name');
+      compiler.internalError(jsGlobalCall, 'Embedded Global is missing name.');
     }
 
     if (!argNodes.tail.tail.isEmpty) {
@@ -363,15 +519,9 @@
           jsGlobalCall);
     }
 
-    void setSideEffects(SideEffects newEffects) {
-      compiler.internalError(jsGlobalCall,
-          'Embedded global calls may not have any side-effect overwrites: '
-          '$specString');
-    }
-
     processSpecString(compiler, jsGlobalCall,
                       specString,
-                      setSideEffects: setSideEffects,
+                      validTags: const ['returns', 'creates'],
                       resolveType: resolveType,
                       typesReturned: behavior.typesReturned,
                       typesInstantiated: behavior.typesInstantiated,
@@ -526,19 +676,22 @@
 
     int index = typeString.indexOf('<');
     if (index < 1) {
-      compiler.internalError(
+      compiler.reportError(
           _errorNode(locationNodeOrElement, compiler),
-          "Type '$typeString' not found.");
+          MessageKind.GENERIC,
+          {'text': "Type '$typeString' not found."});
+      return const DynamicType();
     }
     type = lookup(typeString.substring(0, index));
     if (type != null)  {
       // TODO(sra): Parse type parameters.
       return type;
     }
-    compiler.internalError(
+    compiler.reportError(
         _errorNode(locationNodeOrElement, compiler),
-        "Type '$typeString' not found.");
-    return null;
+        MessageKind.GENERIC,
+        {'text': "Type '$typeString' not found."});
+    return const DynamicType();
   }
 
   static _errorNode(locationNodeOrElement, compiler) {
diff --git a/pkg/compiler/lib/src/resolution/access_semantics.dart b/pkg/compiler/lib/src/resolution/access_semantics.dart
index 6aaabf6..10800dd 100644
--- a/pkg/compiler/lib/src/resolution/access_semantics.dart
+++ b/pkg/compiler/lib/src/resolution/access_semantics.dart
@@ -12,6 +12,7 @@
 
 import '../constants/expressions.dart';
 import '../elements/elements.dart';
+import '../dart_types.dart';
 
 /// Enum representing the different kinds of destinations which a property
 /// access or method or function invocation might refer to.
@@ -307,3 +308,124 @@
 
   Element get element => setter;
 }
+
+/// Enum representing the different kinds of destinations which a constructor
+/// invocation might refer to.
+enum ConstructorAccessKind {
+  /// An invocation of a generative constructor.
+  ///
+  /// For instance
+  ///     class C {
+  ///       C();
+  ///     }
+  ///     m() => new C();
+  ///
+  GENERATIVE,
+
+  /// An invocation of a redirecting generative constructor.
+  ///
+  /// For instance
+  ///     class C {
+  ///       C() : this._();
+  ///       C._();
+  ///     }
+  ///     m() => new C();
+  ///
+  REDIRECTING_GENERATIVE,
+
+  /// An invocation of a factory constructor.
+  ///
+  /// For instance
+  ///     class C {
+  ///       factory C() => new C._();
+  ///       C._();
+  ///     }
+  ///     m() => new C();
+  ///
+  FACTORY,
+
+  /// An invocation of a redirecting factory constructor.
+  ///
+  /// For instance
+  ///     class C {
+  ///       factory C() = C._;
+  ///       C._();
+  ///     }
+  ///     m() => new C();
+  ///
+  REDIRECTING_FACTORY,
+
+  /// An invocation of a (redirecting) generative constructor of an abstract
+  /// class.
+  ///
+  /// For instance
+  ///     abstract class C {
+  ///       C();
+  ///     }
+  ///     m() => new C();
+  ///
+  ABSTRACT,
+
+  /// An invocation of an unresolved constructor or an unresolved type.
+  ///
+  /// For instance
+  ///     class C {
+  ///       C();
+  ///     }
+  ///     m1() => new C.unresolved();
+  ///     m2() => new Unresolved();
+  ///
+  // TODO(johnniwinther): Differentiate between error types.
+  ERRONEOUS,
+
+  /// An invocation of an ill-defined redirecting factory constructor.
+  ///
+  /// For instance
+  ///     class C {
+  ///       factory C() = Unresolved;
+  ///     }
+  ///     m() => new C();
+  ///
+  ERRONEOUS_REDIRECTING_FACTORY,
+}
+
+/// Data structure used to classify the semantics of a constructor invocation.
+class ConstructorAccessSemantics {
+  /// The kind of constructor invocation.
+  final ConstructorAccessKind kind;
+
+  /// The invoked constructor.
+  final Element element;
+
+  /// The type on which the constructor is invoked.
+  final DartType type;
+
+  ConstructorAccessSemantics(this.kind, this.element, this.type);
+
+  /// The effect target of the access. Used to defined redirecting factory
+  /// constructor invocations.
+  ConstructorAccessSemantics get effectiveTargetSemantics => this;
+
+  /// `true` if this invocation is erroneous.
+  bool get isErroneous {
+    return kind == ConstructorAccessKind.ABSTRACT ||
+           kind == ConstructorAccessKind.ERRONEOUS ||
+           kind == ConstructorAccessKind.ERRONEOUS_REDIRECTING_FACTORY;
+  }
+}
+
+/// Data structure used to classify the semantics of a redirecting factory
+/// constructor invocation.
+class RedirectingFactoryConstructorAccessSemantics
+    extends ConstructorAccessSemantics {
+  final ConstructorAccessSemantics effectiveTargetSemantics;
+
+  RedirectingFactoryConstructorAccessSemantics(
+      ConstructorAccessKind kind,
+      Element element,
+      DartType type,
+      this.effectiveTargetSemantics)
+      : super(kind, element, type);
+}
+
+
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 40ed27d..652387b 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -1500,7 +1500,7 @@
     final String className = lookupTarget.name;
     verifyThatConstructorMatchesCall(constructor,
                                      calledConstructor,
-                                     selector,
+                                     selector.callStructure,
                                      isImplicitSuperCall,
                                      call,
                                      className,
@@ -1519,11 +1519,6 @@
     if (classElement != visitor.compiler.objectClass) {
       assert(superClass != null);
       assert(superClass.resolutionState == STATE_DONE);
-      String constructorName = '';
-      Selector callToMatch = new Selector.call(
-          constructorName,
-          classElement.library,
-          0);
 
       final bool isSuperCall = true;
       ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
@@ -1537,7 +1532,7 @@
       final bool isImplicitSuperCall = true;
       verifyThatConstructorMatchesCall(constructor,
                                        calledConstructor,
-                                       callToMatch,
+                                       CallStructure.NO_ARGS,
                                        isImplicitSuperCall,
                                        functionNode,
                                        className,
@@ -1549,8 +1544,8 @@
 
   void verifyThatConstructorMatchesCall(
       FunctionElement caller,
-      FunctionElement lookedupConstructor,
-      Selector call,
+      ConstructorElementX lookedupConstructor,
+      CallStructure call,
       bool isImplicitSuperCall,
       Node diagnosticNode,
       String className,
@@ -1567,7 +1562,7 @@
           diagnosticNode, kind, {'constructorName': fullConstructorName});
     } else {
       lookedupConstructor.computeSignature(visitor.compiler);
-      if (!call.applies(lookedupConstructor, visitor.compiler.world)) {
+      if (!call.signatureApplies(lookedupConstructor)) {
         MessageKind kind = isImplicitSuperCall
                            ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
                            : MessageKind.NO_MATCHING_CONSTRUCTOR;
@@ -1584,8 +1579,8 @@
    * Resolve all initializers of this constructor. In the case of a redirecting
    * constructor, the resolved constructor's function element is returned.
    */
-  FunctionElement resolveInitializers(FunctionElement constructor,
-                                      FunctionExpression functionNode) {
+  ConstructorElement resolveInitializers(ConstructorElementX constructor,
+                                         FunctionExpression functionNode) {
     // Keep track of all "this.param" parameters specified for constructor so
     // that we can ensure that fields are initialized only once.
     FunctionSignature functionParameters = constructor.functionSignature;
@@ -1630,6 +1625,8 @@
           // Check that there are no other initializers.
           if (!initializers.tail.isEmpty) {
             error(call, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER);
+          } else {
+            constructor.isRedirectingGenerative = true;
           }
           // Check that there are no field initializing parameters.
           Compiler compiler = visitor.compiler;
@@ -3152,8 +3149,8 @@
                              MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR);
       } else if (!node.isArrowBody && currentAsyncMarker.isYielding) {
         compiler.reportError(
-            node, 
-            MessageKind.RETURN_IN_GENERATOR, 
+            node,
+            MessageKind.RETURN_IN_GENERATOR,
             {'modifier': currentAsyncMarker});
       }
     }
@@ -4830,22 +4827,26 @@
     throw 'not supported';
   }
 
-  failOrReturnErroneousConstructorElement(
-      Element enclosing, Node diagnosticNode,
-      String targetName, MessageKind kind,
-      Map arguments) {
-    if (kind == MessageKind.CANNOT_FIND_CONSTRUCTOR) {
+  ErroneousConstructorElementX failOrReturnErroneousConstructorElement(
+      Spannable diagnosticNode,
+      Element enclosing,
+      String name,
+      MessageKind kind,
+      Map arguments,
+      {bool isError: false,
+       bool missingConstructor: false}) {
+    if (missingConstructor) {
       registry.registerThrowNoSuchMethod();
     } else {
       registry.registerThrowRuntimeError();
     }
-    if (inConstContext) {
+    if (isError || inConstContext) {
       compiler.reportError(diagnosticNode, kind, arguments);
     } else {
       compiler.reportWarning(diagnosticNode, kind, arguments);
     }
     return new ErroneousConstructorElementX(
-        kind, arguments, targetName, enclosing);
+        kind, arguments, name, enclosing);
   }
 
   FunctionElement resolveConstructor(ClassElement cls,
@@ -4853,16 +4854,21 @@
                                      String constructorName) {
     cls.ensureResolved(compiler);
     Element result = cls.lookupConstructor(constructorName);
+    // TODO(johnniwinther): Use [Name] for lookup.
+    if (isPrivateName(constructorName) &&
+        resolver.enclosingElement.library != cls.library) {
+      result = null;
+    }
     if (result == null) {
       String fullConstructorName = Elements.constructorNameForDiagnostics(
               cls.name,
               constructorName);
       return failOrReturnErroneousConstructorElement(
-          cls,
           diagnosticNode,
-          fullConstructorName,
+          cls, constructorName,
           MessageKind.CANNOT_FIND_CONSTRUCTOR,
-          {'constructorName': fullConstructorName});
+          {'constructorName': fullConstructorName},
+          missingConstructor: true);
     } else if (inConstContext && !result.isConst) {
       error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
     }
@@ -4895,10 +4901,12 @@
         element = resolveConstructor(cls, diagnosticNode, '');
       } else {
         element = failOrReturnErroneousConstructorElement(
-            element, diagnosticNode, element.name, MessageKind.NOT_A_TYPE,
-            {'node': diagnosticNode});
+            diagnosticNode,
+            element, element.name,
+            MessageKind.NOT_A_TYPE, {'node': diagnosticNode});
       }
     } else if (element.isErroneous && element is! ErroneousElementX) {
+      // Parser error. The error has already been reported.
       element = new ErroneousConstructorElementX(
           MessageKind.NOT_A_TYPE, {'node': diagnosticNode},
           element.name, element);
@@ -4945,12 +4953,15 @@
       element = Elements.unwrap(element, compiler, node);
       if (element == null) {
         return failOrReturnErroneousConstructorElement(
-            resolver.enclosingElement, name,
-            name.source,
-            MessageKind.CANNOT_RESOLVE,
-            {'name': name});
+            name,
+            resolver.enclosingElement, name.source,
+            MessageKind.CANNOT_RESOLVE, {'name': name});
       } else if (!element.isClass) {
-        error(node, MessageKind.NOT_A_TYPE, {'node': name});
+        return failOrReturnErroneousConstructorElement(
+            name,
+            resolver.enclosingElement, name.source,
+            MessageKind.NOT_A_TYPE, {'node': name},
+            isError: true);
       }
     } else {
       internalError(node.receiver, 'unexpected element $element');
@@ -4966,31 +4977,31 @@
     // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
     if (element == null) {
       return failOrReturnErroneousConstructorElement(
-          resolver.enclosingElement, node, name,
+          node,
+          resolver.enclosingElement, name,
           MessageKind.CANNOT_RESOLVE,
           {'name': name});
     } else if (element.isErroneous) {
       return element;
     } else if (element.isTypedef) {
-      error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF,
-            {'typedefName': name});
-      element = new ErroneousConstructorElementX(
-          MessageKind.CANNOT_INSTANTIATE_TYPEDEF,
-          {'typedefName': name}, name, resolver.enclosingElement);
-      registry.registerThrowRuntimeError();
+      element = failOrReturnErroneousConstructorElement(
+          node,
+          resolver.enclosingElement, name,
+          MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name},
+          isError: true);
     } else if (element.isTypeVariable) {
-      error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
-            {'typeVariableName': name});
-      element = new ErroneousConstructorElementX(
+      element = failOrReturnErroneousConstructorElement(
+          node,
+          resolver.enclosingElement, name,
           MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
-          {'typeVariableName': name}, name, resolver.enclosingElement);
-      registry.registerThrowRuntimeError();
+          {'typeVariableName': name},
+          isError: true);
     } else if (!element.isClass && !element.isPrefix) {
-      error(node, MessageKind.NOT_A_TYPE, {'node': name});
-      element = new ErroneousConstructorElementX(
-          MessageKind.NOT_A_TYPE, {'node': name}, name,
-          resolver.enclosingElement);
-      registry.registerThrowRuntimeError();
+      element = failOrReturnErroneousConstructorElement(
+          node,
+          resolver.enclosingElement, name,
+          MessageKind.NOT_A_TYPE, {'node': name},
+          isError: true);
     }
     return element;
   }
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index 3489fbd..326bd39 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -45,6 +45,7 @@
 
 import '../ordered_typeset.dart' show OrderedTypeSet, OrderedTypeSetBuilder;
 import '../util/util.dart';
+import '../universe/universe.dart' show CallStructure;
 
 import 'class_members.dart' show MembersCreator;
 import 'enum_creator.dart';
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor.dart b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
index 7e259aa..3957d1d 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
@@ -8,6 +8,7 @@
 import '../dart2jslib.dart' show invariant;
 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;
@@ -56,6 +57,19 @@
   R visitSendSet(SendSet node) {
     return visitSend(node);
   }
+
+  @override
+  R visitNewExpression(NewExpression node) {
+    // TODO(johnniwinther): Support argument.
+    A arg = null;
+
+    NewStructure structure = computeNewStructure(node);
+    if (structure == null) {
+      return internalError(node, 'No structure for $node');
+    } else {
+      return structure.dispatch(sendVisitor, node, arg);
+    }
+  }
 }
 
 // TODO(johnniwinther): Add visits for [visitLocalConstantGet],
@@ -900,7 +914,7 @@
   ///
   R visitClassTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg);
 
   /// Invocation of the type literal for class [element] with [arguments].
@@ -911,7 +925,7 @@
   ///
   R visitClassTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg);
@@ -924,7 +938,7 @@
   ///
   R errorClassTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg);
 
@@ -936,7 +950,7 @@
   ///
   R visitTypedefTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg);
 
   /// Invocation of the type literal for typedef [element] with [arguments].
@@ -947,7 +961,7 @@
   ///
   R visitTypedefTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg);
@@ -960,7 +974,7 @@
   ///
   R errorTypedefTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg);
 
@@ -1011,7 +1025,7 @@
   ///
   R visitDynamicTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg);
 
   /// Invocation of the type literal for `dynamic` with [arguments].
@@ -1021,7 +1035,7 @@
   ///
   R visitDynamicTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg);
@@ -1033,7 +1047,7 @@
   ///
   R errorDynamicTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg);
 
@@ -1794,7 +1808,7 @@
   ///
   R errorClassTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg);
@@ -1808,7 +1822,7 @@
   ///
   R errorTypedefTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg);
@@ -1836,7 +1850,7 @@
   ///
   R errorDynamicTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg);
@@ -2169,7 +2183,7 @@
   ///
   R errorClassTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg);
 
@@ -2182,7 +2196,7 @@
   ///
   R errorTypedefTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg);
 
@@ -2207,7 +2221,7 @@
   ///
   R errorDynamicTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg);
 
@@ -2504,7 +2518,7 @@
   ///
   R errorClassTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg);
 
@@ -2517,7 +2531,7 @@
   ///
   R errorTypedefTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg);
 
@@ -2542,7 +2556,7 @@
   ///
   R errorDynamicTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg);
 
@@ -2765,4 +2779,169 @@
       Operator operator,
       Node right,
       A arg);
+
+  /// Const invocation of a [constructor].
+  ///
+  /// For instance
+  ///   class C<T> {
+  ///     const C(a, b);
+  ///   }
+  ///   m() => const C<int>(true, 42);
+  ///
+  R visitConstConstructorInvoke(
+      NewExpression node,
+      ConstructedConstantExpression constant,
+      A arg);
+
+  /// Invocation of a generative [constructor] on [type] with [arguments].
+  ///
+  /// For instance
+  ///   class C<T> {
+  ///     C(a, b);
+  ///   }
+  ///   m() => new C<int>(true, 42);
+  ///
+  /// where [type] is `C<int>`.
+  ///
+  R visitGenerativeConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  /// Invocation of a redirecting generative [constructor] on [type] with
+  /// [arguments].
+  ///
+  /// For instance
+  ///   class C<T> {
+  ///     C(a, b) : this._(b, a);
+  ///     C._(b, a);
+  ///   }
+  ///   m() => new C<int>(true, 42);
+  ///
+  /// where [type] is `C<int>`.
+  ///
+  R visitRedirectingGenerativeConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  /// Invocation of a factory [constructor] on [type] with [arguments].
+  ///
+  /// For instance
+  ///   class C<T> {
+  ///     factory C(a, b) => new C<T>._(b, a);
+  ///     C._(b, a);
+  ///   }
+  ///   m() => new C<int>(true, 42);
+  ///
+  /// where [type] is `C<int>`.
+  ///
+  R visitFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  /// Invocation of a factory [constructor] on [type] with [arguments] where
+  /// [effectiveTarget] and [effectiveTargetType] are the constructor effective
+  /// invoked and its type, respectively.
+  ///
+  /// For instance
+  ///   class C<T> {
+  ///     factory C(a, b) = C<int>.a;
+  ///     factory C.a(a, b) = C<C<T>>.b;
+  ///     C.b(a, b);
+  ///   }
+  ///   m() => new C<double>(true, 42);
+  ///
+  /// where [type] is `C<double>`, [effectiveTarget] is `C.b` and
+  /// [effectiveTargetType] is `C<C<int>>`.
+  ///
+  R visitRedirectingFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      ConstructorElement effectiveTarget,
+      InterfaceType effectiveTargetType,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  /// Invocation of an unresolved [constructor] on [type] with [arguments].
+  ///
+  /// For instance
+  ///   class C<T> {
+  ///     C();
+  ///   }
+  ///   m() => new C<int>.unresolved(true, 42);
+  ///
+  /// where [type] is `C<int>`.
+  ///
+  // TODO(johnniwinther): Update [type] to be [InterfaceType] when this is no
+  // longer a catch-all clause for the erroneous constructor invocations.
+  R errorUnresolvedConstructorInvoke(
+      NewExpression node,
+      Element constructor,
+      DartType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  /// Invocation of a constructor on an unresolved [type] with [arguments].
+  ///
+  /// For instance
+  ///   m() => new Unresolved(true, 42);
+  ///
+  /// where [type] is the malformed type `Unresolved`.
+  ///
+  R errorUnresolvedClassConstructorInvoke(
+      NewExpression node,
+      Element element,
+      MalformedType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  /// Invocation of a constructor on an abstract [type] with [arguments].
+  ///
+  /// For instance
+  ///   m() => new Unresolved(true, 42);
+  ///
+  /// where [type] is the malformed type `Unresolved`.
+  ///
+  R errorAbstractClassConstructorInvoke(
+      NewExpression node,
+      ConstructorElement element,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  /// Invocation of a factory [constructor] on [type] with [arguments] where
+  /// [effectiveTarget] and [effectiveTargetType] are the constructor effective
+  /// invoked and its type, respectively.
+  ///
+  /// For instance
+  ///   class C {
+  ///     factory C(a, b) = Unresolved;
+  ///     factory C.a(a, b) = C.unresolved;
+  ///   }
+  ///   m1() => new C(true, 42);
+  ///   m2() => new C.a(true, 42);
+  ///
+  R errorUnresolvedRedirectingFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
 }
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
index 47846a6..f1951bf 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor_mixins.dart
@@ -9,10 +9,10 @@
 ///
 /// Use this mixin to provide a trivial implementation for all `errorX` methods.
 abstract class ErrorBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleError(Send node) {
-    return bulkHandleNode(node, "Error expression `$node` unhandled.");
+  R bulkHandleError(Node node, A arg) {
+    return bulkHandleNode(node, "Error expression `$node` unhandled.", arg);
   }
 
   @override
@@ -20,81 +20,92 @@
       Send node,
       NodeList arguments,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
+  }
+
+  @override
+  R errorAbstractClassConstructorInvoke(
+      NewExpression node,
+      ConstructorElement element,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorClassTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorClassTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorClassTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorClassTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorDynamicTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorDynamicTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorDynamicTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorDynamicTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -105,7 +116,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -114,7 +125,7 @@
       LocalVariableElement variable,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -124,7 +135,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -133,7 +144,7 @@
       ParameterElement parameter,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -143,7 +154,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -152,7 +163,7 @@
       FieldElement field,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -162,7 +173,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -171,7 +182,7 @@
       FieldElement field,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -181,7 +192,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -190,7 +201,7 @@
       FieldElement field,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -200,7 +211,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -209,7 +220,7 @@
       LocalFunctionElement function,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -218,7 +229,7 @@
       LocalFunctionElement function,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -227,7 +238,7 @@
       LocalFunctionElement function,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -236,7 +247,7 @@
       MethodElement function,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -245,7 +256,7 @@
       FunctionElement getter,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -253,7 +264,7 @@
       Send node,
       FunctionElement setter,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -263,7 +274,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -272,7 +283,7 @@
       FunctionElement getter,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -281,7 +292,7 @@
       MethodElement method,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -289,7 +300,7 @@
       Send node,
       FunctionElement setter,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -299,7 +310,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -308,7 +319,7 @@
       MethodElement function,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -317,7 +328,7 @@
       FunctionElement getter,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -325,7 +336,7 @@
       Send node,
       FunctionElement setter,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -335,7 +346,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -345,7 +356,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -354,7 +365,7 @@
       TypeVariableElement element,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -363,7 +374,7 @@
       TypeVariableElement element,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -372,44 +383,44 @@
       TypeVariableElement element,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorTypedefTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorTypedefTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorTypedefTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
   R errorTypedefTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -419,7 +430,29 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
+  }
+
+  @override
+  R errorUnresolvedClassConstructorInvoke(
+      NewExpression node,
+      Element element,
+      MalformedType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return bulkHandleError(node, arg);
+  }
+
+  @override
+  R errorUnresolvedConstructorInvoke(
+      NewExpression node,
+      Element constructor,
+      DartType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -427,7 +460,7 @@
       Send node,
       Element element,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -437,7 +470,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -446,7 +479,7 @@
       Element element,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -455,7 +488,18 @@
       Element element,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
+  }
+
+  @override
+  R errorUnresolvedRedirectingFactoryConstructorInvoke(
+       NewExpression node,
+       ConstructorElement constructor,
+       InterfaceType type,
+       NodeList arguments,
+       Selector selector,
+       A arg) {
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -464,7 +508,7 @@
       Element element,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -475,7 +519,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -484,7 +528,7 @@
       Element function,
       Node index,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -494,7 +538,7 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -504,7 +548,7 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -514,7 +558,7 @@
       Node index,
       Node rhs,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -524,7 +568,7 @@
       BinaryOperator operator,
       Node argument,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -533,7 +577,7 @@
       UnaryOperator operator,
       Element element,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -543,7 +587,7 @@
       Operator operator,
       Node right,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 
   @override
@@ -552,7 +596,7 @@
       Operator operator,
       Node expression,
       A arg) {
-    return bulkHandleError(node);
+    return bulkHandleError(node, arg);
   }
 }
 
@@ -562,10 +606,10 @@
 /// Use this mixin to provide a trivial implementation for all `visitXPrefix`
 /// methods.
 abstract class PrefixBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandlePrefix(Send node) {
-    return bulkHandleNode(node, "Prefix expression `$node` unhandled.");
+  R bulkHandlePrefix(Send node, A arg) {
+    return bulkHandleNode(node, "Prefix expression `$node` unhandled.", arg);
   }
 
   @override
@@ -576,7 +620,7 @@
       Selector getterSelector,
       Selector setterSelector,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -586,7 +630,7 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -595,7 +639,7 @@
       LocalVariableElement variable,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -604,7 +648,7 @@
       ParameterElement parameter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -613,7 +657,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -623,7 +667,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -633,7 +677,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -643,7 +687,7 @@
       FieldElement writtenField,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -652,7 +696,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -662,7 +706,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -672,7 +716,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -682,7 +726,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -693,7 +737,7 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -703,7 +747,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -713,7 +757,7 @@
       Selector getterSelector,
       Selector setterSelector,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -722,7 +766,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -732,7 +776,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 
   @override
@@ -742,7 +786,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePrefix(node);
+    return bulkHandlePrefix(node, arg);
   }
 }
 
@@ -752,10 +796,10 @@
 /// Use this mixin to provide a trivial implementation for all `visitXPostfix`
 /// methods.
 abstract class PostfixBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandlePostfix(Send node) {
-    return bulkHandleNode(node, "Postfix expression `$node` unhandled.");
+  R bulkHandlePostfix(Send node, A arg) {
+    return bulkHandleNode(node, "Postfix expression `$node` unhandled.", arg);
   }
 
   @override
@@ -766,7 +810,7 @@
       Selector getterSelector,
       Selector setterSelector,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -776,7 +820,7 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -785,7 +829,7 @@
       LocalVariableElement variable,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -794,7 +838,7 @@
       ParameterElement parameter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -803,7 +847,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -813,7 +857,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -823,7 +867,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -833,7 +877,7 @@
       FieldElement writtenField,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -842,7 +886,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -852,7 +896,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -862,7 +906,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -872,7 +916,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -883,7 +927,7 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -893,7 +937,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -903,7 +947,7 @@
       Selector getterSelector,
       Selector setterSelector,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -912,7 +956,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -922,7 +966,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 
   @override
@@ -932,7 +976,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandlePostfix(node);
+    return bulkHandlePostfix(node, arg);
   }
 }
 
@@ -942,10 +986,10 @@
 /// Use this mixin to provide a trivial implementation for all `xCompound`
 /// methods.
 abstract class CompoundBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleCompound(Send node) {
-    return bulkHandleNode(node, "Compound assignment `$node` unhandled.");
+  R bulkHandleCompound(Send node, A arg) {
+    return bulkHandleNode(node, "Compound assignment `$node` unhandled.", arg);
   }
 
   @override
@@ -957,7 +1001,7 @@
       Selector getterSelector,
       Selector setterSelector,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -967,7 +1011,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -977,7 +1021,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -987,7 +1031,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -998,7 +1042,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1009,7 +1053,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1019,7 +1063,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1030,7 +1074,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1041,7 +1085,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1052,7 +1096,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1063,7 +1107,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1074,7 +1118,7 @@
       Selector getterSelector,
       Selector setterSelector,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1084,7 +1128,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1095,7 +1139,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 
   @override
@@ -1106,7 +1150,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleCompound(node);
+    return bulkHandleCompound(node, arg);
   }
 }
 
@@ -1116,20 +1160,20 @@
 /// Use this mixin to provide a trivial implementation for all `visitXInvoke`
 /// methods.
 abstract class InvokeBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleInvoke(Send node) {
-    return bulkHandleNode(node, "Invocation `$node` unhandled.");
+  R bulkHandleInvoke(Send node, A arg) {
+    return bulkHandleNode(node, "Invocation `$node` unhandled.", arg);
   }
 
   @override
   R visitClassTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1139,17 +1183,17 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
   R visitDynamicTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1159,7 +1203,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1169,7 +1213,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1179,7 +1223,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1189,7 +1233,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1199,7 +1243,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1209,7 +1253,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1219,7 +1263,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1229,7 +1273,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1239,7 +1283,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1249,7 +1293,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1258,7 +1302,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1267,7 +1311,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1277,7 +1321,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1287,7 +1331,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1297,7 +1341,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1307,17 +1351,17 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
   R visitTypedefTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 
   @override
@@ -1327,7 +1371,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleInvoke(node);
+    return bulkHandleInvoke(node, arg);
   }
 }
 
@@ -1337,18 +1381,18 @@
 /// Use this mixin to provide a trivial implementation for all `visitXGet`
 /// methods.
 abstract class GetBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleGet(Node node) {
-    return bulkHandleNode(node, "Read `$node` unhandled.");
+  R bulkHandleGet(Node node, A arg) {
+    return bulkHandleNode(node, "Read `$node` unhandled.", arg);
   }
 
   @override
   R visitClassTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1357,15 +1401,15 @@
       Node receiver,
       Selector selector,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
   R visitDynamicTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1373,7 +1417,7 @@
       Send node,
       LocalFunctionElement function,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1381,7 +1425,7 @@
       Send node,
       LocalVariableElement variable,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1389,7 +1433,7 @@
       Send node,
       ParameterElement parameter,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1397,7 +1441,7 @@
       Send node,
       FieldElement field,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1405,7 +1449,7 @@
       Send node,
       MethodElement function,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1413,7 +1457,7 @@
       Send node,
       FunctionElement getter,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1421,7 +1465,7 @@
       Send node,
       FieldElement field,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1429,7 +1473,7 @@
       Send node,
       FunctionElement getter,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1437,12 +1481,12 @@
       Send node,
       MethodElement method,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
   R visitThisGet(Identifier node, A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1450,7 +1494,7 @@
       Send node,
       Selector selector,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1458,7 +1502,7 @@
       Send node,
       FieldElement field,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1466,7 +1510,7 @@
       Send node,
       MethodElement function,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1474,7 +1518,7 @@
       Send node,
       FunctionElement getter,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
@@ -1482,23 +1526,23 @@
       Send node,
       TypeVariableElement element,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
   R visitTypedefTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 
   @override
   R visitConstantGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
-    return bulkHandleGet(node);
+    return bulkHandleGet(node, arg);
   }
 }
 
@@ -1508,10 +1552,10 @@
 /// Use this mixin to provide a trivial implementation for all `visitXSet`
 /// methods.
 abstract class SetBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleSet(Send node) {
-    return bulkHandleNode(node, "Assignment `$node` unhandled.");
+  R bulkHandleSet(Send node, A arg) {
+    return bulkHandleNode(node, "Assignment `$node` unhandled.", arg);
   }
 
   @override
@@ -1521,7 +1565,7 @@
       Selector selector,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1530,7 +1574,7 @@
       LocalVariableElement variable,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1539,7 +1583,7 @@
       ParameterElement parameter,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1548,7 +1592,7 @@
       FieldElement field,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1557,7 +1601,7 @@
       FunctionElement setter,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1566,7 +1610,7 @@
       FieldElement field,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1575,7 +1619,7 @@
       FunctionElement setter,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1584,7 +1628,7 @@
       Selector selector,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1593,7 +1637,7 @@
       FieldElement field,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 
   @override
@@ -1602,7 +1646,7 @@
       FunctionElement setter,
       Node rhs,
       A arg) {
-    return bulkHandleSet(node);
+    return bulkHandleSet(node, arg);
   }
 }
 
@@ -1612,10 +1656,10 @@
 /// Use this mixin to provide a trivial implementation for all `visitXIndexSet`
 /// methods.
 abstract class IndexSetBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleIndexSet(Send node) {
-    return bulkHandleNode(node, "Index set expression `$node` unhandled.");
+  R bulkHandleIndexSet(Send node, A arg) {
+    return bulkHandleNode(node, "Index set expression `$node` unhandled.", arg);
   }
 
   @override
@@ -1626,7 +1670,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleIndexSet(node);
+    return bulkHandleIndexSet(node, arg);
   }
 
   @override
@@ -1636,7 +1680,7 @@
       Node index,
       Node rhs,
       A arg) {
-    return bulkHandleIndexSet(node);
+    return bulkHandleIndexSet(node, arg);
   }
 
   @override
@@ -1648,7 +1692,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleIndexSet(node);
+    return bulkHandleIndexSet(node, arg);
   }
 
   @override
@@ -1658,7 +1702,7 @@
       Node index,
       Node rhs,
       A arg) {
-    return bulkHandleIndexSet(node);
+    return bulkHandleIndexSet(node, arg);
   }
 }
 
@@ -1668,10 +1712,10 @@
 /// Use this mixin to provide a trivial implementation for all binary visitor
 /// methods.
 abstract class BinaryBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleBinary(Send node) {
-    return bulkHandleNode(node, "Binary expression `$node` unhandled.");
+  R bulkHandleBinary(Send node, A arg) {
+    return bulkHandleNode(node, "Binary expression `$node` unhandled.", arg);
   }
 
   @override
@@ -1681,7 +1725,7 @@
       BinaryOperator operator,
       Node right,
       A arg) {
-    return bulkHandleBinary(node);
+    return bulkHandleBinary(node, arg);
   }
 
   @override
@@ -1690,7 +1734,7 @@
       Node left,
       Node right,
       A arg) {
-    return bulkHandleBinary(node);
+    return bulkHandleBinary(node, arg);
   }
 
   @override
@@ -1699,7 +1743,7 @@
       Node left,
       Node right,
       A arg) {
-    return bulkHandleBinary(node);
+    return bulkHandleBinary(node, arg);
   }
 
   @override
@@ -1708,7 +1752,7 @@
       Node receiver,
       Node index,
       A arg) {
-    return bulkHandleBinary(node);
+    return bulkHandleBinary(node, arg);
   }
 
   @override
@@ -1718,7 +1762,7 @@
       BinaryOperator operator,
       Node argument,
       A arg) {
-    return bulkHandleBinary(node);
+    return bulkHandleBinary(node, arg);
   }
 
   @override
@@ -1727,7 +1771,7 @@
       FunctionElement function,
       Node argument,
       A arg) {
-    return bulkHandleBinary(node);
+    return bulkHandleBinary(node, arg);
   }
 
   @override
@@ -1736,7 +1780,7 @@
       FunctionElement function,
       Node argument,
       A arg) {
-    return bulkHandleBinary(node);
+    return bulkHandleBinary(node, arg);
   }
 
   @override
@@ -1745,7 +1789,7 @@
       FunctionElement function,
       Node index,
       A arg) {
-    return bulkHandleBinary(node);
+    return bulkHandleBinary(node, arg);
   }
 }
 
@@ -1755,10 +1799,10 @@
 /// Use this mixin to provide a trivial implementation for all unary visitor
 /// methods.
 abstract class UnaryBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleUnary(Send node) {
-    return bulkHandleNode(node, "Unary expression `$node` unhandled.");
+  R bulkHandleUnary(Send node, A arg) {
+    return bulkHandleNode(node, "Unary expression `$node` unhandled.", arg);
   }
 
   @override
@@ -1766,13 +1810,13 @@
       Send node,
       Node expression,
       A arg) {
-    return bulkHandleUnary(node);
+    return bulkHandleUnary(node, arg);
   }
 
   @override
   R visitSuperUnary(Send node, UnaryOperator operator,
                     FunctionElement function, A arg) {
-    return bulkHandleUnary(node);
+    return bulkHandleUnary(node, arg);
   }
 
   @override
@@ -1781,7 +1825,7 @@
       UnaryOperator operator,
       Node expression,
       A arg) {
-    return bulkHandleUnary(node);
+    return bulkHandleUnary(node, arg);
   }
 }
 
@@ -1791,7 +1835,7 @@
 /// Use this mixin to provide a trivial implementation for all purely structural
 /// visitor methods.
 abstract class BaseBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
   @override
   R visitAs(
@@ -1799,7 +1843,7 @@
       Node expression,
       DartType type,
       A arg) {
-    return bulkHandleNode(node, 'As cast `$node` unhandled.');
+    return bulkHandleNode(node, 'As cast `$node` unhandled.', arg);
   }
 
   @override
@@ -1807,7 +1851,7 @@
       Send node,
       Node expression,
       A arg) {
-    return bulkHandleNode(node, 'Assert `$node` unhandled.');
+    return bulkHandleNode(node, 'Assert `$node` unhandled.', arg);
   }
 
   @override
@@ -1816,7 +1860,7 @@
       Node expression,
       DartType type,
       A arg) {
-    return bulkHandleNode(node, 'Is test `$node` unhandled.');
+    return bulkHandleNode(node, 'Is test `$node` unhandled.', arg);
   }
 
   @override
@@ -1825,7 +1869,7 @@
       Node expression,
       DartType type,
       A arg) {
-    return bulkHandleNode(node, 'Is not test `$node` unhandled.');
+    return bulkHandleNode(node, 'Is not test `$node` unhandled.', arg);
   }
 
   @override
@@ -1834,7 +1878,7 @@
       Node left,
       Node right,
       A arg) {
-    return bulkHandleNode(node, 'Lazy and `$node` unhandled.');
+    return bulkHandleNode(node, 'Lazy and `$node` unhandled.', arg);
   }
 
   @override
@@ -1843,7 +1887,7 @@
       Node left,
       Node right,
       A arg) {
-    return bulkHandleNode(node, 'Lazy or `$node` unhandled.');
+    return bulkHandleNode(node, 'Lazy or `$node` unhandled.', arg);
   }
 }
 
@@ -1853,10 +1897,10 @@
 /// Use this mixin to provide a trivial implementation for `super` calls
 /// visitor methods.
 abstract class SuperBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
-  R bulkHandleNode(Node node, String message);
+  R bulkHandleNode(Node node, String message, A arg);
 
-  R bulkHandleSuper(Send node) {
-    return bulkHandleNode(node, "Super call `$node` unhandled.");
+  R bulkHandleSuper(Send node, A arg) {
+    return bulkHandleNode(node, "Super call `$node` unhandled.", arg);
   }
 
   @override
@@ -1866,7 +1910,7 @@
       BinaryOperator operator,
       Node argument,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1878,7 +1922,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1887,7 +1931,7 @@
       FunctionElement function,
       Node argument,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1897,7 +1941,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1907,7 +1951,7 @@
       FieldElement writtenField,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1917,7 +1961,7 @@
       FieldElement writtenField,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1925,7 +1969,7 @@
       Send node,
       FieldElement field,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1935,7 +1979,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1944,7 +1988,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1953,7 +1997,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1962,7 +2006,7 @@
       FieldElement field,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1973,7 +2017,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1983,7 +2027,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -1993,7 +2037,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2004,7 +2048,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2014,7 +2058,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2024,7 +2068,7 @@
       FieldElement field,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2032,7 +2076,7 @@
       Send node,
       FunctionElement getter,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2042,7 +2086,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2053,7 +2097,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2063,7 +2107,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2073,7 +2117,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2083,7 +2127,7 @@
       Node index,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2091,7 +2135,7 @@
       Send node,
       MethodElement method,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2101,7 +2145,7 @@
       NodeList arguments,
       Selector selector,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2112,7 +2156,7 @@
       AssignmentOperator operator,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2122,7 +2166,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2132,7 +2176,7 @@
       FunctionElement setter,
       IncDecOperator operator,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2141,7 +2185,7 @@
       FunctionElement function,
       Node argument,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2150,7 +2194,7 @@
       FunctionElement setter,
       Node rhs,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
   }
 
   @override
@@ -2159,7 +2203,66 @@
       UnaryOperator operator,
       FunctionElement function,
       A arg) {
-    return bulkHandleSuper(node);
+    return bulkHandleSuper(node, arg);
+  }
+}
+
+abstract class NewBulkMixin<R, A> implements SemanticSendVisitor<R, A> {
+  R bulkHandleNode(Node node, String message, A arg);
+
+  R bulkHandleNew(NewExpression node, A arg) {
+    return bulkHandleNode(
+        node, "Constructor invocation `$node` unhandled.", arg);
+  }
+
+  @override
+  R visitConstConstructorInvoke(
+      NewExpression node,
+      ConstructedConstantExpression constant,
+      A arg) {
+    return bulkHandleNew(node, arg);
+  }
+
+  R visitGenerativeConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return bulkHandleNew(node, arg);
+  }
+
+  R visitRedirectingGenerativeConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return bulkHandleNew(node, arg);
+  }
+
+  R visitFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return bulkHandleNew(node, arg);
+  }
+
+  R visitRedirectingFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      ConstructorElement effectiveTarget,
+      InterfaceType effectiveTargetType,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return bulkHandleNew(node, arg);
   }
 }
 
@@ -2179,15 +2282,15 @@
          BaseBulkMixin<R, A>,
          BinaryBulkMixin<R, A>,
          PrefixBulkMixin<R, A>,
-         PostfixBulkMixin<R, A> {
-
+         PostfixBulkMixin<R, A>,
+         NewBulkMixin<R, A> {
   @override
   R apply(Node node, A arg) {
     throw new UnimplementedError("BulkVisitor.apply unimplemented");
   }
 
   @override
-  R bulkHandleNode(Node node, String message) {
+  R bulkHandleNode(Node node, String message, A arg) {
     throw new UnimplementedError("BulkVisitor.bulkHandleNode unimplemented");
   }
 }
@@ -2211,7 +2314,7 @@
   @override
   R errorClassTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg) {
     apply(rhs, arg);
@@ -2221,7 +2324,7 @@
   @override
   R errorDynamicTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg) {
     apply(rhs, arg);
@@ -2502,7 +2605,7 @@
   @override
   R errorTypedefTypeLiteralSet(
       SendSet node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       Node rhs,
       A arg) {
     apply(rhs, arg);
@@ -2553,7 +2656,7 @@
   @override
   R errorClassTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg) {
@@ -2564,7 +2667,7 @@
   @override
   R visitClassTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
     return null;
   }
@@ -2572,7 +2675,7 @@
   @override
   R visitClassTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
@@ -2583,7 +2686,7 @@
   @override
   R errorClassTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
     return null;
@@ -2592,7 +2695,7 @@
   @override
   R errorClassTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
     return null;
@@ -2705,7 +2808,7 @@
   @override
   R errorDynamicTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg) {
@@ -2716,7 +2819,7 @@
   @override
   R visitDynamicTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
     return null;
   }
@@ -2724,7 +2827,7 @@
   @override
   R visitDynamicTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
@@ -2735,7 +2838,7 @@
   @override
   R errorDynamicTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
     return null;
@@ -2744,7 +2847,7 @@
   @override
   R errorDynamicTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
     return null;
@@ -3789,7 +3892,7 @@
   @override
   R errorTypedefTypeLiteralCompound(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       AssignmentOperator operator,
       Node rhs,
       A arg) {
@@ -3800,7 +3903,7 @@
   @override
   R visitTypedefTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
     return null;
   }
@@ -3808,7 +3911,7 @@
   @override
   R visitTypedefTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
@@ -3819,7 +3922,7 @@
   @override
   R errorTypedefTypeLiteralPostfix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
     return null;
@@ -3828,7 +3931,7 @@
   @override
   R errorTypedefTypeLiteralPrefix(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       IncDecOperator operator,
       A arg) {
     return null;
@@ -3976,7 +4079,8 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    // TODO: implement errorUnresolvedSuperIndexPostfix
+    apply(index, arg);
+    return null;
   }
 
   @override
@@ -3986,7 +4090,8 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    // TODO: implement errorUnresolvedSuperIndexPrefix
+    apply(index, arg);
+    return null;
   }
 
   @override
@@ -3996,7 +4101,9 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    // TODO: implement visitIndexPostfix
+    apply(receiver, arg);
+    apply(index, arg);
+    return null;
   }
 
   @override
@@ -4006,7 +4113,9 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    // TODO: implement visitIndexPrefix
+    apply(receiver, arg);
+    apply(index, arg);
+    return null;
   }
 
   @override
@@ -4017,7 +4126,8 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    // TODO: implement visitSuperIndexPostfix
+    apply(index, arg);
+    return null;
   }
 
   @override
@@ -4028,7 +4138,112 @@
       Node index,
       IncDecOperator operator,
       A arg) {
-    // TODO: implement visitSuperIndexPrefix
+    apply(index, arg);
+    return null;
+  }
+
+  @override
+  R visitConstConstructorInvoke(
+      NewExpression node,
+      ConstructedConstantExpression constant,
+      A arg) {
+    return null;
+  }
+
+  @override
+  R errorUnresolvedClassConstructorInvoke(
+      NewExpression node,
+      Element constructor,
+      MalformedType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
+  R errorUnresolvedConstructorInvoke(
+      NewExpression node,
+      Element constructor,
+      DartType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+  R visitFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
+  R visitGenerativeConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
+  R visitRedirectingFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      ConstructorElement effectiveTarget,
+      InterfaceType effectiveTargetType,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
+  R visitRedirectingGenerativeConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
+  R errorAbstractClassConstructorInvoke(
+      NewExpression node,
+      ConstructorElement element,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
+  }
+
+  @override
+  R errorUnresolvedRedirectingFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    apply(arguments, arg);
+    return null;
   }
 }
 
@@ -4056,12 +4271,6 @@
     return null;
   }
 
-  @override
-  R visitNewExpression(NewExpression node) {
-    // Bypass the [Send] holding the class/constructor name.
-    return apply(node.send.argumentsNode, null);
-  }
-
   void visitParameters(NodeList parameters) {
 
   }
@@ -4707,7 +4916,7 @@
 abstract class BaseImplementationOfConstantsMixin<R, A>
     implements SemanticSendVisitor<R, A> {
   R handleConstantGet(
-      Send node,
+      Node node,
       ConstantExpression constant,
       A arg);
 
@@ -4721,7 +4930,7 @@
   @override
   R visitClassTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
     return handleConstantGet(node, constant, arg);
   }
@@ -4729,7 +4938,7 @@
   @override
   R visitClassTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
@@ -4737,6 +4946,14 @@
   }
 
   @override
+  R visitConstConstructorInvoke(
+      NewExpression node,
+      ConstructedConstantExpression constant,
+      A arg) {
+    return handleConstantGet(node, constant, arg);
+  }
+
+  @override
   R visitConstantGet(
       Send node,
       ConstantExpression constant,
@@ -4757,7 +4974,7 @@
   @override
   R visitDynamicTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
     return handleConstantGet(node, constant, arg);
   }
@@ -4765,7 +4982,7 @@
   @override
   R visitDynamicTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
@@ -4775,7 +4992,7 @@
   @override
   R visitTypedefTypeLiteralGet(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       A arg) {
     return handleConstantGet(node, constant, arg);
   }
@@ -4783,7 +5000,7 @@
   @override
   R visitTypedefTypeLiteralInvoke(
       Send node,
-      TypeConstantExpression constant,
+      ConstantExpression constant,
       NodeList arguments,
       Selector selector,
       A arg) {
@@ -4998,8 +5215,8 @@
   }
 }
 
-/// Mixin that groups all `visitSuperXPrefix`, `visitSuperXPostfix` methods for
-/// by delegating calls to `handleSuperXPostfixPrefix` methods.
+/// Mixin that groups all `visitSuperXPrefix`, `visitSuperXPostfix` methods by
+/// delegating calls to `handleSuperXPostfixPrefix` methods.
 ///
 /// This mixin is useful for the cases where super prefix/postfix expression are
 /// handled uniformly.
@@ -5210,3 +5427,66 @@
         index, operator, arg, isPrefix: true);
   }
 }
+
+/// Mixin that groups the non-constant `visitXConstructorInvoke` methods by
+/// delegating calls to the `handleConstructorInvoke` method.
+///
+/// This mixin is useful for the cases where all constructor invocations are
+/// handled uniformly.
+abstract class BaseImplementationOfNewMixin<R, A>
+    implements SemanticSendVisitor<R, A> {
+
+  R handleConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      DartType type,
+      NodeList arguments,
+      Selector selector,
+      A arg);
+
+  R visitGenerativeConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return handleConstructorInvoke(
+        node, constructor, type, arguments, selector, arg);
+  }
+
+  R visitRedirectingGenerativeConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return handleConstructorInvoke(
+        node, constructor, type, arguments, selector, arg);
+  }
+
+  R visitFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return handleConstructorInvoke(
+        node, constructor, type, arguments, selector, arg);
+  }
+
+  R visitRedirectingFactoryConstructorInvoke(
+      NewExpression node,
+      ConstructorElement constructor,
+      InterfaceType type,
+      ConstructorElement effectiveTarget,
+      InterfaceType effectiveTargetType,
+      NodeList arguments,
+      Selector selector,
+      A arg) {
+    return handleConstructorInvoke(
+        node, constructor, type, arguments, selector, arg);
+  }
+}
diff --git a/pkg/compiler/lib/src/resolution/send_resolver.dart b/pkg/compiler/lib/src/resolution/send_resolver.dart
index aa5a747..0ddce75 100644
--- a/pkg/compiler/lib/src/resolution/send_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/send_resolver.dart
@@ -309,7 +309,10 @@
     Element getter = isCompound ? elements[node.selector] : null;
     if (elements.isTypeLiteral(node)) {
       DartType dartType = elements.getTypeLiteralType(node);
-      TypeConstantExpression constant = elements.getConstant(
+      // TODO(johnniwinther): Handle deferred constants. There are runtime
+      // but not compile-time constants and should have their own
+      // [DeferredConstantExpression] class.
+      ConstantExpression constant = elements.getConstant(
           isInvoke ? node.selector : node);
       switch (dartType.kind) {
         case TypeKind.INTERFACE:
@@ -397,5 +400,68 @@
       }
     }
   }
+
+  ConstructorAccessSemantics computeConstructorAccessSemantics(
+        ConstructorElement constructor,
+        DartType type) {
+    if (constructor.isErroneous) {
+      return new ConstructorAccessSemantics(
+          ConstructorAccessKind.ERRONEOUS, constructor, type);
+    } else if (constructor.isRedirectingFactory) {
+      ConstructorElement effectiveTarget = constructor.effectiveTarget;
+      if (effectiveTarget == constructor ||
+          effectiveTarget.isErroneous) {
+        return new ConstructorAccessSemantics(
+            ConstructorAccessKind.ERRONEOUS_REDIRECTING_FACTORY,
+            constructor,
+            type);
+      }
+      ConstructorAccessSemantics effectiveTargetSemantics =
+          computeConstructorAccessSemantics(
+              effectiveTarget,
+              constructor.computeEffectiveTargetType(type));
+      if (effectiveTargetSemantics.isErroneous) {
+        return new RedirectingFactoryConstructorAccessSemantics(
+            ConstructorAccessKind.ERRONEOUS_REDIRECTING_FACTORY,
+            constructor,
+            type,
+            effectiveTargetSemantics);
+      }
+      return new RedirectingFactoryConstructorAccessSemantics(
+          ConstructorAccessKind.REDIRECTING_FACTORY,
+          constructor,
+          type,
+          effectiveTargetSemantics);
+    } else if (constructor.isFactoryConstructor) {
+      return new ConstructorAccessSemantics(
+          ConstructorAccessKind.FACTORY, constructor, type);
+    } else if (constructor.isRedirectingGenerative) {
+      if (constructor.enclosingClass.isAbstract) {
+          return new ConstructorAccessSemantics(
+              ConstructorAccessKind.ABSTRACT, constructor, type);
+      }
+      return new ConstructorAccessSemantics(
+          ConstructorAccessKind.REDIRECTING_GENERATIVE, constructor, type);
+    } else if (constructor.enclosingClass.isAbstract) {
+      return new ConstructorAccessSemantics(
+          ConstructorAccessKind.ABSTRACT, constructor, type);
+    } else {
+      return new ConstructorAccessSemantics(
+          ConstructorAccessKind.GENERATIVE, constructor, type);
+    }
+  }
+
+  NewStructure computeNewStructure(NewExpression node) {
+    if (node.isConst) {
+      return new ConstInvokeStructure(elements.getConstant(node));
+    }
+    Element element = elements[node.send];
+    Selector selector = elements.getSelector(node.send);
+    DartType type = elements.getType(node);
+
+    ConstructorAccessSemantics constructorAccessSemantics =
+        computeConstructorAccessSemantics(element, type);
+    return new NewInvokeStructure(constructorAccessSemantics, selector);
+  }
 }
 
diff --git a/pkg/compiler/lib/src/resolution/send_structure.dart b/pkg/compiler/lib/src/resolution/send_structure.dart
index c233b35..d507dda 100644
--- a/pkg/compiler/lib/src/resolution/send_structure.dart
+++ b/pkg/compiler/lib/src/resolution/send_structure.dart
@@ -7,8 +7,10 @@
 import 'access_semantics.dart';
 import 'operators.dart';
 import 'semantic_visitor.dart';
-import '../tree/tree.dart';
 import '../dart_types.dart';
+import '../constants/expressions.dart';
+import '../elements/elements.dart';
+import '../tree/tree.dart';
 import '../universe/universe.dart';
 import '../util/util.dart';
 
@@ -31,6 +33,8 @@
         node.arguments.single,
         arg);
   }
+
+  String toString() => 'assert';
 }
 
 /// The structure for a [Send] of the form an `assert` with less or more than
@@ -44,6 +48,8 @@
         node.argumentsNode,
         arg);
   }
+
+  String toString() => 'invalid assert';
 }
 
 /// The structure for a [Send] of the form `a && b`.
@@ -57,6 +63,8 @@
         node.arguments.single,
         arg);
   }
+
+  String toString() => '&&';
 }
 
 /// The structure for a [Send] of the form `a || b`.
@@ -70,6 +78,8 @@
         node.arguments.single,
         arg);
   }
+
+  String toString() => '||';
 }
 
 /// The structure for a [Send] of the form `a is T`.
@@ -86,6 +96,8 @@
         type,
         arg);
   }
+
+  String toString() => 'is $type';
 }
 
 /// The structure for a [Send] of the form `a is! T`.
@@ -102,6 +114,8 @@
         type,
         arg);
   }
+
+  String toString() => 'is! $type';
 }
 
 /// The structure for a [Send] of the form `a as T`.
@@ -118,6 +132,8 @@
         type,
         arg);
   }
+
+  String toString() => 'as $type';
 }
 
 /// The structure for a [Send] that is an invocation.
@@ -317,6 +333,8 @@
     }
     throw new SpannableAssertionFailure(node, "Invalid invoke: ${semantics}");
   }
+
+  String toString() => 'invoke($selector,$semantics)';
 }
 
 /// The structure for a [Send] that is a read access.
@@ -459,6 +477,8 @@
     }
     throw new SpannableAssertionFailure(node, "Invalid getter: ${semantics}");
   }
+
+  String toString() => 'get($selector,$semantics)';
 }
 
 /// The structure for a [Send] that is an assignment.
@@ -621,6 +641,8 @@
     }
     throw new SpannableAssertionFailure(node, "Invalid setter: ${semantics}");
   }
+
+  String toString() => 'set($selector,$semantics)';
 }
 
 /// The structure for a [Send] that is a negation, i.e. of the form `!e`.
@@ -646,6 +668,8 @@
     }
     throw new SpannableAssertionFailure(node, "Invalid setter: ${semantics}");
   }
+
+  String toString() => 'not($selector,$semantics)';
 }
 
 /// The structure for a [Send] that is an invocation of a user definable unary
@@ -689,6 +713,8 @@
     }
     throw new SpannableAssertionFailure(node, "Invalid setter: ${semantics}");
   }
+
+  String toString() => 'unary($operator,$semantics)';
 }
 
 /// The structure for a [Send] that is an invocation of a undefined unary
@@ -704,6 +730,8 @@
         node.receiver,
         arg);
   }
+
+  String toString() => 'invalid unary';
 }
 
 /// The structure for a [Send] that is an index expression, i.e. of the form
@@ -778,6 +806,8 @@
     }
     throw new SpannableAssertionFailure(node, "Invalid equals: ${semantics}");
   }
+
+  String toString() => '==($semantics)';
 }
 
 /// The structure for a [Send] that is a not-equals test, i.e. of the form
@@ -813,6 +843,8 @@
     throw new SpannableAssertionFailure(
         node, "Invalid not equals: ${semantics}");
   }
+
+  String toString() => '!=($semantics)';
 }
 
 /// The structure for a [Send] that is an invocation of a user-definable binary
@@ -860,6 +892,8 @@
     throw new SpannableAssertionFailure(
         node, "Invalid binary: ${semantics}");
   }
+
+  String toString() => 'binary($operator,$semantics)';
 }
 
 /// The structure for a [Send] that is an invocation of a undefined binary
@@ -876,6 +910,8 @@
         node.arguments.single,
         arg);
   }
+
+  String toString() => 'invalid binary';
 }
 
 /// The structure for a [Send] that is of the form `a[b] = c`.
@@ -919,6 +955,8 @@
     throw new SpannableAssertionFailure(
         node, "Invalid index set: ${semantics}");
   }
+
+  String toString() => '[]=($semantics)';
 }
 
 /// The structure for a [Send] that is an prefix operation on an index
@@ -1275,6 +1313,8 @@
     throw new SpannableAssertionFailure(node,
         "Invalid compound assigment: ${semantics}");
   }
+
+  String toString() => 'compound($operator,$semantics)';
 }
 
 /// The structure for a [Send] that is a compound assignment on the index
@@ -1338,6 +1378,8 @@
     throw new SpannableAssertionFailure(
         node, "Invalid compound index set: ${semantics}");
   }
+
+  String toString() => 'compound []=($operator,$semantics)';
 }
 
 /// The structure for a [Send] that is a prefix operations. For instance
@@ -1550,6 +1592,8 @@
     throw new SpannableAssertionFailure(node,
         "Invalid compound assigment: ${semantics}");
   }
+
+  String toString() => 'prefix($operator,$semantics)';
 }
 
 /// The structure for a [Send] that is a postfix operations. For instance
@@ -1762,5 +1806,71 @@
     throw new SpannableAssertionFailure(node,
         "Invalid compound assigment: ${semantics}");
   }
+
+  String toString() => 'postfix($operator,$semantics)';
+}
+
+/// The structure for a [NewExpression] of a new invocation.
+abstract class NewStructure<R, A> {
+  /// Calls the matching visit method on [visitor] with [node] and [arg].
+  R dispatch(SemanticSendVisitor<R, A> visitor, NewExpression node, A arg);
+}
+
+/// The structure for a [NewExpression] of a new invocation. For instance
+/// `new C()`.
+class NewInvokeStructure<R, A> extends NewStructure<R, A> {
+  final ConstructorAccessSemantics semantics;
+  final Selector selector;
+
+  NewInvokeStructure(this.semantics, this.selector);
+
+  R dispatch(SemanticSendVisitor<R, A> visitor, NewExpression node, A arg) {
+    switch (semantics.kind) {
+      case ConstructorAccessKind.GENERATIVE:
+        return visitor.visitGenerativeConstructorInvoke(
+            node, semantics.element, semantics.type,
+            node.send.argumentsNode, selector, arg);
+      case ConstructorAccessKind.REDIRECTING_GENERATIVE:
+        return visitor.visitRedirectingGenerativeConstructorInvoke(
+            node, semantics.element, semantics.type,
+            node.send.argumentsNode, selector, arg);
+      case ConstructorAccessKind.FACTORY:
+        return visitor.visitFactoryConstructorInvoke(
+            node, semantics.element, semantics.type,
+            node.send.argumentsNode, selector, arg);
+      case ConstructorAccessKind.REDIRECTING_FACTORY:
+        return visitor.visitRedirectingFactoryConstructorInvoke(
+            node, semantics.element, semantics.type,
+            semantics.effectiveTargetSemantics.element,
+            semantics.effectiveTargetSemantics.type,
+            node.send.argumentsNode, selector, arg);
+      case ConstructorAccessKind.ABSTRACT:
+        return visitor.errorAbstractClassConstructorInvoke(
+            node, semantics.element, semantics.type,
+            node.send.argumentsNode, selector, arg);
+      case ConstructorAccessKind.ERRONEOUS:
+        return visitor.errorUnresolvedConstructorInvoke(
+            node, semantics.element, semantics.type,
+            node.send.argumentsNode, selector, arg);
+      case ConstructorAccessKind.ERRONEOUS_REDIRECTING_FACTORY:
+        return visitor.errorUnresolvedRedirectingFactoryConstructorInvoke(
+            node, semantics.element, semantics.type,
+            node.send.argumentsNode, selector, arg);
+    }
+    throw new SpannableAssertionFailure(node,
+        "Unhandled constructor invocation kind: ${semantics.kind}");
+  }
+}
+
+/// The structure for a [NewExpression] of a constant invocation. For instance
+/// `const C()`.
+class ConstInvokeStructure<R, A> extends NewStructure<R, A> {
+  final ConstructedConstantExpression constant;
+
+  ConstInvokeStructure(this.constant);
+
+  R dispatch(SemanticSendVisitor<R, A> visitor, NewExpression node, A arg) {
+    return visitor.visitConstConstructorInvoke(node, constant, arg);
+  }
 }
 
diff --git a/pkg/compiler/lib/src/resolved_visitor.dart b/pkg/compiler/lib/src/resolved_visitor.dart
index 5d4ae3b..561746b 100644
--- a/pkg/compiler/lib/src/resolved_visitor.dart
+++ b/pkg/compiler/lib/src/resolved_visitor.dart
@@ -4,55 +4,24 @@
 
 part of dart2js;
 
-abstract class ResolvedVisitor<R> extends Visitor<R> {
-  TreeElements elements;
+/// Enum for the visit methods added in [ResolvedVisitor].
+// TODO(johnniwinther): Remove this.
+enum ResolvedKind {
+  ASSERT,
+  TYPE_LITERAL,
+  SUPER,
+  OPERATOR,
+  TYPE_PREFIX,
+  GETTER,
+  STATIC,
+  CLOSURE,
+  DYNAMIC,
+  ERROR,
+}
 
-  ResolvedVisitor(this.elements);
-
-  R visitSend(Send node) {
-    Element element = elements[node];
-    if (elements.isAssert(node)) {
-      return visitAssert(node);
-    } else if (elements.isTypeLiteral(node)) {
-      return visitTypeLiteralSend(node);
-    } else if (node.isSuperCall) {
-      return visitSuperSend(node);
-    } else if (node.isOperator) {
-      return visitOperatorSend(node);
-    } else if (node.isPropertyAccess) {
-      if (!Elements.isUnresolved(element) && element.impliesType) {
-        return visitTypePrefixSend(node);
-      } else {
-        return visitGetterSend(node);
-      }
-    } else if (element != null && Initializers.isConstructorRedirect(node)) {
-      return visitStaticSend(node);
-    } else if (Elements.isClosureSend(node, element)) {
-      return visitClosureSend(node);
-    } else {
-      if (Elements.isUnresolved(element)) {
-        if (element == null) {
-          // Example: f() with 'f' unbound.
-          // This can only happen inside an instance method.
-          return visitDynamicSend(node);
-        } else {
-          return visitStaticSend(node);
-        }
-      } else if (element.isInstanceMember) {
-        // Example: f() with 'f' bound to instance method.
-        return visitDynamicSend(node);
-      } else if (!element.isInstanceMember) {
-        // Example: A.f() or f() with 'f' bound to a static function.
-        // Also includes new A() or new A.named() which is treated like a
-        // static call to a factory.
-        return visitStaticSend(node);
-      } else {
-        internalError("Cannot generate code for send", node: node);
-        return null;
-      }
-    }
-  }
-
+/// Abstract interface for a [ResolvedVisitor].
+// TODO(johnniwinther): Remove this.
+abstract class ResolvedKindVisitor<R> {
   R visitSuperSend(Send node);
   R visitOperatorSend(Send node);
   R visitGetterSend(Send node);
@@ -68,12 +37,671 @@
   // TODO(johnniwinther): Remove this when not needed by the dart backend.
   R visitTypePrefixSend(Send node);
 
-  R visitAssert(Send node);
+  R visitAssertSend(Send node);
 
-  void internalError(String reason, {Node node});
+  internalError(Spannable node, String reason);
+}
+
+/// Visitor that returns the [ResolvedKind] corresponding to the called visitor
+/// method.
+class ResolvedKindComputer implements ResolvedKindVisitor {
+  const ResolvedKindComputer();
+
+  ResolvedKind visitSuperSend(Send node) => ResolvedKind.SUPER;
+  ResolvedKind visitOperatorSend(Send node) => ResolvedKind.OPERATOR;
+  ResolvedKind visitGetterSend(Send node) => ResolvedKind.GETTER;
+  ResolvedKind visitClosureSend(Send node) => ResolvedKind.CLOSURE;
+  ResolvedKind visitDynamicSend(Send node) => ResolvedKind.DYNAMIC;
+  ResolvedKind visitStaticSend(Send node) => ResolvedKind.STATIC;
+  ResolvedKind visitTypeLiteralSend(Send node) => ResolvedKind.TYPE_LITERAL;
+  ResolvedKind visitTypePrefixSend(Send node) => ResolvedKind.TYPE_PREFIX;
+  ResolvedKind visitAssertSend(Send node) => ResolvedKind.ASSERT;
+  internalError(Spannable node, String reason) => ResolvedKind.ERROR;
+}
+
+abstract class ResolvedVisitor<R>
+    implements Visitor<R>, ResolvedKindVisitor<R> {}
+
+abstract class BaseResolvedVisitor<R> extends Visitor<R>
+    implements ResolvedVisitor<R> {
+
+  TreeElements elements;
+
+  BaseResolvedVisitor(this.elements);
+
+  /// Dispatch using the old [ResolvedVisitor] logic.
+  // TODO(johnniwinther): Remove this.
+  _oldDispatch(Send node, ResolvedKindVisitor visitor) {
+    Element element = elements[node];
+    if (elements.isAssert(node)) {
+      return visitor.visitAssertSend(node);
+    } else if (elements.isTypeLiteral(node)) {
+      return visitor.visitTypeLiteralSend(node);
+    } else if (node.isSuperCall) {
+      return visitor.visitSuperSend(node);
+    } else if (node.isOperator) {
+      return visitor.visitOperatorSend(node);
+    } else if (node.isPropertyAccess) {
+      if (!Elements.isUnresolved(element) && element.impliesType) {
+        return visitor.visitTypePrefixSend(node);
+      } else {
+        return visitor.visitGetterSend(node);
+      }
+    } else if (element != null && Initializers.isConstructorRedirect(node)) {
+      return visitor.visitStaticSend(node);
+    } else if (Elements.isClosureSend(node, element)) {
+      return visitor.visitClosureSend(node);
+    } else {
+      if (Elements.isUnresolved(element)) {
+        if (element == null) {
+          // Example: f() with 'f' unbound.
+          // This can only happen inside an instance method.
+          return visitor.visitDynamicSend(node);
+        } else {
+          return visitor.visitStaticSend(node);
+        }
+      } else if (element.isInstanceMember) {
+        // Example: f() with 'f' bound to instance method.
+        return visitor.visitDynamicSend(node);
+      } else if (!element.isInstanceMember) {
+        // Example: A.f() or f() with 'f' bound to a static function.
+        // Also includes new A() or new A.named() which is treated like a
+        // static call to a factory.
+        return visitor.visitStaticSend(node);
+      } else {
+        return visitor.internalError(node, "Cannot generate code for send");
+      }
+    }
+  }
+
+  internalError(Spannable node, String reason);
 
   R visitNode(Node node) {
-    internalError("Unhandled node", node: node);
+    internalError(node, "Unhandled node");
     return null;
   }
 }
+
+// TODO(johnniwinther): Remove this. Currently need by the old dart2dart
+// backend.
+abstract class OldResolvedVisitor<R> extends BaseResolvedVisitor<R> {
+  OldResolvedVisitor(TreeElements elements) : super(elements);
+
+  R visitSend(Send node) {
+    return _oldDispatch(node, this);
+  }
+}
+
+abstract class NewResolvedVisitor<R> extends BaseResolvedVisitor<R>
+    with SendResolverMixin,
+         GetBulkMixin<R, dynamic>,
+         SetBulkMixin<R, dynamic>,
+         ErrorBulkMixin<R, dynamic>,
+         InvokeBulkMixin<R, dynamic>,
+         IndexSetBulkMixin<R, dynamic>,
+         CompoundBulkMixin<R, dynamic>,
+         UnaryBulkMixin<R, dynamic>,
+         BaseBulkMixin<R, dynamic>,
+         BinaryBulkMixin<R, dynamic>,
+         PrefixBulkMixin<R, dynamic>,
+         PostfixBulkMixin<R, dynamic>,
+         NewBulkMixin<R, dynamic> {
+
+  final ResolvedSemanticDispatcher<R> _semanticDispatcher =
+      new ResolvedSemanticDispatcher<R>();
+
+  final ResolvedSemanticDispatcher<ResolvedKind> _resolvedKindDispatcher =
+      new ResolvedSemanticDispatcher<ResolvedKind>();
+
+  NewResolvedVisitor(TreeElements elements) : super(elements);
+
+  /// Dispatch using the new [SemanticSendVisitor] logic.
+  _newDispatch(Send node,
+               ResolvedKindVisitor kindVisitor,
+               SemanticSendVisitor sendVisitor) {
+    Element element = elements[node];
+    if (element != null && element.isConstructor) {
+      if (node.isSuperCall) {
+        return kindVisitor.visitSuperSend(node);
+      } else {
+        return kindVisitor.visitStaticSend(node);
+      }
+    } else if (element != null && element.isPrefix) {
+      return kindVisitor.visitGetterSend(node);
+    } else if (!elements.isTypeLiteral(node) &&
+               node.isPropertyAccess &&
+               !Elements.isUnresolved(element) &&
+               element.impliesType) {
+      return kindVisitor.visitTypePrefixSend(node);
+    } else {
+      SendStructure sendStructure = computeSendStructure(node);
+      if (sendStructure != null) {
+        var arg = sendVisitor == _resolvedKindDispatcher
+            ? kindVisitor : sendStructure;
+        return sendStructure.dispatch(sendVisitor, node, arg);
+      } else {
+        return kindVisitor.visitStaticSend(node);
+      }
+    }
+  }
+
+  R visitSend(Send node) {
+    ResolvedKind oldKind;
+    ResolvedKind newKind;
+    assert(invariant(node, () {
+      oldKind = _oldDispatch(node, const ResolvedKindComputer());
+      newKind = _newDispatch(
+          node, const ResolvedKindComputer(), _resolvedKindDispatcher);
+      return oldKind == newKind;
+    }, message: () => '$oldKind != $newKind'));
+    return _newDispatch(node, this, this);
+  }
+
+  @override
+  R apply(Node node, arg) {
+    return visitNode(node);
+  }
+
+  @override
+  R bulkHandleNode(
+      Node node,
+      String message,
+      SendStructure sendStructure) {
+    return sendStructure.dispatch(_semanticDispatcher, node, this);
+  }
+}
+
+/// Visitor that dispatches [SemanticSendVisitor] calls to the corresponding
+/// visit methods in [ResolvedVisitor].
+class ResolvedSemanticDispatcher<R> extends Object
+    with GetBulkMixin<R, ResolvedKindVisitor<R>>,
+         SetBulkMixin<R, ResolvedKindVisitor<R>>,
+         InvokeBulkMixin<R, ResolvedKindVisitor<R>>,
+         PrefixBulkMixin<R, ResolvedKindVisitor<R>>,
+         PostfixBulkMixin<R, ResolvedKindVisitor<R>>,
+         SuperBulkMixin<R, ResolvedKindVisitor<R>>,
+         CompoundBulkMixin<R, ResolvedKindVisitor<R>>,
+         IndexSetBulkMixin<R, ResolvedKindVisitor<R>>,
+         NewBulkMixin<R, ResolvedKindVisitor<R>>,
+         ErrorBulkMixin<R, ResolvedKindVisitor<R>>
+    implements SemanticSendVisitor<R, ResolvedKindVisitor<R>> {
+
+  ResolvedSemanticDispatcher();
+
+  @override
+  R apply(Node node, ResolvedKindVisitor<R> visitor) {
+    return visitor.internalError(
+        node, "ResolvedSemanticDispatcher.apply unsupported.");
+  }
+
+  @override
+  R bulkHandleNode(
+      Node node,
+      String message,
+      ResolvedKindVisitor<R> visitor) {
+    // Set, Compound, IndexSet, and NewExpression are not handled by
+    // [ResolvedVisitor].
+    return bulkHandleError(node, visitor);
+  }
+
+  R bulkHandleError(Node node, ResolvedKindVisitor<R> visitor) {
+    return visitor.internalError(node, "No resolved kind for node.");
+  }
+
+  @override
+  R bulkHandleGet(Node node, ResolvedKindVisitor<R> visitor) {
+    return visitor.visitGetterSend(node);
+  }
+
+  @override
+  R bulkHandleInvoke(Node node, ResolvedKindVisitor<R> visitor) {
+    // Most invokes are static.
+    return visitor.visitStaticSend(node);
+  }
+
+  @override
+  R bulkHandlePrefix(Node node, ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R bulkHandlePostfix(Node node, ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R bulkHandleSuper(Node node, ResolvedKindVisitor<R> visitor) {
+    return visitor.visitSuperSend(node);
+  }
+
+  @override
+  R errorInvalidAssert(
+      Send node,
+      NodeList arguments,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitAssertSend(node);
+  }
+
+  @override
+  R errorLocalFunctionPostfix(
+      Send node,
+      LocalFunctionElement function,
+      op.IncDecOperator operator,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R errorLocalFunctionPrefix(
+      Send node,
+      LocalFunctionElement function,
+      op.IncDecOperator operator,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R errorStaticSetterGet(
+      Send node,
+      FunctionElement setter,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitGetterSend(node);
+  }
+
+  @override
+  R errorStaticSetterInvoke(
+      Send node,
+      FunctionElement setter,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitStaticSend(node);
+  }
+
+  @override
+  R errorSuperSetterGet(
+      Send node,
+      FunctionElement setter,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitGetterSend(node);
+  }
+
+  @override
+  R errorSuperSetterInvoke(
+      Send node,
+      FunctionElement setter,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitSuperSend(node);
+  }
+
+  @override
+  R errorTopLevelSetterGet(
+      Send node,
+      FunctionElement setter,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitGetterSend(node);
+  }
+
+  @override
+  R errorTopLevelSetterInvoke(
+      Send node,
+      FunctionElement setter,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitStaticSend(node);
+  }
+
+  @override
+  R errorUndefinedBinaryExpression(
+      Send node,
+      Node left,
+      Operator operator,
+      Node right,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R errorUndefinedUnaryExpression(
+      Send node,
+      Operator operator,
+      Node expression,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R errorUnresolvedGet(
+      Send node,
+      Element element,
+      ResolvedKindVisitor<R> visitor) {
+    if (node.isSuperCall) {
+      return visitor.visitSuperSend(node);
+    }
+    return visitor.visitGetterSend(node);
+  }
+
+  @override
+  R errorUnresolvedInvoke(
+      Send node,
+      Element element,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    if (node.isSuperCall) {
+      return visitor.visitSuperSend(node);
+    }
+    return visitor.visitStaticSend(node);
+  }
+
+  @override
+  R errorUnresolvedPostfix(
+      Send node,
+      Element element,
+      op.IncDecOperator operator,
+      ResolvedKindVisitor<R> visitor) {
+    if (node.isSuperCall) {
+      return visitor.visitSuperSend(node);
+    }
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R errorUnresolvedPrefix(
+      Send node,
+      Element element,
+      op.IncDecOperator operator,
+      ResolvedKindVisitor<R> visitor) {
+    if (node.isSuperCall) {
+      return visitor.visitSuperSend(node);
+    }
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R errorUnresolvedSuperBinary(
+      Send node,
+      Element element,
+      op.BinaryOperator operator,
+      Node argument,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitSuperSend(node);
+  }
+
+  @override
+  R errorUnresolvedSuperUnary(
+      Send node,
+      op.UnaryOperator operator,
+      Element element,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitSuperSend(node);
+  }
+
+  @override
+  R visitAs(
+      Send node,
+      Node expression,
+      DartType type,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitAssert(
+      Send node,
+      Node expression,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitAssertSend(node);
+  }
+
+  @override
+  R visitBinary(
+      Send node,
+      Node left,
+      op.BinaryOperator operator,
+      Node right,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitEquals(
+      Send node,
+      Node left,
+      Node right,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitIs(
+      Send node,
+      Node expression,
+      DartType type,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitIsNot(
+      Send node,
+      Node expression,
+      DartType type,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitLogicalAnd(
+      Send node,
+      Node left,
+      Node right,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitLogicalOr(
+      Send node,
+      Node left,
+      Node right,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitNot(
+      Send node,
+      Node expression,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitNotEquals(
+      Send node,
+      Node left,
+      Node right,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitUnary(
+      Send node,
+      op.UnaryOperator operator,
+      Node expression,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitDynamicPropertyInvoke(
+      Send node,
+      Node receiver,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitDynamicSend(node);
+  }
+
+  @override
+  R visitThisPropertyInvoke(
+      Send node,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitDynamicSend(node);
+  }
+
+  @override
+  R visitExpressionInvoke(
+      Send node,
+      Node receiver,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitClosureSend(node);
+  }
+
+  @override
+  R visitParameterInvoke(
+      Send node,
+      ParameterElement parameter,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitClosureSend(node);
+  }
+
+  @override
+  R visitLocalVariableInvoke(
+      Send node,
+      LocalVariableElement variable,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitClosureSend(node);
+  }
+
+  @override
+  R visitLocalFunctionInvoke(
+      Send node,
+      LocalFunctionElement function,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitClosureSend(node);
+  }
+
+  @override
+  R visitThisInvoke(
+      Send node,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitClosureSend(node);
+  }
+
+  @override
+  R visitClassTypeLiteralGet(
+      Send node,
+      ConstantExpression constant,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitTypeLiteralSend(node);
+  }
+
+  @override
+  R visitTypedefTypeLiteralGet(
+      Send node,
+      ConstantExpression constant,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitTypeLiteralSend(node);
+  }
+
+  @override
+  R visitDynamicTypeLiteralGet(
+      Send node,
+      ConstantExpression constant,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitTypeLiteralSend(node);
+  }
+
+  @override
+  R visitTypeVariableTypeLiteralGet(
+      Send node,
+      TypeVariableElement element,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitTypeLiteralSend(node);
+  }
+
+  @override
+  R visitClassTypeLiteralInvoke(
+      Send node,
+      ConstantExpression constant,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitTypeLiteralSend(node);
+  }
+
+  @override
+  R visitTypedefTypeLiteralInvoke(
+      Send node,
+      ConstantExpression constant,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitTypeLiteralSend(node);
+  }
+
+  @override
+  R visitDynamicTypeLiteralInvoke(
+      Send node,
+      ConstantExpression constant,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitTypeLiteralSend(node);
+  }
+
+  @override
+  R visitTypeVariableTypeLiteralInvoke(
+      Send node,
+      TypeVariableElement element,
+      NodeList arguments,
+      Selector selector,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitTypeLiteralSend(node);
+  }
+
+  @override
+  R visitIndex(
+      Send node,
+      Node receiver,
+      Node index,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitOperatorSend(node);
+  }
+
+  @override
+  R visitSuperIndex(
+      Send node,
+      FunctionElement function,
+      Node index,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitSuperSend(node);
+  }
+
+  @override
+  R errorUnresolvedSuperIndex(
+      Send node,
+      Element function,
+      Node index,
+      ResolvedKindVisitor<R> visitor) {
+    return visitor.visitSuperSend(node);
+  }
+}
diff --git a/pkg/compiler/lib/src/scanner/parser.dart b/pkg/compiler/lib/src/scanner/parser.dart
index 00e599f..7957b5e 100644
--- a/pkg/compiler/lib/src/scanner/parser.dart
+++ b/pkg/compiler/lib/src/scanner/parser.dart
@@ -1073,6 +1073,8 @@
         parseModifier(token);
       } else {
         listener.unexpected(token);
+        // Skip the remaining modifiers.
+        break;
       }
       count++;
     }
diff --git a/pkg/compiler/lib/src/scanner/token.dart b/pkg/compiler/lib/src/scanner/token.dart
index 483eda9..76229cd 100644
--- a/pkg/compiler/lib/src/scanner/token.dart
+++ b/pkg/compiler/lib/src/scanner/token.dart
@@ -385,12 +385,9 @@
   static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) {
     var s;
     if (asciiOnly) {
-      // getRange returns an iterator, it does not copy the data.
-      s = new String.fromCharCodes(data.getRange(start, end));
+      s = new String.fromCharCodes(data, start, end);
     } else {
-      // TODO(lry): this is measurably slow. Also sublist is copied eagerly.
-      var bytes = data.sublist(start, end);
-      s = UTF8.decode(bytes);
+      s = UTF8.decoder.convert(data, start, end);
     }
     return canonicalizedString(s, true);
   }
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 590dd80..195b188 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -89,6 +89,8 @@
   final ExecutableElement executableContext;
 
   SyntheticLocal(this.name, this.executableContext);
+
+  toString() => 'SyntheticLocal($name)';
 }
 
 class SsaBuilderTask extends CompilerTask {
@@ -389,8 +391,11 @@
       HParameterValue value =
           new HParameterValue(parameter, builder.getTypeOfThis());
       builder.graph.explicitReceiverParameter = value;
-      builder.graph.entry.addAfter(
-          directLocals[closureData.thisLocal], value);
+      builder.graph.entry.addAfter(directLocals[closureData.thisLocal], value);
+      if (builder.lastAddedParameter == null) {
+        // If this is the first parameter inserted, make sure it stays first.
+        builder.lastAddedParameter = value;
+      }
       if (isInterceptorClass) {
         // Only use the extra parameter in intercepted classes.
         directLocals[closureData.thisLocal] = value;
@@ -980,7 +985,7 @@
 /**
  * This class builds SSA nodes for functions represented in AST.
  */
-class SsaBuilder extends ResolvedVisitor {
+class SsaBuilder extends NewResolvedVisitor {
   final Compiler compiler;
   final JavaScriptBackend backend;
   final ConstantSystem constantSystem;
@@ -1244,7 +1249,8 @@
        * For each parameter name in the signature, if the argument name matches
        * we use the next provided argument, otherwise we get the default.
        */
-      List<String> selectorArgumentNames = selector.getOrderedNamedArguments();
+      List<String> selectorArgumentNames =
+          selector.callStructure.getOrderedNamedArguments();
       int namedArgumentIndex = 0;
       int firstProvidedNamedArgument = index;
       signature.orderedOptionalParameters.forEach((element) {
@@ -1893,13 +1899,12 @@
       }
 
       Element target = constructor.definingConstructor.implementation;
-      bool match = Selector.addForwardingElementArgumentsToList(
+      bool match = CallStructure.addForwardingElementArgumentsToList(
           constructor,
           arguments,
           target,
           compileArgument,
-          handleConstantForOptionalParameter,
-          compiler.world);
+          handleConstantForOptionalParameter);
       if (!match) {
         if (compiler.elementHasCompileTimeError(constructor)) {
           return;
@@ -1933,12 +1938,13 @@
           assert(ast.Initializers.isSuperConstructorCall(call) ||
                  ast.Initializers.isConstructorRedirect(call));
           FunctionElement target = elements[call].implementation;
-          Selector selector = elements.getSelector(call);
+          CallStructure callStructure =
+              elements.getSelector(call).callStructure;
           Link<ast.Node> arguments = call.arguments;
           List<HInstruction> compiledArguments;
           inlinedFrom(constructor, () {
             compiledArguments =
-                makeStaticArgumentList(selector, arguments, target);
+                makeStaticArgumentList(callStructure, arguments, target);
           });
           inlineSuperOrRedirect(target,
                                 compiledArguments,
@@ -1972,12 +1978,12 @@
           compiler.internalError(superClass,
               "No default constructor available.");
         }
-        Selector selector = new Selector.callDefaultConstructor();
         List<HInstruction> arguments =
-            selector.makeArgumentsList(const Link<ast.Node>(),
-                                       target.implementation,
-                                       null,
-                                       handleConstantForOptionalParameter);
+            CallStructure.NO_ARGS.makeArgumentsList(
+                const Link<ast.Node>(),
+                target.implementation,
+                null,
+                handleConstantForOptionalParameter);
         inlineSuperOrRedirect(target,
                               arguments,
                               constructors,
@@ -3133,7 +3139,7 @@
     pushWithPosition(not, node);
   }
 
-  void visitUnary(ast.Send node, ast.Operator op) {
+  void visitUnarySend(ast.Send node, ast.Operator op) {
     assert(node.argumentsNode is ast.Prefix);
     visit(node.receiver);
     assert(!identical(op.token.kind, PLUS_TOKEN));
@@ -3153,11 +3159,11 @@
     pushInvokeDynamic(node, elements.getSelector(node), [operand]);
   }
 
-  void visitBinary(HInstruction left,
-                   ast.Operator op,
-                   HInstruction right,
-                   Selector selector,
-                   ast.Send send) {
+  void visitBinarySend(HInstruction left,
+                       ast.Operator op,
+                       HInstruction right,
+                       Selector selector,
+                       ast.Send send) {
     switch (op.source) {
       case "===":
         pushWithPosition(
@@ -3425,7 +3431,7 @@
     } else if ("!" == op.source) {
       visitLogicalNot(node);
     } else if (node.argumentsNode is ast.Prefix) {
-      visitUnary(node, op);
+      visitUnarySend(node, op);
     } else if ("is" == op.source) {
       visitIsSend(node);
     } else if ("as" == op.source) {
@@ -3448,7 +3454,7 @@
       visit(node.argumentsNode);
       var right = pop();
       var left = pop();
-      visitBinary(left, op, right, elements.getSelector(node), node);
+      visitBinarySend(left, op, right, elements.getSelector(node), node);
     }
   }
 
@@ -3522,13 +3528,13 @@
   }
 
   void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) {
-    Selector selector = elements.getSelector(node);
-    if (selector.namedArgumentCount == 0) {
+    CallStructure callStructure = elements.getSelector(node).callStructure;
+    if (callStructure.namedArgumentCount == 0) {
       addGenericSendArgumentsToList(node.arguments, list);
     } else {
       // Visit positional arguments and add them to the list.
       Link<ast.Node> arguments = node.arguments;
-      int positionalArgumentCount = selector.positionalArgumentCount;
+      int positionalArgumentCount = callStructure.positionalArgumentCount;
       for (int i = 0;
            i < positionalArgumentCount;
            arguments = arguments.tail, i++) {
@@ -3539,7 +3545,7 @@
       // Visit named arguments and add them into a temporary map.
       Map<String, HInstruction> instructions =
           new Map<String, HInstruction>();
-      List<String> namedArguments = selector.namedArguments;
+      List<String> namedArguments = callStructure.namedArguments;
       int nameIndex = 0;
       for (; !arguments.isEmpty; arguments = arguments.tail) {
         visit(arguments.head);
@@ -3549,7 +3555,7 @@
       // Iterate through the named arguments to add them to the list
       // of instructions, in an order that can be shared with
       // selectors with the same named arguments.
-      List<String> orderedNames = selector.getOrderedNamedArguments();
+      List<String> orderedNames = callStructure.getOrderedNamedArguments();
       for (String name in orderedNames) {
         list.add(instructions[name]);
       }
@@ -3562,7 +3568,7 @@
    * Precondition: `this.applies(element, world)`.
    * Invariant: [element] must be an implementation element.
    */
-  List<HInstruction> makeStaticArgumentList(Selector selector,
+  List<HInstruction> makeStaticArgumentList(CallStructure callStructure,
                                             Link<ast.Node> arguments,
                                             FunctionElement element) {
     assert(invariant(element, element.isImplementation));
@@ -3572,10 +3578,11 @@
       return pop();
     }
 
-    return selector.makeArgumentsList(arguments,
-                                      element,
-                                      compileArgument,
-                                      handleConstantForOptionalParameter);
+    return callStructure.makeArgumentsList(
+        arguments,
+        element,
+        compileArgument,
+        handleConstantForOptionalParameter);
   }
 
   void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> list) {
@@ -4103,7 +4110,7 @@
         // calling [makeStaticArgumentList].
         FunctionElement function = element.implementation;
         assert(selector.applies(function, compiler.world));
-        inputs = makeStaticArgumentList(selector,
+        inputs = makeStaticArgumentList(selector.callStructure,
                                         node.arguments,
                                         function);
         push(buildInvokeSuper(selector, element, inputs));
@@ -4347,7 +4354,7 @@
     }
 
     Element constructor = elements[send];
-    Selector selector = elements.getSelector(send);
+    CallStructure callStructure = elements.getSelector(send).callStructure;
     ConstructorElement constructorDeclaration = constructor;
     ConstructorElement constructorImplementation = constructor.implementation;
     constructor = constructorImplementation.effectiveTarget;
@@ -4361,8 +4368,8 @@
       constructor = compiler.symbolValidatedConstructor;
       assert(invariant(send, constructor != null,
                        message: 'Constructor Symbol.validated is missing'));
-      selector = compiler.symbolValidatedConstructorSelector;
-      assert(invariant(send, selector != null,
+      callStructure = compiler.symbolValidatedConstructorSelector.callStructure;
+      assert(invariant(send, callStructure != null,
                        message: 'Constructor Symbol.validated is missing'));
     }
 
@@ -4387,11 +4394,11 @@
     }
     // TODO(5347): Try to avoid the need for calling [implementation] before
     // calling [makeStaticArgumentList].
-    if (!selector.applies(constructor.implementation, compiler.world)) {
+    if (!callStructure.signatureApplies(constructor.implementation)) {
       generateWrongArgumentCountError(send, constructor, send.arguments);
       return;
     }
-    inputs.addAll(makeStaticArgumentList(selector,
+    inputs.addAll(makeStaticArgumentList(callStructure,
                                          send.arguments,
                                          constructor.implementation));
 
@@ -4537,7 +4544,7 @@
     return false;
   }
 
-  visitAssert(node) {
+  visitAssertSend(node) {
     if (!compiler.enableUserAssertions) {
       stack.add(graph.addConstantNull(compiler));
       return;
@@ -4550,7 +4557,7 @@
   }
 
   visitStaticSend(ast.Send node) {
-    Selector selector = elements.getSelector(node);
+    CallStructure callStructure = elements.getSelector(node).callStructure;
     Element element = elements[node];
     if (elements.isAssert(node)) {
       element = backend.assertMethod;
@@ -4577,13 +4584,13 @@
     if (element.isFunction) {
       // TODO(5347): Try to avoid the need for calling [implementation] before
       // calling [makeStaticArgumentList].
-      if (!selector.applies(element.implementation, compiler.world)) {
+      if (!callStructure.signatureApplies(element.implementation)) {
         generateWrongArgumentCountError(node, element, node.arguments);
         return;
       }
 
       List<HInstruction> inputs =
-          makeStaticArgumentList(selector,
+          makeStaticArgumentList(callStructure,
                                  node.arguments,
                                  element.implementation);
 
@@ -4598,7 +4605,7 @@
       generateGetter(node, element);
       List<HInstruction> inputs = <HInstruction>[pop()];
       addDynamicSendArgumentsToList(node, inputs);
-      Selector closureSelector = new Selector.callClosureFrom(selector);
+      Selector closureSelector = callStructure.callSelector;
       pushWithPosition(
           new HInvokeClosure(closureSelector, inputs, backend.dynamicType),
           node);
@@ -4637,7 +4644,7 @@
                        backend.getCreateRuntimeType(),
                        [pop()]);
     } else {
-      internalError('unexpected type kind ${type.kind}', node: node);
+      internalError(node, 'unexpected type kind ${type.kind}');
     }
     if (node.isCall) {
       // This send is of the form 'e(...)', where e is resolved to a type
@@ -4659,7 +4666,7 @@
   }
 
   // TODO(antonm): migrate rest of SsaFromAstMixin to internalError.
-  internalError(String reason, {ast.Node node}) {
+  internalError(Spannable node, String reason) {
     compiler.internalError(node, reason);
   }
 
@@ -4924,8 +4931,8 @@
       assert(arguments.tail.isEmpty);
       rhs = pop();
     }
-    visitBinary(receiver, node.assignmentOperator, rhs,
-                elements.getOperatorSelectorInComplexSendSet(node), node);
+    visitBinarySend(receiver, node.assignmentOperator, rhs,
+                    elements.getOperatorSelectorInComplexSendSet(node), node);
   }
 
   visitSendSet(ast.SendSet node) {
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 60403c3..ea200c3 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1472,14 +1472,25 @@
   }
 
   void visitInterceptor(HInterceptor node) {
-    registry.registerSpecializedGetInterceptor(node.interceptedClasses);
-    String name = backend.namer.nameForGetInterceptor(node.interceptedClasses);
-    var isolate = new js.VariableUse(
-        backend.namer.globalObjectFor(backend.interceptorsLibrary));
-    use(node.receiver);
-    List<js.Expression> arguments = <js.Expression>[pop()];
-    push(js.propertyCall(isolate, name, arguments), node);
-    registry.registerUseInterceptor();
+    if (node.isConditionalConstantInterceptor) {
+      assert(node.inputs.length == 2);
+      use(node.receiver);
+      js.Expression receiverExpression = pop();
+      use(node.conditionalConstantInterceptor);
+      js.Expression constant = pop();
+      push(js.js('# && #', [receiverExpression, constant]));
+    } else {
+      assert(node.inputs.length == 1);
+      registry.registerSpecializedGetInterceptor(node.interceptedClasses);
+      String name =
+          backend.namer.nameForGetInterceptor(node.interceptedClasses);
+      var isolate = new js.VariableUse(
+          backend.namer.globalObjectFor(backend.interceptorsLibrary));
+      use(node.receiver);
+      List<js.Expression> arguments = <js.Expression>[pop()];
+      push(js.propertyCall(isolate, name, arguments), node);
+      registry.registerUseInterceptor();
+    }
   }
 
   visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index d8213e2..a22b94d 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -110,47 +110,8 @@
       return graph.thisInstruction;
     }
 
-    ClassElement constantInterceptor;
-    ClassWorld classWorld = compiler.world;
-    JavaScriptBackend backend = compiler.backend;
-    if (input.canBeNull()) {
-      if (input.isNull()) {
-        constantInterceptor = backend.jsNullClass;
-      }
-    } else if (input.isInteger(compiler)) {
-      constantInterceptor = backend.jsIntClass;
-    } else if (input.isDouble(compiler)) {
-      constantInterceptor = backend.jsDoubleClass;
-    } else if (input.isBoolean(compiler)) {
-      constantInterceptor = backend.jsBoolClass;
-    } else if (input.isString(compiler)) {
-      constantInterceptor = backend.jsStringClass;
-    } else if (input.isArray(compiler)) {
-      constantInterceptor = backend.jsArrayClass;
-    } else if (input.isNumber(compiler) &&
-        !interceptedClasses.contains(backend.jsIntClass) &&
-        !interceptedClasses.contains(backend.jsDoubleClass)) {
-      // If the method being intercepted is not defined in [int] or [double] we
-      // can safely use the number interceptor.  This is because none of the
-      // [int] or [double] methods are called from a method defined on [num].
-      constantInterceptor = backend.jsNumberClass;
-    } else {
-      // Try to find constant interceptor for a native class.  If the receiver
-      // is constrained to a leaf native class, we can use the class's
-      // interceptor directly.
-
-      // TODO(sra): Key DOM classes like Node, Element and Event are not leaf
-      // classes.  When the receiver type is not a leaf class, we might still be
-      // able to use the receiver class as a constant interceptor.  It is
-      // usually the case that methods defined on a non-leaf class don't test
-      // for a subclass or call methods defined on a subclass.  Provided the
-      // code is completely insensitive to the specific instance subclasses, we
-      // can use the non-leaf class directly.
-      ClassElement element = input.instructionType.singleClass(classWorld);
-      if (element != null && element.isNative) {
-        constantInterceptor = element;
-      }
-    }
+    ClassElement constantInterceptor = tryComputeConstantInterceptorFromType(
+        input.instructionType, interceptedClasses);
 
     if (constantInterceptor == null) return null;
 
@@ -166,6 +127,54 @@
     return graph.addConstant(constant, compiler);
   }
 
+  ClassElement tryComputeConstantInterceptorFromType(
+      TypeMask type,
+      Set<ClassElement> interceptedClasses) {
+
+    ClassWorld classWorld = compiler.world;
+    JavaScriptBackend backend = compiler.backend;
+    if (type.isNullable) {
+      if (type.isEmpty) {
+        return backend.jsNullClass;
+      }
+    } else if (type.containsOnlyInt(classWorld)) {
+      return backend.jsIntClass;
+    } else if (type.containsOnlyDouble(classWorld)) {
+      return backend.jsDoubleClass;
+    } else if (type.containsOnlyBool(classWorld)) {
+      return backend.jsBoolClass;
+    } else if (type.containsOnlyString(classWorld)) {
+      return backend.jsStringClass;
+    } else if (type.satisfies(backend.jsArrayClass, classWorld)) {
+      return backend.jsArrayClass;
+    } else if (type.containsOnlyNum(classWorld) &&
+        !interceptedClasses.contains(backend.jsIntClass) &&
+        !interceptedClasses.contains(backend.jsDoubleClass)) {
+      // If the method being intercepted is not defined in [int] or [double] we
+      // can safely use the number interceptor.  This is because none of the
+      // [int] or [double] methods are called from a method defined on [num].
+      return backend.jsNumberClass;
+    } else {
+      // Try to find constant interceptor for a native class.  If the receiver
+      // is constrained to a leaf native class, we can use the class's
+      // interceptor directly.
+
+      // TODO(sra): Key DOM classes like Node, Element and Event are not leaf
+      // classes.  When the receiver type is not a leaf class, we might still be
+      // able to use the receiver class as a constant interceptor.  It is
+      // usually the case that methods defined on a non-leaf class don't test
+      // for a subclass or call methods defined on a subclass.  Provided the
+      // code is completely insensitive to the specific instance subclasses, we
+      // can use the non-leaf class directly.
+      ClassElement element = type.singleClass(classWorld);
+      if (element != null && element.isNative) {
+        return element;
+      }
+    }
+
+    return null;
+  }
+
   HInstruction findDominator(Iterable<HInstruction> instructions) {
     HInstruction result;
     L1: for (HInstruction candidate in instructions) {
@@ -276,6 +285,32 @@
       return false;
     }
 
+    // Do we have an 'almost constant' interceptor?  The receiver could be
+    // `null` but not any other JavaScript falsy value, `null` values cause
+    // `NoSuchMethodError`s, and if the receiver was not null we would have a
+    // constant interceptor `C`.  Then we can use `(receiver && C)` for the
+    // interceptor.
+    if (receiver.canBeNull() && !node.isConditionalConstantInterceptor) {
+      if (!interceptedClasses.contains(backend.jsNullClass)) {
+        // Can use `(receiver && C)` only if receiver is either null or truthy.
+        if (!(receiver.canBePrimitiveNumber(compiler) ||
+            receiver.canBePrimitiveBoolean(compiler) ||
+            receiver.canBePrimitiveString(compiler))) {
+          ClassElement interceptorClass = tryComputeConstantInterceptorFromType(
+              receiver.instructionType.nonNullable(), interceptedClasses);
+          if (interceptorClass != null) {
+            HInstruction constantInstruction =
+                graph.addConstant(
+                    new InterceptorConstantValue(interceptorClass.thisType),
+                    compiler);
+            node.conditionalConstantInterceptor = constantInstruction;
+            constantInstruction.usedBy.add(node);
+            return false;
+          }
+        }
+      }
+    }
+
     // Try creating a one-shot interceptor or optimized is-check
     if (compiler.hasIncrementalSupport) return false;
     if (node.usedBy.length != 1) return false;
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index c5cdc94..7f5ff1d 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -236,8 +236,8 @@
     if (selector.name == name) return selector;
     JavaScriptBackend backend = compiler.backend;
     Selector newSelector = new Selector(
-        SelectorKind.CALL, name, backend.interceptorsLibrary,
-        selector.argumentCount);
+        SelectorKind.CALL, new Name(name, backend.interceptorsLibrary),
+        new CallStructure(selector.argumentCount));
     return selector.mask == null
         ? newSelector
         : new TypedSelector(selector.mask, newSelector, compiler.world);
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index f4e813b..fd28580 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -2057,7 +2057,7 @@
   HConstant.internal(this.constant, TypeMask constantType)
       : super(<HInstruction>[], constantType);
 
-  toString() => 'literal: $constant';
+  toString() => 'literal: ${constant.toStructuredString()}';
   accept(HVisitor visitor) => visitor.visitConstant(this);
 
   bool isConstant() => true;
@@ -2300,15 +2300,34 @@
   // This field should originally be null to allow GVN'ing all
   // [HInterceptor] on the same input.
   Set<ClassElement> interceptedClasses;
+
+  // inputs[0] is initially the only input, the receiver.
+
+  // inputs[1] is a constant interceptor when the interceptor is a constant
+  // except for a `null` receiver.  This is used when the receiver can't be
+  // falsy, except for `null`, allowing the generation of code like
+  //
+  //     (a && C.JSArray_methods).get$first(a)
+  //
+
   HInterceptor(HInstruction receiver, TypeMask type)
       : super(<HInstruction>[receiver], type) {
     sideEffects.clearAllSideEffects();
     sideEffects.clearAllDependencies();
     setUseGvn();
   }
+
   String toString() => 'interceptor on $interceptedClasses';
   accept(HVisitor visitor) => visitor.visitInterceptor(this);
   HInstruction get receiver => inputs[0];
+
+  bool get isConditionalConstantInterceptor => inputs.length == 2;
+  HInstruction get conditionalConstantInterceptor => inputs[1];
+  void set conditionalConstantInterceptor(HConstant constant) {
+    assert(!isConditionalConstantInterceptor);
+    inputs.add(constant);
+  }
+
   bool isInterceptor(Compiler compiler) => true;
 
   int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index ac930ce..8491860 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -57,10 +57,10 @@
     if (irObject is ssa.HGraph) {
       new HTracer(output, compiler, context).traceGraph(name, irObject);
     }
-    else if (irObject is cps_ir.ExecutableDefinition) {
+    else if (irObject is cps_ir.RootNode) {
       new IRTracer(output).traceGraph(name, irObject);
     }
-    else if (irObject is tree_ir.ExecutableDefinition) {
+    else if (irObject is tree_ir.RootNode) {
       new TreeTracer(output).traceGraph(name, irObject);
     }
   }
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/copy_propagator.dart b/pkg/compiler/lib/src/tree_ir/optimization/copy_propagator.dart
deleted file mode 100644
index f7e5369..0000000
--- a/pkg/compiler/lib/src/tree_ir/optimization/copy_propagator.dart
+++ /dev/null
@@ -1,266 +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.
-
-part of tree_ir.optimization;
-
-/// Eliminates moving assignments, such as w := v, by assigning directly to w
-/// at the definition of v.
-///
-/// This compensates for suboptimal register allocation, and merges closure
-/// variables with local temporaries that were left behind when translating
-/// out of CPS (where closure variables live in a separate space).
-class CopyPropagator extends RecursiveVisitor with PassMixin {
-  String get passName => 'Copy propagation';
-
-  /// After visitStatement returns, [move] maps a variable v to an
-  /// assignment A of form w := v, under the following conditions:
-  /// - there are no reads or writes of w before A
-  /// - A is the only use of v
-  Map<Variable, Assign> move = <Variable, Assign>{};
-
-  /// Like [move], except w is the key instead of v.
-  Map<Variable, Assign> inverseMove = <Variable, Assign>{};
-
-  ExecutableElement currentElement;
-
-  /// Number of try blocks enclosing the currently visited node.
-  int enclosingTrys = 0;
-
-  void rewriteExecutableDefinition(ExecutableDefinition root) {
-    currentElement = root.element;
-    root.body = visitStatement(root.body);
-  }
-
-  rewriteFunctionDefinition(FunctionDefinition node) {
-    if (node.isAbstract) return;
-    rewriteExecutableDefinition(node);
-
-    // Try to propagate moving assignments into function parameters.
-    // For example:
-    // foo(x) {
-    //   var v1 = x;
-    //   BODY
-    // }
-    //   ==>
-    // foo(v1) {
-    //   BODY
-    // }
-
-    // Variables must not occur more than once in the parameter list, so
-    // invalidate all moving assignments that would propagate a parameter
-    // into another parameter. For example:
-    // foo(x,y) {
-    //   y = x;
-    //   BODY
-    // }
-    // Cannot declare function as foo(x,x)!
-    node.parameters.forEach(invalidateMovingAssignment);
-
-    // Now do the propagation.
-    for (int i = 0; i < node.parameters.length; i++) {
-      Variable param = node.parameters[i];
-      Variable replacement = copyPropagateVariable(param);
-      replacement.element = param.element; // Preserve parameter name.
-      node.parameters[i] = replacement;
-    }
-  }
-
-  rewriteConstructorDefinition(ConstructorDefinition node) {
-    if (node.isAbstract) return;
-    node.initializers.forEach(visitExpression);
-    rewriteExecutableDefinition(node);
-
-
-    // Try to propagate moving assignments into function parameters.
-    // For example:
-    // foo(x) {
-    //   var v1 = x;
-    //   BODY
-    // }
-    //   ==>
-    // foo(v1) {
-    //   BODY
-    // }
-
-    // Variables must not occur more than once in the parameter list, so
-    // invalidate all moving assignments that would propagate a parameter
-    // into another parameter. For example:
-    // foo(x,y) {
-    //   y = x;
-    //   BODY
-    // }
-    // Cannot declare function as foo(x,x)!
-    node.parameters.forEach(invalidateMovingAssignment);
-
-    // Now do the propagation.
-    for (int i = 0; i < node.parameters.length; i++) {
-      Variable param = node.parameters[i];
-      Variable replacement = copyPropagateVariable(param);
-      replacement.element = param.element; // Preserve parameter name.
-      node.parameters[i] = replacement;
-    }
-
-  }
-
-
-  Statement visitBasicBlock(Statement node) {
-    node = visitStatement(node);
-    move.clear();
-    inverseMove.clear();
-    return node;
-  }
-
-  /// Remove an assignment of form [w] := v from the move maps.
-  void invalidateMovingAssignment(Variable w) {
-    Assign movingAssignment = inverseMove.remove(w);
-    if (movingAssignment != null) {
-      VariableUse value = movingAssignment.value;
-      move.remove(value.variable);
-    }
-  }
-
-  visitVariableUse(VariableUse node) {
-    // We found a use of w; we can't propagate assignments across this use.
-    invalidateMovingAssignment(node.variable);
-  }
-
-  /**
-   * Called when a definition of [v] is encountered.
-   * Attempts to propagate the assignment through a moving assignment.
-   * Returns the variable to be assigned into, defaulting to [v] itself if
-   * no optimization could be performed.
-   */
-  Variable copyPropagateVariable(Variable v) {
-    Assign movingAssign = move[v];
-    if (movingAssign != null) {
-      // We found the pattern:
-      //   v := EXPR
-      //   BLOCK   (does not use w)
-      //   w := v  (only use of v)
-      //
-      // Rewrite to:
-      //   w := EXPR
-      //   BLOCK
-      //   w := w  (to be removed later)
-      Variable w = movingAssign.variable;
-
-      // Make w := w.
-      // We can't remove the statement from here because we don't have
-      // parent pointers. So just make it a no-op so it can be removed later.
-      movingAssign.value = new VariableUse(w);
-
-      // The intermediate variable 'v' should now be orphaned, so don't bother
-      // updating its read/write counters.
-
-      // Make w := EXPR
-      ++w.writeCount;
-      return w;
-    }
-    return v;
-  }
-
-  Statement visitAssign(Assign node) {
-    node.next = visitStatement(node.next);
-    node.variable = copyPropagateVariable(node.variable);
-
-    // If a moving assignment w := v exists later, and we assign to w here,
-    // the moving assignment is no longer a candidate for copy propagation.
-    invalidateMovingAssignment(node.variable);
-
-    visitExpression(node.value);
-
-    // If this is a moving assignment w := v, with this being the only use of v,
-    // try to propagate it backwards.
-    // Do not propagate assignments where w is captured or if where are inside a
-    // try block, because then we can't isolate the uses of w to a single block.
-    // We currently do not support propagation if the assignment is a
-    // declaration. To support this we would need to ensure that the target
-    // assignment is turned into a declaration as well.
-    if (node.value is VariableUse &&
-        !node.variable.isCaptured &&
-        enclosingTrys == 0 &&
-        !node.isDeclaration) {
-      VariableUse value = node.value;
-      if (value.variable.readCount == 1) {
-        move[value.variable] = node;
-        inverseMove[node.variable] = node;
-      }
-    }
-
-    return node;
-  }
-
-  Statement visitLabeledStatement(LabeledStatement node) {
-    node.next = visitBasicBlock(node.next);
-    node.body = visitStatement(node.body);
-    return node;
-  }
-
-  Statement visitReturn(Return node) {
-    visitExpression(node.value);
-    return node;
-  }
-
-  Statement visitBreak(Break node) {
-    return node;
-  }
-
-  Statement visitContinue(Continue node) {
-    return node;
-  }
-
-  Statement visitIf(If node) {
-    visitExpression(node.condition);
-    node.thenStatement = visitBasicBlock(node.thenStatement);
-    node.elseStatement = visitBasicBlock(node.elseStatement);
-    return node;
-  }
-
-  Statement visitWhileTrue(WhileTrue node) {
-    node.body = visitBasicBlock(node.body);
-    return node;
-  }
-
-  Statement visitWhileCondition(WhileCondition node) {
-    throw "WhileCondition before LoopRewriter";
-  }
-
-  Statement visitTry(Try node) {
-    enclosingTrys++;
-    node.tryBody = visitBasicBlock(node.tryBody);
-    enclosingTrys--;
-    node.catchBody = visitBasicBlock(node.catchBody);
-    return node;
-  }
-
-  Statement visitFunctionDeclaration(FunctionDeclaration node) {
-    // Unlike var declarations, function declarations are not hoisted, so we
-    // can't do copy propagation of the variable.
-    new CopyPropagator().rewrite(node.definition);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  Statement visitExpressionStatement(ExpressionStatement node) {
-    node.next = visitStatement(node.next);
-    visitExpression(node.expression);
-    return node;
-  }
-
-  Statement visitSetField(SetField node) {
-    node.next = visitStatement(node.next);
-    visitExpression(node.value);
-    visitExpression(node.object);
-    return node;
-  }
-
-  void visitFunctionExpression(FunctionExpression node) {
-    new CopyPropagator().rewrite(node.definition);
-  }
-
-  void visitFieldInitializer(FieldInitializer node) {
-    visitStatement(node.body);
-  }
-
-}
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 f68677b..9a856ba 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
@@ -54,38 +54,23 @@
 ///   x && !!y          (!!y validated by [isBooleanValued])
 ///   x && y            (double negation removed by [putInBooleanContext])
 ///
-class LogicalRewriter extends Visitor<Statement, Expression> with PassMixin {
+class LogicalRewriter extends RecursiveTransformer
+                      implements Pass {
   String get passName => 'Logical rewriter';
 
+  @override
+  void rewrite(RootNode node) {
+    node.replaceEachBody(visitStatement);
+  }
+
   /// Statement to be executed next by natural fallthrough. Although fallthrough
   /// is not introduced in this phase, we need to reason about fallthrough when
   /// evaluating the benefit of swapping the branches of an [If].
   Statement fallthrough;
 
-  void rewriteExecutableDefinition(ExecutableDefinition root) {
-    root.body = visitStatement(root.body);
-  }
-
-  void rewriteConstructorDefinition(ConstructorDefinition root) {
-    if (root.isAbstract) return;
-    List<Initializer> initializers = root.initializers;
-    for (int i = 0; i < initializers.length; ++i) {
-      initializers[i] = visitExpression(initializers[i]);
-    }
-    root.body = visitStatement(root.body);
-  }
-
-  Expression visitFieldInitializer(FieldInitializer node) {
-    node.body = visitStatement(node.body);
-    return node;
-  }
-
-  visitSuperInitializer(SuperInitializer node) {
-    List<Statement> arguments = node.arguments;
-    for (int i = 0; i < arguments.length; ++i) {
-      arguments[i] = visitStatement(arguments[i]);
-    }
-    return node;
+  @override
+  void visitInnerFunction(FunctionDefinition node) {
+    new LogicalRewriter().rewrite(node);
   }
 
   Statement visitLabeledStatement(LabeledStatement node) {
@@ -97,25 +82,6 @@
     return node;
   }
 
-  Statement visitAssign(Assign node) {
-    node.value = visitExpression(node.value);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  Statement visitReturn(Return node) {
-    node.value = visitExpression(node.value);
-    return node;
-  }
-
-  Statement visitBreak(Break node) {
-    return node;
-  }
-
-  Statement visitContinue(Continue node) {
-    return node;
-  }
-
   bool isFallthroughBreak(Statement node) {
     return node is Break && node.target.binding.next == fallthrough;
   }
@@ -160,11 +126,6 @@
     return node;
   }
 
-  Statement visitWhileTrue(WhileTrue node) {
-    node.body = visitStatement(node.body);
-    return node;
-  }
-
   Statement visitWhileCondition(WhileCondition node) {
     node.condition = makeCondition(node.condition, true, liftNots: false);
     node.body = visitStatement(node.body);
@@ -172,90 +133,6 @@
     return node;
   }
 
-  Statement visitTry(Try node) {
-    node.tryBody = visitStatement(node.tryBody);
-    node.catchBody = visitStatement(node.catchBody);
-    return node;
-  }
-
-  Statement visitExpressionStatement(ExpressionStatement node) {
-    node.expression = visitExpression(node.expression);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  Expression visitVariableUse(VariableUse node) {
-    return node;
-  }
-
-  Expression visitInvokeStatic(InvokeStatic node) {
-    _rewriteList(node.arguments);
-    return node;
-  }
-
-  Expression visitInvokeMethod(InvokeMethod node) {
-    node.receiver = visitExpression(node.receiver);
-    _rewriteList(node.arguments);
-    return node;
-  }
-
-  Expression visitInvokeMethodDirectly(InvokeMethodDirectly node) {
-    node.receiver = visitExpression(node.receiver);
-    _rewriteList(node.arguments);
-    return node;
-  }
-
-  Expression visitInvokeConstructor(InvokeConstructor node) {
-    _rewriteList(node.arguments);
-    return node;
-  }
-
-  Expression visitConcatenateStrings(ConcatenateStrings node) {
-    _rewriteList(node.arguments);
-    return node;
-  }
-
-  Expression visitLiteralList(LiteralList node) {
-    _rewriteList(node.values);
-    return node;
-  }
-
-  Expression visitLiteralMap(LiteralMap node) {
-    node.entries.forEach((LiteralMapEntry entry) {
-      entry.key = visitExpression(entry.key);
-      entry.value = visitExpression(entry.value);
-    });
-    return node;
-  }
-
-  Expression visitTypeOperator(TypeOperator node) {
-    node.receiver = visitExpression(node.receiver);
-    return node;
-  }
-
-  Expression visitConstant(Constant node) {
-    return node;
-  }
-
-  Expression visitThis(This node) {
-    return node;
-  }
-
-  Expression visitReifyTypeVar(ReifyTypeVar node) {
-    return node;
-  }
-
-  Expression visitFunctionExpression(FunctionExpression node) {
-    new LogicalRewriter().rewrite(node.definition);
-    return node;
-  }
-
-  Statement visitFunctionDeclaration(FunctionDeclaration node) {
-    new LogicalRewriter().rewrite(node.definition);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
   Expression visitNot(Not node) {
     return toBoolean(makeCondition(node.operand, false, liftNots: false));
   }
@@ -322,37 +199,6 @@
     return node;
   }
 
-  Statement visitSetField(SetField node) {
-    node.object = visitExpression(node.object);
-    node.value = visitExpression(node.value);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  Expression visitGetField(GetField node) {
-    node.object = visitExpression(node.object);
-    return node;
-  }
-
-  Expression visitCreateBox(CreateBox node) {
-    return node;
-  }
-
-  Expression visitCreateInstance(CreateInstance 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;
-  }
-
   /// True if the given expression is known to evaluate to a boolean.
   /// This will not recursively traverse [Conditional] expressions, but if
   /// applied to the result of [visitExpression] conditionals will have been
@@ -498,11 +344,5 @@
     }
   }
 
-  /// Destructively updates each entry of [l] with the result of visiting it.
-  void _rewriteList(List<Expression> l) {
-    for (int i = 0; i < l.length; i++) {
-      l[i] = visitExpression(l[i]);
-    }
-  }
 }
 
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
index d02e1ac..e2b7011 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
@@ -27,41 +27,19 @@
 ///
 /// Note that the above pattern needs no iteration since nested ifs
 /// have been collapsed previously in the [StatementRewriter] phase.
-class LoopRewriter extends RecursiveVisitor with PassMixin {
+class LoopRewriter extends RecursiveTransformer
+                   implements Pass {
   String get passName => 'Loop rewriter';
 
   Set<Label> usedContinueLabels = new Set<Label>();
 
-  void rewriteExecutableDefinition(ExecutableDefinition root) {
-    root.body = visitStatement(root.body);
+  void rewrite(RootNode root) {
+    root.replaceEachBody(visitStatement);
   }
 
-  Statement visitLabeledStatement(LabeledStatement node) {
-    node.body = visitStatement(node.body);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  Statement visitAssign(Assign node) {
-    // Clean up redundant assignments left behind in the previous phase.
-    Expression value = node.value;
-    if (value is VariableUse && node.variable == value.variable) {
-      --node.variable.readCount;
-      --node.variable.writeCount;
-      return visitStatement(node.next);
-    }
-    visitExpression(node.value);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  Statement visitReturn(Return node) {
-    visitExpression(node.value);
-    return node;
-  }
-
-  Statement visitBreak(Break node) {
-    return node;
+  @override
+  void visitInnerFunction(FunctionDefinition node) {
+    node.body = new LoopRewriter().visitStatement(node.body);
   }
 
   Statement visitContinue(Continue node) {
@@ -69,13 +47,6 @@
     return node;
   }
 
-  Statement visitIf(If node) {
-    visitExpression(node.condition);
-    node.thenStatement = visitStatement(node.thenStatement);
-    node.elseStatement = visitStatement(node.elseStatement);
-    return node;
-  }
-
   Statement visitWhileTrue(WhileTrue node) {
     assert(!usedContinueLabels.contains(node.label));
     if (node.body is If) {
@@ -105,42 +76,4 @@
     }
     return node;
   }
-
-  Statement visitWhileCondition(WhileCondition node) {
-    // Note: not reachable but the implementation is trivial
-    visitExpression(node.condition);
-    node.body = visitStatement(node.body);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  Statement visitExpressionStatement(ExpressionStatement node) {
-    visitExpression(node.expression);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  Statement visitTry(Try node) {
-    node.tryBody = visitStatement(node.tryBody);
-    node.catchBody = visitStatement(node.catchBody);
-    return node;
-  }
-
-  Statement visitFunctionDeclaration(FunctionDeclaration node) {
-    new LoopRewriter().rewrite(node.definition);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
-  void visitFunctionExpression(FunctionExpression node) {
-    new LoopRewriter().rewrite(node.definition);
-  }
-
-  Statement visitSetField(SetField node) {
-    visitExpression(node.object);
-    visitExpression(node.value);
-    node.next = visitStatement(node.next);
-    return node;
-  }
-
 }
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart b/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
index fc7aca1..7dae5cd 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
@@ -1,10 +1,11 @@
 library tree_ir.optimization;
 
 import '../tree_ir_nodes.dart';
-import '../../elements/elements.dart';
 import '../../constants/values.dart' as values;
+import 'variable_merger.dart';
 
-part 'copy_propagator.dart';
+export 'variable_merger.dart' show VariableMerger;
+
 part 'logical_rewriter.dart';
 part 'loop_rewriter.dart';
 part 'statement_rewriter.dart';
@@ -12,28 +13,7 @@
 /// An optimization pass over the Tree IR.
 abstract class Pass {
   /// Applies optimizations to root, rewriting it in the process.
-  void rewrite(ExecutableDefinition root) => root.applyPass(this);
-  void rewriteFieldDefinition(FieldDefinition root);
-  void rewriteFunctionDefinition(FunctionDefinition root);
-  void rewriteConstructorDefinition(ConstructorDefinition root);
+  void rewrite(RootNode root);
 
   String get passName;
 }
-
-
-abstract class PassMixin implements Pass {
-  void rewrite(ExecutableDefinition root) => root.applyPass(this);
-  void rewriteExecutableDefinition(ExecutableDefinition root);
-  void rewriteFieldDefinition(FieldDefinition root) {
-    if (!root.hasInitializer) return;
-    rewriteExecutableDefinition(root);
-  }
-  void rewriteFunctionDefinition(FunctionDefinition root) {
-    if (root.isAbstract) return;
-    rewriteExecutableDefinition(root);
-  }
-  void rewriteConstructorDefinition(ConstructorDefinition root) {
-    if (root.isAbstract) return;
-    rewriteExecutableDefinition(root);
-  }
-}
\ No newline at end of file
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 1902e8f..88ab5d8 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -91,12 +91,17 @@
  * This may trigger a flattening of nested ifs in case the eliminated label
  * separated two ifs.
  */
-class StatementRewriter extends Visitor<Statement, Expression> with PassMixin {
+class StatementRewriter extends Transformer implements Pass {
   String get passName => 'Statement rewriter';
 
+  @override
+  void rewrite(RootNode node) {
+    node.replaceEachBody(visitStatement);
+  }
+
   // The binding environment.  The rightmost element of the list is the nearest
   // available enclosing binding.
-  List<Assign> environment;
+  List<Assign> environment = <Assign>[];
 
   /// Binding environment for variables that are assigned to effectively
   /// constant expressions (see [isEffectivelyConstant]).
@@ -128,18 +133,6 @@
     return newJump != null ? newJump : jump;
   }
 
-  rewriteExecutableDefinition(ExecutableDefinition definition) {
-    inEmptyEnvironment(() {
-      definition.body = visitStatement(definition.body);
-    });
-  }
-
-  void rewriteConstructorDefinition(ConstructorDefinition definition) {
-    if (definition.isAbstract) return;
-    definition.initializers.forEach(visitExpression);
-    rewriteExecutableDefinition(definition);
-  }
-
   void inEmptyEnvironment(void action()) {
     List<Assign> oldEnvironment = environment;
     environment = <Assign>[];
@@ -148,23 +141,6 @@
     environment = oldEnvironment;
   }
 
-  Expression visitFieldInitializer(FieldInitializer node) {
-    inEmptyEnvironment(() {
-      node.body = visitStatement(node.body);
-    });
-    return node;
-  }
-
-  Expression visitSuperInitializer(SuperInitializer node) {
-    inEmptyEnvironment(() {
-      for (int i = node.arguments.length - 1; i >= 0; --i) {
-        node.arguments[i] = visitStatement(node.arguments[i]);
-        assert(environment.isEmpty);
-      }
-    });
-    return node;
-  }
-
   Expression visitExpression(Expression e) => e.processed ? e : e.accept(this);
 
   @override
@@ -395,11 +371,11 @@
         node.elseStatement,
         (t,f) => new Conditional(node.condition, t, f)..processed = true);
     if (reduced != null) {
-      if (reduced.next is Break) {
-        // In case the break can now be inlined.
-        reduced = visitStatement(reduced);
-      }
-      return reduced;
+      // TODO(asgerf): Avoid revisiting nodes or visiting nodes that we created.
+      //               This breaks the assumption that all subexpressions are
+      //               variable uses, and it can be expensive.
+      // Revisit in case the break can now be inlined.
+      return visitStatement(reduced);
     }
 
     return node;
@@ -511,6 +487,14 @@
     return node;
   }
 
+  @override
+  Expression visitTypeExpression(TypeExpression node) {
+    for (int i = node.arguments.length - 1; i >= 0; --i) {
+      node.arguments[i] = visitExpression(node.arguments[i]);
+    }
+    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:
@@ -576,6 +560,17 @@
         return new Return(e);
       }
     }
+    if (s is Assign && t is Assign &&
+        s.variable == t.variable &&
+        isSameVariable(s.value, t.value)) {
+      Statement next = combineStatements(s.next, t.next);
+      if (next != null) {
+        s.next = next;
+        --t.variable.writeCount;
+        --(t.value as VariableUse).variable.readCount;
+        return s;
+      }
+    }
     return null;
   }
 
@@ -646,30 +641,36 @@
     // NOTE: We name variables here as if S is in the then-then position.
     Statement outerThen = getBranch(outerIf, branch1);
     Statement outerElse = getBranch(outerIf, !branch1);
-    if (outerThen is If && outerElse is Break) {
+    if (outerThen is If) {
       If innerIf = outerThen;
       Statement innerThen = getBranch(innerIf, branch2);
       Statement innerElse = getBranch(innerIf, !branch2);
-      if (innerElse is Break && innerElse.target == outerElse.target) {
+      Statement combinedElse = combineStatements(innerElse, outerElse);
+      if (combinedElse != null) {
         // We always put S in the then branch of the result, and adjust the
         // condition expression if S was actually found in the else branch(es).
         outerIf.condition = new LogicalOperator.and(
             makeCondition(outerIf.condition, branch1),
             makeCondition(innerIf.condition, branch2));
         outerIf.thenStatement = innerThen;
-        --innerElse.target.useCount;
 
         // Try to inline the remaining break.  Do not propagate assignments.
         inEmptyEnvironment(() {
-          outerIf.elseStatement = visitStatement(outerElse);
+          // TODO(asgerf): Avoid quadratic cost from repeated processing. This
+          //               should be easier after we introduce basic blocks.
+          outerIf.elseStatement = visitStatement(combinedElse);
         });
 
-        return outerIf.elseStatement is If && innerThen is Break;
+        return outerIf.elseStatement is If;
       }
     }
     return false;
   }
 
+  static bool isSameVariable(Expression e1, Expression e2) {
+    return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable;
+  }
+
   Expression makeCondition(Expression e, bool polarity) {
     return polarity ? e : new Not(e);
   }
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
new file mode 100644
index 0000000..f1b64cf
--- /dev/null
+++ b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
@@ -0,0 +1,514 @@
+// 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 tree_ir.optimization.variable_merger;
+
+import 'optimization.dart' show Pass, PassMixin;
+import '../tree_ir_nodes.dart';
+import '../../elements/elements.dart' show Local, ParameterElement;
+
+/// Merges variables based on liveness and source variable information.
+///
+/// This phase cleans up artifacts introduced by the translation through CPS,
+/// where each source variable is translated into several copies. The copies
+/// are merged again when they are not live simultaneously.
+class VariableMerger extends RecursiveVisitor implements Pass {
+  String get passName => 'Variable merger';
+
+  void rewrite(RootNode node) {
+    rewriteFunction(node);
+    node.forEachBody(visitStatement);
+  }
+
+  @override
+  void visitInnerFunction(FunctionDefinition node) {
+    rewriteFunction(node);
+  }
+
+  /// Rewrites the given function.
+  /// This is called for the outermost function and inner functions.
+  void rewriteFunction(RootNode node) {
+    node.forEachBody((Statement body) {
+      BlockGraphBuilder builder = new BlockGraphBuilder();
+      builder.build(node.parameters, body);
+      _computeLiveness(builder.blocks);
+      Map<Variable, Variable> subst =
+          _computeRegisterAllocation(builder.blocks);
+      new SubstituteVariables(subst).apply(node);
+    });
+  }
+}
+
+/// A read or write access to a variable.
+class VariableAccess {
+  Variable variable;
+  bool isRead;
+  bool get isWrite => !isRead;
+
+  VariableAccess.read(this.variable) : isRead = true;
+  VariableAccess.write(this.variable) : isRead = false;
+}
+
+/// Basic block in a control-flow graph.
+class Block {
+  /// List of predecessors in the control-flow graph.
+  final List<Block> predecessors = <Block>[];
+
+  /// Entry to the catch block for the enclosing try, or `null`.
+  final Block catchBlock;
+
+  /// List of nodes with this block as [catchBlock].
+  final List<Block> catchPredecessors = <Block>[];
+
+  /// Sequence of read and write accesses in the block.
+  final List<VariableAccess> accesses = <VariableAccess>[];
+
+  /// Auxiliary fields used by the liveness analysis.
+  bool inWorklist = true;
+  Set<Variable> liveIn;
+  Set<Variable> liveOut = new Set<Variable>();
+  Set<Variable> gen = new Set<Variable>();
+  Set<Variable> kill = new Set<Variable>();
+
+  /// Adds a read operation to the block and updates gen/kill sets accordingly.
+  void addRead(Variable variable) {
+    // Operations are seen in forward order.
+    // If the read is not preceded by a write, then add it to the GEN set.
+    if (!kill.contains(variable)) {
+      gen.add(variable);
+    }
+    accesses.add(new VariableAccess.read(variable));
+  }
+
+  /// Adds a write operation to the block and updates gen/kill sets accordingly.
+  void addWrite(Variable variable) {
+    // If the write is not preceded by a read, then add it to the KILL set.
+    if (!gen.contains(variable)) {
+      kill.add(variable);
+    }
+    accesses.add(new VariableAccess.write(variable));
+  }
+
+  Block(this.catchBlock) {
+    if (catchBlock != null) {
+      catchBlock.catchPredecessors.add(this);
+    }
+  }
+}
+
+/// Builds a control-flow graph suitable for performing liveness analysis.
+class BlockGraphBuilder extends RecursiveVisitor {
+  Map<Label, Block> _jumpTarget = <Label, Block>{};
+  Block _currentBlock;
+  List<Block> blocks = <Block>[];
+
+  /// Variables with an assignment that should be treated as final.
+  ///
+  /// Such variables cannot be merged with any other variables, so we exclude
+  /// them from the control-flow graph entirely.
+  Set<Variable> _ignoredVariables = new Set<Variable>();
+
+  void build(List<Variable> parameters, Statement body) {
+    _currentBlock = newBlock();
+    parameters.forEach(write);
+    visitStatement(body);
+  }
+
+  @override
+  void visitInnerFunction(FunctionDefinition node) {
+    // Do nothing. Inner functions are traversed in VariableMerger.
+  }
+
+  /// Creates a new block with the current exception handler or [catchBlock]
+  /// if provided.
+  Block newBlock({Block catchBlock}) {
+    if (catchBlock == null && _currentBlock != null) {
+      catchBlock = _currentBlock.catchBlock;
+    }
+    Block block = new Block(catchBlock);
+    blocks.add(block);
+    return block;
+  }
+
+  /// Starts a new block after the end of [block].
+  void branchFrom(Block block, {Block catchBlock}) {
+    _currentBlock = newBlock(catchBlock: catchBlock)..predecessors.add(block);
+  }
+
+  /// Called when reading from [variable].
+  ///
+  /// Appends a read operation to the current basic block.
+  void read(Variable variable) {
+    if (variable.isCaptured) return;
+    if (_ignoredVariables.contains(variable)) return;
+    _currentBlock.addRead(variable);
+  }
+
+  /// Called when writing to [variable].
+  ///
+  /// Appends a write operation to the current basic block.
+  void write(Variable variable) {
+    if (variable.isCaptured) return;
+    if (_ignoredVariables.contains(variable)) return;
+    _currentBlock.addWrite(variable);
+  }
+
+  /// Called to indicate that [variable] should not be merged, and therefore
+  /// be excluded from the control-flow graph.
+  /// Subsequent calls to [read] and [write] will ignore it.
+  void ignoreVariable(Variable variable) {
+    _ignoredVariables.add(variable);
+  }
+
+  visitVariableUse(VariableUse node) {
+    read(node.variable);
+  }
+
+  visitAssign(Assign node) {
+    visitExpression(node.value);
+    write(node.variable);
+    visitStatement(node.next);
+  }
+
+  visitIf(If node) {
+    visitExpression(node.condition);
+    Block afterCondition = _currentBlock;
+    branchFrom(afterCondition);
+    visitStatement(node.thenStatement);
+    branchFrom(afterCondition);
+    visitStatement(node.elseStatement);
+  }
+
+  visitLabeledStatement(LabeledStatement node) {
+    Block join = _jumpTarget[node.label] = newBlock();
+    visitStatement(node.body); // visitBreak will add predecessors to join.
+    _currentBlock = join;
+    visitStatement(node.next);
+  }
+
+  visitBreak(Break node) {
+    _jumpTarget[node.target].predecessors.add(_currentBlock);
+  }
+
+  visitContinue(Continue node) {
+    _jumpTarget[node.target].predecessors.add(_currentBlock);
+  }
+
+  visitWhileTrue(WhileTrue node) {
+    Block join = _jumpTarget[node.label] = newBlock();
+    join.predecessors.add(_currentBlock);
+    _currentBlock = join;
+    visitStatement(node.body); // visitContinue will add predecessors to join.
+  }
+
+  visitWhileCondition(WhileCondition node) {
+    Block join = _jumpTarget[node.label] = newBlock();
+    join.predecessors.add(_currentBlock);
+    _currentBlock = join;
+    visitExpression(node.condition);
+    Block afterCondition = _currentBlock;
+    branchFrom(afterCondition);
+    visitStatement(node.body); // visitContinue will add predecessors to join.
+    branchFrom(afterCondition);
+    visitStatement(node.next);
+  }
+
+  visitTry(Try node) {
+    Block catchBlock = newBlock();
+    branchFrom(_currentBlock, catchBlock: catchBlock);
+    visitStatement(node.tryBody);
+    _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);
+  }
+
+  visitConditional(Conditional node) {
+    visitExpression(node.condition);
+    // TODO(asgerf): When assignment expressions are added, this is no longer
+    // sound; then we need to handle as a branch.
+    visitExpression(node.thenExpression);
+    visitExpression(node.elseExpression);
+  }
+
+  visitLogicalOperator(LogicalOperator node) {
+    visitExpression(node.left);
+    // TODO(asgerf): When assignment expressions are added, this is no longer
+    // sound; then we need to handle as a branch.
+    visitExpression(node.right);
+  }
+
+  visitFunctionDeclaration(FunctionDeclaration node) {
+    // The function variable is final, hence cannot be merged.
+    ignoreVariable(node.variable);
+    visitStatement(node.next);
+  }
+}
+
+/// Computes liveness information of the given control-flow graph.
+///
+/// The results are stored in [Block.liveIn] and [Block.liveOut].
+void _computeLiveness(List<Block> blocks) {
+  // We use a LIFO queue as worklist. Blocks are given in AST order, so by
+  // inserting them in this order, we initially visit them backwards, which
+  // is a good ordering.
+  // The choice of LIFO for re-inserted blocks is currently arbitrary,
+  List<Block> worklist = new List<Block>.from(blocks);
+  while (!worklist.isEmpty) {
+    Block block = worklist.removeLast();
+    block.inWorklist = false;
+
+    bool changed = false;
+
+    // The liveIn set is computed as:
+    //
+    //    liveIn = (liveOut - kill) + gen
+    //
+    // We do the computation in two steps:
+    //
+    //    1. liveIn = gen
+    //    2. liveIn += (liveOut - kill)
+    //
+    // However, since liveIn only grows, and gen never changes, we only have
+    // to do the first step at the first iteration. Moreover, the gen set is
+    // not needed anywhere else, so we don't even need to copy it.
+    if (block.liveIn == null) {
+      block.liveIn = block.gen;
+      block.gen = null;
+      changed = true;
+    }
+
+    // liveIn += (liveOut - kill)
+    for (Variable variable in block.liveOut) {
+      if (!block.kill.contains(variable)) {
+        if (block.liveIn.add(variable)) {
+          changed = true;
+        }
+      }
+    }
+
+    // If anything changed, propagate liveness backwards.
+    if (changed) {
+      // Propagate live variables to predecessors.
+      for (Block predecessor in block.predecessors) {
+        int lengthBeforeChange = predecessor.liveOut.length;
+        predecessor.liveOut.addAll(block.liveIn);
+        if (!predecessor.inWorklist &&
+            predecessor.liveOut.length != lengthBeforeChange) {
+          worklist.add(predecessor);
+          predecessor.inWorklist = true;
+        }
+      }
+
+      // Propagate live variables to catch predecessors.
+      for (Block pred in block.catchPredecessors) {
+        bool changed = false;
+        int lengthBeforeChange = pred.liveOut.length;
+        pred.liveOut.addAll(block.liveIn);
+        if (pred.liveOut.length != lengthBeforeChange) {
+          changed = true;
+        }
+        // Assigning to a variable that is live in the catch block, does not
+        // kill the variable, because we conservatively assume that an exception
+        // could be thrown immediately before the assignment.
+        // Therefore remove live variables from all kill sets inside the try.
+        // Since the kill set is only used to subtract live variables from a
+        // set, the analysis remains monotone.
+        lengthBeforeChange = pred.kill.length;
+        pred.kill.removeAll(block.liveIn);
+        if (pred.kill.length != lengthBeforeChange) {
+          changed = true;
+        }
+        if (changed && !pred.inWorklist) {
+          worklist.add(pred);
+          pred.inWorklist = true;
+        }
+      }
+    }
+  }
+}
+
+/// 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
+/// 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');
+
+/// Based on liveness information, computes a map of variable substitutions to
+/// merge variables.
+///
+/// Constructs a register interference graph. This is an undirected graph of
+/// variables, with an edge between two variables if they cannot be merged
+/// (because they are live simultaneously).
+///
+/// We then compute a graph coloring, where the color of a node denotes which
+/// variable it will be substituted by.
+///
+/// We never merge variables that originated from distinct source variables,
+/// so we build a separate register interference graph for each source variable.
+Map<Variable, Variable> _computeRegisterAllocation(List<Block> blocks) {
+  Map<Variable, Set<Variable>> interference = <Variable, Set<Variable>>{};
+
+  /// Group for the given variable. We attempt to merge variables in the same
+  /// group.
+  /// By default, variables are grouped based on their source variable, but
+  /// this can be disabled for testing purposes.
+  Local group(Variable variable) {
+    if (NO_PRESERVE_VARS) {
+      // Parameters may not occur more than once in a parameter list,
+      // so except for parameters, we try to merge all variables.
+      return variable.element is ParameterElement ? variable.element : null;
+    }
+    return variable.element;
+  }
+
+  Set<Variable> empty = new Set<Variable>();
+
+  // At the assignment to a variable x, add an edge to every variable that is
+  // live after the assignment (if it came from the same source variable).
+  for (Block block in blocks) {
+    // Group the liveOut set by source variable.
+    Map<Local, Set<Variable>> liveOut = <Local, Set<Variable>>{};
+    for (Variable variable in block.liveOut) {
+      liveOut.putIfAbsent(
+          group(variable),
+          () => new Set<Variable>()).add(variable);
+      interference.putIfAbsent(variable, () => new Set<Variable>());
+    }
+    // Get variables that are live at the catch block.
+    Set<Variable> liveCatch = block.catchBlock != null
+        ? block.catchBlock.liveIn
+        : empty;
+    // Add edges for each variable being assigned here.
+    for (VariableAccess access in block.accesses.reversed) {
+      Variable variable = access.variable;
+      interference.putIfAbsent(variable, () => new Set<Variable>());
+      Set<Variable> live =
+          liveOut.putIfAbsent(group(variable), () => new Set<Variable>());
+      if (access.isRead) {
+        live.add(variable);
+      } else {
+        if (!liveCatch.contains(variable)) {
+          // Assignment to a variable that is not live in the catch block.
+          live.remove(variable);
+        }
+        for (Variable other in live) {
+          interference[variable].add(other);
+          interference[other].add(variable);
+        }
+      }
+    }
+  }
+
+  // Sort the variables by descending degree.
+  // The most constrained variables will be assigned a color first.
+  List<Variable> variables = interference.keys.toList();
+  variables.sort((x, y) => interference[y].length - interference[x].length);
+
+  Map<Local, List<Variable>> registers = <Local, List<Variable>>{};
+  Map<Variable, Variable> subst = <Variable, Variable>{};
+
+  for (Variable v1 in variables) {
+    List<Variable> register = registers[group(v1)];
+
+    // Optimization: For the first variable in a group, allocate a new color
+    // without iterating over its interference edges.
+    if (register == null) {
+      registers[group(v1)] = <Variable>[v1];
+      subst[v1] = v1;
+      continue;
+    }
+
+    // Optimization: If there are no inteference edges for this variable,
+    // assign it the first color without copying the register list.
+    Set<Variable> interferenceSet = interference[v1];
+    if (interferenceSet.isEmpty) {
+      subst[v1] = register[0];
+      continue;
+    }
+
+    // Find an unused color.
+    Set<Variable> potential = new Set<Variable>.from(register);
+    for (Variable v2 in interferenceSet) {
+      Variable v2subst = subst[v2];
+      if (v2subst != null) {
+        potential.remove(v2subst);
+        if (potential.isEmpty) break;
+      }
+    }
+
+    if (potential.isEmpty) {
+      // If no free color was found, add this variable as a new color.
+      register.add(v1);
+      subst[v1] = v1;
+    } else {
+      subst[v1] = potential.first;
+    }
+  }
+
+  return subst;
+}
+
+/// Performs variable substitution and removes redundant assignments.
+class SubstituteVariables extends RecursiveTransformer {
+
+  Map<Variable, Variable> mapping;
+
+  SubstituteVariables(this.mapping);
+
+  Variable replaceRead(Variable variable) {
+    Variable w = mapping[variable];
+    if (w == null) return variable; // Skip ignored variables.
+    w.readCount++;
+    variable.readCount--;
+    return w;
+  }
+
+  Variable replaceWrite(Variable variable) {
+    Variable w = mapping[variable];
+    if (w == null) return variable; // Skip ignored variables.
+    w.writeCount++;
+    variable.writeCount--;
+    return w;
+  }
+
+  void apply(RootNode node) {
+    for (int i = 0; i < node.parameters.length; ++i) {
+      node.parameters[i] = replaceWrite(node.parameters[i]);
+    }
+    node.replaceEachBody(visitStatement);
+  }
+
+  @override
+  void visitInnerFunction(FunctionDefinition node) {
+    // Do nothing. Inner functions are traversed in VariableMerger.
+  }
+
+  Expression visitVariableUse(VariableUse node) {
+    node.variable = replaceRead(node.variable);
+    return node;
+  }
+
+  Statement visitAssign(Assign node) {
+    node.variable = replaceWrite(node.variable);
+
+    visitExpression(node.value);
+    node.next = visitStatement(node.next);
+
+    // Remove assignments of form "x := x"
+    if (node.value is VariableUse) {
+      VariableUse value = node.value;
+      if (value.variable == node.variable) {
+        value.variable.readCount--;
+        node.variable.writeCount--;
+        return node.next;
+      }
+    }
+
+    return node;
+  }
+}
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 f61630c..fda5ca6 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -46,11 +46,9 @@
 class Builder implements cps_ir.Visitor<Node> {
   final dart2js.InternalErrorFunction internalError;
 
-  /// Maps variable/parameter elements to the Tree variables that represent it.
-  final Map<Local, List<Variable>> local2variables = <Local, List<Variable>>{};
-
-  /// Like [local2variables], except for mutable variables.
-  final Map<cps_ir.MutableVariable, Variable> local2mutable =
+  final Map<cps_ir.Primitive, Variable> primitive2variable =
+      <cps_ir.Primitive, Variable>{};
+  final Map<cps_ir.MutableVariable, Variable> mutable2variable =
       <cps_ir.MutableVariable, Variable>{};
 
   // Continuations with more than one use are replaced with Tree labels.  This
@@ -85,9 +83,9 @@
 
   Variable addMutableVariable(cps_ir.MutableVariable irVariable) {
     assert(irVariable.host == currentElement);
-    assert(!local2mutable.containsKey(irVariable));
+    assert(!mutable2variable.containsKey(irVariable));
     Variable variable = new Variable(currentElement, irVariable.hint);
-    local2mutable[irVariable] = variable;
+    mutable2variable[irVariable] = variable;
     return variable;
   }
 
@@ -95,7 +93,7 @@
     if (mutableVariable.host != currentElement) {
       return parent.getMutableVariable(mutableVariable)..isCaptured = true;
     }
-    return local2mutable[mutableVariable];
+    return mutable2variable[mutableVariable];
   }
 
   VariableUse getMutableVariableUse(
@@ -107,15 +105,8 @@
   /// Obtains the variable representing the given primitive. Returns null for
   /// primitives that have no reference and do not need a variable.
   Variable getVariable(cps_ir.Primitive primitive) {
-    if (primitive.registerIndex == null) {
-      return null; // variable is unused
-    }
-    List<Variable> variables = local2variables.putIfAbsent(primitive.hint,
-        () => <Variable>[]);
-    while (variables.length <= primitive.registerIndex) {
-      variables.add(new Variable(currentElement, primitive.hint));
-    }
-    return variables[primitive.registerIndex];
+    return primitive2variable.putIfAbsent(primitive,
+        () => new Variable(currentElement, primitive.hint));
   }
 
   /// Obtains a reference to the tree Variable corresponding to the IR primitive
@@ -126,18 +117,11 @@
     if (thisParameter != null && reference.definition == thisParameter) {
       return new This();
     }
-    Variable variable = getVariable(reference.definition);
-    if (variable == null) {
-      // Note: this may fail because you forgot to implement a visit-function
-      // in the RegisterAllocator.
-      internalError(
-          CURRENT_ELEMENT_SPANNABLE,
-          "Reference to ${reference.definition} has no register");
-    }
-    return new VariableUse(variable);
+    return new VariableUse(getVariable(reference.definition));
   }
 
-  ExecutableDefinition build(cps_ir.ExecutableDefinition node) {
+  RootNode build(cps_ir.RootNode node) {
+    // TODO(asgerf): Don't have build AND buildXXX as public API.
     if (node is cps_ir.FieldDefinition) {
       return buildField(node);
     } else if (node is cps_ir.ConstructorDefinition) {
@@ -154,7 +138,7 @@
 
   FieldDefinition buildField(cps_ir.FieldDefinition node) {
     Statement body;
-    if (node.hasInitializer) {
+    if (!node.isEmpty) {
       currentElement = node.element;
       returnContinuation = node.body.returnContinuation;
 
@@ -184,7 +168,7 @@
     List<Variable> parameters =
         node.parameters.map(addFunctionParameter).toList();
     Statement body;
-    if (!node.isAbstract) {
+    if (!node.isEmpty) {
       returnContinuation = node.body.returnContinuation;
       phiTempVar = new Variable(node.element, null);
       body = visit(node.body);
@@ -201,7 +185,7 @@
         node.parameters.map(addFunctionParameter).toList();
     List<Initializer> initializers;
     Statement body;
-    if (!node.isAbstract) {
+    if (!node.isEmpty) {
       initializers = node.initializers.map(visit).toList();
       returnContinuation = node.body.returnContinuation;
 
@@ -230,12 +214,12 @@
       cps_ir.Parameter parameter,
       Expression argument,
       Statement buildRest()) {
-    Variable variable = getVariable(parameter);
     Statement assignment;
-    if (variable == null) {
-      assignment = new ExpressionStatement(argument, null);
-    } else {
+    if (parameter.hasAtLeastOneUse) {
+      Variable variable = getVariable(parameter);
       assignment = new Assign(variable, argument, null);
+    } else {
+      assignment = new ExpressionStatement(argument, null);
     }
     assignment.next = buildRest();
     return assignment;
@@ -366,7 +350,7 @@
 
   Initializer visitSuperInitializer(cps_ir.SuperInitializer node) {
     List<Statement> arguments =
-        node.arguments.map((cps_ir.RunnableBody argument) {
+        node.arguments.map((cps_ir.Body argument) {
       returnContinuation = argument.returnContinuation;
       return visit(argument.body);
     }).toList();
@@ -391,7 +375,7 @@
     }
   }
 
-  Statement visitRunnableBody(cps_ir.RunnableBody node) {
+  Statement visitBody(cps_ir.Body node) {
     return visit(node.body);
   }
 
@@ -519,8 +503,11 @@
 
   Statement visitInvokeConstructor(cps_ir.InvokeConstructor node) {
     List<Expression> arguments = translateArguments(node.arguments);
-    Expression invoke =
-        new InvokeConstructor(node.type, node.target, node.selector, arguments);
+    Expression invoke = new InvokeConstructor(
+        node.type,
+        node.target,
+        node.selector,
+        arguments);
     return continueWithExpression(node.continuation, invoke);
   }
 
@@ -651,4 +638,12 @@
   Expression visitReadTypeVariable(cps_ir.ReadTypeVariable node) {
     return new ReadTypeVariable(node.variable, getVariableUse(node.target));
   }
+
+  @override
+  Node visitTypeExpression(cps_ir.TypeExpression node) {
+    return new TypeExpression(
+        node.dartType,
+        node.arguments.map(getVariableUse).toList());
+  }
 }
+
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart
index 01eaa9c..8829e70 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart
@@ -16,7 +16,7 @@
 /// - Variables must not have more than one declaration.
 ///
 class CheckTreeIntegrity extends RecursiveVisitor {
-  ExecutableDefinition topLevelNode;
+  RootNode topLevelNode;
 
   Map<Variable, int> varReads = <Variable, int>{};
   Map<Variable, int> varWrites = <Variable, int>{};
@@ -85,22 +85,9 @@
     node.catchParameters.forEach(undeclare);
   }
 
-  visitFunctionDefinition(FunctionDefinition node) {
-    node.parameters.forEach(declare);
-    if (node.body != null) visitStatement(node.body);
-    node.parameters.forEach(undeclare);
-  }
-
-  visitConstructorDefinition(ConstructorDefinition node) {
-    node.parameters.forEach(declare);
-    if (node.initializers != null) node.initializers.forEach(visitInitializer);
-    if (node.body != null) visitStatement(node.body);
-    node.parameters.forEach(undeclare);
-  }
-
   visitFunctionDeclaration(FunctionDeclaration node) {
     declare(node.variable);
-    visitFunctionDefinition(node.definition);
+    checkBody(node.definition);
     visitStatement(node.next);
     undeclare(node.variable);
     if (varWrites[node.variable] > 1) {
@@ -159,13 +146,23 @@
     labelUses[node.target]++;
   }
 
+  visitInnerFunction(FunctionDefinition node) {
+    checkBody(node);
+  }
+
+  void checkBody(RootNode node) {
+    node.parameters.forEach(declare);
+    node.forEachBody(visitStatement);
+    node.parameters.forEach(undeclare);
+  }
+
   dynamic error(String message) {
     throw 'Tree IR integrity violation in ${topLevelNode.element}:\n$message';
   }
 
-  void check(ExecutableDefinition node) {
+  void check(RootNode node) {
     topLevelNode = node;
-    visitExecutableDefinition(node);
+    checkBody(node);
 
     // Verify reference counters for all variables.
     List<Variable> seenVariables = new List<Variable>();
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 005d082..92abcc8 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
@@ -6,12 +6,11 @@
 
 import '../constants/expressions.dart';
 import '../constants/values.dart' as values;
-import '../dart_types.dart' show DartType, GenericType, TypeVariableType;
+import '../dart_types.dart' show DartType, GenericType, InterfaceType, TypeVariableType;
 import '../elements/elements.dart';
 import '../io/source_information.dart' show SourceInformation;
 import '../universe/universe.dart';
 import '../universe/universe.dart' show Selector;
-import 'optimization/optimization.dart';
 
 // The Tree language is the target of translation out of the CPS-based IR.
 //
@@ -222,11 +221,14 @@
   final values.ConstantValue constant;
 
   InvokeConstructor(this.type, this.target, this.selector, this.arguments,
-      [this.constant]);
+                    [this.constant]);
 
   ClassElement get targetClass => target.enclosingElement;
 
-  accept(ExpressionVisitor visitor) => visitor.visitInvokeConstructor(this);
+  accept(ExpressionVisitor visitor) {
+    return visitor.visitInvokeConstructor(this);
+  }
+
   accept1(ExpressionVisitor1 visitor, arg) {
     return visitor.visitInvokeConstructor(this, arg);
   }
@@ -597,9 +599,6 @@
   }
 }
 
-// TODO(kmillikin): Do we want this 'TryStatement'?  Other than
-// LabeledStatement and EmptyStatement, the statement class names are not
-// suffixed with 'Statement'.
 class Try extends Statement {
   Statement tryBody;
   List<Variable> catchParameters;
@@ -620,42 +619,49 @@
   }
 }
 
-abstract class ExecutableDefinition {
+abstract class RootNode extends Node {
   ExecutableElement get element;
-  Statement body;
+  List<Variable> get parameters;
 
-  applyPass(Pass pass);
+  /// True if there is no body for this root node.
+  ///
+  /// In some parts of the compiler, empty root nodes are used as placeholders
+  /// for abstract methods, external constructors, fields without initializers,
+  /// etc.
+  bool get isEmpty;
+
+  void forEachBody(void action(Statement node));
+  void replaceEachBody(Statement transform(Statement node));
+
+  accept(RootVisitor v);
+  accept1(RootVisitor1 v, arg);
 }
 
-class FieldDefinition extends Node implements ExecutableDefinition {
+class FieldDefinition extends RootNode implements DartSpecificNode {
   final FieldElement element;
   // The `body` of a field is its initializer.
   Statement body;
+  List<Variable> get parameters => const <Variable>[];
 
   FieldDefinition(this.element, this.body);
-  applyPass(Pass pass) => pass.rewriteFieldDefinition(this);
 
-  /// `true` if this field has no initializer.
-  ///
-  /// If `true` [body] is `null`.
-  ///
-  /// This is different from a initializer that is `null`. Consider this class:
-  ///
-  ///     class Class {
-  ///       final field;
-  ///       Class.a(this.field);
-  ///       Class.b() : this.field = null;
-  ///       Class.c();
-  ///     }
-  ///
-  /// If `field` had an initializer, possibly `null`, constructors `Class.a` and
-  /// `Class.b` would be invalid, and since `field` has no initializer
-  /// constructor `Class.c` is invalid. We therefore need to distinguish the two
-  /// cases.
-  bool get hasInitializer => body != null;
+  bool get isEmpty => body == null;
+
+  accept(RootVisitor v) => v.visitFieldDefinition(this);
+  accept1(RootVisitor1 v, arg) => v.visitFieldDefinition(this, arg);
+
+  void forEachBody(void action(Statement node)) {
+    if (isEmpty) return;
+    action(body);
+  }
+
+  void replaceEachBody(Statement transform(Statement node)) {
+    if (isEmpty) return;
+    body = transform(body);
+  }
 }
 
-class FunctionDefinition extends Node implements ExecutableDefinition {
+class FunctionDefinition extends RootNode {
   final FunctionElement element;
   final List<Variable> parameters;
   Statement body;
@@ -670,14 +676,29 @@
     }
   }
 
-  /// Returns `true` if this function is abstract.
-  ///
-  /// If `true` [body] is `null` and [localConstants] is empty.
-  bool get isAbstract => body == null;
-  applyPass(Pass pass) => pass.rewriteFunctionDefinition(this);
+  bool get isEmpty => body == null;
+
+  accept(RootVisitor v) => v.visitFunctionDefinition(this);
+  accept1(RootVisitor1 v, arg) => v.visitFunctionDefinition(this, arg);
+
+  void forEachBody(void action(Statement node)) {
+    if (isEmpty) return;
+    action(body);
+  }
+
+  void replaceEachBody(Statement transform(Statement node)) {
+    if (isEmpty) return;
+    body = transform(body);
+  }
 }
 
-abstract class Initializer implements Expression, DartSpecificNode {}
+abstract class Initializer implements DartSpecificNode {
+  accept(InitializerVisitor v);
+  accept1(InitializerVisitor1 v, arg);
+
+  void forEachBody(void action(Statement node));
+  void replaceEachBody(Statement transform(Statement node));
+}
 
 class FieldInitializer extends Initializer {
   final FieldElement element;
@@ -686,10 +707,18 @@
 
   FieldInitializer(this.element, this.body);
 
-  accept(ExpressionVisitor visitor) => visitor.visitFieldInitializer(this);
-  accept1(ExpressionVisitor1 visitor, arg) {
+  accept(InitializerVisitor visitor) => visitor.visitFieldInitializer(this);
+  accept1(InitializerVisitor1 visitor, arg) {
     return visitor.visitFieldInitializer(this, arg);
   }
+
+  void forEachBody(void action(Statement node)) {
+    action(body);
+  }
+
+  void replaceEachBody(Statement transform(Statement node)) {
+    body = transform(body);
+  }
 }
 
 class SuperInitializer extends Initializer {
@@ -699,25 +728,62 @@
   bool processed = false;
 
   SuperInitializer(this.target, this.selector, this.arguments);
-  accept(ExpressionVisitor visitor) => visitor.visitSuperInitializer(this);
-  accept1(ExpressionVisitor1 visitor, arg) {
+  accept(InitializerVisitor visitor) => visitor.visitSuperInitializer(this);
+  accept1(InitializerVisitor1 visitor, arg) {
     return visitor.visitSuperInitializer(this, arg);
   }
+
+  void forEachBody(void action(Statement node)) {
+    arguments.forEach(action);
+  }
+
+  void replaceEachBody(Statement transform(Statement node)) {
+    for (int i = 0; i < arguments.length; i++) {
+      arguments[i] = transform(arguments[i]);
+    }
+  }
 }
 
-class ConstructorDefinition extends FunctionDefinition {
+class ConstructorDefinition extends RootNode
+                            implements DartSpecificNode {
+  final ConstructorElement element;
+  final List<Variable> parameters;
+  Statement body;
+  final List<ConstDeclaration> localConstants;
+  final List<ConstantExpression> defaultParameterValues;
   final List<Initializer> initializers;
 
-  ConstructorDefinition(ConstructorElement element,
-                        List<Variable> parameters,
-                        Statement body,
+  ConstructorDefinition(this.element,
+                        this.parameters,
+                        this.body,
                         this.initializers,
-                        List<ConstDeclaration> localConstants,
-                        List<ConstantExpression> defaultParameterValues)
-      : super(element, parameters, body, localConstants,
-              defaultParameterValues);
+                        this.localConstants,
+                        this.defaultParameterValues) {
+    for (Variable param in parameters) {
+      param.writeCount++; // Being a parameter counts as a write.
+    }
+  }
 
-  applyPass(Pass pass) => pass.rewriteConstructorDefinition(this);
+  bool get isEmpty => body == null;
+
+  accept(RootVisitor v) => v.visitConstructorDefinition(this);
+  accept1(RootVisitor1 v, arg) => v.visitConstructorDefinition(this, arg);
+
+  void forEachBody(void action(Statement node)) {
+    if (isEmpty) return;
+    for (Initializer init in initializers) {
+      init.forEachBody(action);
+    }
+    action(body);
+  }
+
+  void replaceEachBody(Statement transform(Statement node)) {
+    if (isEmpty) return;
+    for (Initializer init in initializers) {
+      init.replaceEachBody(transform);
+    }
+    body = transform(body);
+  }
 }
 
 abstract class JsSpecificNode implements Node {}
@@ -732,8 +798,9 @@
 class CreateInstance extends Expression implements JsSpecificNode {
   ClassElement classElement;
   List<Expression> arguments;
+  List<Expression> typeInformation;
 
-  CreateInstance(this.classElement, this.arguments);
+  CreateInstance(this.classElement, this.arguments, this.typeInformation);
 
   accept(ExpressionVisitor visitor) => visitor.visitCreateInstance(this);
   accept1(ExpressionVisitor1 visitor, arg) {
@@ -792,8 +859,26 @@
   }
 }
 
+/// 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.)
+class TypeExpression extends Expression {
+  final DartType dartType;
+  final List<Expression> arguments;
+
+  TypeExpression(this.dartType, this.arguments);
+
+  accept(ExpressionVisitor visitor) {
+    return visitor.visitTypeExpression(this);
+  }
+
+  accept1(ExpressionVisitor1 visitor, arg) {
+    return visitor.visitTypeExpression(this, arg);
+  }
+}
+
 abstract class ExpressionVisitor<E> {
-  E visitExpression(Expression e) => e.accept(this);
+  E visitExpression(Expression node) => node.accept(this);
   E visitVariableUse(VariableUse node);
   E visitInvokeStatic(InvokeStatic node);
   E visitInvokeMethod(InvokeMethod node);
@@ -810,17 +895,16 @@
   E visitLiteralMap(LiteralMap node);
   E visitTypeOperator(TypeOperator node);
   E visitFunctionExpression(FunctionExpression node);
-  E visitFieldInitializer(FieldInitializer node);
-  E visitSuperInitializer(SuperInitializer node);
   E visitGetField(GetField node);
   E visitCreateBox(CreateBox node);
   E visitCreateInstance(CreateInstance node);
   E visitReifyRuntimeType(ReifyRuntimeType node);
   E visitReadTypeVariable(ReadTypeVariable node);
+  E visitTypeExpression(TypeExpression node);
 }
 
 abstract class ExpressionVisitor1<E, A> {
-  E visitExpression(Expression e, A arg) => e.accept1(this, arg);
+  E visitExpression(Expression node, A arg) => node.accept1(this, arg);
   E visitVariableUse(VariableUse node, A arg);
   E visitInvokeStatic(InvokeStatic node, A arg);
   E visitInvokeMethod(InvokeMethod node, A arg);
@@ -837,17 +921,16 @@
   E visitLiteralMap(LiteralMap node, A arg);
   E visitTypeOperator(TypeOperator node, A arg);
   E visitFunctionExpression(FunctionExpression node, A arg);
-  E visitFieldInitializer(FieldInitializer node, A arg);
-  E visitSuperInitializer(SuperInitializer node, A arg);
   E visitGetField(GetField node, A arg);
   E visitCreateBox(CreateBox node, A arg);
   E visitCreateInstance(CreateInstance node, A arg);
-  E visitReifyRuntimeType(ReifyRuntimeType reifyRuntimeType, A arg);
-  E visitReadTypeVariable(ReadTypeVariable readTypeVariable, A arg);
+  E visitReifyRuntimeType(ReifyRuntimeType node, A arg);
+  E visitReadTypeVariable(ReadTypeVariable node, A arg);
+  E visitTypeExpression(TypeExpression node, A arg);
 }
 
 abstract class StatementVisitor<S> {
-  S visitStatement(Statement s) => s.accept(this);
+  S visitStatement(Statement node) => node.accept(this);
   S visitLabeledStatement(LabeledStatement node);
   S visitAssign(Assign node);
   S visitReturn(Return node);
@@ -863,7 +946,7 @@
 }
 
 abstract class StatementVisitor1<S, A> {
-  S visitStatement(Statement s, A arg) => s.accept1(this, arg);
+  S visitStatement(Statement node, A arg) => node.accept1(this, arg);
   S visitLabeledStatement(LabeledStatement node, A arg);
   S visitAssign(Assign node, A arg);
   S visitReturn(Return node, A arg);
@@ -878,59 +961,37 @@
   S visitSetField(SetField node, A arg);
 }
 
-abstract class Visitor<S, E> implements ExpressionVisitor<E>,
-                                        StatementVisitor<S> {
-   E visitExpression(Expression e) => e.accept(this);
-   S visitStatement(Statement s) => s.accept(this);
+abstract class RootVisitor<T> {
+  T visitRootNode(RootNode node) => node.accept(this);
+  T visitFunctionDefinition(FunctionDefinition node);
+  T visitConstructorDefinition(ConstructorDefinition node);
+  T visitFieldDefinition(FieldDefinition node);
 }
 
-abstract class Visitor1<S, E, A> implements ExpressionVisitor1<E, A>,
-                                            StatementVisitor1<S, A> {
-   E visitExpression(Expression e, A arg) => e.accept1(this, arg);
-   S visitStatement(Statement s, A arg) => s.accept1(this, arg);
+abstract class RootVisitor1<T, A> {
+  T visitRootNode(RootNode node, A arg) => node.accept1(this, arg);
+  T visitFunctionDefinition(FunctionDefinition node, A arg);
+  T visitConstructorDefinition(ConstructorDefinition node, A arg);
+  T visitFieldDefinition(FieldDefinition node, A arg);
 }
 
-class RecursiveVisitor extends Visitor {
-  // TODO(asgerf): Clean up the tree visitor.
-  
-  visitExecutableDefinition(ExecutableDefinition node) {
-    if (node is ConstructorDefinition) return visitConstructorDefinition(node);
-    if (node is FunctionDefinition) return visitFunctionDefinition(node);
-    if (node is FieldDefinition) return visitFieldDefinition(node);
-    throw 'Unexpected ExecutableDefinition: $node';
-  }
+abstract class InitializerVisitor<T> {
+  T visitInitializer(Initializer node) => node.accept(this);
+  T visitFieldInitializer(FieldInitializer node);
+  T visitSuperInitializer(SuperInitializer node);
+}
 
-  visitFunctionDefinition(FunctionDefinition node) {
-    node.parameters.forEach(visitVariable);
-    if (node.body != null) visitStatement(node.body);
-  }
+abstract class InitializerVisitor1<T, A> {
+  T visitInitializer(Initializer node, A arg) => node.accept1(this, arg);
+  T visitFieldInitializer(FieldInitializer node, A arg);
+  T visitSuperInitializer(SuperInitializer node, A arg);
+}
 
-  visitConstructorDefinition(ConstructorDefinition node) {
-    if (node.initializers != null) node.initializers.forEach(visitInitializer);
-    visitFunctionDefinition(node);
-  }
+abstract class RecursiveVisitor implements StatementVisitor, ExpressionVisitor {
+  visitExpression(Expression e) => e.accept(this);
+  visitStatement(Statement s) => s.accept(this);
 
-  visitFieldDefinition(FieldDefinition node) {
-    if (node.body != null) {
-      visitStatement(node.body);
-    }
-  }
-
-  visitInitializer(Initializer node) {
-    if (node is FieldInitializer) {
-      return visitFieldInitializer(node);
-    } else {
-      return visitSuperInitializer(node);
-    }
-  }
-
-  visitFieldInitializer(FieldInitializer node) {
-    visitStatement(node.body);
-  }
-
-  visitSuperInitializer(SuperInitializer node) {
-    node.arguments.forEach(visitStatement);
-  }
+  visitInnerFunction(FunctionDefinition node);
 
   visitVariable(Variable node) {}
 
@@ -997,7 +1058,7 @@
   }
 
   visitFunctionExpression(FunctionExpression node) {
-    visitFunctionDefinition(node.definition);
+    visitInnerFunction(node.definition);
   }
 
   visitLabeledStatement(LabeledStatement node) {
@@ -1036,7 +1097,7 @@
   }
 
   visitFunctionDeclaration(FunctionDeclaration node) {
-    visitFunctionDefinition(node.definition);
+    visitInnerFunction(node.definition);
     visitStatement(node.next);
   }
 
@@ -1065,6 +1126,7 @@
 
   visitCreateInstance(CreateInstance node) {
     node.arguments.forEach(visitExpression);
+    node.typeInformation.forEach(visitExpression);
   }
 
   visitReifyRuntimeType(ReifyRuntimeType node) {
@@ -1074,4 +1136,194 @@
   visitReadTypeVariable(ReadTypeVariable node) {
     visitExpression(node.target);
   }
+
+  visitTypeExpression(TypeExpression node) {
+    node.arguments.forEach(visitExpression);
+  }
+}
+
+abstract class Transformer implements ExpressionVisitor<Expression>,
+                                      StatementVisitor<Statement> {
+   Expression visitExpression(Expression e) => e.accept(this);
+   Statement visitStatement(Statement s) => s.accept(this);
+}
+
+class RecursiveTransformer extends Transformer {
+  void visitInnerFunction(FunctionDefinition node) {
+    node.body = visitStatement(node.body);
+  }
+
+  void _replaceExpressions(List<Expression> list) {
+    for (int i = 0; i < list.length; i++) {
+      list[i] = visitExpression(list[i]);
+    }
+  }
+
+  visitVariableUse(VariableUse node) => node;
+
+  visitInvokeStatic(InvokeStatic node) {
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitInvokeMethod(InvokeMethod node) {
+    node.receiver = visitExpression(node.receiver);
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitInvokeMethodDirectly(InvokeMethodDirectly node) {
+    node.receiver = visitExpression(node.receiver);
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitInvokeConstructor(InvokeConstructor node) {
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitConcatenateStrings(ConcatenateStrings node) {
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitConstant(Constant node) => node;
+
+  visitThis(This node) => node;
+
+  visitReifyTypeVar(ReifyTypeVar node) => node;
+
+  visitConditional(Conditional node) {
+    node.condition = visitExpression(node.condition);
+    node.thenExpression = visitExpression(node.thenExpression);
+    node.elseExpression = visitExpression(node.elseExpression);
+    return node;
+  }
+
+  visitLogicalOperator(LogicalOperator node) {
+    node.left = visitExpression(node.left);
+    node.right = visitExpression(node.right);
+    return node;
+  }
+
+  visitNot(Not node) {
+    node.operand = visitExpression(node.operand);
+    return node;
+  }
+
+  visitLiteralList(LiteralList node) {
+    _replaceExpressions(node.values);
+    return node;
+  }
+
+  visitLiteralMap(LiteralMap node) {
+    node.entries.forEach((LiteralMapEntry entry) {
+      entry.key = visitExpression(entry.key);
+      entry.value = visitExpression(entry.value);
+    });
+    return node;
+  }
+
+  visitTypeOperator(TypeOperator node) {
+    node.receiver = visitExpression(node.receiver);
+    return node;
+  }
+
+  visitFunctionExpression(FunctionExpression node) {
+    visitInnerFunction(node.definition);
+    return node;
+  }
+
+  visitLabeledStatement(LabeledStatement node) {
+    node.body = visitStatement(node.body);
+    node.next = visitStatement(node.next);
+    return node;
+  }
+
+  visitAssign(Assign node) {
+    node.value = visitExpression(node.value);
+    node.next = visitStatement(node.next);
+    return node;
+  }
+
+  visitReturn(Return node) {
+    node.value = visitExpression(node.value);
+    return node;
+  }
+
+  visitBreak(Break node) => node;
+
+  visitContinue(Continue node) => node;
+
+  visitIf(If node) {
+    node.condition = visitExpression(node.condition);
+    node.thenStatement = visitStatement(node.thenStatement);
+    node.elseStatement = visitStatement(node.elseStatement);
+    return node;
+  }
+
+  visitWhileTrue(WhileTrue node) {
+    node.body = visitStatement(node.body);
+    return node;
+  }
+
+  visitWhileCondition(WhileCondition node) {
+    node.condition = visitExpression(node.condition);
+    node.body = visitStatement(node.body);
+    node.next = visitStatement(node.next);
+    return node;
+  }
+
+  visitFunctionDeclaration(FunctionDeclaration node) {
+    visitInnerFunction(node.definition);
+    node.next = visitStatement(node.next);
+    return node;
+  }
+
+  visitExpressionStatement(ExpressionStatement node) {
+    node.expression = visitExpression(node.expression);
+    node.next = visitStatement(node.next);
+    return node;
+  }
+
+  visitTry(Try node) {
+    node.tryBody = visitStatement(node.tryBody);
+    node.catchBody = visitStatement(node.catchBody);
+    return node;
+  }
+
+  visitGetField(GetField node) {
+    node.object = visitExpression(node.object);
+    return node;
+  }
+
+  visitSetField(SetField node) {
+    node.object = visitExpression(node.object);
+    node.value = visitExpression(node.value);
+    node.next = visitStatement(node.next);
+    return node;
+  }
+
+  visitCreateBox(CreateBox node) => node;
+
+  visitCreateInstance(CreateInstance node) {
+    _replaceExpressions(node.arguments);
+    return node;
+  }
+
+  visitReifyRuntimeType(ReifyRuntimeType node) {
+    node.value = visitExpression(node.value);
+    return node;
+  }
+
+  visitReadTypeVariable(ReadTypeVariable node) {
+    node.target = visitExpression(node.target);
+    return node;
+  }
+
+  visitTypeExpression(TypeExpression node) {
+    _replaceExpressions(node.arguments);
+    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 5bea4f5..a6423f3 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
@@ -7,7 +7,6 @@
 import 'dart:async' show EventSink;
 import '../tracer.dart';
 import 'tree_ir_nodes.dart';
-import 'optimization/optimization.dart';
 
 class Block {
   Label label;
@@ -22,6 +21,10 @@
   /// `null` if not inside a try block.
   Block catcher;
 
+  /// True if this block is the entry point to one of the bodies
+  /// (constructors can have multiple bodies).
+  bool isEntryPoint = false;
+
   String get name => 'B$index';
 
   Block([this.label]);
@@ -35,7 +38,7 @@
 class BlockCollector extends StatementVisitor {
   // Accumulate a list of blocks.  The current block is the last block in
   // the list.
-  final List<Block> blocks = [new Block()..index = 0];
+  final List<Block> blocks = [];
 
   // Map tree [Label]s (break or continue targets) and [Statement]s
   // (if targets) to blocks.
@@ -58,17 +61,11 @@
     blocks.add(block);
   }
 
-  void collect(ExecutableDefinition node) {
-    if (node.body != null) {
-      if (node is ConstructorDefinition) {
-        for (Initializer initializer in node.initializers) {
-          if (initializer is FieldInitializer) {
-            visitStatement(initializer.body);
-          }
-        }
-      }
-      visitStatement(node.body);
-    }
+  void collect(RootNode node) {
+    node.forEachBody((Statement body) {
+      _addBlock(new Block()..isEntryPoint = true);
+      visitStatement(body);
+    });
   }
 
   visitLabeledStatement(LabeledStatement node) {
@@ -183,30 +180,29 @@
 
 }
 
-class TreeTracer extends TracerUtil with StatementVisitor, PassMixin {
-  // TODO(asgerf): Fix visitors so we don't have to use PassMixin here.
+class TreeTracer extends TracerUtil with StatementVisitor {
   String get passName => null;
 
   final EventSink<String> output;
 
   TreeTracer(this.output);
 
+  List<Variable> parameters;
   Names names;
   BlockCollector collector;
   int statementCounter;
 
-  void traceGraph(String name, ExecutableDefinition node) {
-    if (node is FunctionDefinition && node.isAbstract) return;
-    if (node is FieldDefinition && node.body == null) return;
+  void traceGraph(String name, RootNode node) {
+    if (node.isEmpty) return;
+    parameters = node.parameters;
     tag("cfg", () {
       printProperty("name", name);
-      rewrite(node);
+      printRootNode(node);
       collector.blocks.forEach(printBlock);
     });
   }
 
-  @override
-  void rewriteExecutableDefinition(ExecutableDefinition node) {
+  void printRootNode(RootNode node) {
     collector = new BlockCollector();
     names = new Names();
     statementCounter = 0;
@@ -231,6 +227,10 @@
         });
       });
       tag("HIR", () {
+        if (block.isEntryPoint) {
+          String params = parameters.map(names.varName).join(', ');
+          printStatement(null, 'Entry ($params)');
+        }
         if (block.label != null) {
           printStatement(null,
               "Label ${block.name}, useCount=${block.label.useCount}");
@@ -381,11 +381,12 @@
   }
 
   String visitInvokeConstructor(InvokeConstructor node) {
+    String className = node.target.enclosingClass.name;
     String callName;
     if (node.target.name.isEmpty) {
-      callName = '${node.type}';
+      callName = '${className}';
     } else {
-      callName = '${node.type}.${node.target.name}';
+      callName = '${className}.${node.target.name}';
     }
     String args = formatArguments(node);
     String keyword = node.constant != null ? 'const' : 'new';
@@ -495,12 +496,17 @@
 
   @override
   String visitReadTypeVariable(ReadTypeVariable node) {
-    return 'read ${node.variable.element} ${visitExpression(node.target)}';
+    return 'Read ${node.variable.element} ${visitExpression(node.target)}';
   }
 
   @override
   String visitReifyRuntimeType(ReifyRuntimeType node) {
-    return 'reify ${node.value}';
+    return 'Reify ${node.value}';
+  }
+
+  @override
+  String visitTypeExpression(TypeExpression node) {
+    return node.dartType.toString();
   }
 }
 
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart
index bb97a15..a6ac402 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/types/type_mask.dart
@@ -200,14 +200,18 @@
   bool operator==(other);
 
   /**
-   * Returns `true` if [other] is a supertype of this mask, i.e., if
-   * this mask is in [other].
+   * If this returns `true`, [other] is guaranteed to be a supertype of this
+   * mask, i.e., this mask is in [other]. However, the inverse does not hold.
+   * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
+   * false negatives.
    */
   bool isInMask(TypeMask other, ClassWorld classWorld);
 
   /**
-   * Returns `true` if [other] is a subtype of this mask, i.e., if
-   * this mask contains [other].
+   * If this returns `true`, [other] is guaranteed to be a subtype of this mask,
+   * i.e., this mask contains [other]. However, the inverse does not hold.
+   * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
+   * false negatives.
    */
   bool containsMask(TypeMask other, ClassWorld classWorld);
 
diff --git a/pkg/compiler/lib/src/types/union_type_mask.dart b/pkg/compiler/lib/src/types/union_type_mask.dart
index 0ad1cc6..3b0f139 100644
--- a/pkg/compiler/lib/src/types/union_type_mask.dart
+++ b/pkg/compiler/lib/src/types/union_type_mask.dart
@@ -9,6 +9,11 @@
 
   static const int MAX_UNION_LENGTH = 4;
 
+  // Set this flag to `true` to perform a set-membership based containment check
+  // instead of relying on normalized types. This is quite slow but can be
+  // helpful in debugging.
+  static const bool PERFORM_EXTRA_CONTAINS_CHECK = false;
+
   UnionTypeMask._internal(this.disjointMasks) {
     assert(disjointMasks.length > 1);
     assert(disjointMasks.every((TypeMask mask) => !mask.isUnion));
@@ -231,7 +236,11 @@
       }
       return disjointMasks.every((FlatTypeMask disjointMask) {
         bool contained = containedInAnyOf(disjointMask, union.disjointMasks);
-        assert(contained || !union.slowContainsCheck(disjointMask, classWorld));
+        if (PERFORM_EXTRA_CONTAINS_CHECK &&
+            !contained &&
+            union.slowContainsCheck(disjointMask, classWorld)) {
+          throw "TypeMask based containment check failed for $this and $other.";
+        }
         return contained;
       });
     }
@@ -245,7 +254,11 @@
     other = other.nonNullable(); // nullable is not canonicalized, so drop it.
     bool contained =
         disjointMasks.any((mask) => mask.containsMask(other, classWorld));
-    assert(contained || !slowContainsCheck(other, classWorld));
+    if (PERFORM_EXTRA_CONTAINS_CHECK &&
+        !contained &&
+        slowContainsCheck(other, classWorld)) {
+      throw "TypeMask based containment check failed for $this and $other.";
+    }
     return contained;
   }
 
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index 3deffcb..590bb54 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -228,230 +228,78 @@
   String toString() => name;
 }
 
-class Selector {
-  final SelectorKind kind;
-  final String name;
-  final LibraryElement library; // Library is null for non-private selectors.
+/// The structure of the arguments at a call-site.
+// TODO(johnniwinther): Should these be cached?
+// TODO(johnniwinther): Should isGetter/isSetter be part of the call structure
+// instead of the selector?
+class CallStructure {
+  static const CallStructure NO_ARGS = const CallStructure.unnamed(0);
+  static const CallStructure ONE_ARG = const CallStructure.unnamed(1);
+  static const CallStructure TWO_ARGS = const CallStructure.unnamed(2);
 
-  // The numbers of arguments of the selector. Includes named arguments.
+  /// The numbers of arguments of the call. Includes named arguments.
   final int argumentCount;
-  final List<String> namedArguments;
-  final List<String> _orderedNamedArguments;
-  final int hashCode;
 
-  static const String INDEX_NAME ="[]";
-  static const String INDEX_SET_NAME = "[]=";
-  static const String CALL_NAME = Compiler.CALL_OPERATOR_NAME;
+  /// The number of named arguments of the call.
+  int get namedArgumentCount => 0;
 
-  Selector.internal(this.kind,
-                    this.name,
-                    this.library,
-                    this.argumentCount,
-                    this.namedArguments,
-                    this._orderedNamedArguments,
-                    this.hashCode) {
-    assert(kind == SelectorKind.INDEX
-           || (name != INDEX_NAME && name != INDEX_SET_NAME));
-    assert(kind == SelectorKind.OPERATOR
-           || kind == SelectorKind.INDEX
-           || !Elements.isOperatorName(name));
-    assert(kind == SelectorKind.CALL
-           || kind == SelectorKind.GETTER
-           || kind == SelectorKind.SETTER
-           || Elements.isOperatorName(name));
-    assert(!isPrivateName(name) || library != null);
-  }
+  /// The number of positional argument of the call.
+  int get positionalArgumentCount => argumentCount;
 
-  static Map<int, List<Selector>> canonicalizedValues =
-      new Map<int, List<Selector>>();
+  const CallStructure.unnamed(this.argumentCount);
 
-  factory Selector(SelectorKind kind,
-                   String name,
-                   LibraryElement library,
-                   int argumentCount,
-                   [List<String> namedArguments]) {
-    if (!isPrivateName(name)) library = null;
-    if (namedArguments == null) namedArguments = const <String>[];
-    int hashCode = computeHashCode(
-        kind, name, library, argumentCount, namedArguments);
-    List<Selector> list = canonicalizedValues.putIfAbsent(hashCode,
-        () => <Selector>[]);
-    for (int i = 0; i < list.length; i++) {
-      Selector existing = list[i];
-      if (existing.match(kind, name, library, argumentCount, namedArguments)) {
-        assert(existing.hashCode == hashCode);
-        assert(existing.mask == null);
-        return existing;
-      }
+  factory CallStructure(int argumentCount, [List<String> namedArguments]) {
+    if (namedArguments == null || namedArguments.isEmpty) {
+      return new CallStructure.unnamed(argumentCount);
     }
-    List<String> orderedNamedArguments = namedArguments.isEmpty
-        ? const <String>[]
-        : <String>[];
-    Selector result = new Selector.internal(
-        kind, name, library, argumentCount,
-        namedArguments, orderedNamedArguments,
-        hashCode);
-    list.add(result);
-    return result;
+    return new NamedCallStructure(argumentCount, namedArguments);
   }
 
-  factory Selector.fromElement(Element element) {
-    String name = element.name;
-    if (element.isFunction) {
-      if (name == '[]') {
-        return new Selector.index();
-      } else if (name == '[]=') {
-        return new Selector.indexSet();
-      }
-      FunctionSignature signature =
-          element.asFunctionElement().functionSignature;
-      int arity = signature.parameterCount;
-      List<String> namedArguments = null;
-      if (signature.optionalParametersAreNamed) {
-        namedArguments =
-            signature.orderedOptionalParameters.map((e) => e.name).toList();
-      }
-      if (element.isOperator) {
-        // Operators cannot have named arguments, however, that doesn't prevent
-        // a user from declaring such an operator.
-        return new Selector(
-            SelectorKind.OPERATOR, name, null, arity, namedArguments);
-      } else {
-        return new Selector.call(
-            name, element.library, arity, namedArguments);
-      }
-    } else if (element.isSetter) {
-      return new Selector.setter(name, element.library);
-    } else if (element.isGetter) {
-      return new Selector.getter(name, element.library);
-    } else if (element.isField) {
-      return new Selector.getter(name, element.library);
-    } else if (element.isConstructor) {
-      return new Selector.callConstructor(name, element.library);
-    } else {
-      throw new SpannableAssertionFailure(
-          element, "Can't get selector from $element");
+  /// `true` if this call has named arguments.
+  bool get isNamed => false;
+
+  /// `true` if this call has no named arguments.
+  bool get isUnnamed => true;
+
+  /// The names of the named arguments in call-site order.
+  List<String> get namedArguments => const <String>[];
+
+  /// The names of the named arguments in canonicalized order.
+  List<String> getOrderedNamedArguments() => const <String>[];
+
+  /// A description of the argument structure.
+  String structureToString() => 'arity=$argumentCount';
+
+  String toString() => 'CallStructure(${structureToString()})';
+
+  Selector get callSelector {
+    return new Selector(SelectorKind.CALL, Selector.CALL_NAME, this);
+  }
+
+  bool match(CallStructure other) {
+    if (identical(this, other)) return true;
+    return this.argumentCount == other.argumentCount
+        && this.namedArgumentCount == other.namedArgumentCount
+        && sameNames(this.namedArguments, other.namedArguments);
+  }
+
+  // TODO(johnniwinther): Cache hash code?
+  int get hashCode {
+    int named = namedArguments.length;
+    int hash = mixHashCodeBits(argumentCount, named);
+    for (int i = 0; i < named; i++) {
+      hash = mixHashCodeBits(hash, namedArguments[i].hashCode);
     }
+    return hash;
   }
 
-  factory Selector.getter(String name, LibraryElement library)
-      => new Selector(SelectorKind.GETTER, name, library, 0);
-
-  factory Selector.getterFrom(Selector selector)
-      => new Selector(SelectorKind.GETTER, selector.name, selector.library, 0);
-
-  factory Selector.setter(String name, LibraryElement library)
-      => new Selector(SelectorKind.SETTER, name, library, 1);
-
-  factory Selector.unaryOperator(String name)
-      => new Selector(SelectorKind.OPERATOR,
-                      Elements.constructOperatorName(name, true),
-                      null, 0);
-
-  factory Selector.binaryOperator(String name)
-      => new Selector(SelectorKind.OPERATOR,
-                      Elements.constructOperatorName(name, false),
-                      null, 1);
-
-  factory Selector.index()
-      => new Selector(SelectorKind.INDEX,
-                      Elements.constructOperatorName(INDEX_NAME, false),
-                      null, 1);
-
-  factory Selector.indexSet()
-      => new Selector(SelectorKind.INDEX,
-                      Elements.constructOperatorName(INDEX_SET_NAME, false),
-                      null, 2);
-
-  factory Selector.call(String name,
-                        LibraryElement library,
-                        int arity,
-                        [List<String> namedArguments])
-      => new Selector(SelectorKind.CALL, name, library, arity, namedArguments);
-
-  factory Selector.callClosure(int arity, [List<String> namedArguments])
-      => new Selector(SelectorKind.CALL, CALL_NAME, null,
-                      arity, namedArguments);
-
-  factory Selector.callClosureFrom(Selector selector)
-      => new Selector(SelectorKind.CALL, CALL_NAME, null,
-                      selector.argumentCount, selector.namedArguments);
-
-  factory Selector.callConstructor(String name, LibraryElement library,
-                                   [int arity = 0,
-                                    List<String> namedArguments])
-      => new Selector(SelectorKind.CALL, name, library,
-                      arity, namedArguments);
-
-  factory Selector.callDefaultConstructor()
-      => new Selector(SelectorKind.CALL, "", null, 0);
-
-  bool get isGetter => identical(kind, SelectorKind.GETTER);
-  bool get isSetter => identical(kind, SelectorKind.SETTER);
-  bool get isCall => identical(kind, SelectorKind.CALL);
-  bool get isClosureCall {
-    String callName = Compiler.CALL_OPERATOR_NAME;
-    return isCall && name == callName;
-  }
-
-  bool get isIndex => identical(kind, SelectorKind.INDEX) && argumentCount == 1;
-  bool get isIndexSet => identical(kind, SelectorKind.INDEX) && argumentCount == 2;
-
-  bool get isOperator => identical(kind, SelectorKind.OPERATOR);
-  bool get isUnaryOperator => isOperator && argumentCount == 0;
-
-  /** Check whether this is a call to 'assert'. */
-  bool get isAssert => isCall && identical(name, "assert");
-
-  int get namedArgumentCount => namedArguments.length;
-  int get positionalArgumentCount => argumentCount - namedArgumentCount;
-
-  bool get hasExactMask => false;
-  TypeMask get mask => null;
-  Selector get asUntyped => this;
-
-  /**
-   * The member name for invocation mirrors created from this selector.
-   */
-  String get invocationMirrorMemberName =>
-      isSetter ? '$name=' : name;
-
-  int get invocationMirrorKind {
-    const int METHOD = 0;
-    const int GETTER = 1;
-    const int SETTER = 2;
-    int kind = METHOD;
-    if (isGetter) {
-      kind = GETTER;
-    } else if (isSetter) {
-      kind = SETTER;
-    }
-    return kind;
-  }
-
-  bool appliesUnnamed(Element element, World world) {
-    assert(sameNameHack(element, world));
-    return appliesUntyped(element, world);
-  }
-
-  bool appliesUntyped(Element element, World world) {
-    assert(sameNameHack(element, world));
-    if (Elements.isUnresolved(element)) return false;
-    if (isPrivateName(name) && library != element.library) return false;
-    if (world.isForeign(element)) return true;
-    if (element.isSetter) return isSetter;
-    if (element.isGetter) return isGetter || isCall;
-    if (element.isField) {
-      return isSetter
-          ? !element.isFinal && !element.isConst
-          : isGetter || isCall;
-    }
-    if (isGetter) return true;
-    if (isSetter) return false;
-    return signatureApplies(element);
+  bool operator ==(other) {
+    if (other is! CallStructure) return false;
+    return match(other);
   }
 
   bool signatureApplies(FunctionElement function) {
+    if (Elements.isUnresolved(function)) return false;
     FunctionSignature parameters = function.functionSignature;
     if (argumentCount > parameters.parameterCount) return false;
     int requiredParameterCount = parameters.requiredParameterCount;
@@ -484,18 +332,6 @@
     }
   }
 
-  bool sameNameHack(Element element, World world) {
-    // TODO(ngeoffray): Remove workaround checks.
-    return element.isConstructor ||
-           name == element.name ||
-           name == 'assert' && world.isAssertMethod(element);
-  }
-
-  bool applies(Element element, World world) {
-    if (!sameNameHack(element, world)) return false;
-    return appliesUnnamed(element, world);
-  }
-
   /**
    * Returns a `List` with the evaluated arguments in the normalized order.
    *
@@ -564,21 +400,20 @@
    * Returns [:true:] if the signature of the [caller] matches the
    * signature of the [callee], [:false:] otherwise.
    */
-  static bool addForwardingElementArgumentsToList(
-      FunctionElement caller,
-      List list,
-      FunctionElement callee,
-      compileArgument(Element element),
-      compileConstant(Element element),
-      World world) {
+  static /*<T>*/ bool addForwardingElementArgumentsToList(
+      ConstructorElement caller,
+      List/*<T>*/ list,
+      ConstructorElement callee,
+      /*T*/ compileArgument(ParameterElement element),
+      /*T*/ compileConstant(ParameterElement element)) {
 
     FunctionSignature signature = caller.functionSignature;
-    Map mapping = new Map();
+    Map<Node, ParameterElement> mapping = <Node, ParameterElement>{};
 
     // TODO(ngeoffray): This is a hack that fakes up AST nodes, so
     // that we can call [addArgumentsToList].
-    Link computeCallNodesFromParameters() {
-      LinkBuilder builder = new LinkBuilder();
+    Link<Node> computeCallNodesFromParameters() {
+      LinkBuilder<Node> builder = new LinkBuilder<Node>();
       signature.forEachRequiredParameter((ParameterElement element) {
         Node node = element.node;
         mapping[node] = element;
@@ -599,29 +434,28 @@
       return builder.toLink();
     }
 
-    internalCompileArgument(Node node) {
+    /*T*/ internalCompileArgument(Node node) {
       return compileArgument(mapping[node]);
     }
 
     Link<Node> nodes = computeCallNodesFromParameters();
 
-    // Synthesize a selector for the call.
+    // Synthesize a structure for the call.
     // TODO(ngeoffray): Should the resolver do it instead?
     List<String> namedParameters;
     if (signature.optionalParametersAreNamed) {
-      namedParameters =
-          signature.optionalParameters.mapToList((e) => e.name);
+      namedParameters = signature.optionalParameters.mapToList((e) => e.name);
     }
-    Selector selector = new Selector.call(callee.name,
-                                          caller.library,
-                                          signature.parameterCount,
-                                          namedParameters);
-
-    if (!selector.applies(callee, world)) return false;
-    list.addAll(selector.makeArgumentsList(nodes,
-                                           callee,
-                                           internalCompileArgument,
-                                           compileConstant));
+    CallStructure callStructure =
+        new CallStructure(signature.parameterCount, namedParameters);
+    if (!callStructure.signatureApplies(callee)) {
+      return false;
+    }
+    list.addAll(callStructure.makeArgumentsList(
+        nodes,
+        callee,
+        internalCompileArgument,
+        compileConstant));
 
     return true;
   }
@@ -632,59 +466,32 @@
     }
     return true;
   }
+}
 
-  bool match(SelectorKind kind,
-             String name,
-             LibraryElement library,
-             int argumentCount,
-             List<String> namedArguments) {
-    return this.kind == kind
-        && this.name == name
-        && identical(this.library, library)
-        && this.argumentCount == argumentCount
-        && this.namedArguments.length == namedArguments.length
-        && sameNames(this.namedArguments, namedArguments);
+///
+class NamedCallStructure extends CallStructure {
+  final List<String> namedArguments;
+  final List<String> _orderedNamedArguments = <String>[];
+
+  NamedCallStructure(int argumentCount, this.namedArguments)
+      : super.unnamed(argumentCount) {
+    assert(namedArguments.isNotEmpty);
   }
 
-  static int computeHashCode(SelectorKind kind,
-                             String name,
-                             LibraryElement library,
-                             int argumentCount,
-                             List<String> namedArguments) {
-    // Add bits from name and kind.
-    int hash = mixHashCodeBits(name.hashCode, kind.hashCode);
-    // Add bits from the library.
-    if (library != null) hash = mixHashCodeBits(hash, library.hashCode);
-    // Add bits from the unnamed arguments.
-    hash = mixHashCodeBits(hash, argumentCount);
-    // Add bits from the named arguments.
-    int named = namedArguments.length;
-    hash = mixHashCodeBits(hash, named);
-    for (int i = 0; i < named; i++) {
-      hash = mixHashCodeBits(hash, namedArguments[i].hashCode);
-    }
-    return hash;
-  }
+  @override
+  bool get isNamed => true;
 
-  // TODO(kasperl): Move this out so it becomes useful in other places too?
-  static int mixHashCodeBits(int existing, int value) {
-    // Spread the bits of value. Try to stay in the 30-bit range to
-    // avoid overflowing into a more expensive integer representation.
-    int h = value & 0x1fffffff;
-    h += ((h & 0x3fff) << 15) ^ 0x1fffcd7d;
-    h ^= (h >> 10);
-    h += ((h & 0x3ffffff) << 3);
-    h ^= (h >> 6);
-    h += ((h & 0x7ffffff) << 2) + ((h & 0x7fff) << 14);
-    h ^= (h >> 16);
-    // Combine the two hash values.
-    int high = existing >> 15;
-    int low = existing & 0x7fff;
-    return ((high * 13) ^ (low * 997) ^ h) & SMI_MASK;
-  }
+  @override
+  bool get isUnnamed => false;
 
+  @override
+  int get namedArgumentCount => namedArguments.length;
+
+  @override
+  int get positionalArgumentCount => argumentCount - namedArgumentCount;
+
+  @override
   List<String> getOrderedNamedArguments() {
-    if (namedArguments.isEmpty) return namedArguments;
     if (!_orderedNamedArguments.isEmpty) return _orderedNamedArguments;
 
     _orderedNamedArguments.addAll(namedArguments);
@@ -694,25 +501,273 @@
     return _orderedNamedArguments;
   }
 
-  String namedArgumentsToString() {
-    if (namedArgumentCount > 0) {
-      StringBuffer result = new StringBuffer();
-      for (int i = 0; i < namedArgumentCount; i++) {
-        if (i != 0) result.write(', ');
-        result.write(namedArguments[i]);
+  @override
+  String structureToString() {
+    return 'arity=$argumentCount, named=[${namedArguments.join(', ')}]';
+  }
+}
+
+class Selector {
+  final SelectorKind kind;
+  final Name memberName;
+  final CallStructure callStructure;
+
+  final int hashCode;
+
+  int get argumentCount => callStructure.argumentCount;
+  int get namedArgumentCount => callStructure.namedArgumentCount;
+  int get positionalArgumentCount => callStructure.positionalArgumentCount;
+  List<String> get namedArguments => callStructure.namedArguments;
+
+  String get name => memberName.text;
+
+  LibraryElement get library => memberName.library;
+
+  static const Name INDEX_NAME = const PublicName("[]");
+  static const Name INDEX_SET_NAME = const PublicName("[]=");
+  static const Name CALL_NAME = const PublicName(Compiler.CALL_OPERATOR_NAME);
+
+  Selector.internal(this.kind,
+                    this.memberName,
+                    this.callStructure,
+                    this.hashCode) {
+    assert(kind == SelectorKind.INDEX ||
+           (memberName != INDEX_NAME && memberName != INDEX_SET_NAME));
+    assert(kind == SelectorKind.OPERATOR ||
+           kind == SelectorKind.INDEX ||
+           !Elements.isOperatorName(memberName.text));
+    assert(kind == SelectorKind.CALL ||
+           kind == SelectorKind.GETTER ||
+           kind == SelectorKind.SETTER ||
+           Elements.isOperatorName(memberName.text));
+  }
+
+  // TODO(johnniwinther): Extract caching.
+  static Map<int, List<Selector>> canonicalizedValues =
+      new Map<int, List<Selector>>();
+
+  factory Selector(SelectorKind kind,
+                   Name name,
+                   CallStructure callStructure) {
+    // TODO(johnniwinther): Maybe use equality instead of implicit hashing.
+    int hashCode = computeHashCode(kind, name, callStructure);
+    List<Selector> list = canonicalizedValues.putIfAbsent(hashCode,
+        () => <Selector>[]);
+    for (int i = 0; i < list.length; i++) {
+      Selector existing = list[i];
+      if (existing.match(kind, name, callStructure)) {
+        assert(existing.hashCode == hashCode);
+        assert(existing.mask == null);
+        return existing;
       }
-      return "[$result]";
     }
-    return '';
+    Selector result = new Selector.internal(
+        kind, name, callStructure, hashCode);
+    list.add(result);
+    return result;
+  }
+
+  factory Selector.fromElement(Element element) {
+    String name = element.name;
+    if (element.isFunction) {
+      if (name == '[]') {
+        return new Selector.index();
+      } else if (name == '[]=') {
+        return new Selector.indexSet();
+      }
+      FunctionSignature signature =
+          element.asFunctionElement().functionSignature;
+      int arity = signature.parameterCount;
+      List<String> namedArguments = null;
+      if (signature.optionalParametersAreNamed) {
+        namedArguments =
+            signature.orderedOptionalParameters.map((e) => e.name).toList();
+      }
+      if (element.isOperator) {
+        // Operators cannot have named arguments, however, that doesn't prevent
+        // a user from declaring such an operator.
+        return new Selector(
+            SelectorKind.OPERATOR,
+            new PublicName(name),
+            new CallStructure(arity, namedArguments));
+      } else {
+        return new Selector.call(
+            name, element.library, arity, namedArguments);
+      }
+    } else if (element.isSetter) {
+      return new Selector.setter(name, element.library);
+    } else if (element.isGetter) {
+      return new Selector.getter(name, element.library);
+    } else if (element.isField) {
+      return new Selector.getter(name, element.library);
+    } else if (element.isConstructor) {
+      return new Selector.callConstructor(name, element.library);
+    } else {
+      throw new SpannableAssertionFailure(
+          element, "Can't get selector from $element");
+    }
+  }
+
+  factory Selector.getter(String name, LibraryElement library)
+      => new Selector(SelectorKind.GETTER,
+                      new Name(name, library),
+                      CallStructure.NO_ARGS);
+
+  factory Selector.getterFrom(Selector selector)
+      => new Selector(SelectorKind.GETTER,
+                      selector.memberName,
+                      CallStructure.NO_ARGS);
+
+  factory Selector.setter(String name, LibraryElement library)
+      => new Selector(SelectorKind.SETTER,
+                      new Name(name, library, isSetter: true),
+                      CallStructure.ONE_ARG);
+
+  factory Selector.unaryOperator(String name) => new Selector(
+      SelectorKind.OPERATOR,
+      new PublicName(Elements.constructOperatorName(name, true)),
+      CallStructure.NO_ARGS);
+
+  factory Selector.binaryOperator(String name) => new Selector(
+      SelectorKind.OPERATOR,
+      new PublicName(Elements.constructOperatorName(name, false)),
+      CallStructure.ONE_ARG);
+
+  factory Selector.index()
+      => new Selector(SelectorKind.INDEX, INDEX_NAME,
+                      CallStructure.ONE_ARG);
+
+  factory Selector.indexSet()
+      => new Selector(SelectorKind.INDEX, INDEX_SET_NAME,
+                      CallStructure.TWO_ARGS);
+
+  factory Selector.call(String name,
+                        LibraryElement library,
+                        int arity,
+                        [List<String> namedArguments])
+      => new Selector(SelectorKind.CALL,
+          new Name(name, library),
+          new CallStructure(arity, namedArguments));
+
+  factory Selector.callClosure(int arity, [List<String> namedArguments])
+      => new Selector(SelectorKind.CALL, CALL_NAME,
+                      new CallStructure(arity, namedArguments));
+
+  factory Selector.callClosureFrom(Selector selector)
+      => new Selector(SelectorKind.CALL, CALL_NAME, selector.callStructure);
+
+  factory Selector.callConstructor(String name, LibraryElement library,
+                                   [int arity = 0,
+                                    List<String> namedArguments])
+      => new Selector(SelectorKind.CALL, new Name(name, library),
+                      new CallStructure(arity, namedArguments));
+
+  factory Selector.callDefaultConstructor()
+      => new Selector(
+          SelectorKind.CALL,
+          const PublicName(''),
+          CallStructure.NO_ARGS);
+
+  bool get isGetter => kind == SelectorKind.GETTER;
+  bool get isSetter => kind == SelectorKind.SETTER;
+  bool get isCall => kind == SelectorKind.CALL;
+  bool get isClosureCall => isCall && memberName == CALL_NAME;
+
+  bool get isIndex => kind == SelectorKind.INDEX && argumentCount == 1;
+  bool get isIndexSet => kind == SelectorKind.INDEX && argumentCount == 2;
+
+  bool get isOperator => kind == SelectorKind.OPERATOR;
+  bool get isUnaryOperator => isOperator && argumentCount == 0;
+
+  /** 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.
+   */
+  String get invocationMirrorMemberName =>
+      isSetter ? '$name=' : name;
+
+  int get invocationMirrorKind {
+    const int METHOD = 0;
+    const int GETTER = 1;
+    const int SETTER = 2;
+    int kind = METHOD;
+    if (isGetter) {
+      kind = GETTER;
+    } else if (isSetter) {
+      kind = SETTER;
+    }
+    return kind;
+  }
+
+  bool appliesUnnamed(Element element, World world) {
+    assert(sameNameHack(element, world));
+    return appliesUntyped(element, world);
+  }
+
+  bool appliesUntyped(Element element, World world) {
+    assert(sameNameHack(element, world));
+    if (Elements.isUnresolved(element)) return false;
+    if (memberName.isPrivate && memberName.library != element.library) {
+      // TODO(johnniwinther): Maybe this should be
+      // `memberName != element.memberName`.
+      return false;
+    }
+    if (world.isForeign(element)) return true;
+    if (element.isSetter) return isSetter;
+    if (element.isGetter) return isGetter || isCall;
+    if (element.isField) {
+      return isSetter
+          ? !element.isFinal && !element.isConst
+          : isGetter || isCall;
+    }
+    if (isGetter) return true;
+    if (isSetter) return false;
+    return signatureApplies(element);
+  }
+
+  bool signatureApplies(FunctionElement function) {
+    return callStructure.signatureApplies(function);
+  }
+
+  bool sameNameHack(Element element, World world) {
+    // TODO(ngeoffray): Remove workaround checks.
+    return element.isConstructor ||
+           name == element.name ||
+           name == 'assert' && world.isAssertMethod(element);
+  }
+
+  bool applies(Element element, World world) {
+    if (!sameNameHack(element, world)) return false;
+    return appliesUnnamed(element, world);
+  }
+
+  bool match(SelectorKind kind,
+             Name memberName,
+             CallStructure callStructure) {
+    return this.kind == kind
+        && this.memberName == memberName
+        && this.callStructure.match(callStructure);
+  }
+
+  static int computeHashCode(SelectorKind kind,
+                             Name name,
+                             CallStructure callStructure) {
+    // Add bits from name and kind.
+    int hash = mixHashCodeBits(name.hashCode, kind.hashCode);
+    // Add bits from the call structure.
+    return mixHashCodeBits(hash, callStructure.hashCode);
   }
 
   String toString() {
-    String named = '';
     String type = '';
-    if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}';
     if (mask != null) type = ', mask=$mask';
-    return 'Selector($kind, $name, '
-           'arity=$argumentCount$named$type)';
+    return 'Selector($kind, $name, ${callStructure.structureToString()}$type)';
   }
 
   Selector extendIfReachesAll(Compiler compiler) {
@@ -730,11 +785,8 @@
   TypedSelector.internal(this.mask, Selector selector, int hashCode)
       : asUntyped = selector,
         super.internal(selector.kind,
-                       selector.name,
-                       selector.library,
-                       selector.argumentCount,
-                       selector.namedArguments,
-                       selector._orderedNamedArguments,
+                       selector.memberName,
+                       selector.callStructure,
                        hashCode) {
     assert(mask != null);
     assert(asUntyped.mask == null);
@@ -758,7 +810,7 @@
         .putIfAbsent(untyped, () => new Map<TypeMask, TypedSelector>());
     TypedSelector result = map[mask];
     if (result == null) {
-      int hashCode = Selector.mixHashCodeBits(untyped.hashCode, mask.hashCode);
+      int hashCode = mixHashCodeBits(untyped.hashCode, mask.hashCode);
       result = map[mask] = new TypedSelector.internal(mask, untyped, hashCode);
     }
     return result;
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index aee8529..8edad0b 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -15,6 +15,7 @@
 import 'cps_ir/cps_ir_builder.dart' as ir_builder;
 import 'cps_ir/cps_ir_builder_task.dart' as ir_builder;
 import 'cps_ir/cps_ir_nodes_sexpr.dart' as cps_ir_nodes_sexpr;
+import 'tree_ir/tree_ir_nodes.dart' as tree_ir;
 import 'dart_types.dart' as dart_types;
 import 'dart2js.dart' as dart2js;
 import 'dart2jslib.dart' as dart2jslib;
@@ -47,6 +48,7 @@
 void main(List<String> arguments) {
   useApi();
   dart2js.main(arguments);
+  dart2jslib.isPublicName(null);
   useConstant(null, null);
   useNode(null);
   useUtil(null);
@@ -72,6 +74,7 @@
   useScript(null);
   useProgramBuilder(null);
   useSemanticVisitor();
+  useTreeVisitors();
 }
 
 useApi() {
@@ -269,6 +272,8 @@
 
 useCodeEmitterTask(js_emitter.CodeEmitterTask codeEmitterTask) {
   codeEmitterTask.oldEmitter.clearCspPrecompiledNodes();
+  codeEmitterTask.oldEmitter.
+      buildLazilyInitializedStaticField(null, isolateProperties: null);
 }
 
 useScript(dart2jslib.Script script) {
@@ -284,3 +289,18 @@
   new semantic_visitor.BulkVisitor().apply(null, null);
   new semantic_visitor.TraversalVisitor(null).apply(null, null);
 }
+
+class DummyTreeVisitor extends tree_ir.RootVisitor
+                          with tree_ir.InitializerVisitor {
+  visitFunctionDefinition(tree_ir.FunctionDefinition node) {}
+  visitConstructorDefinition(tree_ir.ConstructorDefinition node) {}
+  visitFieldDefinition(tree_ir.FieldDefinition node) {}
+
+  visitFieldInitializer(tree_ir.FieldInitializer node) {}
+  visitSuperInitializer(tree_ir.SuperInitializer node) {}
+}
+
+useTreeVisitors() {
+  new DummyTreeVisitor().visitRootNode(null);
+  new DummyTreeVisitor().visitInitializer(null);
+}
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 7c75819..b825d18 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -18,6 +18,23 @@
 /// Smi range.
 const int SMI_MASK = 0x3fffffff;
 
+/// Mix the bits of [value] and merge them with [existing].
+int mixHashCodeBits(int existing, int value) {
+  // Spread the bits of value. Try to stay in the 30-bit range to
+  // avoid overflowing into a more expensive integer representation.
+  int h = value & 0x1fffffff;
+  h += ((h & 0x3fff) << 15) ^ 0x1fffcd7d;
+  h ^= (h >> 10);
+  h += ((h & 0x3ffffff) << 3);
+  h ^= (h >> 6);
+  h += ((h & 0x7ffffff) << 2) + ((h & 0x7fff) << 14);
+  h ^= (h >> 16);
+  // Combine the two hash values.
+  int high = existing >> 15;
+  int low = existing & 0x7fff;
+  return ((high * 13) ^ (low * 997) ^ h) & SMI_MASK;
+}
+
 /**
  * Tagging interface for classes from which source spans can be generated.
  */
diff --git a/pkg/compiler/lib/src/warnings.dart b/pkg/compiler/lib/src/warnings.dart
index 40b04ed..94714195 100644
--- a/pkg/compiler/lib/src/warnings.dart
+++ b/pkg/compiler/lib/src/warnings.dart
@@ -2410,6 +2410,28 @@
           "Non-supported 'call' member on a native class, or a "
           "subclass of a native class.");
 
+  static const MessageKind DIRECTLY_THROWING_NSM =
+      const MessageKind(
+          "This 'noSuchMethod' implementation is guaranteed to throw an "
+          "exception. The generated code will be smaller if it is "
+          "rewritten.",
+          howToFix: "Rewrite to "
+                    "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'.");
+
+  static const MessageKind COMPLEX_THROWING_NSM =
+      const MessageKind(
+          "This 'noSuchMethod' implementation is guaranteed to throw an "
+          "exception. The generated code will be smaller and the compiler "
+          "will be able to perform more optimizations if it is rewritten.",
+          howToFix: "Rewrite to "
+                    "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'.");
+
+  static const MessageKind COMPLEX_RETURNING_NSM =
+      const MessageKind(
+          "Overriding 'noSuchMethod' causes the compiler to generate "
+          "more code and prevents the compiler from doing some optimizations.",
+          howToFix: "Consider removing this 'noSuchMethod' implementation.");
+
   toString() => template;
 
   Message message([Map arguments = const {}, bool terse = false]) {
diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart
index 57d4142..6b08832 100644
--- a/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/pkg/dart2js_incremental/lib/library_updater.dart
@@ -978,7 +978,7 @@
     if (backend.constants.lazyStatics.contains(element)) {
       jsAst.Expression init =
           emitter.oldEmitter.buildLazilyInitializedStaticField(
-              element, namer.currentIsolate);
+              element, isolateProperties: namer.currentIsolate);
       if (init == null) {
         throw new StateError("Initializer optimized away for $element");
       }
diff --git a/pkg/docgen/lib/src/models/model_helpers.dart b/pkg/docgen/lib/src/models/model_helpers.dart
index f962e75..d587681 100644
--- a/pkg/docgen/lib/src/models/model_helpers.dart
+++ b/pkg/docgen/lib/src/models/model_helpers.dart
@@ -113,7 +113,7 @@
   }
 
   @override
-  Annotation visitConstructed(ConstructedConstantExpresssion exp,
+  Annotation visitConstructed(ConstructedConstantExpression exp,
                               AnnotationInfo context) {
     return createAnnotation(exp.target, context,
         exp.arguments.map((a) => a.getText()).toList());
diff --git a/pkg/pkg.status b/pkg/pkg.status
index b24c089..a38d8eb 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -163,9 +163,9 @@
 third_party/html5lib/test/selectors/*: SkipByDesign # Uses dart:io.
 third_party/html5lib/test/tokenizer_test: SkipByDesign # Uses dart:io.
 
-[ $arch == simarm64 ]
+[ $arch == simarm64 || $arch == armv5te ]
 # Timeout. These are not unit tests. They do not run efficiently on our
-# simulator.
+# simulator or low-end devices.
 *: Skip
 
 [ $runtime == vm ]
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index fb02b45..beaf048 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -60,7 +60,6 @@
   deps = [
     "vm:libdart_lib",
     "vm:libdart_vm",
-    "third_party/jscre:libjscre",
     "third_party/double-conversion/src:libdouble_conversion",
     ":generate_version_cc_file",
   ]
@@ -116,7 +115,6 @@
     "vm:libdart_lib",
     "vm:libdart_vm",
     "vm:libdart_platform",
-    "third_party/jscre:libjscre",
     "third_party/double-conversion/src:libdouble_conversion",
   ]
   sources = [
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 7ddfa0c..576a0ef 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -114,7 +114,6 @@
     "../vm:libdart_lib_withcore",
     "../vm:libdart_vm",
     "../vm:libdart_platform",
-    "../third_party/jscre:libjscre",
     "../third_party/double-conversion/src:libdouble_conversion",
     "..:generate_version_cc_file",
   ]
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index c626805..08413e4 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -11,7 +11,8 @@
     'builtin_in_cc_file': 'builtin_in.cc',
     'builtin_cc_file': '<(gen_source_dir)/builtin_gen.cc',
     'snapshot_in_cc_file': 'snapshot_in.cc',
-    'snapshot_bin_file': '<(gen_source_dir)/snapshot_gen.bin',
+    'vm_isolate_snapshot_bin_file': '<(gen_source_dir)/vm_isolate_snapshot_gen.bin',
+    'isolate_snapshot_bin_file': '<(gen_source_dir)/isolate_snapshot_gen.bin',
     'resources_cc_file': '<(gen_source_dir)/resources_gen.cc',
     'bootstrap_resources_cc_file':
         '<(gen_source_dir)/bootstrap_resources_gen.cc',
@@ -352,7 +353,6 @@
       'dependencies': [
         'libdart_lib_withcore',
         'libdart_vm',
-        'libjscre',
         'libdouble_conversion',
         'generate_version_cc_file#host',
       ],
@@ -431,17 +431,19 @@
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)gen_snapshot<(EXECUTABLE_SUFFIX)',
           ],
           'outputs': [
-            '<(snapshot_bin_file)',
+            '<(vm_isolate_snapshot_bin_file)',
+            '<(isolate_snapshot_bin_file)',
           ],
           'action': [
             'python',
             'tools/create_snapshot_bin.py',
             '--executable',
             '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)gen_snapshot<(EXECUTABLE_SUFFIX)',
-            '--output_bin', '<(snapshot_bin_file)',
+            '--vm_output_bin', '<(vm_isolate_snapshot_bin_file)',
+            '--output_bin', '<(isolate_snapshot_bin_file)',
             '--target_os', '<(OS)'
           ],
-          'message': 'Generating ''<(snapshot_bin_file)'' file.'
+          'message': 'Generating ''<(vm_isolate_snapshot_bin_file)'' ''<(isolate_snapshot_bin_file)'' files.'
         },
       ],
     },
@@ -459,7 +461,8 @@
           'inputs': [
             '../tools/create_snapshot_file.py',
             '<(snapshot_in_cc_file)',
-            '<(snapshot_bin_file)'
+            '<(vm_isolate_snapshot_bin_file)',
+            '<(isolate_snapshot_bin_file)',
           ],
           'outputs': [
             '<(snapshot_cc_file)',
@@ -467,7 +470,8 @@
           'action': [
             'python',
             'tools/create_snapshot_file.py',
-            '--input_bin', '<(snapshot_bin_file)',
+            '--vm_input_bin', '<(vm_isolate_snapshot_bin_file)',
+            '--input_bin', '<(isolate_snapshot_bin_file)',
             '--input_cc', '<(snapshot_in_cc_file)',
             '--output', '<(snapshot_cc_file)',
           ],
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 59338260..1f9584d 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -353,6 +353,7 @@
     case 'package':
       return _filePathFromUri(_resolvePackageUri(uri).toString());
     case 'data':
+    case 'embedder-package':
     case 'http':
     case 'https':
       return uri.toString();
diff --git a/runtime/bin/dbg_connection.cc b/runtime/bin/dbg_connection.cc
index 0b0b217..2cc4cd8 100644
--- a/runtime/bin/dbg_connection.cc
+++ b/runtime/bin/dbg_connection.cc
@@ -21,7 +21,7 @@
 namespace dart {
 namespace bin {
 
-extern bool trace_debug_protocol;
+bool trace_debug_protocol = false;
 
 intptr_t DebuggerConnectionHandler::listener_fd_ = -1;
 Monitor* DebuggerConnectionHandler::handler_lock_ = new Monitor();
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 719b2b5..06d8a02 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -25,7 +25,6 @@
 
 #define CHECK_RESULT(result)                                                   \
   if (Dart_IsError(result)) {                                                  \
-    free(snapshot_buffer);                                                     \
     Log::PrintErr("Error: %s", Dart_GetError(result));                         \
     Dart_ExitScope();                                                          \
     Dart_ShutdownIsolate();                                                    \
@@ -35,9 +34,9 @@
 
 // Global state that indicates whether a snapshot is to be created and
 // if so which file to write the snapshot into.
-static const char* snapshot_filename = NULL;
+static const char* vm_isolate_snapshot_filename = NULL;
+static const char* isolate_snapshot_filename = NULL;
 static const char* package_root = NULL;
-static uint8_t* snapshot_buffer = NULL;
 
 
 // Global state which contains a pointer to the script name for which
@@ -67,10 +66,20 @@
 }
 
 
-static bool ProcessSnapshotOption(const char* option) {
-  const char* name = ProcessOption(option, "--snapshot=");
+static bool ProcessVmIsolateSnapshotOption(const char* option) {
+  const char* name = ProcessOption(option, "--vm_isolate_snapshot=");
   if (name != NULL) {
-    snapshot_filename = name;
+    vm_isolate_snapshot_filename = name;
+    return true;
+  }
+  return false;
+}
+
+
+static bool ProcessIsolateSnapshotOption(const char* option) {
+  const char* name = ProcessOption(option, "--isolate_snapshot=");
+  if (name != NULL) {
+    isolate_snapshot_filename = name;
     return true;
   }
   return false;
@@ -114,7 +123,8 @@
 
   // Parse out the vm options.
   while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) {
-    if (ProcessSnapshotOption(argv[i]) ||
+    if (ProcessVmIsolateSnapshotOption(argv[i]) ||
+        ProcessIsolateSnapshotOption(argv[i]) ||
         ProcessURLmappingOption(argv[i]) ||
         ProcessPackageRootOption(argv[i])) {
       i += 1;
@@ -132,8 +142,13 @@
     *script_name = NULL;
   }
 
-  if (snapshot_filename == NULL) {
-    Log::PrintErr("No snapshot output file specified.\n\n");
+  if (vm_isolate_snapshot_filename == NULL) {
+    Log::PrintErr("No vm isolate snapshot output file specified.\n\n");
+    return -1;
+  }
+
+  if (isolate_snapshot_filename == NULL) {
+    Log::PrintErr("No isolate snapshot output file specified.\n\n");
     return -1;
   }
 
@@ -141,11 +156,13 @@
 }
 
 
-static void WriteSnapshotFile(const uint8_t* buffer, const intptr_t size) {
-  File* file = File::Open(snapshot_filename, File::kWriteTruncate);
+static void WriteSnapshotFile(const char* filename,
+                              const uint8_t* buffer,
+                              const intptr_t size) {
+  File* file = File::Open(filename, File::kWriteTruncate);
   ASSERT(file != NULL);
   if (!file->WriteFully(buffer, size)) {
-    Log::PrintErr("Error: Failed to write full snapshot.\n\n");
+    Log::PrintErr("Error: Failed to write snapshot file.\n\n");
   }
   delete file;
 }
@@ -438,15 +455,26 @@
 
 static void CreateAndWriteSnapshot() {
   Dart_Handle result;
-  uint8_t* buffer = NULL;
-  intptr_t size = 0;
+  uint8_t* vm_isolate_buffer = NULL;
+  intptr_t vm_isolate_size = 0;
+  uint8_t* isolate_buffer = NULL;
+  intptr_t isolate_size = 0;
 
   // First create a snapshot.
-  result = Dart_CreateSnapshot(&buffer, &size);
+  result = Dart_CreateSnapshot(&vm_isolate_buffer,
+                               &vm_isolate_size,
+                               &isolate_buffer,
+                               &isolate_size);
   CHECK_RESULT(result);
 
-  // Now write the snapshot out to specified file and exit.
-  WriteSnapshotFile(buffer, size);
+  // Now write the vm isolate and isolate snapshots out to the
+  // specified file and exit.
+  WriteSnapshotFile(vm_isolate_snapshot_filename,
+                    vm_isolate_buffer,
+                    vm_isolate_size);
+  WriteSnapshotFile(isolate_snapshot_filename,
+                    isolate_buffer,
+                    isolate_size);
   Dart_ExitScope();
 
   // Shutdown the isolate.
@@ -510,7 +538,8 @@
   // Initialize the Dart VM.
   // Note: We don't expect isolates to be created from dart code during
   // snapshot generation.
-  if (!Dart_Initialize(NULL, NULL, NULL, NULL,
+  if (!Dart_Initialize(NULL,
+                       NULL, NULL, NULL, NULL,
                        DartUtils::OpenFile,
                        DartUtils::ReadFile,
                        DartUtils::WriteFile,
@@ -532,7 +561,8 @@
   Dart_Handle library;
   Dart_EnterScope();
 
-  ASSERT(snapshot_filename != NULL);
+  ASSERT(vm_isolate_snapshot_filename != NULL);
+  ASSERT(isolate_snapshot_filename != NULL);
   // Load up the script before a snapshot is created.
   if (app_script_name != NULL) {
     // This is the case of a custom embedder (e.g: dartium) trying to
@@ -557,6 +587,7 @@
         DartUtils::PrepareForScriptLoading(package_root, false, builtin_lib);
     CHECK_RESULT(result);
     Dart_ExitScope();
+    Dart_ExitIsolate();
 
     UriResolverIsolateScope::isolate = isolate;
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 693ab90..9fa8de9 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -28,9 +28,13 @@
 namespace dart {
 namespace bin {
 
-// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
-// it is initialized to NULL.
-extern const uint8_t* snapshot_buffer;
+// vm_isolate_snapshot_buffer points to a snapshot for the vm isolate if we
+// link in a snapshot otherwise it is initialized to NULL.
+extern const uint8_t* vm_isolate_snapshot_buffer;
+
+// isolate_snapshot_buffer points to a snapshot for an isolate if we link in a
+// snapshot otherwise it is initialized to NULL.
+extern const uint8_t* isolate_snapshot_buffer;
 
 // Global state that stores a pointer to the application script snapshot.
 static bool generate_script_snapshot = false;
@@ -293,7 +297,7 @@
                                            CommandLineOptions* vm_options) {
   if (filename != NULL && strlen(filename) != 0) {
     // Ensure that are already running using a full snapshot.
-    if (snapshot_buffer == NULL) {
+    if (isolate_snapshot_buffer == NULL) {
       Log::PrintErr("Script snapshots cannot be generated in this version of"
                     " dart\n");
       return false;
@@ -346,7 +350,7 @@
 }
 
 
-bool trace_debug_protocol = false;
+extern bool trace_debug_protocol;
 static bool ProcessTraceDebugProtocolOption(const char* arg,
                                             CommandLineOptions* vm_options) {
   if (*arg != '\0') {
@@ -584,7 +588,7 @@
 
   isolate = Dart_CreateIsolate(script_uri,
                                main,
-                               snapshot_buffer,
+                               isolate_snapshot_buffer,
                                isolate_data,
                                error);
 
@@ -594,7 +598,7 @@
 
   Dart_EnterScope();
 
-  if (snapshot_buffer != NULL) {
+  if (isolate_snapshot_buffer != NULL) {
     // Setup the native resolver as the snapshot does not carry it.
     Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
     Builtin::SetNativeResolver(Builtin::kIOLibrary);
@@ -610,6 +614,10 @@
       *error = strdup(VmService::GetErrorMessage());
       return NULL;
     }
+    if (has_compile_all) {
+      result = Dart_CompileAll();
+      CHECK_RESULT(result);
+    }
     Dart_ExitScope();
     Dart_ExitIsolate();
     return isolate;
@@ -960,7 +968,8 @@
   }
 
   // Initialize the Dart VM.
-  if (!Dart_Initialize(CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
+  if (!Dart_Initialize(vm_isolate_snapshot_buffer,
+                       CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
                        DartUtils::OpenFile,
                        DartUtils::ReadFile,
                        DartUtils::WriteFile,
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 0cffb5a..b6d40ee 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -490,7 +490,7 @@
 
     _processes.remove(_serviceId);
 
-    return new _ProcessResult(
+    return new ProcessResult(
         result[0],
         result[1],
         getOutput(result[2], stdoutEncoding),
@@ -602,7 +602,7 @@
     Future stderr = foldStream(p.stderr, stderrEncoding);
 
     return Future.wait([p.exitCode, stdout, stderr]).then((result) {
-      return new _ProcessResult(pid, result[0], result[1], result[2]);
+      return new ProcessResult(pid, result[0], result[1], result[2]);
     });
   });
 }
@@ -625,16 +625,3 @@
                                  ProcessStartMode.NORMAL);
   return process._runAndWait(stdoutEncoding, stderrEncoding);
 }
-
-
-class _ProcessResult implements ProcessResult {
-  const _ProcessResult(int this.pid,
-                       int this.exitCode,
-                       this.stdout,
-                       this.stderr);
-
-  final int pid;
-  final int exitCode;
-  final stdout;
-  final stderr;
-}
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 9688457..f6bffe8 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -97,7 +97,8 @@
   bool set_vm_flags_success = Flags::ProcessCommandLineFlags(dart_argc,
                                                              dart_argv);
   ASSERT(set_vm_flags_success);
-  const char* err_msg = Dart::InitOnce(NULL, NULL, NULL, NULL,
+  const char* err_msg = Dart::InitOnce(NULL,
+                                       NULL, NULL, NULL, NULL,
                                        dart::bin::DartUtils::OpenFile,
                                        dart::bin::DartUtils::ReadFile,
                                        dart::bin::DartUtils::WriteFile,
diff --git a/runtime/bin/snapshot_empty.cc b/runtime/bin/snapshot_empty.cc
index f8c3f95..4fd42b3 100644
--- a/runtime/bin/snapshot_empty.cc
+++ b/runtime/bin/snapshot_empty.cc
@@ -17,7 +17,8 @@
 namespace dart {
 namespace bin {
 
-const uint8_t* snapshot_buffer = NULL;
+const uint8_t* vm_isolate_snapshot_buffer = NULL;
+const uint8_t* isolate_snapshot_buffer = NULL;
 
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/snapshot_in.cc b/runtime/bin/snapshot_in.cc
index 2e2a497..1f57a55 100644
--- a/runtime/bin/snapshot_in.cc
+++ b/runtime/bin/snapshot_in.cc
@@ -18,12 +18,24 @@
 namespace bin {
 
 // The string on the next line will be filled in with the contents of the
-// generated snapshot binary file.
-// This string forms the content of a snapshot which is loaded in by dart.
-static const uint8_t snapshot_buffer_[] = {
+// generated snapshot binary file for the vm isolate.
+// This string forms the content of a vm isolate snapshot which is loaded
+// into the vm isolate.
+static const uint8_t vm_isolate_snapshot_buffer_[] = {
+  0,
   %s
 };
-const uint8_t* snapshot_buffer = snapshot_buffer_;
+const uint8_t* vm_isolate_snapshot_buffer = vm_isolate_snapshot_buffer_;
+
+
+// The string on the next line will be filled in with the contents of the
+// generated snapshot binary file for a regular dart isolate.
+// This string forms the content of a regular dart isolate snapshot which is
+// loaded into an isolate when it is created.
+static const uint8_t isolate_snapshot_buffer_[] = {
+  %s
+};
+const uint8_t* isolate_snapshot_buffer = isolate_snapshot_buffer_;
 
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index a847828..2530f37 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -10,11 +10,9 @@
   static const int NOT_MAP_ERROR_CODE = 4002;
   final WebSocket socket;
 
-  WebSocketClient(this.socket, service) : super(service) {
+  WebSocketClient(this.socket, VMService service) : super(service) {
     socket.listen((message) => onWebSocketMessage(message));
     socket.done.then((_) => close());
-    service.subscribe('debug', this);
-    service.subscribe('gc', this);
   }
 
   void onWebSocketMessage(message) {
@@ -37,15 +35,15 @@
     }
   }
 
-  void post(var serial, dynamic response) {
+  void post(var serial, dynamic result) {
     try {
-      Map map = {
-        'id': serial,
-        'response': response
-      };
-      if (serial == null && response is! String) {
-        socket.add(response);
+      if (serial == null && result is! String) {
+        socket.add(result);
       } else {
+        Map map = {
+          'id': serial,
+          'result': result
+        };
         socket.add(JSON.encode(map));
       }
     } catch (_) {
@@ -67,11 +65,12 @@
       new ContentType("application", "json", charset: "utf-8");
   final HttpRequest request;
 
-  HttpRequestClient(this.request, service) : super(service);
+  HttpRequestClient(this.request, VMService service)
+      : super(service, sendEvents:false);
 
-  void post(var serial, String response) {
+  void post(var serial, String result) {
     request.response..headers.contentType = jsonContentType
-                    ..write(response)
+                    ..write(result)
                     ..close();
     close();
   }
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index 75aa56c..409bc59 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -31,7 +31,9 @@
 
 _onShutdown() {
   if (server != null) {
-    server.close(true).catchError((e, st) { assert(e); });
+    server.close(true).catchError((e, st) {
+      print("Error in vm-service shutdown: $e\n$st\n");
+    });
   }
   if (_signalSubscription != null) {
     _signalSubscription.cancel();
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index 986aa92..725d204 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -24,9 +24,9 @@
 
 
 
-// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
-// it is initialized to NULL.
-extern const uint8_t* snapshot_buffer;
+// isolate_snapshot_buffer points to a snapshot if we link in a snapshot
+// otherwise it is initialized to NULL.
+extern const uint8_t* isolate_snapshot_buffer;
 
 static const char* DEFAULT_VM_SERVICE_SERVER_IP = "127.0.0.1";
 static const int DEFAULT_VM_SERVICE_SERVER_PORT = 0;
@@ -42,12 +42,12 @@
 
 
 Dart_Isolate VmServiceServer::CreateIsolate() {
-  ASSERT(snapshot_buffer != NULL);
+  ASSERT(isolate_snapshot_buffer != NULL);
   // Create the isolate.
   char* error = 0;
   Dart_Isolate isolate = Dart_CreateIsolate(DART_VM_SERVICE_ISOLATE_NAME,
                                             "main",
-                                            dart::bin::snapshot_buffer,
+                                            dart::bin::isolate_snapshot_buffer,
                                             NULL,
                                             &error);
   if (!isolate) {
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp
index 5e7c5d5..d64b9a9 100644
--- a/runtime/dart-runtime.gyp
+++ b/runtime/dart-runtime.gyp
@@ -9,7 +9,6 @@
     'observatory/observatory.gypi',
     'bin/bin.gypi',
     'third_party/double-conversion/src/double-conversion.gypi',
-    'third_party/jscre/jscre.gypi',
   ],
   'variables': {
     'gen_source_dir': '<(SHARED_INTERMEDIATE_DIR)',
@@ -17,7 +16,7 @@
     'version_cc_file': '<(gen_source_dir)/version.cc',
 
     'libdart_deps': ['libdart_lib_withcore', 'libdart_lib', 'libdart_vm',
-                     'libjscre', 'libdouble_conversion',],
+                     'libdouble_conversion',],
   },
   'targets': [
     {
@@ -26,7 +25,6 @@
       'dependencies': [
         'libdart_lib',
         'libdart_vm',
-        'libjscre',
         'libdouble_conversion',
         'generate_version_cc_file#host',
       ],
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 2d2dbc3..af5f977 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -825,6 +825,8 @@
 /**
  * Initializes the VM.
  *
+ * \param vm_isolate_snapshot A buffer containing a snapshot of the VM isolate
+ *   or NULL if no snapshot is provided.
  * \param create A function to be called during isolate creation.
  *   See Dart_IsolateCreateCallback.
  * \param interrupt A function to be called when an isolate is interrupted.
@@ -837,6 +839,7 @@
  * \return True if initialization is successful.
  */
 DART_EXPORT bool Dart_Initialize(
+    const uint8_t* vm_isolate_snapshot,
     Dart_IsolateCreateCallback create,
     Dart_IsolateInterruptCallback interrupt,
     Dart_IsolateUnhandledExceptionCallback unhandled_exception,
@@ -889,8 +892,8 @@
  *   Provided only for advisory purposes to improve debugging messages.
  * \param main The name of the main entry point this isolate will run.
  *   Provided only for advisory purposes to improve debugging messages.
- * \param snapshot A buffer containing a VM snapshot or NULL if no
- *   snapshot is provided.
+ * \param snapshot A buffer containing a snapshot of the isolate or
+ *   NULL if no snapshot is provided.
  * \param callback_data Embedder data.  This data will be passed to
  *   the Dart_IsolateCreateCallback when new isolates are spawned from
  *   this parent isolate.
@@ -949,12 +952,10 @@
  * Enters an isolate. After calling this function,
  * the current isolate will be set to the provided isolate.
  *
- * Requires there to be no current isolate.
+ * Requires there to be no current isolate. Multiple threads may not be in
+ * the same isolate at once.
  */
 DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate);
-/* TODO(turnidge): Describe what happens if two threads attempt to
- * enter the same isolate simultaneously. Check for this in the code.
- * Describe whether isolates are allowed to migrate. */
 
 /**
  * Notifies the VM that the current isolate is about to make a blocking call.
@@ -992,9 +993,10 @@
 /**
  * Creates a full snapshot of the current isolate heap.
  *
- * A full snapshot is a compact representation of the dart heap state and
- * can be used for fast initialization of an isolate. A Snapshot of the heap
- * can only be created before any dart code has executed.
+ * A full snapshot is a compact representation of the dart vm isolate heap
+ * and dart isolate heap states. These snapshots are used to initialize
+ * the vm isolate on startup and fast initialization of an isolate.
+ * A Snapshot of the heap is created before any dart code has executed.
  *
  * Requires there to be a current isolate.
  *
@@ -1005,8 +1007,11 @@
  *
  * \return A valid handle if no error occurs during the operation.
  */
-DART_EXPORT Dart_Handle Dart_CreateSnapshot(uint8_t** buffer,
-                                            intptr_t* size);
+DART_EXPORT Dart_Handle Dart_CreateSnapshot(
+    uint8_t** vm_isolate_snapshot_buffer,
+    intptr_t* vm_isolate_snapshot_size,
+    uint8_t** isolate_snapshot_buffer,
+    intptr_t* isolate_snapshot_size);
 
 /**
  * Creates a snapshot of the application script loaded in the isolate.
@@ -1169,6 +1174,11 @@
 
 /**
  * Returns a new SendPort with the provided port id.
+ *
+ * \param port_id The destination port.
+ *
+ * \return A new SendPort if no errors occurs. Otherwise returns
+ *   an error handle.
  */
 DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id);
 
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
index cad1562..78b5cc5 100644
--- a/runtime/lib/bigint.dart
+++ b/runtime/lib/bigint.dart
@@ -65,6 +65,16 @@
   static _Bigint _ZERO = new _Bigint._fromInt(0);
   static _Bigint _ONE = new _Bigint._fromInt(1);
 
+  // Result cache for last _divRem call.
+  static Uint32List _lastDividend_digits;
+  static int _lastDividend_used;
+  static Uint32List _lastDivisor_digits;
+  static int _lastDivisor_used;
+  static Uint32List _lastQuoRem_digits;
+  static int _lastQuoRem_used;
+  static int _lastRem_used;
+  static int _lastRem_nsh;
+
   // Internal data structure.
   bool get _neg native "Bigint_getNeg";
   int get _used native "Bigint_getUsed";
@@ -171,13 +181,13 @@
 
   // Return this << n*_DIGIT_BITS.
   _Bigint _dlShift(int n) {
-    var used = _used;
+    final used = _used;
     if (used == 0) {
       return _ZERO;
     }
-    var r_used = used + n;
-    var digits = _digits;
-    var r_digits = new Uint32List(r_used + (r_used & 1));
+    final r_used = used + n;
+    final digits = _digits;
+    final r_digits = new Uint32List(r_used + (r_used & 1));
     var i = used;
     while (--i >= 0) {
       r_digits[i + n] = digits[i];
@@ -192,10 +202,10 @@
     if (x_used == 0) {
       return 0;
     }
-    if (n == 0 && r_digits == x_digits) {
+    if (n == 0 && identical(r_digits, x_digits)) {
       return x_used;
     }
-    var r_used = x_used + n;
+    final r_used = x_used + n;
     assert(r_digits.length >= r_used + (r_used & 1));
     var i = x_used;
     while (--i >= 0) {
@@ -213,20 +223,20 @@
 
   // Return this >> n*_DIGIT_BITS.
   _Bigint _drShift(int n) {
-    var used = _used;
+    final used = _used;
     if (used == 0) {
       return _ZERO;
     }
-    var r_used = used - n;
+    final r_used = used - n;
     if (r_used <= 0) {
       return _neg ? _MINUS_ONE : _ZERO;
     }
-    var digits = _digits;
-    var r_digits = new Uint32List(r_used + (r_used & 1));
+    final digits = _digits;
+    final r_digits = new Uint32List(r_used + (r_used & 1));
     for (var i = n; i < used; i++) {
       r_digits[i - n] = digits[i];
     }
-    var r = new _Bigint(_neg, r_used, r_digits);
+    final r = new _Bigint(_neg, r_used, r_digits);
     if (_neg) {
       // Round down if any bit was shifted out.
       for (var i = 0; i < n; i++) {
@@ -242,7 +252,7 @@
   // Return r_used.
   static int _drShiftDigits(Uint32List x_digits, int x_used, int n,
                             Uint32List r_digits) {
-    var r_used = x_used - n;
+    final r_used = x_used - n;
     if (r_used <= 0) {
       return 0;
     }
@@ -256,25 +266,33 @@
     return r_used;
   }
 
+  // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n.
+  static void _lsh(Uint32List x_digits, int x_used, int n,
+                   Uint32List r_digits) {
+    final ds = n ~/ _DIGIT_BITS;
+    final bs = n % _DIGIT_BITS;
+    final cbs = _DIGIT_BITS - bs;
+    final bm = (1 << cbs) - 1;
+    var c = 0;
+    var i = x_used;
+    while (--i >= 0) {
+      final d = x_digits[i];
+      r_digits[i + ds + 1] = (d >> cbs) | c;
+      c = (d & bm) << bs;
+    }
+    r_digits[ds] = c;
+  }
+
   // Return this << n.
   _Bigint _lShift(int n) {
-    var ds = n ~/ _DIGIT_BITS;
-    var bs = n % _DIGIT_BITS;
+    final ds = n ~/ _DIGIT_BITS;
+    final bs = n % _DIGIT_BITS;
     if (bs == 0) {
       return _dlShift(ds);
     }
-    var cbs = _DIGIT_BITS - bs;
-    var bm = (1 << cbs) - 1;
     var r_used = _used + ds + 1;
-    var digits = _digits;
-    var r_digits = new Uint32List(r_used + (r_used & 1));
-    var c = 0;
-    var i = _used;
-    while (--i >= 0) {
-      r_digits[i + ds + 1] = (digits[i] >> cbs) | c;
-      c = (digits[i] & bm) << bs;
-    }
-    r_digits[ds] = c;
+    var r_digits = new Uint32List(r_used + 2 + (r_used & 1));  // +2 for 64-bit.
+    _lsh(_digits, _used, n, r_digits);
     return new _Bigint(_neg, r_used, r_digits);
   }
 
@@ -282,57 +300,62 @@
   // Return r_used.
   static int _lShiftDigits(Uint32List x_digits, int x_used, int n,
                            Uint32List r_digits) {
-    var ds = n ~/ _DIGIT_BITS;
-    var bs = n % _DIGIT_BITS;
+    final ds = n ~/ _DIGIT_BITS;
+    final bs = n % _DIGIT_BITS;
     if (bs == 0) {
       return _dlShiftDigits(x_digits, x_used, ds, r_digits);
     }
-    var cbs = _DIGIT_BITS - bs;
-    var bm = (1 << cbs) - 1;
     var r_used = x_used + ds + 1;
-    assert(r_digits.length >= r_used + (r_used & 1));
-    var c = 0;
-    var i = x_used;
-    while (--i >= 0) {
-      r_digits[i + ds + 1] = (x_digits[i] >> cbs) | c;
-      c = (x_digits[i] & bm) << bs;
-    }
-    r_digits[ds] = c;
-    i = ds;
+    assert(r_digits.length >= r_used + 2 + (r_used & 1));  // +2 for 64-bit.
+    _lsh(x_digits, x_used, n, r_digits);
+    var i = ds;
     while (--i >= 0) {
       r_digits[i] = 0;
     }
-    if (r_used.isOdd) {
+    if (r_digits[r_used - 1] == 0) {
+      r_used--;  // Clamp result.
+    } else if (r_used.isOdd) {
       r_digits[r_used] = 0;
     }
     return r_used;
   }
 
+  // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n.
+  static void _rsh(Uint32List x_digits, int x_used, int n,
+                   Uint32List r_digits) {
+    final ds = n ~/ _DIGIT_BITS;
+    final bs = n % _DIGIT_BITS;
+    final cbs = _DIGIT_BITS - bs;
+    final bm = (1 << bs) - 1;
+    var c = x_digits[ds] >> bs;
+    final last = x_used - ds - 1;
+    for (var i = 0; i < last; i++) {
+      final d = x_digits[i + ds + 1];
+      r_digits[i] = ((d & bm) << cbs) | c;
+      c = d >> bs;
+    }
+    r_digits[last] = c;
+  }
+
   // Return this >> n.
   _Bigint _rShift(int n) {
-    var ds = n ~/ _DIGIT_BITS;
-    var bs = n % _DIGIT_BITS;
+    final ds = n ~/ _DIGIT_BITS;
+    final bs = n % _DIGIT_BITS;
     if (bs == 0) {
       return _drShift(ds);
     }
-    var r_used = _used - ds;
+    final used = _used;
+    final r_used = used - ds;
     if (r_used <= 0) {
       return _neg ? _MINUS_ONE : _ZERO;
     }
-    var cbs = _DIGIT_BITS - bs;
-    var bm = (1 << bs) - 1;
-    var digits = _digits;
-    var r_digits = new Uint32List(r_used + (r_used & 1));
-    r_digits[0] = digits[ds] >> bs;
-    var used = _used;
-    for (var i = ds + 1; i < used; i++) {
-      r_digits[i - ds - 1] |= (digits[i] & bm) << cbs;
-      r_digits[i - ds] = digits[i] >> bs;
-    }
-    var r = new _Bigint(_neg, r_used, r_digits);
+    final digits = _digits;
+    final r_digits = new Uint32List(r_used + (r_used & 1));
+    _rsh(digits, used, n, r_digits);
+    final r = new _Bigint(_neg, r_used, r_digits);
     if (_neg) {
       // Round down if any bit was shifted out.
-      if ((digits[ds] & bm) != 0) {
+      if ((digits[ds] & ((1 << bs) - 1)) != 0) {
         return r._sub(_ONE);
       }
       for (var i = 0; i < ds; i++) {
@@ -348,8 +371,8 @@
   // Return r_used.
   static int _rShiftDigits(Uint32List x_digits, int x_used, int n,
                            Uint32List r_digits) {
-    var ds = n ~/ _DIGIT_BITS;
-    var bs = n % _DIGIT_BITS;
+    final ds = n ~/ _DIGIT_BITS;
+    final bs = n % _DIGIT_BITS;
     if (bs == 0) {
       return _drShiftDigits(x_digits, x_used, ds, r_digits);
     }
@@ -357,15 +380,11 @@
     if (r_used <= 0) {
       return 0;
     }
-    var cbs = _DIGIT_BITS - bs;
-    var bm = (1 << bs) - 1;
     assert(r_digits.length >= r_used + (r_used & 1));
-    r_digits[0] = x_digits[ds] >> bs;
-    for (var i = ds + 1; i < x_used; i++) {
-      r_digits[i - ds - 1] |= (x_digits[i] & bm) << cbs;
-      r_digits[i - ds] = x_digits[i] >> bs;
-    }
-    if (r_used.isOdd) {
+    _rsh(x_digits, x_used, n, r_digits);
+    if (r_digits[r_used - 1] == 0) {
+      r_used--;  // Clamp result.
+    } else if (r_used.isOdd) {
       r_digits[r_used] = 0;
     }
     return r_used;
@@ -935,128 +954,156 @@
 
   // Return trunc(this / a), a != 0.
   _Bigint _div(_Bigint a) {
-    return _divRem(a, true);
+    assert(a._used > 0);
+    if (_used < a._used) {
+      return _ZERO;
+    }
+    _divRem(a);
+    // Return quotient, i.e.
+    // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign.
+    var lastQuo_used = _lastQuoRem_used - _lastRem_used;
+    var quo_digits = _cloneDigits(_lastQuoRem_digits,
+                                  _lastRem_used,
+                                  _lastQuoRem_used,
+                                  lastQuo_used);
+    var quo = new _Bigint(false, lastQuo_used, quo_digits);
+    if ((_neg != a._neg) && (quo._used > 0)) {
+      quo = quo._negate();
+    }
+    return quo;
   }
 
   // Return this - a * trunc(this / a), a != 0.
   _Bigint _rem(_Bigint a) {
-    return _divRem(a, false);
-  }
-
-  // Return trunc(this / a), a != 0, if div == true.
-  // Return this - a * trunc(this / a), a != 0, if div == false.
-  _Bigint _divRem(_Bigint a, bool div) {
     assert(a._used > 0);
     if (_used < a._used) {
-      return div ? _ZERO : this;
+      return this;
+    }
+    _divRem(a);
+    // Return remainder, i.e.
+    // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign.
+    var rem_digits = _cloneDigits(_lastQuoRem_digits,
+                                  0,
+                                  _lastRem_used,
+                                  _lastRem_used);
+    var rem = new _Bigint(false, _lastRem_used, rem_digits);
+    if (_lastRem_nsh > 0) {
+      rem = rem._rShift(_lastRem_nsh);  // Denormalize remainder.
+    }
+    if (_neg && (rem._used > 0)) {
+      rem = rem._negate();
+    }
+    return rem;
+  }
+
+  // Cache concatenated positive quotient and normalized positive remainder.
+  void _divRem(_Bigint a) {
+    // Check if result is already cached (identical on Bigint is too expensive).
+    if ((this._used == _lastDividend_used) &&
+        (a._used == _lastDivisor_used) &&
+        identical(this._digits, _lastDividend_digits) &&
+        identical(a._digits, _lastDivisor_digits)) {
+      return;
     }
     var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]);
     // For 64-bit processing, make sure y has an even number of digits.
     if (a._used.isOdd) {
       nsh += _DIGIT_BITS;
     }
-    var y;  // Normalized positive divisor.
-    var r;  // Concatenated positive quotient and normalized positive remainder.
+    // Concatenated positive quotient and normalized positive remainder.
+    var r_digits;
+    var r_used;
+    // Normalized positive divisor.
+    var y_digits;
+    var y_used;
     if (nsh > 0) {
-      y = a._lShift(nsh)._abs();
-      r = _lShift(nsh)._abs();
+      y_digits = new Uint32List(a._used + 5);  // +5 for norm. and 64-bit.
+      y_used = _lShiftDigits(a._digits, a._used, nsh, y_digits);
+      r_digits = new Uint32List(_used + 5);  // +5 for normalization and 64-bit.
+      r_used = _lShiftDigits(_digits, _used, nsh, r_digits);
+    } else {
+      y_digits = a._digits;
+      y_used = a._used;
+      r_digits = _cloneDigits(_digits, 0, _used, _used + 2);
+      r_used = _used;
     }
-    else {
-      y = a._abs();
-      r = _abs();
-    }
-    var y_used = y._used;
-    var y_digits = y._digits;
-    Uint32List args = new Uint32List(4);
-    args[_YT_LO] = y_digits[y_used - 2];
-    args[_YT] = y_digits[y_used - 1];
-    var r_used = r._used;
+    Uint32List yt_qd = new Uint32List(4);
+    yt_qd[_YT_LO] = y_digits[y_used - 2];
+    yt_qd[_YT] = y_digits[y_used - 1];
     // For 64-bit processing, make sure y_used, i, and j are even.
     assert(y_used.isEven);
     var i = r_used + (r_used & 1);
     var j = i - y_used;
-    var t = y._dlShift(j);
-    if (r._compare(t) >= 0) {
+    // t_digits is a temporary array of i digits.
+    var t_digits = new Uint32List(i);
+    var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits);
+    // Explicit first division step in case normalized dividend is larger or
+    // equal to shifted normalized divisor.
+    if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) {
       assert(i == r_used);
-      r = r._or(_ONE._dlShift(r_used++))._sub(t);
-      assert(r._used == r_used && (i + 1) == r_used);
+      r_digits[r_used++] = 1;  // Quotient = 1.
+      r_digits[r_used] = 0;  // Leading zero.
+      // Subtract divisor from remainder.
+      _absSub(r_digits, r_used, t_digits, t_used, r_digits);
     }
     // Negate y so we can later use _mulAdd instead of non-existent _mulSub.
-    y = _ONE._dlShift(y_used)._sub(y);
-    if (y._used < y_used) {
-      y_digits = _cloneDigits(y._digits, 0, y._used, y_used);
-    } else {
-      y_digits = y._digits;
-    }
-    // y_digits is read-only and has y_used digits (possibly including several
+    var ny_digits = new Uint32List(y_used + 2);
+    ny_digits[y_used] = 1;
+    _absSub(ny_digits, y_used + 1, y_digits, y_used, ny_digits);
+    // ny_digits is read-only and has y_used digits (possibly including several
     // leading zeros) plus a leading zero for 64-bit processing.
-    var r_digits = _cloneDigits(r._digits, 0, r._used, i + 1);
     // r_digits is modified during iteration.
     // r_digits[0..y_used-1] is the current remainder.
     // r_digits[y_used..r_used-1] is the current quotient.
     --i;
     while (j > 0) {
-      var d0 = _estQuotientDigit(args, r_digits, i);
+      var d0 = _estQuotientDigit(yt_qd, r_digits, i);
       j -= d0;
-      var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used);
+      var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used);
       // _estQuotientDigit and _mulAdd must agree on the number of digits to
       // process.
       assert(d0 == d1);
       if (d0 == 1) {
-        if (r_digits[i] < args[_QD]) {
-          var t = y._dlShift(j);
-          var t_digits = t._digits;
-          var t_used = t._used;
+        if (r_digits[i] < yt_qd[_QD]) {
+          var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
           _absSub(r_digits, r_used, t_digits, t_used, r_digits);
-          while (r_digits[i] < --args[_QD]) {
+          while (r_digits[i] < --yt_qd[_QD]) {
             _absSub(r_digits, r_used, t_digits, t_used, r_digits);
           }
         }
       } else {
         assert(d0 == 2);
-        assert(r_digits[i] <= args[_QD_HI]);
-        if ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) {
-          var t = y._dlShift(j);
-          var t_digits = t._digits;
-          var t_used = t._used;
+        assert(r_digits[i] <= yt_qd[_QD_HI]);
+        if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i-1] < yt_qd[_QD])) {
+          var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
           _absSub(r_digits, r_used, t_digits, t_used, r_digits);
-          if (args[_QD] == 0) {
-            --args[_QD_HI];
+          if (yt_qd[_QD] == 0) {
+            --yt_qd[_QD_HI];
           }
-          --args[_QD];
-          assert(r_digits[i] <= args[_QD_HI]);
-          while ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) {
+          --yt_qd[_QD];
+          assert(r_digits[i] <= yt_qd[_QD_HI]);
+          while ((r_digits[i] < yt_qd[_QD_HI]) ||
+                 (r_digits[i-1] < yt_qd[_QD])) {
             _absSub(r_digits, r_used, t_digits, t_used, r_digits);
-            if (args[_QD] == 0) {
-              --args[_QD_HI];
+            if (yt_qd[_QD] == 0) {
+              --yt_qd[_QD_HI];
             }
-            --args[_QD];
-            assert(r_digits[i] <= args[_QD_HI]);
+            --yt_qd[_QD];
+            assert(r_digits[i] <= yt_qd[_QD_HI]);
           }
         }
       }
       i -= d0;
     }
-    if (div) {
-      // Return quotient, i.e. r_digits[y_used..r_used-1] with proper sign.
-      r_digits = _cloneDigits(r_digits, y_used, r_used, r_used - y_used);
-      r = new _Bigint(false, r_used - y_used, r_digits);
-      if (_neg != a._neg && r._used > 0) {
-        r = r._negate();
-      }
-      return r;
-    }
-    // Return remainder, i.e. denormalized r_digits[0..y_used-1] with
-    // proper sign.
-    r_digits = _cloneDigits(r_digits, 0, y_used, y_used);
-    r = new _Bigint(false, y_used, r_digits);
-    if (nsh > 0) {
-      r = r._rShift(nsh);  // Denormalize remainder.
-    }
-    if (_neg && r._used > 0) {
-      r = r._negate();
-    }
-    return r;
+    // Cache result.
+    _lastDividend_digits = _digits;
+    _lastDividend_used = _used;
+    _lastDivisor_digits = a._digits;
+    _lastDivisor_used = a._used;
+    _lastQuoRem_digits = r_digits;
+    _lastQuoRem_used = r_used;
+    _lastRem_used = y_used;
+    _lastRem_nsh = nsh;
   }
 
   // Customized version of _rem() minimizing allocations for use in reduction.
@@ -1189,6 +1236,7 @@
     assert(_DIGIT_BITS == 32);  // Otherwise this code needs to be revised.
     var shift;
     if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) {
+      if (other == 0) return 0;  // Shifted value is zero.
       throw new OutOfMemoryError();
     } else {
       shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0];
@@ -1346,7 +1394,7 @@
     if (e == 0) return 1;
     m = m._toBigint();
     final m_used = m._used;
-    final m_used2p2 = 2*m_used + 2;
+    final m_used2p4 = 2*m_used + 4;
     final e_bitlen = e.bitLength;
     if (e_bitlen <= 0) return 1;
     final bool cannotUseMontgomery = m.isEven || _abs() >= m;
@@ -1355,8 +1403,8 @@
           new _Classic(m) : new _Montgomery(m);
       // TODO(regis): Should we use Barrett reduction for an even modulus and a
       // large exponent?
-      var r_digits = new Uint32List(m_used2p2);
-      var r2_digits = new Uint32List(m_used2p2);
+      var r_digits = new Uint32List(m_used2p4);
+      var r2_digits = new Uint32List(m_used2p4);
       var g_digits = new Uint32List(m_used + (m_used & 1));
       var g_used = z._convert(this, g_digits);
       // Initialize r with g.
@@ -1398,10 +1446,10 @@
     g_digits[1] = new Uint32List(m_used + (m_used & 1));
     g_used[1] = z._convert(this, g_digits[1]);
     if (k > 1) {
-      var g2_digits = new Uint32List(m_used2p2);
+      var g2_digits = new Uint32List(m_used2p4);
       var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits);
       while (n <= km) {
-        g_digits[n] = new Uint32List(m_used2p2);
+        g_digits[n] = new Uint32List(m_used2p4);
         g_used[n] = z._mul(g2_digits, g2_used,
                            g_digits[n - 2], g_used[n - 2],
                            g_digits[n]);
@@ -1412,7 +1460,7 @@
     var is1 = true;
     var r_digits = _ONE._digits;
     var r_used = _ONE._used;
-    var r2_digits = new Uint32List(m_used2p2);
+    var r2_digits = new Uint32List(m_used2p4);
     var r2_used;
     var e_digits = e._digits;
     var j = e._used - 1;
@@ -1436,7 +1484,7 @@
         --j;
       }
       if (is1) {  // r == 1, don't bother squaring or multiplying it.
-        r_digits = new Uint32List(m_used2p2);
+        r_digits = new Uint32List(m_used2p4);
         r_used = g_used[w];
         var gw_digits = g_digits[w];
         var ri = r_used + (r_used & 1);  // Copy leading zero if any.
@@ -1698,7 +1746,7 @@
     // _neg_norm_m_digits is read-only and has nm_used digits (possibly
     // including several leading zeros) plus a leading zero for 64-bit
     // processing.
-    _t_digits = new Uint32List(2*nm_used + 2);
+    _t_digits = new Uint32List(2*nm_used);
   }
 
   int _convert(_Bigint x, Uint32List r_digits) {
@@ -1728,6 +1776,9 @@
   }
 
   int _reduce(Uint32List x_digits, int x_used) {
+    if (x_used < _m._used) {
+      return x_used;
+    }
     // The function _remDigits(...) is optimized for reduction and equivalent to
     // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits);
     return _Bigint._remDigits(x_digits, x_used,
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index f3f9da3..5ff7676 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -36,12 +36,14 @@
   bool isAdding = false;
   bool onListenReceived = false;
   bool isScheduled = false;
+  bool isSuspendedAtYield = false;
   Completer cancellationCompleter = null;
 
   Stream get stream => controller.stream;
 
   void runBody() {
     isScheduled = false;
+    isSuspendedAtYield = false;
     asyncStarBody();
   }
 
@@ -62,15 +64,17 @@
   // The generator would translate a 'yield e' statement to
   // controller.add(e);
   // suspend;
-  // if (controller.isCanelled) return;
+  // if (controller.isCancelled) return;
   bool add(event) {
     if (!onListenReceived) _fatal("yield before stream is listened to!");
+    if (isSuspendedAtYield) _fatal("unexpected yield");
     // If stream is cancelled, tell caller to exit the async generator.
     if (!controller.hasListener) {
       return true;
     }
     controller.add(event);
     scheduleGenerator();
+    isSuspendedAtYield = true;
     return false;
   }
 
@@ -131,7 +135,9 @@
   }
 
   onResume() {
-    scheduleGenerator();
+    if (isSuspendedAtYield) {
+      scheduleGenerator();
+    }
   }
 
   onCancel() {
diff --git a/runtime/lib/core_sources.gypi b/runtime/lib/core_sources.gypi
index d5be47e..8bab528 100644
--- a/runtime/lib/core_sources.gypi
+++ b/runtime/lib/core_sources.gypi
@@ -43,8 +43,6 @@
     'object.cc',
     'object_patch.dart',
     'regexp.cc',
-    'regexp_jsc.cc',
-    'regexp_jsc.h',
     'regexp_patch.dart',
     'stacktrace.cc',
     'stacktrace.dart',
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 9f78df3..1f72dc2 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -168,7 +168,6 @@
   Dart_IsolateCreateCallback callback = Isolate::CreateCallback();
   if (callback == NULL) {
     *error = strdup("Null callback specified for isolate creation\n");
-    Isolate::SetCurrent(parent_isolate);
     return false;
   }
 
@@ -180,7 +179,6 @@
                  init_data,
                  error));
   if (child_isolate == NULL) {
-    Isolate::SetCurrent(parent_isolate);
     return false;
   }
   if (!state->is_spawn_uri()) {
@@ -189,22 +187,22 @@
     child_isolate->set_origin_id(parent_isolate->origin_id());
   }
   state->set_isolate(reinterpret_cast<Isolate*>(child_isolate));
-
-  Isolate::SetCurrent(parent_isolate);
   return true;
 }
 
 
 static void Spawn(Isolate* parent_isolate, IsolateSpawnState* state) {
+  Thread::ExitIsolate();
   // Create a new isolate.
   char* error = NULL;
   if (!CreateIsolate(parent_isolate, state, &error)) {
+    Thread::EnterIsolate(parent_isolate);
     delete state;
     const String& msg = String::Handle(String::New(error));
     free(error);
     ThrowIsolateSpawnException(msg);
   }
-
+  Thread::EnterIsolate(parent_isolate);
   // Start the new isolate if it is already marked as runnable.
   Isolate* spawned_isolate = state->isolate();
   MutexLocker ml(spawned_isolate->mutex());
@@ -229,6 +227,8 @@
       ctx = Closure::context(closure);
       ASSERT(ctx.num_variables() == 0);
 #endif
+      // Get the parent function so that we get the right function name.
+      func = func.parent_function();
       Spawn(isolate, new IsolateSpawnState(port.Id(),
                                            func,
                                            message,
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 7fb8fd0..cfa2e8c 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -240,8 +240,9 @@
 
 
 static RawInstance* CreateMethodMirror(const Function& func,
-                                       const Instance& owner_mirror) {
-  const Array& args = Array::Handle(Array::New(12));
+                                       const Instance& owner_mirror,
+                                       const AbstractType& instantiator) {
+  const Array& args = Array::Handle(Array::New(13));
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func)));
 
   String& name = String::Handle(func.name());
@@ -249,17 +250,18 @@
   args.SetAt(1, name);
 
   args.SetAt(2, owner_mirror);
-  args.SetAt(3, Bool::Get(func.is_static()));
-  args.SetAt(4, Bool::Get(func.is_abstract()));
-  args.SetAt(5, Bool::Get(func.IsGetterFunction()));
-  args.SetAt(6, Bool::Get(func.IsSetterFunction()));
+  args.SetAt(3, instantiator);
+  args.SetAt(4, Bool::Get(func.is_static()));
+  args.SetAt(5, Bool::Get(func.is_abstract()));
+  args.SetAt(6, Bool::Get(func.IsGetterFunction()));
+  args.SetAt(7, Bool::Get(func.IsSetterFunction()));
 
   bool isConstructor = (func.kind() == RawFunction::kConstructor);
-  args.SetAt(7, Bool::Get(isConstructor));
-  args.SetAt(8, Bool::Get(isConstructor && func.is_const()));
-  args.SetAt(9, Bool::Get(isConstructor && func.IsGenerativeConstructor()));
-  args.SetAt(10, Bool::Get(isConstructor && func.is_redirecting()));
-  args.SetAt(11, Bool::Get(isConstructor && func.IsFactory()));
+  args.SetAt(8, Bool::Get(isConstructor));
+  args.SetAt(9, Bool::Get(isConstructor && func.is_const()));
+  args.SetAt(10, Bool::Get(isConstructor && func.IsGenerativeConstructor()));
+  args.SetAt(11, Bool::Get(isConstructor && func.is_redirecting()));
+  args.SetAt(12, Bool::Get(isConstructor && func.IsFactory()));
 
   return CreateMirror(Symbols::_LocalMethodMirror(), args);
 }
@@ -747,7 +749,7 @@
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsMalformed());
 
-  if (type.IsInstantiated()) {
+  if (type.IsInstantiated() || instantiator.IsNull()) {
     return type.Canonicalize();
   }
 
@@ -864,7 +866,7 @@
   const Class& cls = Class::Handle(ref.GetClassReferent());
   const Function& func = Function::Handle(CallMethod(cls));
   ASSERT(!func.IsNull());
-  return CreateMethodMirror(func, owner_mirror);
+  return CreateMethodMirror(func, owner_mirror, AbstractType::Handle());
 }
 
 
@@ -1009,11 +1011,14 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(ClassMirror_members, 2) {
+DEFINE_NATIVE_ENTRY(ClassMirror_members, 3) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance,
                                owner_mirror,
                                arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
+  GET_NATIVE_ARGUMENT(AbstractType,
+                      owner_instantiator,
+                      arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(2));
   const Class& klass = Class::Handle(ref.GetClassReferent());
 
   const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
@@ -1047,7 +1052,8 @@
         (func.kind() == RawFunction::kRegularFunction ||
         func.kind() == RawFunction::kGetterFunction ||
         func.kind() == RawFunction::kSetterFunction)) {
-      member_mirror = CreateMethodMirror(func, owner_mirror);
+      member_mirror = CreateMethodMirror(func, owner_mirror,
+                                         owner_instantiator);
       member_mirrors.Add(member_mirror);
     }
   }
@@ -1056,11 +1062,14 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(ClassMirror_constructors, 2) {
+DEFINE_NATIVE_ENTRY(ClassMirror_constructors, 3) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance,
                                owner_mirror,
                                arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
+  GET_NATIVE_ARGUMENT(AbstractType,
+                      owner_instantiator,
+                      arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(2));
   const Class& klass = Class::Handle(ref.GetClassReferent());
 
   const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
@@ -1079,7 +1088,8 @@
   for (intptr_t i = 0; i < num_functions; i++) {
     func ^= functions.At(i);
     if (func.is_reflectable() && func.kind() == RawFunction::kConstructor) {
-      constructor_mirror = CreateMethodMirror(func, owner_mirror);
+      constructor_mirror = CreateMethodMirror(func, owner_mirror,
+                                              owner_instantiator);
       constructor_mirrors.Add(constructor_mirror);
     }
   }
@@ -1134,7 +1144,8 @@
           (func.kind() == RawFunction::kRegularFunction ||
           func.kind() == RawFunction::kGetterFunction ||
           func.kind() == RawFunction::kSetterFunction)) {
-        member_mirror = CreateMethodMirror(func, owner_mirror);
+        member_mirror = CreateMethodMirror(func, owner_mirror,
+                                           AbstractType::Handle());
         member_mirrors.Add(member_mirror);
       }
     }
@@ -1238,6 +1249,17 @@
     Exceptions::PropagateError(Error::Cast(result));
     UNREACHABLE();
   }
+
+  // Because we currently only use this native for building field extractors and
+  // setters, assume the result is a closure and mark its function as invisible,
+  // so it will not appear in stack traces. Whenever we support
+  // ObjectMirror.evaluate this will need to be separated.
+  ASSERT(Instance::Cast(result).IsClosure());
+  const Function& func =
+      Function::Handle(Closure::function(Instance::Cast(result)));
+  func.set_is_visible(false);
+  func.set_is_debuggable(false);
+
   return result.raw();
 }
 
@@ -1373,7 +1395,19 @@
       // the equality test.
       function = function.parent_function();
     }
-    return CreateMethodMirror(function, Instance::null_instance());
+
+    Type& instantiator = Type::Handle();
+    if (closure.IsClosure()) {
+      const TypeArguments& arguments =
+          TypeArguments::Handle(Closure::GetTypeArguments(closure));
+      const Class& cls =
+          Class::Handle(Isolate::Current()->object_store()->object_class());
+      instantiator = Type::New(cls, arguments, Scanner::kNoSourcePos);
+      instantiator.SetIsFinalized();
+    }
+    return CreateMethodMirror(function,
+                              Instance::null_instance(),
+                              instantiator);
   }
   return Instance::null();
 }
@@ -1818,12 +1852,13 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(MethodMirror_owner, 1) {
+DEFINE_NATIVE_ENTRY(MethodMirror_owner, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
+  GET_NATIVE_ARGUMENT(AbstractType, instantiator, arguments->NativeArgAt(1));
   const Function& func = Function::Handle(ref.GetFunctionReferent());
   if (func.IsNonImplicitClosureFunction()) {
     return CreateMethodMirror(Function::Handle(
-        func.parent_function()), Object::null_instance());
+        func.parent_function()), Object::null_instance(), instantiator);
   }
   const Class& owner = Class::Handle(func.Owner());
   if (owner.IsTopLevel()) {
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 2cbb083..e3f87ba 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -15,16 +15,6 @@
   String toString() => _msg;
 }
 
-Map _filterMap(Map<Symbol, dynamic> old_map, bool filter(Symbol key, value)) {
-  Map new_map = new Map<Symbol, dynamic>();
-  old_map.forEach((key, value) {
-    if (filter(key, value)) {
-      new_map[key] = value;
-    }
-  });
-  return new UnmodifiableMapView(new_map);
-}
-
 Map _makeMemberMap(List mirrors) {
   return new UnmodifiableMapView<Symbol, DeclarationMirror>(
       new Map<Symbol, DeclarationMirror>.fromIterable(
@@ -693,11 +683,12 @@
   ClassMirror get mixin {
     if (_mixin == null) {
       if (_isMixinAlias) {
-        Type mixinType = _nativeMixinInstantiated(_trueSuperclass._reflectedType,
-                                                  _instantiator);
+        Type mixinType = _nativeMixinInstantiated(
+            _trueSuperclass._reflectedType, _instantiator);
         _mixin = reflectType(mixinType);
       } else {
-        Type mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
+        Type mixinType = _nativeMixinInstantiated(_reflectedType,
+                                                  _instantiator);
         if (mixinType == null) {
           // The reflectee is not a mixin application.
           _mixin = this;
@@ -778,25 +769,16 @@
   Map<Symbol, Mirror> get _members {
     if (_cachedMembers == null) {
       var whoseMembers = _isMixinAlias ? _trueSuperclass : this;
-      _cachedMembers = _makeMemberMap(mixin._computeMembers(whoseMembers.mixin._reflectee));
+      _cachedMembers = _makeMemberMap(mixin._computeMembers(
+          _instantiator, whoseMembers.mixin._reflectee));
     }
     return _cachedMembers;
   }
 
-  Map<Symbol, MethodMirror> _cachedMethods;
-  Map<Symbol, MethodMirror> get _methods {
-    if (_cachedMethods == null) {
-      _cachedMethods = _filterMap(
-          _members,
-          (key, value) => (value is MethodMirror && value.isRegularMethod));
-    }
-    return _cachedMethods;
-  }
-
   Map<Symbol, MethodMirror> _cachedConstructors;
   Map<Symbol, MethodMirror> get _constructors {
     if (_cachedConstructors == null) {
-      var constructorsList = _computeConstructors(_reflectee);
+      var constructorsList = _computeConstructors(_instantiator, _reflectee);
       var stringName = _n(simpleName);
       constructorsList.forEach((c) => c._patchConstructorName(stringName));
       _cachedConstructors =
@@ -943,10 +925,10 @@
   static _nativeMixinInstantiated(reflectedType, instantiator)
       native "ClassMirror_mixin_instantiated";
 
-  _computeMembers(reflectee)
+  _computeMembers(reflectee, instantiator)
       native "ClassMirror_members";
 
-  _computeConstructors(reflectee)
+  _computeConstructors(reflectee, instantiator)
       native "ClassMirror_constructors";
 
   _invoke(reflectee, memberName, arguments, argumentNames)
@@ -1015,8 +997,6 @@
   get typeVariables => emptyList;
   get typeArguments => emptyList;
   get metadata => emptyList;
-  Map<Symbol, Mirror> get members => emptyMap;
-  Map<Symbol, MethodMirror> get constructors => emptyMap;
 
   String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
 
@@ -1357,6 +1337,7 @@
 
 class _LocalMethodMirror extends _LocalDeclarationMirror
     implements MethodMirror {
+  final Type _instantiator;
   final bool isStatic;
   final bool isAbstract;
   final bool isGetter;
@@ -1374,6 +1355,7 @@
   _LocalMethodMirror(reflectee,
                      String simpleName,
                      this._owner,
+                     this._instantiator,
                      this.isStatic,
                      this.isAbstract,
                      this.isGetter,
@@ -1391,7 +1373,7 @@
     // For nested closures it is possible, that the mirror for the owner has not
     // been created yet.
     if (_owner == null) {
-      _owner = _MethodMirror_owner(_reflectee);
+      _owner = _MethodMirror_owner(_reflectee, _instantiator);
     }
     return _owner;
   }
@@ -1402,12 +1384,6 @@
   bool get isTopLevel => owner is LibraryMirror;
   bool get isSynthetic => false;
 
-  Type get _instantiator {
-    var o = owner;
-    while (o is MethodMirror) o = o.owner;
-    return o._instantiator;
-  }
-
   TypeMirror _returnType = null;
   TypeMirror get returnType {
     if (_returnType == null) {
@@ -1473,7 +1449,7 @@
 
   String toString() => "MethodMirror on '${MirrorSystem.getName(simpleName)}'";
 
-  static dynamic _MethodMirror_owner(reflectee)
+  static dynamic _MethodMirror_owner(reflectee, instantiator)
       native "MethodMirror_owner";
 
   static dynamic _MethodMirror_return_type(reflectee, instantiator)
@@ -1571,9 +1547,7 @@
   }
 
   Type get _instantiator {
-    var o = owner;
-    while (o is MethodMirror) o = o.owner;
-    return o._instantiator;
+    return owner._instantiator;
   }
 
   TypeMirror _type = null;
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 0adb8d2..6ffeb6d 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -10,12 +10,9 @@
 #include "vm/regexp_parser.h"
 #include "vm/thread.h"
 
-#include "lib/regexp_jsc.h"
-
 namespace dart {
 
 DECLARE_FLAG(bool, trace_irregexp);
-DEFINE_FLAG(bool, use_jscre, false, "Use the JSCRE regular expression engine");
 
 
 DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_factory, 4) {
@@ -28,9 +25,6 @@
   bool ignore_case = handle_case_sensitive.raw() != Bool::True().raw();
   bool multi_line = handle_multi_line.raw() == Bool::True().raw();
 
-  if (FLAG_use_jscre) {
-    return Jscre::Compile(pattern, multi_line, ignore_case);
-  }
   // Parse the pattern once in order to throw any format exceptions within
   // the factory constructor. It is parsed again upon compilation.
   RegExpCompileData compileData;
@@ -91,10 +85,6 @@
   GET_NON_NULL_NATIVE_ARGUMENT(String, str, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
 
-  if (FLAG_use_jscre) {
-    return Jscre::Execute(regexp, str, start_index.Value());
-  }
-
   // This function is intrinsified. See Intrinsifier::JSRegExp_ExecuteMatch.
   const intptr_t cid = str.GetClassId();
 
diff --git a/runtime/lib/regexp_jsc.cc b/runtime/lib/regexp_jsc.cc
deleted file mode 100644
index 158579f..0000000
--- a/runtime/lib/regexp_jsc.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// This file encapsulates all the interaction with the
-// JSC regular expression library also referred to as pcre
-
-#include "lib/regexp_jsc.h"
-
-#include "platform/assert.h"
-#include "vm/allocation.h"
-#include "vm/exceptions.h"
-#include "vm/globals.h"
-#include "vm/isolate.h"
-#include "third_party/jscre/pcre.h"
-
-namespace dart {
-
-static uint16_t* GetTwoByteData(const String& str) {
-  Zone* zone = Isolate::Current()->current_zone();
-  uint16_t* two_byte_str = zone->Alloc<uint16_t>(str.Length());
-  for (intptr_t i = 0; i < str.Length(); i++) {
-    two_byte_str[i] = str.CharAt(i);
-  }
-  return two_byte_str;
-}
-
-
-static void* JSREMalloc(size_t size) {
-  intptr_t regexp_size = static_cast<intptr_t>(size);
-  ASSERT(regexp_size > 0);
-  const JSRegExp& new_regex = JSRegExp::Handle(JSRegExp::New(size));
-  return new_regex.GetDataStartAddress();
-}
-
-
-static void JSREFree(void* ptr) {
-  USE(ptr);  // Do nothing, memory is garbage collected.
-}
-
-
-static void ThrowExceptionOnError(const String& pattern,
-                                  const char* error_msg) {
-  if (error_msg == NULL) {
-    error_msg = "Unknown regexp compile error. ";
-  }
-  const String& errmsg = String::Handle(String::New(error_msg));
-  const String& message = String::Handle(String::Concat(errmsg, pattern));
-  const Array& args = Array::Handle(Array::New(1));
-  args.SetAt(0, message);
-  Exceptions::ThrowByType(Exceptions::kFormat, args);
-}
-
-
-RawJSRegExp* Jscre::Compile(const String& pattern,
-                            bool multi_line,
-                            bool ignore_case) {
-  // First convert the pattern to UTF16 format as the jscre library expects
-  // strings to be in UTF16 encoding.
-  uint16_t* two_byte_pattern = GetTwoByteData(pattern);
-
-  // A Dart regexp is always global.
-  bool is_global = true;
-  // Parse the flags.
-  jscre::JSRegExpIgnoreCaseOption jscre_ignore_case = ignore_case ?
-      jscre::JSRegExpIgnoreCase : jscre::JSRegExpDoNotIgnoreCase;
-  jscre::JSRegExpMultilineOption jscre_multi_line = multi_line ?
-      jscre::JSRegExpMultiline : jscre::JSRegExpSingleLine;
-
-  // Compile the regex by calling into the jscre library.
-  uint32_t num_bracket_expressions = 0;
-  const char* error_msg = NULL;
-  jscre::JSRegExp* jscregexp = jscre::jsRegExpCompile(two_byte_pattern,
-                                                      pattern.Length(),
-                                                      jscre_ignore_case,
-                                                      jscre_multi_line,
-                                                      &num_bracket_expressions,
-                                                      &error_msg,
-                                                      &JSREMalloc,
-                                                      &JSREFree);
-
-  if (jscregexp == NULL) {
-    // There was an error compiling the regex, Throw an exception.
-    ThrowExceptionOnError(pattern, error_msg);
-    UNREACHABLE();
-    return JSRegExp::null();
-  } else {
-    // Setup the compiled regex object and return it.
-    JSRegExp& regexp =
-        JSRegExp::Handle(JSRegExp::FromDataStartAddress(jscregexp));
-    regexp.set_pattern(pattern);
-    if (jscre_multi_line == jscre::JSRegExpMultiline) {
-      regexp.set_is_multi_line();
-    }
-    if (jscre_ignore_case == jscre::JSRegExpIgnoreCase) {
-      regexp.set_is_ignore_case();
-    }
-    if (is_global) {
-      regexp.set_is_global();
-    }
-    regexp.set_is_complex();  // Always use jscre library.
-    regexp.set_num_bracket_expressions(num_bracket_expressions);
-    return regexp.raw();
-  }
-}
-
-
-RawArray* Jscre::Execute(const JSRegExp& regex,
-                         const String& str,
-                         intptr_t start_index) {
-  // First convert the input str to UTF16 format as the jscre library expects
-  // strings to be in UTF16 encoding.
-  uint16_t* two_byte_str = GetTwoByteData(str);
-
-  // Execute a regex match by calling into the jscre library.
-  jscre::JSRegExp* jscregexp =
-      reinterpret_cast<jscre::JSRegExp*>(regex.GetDataStartAddress());
-  ASSERT(jscregexp != NULL);
-  const Smi& num_bracket_exprs = Smi::Handle(regex.num_bracket_expressions());
-  intptr_t num_bracket_expressions = num_bracket_exprs.Value();
-  Zone* zone = Isolate::Current()->current_zone();
-  // The jscre library rounds the passed in size to a multiple of 3 in order
-  // to reuse the passed in offsets array as a temporary chunk of working
-  // storage during matching, so we just pass in a size which is a multiple
-  // of 3.
-  const int kJscreMultiple = 3;
-  int offsets_length = (num_bracket_expressions + 1) * kJscreMultiple;
-  int* offsets = NULL;
-  offsets = zone->Alloc<int>(offsets_length);
-  int retval = jscre::jsRegExpExecute(jscregexp,
-                                      two_byte_str,
-                                      str.Length(),
-                                      start_index,
-                                      offsets,
-                                      offsets_length);
-
-  // The KJS JavaScript engine returns null (ie, a failed match) when
-  // JSRE's internal match limit is exceeded.  We duplicate that behavior here.
-  if (retval == jscre::JSRegExpErrorNoMatch
-      || retval == jscre::JSRegExpErrorHitLimit) {
-    return Array::null();
-  }
-
-  // Other JSRE errors:
-  if (retval < 0) {
-    const String& pattern = String::Handle(regex.pattern());
-    const int kErrorLength = 256;
-    char error_msg[kErrorLength];
-    OS::SNPrint(error_msg, kErrorLength,
-                "jscre::jsRegExpExecute error : %d", retval);
-    ThrowExceptionOnError(pattern, error_msg);
-    UNREACHABLE();
-    return Array::null();
-  }
-
-  const int kMatchPair = 2;
-  Array& array =
-      Array::Handle(Array::New(kMatchPair * (num_bracket_expressions + 1)));
-  // The matches come in (start, end + 1) pairs for each bracketted expression.
-  Smi& start = Smi::Handle();
-  Smi& end = Smi::Handle();
-  for (intptr_t i = 0;
-       i < (kMatchPair * (num_bracket_expressions + 1));
-       i += kMatchPair) {
-    start = Smi::New(offsets[i]);
-    end = Smi::New(offsets[i + 1]);
-    array.SetAt(i, start);
-    array.SetAt(i+1, end);
-  }
-  return array.raw();
-}
-
-}  // namespace dart
diff --git a/runtime/lib/regexp_jsc.h b/runtime/lib/regexp_jsc.h
deleted file mode 100644
index 2dff024..0000000
--- a/runtime/lib/regexp_jsc.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef LIB_REGEXP_JSC_H_
-#define LIB_REGEXP_JSC_H_
-
-#include "vm/object.h"
-
-
-namespace dart {
-
-class Jscre : public AllStatic {
- public:
-  static RawJSRegExp* Compile(const String& pattern,
-                              bool multi_line,
-                              bool ignore_case);
-  static RawArray* Execute(const JSRegExp& regex,
-                           const String& str,
-                           intptr_t index);
-};
-
-}  // namespace dart
-
-#endif  // LIB_REGEXP_JSC_H_
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index 61065ed..4fb7fff 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -3446,11 +3446,11 @@
     if (byteOffset < 0 || byteOffset + 3 >= length) {
       throw _newRangeError(byteOffset + 3, length);
     }
-    var result = _typedData._getFloat32(_offset + byteOffset);
     if (identical(endian, Endianness.HOST_ENDIAN)) {
-      return result;
+      return _typedData._getFloat32(_offset + byteOffset);
     }
-    return _byteSwapFloat32(result);
+    _convU32[0] = _byteSwap32(_typedData._getUint32(_offset + byteOffset));
+    return _convF32[0];
   }
   void setFloat32(int byteOffset,
                   double value,
@@ -3458,9 +3458,12 @@
     if (byteOffset < 0 || byteOffset + 3 >= length) {
       throw _newRangeError(byteOffset + 3, length);
     }
-    _typedData._setFloat32(_offset + byteOffset,
-        identical(endian, Endianness.HOST_ENDIAN) ? value
-                                                  : _byteSwapFloat32(value));
+    if (identical(endian, Endianness.HOST_ENDIAN)) {
+      _typedData._setFloat32(_offset + byteOffset, value);
+      return;
+    }
+    _convF32[0] = value;
+    _typedData._setUint32(_offset + byteOffset, _byteSwap32(_convU32[0]));
   }
 
   double getFloat64(int byteOffset,
@@ -3468,11 +3471,11 @@
     if (byteOffset < 0 || byteOffset + 7 >= length) {
       throw _newRangeError(byteOffset + 7, length);
     }
-    var result = _typedData._getFloat64(_offset + byteOffset);
     if (identical(endian, Endianness.HOST_ENDIAN)) {
-      return result;
+      return _typedData._getFloat64(_offset + byteOffset);
     }
-    return _byteSwapFloat64(result);
+    _convU64[0] = _byteSwap64(_typedData._getUint64(_offset + byteOffset));
+    return _convF64[0];
   }
   void setFloat64(int byteOffset,
                   double value,
@@ -3480,9 +3483,12 @@
     if (byteOffset < 0 || byteOffset + 7 >= length) {
       throw _newRangeError(byteOffset + 7, length);
     }
-    _typedData._setFloat64(_offset + byteOffset,
-        identical(endian, Endianness.HOST_ENDIAN) ? value
-                                                  : _byteSwapFloat64(value));
+    if (identical(endian, Endianness.HOST_ENDIAN)) {
+      _typedData._setFloat64(_offset + byteOffset, value);
+      return;
+    }
+    _convF64[0] = value;
+    _typedData._setUint64(_offset + byteOffset, _byteSwap64(_convU64[0]));
   }
 
   Float32x4 getFloat32x4(int byteOffset,
@@ -3525,23 +3531,10 @@
 }
 
 final _convU32 = new Uint32List(2);
+final _convU64 = new Uint64List.view(_convU32.buffer);
 final _convF32 = new Float32List.view(_convU32.buffer);
 final _convF64 = new Float64List.view(_convU32.buffer);
 
-double _byteSwapFloat32(double value) {
-  _convF32[0] = value;
-  _convU32[0] = _byteSwap32(_convU32[0]);
-  return _convF32[0];
-}
-
-double _byteSwapFloat64(double value) {
-  _convF64[0] = value;
-  var lo = _convU32[0];
-  _convU32[0] = _byteSwap32(_convU32[1]);
-  _convU32[1] = _byteSwap32(lo);
-  return _convF64[0];
-}
-
 // Top level utility methods.
 int _toInt(int value, int mask) {
   value &= mask;
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index 3add115..c47d2b3 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -186,15 +186,15 @@
       Logger.root.severe('WebSocketVM got empty message');
       return;
     }
-    // Extract serial and response.
+    // Extract serial and result.
     var serial;
-    var response;
+    var result;
     serial = map['id'];
-    response = map['response'];
+    result = map['result'];
     if (serial == null) {
       // Messages without serial numbers are asynchronous events
       // from the vm.
-      postServiceEvent(response, null);
+      postServiceEvent(result, null);
       return;
     }
     // Complete request.
@@ -209,7 +209,7 @@
       Logger.root.info(
           'RESPONSE [${serial}] ${request.method}');
     }
-    request.completer.complete(response);
+    request.completer.complete(result);
   }
 
   // WebSocket message event handler.
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index d06c6e1..090d300 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -67,6 +67,7 @@
   void _onEvent(ServiceEvent event) {
     switch(event.eventType) {
       case ServiceEvent.kIsolateStart:
+      case ServiceEvent.kIsolateUpdate:
       case ServiceEvent.kGraph:
       case ServiceEvent.kBreakpointAdded:
       case ServiceEvent.kBreakpointResolved:
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index c777579..e79f3dc 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -58,10 +58,11 @@
   }
 
   Future<Isolate> getIsolate(Uri uri) {
-    return app.vm.getIsolate(uri.queryParameters['isolateId']).catchError((e) {
-      Logger.root.severe('$path visit error: $e');
-      return e;
-    });
+    return app.vm.getIsolate(uri.queryParameters['isolateId'])
+      .catchError((e, stack) {
+        Logger.root.severe('$path visit error: $e\n$stack');
+        return e;
+      });
   }
 
   bool canVisit(Uri uri) => uri.path == path;
@@ -110,8 +111,8 @@
         ServiceObjectViewElement serviceElement = element;
         serviceElement.object = vm;
       }
-    }).catchError((e) {
-      Logger.root.severe('VMPage visit error: $e');
+    }).catchError((e, stack) {
+      Logger.root.severe('VMPage visit error: $e\n$stack');
     });
   }
 }
@@ -126,8 +127,8 @@
         FlagListElement serviceElement = element;
         serviceElement.flagList = flags;
       }
-    }).catchError((e) {
-      Logger.root.severe('FlagsPage visit error: $e');
+    }).catchError((e, stack) {
+      Logger.root.severe('FlagsPage visit error: $e\n$stack');
     });
   }
 }
@@ -181,6 +182,7 @@
       if (element != null) {
         /// Update the page.
         DebuggerPageElement page = element;
+        page.app = app;
         page.isolate = isolate;
       }
     });
diff --git a/runtime/observatory/lib/src/cli/command.dart b/runtime/observatory/lib/src/cli/command.dart
index 67b21c2..0f57376 100644
--- a/runtime/observatory/lib/src/cli/command.dart
+++ b/runtime/observatory/lib/src/cli/command.dart
@@ -10,8 +10,6 @@
 List<String> _splitLine(String line) {
   line = line.trimLeft();
   var args = [];
-  var codes = line.codeUnits;
-
   int pos = 0;
   while (pos < line.length) {
     int startPos = pos;
@@ -149,11 +147,11 @@
     }
 
     // We have found a set of commands which match all of the args.
-    // Return the completions strings.
+    // Return the completion strings.
     var prefix = _concatArgs(args, args.length - 1);
     var completions =
         commands.map((command) => '${prefix}${command.name} ').toList();
-    if (showAll && matchLen == args.length) {
+    if (matchLen == args.length) {
       // If we are showing all possiblities, also include local
       // completions for the parent command.
       return commands[0]._parent._buildCompletions(args, false)
diff --git a/runtime/observatory/lib/src/debugger/debugger.dart b/runtime/observatory/lib/src/debugger/debugger.dart
index 97a6ff5..b2d5203 100644
--- a/runtime/observatory/lib/src/debugger/debugger.dart
+++ b/runtime/observatory/lib/src/debugger/debugger.dart
@@ -6,6 +6,7 @@
 
 // TODO(turnidge): Move more of ObservatoryDebugger to this class.
 abstract class Debugger {
+  VM get vm;
   Isolate get isolate;
   ServiceMap get stack;
   int get currentFrame;
diff --git a/runtime/observatory/lib/src/debugger/source_location.dart b/runtime/observatory/lib/src/debugger/source_location.dart
index f14d87b..91da581 100644
--- a/runtime/observatory/lib/src/debugger/source_location.dart
+++ b/runtime/observatory/lib/src/debugger/source_location.dart
@@ -187,7 +187,6 @@
   }
 
   static ServiceFunction _getConstructor(Class cls, String name) {
-    var matches = [];
     for (var function in cls.functions) {
       assert(cls.loaded);
       if (name == function.name) {
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index 400bc83..3a3253c 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -77,7 +77,7 @@
             <div class="memberName">implements</div>
             <div class="memberValue">
               <template repeat="{{ interface in cls.interfaces }}">
-                <class-ref ref="{{ interface }}"></class-ref>
+                <instance-ref ref="{{ interface }}"></instance-ref>
               </template>
             </div>
           </div>
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile.dart
index 8a69f90..b4406ac 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:html';
 import 'observatory_element.dart';
-import 'package:logging/logging.dart';
 import 'package:observatory/service.dart';
 import 'package:observatory/app.dart';
 import 'package:observatory/cpu_profile.dart';
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 4a9bdf8..662ebb8 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 import 'dart:html';
 import 'observatory_element.dart';
+import 'package:observatory/app.dart';
 import 'package:observatory/cli.dart';
 import 'package:observatory/debugger.dart';
 import 'package:observatory/service.dart';
@@ -30,9 +31,9 @@
 
   String _nameAndAlias(Command cmd) {
     if (cmd.alias == null) {
-      return cmd.name;
+      return cmd.fullName;
     } else {
-      return '${cmd.name}, ${cmd.alias}';
+      return '${cmd.fullName}, ${cmd.alias}';
     }
   }
 
@@ -51,7 +52,7 @@
           "\nFor more information on a specific command type 'help <command>'\n"
           "\n"
           "Command prefixes are accepted (e.g. 'h' for 'help')\n"
-          "Hit [TAB] to complete a command (try 'i[TAB][TAB]')\n"
+          "Hit [TAB] to complete a command (try 'is[TAB][TAB]')\n"
           "Hit [ENTER] to repeat the last command\n"
           "Use up/down arrow for command history\n");
       return new Future.value(null);
@@ -409,7 +410,7 @@
 
   Future<List<String>> complete(List<String> args) {
     if (args.length != 1) {
-      return new Future.value([]);
+      return new Future.value([args.join('')]);
     }
     // TODO - fix SourceLocation complete
     return new Future.value(SourceLocation.complete(debugger, args[0]));
@@ -493,7 +494,7 @@
 
   Future<List<String>> complete(List<String> args) {
     if (args.length != 1) {
-      return new Future.value([]);
+      return new Future.value([args.join('')]);
     }
     return new Future.value(SourceLocation.complete(debugger, args[0]));
   }
@@ -603,32 +604,12 @@
       'Syntax: info breakpoints\n';
 }
 
-class InfoIsolatesCommand extends DebuggerCommand {
-  InfoIsolatesCommand(Debugger debugger) : super(debugger, 'isolates', []);
-
-  Future run(List<String> args) {
-    for (var isolate in debugger.isolate.vm.isolates) {
-      String current = (isolate == debugger.isolate ? ' *' : '');
-      debugger.console.print(
-          "Isolate ${isolate.id} '${isolate.name}'${current}");
-    }
-    return new Future.value(null);
-  }
-
-  String helpShort = 'List all isolates';
-
-  String helpLong =
-      'List all isolates.\n'
-      '\n'
-      'Syntax: info isolates\n';
-}
-
 class InfoFrameCommand extends DebuggerCommand {
   InfoFrameCommand(Debugger debugger) : super(debugger, 'frame', []);
 
   Future run(List<String> args) {
     if (args.length > 0) {
-      debugger.console.print('info frame expects 1 argument');
+      debugger.console.print('info frame expects no arguments');
       return new Future.value(null);
     }
     debugger.console.print('frame = ${debugger.currentFrame}');
@@ -643,12 +624,131 @@
       'Syntax: info frame\n';
 }
 
+class IsolateCommand extends DebuggerCommand {
+  IsolateCommand(Debugger debugger) : super(debugger, 'isolate', [
+    new IsolateListCommand(debugger),
+    new IsolateNameCommand(debugger),
+  ]) {
+    alias = 'i';
+  }
+
+  Future run(List<String> args) {
+    if (args.length != 1) {
+      debugger.console.print('isolate expects one argument');
+      return new Future.value(null);
+    }
+    var arg = args[0].trim();
+    var num = int.parse(arg, onError:(_) => null);
+
+    var candidate;
+    for (var isolate in debugger.vm.isolates) {
+      if (num != null && num == isolate.number) {
+        candidate = isolate;
+        break;
+      } else if (arg == isolate.name) {
+        if (candidate != null) {
+          debugger.console.print(
+              "Isolate identifier '${arg}' is ambiguous: "
+              'use the isolate number instead');
+          return new Future.value(null);
+        }
+        candidate = isolate;
+      }
+    }
+    if (candidate == null) {
+      debugger.console.print("Invalid isolate identifier '${arg}'");
+    } else {
+      if (candidate == debugger.isolate) {
+        debugger.console.print(
+            "Current isolate is already ${candidate.number} '${candidate.name}'");
+      } else {
+        debugger.console.print(
+            "Switching to isolate ${candidate.number} '${candidate.name}'");
+        debugger.isolate = candidate;
+      }
+    }
+    return new Future.value(null);
+  }
+
+  Future<List<String>> complete(List<String> args) {
+    if (args.length != 1) {
+      return new Future.value([args.join('')]);
+    }
+    var isolates = debugger.vm.isolates.toList();
+    isolates.sort((a, b) => a.startTime.compareTo(b.startTime));
+    var result = [];
+    for (var isolate in isolates) {
+      var str = isolate.number.toString();
+      if (str.startsWith(args[0])) {
+        result.add('$str ');
+      }
+    }
+    for (var isolate in isolates) {
+      if (isolate.name.startsWith(args[0])) {
+        result.add('${isolate.name} ');
+      }
+    }
+    return new Future.value(result);
+  }
+  String helpShort = 'Switch the current isolate';
+
+  String helpLong =
+      'Switch the current isolate.\n'
+      '\n'
+      'Syntax: isolate <number>\n'
+      '        isolate <name>\n';
+}
+
+class IsolateListCommand extends DebuggerCommand {
+  IsolateListCommand(Debugger debugger) : super(debugger, 'list', []);
+
+  Future run(List<String> args) {
+    if (debugger.vm == null) {
+      debugger.console.print(
+          "Internal error: vm has not been set");
+      return new Future.value(null);
+    }
+    var isolates = debugger.vm.isolates.toList();
+    isolates.sort((a, b) => a.startTime.compareTo(b.startTime));
+    for (var isolate in isolates) {
+      String current = (isolate == debugger.isolate ? ' *' : '');
+      debugger.console.print(
+          "Isolate ${isolate.number} '${isolate.name}'${current}");
+    }
+    return new Future.value(null);
+  }
+
+  String helpShort = 'List all isolates';
+
+  String helpLong =
+      'List all isolates.\n'
+      '\n'
+      'Syntax: isolate list\n';
+}
+
+class IsolateNameCommand extends DebuggerCommand {
+  IsolateNameCommand(Debugger debugger) : super(debugger, 'name', []);
+
+  Future run(List<String> args) {
+    if (args.length != 1) {
+      debugger.console.print('isolate name expects one argument');
+      return new Future.value(null);
+    }
+    return debugger.isolate.setName(args[0]);
+  }
+
+  String helpShort = 'Rename an isolate';
+
+  String helpLong =
+      'Rename an isolate.\n'
+      '\n'
+      'Syntax: isolate name <name>\n';
+}
+
 class InfoCommand extends DebuggerCommand {
   InfoCommand(Debugger debugger) : super(debugger, 'info', [
       new InfoBreakpointsCommand(debugger),
-      new InfoIsolatesCommand(debugger),
-      new InfoFrameCommand(debugger),
-  ]);
+      new InfoFrameCommand(debugger)]);
 
   Future run(List<String> args) {
     debugger.console.print("'info' expects a subcommand (see 'help info')");
@@ -689,8 +789,6 @@
   RefreshStackCommand(Debugger debugger) : super(debugger, 'stack', []);
 
   Future run(List<String> args) {
-    Set<Script> scripts = debugger.stackElement.activeScripts();
-    List pending = [];
     return debugger.refreshStack();
   }
 
@@ -724,6 +822,7 @@
 // Tracks the state for an isolate debugging session.
 class ObservatoryDebugger extends Debugger {
   RootCommand cmd;
+  DebuggerPageElement page;
   DebuggerConsoleElement console;
   DebuggerStackElement stackElement;
   ServiceMap stack;
@@ -758,14 +857,17 @@
         new ClearCommand(this),
         new DeleteCommand(this),
         new InfoCommand(this),
+        new IsolateCommand(this),
         new RefreshCommand(this),
     ]);
   }
 
-  void set isolate(Isolate iso) {
+  VM get vm => page.app.vm;
+
+  void updateIsolate(Isolate iso) {
     _isolate = iso;
     if (_isolate != null) {
-      _isolate.reload().then((_) {
+      _isolate.reload().then((response) {
         // TODO(turnidge): Currently the debugger relies on all libs
         // being loaded.  Fix this.
         var pending = [];
@@ -775,26 +877,46 @@
           }
         }
         Future.wait(pending).then((_) {
-          _isolate.vm.events.stream.listen(_onEvent);
+          if (_subscription == null) {
+            _subscription = vm.events.stream.listen(_onEvent);
+          }
           _refreshStack(isolate.pauseEvent).then((_) {
             reportStatus();
           });
         });
       });
+    } else {
+      reportStatus();
     }
   }
+
+  void set isolate(Isolate iso) {
+    // Setting the page's isolate will trigger updateIsolate to be called.
+    //
+    // TODO(turnidge): Rework ownership of the ObservatoryDebugger in another
+    // change.
+    page.isolate = iso;
+  }
   Isolate get isolate => _isolate;
   Isolate _isolate;
+  var _subscription;
 
   void init() {
     console.newline();
     console.printBold("Type 'h' for help");
+    // Wait a bit and if polymer still hasn't set up the isolate,
+    // report this to the user.
+    new Timer(const Duration(seconds:1), () {
+      if (isolate == null) {
+        reportStatus();
+      }
+    });
   }
 
   Future refreshStack() {
     return _refreshStack(isolate.pauseEvent).then((_) {
-        reportStatus();
-      });
+      reportStatus();
+    });
   }
 
   bool isolatePaused() {
@@ -830,7 +952,9 @@
   }
 
   void reportStatus() {
-    if (_isolate.idle) {
+    if (_isolate == null) {
+      console.print('No current isolate');
+    } else if (_isolate.idle) {
       console.print('Isolate is idle');
     } else if (_isolate.running) {
       console.print("Isolate is running (type 'pause' to interrupt)");
@@ -902,13 +1026,30 @@
   }
 
   void _onEvent(ServiceEvent event) {
-    if (event.owner != isolate) {
-      return;
-    }
     switch(event.eventType) {
+      case ServiceEvent.kIsolateStart:
+        {
+          var iso = event.owner;
+          console.print(
+              "Isolate ${iso.number} '${iso.name}' has been created");
+        }
+        break;
+
       case ServiceEvent.kIsolateExit:
-        console.print('Isolate shutdown');
-        isolate = null;
+        {
+          var iso = event.owner;
+          if (iso == isolate) {
+            console.print("The current isolate has exited");
+          } else {
+            console.print(
+                "Isolate ${iso.number} '${iso.name}' has exited");
+          }
+        }
+        break;
+
+      case ServiceEvent.kIsolateUpdate:
+        var iso = event.owner;
+        console.print("Isolate ${iso.number} renamed to '${iso.name}'");
         break;
 
       case ServiceEvent.kPauseStart:
@@ -916,25 +1057,30 @@
       case ServiceEvent.kPauseBreakpoint:
       case ServiceEvent.kPauseInterrupted:
       case ServiceEvent.kPauseException:
-        _refreshStack(event).then((_) {
-          _reportPause(event);
-        });
+        if (event.owner == isolate) {
+          _refreshStack(event).then((_) {
+            _reportPause(event);
+          });
+        }
         break;
 
       case ServiceEvent.kResume:
-        console.print('Continuing...');
+        if (event.owner == isolate) {
+          console.print('Continuing...');
+        }
         break;
 
       case ServiceEvent.kBreakpointAdded:
       case ServiceEvent.kBreakpointResolved:
       case ServiceEvent.kBreakpointRemoved:
-        _reportBreakpointEvent(event);
+        if (event.owner == isolate) {
+          _reportBreakpointEvent(event);
+        }
         break;
 
       case ServiceEvent.kIsolateStart:
       case ServiceEvent.kGraph:
       case ServiceEvent.kGC:
-        // Ignore these events for now.
         break;
 
       default:
@@ -1008,16 +1154,19 @@
 
 @CustomTag('debugger-page')
 class DebuggerPageElement extends ObservatoryElement {
+  @published ObservatoryApplication app;
   @published Isolate isolate;
 
   isolateChanged(oldValue) {
     if (isolate != null) {
-      debugger.isolate = isolate;
+      debugger.updateIsolate(isolate);
     }
   }
   ObservatoryDebugger debugger = new ObservatoryDebugger();
 
-  DebuggerPageElement.created() : super.created();
+  DebuggerPageElement.created() : super.created() {
+    debugger.page = this;
+  }
 
   @override
   void attached() {
@@ -1027,7 +1176,6 @@
     var stackDiv = $['stackDiv'];
     var splitterDiv = $['splitterDiv'];
     var cmdDiv = $['commandDiv'];
-    var consoleDiv = $['consoleDiv'];
 
     int navbarHeight = navbarDiv.clientHeight;
     int splitterHeight = splitterDiv.clientHeight;
diff --git a/runtime/observatory/lib/src/elements/field_view.html b/runtime/observatory/lib/src/elements/field_view.html
index 2a9d728..cad31aa 100644
--- a/runtime/observatory/lib/src/elements/field_view.html
+++ b/runtime/observatory/lib/src/elements/field_view.html
@@ -12,12 +12,9 @@
     <nav-bar>
       <top-nav-menu></top-nav-menu>
       <isolate-nav-menu isolate="{{ field.isolate }}"></isolate-nav-menu>
-      <template if="{{ field.owner.type == 'Class' }}">
-        <!-- TODO(turnidge): Add library nav menu here. -->
-        <class-nav-menu cls="{{ field.owner }}"></class-nav-menu>
-      </template>
-      <template if="{{ field.owner.type == 'Library' }}">
-        <library-nav-menu library="{{ field.owner }}"></library-nav-menu>
+      <library-nav-menu library="{{ field.library }}"></library-nav-menu>
+      <template if="{{ field.dartOwner is ServiceClass }}">
+        <class-nav-menu cls="{{ field.dartOwner }}"></class-nav-menu>
       </template>
       <nav-menu link="{{ makeLink('/inspect', field) }}" anchor="{{ field.name }}" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
@@ -42,12 +39,7 @@
         <div class="memberItem">
           <div class="memberName">owner</div>
           <div class="memberValue">
-            <template if="{{ field.owner.type == 'Class' }}">
-              <class-ref ref="{{ field.owner }}"></class-ref>
-            </template>
-            <template if="{{ field.owner.type != 'Class' }}">
-              <library-ref ref="{{ field.owner }}"></library-ref>
-            </template>
+            <any-service-ref ref="{{ function.dartOwner }}"></any-service-ref>
           </div>
         </div>
         <div class="memberItem">
diff --git a/runtime/observatory/lib/src/elements/function_ref.dart b/runtime/observatory/lib/src/elements/function_ref.dart
index 2e92f60..53920b9 100644
--- a/runtime/observatory/lib/src/elements/function_ref.dart
+++ b/runtime/observatory/lib/src/elements/function_ref.dart
@@ -28,18 +28,17 @@
     }
     if (function.isDart) {
       if (qualified) {
-        // Add class-name or parent-function-name followed by a dot.
-        if ((function.parent == null) && (function.owningClass != null)) {
-          var classRef = new Element.tag('class-ref');
-          classRef.ref = function.owningClass;
-          shadowRoot.children.add(classRef);
-          insertTextSpanIntoShadowRoot('.');
-        } else if (function.parent != null) {
+        if (function.dartOwner is ServiceFunction) {
           var functionRef = new Element.tag('function-ref');
-          functionRef.ref = function.parent;
+          functionRef.ref = function.dartOwner;
           functionRef.qualified = true;
           shadowRoot.children.add(functionRef);
           insertTextSpanIntoShadowRoot('.');
+        } else if (function.dartOwner is Class) {
+          var classRef = new Element.tag('class-ref');
+          classRef.ref = function.dartOwner;
+          shadowRoot.children.add(classRef);
+          insertTextSpanIntoShadowRoot('.');
         }
       }
       insertLinkIntoShadowRoot(name, url, hoverText);
diff --git a/runtime/observatory/lib/src/elements/function_view.html b/runtime/observatory/lib/src/elements/function_view.html
index 519cad8..4b75c5c 100644
--- a/runtime/observatory/lib/src/elements/function_view.html
+++ b/runtime/observatory/lib/src/elements/function_view.html
@@ -14,12 +14,9 @@
     <nav-bar>
       <top-nav-menu></top-nav-menu>
       <isolate-nav-menu isolate="{{ function.isolate }}"></isolate-nav-menu>
-      <template if="{{ function.owningClass != null }}">
-        <!-- TODO(turnidge): Add library nav menu here. -->
-        <class-nav-menu cls="{{ function.owningClass }}"></class-nav-menu>
-      </template>
-      <template if="{{ function.owningLibrary != null }}">
-        <library-nav-menu library="{{ function.owningLibrary }}"></library-nav-menu>
+      <library-nav-menu library="{{ function.library }}"></library-nav-menu>
+      <template if="{{ function.dartOwner is ServiceClass }}">
+        <class-nav-menu cls="{{ function.dartOwner }}"></class-nav-menu>
       </template>
       <nav-menu link="{{ makeLink('/inspect', function) }}" anchor="{{ function.name }}" last="{{ true }}"></nav-menu>
       <nav-refresh callback="{{ refreshCoverage }}" label="Refresh Coverage"></nav-refresh>
@@ -39,23 +36,10 @@
             {{ function.kind.toString() }}
           </div>
         </div>
-        <template if="{{ function.parent != null }}">
-          <div class="memberItem">
-            <div class="memberName">parent function</div>
-            <div class="memberValue">
-              <function-ref ref="{{ function.parent }}"></function-ref>
-            </div>
-          </div>
-        </template>
         <div class="memberItem">
           <div class="memberName">owner</div>
           <div class="memberValue">
-            <template if="{{ function.owningClass != null }}">
-              <class-ref ref="{{ function.owningClass }}"></class-ref>
-            </template>
-            <template if="{{ function.owningLibrary != null }}">
-              <library-ref ref="{{ function.owningLibrary }}"></library-ref>
-            </template>
+            <any-service-ref ref="{{ function.dartOwner }}"></any-service-ref>
           </div>
         </div>
         <div class="memberItem">
diff --git a/runtime/observatory/lib/src/elements/heap_profile.dart b/runtime/observatory/lib/src/elements/heap_profile.dart
index 2cac03f..d826a48 100644
--- a/runtime/observatory/lib/src/elements/heap_profile.dart
+++ b/runtime/observatory/lib/src/elements/heap_profile.dart
@@ -102,13 +102,34 @@
     _subscription.cancel((){});
     super.detached();
   }
-
+  
+  // Keep at most one outstanding auto-refresh RPC.
+  bool refreshAutoPending = false;
+  bool refreshAutoQueued = false;
+  
   void _onEvent(ServiceEvent event) {
     if (autoRefresh && event.eventType == 'GC') {
-      refresh((){});
+      if (!refreshAutoPending) {
+        refreshAuto();
+      } else {
+        // Remember to refresh once more, to ensure latest profile.
+        refreshAutoQueued = true;
+      }
     }
   }
 
+  void refreshAuto() {
+    refreshAutoPending = true;
+    refreshAutoQueued = false;
+    refresh(() {
+      refreshAutoPending = false;
+      // Keep refreshing if at least one GC event was received while waiting.
+      if (refreshAutoQueued) {
+        refreshAuto();
+      }
+    });
+  }
+
   void _updatePieCharts() {
     assert(profile != null);
     _newPieDataTable.clearRows();
diff --git a/runtime/observatory/lib/src/elements/heap_profile.html b/runtime/observatory/lib/src/elements/heap_profile.html
index 460a021..3d0bfec 100644
--- a/runtime/observatory/lib/src/elements/heap_profile.html
+++ b/runtime/observatory/lib/src/elements/heap_profile.html
@@ -57,11 +57,9 @@
     <nav-refresh callback="{{ resetAccumulator }}" label="Reset Accumulator"></nav-refresh>
     <nav-refresh callback="{{ refreshGC }}" label="GC"></nav-refresh>
     <nav-refresh callback="{{ refresh }}"></nav-refresh>
-    <!-- Disabled dartbug.com/22970
     <div class="nav-option">
       <input type="checkbox" checked="{{ autoRefresh }}">Auto-refresh on GC
     </div>
-    -->
     <nav-control></nav-control>
   </nav-bar>
   <div class="content">
diff --git a/runtime/observatory/lib/src/elements/instance_ref.html b/runtime/observatory/lib/src/elements/instance_ref.html
index ab7bb16..2f4fff1 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.html
+++ b/runtime/observatory/lib/src/elements/instance_ref.html
@@ -38,8 +38,7 @@
 
       <template if="{{ ref.isClosure }}">
         <a on-click="{{ goto }}" _href="{{ url }}">
-          <!-- TODO(turnidge): Switch this to fully-qualified function -->
-          {{ ref.closureFunc.name }}
+          {{ ref.closureFunc.qualifiedName }}
         </a>
       </template>
 
diff --git a/runtime/observatory/lib/src/elements/instance_view.html b/runtime/observatory/lib/src/elements/instance_view.html
index b9dbb9b..91fa806 100644
--- a/runtime/observatory/lib/src/elements/instance_view.html
+++ b/runtime/observatory/lib/src/elements/instance_view.html
@@ -46,7 +46,9 @@
           <template if="{{ instance.valueAsString != null }}">
             <div class="memberItem">
               <div class="memberName">value</div>
-              <div class="memberValue">{{ instance.valueAsString }}</div>
+              <div class="memberValue">
+                <pre>{{ instance.valueAsString }}</pre>
+              </div>
             </div>
           </template>
 
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.dart b/runtime/observatory/lib/src/elements/isolate_summary.dart
index cefc373..288a21e 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.dart
+++ b/runtime/observatory/lib/src/elements/isolate_summary.dart
@@ -4,7 +4,6 @@
 
 library isolate_summary_element;
 
-import 'dart:async';
 import 'observatory_element.dart';
 import 'package:observatory/app.dart';
 import 'package:observatory/service.dart';
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index 89ea848..2af908d 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -13,12 +13,15 @@
         <img src="img/isolate_icon.png">
       </div>
       <div class="flex-item-10-percent">
+        {{ isolate.number }}
+      </div>
+      <div class="flex-item-20-percent">
         <isolate-ref ref="{{ isolate }}"></isolate-ref>
       </div>
       <div class="flex-item-10-percent">
         <isolate-run-state isolate="{{ isolate }}"></isolate-run-state>
       </div>
-      <div class="flex-item-60-percent">
+      <div class="flex-item-40-percent">
         <isolate-location isolate="{{ isolate }}"></isolate-location>
         [<a on-click="{{ goto }}" _href="{{ gotoLink('/debugger', isolate) }}">debug</a>]
       </div>
diff --git a/runtime/observatory/lib/src/elements/isolate_view.html b/runtime/observatory/lib/src/elements/isolate_view.html
index 615a855..3bd7845 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.html
+++ b/runtime/observatory/lib/src/elements/isolate_view.html
@@ -80,6 +80,14 @@
         <div class="flex-item-50-percent">
           <div class="memberList">
             <div class="memberItem">
+              <div class="memberName">started at</div>
+              <div class="memberValue">{{ isolate.startTime.toString() }}</div>
+            </div>
+            <div class="memberItem">
+              <div class="memberName">uptime</div>
+              <div class="memberValue">{{ isolate.upTime.toString() }}</div>
+            </div>
+            <div class="memberItem">
               <div class="memberName">root library</div>
               <div class="memberValue">
                 <library-ref ref="{{ isolate.rootLib }}"></library-ref>
@@ -95,7 +103,7 @@
             </div>
             <div class="memberItem">
               <div class="memberName">isolate id</div>
-              <div class="memberValue">{{ isolate.mainPort }}</div>
+              <div class="memberValue">{{ isolate.number }}</div>
             </div>
           </div>
         </div>
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 2acb390..1f57b2a 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -19,17 +19,19 @@
   infoBox.style.border = 'solid black 2px';
   infoBox.style.zIndex = '10';
   infoBox.style.backgroundColor = 'white';
-
+  infoBox.style.cursor = 'auto';
   infoBox.style.display = 'none';  // Initially hidden.
 
   var show = false;
   content.onClick.listen((event) {
     show = !show;
     infoBox.style.display = show ? 'block' : 'none';
+    content.style.backgroundColor = show ? 'white' : '';
   });
 
   // Causes infoBox to be positioned relative to the bottom-left of content.
   content.style.display = 'inline-block';
+  content.style.cursor = 'pointer';
   content.append(infoBox);
 }
 
@@ -54,9 +56,10 @@
 class CallSiteAnnotation extends Annotation {
   CallSite callSite;
 
-  Element row() {
+  Element row([content]) {
     var e = new DivElement();
     e.style.display = "table-row";
+    if (content is String) e.text = content;
     return e;
   }
 
@@ -81,18 +84,22 @@
     e.style.color = "#333";
     e.style.font = "400 14px 'Montserrat', sans-serif";
 
-    var r = row();
-    r.append(cell("Container"));
-    r.append(cell("Count"));
-    r.append(cell("Target"));
-    e.append(r);
-
-    for (var entry in callSite.entries) {
+    if (callSite.entries.isEmpty) {
+      e.append(row('Did not execute'));
+    } else {
       var r = row();
-      r.append(cell(serviceRef(entry.receiverContainer)));
-      r.append(cell(entry.count.toString()));
-      r.append(cell(serviceRef(entry.target)));
+      r.append(cell("Container"));
+      r.append(cell("Count"));
+      r.append(cell("Target"));
       e.append(r);
+
+      for (var entry in callSite.entries) {
+        var r = row();
+        r.append(cell(serviceRef(entry.receiverContainer)));
+        r.append(cell(entry.count.toString()));
+        r.append(cell(serviceRef(entry.target)));
+        e.append(r);
+      }
     }
 
     return e;
diff --git a/runtime/observatory/lib/src/elements/script_view.html b/runtime/observatory/lib/src/elements/script_view.html
index 7e376f7..13802d3 100644
--- a/runtime/observatory/lib/src/elements/script_view.html
+++ b/runtime/observatory/lib/src/elements/script_view.html
@@ -10,7 +10,7 @@
     <top-nav-menu></top-nav-menu>
     <isolate-nav-menu isolate="{{ script.isolate }}">
     </isolate-nav-menu>
-    <nav-menu link="{{ makeLink('/inspect', script.owningLibrary) }}" anchor="{{ script.owningLibrary.name }}"></nav-menu>
+    <library-nav-menu library="{{ script.library }}"></library-nav-menu>
     <nav-menu link="{{ makeLink('/inspect', script) }}" anchor="{{ script.name }}" last="{{ true }}"></nav-menu>
     <nav-refresh callback="{{ refreshCoverage }}" label="Refresh Coverage"></nav-refresh>
     <nav-refresh callback="{{ refresh }}"></nav-refresh>
diff --git a/runtime/observatory/lib/src/elements/vm_view.html b/runtime/observatory/lib/src/elements/vm_view.html
index abf4d58..f1485d8 100644
--- a/runtime/observatory/lib/src/elements/vm_view.html
+++ b/runtime/observatory/lib/src/elements/vm_view.html
@@ -26,8 +26,16 @@
           <div class="memberValue">{{ vm.version }}</div>
         </div>
         <div class="memberItem">
+          <div class="memberName">started at</div>
+          <div class="memberValue">{{ vm.startTime.toString() }}</div>
+        </div>
+        <div class="memberItem">
           <div class="memberName">uptime</div>
-          <div class="memberValue">{{ vm.uptime | formatTime }}</div>
+          <div class="memberValue">{{ vm.upTime.toString() }}</div>
+        </div>
+        <div class="memberItem">
+          <div class="memberName">refreshed at</div>
+          <div class="memberValue">{{ vm.refreshTime.toString() }}</div>
         </div>
         <div class="memberItem">
           <div class="memberName">type checks enabled</div>
@@ -41,10 +49,6 @@
           <div class="memberName">pid</div>
           <div class="memberValue">{{ vm.pid }}</div>
         </div>
-        <div class="memberItem">
-          <div class="memberName">refreshed at</div>
-          <div class="memberValue">{{ vm.lastUpdate }}</div>
-        </div>
         <br>
         <div class="memberItem">
           <div class="memberValue">
@@ -68,4 +72,4 @@
   </template>
 </polymer-element>
 
-<script type="application/dart" src="vm_view.dart"></script>
\ No newline at end of file
+<script type="application/dart" src="vm_view.dart"></script>
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 4a006d2..cc233f9 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -310,7 +310,7 @@
     if (this is! Isolate) {
       params['targetId'] = id;
     }
-    return isolate.invokeRpcNoUpgrade('getCallSiteData', params).then(
+    return isolate.invokeRpcNoUpgrade('_getCallSiteData', params).then(
         (ObservableMap map) {
           var coverage = new ServiceObject._fromMap(isolate, map);
           assert(coverage.type == 'CodeCoverage');
@@ -347,11 +347,13 @@
   @observable String version = 'unknown';
   @observable String targetCPU;
   @observable int architectureBits;
-  @observable double uptime = 0.0;
   @observable bool assertsEnabled = false;
   @observable bool typeChecksEnabled = false;
   @observable String pid = '';
-  @observable DateTime lastUpdate;
+  @observable DateTime startTime;
+  @observable DateTime refreshTime;
+  @observable Duration get upTime =>
+      (new DateTime.now().difference(startTime));
 
   VM() : super._empty(null) {
     name = 'vm';
@@ -367,19 +369,6 @@
   final StreamController<ServiceEvent> events =
       new StreamController.broadcast();
 
-  bool _isIsolateLifecycleEvent(String eventType) {
-    return _isIsolateExitEvent(eventType) ||
-           _isIsolateStartEvent(eventType);
-  }
-
-  bool _isIsolateExitEvent(String eventType) {
-    return (eventType == ServiceEvent.kIsolateExit);
-  }
-
-  bool _isIsolateStartEvent(String eventType) {
-    return (eventType == ServiceEvent.kIsolateStart);
-  }
-
   void postServiceEvent(String response, ByteData data) {
     var map;
     try {
@@ -388,7 +377,7 @@
       if (data != null) {
         map['_data'] = data;
       }
-    } catch (e, st) {
+    } catch (_) {
       Logger.root.severe('Ignoring malformed event response: ${response}');
       return;
     }
@@ -398,98 +387,42 @@
       return;
     }
 
-    var eventType = map['eventType'];
-
-    if (_isIsolateLifecycleEvent(eventType)) {
-      String isolateId = map['isolate']['id'];
-      var event;
-      if (_isIsolateStartEvent(eventType)) {
-        _onIsolateStart(map['isolate']);
-        // By constructing the event *after* adding the isolate to the
-        // isolate cache, the call to getFromMap will use the cached Isolate.
-        event = new ServiceObject._fromMap(this, map);
-      } else {
-        assert(_isIsolateExitEvent(eventType));
-        // By constructing the event *before* removing the isolate from the
-        // isolate cache, the call to getFromMap will use the cached Isolate.
-        event = new ServiceObject._fromMap(this, map);
-        _onIsolateExit(isolateId);
-      }
-      assert(event != null);
+    var eventIsolate = map['isolate'];
+    if (eventIsolate == null) {
+      var event = new ServiceObject._fromMap(vm, map);
       events.add(event);
-      return;
+    } else {
+      // getFromMap creates the Isolate if it hasn't been seen already.
+      var isolate = getFromMap(map['isolate']);
+      var event = new ServiceObject._fromMap(isolate, map);
+      if (event.eventType == ServiceEvent.kIsolateExit) {
+        _removeIsolate(isolate.id);
+      }
+      isolate._onEvent(event);
+      events.add(event);
     }
-
-    // Extract the owning isolate from the event itself.
-    String owningIsolateId = map['isolate']['id'];
-    getIsolate(owningIsolateId).then((owningIsolate) {
-        if (owningIsolate == null) {
-          // TODO(koda): Do we care about GC events in VM isolate?
-          Logger.root.severe('Ignoring event with unknown isolate id: '
-                             '$owningIsolateId');
-          return;
-        }
-        var event = new ServiceObject._fromMap(owningIsolate, map);
-        owningIsolate._onEvent(event);
-        events.add(event);
-    });
   }
 
-  Isolate _onIsolateStart(Map isolateMap) {
-    var isolateId = isolateMap['id'];
-    assert(!_isolateCache.containsKey(isolateId));
-    Isolate isolate = new ServiceObject._fromMap(this, isolateMap);
-    _isolateCache[isolateId] = isolate;
-    notifyPropertyChange(#isolates, true, false);
-    // Eagerly load the isolate.
-    isolate.load().catchError((e) {
-      Logger.root.info('Eagerly loading an isolate failed: $e');
-    });
-    return isolate;
-  }
-
-  void _onIsolateExit(String isolateId) {
+  void _removeIsolate(String isolateId) {
     assert(_isolateCache.containsKey(isolateId));
     _isolateCache.remove(isolateId);
     notifyPropertyChange(#isolates, true, false);
   }
 
-  void _updateIsolatesFromList(List isolateList) {
-    var shutdownIsolates = <String>[];
-    var createdIsolates = <Map>[];
-    var isolateStillExists = <String, bool>{};
+  void _removeDeadIsolates(List newIsolates) {
+    // Build a set of new isolates.
+    var newIsolateSet = new Set();
+    newIsolates.forEach((iso) => newIsolateSet.add(iso.id));
 
-    // Start with the assumption that all isolates are gone.
-    for (var isolateId in _isolateCache.keys) {
-      isolateStillExists[isolateId] = false;
-    }
-
-    // Find created isolates and mark existing isolates as living.
-    for (var isolateMap in isolateList) {
-      var isolateId = isolateMap['id'];
-      if (!_isolateCache.containsKey(isolateId)) {
-        createdIsolates.add(isolateMap);
-      } else {
-        isolateStillExists[isolateId] = true;
-      }
-    }
-
-    // Find shutdown isolates.
-    isolateStillExists.forEach((isolateId, exists) {
-      if (!exists) {
-        shutdownIsolates.add(isolateId);
+    // Remove any old isolates which no longer exist.
+    List toRemove = [];
+    _isolateCache.forEach((id, _) {
+      if (!newIsolateSet.contains(id)) {
+        toRemove.add(id);
       }
     });
-
-    // Process shutdown.
-    for (var isolateId in shutdownIsolates) {
-      _onIsolateExit(isolateId);
-    }
-
-    // Process creation.
-    for (var isolateMap in createdIsolates) {
-      _onIsolateStart(isolateMap);
-    }
+    toRemove.forEach((id) => _removeIsolate(id));
+    notifyPropertyChange(#isolates, true, false);
   }
 
   static final String _isolateIdPrefix = 'isolates/';
@@ -507,11 +440,16 @@
     // Check cache.
     var isolate = _isolateCache[id];
     if (isolate == null) {
-      // We should never see an unknown isolate here.
-      throw new UnimplementedError();
-    }
-    var mapIsRef = _hasRef(map['type']);
-    if (!mapIsRef) {
+      // Add new isolate to the cache.
+      isolate = new ServiceObject._fromMap(this, map);
+      _isolateCache[id] = isolate;
+      notifyPropertyChange(#isolates, true, false);
+
+      // Eagerly load the isolate.
+      isolate.load().catchError((e, stack) {
+        Logger.root.info('Eagerly loading an isolate failed: $e\n$stack');
+      });
+    } else {
       isolate.update(map);
     }
     return isolate;
@@ -624,17 +562,22 @@
     if (mapIsRef) {
       return;
     }
+    // Note that upgrading the collection creates any isolates in the
+    // isolate list which are new.
+    _upgradeCollection(map, vm);
+
     _loaded = true;
     version = map['version'];
     targetCPU = map['targetCPU'];
     architectureBits = map['architectureBits'];
-    uptime = map['uptime'];
-    var dateInMillis = int.parse(map['date']);
-    lastUpdate = new DateTime.fromMillisecondsSinceEpoch(dateInMillis);
-    assertsEnabled = map['assertsEnabled'];
+    var startTimeMillis = map['startTime'];
+    startTime = new DateTime.fromMillisecondsSinceEpoch(startTimeMillis);
+    refreshTime = new DateTime.now();
+    notifyPropertyChange(#upTime, 0, 1);
     pid = map['pid'];
-    typeChecksEnabled = map['typeChecksEnabled'];
-    _updateIsolatesFromList(map['isolates']);
+    assertsEnabled = map['_assertsEnabled'];
+    typeChecksEnabled = map['_typeChecksEnabled'];
+    _removeDeadIsolates(map['isolates']);
   }
 
   // Reload all isolates.
@@ -780,9 +723,12 @@
 class Isolate extends ServiceObjectOwner with Coverage {
   @reflectable VM get vm => owner;
   @reflectable Isolate get isolate => this;
-  @observable ObservableMap counters = new ObservableMap();
+  @observable int number;
+  @observable DateTime startTime;
+  @observable Duration get upTime =>
+      (new DateTime.now().difference(startTime));
 
-  @observable ServiceEvent pauseEvent = null;
+  @observable ObservableMap counters = new ObservableMap();
 
   void _updateRunState() {
     topFrame = (pauseEvent != null ? pauseEvent.topFrame : null);
@@ -796,6 +742,7 @@
     notifyPropertyChange(#idle, 0, 1);
   }
 
+  @observable ServiceEvent pauseEvent = null;
   @observable bool paused = false;
   @observable bool running = false;
   @observable bool idle = false;
@@ -863,13 +810,15 @@
     if (map == null) {
       return null;
     }
+    var mapType = _stripRef(map['type']);
+    if (mapType == 'Isolate') {
+      // There are sometimes isolate refs in ServiceEvents.
+      return vm.getFromMap(map);
+    }
     String mapId = map['id'];
     var obj = (mapId != null) ? _cache[mapId] : null;
     if (obj != null) {
-      var mapIsRef = _hasRef(map['type']);
-      if (!mapIsRef) {
-        obj.update(map);
-      }
+      obj.update(map);
       return obj;
     }
     // Build the object from the map directly.
@@ -917,7 +866,6 @@
 
   @observable String name;
   @observable String vmName;
-  @observable String mainPort;
   @observable ServiceFunction entry;
 
   @observable final Map<String, double> timers =
@@ -953,9 +901,9 @@
   }
 
   void _update(ObservableMap map, bool mapIsRef) {
-    mainPort = map['mainPort'];
     name = map['name'];
     vmName = map['name'];
+    number = int.parse(map['number'], onError:(_) => null);
     if (mapIsRef) {
       return;
     }
@@ -973,7 +921,9 @@
     if (map['entry'] != null) {
       entry = map['entry'];
     }
-
+    var startTimeInMillis = map['startTime'];
+    startTime = new DateTime.fromMillisecondsSinceEpoch(startTimeInMillis);
+    notifyPropertyChange(#upTime, 0, 1);
     var countersMap = map['tagCounters'];
     if (countersMap != null) {
       var names = countersMap['names'];
@@ -1041,21 +991,21 @@
   ObservableMap<int, Breakpoint> breakpoints = new ObservableMap();
 
   void _updateBreakpoints(List newBpts) {
-    // Build a map of new breakpoints.
-    var newBptMap = {};
-    newBpts.forEach((bpt) => (newBptMap[bpt.number] = bpt));
+    // Build a set of new breakpoints.
+    var newBptSet = new Set();
+    newBpts.forEach((bpt) => newBptSet.add(bpt.number));
 
     // Remove any old breakpoints which no longer exist.
     List toRemove = [];
     breakpoints.forEach((key, _) {
-      if (!newBptMap.containsKey(key)) {
+      if (!newBptSet.contains(key)) {
         toRemove.add(key);
       }
     });
     toRemove.forEach((key) => breakpoints.remove(key));
 
     // Add all new breakpoints.
-    breakpoints.addAll(newBptMap);
+    newBpts.forEach((bpt) => (breakpoints[bpt.number] = bpt));
   }
 
   void _addBreakpoint(Breakpoint bpt) {
@@ -1068,13 +1018,17 @@
   }
 
   void _onEvent(ServiceEvent event) {
-    assert(event.eventType != ServiceEvent.kIsolateStart &&
-           event.eventType != ServiceEvent.kIsolateExit);
     switch(event.eventType) {
+      case ServiceEvent.kIsolateStart:
+      case ServiceEvent.kIsolateExit:
+        // Handled elsewhere.
+        break;
+
       case ServiceEvent.kBreakpointAdded:
         _addBreakpoint(event.breakpoint);
         break;
 
+      case ServiceEvent.kIsolateUpdate:
       case ServiceEvent.kBreakpointResolved:
         // Update occurs as side-effect of caching.
         break;
@@ -1145,6 +1099,7 @@
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
         }
+        return result;
       });
   }
 
@@ -1154,6 +1109,7 @@
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
         }
+        return result;
       });
   }
 
@@ -1163,6 +1119,7 @@
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
         }
+        return result;
       });
   }
 
@@ -1172,6 +1129,7 @@
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
         }
+        return result;
       });
   }
 
@@ -1181,9 +1139,17 @@
           // TODO(turnidge): Handle this more gracefully.
           Logger.root.severe(result.message);
         }
+        return result;
       });
   }
 
+  Future setName(String newName) {
+    Map params = {
+      'name': newName,
+    };
+    return invokeRpc('setName', params);
+  }
+
   Future<ServiceMap> getStack() {
     return invokeRpc('getStack', {}).then((result) {
         if (result is DartError) {
@@ -1426,6 +1392,7 @@
   /// The possible 'eventType' 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';
@@ -1455,6 +1422,7 @@
   void _update(ObservableMap map, bool mapIsRef) {
     _loaded = true;
     _upgradeCollection(map, owner);
+    assert(map['isolate'] == null || owner == map['isolate']);
     eventType = map['eventType'];
     name = 'ServiceEvent $eventType';
     vmName = name;
@@ -1663,7 +1631,7 @@
   @reflectable final functions = new ObservableList<ServiceFunction>();
 
   @observable Class superclass;
-  @reflectable final interfaces = new ObservableList<Class>();
+  @reflectable final interfaces = new ObservableList<Instance>();
   @reflectable final subclasses = new ObservableList<Class>();
 
   bool get canCache => true;
@@ -1710,6 +1678,10 @@
     subclasses.addAll(map['subclasses']);
     subclasses.sort(ServiceObject.LexicalSortName);
 
+    interfaces.clear();
+    interfaces.addAll(map['interfaces']);
+    interfaces.sort(ServiceObject.LexicalSortName);
+
     fields.clear();
     fields.addAll(map['fields']);
     fields.sort(ServiceObject.LexicalSortName);
@@ -1850,25 +1822,25 @@
   bool hasDartCode() => isDart() || isStub();
   static FunctionKind fromJSON(String value) {
     switch(value) {
-      case 'kRegularFunction': return kRegularFunction;
-      case 'kClosureFunction': return kClosureFunction;
-      case 'kGetterFunction': return kGetterFunction;
-      case 'kSetterFunction': return kSetterFunction;
-      case 'kConstructor': return kConstructor;
-      case 'kImplicitGetter': return kImplicitGetterFunction;
-      case 'kImplicitSetter': return kImplicitSetterFunction;
-      case 'kImplicitStaticFinalGetter': return kImplicitStaticFinalGetter;
-      case 'kIrregexpFunction': return kIrregexpFunction;
-      case 'kStaticInitializer': return kStaticInitializer;
-      case 'kMethodExtractor': return kMethodExtractor;
-      case 'kNoSuchMethodDispatcher': return kNoSuchMethodDispatcher;
-      case 'kInvokeFieldDispatcher': return kInvokeFieldDispatcher;
+      case 'RegularFunction': return kRegularFunction;
+      case 'ClosureFunction': return kClosureFunction;
+      case 'GetterFunction': return kGetterFunction;
+      case 'SetterFunction': return kSetterFunction;
+      case 'Constructor': return kConstructor;
+      case 'ImplicitGetter': return kImplicitGetterFunction;
+      case 'ImplicitSetter': return kImplicitSetterFunction;
+      case 'ImplicitStaticFinalGetter': return kImplicitStaticFinalGetter;
+      case 'IrregexpFunction': return kIrregexpFunction;
+      case 'StaticInitializer': return kStaticInitializer;
+      case 'MethodExtractor': return kMethodExtractor;
+      case 'NoSuchMethodDispatcher': return kNoSuchMethodDispatcher;
+      case 'InvokeFieldDispatcher': return kInvokeFieldDispatcher;
       case 'Collected': return kCollected;
       case 'Native': return kNative;
       case 'Stub': return kStub;
       case 'Tag': return kTag;
     }
-    print('did not understand $value');
+    Logger.root.severe('Unrecognized function kind: $value');
     throw new FallThroughError();
   }
 
@@ -1893,11 +1865,11 @@
 }
 
 class ServiceFunction extends ServiceObject with Coverage {
-  @observable Class owningClass;
-  @observable Library owningLibrary;
+  // owner is a Library, Class, or ServiceFunction.
+  @observable ServiceObject dartOwner;
+  @observable Library library;
   @observable bool isStatic;
   @observable bool isConst;
-  @observable ServiceFunction parent;
   @observable Script script;
   @observable int tokenPos;
   @observable int endTokenPos;
@@ -1923,17 +1895,23 @@
 
     _upgradeCollection(map, isolate);
 
-    owningClass = map.containsKey('owningClass') ? map['owningClass'] : null;
-    owningLibrary = map.containsKey('owningLibrary') ? map['owningLibrary'] : null;
+    dartOwner = map['owner'];
     kind = FunctionKind.fromJSON(map['kind']);
     isDart = !kind.isSynthetic();
 
-    if (parent == null) {
-      qualifiedName = (owningClass != null) ?
-          "${owningClass.name}.${name}" :
-          name;
+    if (dartOwner is ServiceFunction) {
+      ServiceFunction ownerFunction = dartOwner;
+      library = ownerFunction.library;
+      qualifiedName = "${ownerFunction.qualifiedName}.${name}";
+
+    } else if (dartOwner is Class) {
+      Class ownerClass = dartOwner;
+      library = ownerClass.library;
+      qualifiedName = "${ownerClass.name}.${name}";
+
     } else {
-      qualifiedName = "${parent.qualifiedName}.${name}";
+      library = dartOwner;
+      qualifiedName = name;
     }
 
     if (mapIsRef) {
@@ -1943,22 +1921,23 @@
     _loaded = true;
     isStatic = map['static'];
     isConst = map['const'];
-    parent = map['parent'];
     script = map['script'];
     tokenPos = map['tokenPos'];
     endTokenPos = map['endTokenPos'];
-    code = _convertNull(map['code']);
-    unoptimizedCode = _convertNull(map['unoptimizedCode']);
-    isOptimizable = map['optimizable'];
-    isInlinable = map['inlinable'];
-    deoptimizations = map['deoptimizations'];
-    usageCounter = map['usageCounter'];
+    code = map['code'];
+    isOptimizable = map['_optimizable'];
+    isInlinable = map['_inlinable'];
+    unoptimizedCode = map['_unoptimizedCode'];
+    deoptimizations = map['_deoptimizations'];
+    usageCounter = map['_usageCounter'];
   }
 }
 
 
 class Field extends ServiceObject {
-  @observable var /* Library or Class */ owner;
+  // Library or Class.
+  @observable ServiceObject dartOwner;
+  @observable Library library;
   @observable Instance declaredType;
   @observable bool isStatic;
   @observable bool isFinal;
@@ -1981,27 +1960,35 @@
 
     name = map['name'];
     vmName = (map.containsKey('vmName') ? map['vmName'] : name);
-    owner = map['owner'];
+    dartOwner = map['owner'];
     declaredType = map['declaredType'];
     isStatic = map['static'];
     isFinal = map['final'];
     isConst = map['const'];
     value = map['value'];
 
+    if (dartOwner is Class) {
+      Class ownerClass = dartOwner;
+      library = ownerClass.library;
+
+    } else {
+      library = dartOwner;
+    }
+
     if (mapIsRef) {
       return;
     }
 
-    guardNullable = map['guardNullable'];
-    guardClass = map['guardClass'];
-    guardLength = map['guardLength'];
+    guardNullable = map['_guardNullable'];
+    guardClass = map['_guardClass'];
+    guardLength = map['_guardLength'];
     script = map['script'];
     tokenPos = map['tokenPos'];
 
     _loaded = true;
   }
 
-  String toString() => 'Field(${owner.name}.$name)';
+  String toString() => 'Field(${dartOwner.name}.$name)';
 }
 
 
@@ -2137,7 +2124,7 @@
   @observable String kind;
   @observable int firstTokenPos;
   @observable int lastTokenPos;
-  @observable Library owningLibrary;
+  @observable Library library;
   bool get canCache => true;
   bool get immutable => true;
 
@@ -2171,7 +2158,7 @@
     }
     _parseTokenPosTable(map['tokenPosTable']);
     _processSource(map['source']);
-    owningLibrary = map['owningLibrary'];
+    library = map['library'];
   }
 
   void _parseTokenPosTable(List<List<int>> table) {
@@ -2494,7 +2481,7 @@
     } else if (s == 'Stub') {
       return Stub;
     }
-    print('do not understand code kind $s');
+    Logger.root.severe('Unrecognized code kind: $s');
     throw new FallThroughError();
   }
   static const Collected = const CodeKind._internal('Collected');
@@ -2582,29 +2569,29 @@
   void _update(ObservableMap m, bool mapIsRef) {
     name = m['name'];
     vmName = (m.containsKey('vmName') ? m['vmName'] : name);
-    isOptimized = m['optimized'] != null ? m['optimized'] : false;
+    isOptimized = m['_optimized'];
     kind = CodeKind.fromString(m['kind']);
-    startAddress = int.parse(m['start'], radix:16);
-    endAddress = int.parse(m['end'], radix:16);
-    function = isolate.getFromMap(m['function']);
     if (mapIsRef) {
       return;
     }
     _loaded = true;
-    objectPool = isolate.getFromMap(m['objectPool']);
-    var disassembly = m['disassembly'];
+    startAddress = int.parse(m['_startAddress'], radix:16);
+    endAddress = int.parse(m['_endAddress'], radix:16);
+    function = isolate.getFromMap(m['function']);
+    objectPool = isolate.getFromMap(m['_objectPool']);
+    var disassembly = m['_disassembly'];
     if (disassembly != null) {
       _processDisassembly(disassembly);
     }
-    var descriptors = m['descriptors'];
+    var descriptors = m['_descriptors'];
     if (descriptors != null) {
       descriptors = descriptors['members'];
       _processDescriptors(descriptors);
     }
     hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart);
     inlinedFunctions.clear();
-    var inlinedFunctionsTable = m['inlinedFunctions'];
-    var inlinedIntervals = m['inlinedIntervals'];
+    var inlinedFunctionsTable = m['_inlinedFunctions'];
+    var inlinedIntervals = m['_inlinedIntervals'];
     if (inlinedFunctionsTable != null) {
       // Iterate and upgrade each ServiceFunction.
       for (var i = 0; i < inlinedFunctionsTable.length; i++) {
@@ -2913,14 +2900,6 @@
   }
 }
 
-// Convert any ServiceMaps representing a null instance into an actual null.
-_convertNull(obj) {
-  if (obj.isNull) {
-    return null;
-  }
-  return obj;
-}
-
 // Returns true if [map] is a service map. i.e. it has the following keys:
 // 'id' and a 'type'.
 bool _isServiceMap(ObservableMap m) {
diff --git a/runtime/observatory/observatory.gypi b/runtime/observatory/observatory.gypi
index 46c126c..a53185f 100644
--- a/runtime/observatory/observatory.gypi
+++ b/runtime/observatory/observatory.gypi
@@ -49,132 +49,8 @@
         '../pkg/pkg.gyp:pkg_packages#target',
       ],
       'toolsets': ['host'],
-      'sources': [
-        'lib/app.dart',
-        'lib/cpu_profile.dart',
-        'lib/dominator_tree.dart',
-        'lib/elements.dart',
-        'lib/object_graph.dart',
-        'lib/service_common.dart',
-        'lib/service_io.dart',
-        'lib/service_html.dart',
-        'lib/src/app/application.dart',
-        'lib/src/app/chart.dart',
-        'lib/src/app/location_manager.dart',
-        'lib/src/app/page.dart',
-        'lib/src/app/settings.dart',
-        'lib/src/app/target_manager.dart',
-        'lib/src/app/view_model.dart',
-        'lib/src/cpu_profile/cpu_profile.dart',
-        'lib/src/elements/action_link.dart',
-        'lib/src/elements/action_link.html',
-        'lib/src/elements/class_ref.dart',
-        'lib/src/elements/class_ref.html',
-        'lib/src/elements/class_tree.dart',
-        'lib/src/elements/class_tree.html',
-        'lib/src/elements/class_view.dart',
-        'lib/src/elements/class_view.html',
-        'lib/src/elements/code_ref.dart',
-        'lib/src/elements/code_ref.html',
-        'lib/src/elements/code_view.dart',
-        'lib/src/elements/code_view.html',
-        'lib/src/elements/context_ref.dart',
-        'lib/src/elements/context_ref.html',
-        'lib/src/elements/context_view.dart',
-        'lib/src/elements/context_view.html',
-        'lib/src/elements/cpu_profile.dart',
-        'lib/src/elements/cpu_profile.html',
-        'lib/src/elements/curly_block.dart',
-        'lib/src/elements/curly_block.html',
-        'lib/src/elements/debugger.dart',
-        'lib/src/elements/debugger.html',
-        'lib/src/elements/error_ref.dart',
-        'lib/src/elements/error_ref.html',
-        'lib/src/elements/error_view.dart',
-        'lib/src/elements/error_view.html',
-        'lib/src/elements/eval_box.dart',
-        'lib/src/elements/eval_box.html',
-        'lib/src/elements/eval_link.dart',
-        'lib/src/elements/eval_link.html',
-        'lib/src/elements/field_ref.dart',
-        'lib/src/elements/field_ref.html',
-        'lib/src/elements/field_view.dart',
-        'lib/src/elements/field_view.html',
-        'lib/src/elements/flag_list.dart',
-        'lib/src/elements/flag_list.html',
-        'lib/src/elements/function_ref.dart',
-        'lib/src/elements/function_ref.html',
-        'lib/src/elements/function_view.dart',
-        'lib/src/elements/function_view.html',
-        'lib/src/elements/general_error.dart',
-        'lib/src/elements/general_error.html',
-        'lib/src/elements/heap_map.dart',
-        'lib/src/elements/heap_map.html',
-        'lib/src/elements/heap_profile.dart',
-        'lib/src/elements/heap_profile.html',
-        'lib/src/elements/inbound_reference.dart',
-        'lib/src/elements/inbound_reference.html',
-        'lib/src/elements/instance_ref.dart',
-        'lib/src/elements/instance_ref.html',
-        'lib/src/elements/instance_view.dart',
-        'lib/src/elements/instance_view.html',
-        'lib/src/elements/io_view.dart',
-        'lib/src/elements/io_view.html',
-        'lib/src/elements/isolate_ref.dart',
-        'lib/src/elements/isolate_ref.html',
-        'lib/src/elements/isolate_summary.dart',
-        'lib/src/elements/isolate_summary.html',
-        'lib/src/elements/isolate_view.dart',
-        'lib/src/elements/isolate_view.html',
-        'lib/src/elements/json_view.dart',
-        'lib/src/elements/json_view.html',
-        'lib/src/elements/library_ref.dart',
-        'lib/src/elements/library_ref.html',
-        'lib/src/elements/library_view.dart',
-        'lib/src/elements/library_view.html',
-        'lib/src/elements/metrics.dart',
-        'lib/src/elements/metrics.html',
-        'lib/src/elements/nav_bar.dart',
-        'lib/src/elements/nav_bar.html',
-        'lib/src/elements/object_common.dart',
-        'lib/src/elements/object_common.html',
-        'lib/src/elements/object_view.dart',
-        'lib/src/elements/object_view.html',
-        'lib/src/elements/observatory_application.dart',
-        'lib/src/elements/observatory_application.html',
-        'lib/src/elements/observatory_element.dart',
-        'lib/src/elements/observatory_element.html',
-        'lib/src/elements/script_inset.dart',
-        'lib/src/elements/script_inset.html',
-        'lib/src/elements/script_ref.dart',
-        'lib/src/elements/script_ref.html',
-        'lib/src/elements/script_view.dart',
-        'lib/src/elements/script_view.html',
-        'lib/src/elements/service_error_view.dart',
-        'lib/src/elements/service_error_view.html',
-        'lib/src/elements/service_exception_view.dart',
-        'lib/src/elements/service_exception_view.html',
-        'lib/src/elements/service_ref.dart',
-        'lib/src/elements/service_ref.html',
-        'lib/src/elements/service_view.dart',
-        'lib/src/elements/service_view.html',
-        'lib/src/elements/sliding_checkbox.dart',
-        'lib/src/elements/sliding_checkbox.html',
-        'lib/src/elements/vm_connect.dart',
-        'lib/src/elements/vm_connect.html',
-        'lib/src/elements/vm_ref.dart',
-        'lib/src/elements/vm_ref.html',
-        'lib/src/elements/vm_view.dart',
-        'lib/src/elements/vm_view.html',
-        'lib/src/elements/css/shared.css',
-        'lib/src/elements/img/chromium_icon.png',
-        'lib/src/elements/img/dart_icon.png',
-        'lib/src/elements/img/isolate_icon.png',
-        'lib/src/service/object.dart',
-        'lib/tracer.dart',
-        'lib/utils.dart',
-        'web/index.html',
-        'web/main.dart',
+      'includes': [
+        'observatory_sources.gypi',
       ],
       'actions': [
         {
diff --git a/runtime/observatory/observatory.status b/runtime/observatory/observatory.status
deleted file mode 100644
index e7bb129..0000000
--- a/runtime/observatory/observatory.status
+++ /dev/null
@@ -1,11 +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.
-
-[ $compiler == dart2dart ]
-# The transformations of dart2dart are not guaranteed to preserve the
-# state/properties of the VM that the Observatory tests are inspecting.
-observatory/test/*: Skip
-
-[ $browser ]
-observatory/test/*: SkipByDesign # Uses dart:io
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
new file mode 100644
index 0000000..d16cbd8
--- /dev/null
+++ b/runtime/observatory/observatory_sources.gypi
@@ -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.
+
+# This file contains all dart, css, and html sources for Observatory.
+{
+  'sources': [
+    'lib/app.dart',
+    'lib/cli.dart',
+    'lib/cpu_profile.dart',
+    'lib/debugger.dart',
+    'lib/dominator_tree.dart',
+    'lib/elements.dart',
+    'lib/elements.html',
+    'lib/object_graph.dart',
+    'lib/service.dart',
+    'lib/service_common.dart',
+    'lib/service_io.dart',
+    'lib/service_html.dart',
+    'lib/src/app/application.dart',
+    'lib/src/app/chart.dart',
+    'lib/src/app/location_manager.dart',
+    'lib/src/app/page.dart',
+    'lib/src/app/settings.dart',
+    'lib/src/app/target_manager.dart',
+    'lib/src/app/view_model.dart',
+    'lib/src/cli/command.dart',
+    'lib/src/cpu_profile/cpu_profile.dart',
+    'lib/src/debugger/debugger.dart',
+    'lib/src/debugger/source_location.dart',
+    'lib/src/elements/action_link.dart',
+    'lib/src/elements/action_link.html',
+    'lib/src/elements/class_ref.dart',
+    'lib/src/elements/class_ref.html',
+    'lib/src/elements/class_tree.dart',
+    'lib/src/elements/class_tree.html',
+    'lib/src/elements/class_view.dart',
+    'lib/src/elements/class_view.html',
+    'lib/src/elements/code_ref.dart',
+    'lib/src/elements/code_ref.html',
+    'lib/src/elements/code_view.dart',
+    'lib/src/elements/code_view.html',
+    'lib/src/elements/context_ref.dart',
+    'lib/src/elements/context_ref.html',
+    'lib/src/elements/context_view.dart',
+    'lib/src/elements/context_view.html',
+    'lib/src/elements/cpu_profile.dart',
+    'lib/src/elements/cpu_profile.html',
+    'lib/src/elements/curly_block.dart',
+    'lib/src/elements/curly_block.html',
+    'lib/src/elements/debugger.dart',
+    'lib/src/elements/debugger.html',
+    'lib/src/elements/error_ref.dart',
+    'lib/src/elements/error_ref.html',
+    'lib/src/elements/error_view.dart',
+    'lib/src/elements/error_view.html',
+    'lib/src/elements/eval_box.dart',
+    'lib/src/elements/eval_box.html',
+    'lib/src/elements/eval_link.dart',
+    'lib/src/elements/eval_link.html',
+    'lib/src/elements/field_ref.dart',
+    'lib/src/elements/field_ref.html',
+    'lib/src/elements/field_view.dart',
+    'lib/src/elements/field_view.html',
+    'lib/src/elements/flag_list.dart',
+    'lib/src/elements/flag_list.html',
+    'lib/src/elements/function_ref.dart',
+    'lib/src/elements/function_ref.html',
+    'lib/src/elements/function_view.dart',
+    'lib/src/elements/function_view.html',
+    'lib/src/elements/general_error.dart',
+    'lib/src/elements/general_error.html',
+    'lib/src/elements/heap_map.dart',
+    'lib/src/elements/heap_map.html',
+    'lib/src/elements/heap_profile.dart',
+    'lib/src/elements/heap_profile.html',
+    'lib/src/elements/inbound_reference.dart',
+    'lib/src/elements/inbound_reference.html',
+    'lib/src/elements/instance_ref.dart',
+    'lib/src/elements/instance_ref.html',
+    'lib/src/elements/instance_view.dart',
+    'lib/src/elements/instance_view.html',
+    'lib/src/elements/io_view.dart',
+    'lib/src/elements/io_view.html',
+    'lib/src/elements/isolate_ref.dart',
+    'lib/src/elements/isolate_ref.html',
+    'lib/src/elements/isolate_summary.dart',
+    'lib/src/elements/isolate_summary.html',
+    'lib/src/elements/isolate_view.dart',
+    'lib/src/elements/isolate_view.html',
+    'lib/src/elements/json_view.dart',
+    'lib/src/elements/json_view.html',
+    'lib/src/elements/library_ref.dart',
+    'lib/src/elements/library_ref.html',
+    'lib/src/elements/library_view.dart',
+    'lib/src/elements/library_view.html',
+    'lib/src/elements/metrics.dart',
+    'lib/src/elements/metrics.html',
+    'lib/src/elements/nav_bar.dart',
+    'lib/src/elements/nav_bar.html',
+    'lib/src/elements/object_common.dart',
+    'lib/src/elements/object_common.html',
+    'lib/src/elements/object_view.dart',
+    'lib/src/elements/object_view.html',
+    'lib/src/elements/observatory_application.dart',
+    'lib/src/elements/observatory_application.html',
+    'lib/src/elements/observatory_element.dart',
+    'lib/src/elements/observatory_element.html',
+    'lib/src/elements/script_inset.dart',
+    'lib/src/elements/script_inset.html',
+    'lib/src/elements/script_ref.dart',
+    'lib/src/elements/script_ref.html',
+    'lib/src/elements/script_view.dart',
+    'lib/src/elements/script_view.html',
+    'lib/src/elements/service_error_view.dart',
+    'lib/src/elements/service_error_view.html',
+    'lib/src/elements/service_exception_view.dart',
+    'lib/src/elements/service_exception_view.html',
+    'lib/src/elements/service_ref.dart',
+    'lib/src/elements/service_ref.html',
+    'lib/src/elements/service_view.dart',
+    'lib/src/elements/service_view.html',
+    'lib/src/elements/sliding_checkbox.dart',
+    'lib/src/elements/sliding_checkbox.html',
+    'lib/src/elements/vm_connect.dart',
+    'lib/src/elements/vm_connect.html',
+    'lib/src/elements/vm_ref.dart',
+    'lib/src/elements/vm_ref.html',
+    'lib/src/elements/vm_view.dart',
+    'lib/src/elements/vm_view.html',
+    'lib/src/elements/css/shared.css',
+    'lib/src/elements/img/chromium_icon.png',
+    'lib/src/elements/img/dart_icon.png',
+    'lib/src/elements/img/isolate_icon.png',
+    'lib/src/service/object.dart',
+    'lib/tracer.dart',
+    'lib/utils.dart',
+    'web/index.html',
+    'web/main.dart',
+    'web/favicon.ico',
+  ],
+}
\ No newline at end of file
diff --git a/runtime/observatory/test/vm_test.dart b/runtime/observatory/test/vm_test.dart
deleted file mode 100644
index 86fa089..0000000
--- a/runtime/observatory/test/vm_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-import 'package:observatory/service_io.dart';
-import 'package:unittest/unittest.dart';
-import 'test_helper.dart';
-
-var tests = [
-
-(Isolate isolate) {
-  VM vm = isolate.owner;
-  expect(vm.targetCPU, isNotNull);
-  expect(vm.architectureBits == 32 ||
-         vm.architectureBits == 64, isTrue);
-},
-
-];
-
-main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory/test/allocations_test.dart b/runtime/observatory/tests/service/allocations_test.dart
similarity index 91%
rename from runtime/observatory/test/allocations_test.dart
rename to runtime/observatory/tests/service/allocations_test.dart
index 959276d..4242afc 100644
--- a/runtime/observatory/test/allocations_test.dart
+++ b/runtime/observatory/tests/service/allocations_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 library allocations_test;
 
diff --git a/runtime/observatory/test/async_generator_breakpoint_test.dart b/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
similarity index 76%
rename from runtime/observatory/test/async_generator_breakpoint_test.dart
rename to runtime/observatory/tests/service/async_generator_breakpoint_test.dart
index 5e8d802..91141fa 100644
--- a/runtime/observatory/test/async_generator_breakpoint_test.dart
+++ b/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
@@ -1,24 +1,22 @@
 // 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=--verbose-debug
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked --verbose-debug
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
-import 'dart:async';
 
-printSync() {  // Line 12
+printSync() {  // Line 10
   print('sync');
 }
-printAsync() async {  // Line 15
+printAsync() async {  // Line 13
   print('async');
 }
-printAsyncStar() async* {  // Line 18
+printAsyncStar() async* {  // Line 16
   print('async*');
 }
-printSyncStar() sync* {  // Line 21
+printSyncStar() sync* {  // Line 19
   print('sync*');
 }
 
@@ -36,7 +34,7 @@
   var stream = printAsyncStar();
   var iterator = printSyncStar();
 
-  print('middle');  // Line 39.
+  print('middle');  // Line 37.
 
   future.then((v) => print(v));
   stream.toList();
@@ -47,26 +45,27 @@
   await isolate.rootLib.load();
   var script = isolate.rootLib.scripts[0];
 
-  var bp1 = await isolate.addBreakpoint(script, 12);
+  var bp1 = await isolate.addBreakpoint(script, 10);
   expect(bp1, isNotNull);
   expect(bp1 is Breakpoint, isTrue);
-  var bp2 = await isolate.addBreakpoint(script, 15);
+  var bp2 = await isolate.addBreakpoint(script, 13);
   expect(bp2, isNotNull);
   expect(bp2 is Breakpoint, isTrue);
-  var bp3 = await isolate.addBreakpoint(script, 18);
+  var bp3 = await isolate.addBreakpoint(script, 16);
   expect(bp3, isNotNull);
   expect(bp3 is Breakpoint, isTrue);
-  var bp4 = await isolate.addBreakpoint(script, 21);
+  var bp4 = await isolate.addBreakpoint(script, 19);
   expect(bp4, isNotNull);
   expect(bp4 is Breakpoint, isTrue);
-  var bp5 = await isolate.addBreakpoint(script, 39);
+  var bp5 = await isolate.addBreakpoint(script, 37);
+  print("BP5 - $bp5");
   expect(bp5, isNotNull);
   expect(bp5 is Breakpoint, isTrue);
 
   var hits = [];
 
   isolate.eval(isolate.rootLib, 'testerReady = true;')
-      .then((ServiceObject result) {
+      .then((Instance result) {
         expect(result.valueAsString, equals('true'));
       });
 
diff --git a/runtime/observatory/test/bad_web_socket_address_test.dart b/runtime/observatory/tests/service/bad_web_socket_address_test.dart
similarity index 87%
rename from runtime/observatory/test/bad_web_socket_address_test.dart
rename to runtime/observatory/tests/service/bad_web_socket_address_test.dart
index 65de6cf..06ba878 100644
--- a/runtime/observatory/test/bad_web_socket_address_test.dart
+++ b/runtime/observatory/tests/service/bad_web_socket_address_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import "package:observatory/service_io.dart";
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/test/caching_test.dart b/runtime/observatory/tests/service/caching_test.dart
similarity index 92%
rename from runtime/observatory/test/caching_test.dart
rename to runtime/observatory/tests/service/caching_test.dart
index dacfb18..68cb158 100644
--- a/runtime/observatory/test/caching_test.dart
+++ b/runtime/observatory/tests/service/caching_test.dart
@@ -1,6 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 // If caching is working properly, the coverage data will go into the same
 // Script object from which we requested coverage data, instead of a new
@@ -11,7 +12,6 @@
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
-import 'dart:async';
 
 script() {
   print("This executed");
diff --git a/runtime/observatory/test/call_site_data_test.dart b/runtime/observatory/tests/service/call_site_data_test.dart
similarity index 91%
rename from runtime/observatory/test/call_site_data_test.dart
rename to runtime/observatory/tests/service/call_site_data_test.dart
index 366c721..017bf98 100644
--- a/runtime/observatory/test/call_site_data_test.dart
+++ b/runtime/observatory/tests/service/call_site_data_test.dart
@@ -1,13 +1,13 @@
 // 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 --checked
 
 library call_site_data_test;
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
-import 'dart:async';
 
 class A { foo() => 'A'; }
 class B { foo() => 'B'; }
@@ -88,7 +88,7 @@
   Library lib = await isolate.rootLib.load();
   ServiceFunction func =
      lib.functions.singleWhere((f) => f.name == 'monomorphic');
-  Map response = await isolate.invokeRpcNoUpgrade('getCallSiteData',
+  Map response = await isolate.invokeRpcNoUpgrade('_getCallSiteData',
                                                   { 'targetId': func.id });
   expect(response['type'], equals('CodeCoverage'));
   Map callSite = response['coverage'].single['callSites'].single;
@@ -101,7 +101,7 @@
   Library lib = await isolate.rootLib.load();
   ServiceFunction func =
      lib.functions.singleWhere((f) => f.name == 'polymorphic');
-  Map response = await isolate.invokeRpcNoUpgrade('getCallSiteData',
+  Map response = await isolate.invokeRpcNoUpgrade('_getCallSiteData',
                                                   { 'targetId': func.id });
   expect(response['type'], equals('CodeCoverage'));
   Map callSite = response['coverage'].single['callSites'].single;
@@ -114,7 +114,7 @@
   Library lib = await isolate.rootLib.load();
   ServiceFunction func =
      lib.functions.singleWhere((f) => f.name == 'megamorphic');
-  Map response = await isolate.invokeRpcNoUpgrade('getCallSiteData',
+  Map response = await isolate.invokeRpcNoUpgrade('_getCallSiteData',
                                                   { 'targetId': func.id });
   expect(response['type'], equals('CodeCoverage'));
   Map callSite = response['coverage'].single['callSites'].single;
@@ -128,7 +128,7 @@
   Library lib = await isolate.rootLib.load();
   ServiceFunction func =
      lib.functions.singleWhere((f) => f.name == 'staticCall');
-  Map response = await isolate.invokeRpcNoUpgrade('getCallSiteData',
+  Map response = await isolate.invokeRpcNoUpgrade('_getCallSiteData',
                                                   { 'targetId': func.id });
   expect(response['type'], equals('CodeCoverage'));
   Map callSite = response['coverage'].single['callSites'].single;
@@ -141,7 +141,7 @@
   Library lib = await isolate.rootLib.load();
   ServiceFunction func =
      lib.functions.singleWhere((f) => f.name == 'constructorCall');
-  Map response = await isolate.invokeRpcNoUpgrade('getCallSiteData',
+  Map response = await isolate.invokeRpcNoUpgrade('_getCallSiteData',
                                                   { 'targetId': func.id });
   expect(response['type'], equals('CodeCoverage'));
   Map callSite = response['coverage'].single['callSites'].single;
@@ -154,7 +154,7 @@
   Library lib = await isolate.rootLib.load();
   ServiceFunction func =
      lib.functions.singleWhere((f) => f.name == 'topLevelCall');
-  Map response = await isolate.invokeRpcNoUpgrade('getCallSiteData',
+  Map response = await isolate.invokeRpcNoUpgrade('_getCallSiteData',
                                                   { 'targetId': func.id });
   expect(response['type'], equals('CodeCoverage'));
   Map callSite = response['coverage'].single['callSites'].single;
@@ -167,7 +167,7 @@
   Library lib = await isolate.rootLib.load();
   Class cls = await lib.classes.singleWhere((f) => f.name == 'Sub').load();
   ServiceFunction func = cls.functions.singleWhere((f) => f.name == 'bar');
-  Map response = await isolate.invokeRpcNoUpgrade('getCallSiteData',
+  Map response = await isolate.invokeRpcNoUpgrade('_getCallSiteData',
                                                   { 'targetId': func.id });
   expect(response['type'], equals('CodeCoverage'));
   Map callSite = response['coverage'].single['callSites'].single;
diff --git a/runtime/observatory/test/classes_test.dart b/runtime/observatory/tests/service/classes_test.dart
similarity index 82%
rename from runtime/observatory/test/classes_test.dart
rename to runtime/observatory/tests/service/classes_test.dart
index 85b64bb..9e8e286 100644
--- a/runtime/observatory/test/classes_test.dart
+++ b/runtime/observatory/tests/service/classes_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -15,7 +16,7 @@
 
 (Isolate isolate) =>
   isolate.getObject('classes/62').then((Class c) {
-    expect(c.name, equals('_List'));
+    expect(c.name, equals('_ImmutableList'));
     expect(c.vmCid, equals(62));
 }),
 
diff --git a/runtime/observatory/test/code_test.dart b/runtime/observatory/tests/service/code_test.dart
similarity index 96%
rename from runtime/observatory/test/code_test.dart
rename to runtime/observatory/tests/service/code_test.dart
index 16806ee..b91972c 100644
--- a/runtime/observatory/test/code_test.dart
+++ b/runtime/observatory/tests/service/code_test.dart
@@ -1,6 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -33,7 +34,6 @@
   return isolate.rootLib.load().then((_) {
       // Set up a listener to wait for breakpoint events.
       Completer completer = new Completer();
-      List events = [];
       isolate.vm.events.stream.listen((ServiceEvent event) {
         if (event.eventType == ServiceEvent.kPauseBreakpoint) {
           print('Breakpoint reached');
diff --git a/runtime/observatory/test/command_test.dart b/runtime/observatory/tests/service/command_test.dart
similarity index 98%
rename from runtime/observatory/test/command_test.dart
rename to runtime/observatory/tests/service/command_test.dart
index 260684e..a52f1a1 100644
--- a/runtime/observatory/test/command_test.dart
+++ b/runtime/observatory/tests/service/command_test.dart
@@ -1,6 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'dart:async';
 
@@ -63,7 +64,7 @@
   cmd.completeCommand('alpha').then((result) {
     expect(result, equals(['alpha ']));
   });
-                      
+
   // Extra space, no subcommands.
   cmd.completeCommand('alpha ').then((result) {
     expect(result, equals(['alpha ']));
@@ -168,7 +169,7 @@
           new TestCommand(out, 'alpha', [
               new TestCommand(out, 'beta', []),
               new TestCommand(out, 'gamma', [])])]);
-      
+
   cmd.runCommand('a b').then(expectAsync((_) {
       expect(out.toString(), equals('executing beta([])\n'));
       out.clear();
diff --git a/runtime/observatory/test/contexts_test.dart b/runtime/observatory/tests/service/contexts_test.dart
similarity index 82%
rename from runtime/observatory/test/contexts_test.dart
rename to runtime/observatory/tests/service/contexts_test.dart
index dc0f6e9..7928a74 100644
--- a/runtime/observatory/test/contexts_test.dart
+++ b/runtime/observatory/tests/service/contexts_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 library inbound_references_test;
 
@@ -72,7 +73,11 @@
       return block.closureCtxt.load().then((Context ctxt) {
         expect(ctxt.variables.single['value'].isString, isTrue);
         expect(ctxt.variables.single['value'].valueAsString, equals('I could be copied into the block'));
-        expect(block.closureCtxt.parentContext.isNull, isTrue);
+        expect(ctxt.parentContext.isContext, isTrue);
+        expect(ctxt.parentContext.length, equals(0));
+        return ctxt.parentContext.load().then((Context outerCtxt) {
+          expect(outerCtxt.parentContext.isNull, isTrue);
+        });
       });
     });
   }),
@@ -87,7 +92,11 @@
       return block.closureCtxt.load().then((ctxt) {
         expect(ctxt.variables.single['value'].isInt, isTrue);
         expect(ctxt.variables.single['value'].valueAsString, equals('43'));
-        expect(ctxt.parentContext.isNull, isTrue);
+        expect(ctxt.parentContext.isContext, isTrue);
+        expect(ctxt.parentContext.length, equals(0));
+        return ctxt.parentContext.load().then((Context outerCtxt) {
+          expect(outerCtxt.parentContext.isNull, isTrue);
+        });
       });
     });
   }),
@@ -107,7 +116,11 @@
         return ctxt.parentContext.load().then((Context outerCtxt) {
           expect(outerCtxt.variables.single['value'].isInt, isTrue);
           expect(outerCtxt.variables.single['value'].valueAsString, equals('421'));
-          expect(outerCtxt.parentContext.isNull, isTrue);
+          expect(outerCtxt.parentContext.isContext, isTrue);
+          expect(outerCtxt.parentContext.length, equals(0));
+          return outerCtxt.parentContext.load().then((Context outerCtxt2) {
+            expect(outerCtxt2.parentContext.isNull, isTrue);
+          });
         });
       });
     });
diff --git a/runtime/observatory/test/coverage_test.dart b/runtime/observatory/tests/service/coverage_test.dart
similarity index 84%
rename from runtime/observatory/test/coverage_test.dart
rename to runtime/observatory/tests/service/coverage_test.dart
index 207b67d..db9db76 100644
--- a/runtime/observatory/test/coverage_test.dart
+++ b/runtime/observatory/tests/service/coverage_test.dart
@@ -1,6 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -56,7 +57,6 @@
   return isolate.rootLib.load().then((_) {
       // Set up a listener to wait for breakpoint events.
       Completer completer = new Completer();
-      List events = [];
       isolate.vm.events.stream.listen((ServiceEvent event) {
         if (event.eventType == ServiceEvent.kPauseBreakpoint) {
           print('Breakpoint reached');
@@ -83,12 +83,13 @@
       // Make sure we are in the right place.
       expect(stack.type, equals('Stack'));
       expect(stack['frames'].length, greaterThanOrEqualTo(2));
-      expect(stack['frames'][0]['function'].owningClass.name, equals('MyClass'));
+      expect(stack['frames'][0]['function'].name, equals('myFunction'));
+      expect(stack['frames'][0]['function'].dartOwner.name, equals('MyClass'));
 
       var lib = isolate.rootLib;
       var func = stack['frames'][0]['function'];
       expect(func.name, equals('myFunction'));
-      var cls = stack['frames'][0]['function'].owningClass;
+      var cls = stack['frames'][0]['function'].dartOwner;
       expect(cls.name, equals('MyClass'));
 
       List tests = [];
@@ -99,7 +100,7 @@
                     expect(coverage['type'], equals('CodeCoverage'));
                     expect(coverage['coverage'].length, equals(1));
                     expect(normalize(coverage['coverage'][0]['hits']),
-                           equals([14, 1, 15, 1, 16, 0, 18, 1]));
+                           equals([15, 1, 16, 1, 17, 0, 19, 1]));
                 }));
       // Class
       tests.add(isolate.invokeRpcNoUpgrade('getCoverage',
@@ -108,8 +109,8 @@
                     expect(coverage['type'], equals('CodeCoverage'));
                     expect(coverage['coverage'].length, equals(1));
                     expect(normalize(coverage['coverage'][0]['hits']),
-                           equals([14, 1, 15, 1, 16, 0, 18, 1,
-                                   23, 1, 24, 1, 26, 0]));
+                           equals([15, 1, 16, 1, 17, 0, 19, 1,
+                                   24, 1, 25, 1, 27, 0]));
                 }));
       // Library
       tests.add(isolate.invokeRpcNoUpgrade('getCoverage',
@@ -118,10 +119,10 @@
                     expect(coverage['type'], equals('CodeCoverage'));
                     expect(coverage['coverage'].length, equals(3));
                     expect(normalize(coverage['coverage'][0]['hits']),
-                           equals([14, 1, 15, 1, 16, 0, 18, 1,
-                                   23, 1, 24, 1, 26, 0]));
+                           equals([15, 1, 16, 1, 17, 0, 19, 1,
+                                   24, 1, 25, 1, 27, 0]));
                     expect(normalize(coverage['coverage'][1]['hits']).take(12),
-                           equals([32, 0, 35, 0, 36, 0, 32, 1, 35, 1, 36, 0]));
+                           equals([33, 1, 36, 1, 37, 0, 32, 1, 45, 0, 46, 0]));
                 }));
       // Script
       tests.add(cls.load().then((_) {
@@ -131,10 +132,10 @@
                     expect(coverage['type'], equals('CodeCoverage'));
                     expect(coverage['coverage'].length, equals(3));
                     expect(normalize(coverage['coverage'][0]['hits']),
-                           equals([14, 1, 15, 1, 16, 0, 18, 1,
-                                   23, 1, 24, 1, 26, 0]));
+                           equals([15, 1, 16, 1, 17, 0, 19, 1,
+                                   24, 1, 25, 1, 27, 0]));
                     expect(normalize(coverage['coverage'][1]['hits']).take(12),
-                           equals([32, 0, 35, 0, 36, 0, 32, 1, 35, 1, 36, 0]));
+                           equals([33, 1, 36, 1, 37, 0, 32, 1, 45, 0, 46, 0]));
                 });
           }));
       // Isolate
diff --git a/runtime/observatory/test/debugging_test.dart b/runtime/observatory/tests/service/debugging_test.dart
similarity index 92%
rename from runtime/observatory/test/debugging_test.dart
rename to runtime/observatory/tests/service/debugging_test.dart
index c149ff7..c60b145 100644
--- a/runtime/observatory/test/debugging_test.dart
+++ b/runtime/observatory/tests/service/debugging_test.dart
@@ -1,6 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -55,7 +56,6 @@
   return isolate.rootLib.load().then((_) {
       // Set up a listener to wait for breakpoint events.
       Completer completer = new Completer();
-      List events = [];
       var subscription;
       subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
         if (event.eventType == ServiceEvent.kPauseBreakpoint) {
@@ -72,7 +72,7 @@
           Breakpoint bpt = result;
           expect(bpt.type, equals('Breakpoint'));
           expect(bpt.script.id, equals(script.id));
-          expect(bpt.tokenPos, equals(66));
+          expect(bpt.tokenPos, equals(58));
           expect(isolate.breakpoints.length, equals(1));
           return completer.future;  // Wait for breakpoint events.
       });
@@ -85,6 +85,7 @@
       expect(stack.type, equals('Stack'));
       expect(stack['frames'].length, greaterThanOrEqualTo(1));
       expect(stack['frames'][0]['function'].name, equals('testFunction'));
+      expect(stack['frames'][0]['tokenPos'], equals(58));
   });
 },
 
@@ -92,7 +93,6 @@
 (Isolate isolate) {
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
-  List events = [];
   var subscription;
   subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
     if (event.eventType == ServiceEvent.kPauseBreakpoint) {
@@ -101,18 +101,19 @@
       completer.complete();
     }
   });
-  
+
   return isolate.stepInto().then((isolate) {
     return completer.future;  // Wait for breakpoint events.
   });
 },
 
-// Get the stack trace again.  We are in 'helper'.
+// Get the stack trace again.  Our position has updated.
 (Isolate isolate) {
   return isolate.getStack().then((ServiceMap stack) {
       expect(stack.type, equals('Stack'));
       expect(stack['frames'].length, greaterThanOrEqualTo(2));
-      expect(stack['frames'][0]['function'].name, equals('helper'));
+      expect(stack['frames'][0]['function'].name, equals('testFunction'));
+      expect(stack['frames'][0]['tokenPos'], equals(60));
   });
 },
 
@@ -120,7 +121,6 @@
 (Isolate isolate) {
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
-  List events = [];
   var subscription;
   subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
     if (event.eventType == ServiceEvent.kBreakpointRemoved) {
@@ -156,7 +156,6 @@
 (Isolate isolate) {
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
-  List events = [];
   var subscription;
   subscription = isolate.vm.events.stream.listen((ServiceEvent event) {
     if (event.eventType == ServiceEvent.kPauseBreakpoint) {
@@ -165,7 +164,7 @@
       completer.complete();
     }
   });
-  
+
   // Find a specific function.
   ServiceFunction function = isolate.rootLib.functions.firstWhere(
       (f) => f.name == 'helper');
@@ -177,7 +176,7 @@
     Breakpoint bpt = result;
     expect(bpt.type, equals('Breakpoint'));
     expect(bpt.script.name, equals('debugging_test.dart'));
-    expect(bpt.tokenPos, equals(28));
+    expect(bpt.tokenPos, equals(29));
     expect(isolate.breakpoints.length, equals(1));
     return completer.future;  // Wait for breakpoint events.
   });
diff --git a/runtime/observatory/test/dominator_tree_test.dart b/runtime/observatory/tests/service/dominator_tree_test.dart
similarity index 94%
rename from runtime/observatory/test/dominator_tree_test.dart
rename to runtime/observatory/tests/service/dominator_tree_test.dart
index 0bd52b3..6db7b3c 100644
--- a/runtime/observatory/test/dominator_tree_test.dart
+++ b/runtime/observatory/tests/service/dominator_tree_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/dominator_tree.dart';
 import 'package:unittest/unittest.dart';
@@ -39,7 +40,7 @@
   expect(d.dominator('A'), equals('R'));
   expect(d.dominator('D'), equals('R'));
   expect(d.dominator('B'), equals('R'));
-  
+
   expect(d.dominator('F'), equals('C'));
   expect(d.dominator('G'), equals('C'));
   expect(d.dominator('J'), equals('G'));
diff --git a/runtime/observatory/test/echo_test.dart b/runtime/observatory/tests/service/echo_test.dart
similarity index 93%
rename from runtime/observatory/test/echo_test.dart
rename to runtime/observatory/tests/service/echo_test.dart
index 6a10e24..1e68a2b 100644
--- a/runtime/observatory/test/echo_test.dart
+++ b/runtime/observatory/tests/service/echo_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'dart:async';
 import 'package:observatory/service_io.dart';
diff --git a/runtime/observatory/test/eval_test.dart b/runtime/observatory/tests/service/eval_test.dart
similarity index 92%
rename from runtime/observatory/test/eval_test.dart
rename to runtime/observatory/tests/service/eval_test.dart
index 8355f7e..89afdfa 100644
--- a/runtime/observatory/test/eval_test.dart
+++ b/runtime/observatory/tests/service/eval_test.dart
@@ -1,6 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -33,7 +34,6 @@
   return isolate.rootLib.load().then((_) {
       // Set up a listener to wait for breakpoint events.
       Completer completer = new Completer();
-      List events = [];
       isolate.vm.events.stream.listen((ServiceEvent event) {
         if (event.eventType == ServiceEvent.kPauseBreakpoint) {
           print('Breakpoint reached');
@@ -57,10 +57,10 @@
       expect(stack.type, equals('Stack'));
       expect(stack['frames'].length, greaterThanOrEqualTo(2));
       expect(stack['frames'][0]['function'].name, equals('printValue'));
-      expect(stack['frames'][0]['function'].owningClass.name, equals('MyClass'));
+      expect(stack['frames'][0]['function'].dartOwner.name, equals('MyClass'));
 
       var lib = isolate.rootLib;
-      var cls = stack['frames'][0]['function'].owningClass;
+      var cls = stack['frames'][0]['function'].dartOwner;
       var instance = stack['frames'][0]['vars'][0]['value'];
 
       List evals = [];
diff --git a/runtime/observatory/test/functions_test.dart b/runtime/observatory/tests/service/functions_test.dart
similarity index 92%
rename from runtime/observatory/test/functions_test.dart
rename to runtime/observatory/tests/service/functions_test.dart
index 9290a4b..844de8c 100644
--- a/runtime/observatory/test/functions_test.dart
+++ b/runtime/observatory/tests/service/functions_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 library functions_test;
 
diff --git a/runtime/observatory/test/gc_test.dart b/runtime/observatory/tests/service/gc_test.dart
similarity index 92%
rename from runtime/observatory/test/gc_test.dart
rename to runtime/observatory/tests/service/gc_test.dart
index 11ba8c5..f6d6293 100644
--- a/runtime/observatory/test/gc_test.dart
+++ b/runtime/observatory/tests/service/gc_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'test_helper.dart';
diff --git a/runtime/observatory/test/graph_test.dart b/runtime/observatory/tests/service/graph_test.dart
similarity index 96%
rename from runtime/observatory/test/graph_test.dart
rename to runtime/observatory/tests/service/graph_test.dart
index a496088..2b2d07a 100644
--- a/runtime/observatory/test/graph_test.dart
+++ b/runtime/observatory/tests/service/graph_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'dart:async';
 import 'package:observatory/object_graph.dart';
@@ -25,7 +26,7 @@
   r.left = a;
   r.right = b;
   a.left = b;
-  
+
   lst = new List(2);
   lst[0] = lst;  // Self-loop.
   // Larger than any other fixed-size list in a fresh heap.
@@ -52,14 +53,14 @@
           (ObjectVertex obj) => obj.succ.length == 1).length, equals(1));
       expect(foos.where(
           (ObjectVertex obj) => obj.succ.length == 2).length, equals(1));
-      
+
       ObjectVertex bVertex = foos.where(
           (ObjectVertex obj) => obj.succ.length == 0).first;
       ObjectVertex aVertex = foos.where(
           (ObjectVertex obj) => obj.succ.length == 1).first;
       ObjectVertex rVertex = foos.where(
           (ObjectVertex obj) => obj.succ.length == 2).first;
-      
+
       // TODO(koda): Check actual byte sizes.
 
       expect(aVertex.retainedSize, equals(aVertex.shallowSize));
@@ -67,8 +68,8 @@
       expect(rVertex.retainedSize, equals(aVertex.shallowSize +
                                           bVertex.shallowSize +
                                           rVertex.shallowSize));
-      
-      const int fixedSizeListCid = 62;
+
+      const int fixedSizeListCid = 61;
       List<ObjectVertex> lists = new List.from(graph.vertices.where(
           (ObjectVertex obj) => obj.classId == fixedSizeListCid));
       expect(lists.length >= 2, isTrue);
diff --git a/runtime/observatory/test/inbound_references_test.dart b/runtime/observatory/tests/service/inbound_references_test.dart
similarity index 95%
rename from runtime/observatory/test/inbound_references_test.dart
rename to runtime/observatory/tests/service/inbound_references_test.dart
index 0586620..a9805e8 100644
--- a/runtime/observatory/test/inbound_references_test.dart
+++ b/runtime/observatory/tests/service/inbound_references_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 library inbound_references_test;
 
diff --git a/runtime/observatory/test/isolate_lifecycle_test.dart b/runtime/observatory/tests/service/isolate_lifecycle_test.dart
similarity index 93%
rename from runtime/observatory/test/isolate_lifecycle_test.dart
rename to runtime/observatory/tests/service/isolate_lifecycle_test.dart
index c814ca9..08a2a1b 100644
--- a/runtime/observatory/test/isolate_lifecycle_test.dart
+++ b/runtime/observatory/tests/service/isolate_lifecycle_test.dart
@@ -1,10 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'dart:async';
 import 'dart:isolate' as I;
-import 'dart:math';
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
@@ -27,7 +27,7 @@
   print('spawned all isolates');
 }
 
-Future during() {
+Future during() async {
 }
 
 var tests = [
@@ -67,7 +67,7 @@
     var resumesIssued = 0;
     var isolateList = vm.isolates.toList();
     for (var isolate in isolateList) {
-      if (isolate.name == 'root') {
+      if (isolate.name.endsWith('main')) {
         continue;
       }
       try {
diff --git a/runtime/observatory/test/malformed_test.dart b/runtime/observatory/tests/service/malformed_test.dart
similarity index 91%
rename from runtime/observatory/test/malformed_test.dart
rename to runtime/observatory/tests/service/malformed_test.dart
index 76fffb4..989457d 100644
--- a/runtime/observatory/test/malformed_test.dart
+++ b/runtime/observatory/tests/service/malformed_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/test/metrics_test.dart b/runtime/observatory/tests/service/metrics_test.dart
similarity index 93%
rename from runtime/observatory/test/metrics_test.dart
rename to runtime/observatory/tests/service/metrics_test.dart
index ef227c4..996e1c1 100644
--- a/runtime/observatory/test/metrics_test.dart
+++ b/runtime/observatory/tests/service/metrics_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/test/mirror_references_test.dart b/runtime/observatory/tests/service/mirror_references_test.dart
similarity index 94%
rename from runtime/observatory/test/mirror_references_test.dart
rename to runtime/observatory/tests/service/mirror_references_test.dart
index d6e5f39..0433f28 100644
--- a/runtime/observatory/test/mirror_references_test.dart
+++ b/runtime/observatory/tests/service/mirror_references_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 library vm_references_test;
 
diff --git a/runtime/observatory/test/native_metrics_test.dart b/runtime/observatory/tests/service/native_metrics_test.dart
similarity index 79%
rename from runtime/observatory/test/native_metrics_test.dart
rename to runtime/observatory/tests/service/native_metrics_test.dart
index 39b23d1..5467823 100644
--- a/runtime/observatory/test/native_metrics_test.dart
+++ b/runtime/observatory/tests/service/native_metrics_test.dart
@@ -1,3 +1,8 @@
+// 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 --checked
+
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
new file mode 100644
index 0000000..d3c936e
--- /dev/null
+++ b/runtime/observatory/tests/service/service.status
@@ -0,0 +1,27 @@
+# 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.
+
+[ $system == linux ]
+call_site_data_test: Pass, Fail # Issue 23160
+
+# Unexpected number format
+[ $system == windows ]
+code_test: Skip
+
+# Tests that depend on token positions (which differ in release mode).
+[ $mode == release ]
+debugging_test: Skip
+
+# Disable on simulators.
+[ $arch == simarm || $arch == simmips || $arch == simarm64]
+*: Skip # Slow
+
+# The transformations of dart2dart are not guaranteed to preserve the
+# state/properties of the VM that the Observatory tests are inspecting.
+[ $compiler == dart2dart ]
+*: Skip
+
+# All tests use dart:io
+[ $browser || $compiler == dart2js ]
+*: SkipByDesign
diff --git a/runtime/observatory/test/source_location_test.dart b/runtime/observatory/tests/service/source_location_test.dart
similarity index 94%
rename from runtime/observatory/test/source_location_test.dart
rename to runtime/observatory/tests/service/source_location_test.dart
index e0cdd21..d658b2a 100644
--- a/runtime/observatory/test/source_location_test.dart
+++ b/runtime/observatory/tests/service/source_location_test.dart
@@ -1,6 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:observatory/debugger.dart';
@@ -11,7 +12,7 @@
 void testFunction() {
   int i = 0;
   while (true) {
-    if (++i % 100000000 == 0) {  // line 14
+    if (++i % 100000000 == 0) {  // line 15
       print(i);
     }
   }
@@ -20,6 +21,7 @@
 class TestDebugger extends Debugger {
   TestDebugger(this.isolate, this.stack);
 
+  VM get vm => isolate.vm;
   Isolate isolate;
   ServiceMap stack;
   int currentFrame = 0;
@@ -49,7 +51,7 @@
 
 var tests = [
 
-// Bring the isolate to a breakpoint at line 14.
+// Bring the isolate to a breakpoint at line 15.
 (Isolate isolate) {
   return isolate.rootLib.load().then((_) {
       // Listen for breakpoint event.
@@ -62,7 +64,7 @@
 
       // Add the breakpoint.
       var script = isolate.rootLib.scripts[0];
-      return isolate.addBreakpoint(script, 14).then((ServiceObject bpt) {
+      return isolate.addBreakpoint(script, 15).then((ServiceObject bpt) {
           return completer.future;  // Wait for breakpoint events.
       });
     });
@@ -73,7 +75,7 @@
   return initDebugger(isolate).then((debugger) {
     return SourceLocation.parse(debugger, '').then((SourceLocation loc) {
       expect(loc.valid, isTrue);
-      expect(loc.toString(), equals('source_location_test.dart:14'));
+      expect(loc.toString(), equals('source_location_test.dart:15'));
     });
   });
 },
@@ -81,9 +83,9 @@
 // Parse line
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, '15').then((SourceLocation loc) {
+    return SourceLocation.parse(debugger, '16').then((SourceLocation loc) {
       expect(loc.valid, isTrue);
-      expect(loc.toString(), equals('source_location_test.dart:15'));
+      expect(loc.toString(), equals('source_location_test.dart:16'));
     });
   });
 },
@@ -91,9 +93,9 @@
 // Parse line + col
 (Isolate isolate) {
   return initDebugger(isolate).then((debugger) {
-    return SourceLocation.parse(debugger, '15:11').then((SourceLocation loc) {
+    return SourceLocation.parse(debugger, '16:11').then((SourceLocation loc) {
       expect(loc.valid, isTrue);
-      expect(loc.toString(), equals('source_location_test.dart:15:11'));
+      expect(loc.toString(), equals('source_location_test.dart:16:11'));
     });
   });
 },
diff --git a/runtime/observatory/test/string_escaping_test.dart b/runtime/observatory/tests/service/string_escaping_test.dart
similarity index 97%
rename from runtime/observatory/test/string_escaping_test.dart
rename to runtime/observatory/tests/service/string_escaping_test.dart
index 453eb05..050b3ce 100644
--- a/runtime/observatory/test/string_escaping_test.dart
+++ b/runtime/observatory/tests/service/string_escaping_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 library string_escaping_test;
 
diff --git a/runtime/observatory/test/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
similarity index 76%
rename from runtime/observatory/test/test_helper.dart
rename to runtime/observatory/tests/service/test_helper.dart
index aa3c2a0..3dddedd 100644
--- a/runtime/observatory/test/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -1,15 +1,22 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 library test_helper;
 
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
-import 'package:unittest/unittest.dart';
 import 'package:observatory/service_io.dart';
 
+bool _isWebSocketDisconnect(e) {
+  if (e is! ServiceException) {
+    return false;
+  }
+  return (e as ServiceException).message == 'WebSocket disconnected';
+}
+
 // This invocation should set up the state being tested.
 const String _TESTEE_MODE_FLAG = "--testee-mode";
 
@@ -61,15 +68,15 @@
         print(line);
       });
       process.exitCode.then((exitCode) {
-        expect(exitCode, equals(0));
+        print("** Process exited");
       });
       return completer.future;
     });
   }
 
   void requestExit() {
-    print('** Requesting script to exit.');
-    process.stdin.add([32, 13, 10]);
+    print('** Killing script');
+    process.kill();
   }
 }
 
@@ -93,7 +100,7 @@
     if (testeeConcurrent != null) {
       testeeConcurrent();
     }
-    // Wait until signaled from spawning test.
+    // Wait around for the process to be killed.
     stdin.first.then((_) => exit(0));
   } else {
     var process = new _TestLauncher();
@@ -102,13 +109,20 @@
       var testIndex = 0;
       var totalTests = tests.length - 1;
       var name = Platform.script.pathSegments.last;
-      new WebSocketVM(new WebSocketVMTarget(addr)).load()
-          .then((VM vm) => vm.isolates.first.load())
-          .then((Isolate isolate) => Future.forEach(tests, (test) {
-            print('Running $name [$testIndex/$totalTests]');
-            testIndex++;
-            return test(isolate);
-          })).then((_) => exit(0));
+      runZoned(() {
+        new WebSocketVM(new WebSocketVMTarget(addr)).load()
+            .then((VM vm) => vm.isolates.first.load())
+            .then((Isolate isolate) => Future.forEach(tests, (test) {
+              print('Running $name [$testIndex/$totalTests]');
+              testIndex++;
+              return test(isolate);
+            })).then((_) => process.requestExit());
+      }, onError: (e, st) {
+        if (!_isWebSocketDisconnect(e)) {
+          print('Unexpected exception in service tests: $e $st');
+          throw e;
+        }
+      });
     });
   }
 }
@@ -147,7 +161,7 @@
     if (testeeConcurrent != null) {
       await testeeConcurrent();
     }
-    // Wait until signaled from spawning test.
+    // Wait around for the process to be killed.
     stdin.first.then((_) => exit(0));
   } else {
     var process = new _TestLauncher();
@@ -156,12 +170,19 @@
       var testIndex = 0;
       var totalTests = tests.length - 1;
       var name = Platform.script.pathSegments.last;
-      new WebSocketVM(new WebSocketVMTarget(addr)).load()
-          .then((VM vm) => Future.forEach(tests, (test) {
-            print('Running $name [$testIndex/$totalTests]');
-            testIndex++;
-            return test(vm);
-          })).then((_) => exit(0));
+      runZoned(() {
+        new WebSocketVM(new WebSocketVMTarget(addr)).load()
+            .then((VM vm) => Future.forEach(tests, (test) {
+              print('Running $name [$testIndex/$totalTests]');
+              testIndex++;
+              return test(vm);
+            })).then((_) => process.requestExit());
+      }, onError: (e, st) {
+        if (!_isWebSocketDisconnect(e)) {
+          print('Unexpected exception in service tests: $e $st');
+          throw e;
+        }
+      });
     });
   }
-}
\ No newline at end of file
+}
diff --git a/runtime/observatory/test/type_arguments_test.dart b/runtime/observatory/tests/service/type_arguments_test.dart
similarity index 95%
rename from runtime/observatory/test/type_arguments_test.dart
rename to runtime/observatory/tests/service/type_arguments_test.dart
index 4b82421..aaa85c7 100644
--- a/runtime/observatory/test/type_arguments_test.dart
+++ b/runtime/observatory/tests/service/type_arguments_test.dart
@@ -1,6 +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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/service/vm_test.dart b/runtime/observatory/tests/service/vm_test.dart
new file mode 100644
index 0000000..aea81ca
--- /dev/null
+++ b/runtime/observatory/tests/service/vm_test.dart
@@ -0,0 +1,21 @@
+// 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 --checked
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+var tests = [
+
+(Isolate isolate) {
+  VM vm = isolate.owner;
+  expect(vm.targetCPU, isNotNull);
+  expect(vm.architectureBits == 32 ||
+         vm.architectureBits == 64, isTrue);
+},
+
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory/test/weak_properties_test.dart b/runtime/observatory/tests/service/weak_properties_test.dart
similarity index 95%
rename from runtime/observatory/test/weak_properties_test.dart
rename to runtime/observatory/tests/service/weak_properties_test.dart
index c0e3ff7..c37c38f 100644
--- a/runtime/observatory/test/weak_properties_test.dart
+++ b/runtime/observatory/tests/service/weak_properties_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// VMOptions=--compile-all --error_on_bad_type --error_on_bad_override --checked
 
 library vm_references_test;
 
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 8eff2f4..54ebf4d 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -201,6 +201,19 @@
   static bool DoublesBitEqual(const double a, const double b) {
     return bit_cast<int64_t, double>(a) == bit_cast<int64_t, double>(b);
   }
+
+  // dart2js represents integers as double precision floats, which can
+  // represent anything in the range -2^53 ... 2^53.
+  static bool IsJavascriptInt64(int64_t value) {
+    return ((-0x20000000000000LL <= value) && (value <= 0x20000000000000LL));
+  }
+  static bool IsJavascriptInt(intptr_t value) {
+#if defined(ARCH_IS_64BIT)
+    return ((-0x20000000000000LL <= value) && (value <= 0x20000000000000LL));
+#else
+    return true;
+#endif
+  }
 };
 
 }  // namespace dart
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index e1d95ce..01622e6 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -84,9 +84,6 @@
 [ $compiler == dartanalyzer || $compiler == dart2analyzer ]
 dart/optimized_stacktrace_test: StaticWarning
 
-[ $compiler == none && $runtime == ContentShellOnAndroid ]
-dart/byte_array_test: RuntimeError # Issue 17612
-
 [ $runtime != vm ]
 dart/snapshot_version_test: SkipByDesign  # Spawns processes
 
diff --git a/runtime/third_party/jscre/ASCIICType.h b/runtime/third_party/jscre/ASCIICType.h
deleted file mode 100644
index 1550b83..0000000
--- a/runtime/third_party/jscre/ASCIICType.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution. 
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_JSCRE_ASCIICTYPE_H_
-#define THIRD_PARTY_JSCRE_ASCIICTYPE_H_
-
-// The behavior of many of the functions in the <ctype.h> header is dependent
-// on the current locale. But in the WebKit project, all uses of those functions
-// are in code processing something that's not locale-specific. These
-// equivalents for some of the <ctype.h> functions are named more explicitly,
-// not dependent on the C library locale, and we should also optimize them
-// as needed.
-
-// All functions return false or leave the character unchanged if passed
-// a character that is outside the range 0-7F. So they can be used on
-// Unicode strings or characters if the intent is to do processing only
-// if the character is ASCII.
-
-    inline bool isASCIIAlpha(char c) {
-      return (c | 0x20) >= 'a' && (c | 0x20) <= 'z';
-    }
-    inline bool isASCIIAlpha(uint16_t c) {
-      return (c | 0x20) >= 'a' && (c | 0x20) <= 'z';
-    }
-    inline bool isASCIIAlpha(int c) {
-      return (c | 0x20) >= 'a' && (c | 0x20) <= 'z';
-    }
-
-    inline bool isASCIIAlphanumeric(char c) {
-      return (c >= '0' && c <= '9') ||
-             ((c | 0x20) >= 'a' && (c | 0x20) <= 'z');
-    }
-    inline bool isASCIIAlphanumeric(uint16_t c) {
-      return (c >= '0' && c <= '9') ||
-             ((c | 0x20) >= 'a' && (c | 0x20) <= 'z');
-    }
-    inline bool isASCIIAlphanumeric(int c) {
-      return (c >= '0' && c <= '9') ||
-             ((c | 0x20) >= 'a' && (c | 0x20) <= 'z');
-    }
-
-    inline bool isASCIIDigit(char c) { return (c >= '0') & (c <= '9'); }
-    inline bool isASCIIDigit(uint16_t c) {
-      return (c >= '0') & (c <= '9');
-    }
-    inline bool isASCIIDigit(int c) { return (c >= '0') & (c <= '9'); }
-
-    inline bool isASCIIHexDigit(char c) {
-      return (c >= '0' && c <= '9') ||
-             ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
-    }
-    inline bool isASCIIHexDigit(uint16_t c) {
-      return (c >= '0' && c <= '9') ||
-             ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
-    }
-    inline bool isASCIIHexDigit(int c) {
-      return (c >= '0' && c <= '9') ||
-             ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
-    }
-
-    inline bool isASCIILower(char c) { return c >= 'a' && c <= 'z'; }
-    inline bool isASCIILower(uint16_t c) { return c >= 'a' && c <= 'z'; }
-    inline bool isASCIILower(int c) { return c >= 'a' && c <= 'z'; }
-
-    inline bool isASCIIUpper(char c) { return c >= 'A' && c <= 'Z'; }
-    inline bool isASCIIUpper(uint16_t c) { return c >= 'A' && c <= 'Z'; }
-    inline bool isASCIIUpper(int c) { return c >= 'A' && c <= 'Z'; }
-
-    /*
-        Statistics from a run of Apple's page load test for callers of
-        isASCIISpace:
-
-            character          count
-            ---------          -----
-            non-spaces         689383
-        20  space              294720
-        0A  \n                 89059
-        09  \t                 28320
-        0D  \r                 0
-        0C  \f                 0
-        0B  \v                 0
-    */
-    inline bool isASCIISpace(char c) {
-      return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9));
-    }
-    inline bool isASCIISpace(uint16_t c) {
-      return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9));
-    }
-    inline bool isASCIISpace(int c) {
-      return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9));
-    }
-
-    inline char toASCIILower(char c) {
-      return c | ((c >= 'A' && c <= 'Z') << 5);
-    }
-    inline uint16_t toASCIILower(uint16_t c) {
-      return c | ((c >= 'A' && c <= 'Z') << 5);
-    }
-    inline int toASCIILower(int c) {
-      return c | ((c >= 'A' && c <= 'Z') << 5);
-    }
-
-    inline char toASCIIUpper(char c) {
-      return static_cast<char>(c & ~((c >= 'a' && c <= 'z') << 5));
-    }
-    inline uint16_t toASCIIUpper(uint16_t c) {
-      return static_cast<uint16_t>(c & ~((c >= 'a' && c <= 'z') << 5));
-    }
-    inline int toASCIIUpper(int c) {
-      return static_cast<int>(c & ~((c >= 'a' && c <= 'z') << 5));
-    }
-
-    inline int toASCIIHexValue(char c) {
-      ASSERT(isASCIIHexDigit(c));
-      return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF;
-    }
-    inline int toASCIIHexValue(uint16_t c) {
-      ASSERT(isASCIIHexDigit(c));
-      return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF;
-    }
-    inline int toASCIIHexValue(int c) {
-      ASSERT(isASCIIHexDigit(c));
-      return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF;
-    }
-
-#endif  // THIRD_PARTY_JSCRE_ASCIICTYPE_H_
diff --git a/runtime/third_party/jscre/AUTHORS b/runtime/third_party/jscre/AUTHORS
deleted file mode 100644
index dbac2a5..0000000
--- a/runtime/third_party/jscre/AUTHORS
+++ /dev/null
@@ -1,12 +0,0 @@
-Originally written by:  Philip Hazel
-Email local part:       ph10
-Email domain:           cam.ac.uk
-
-University of Cambridge Computing Service,
-Cambridge, England. Phone: +44 1223 334714.
-
-Copyright (c) 1997-2005 University of Cambridge. All rights reserved.
-
-Adapted for JavaScriptCore and WebKit by Apple Inc.
-
-Copyright (c) 2005, 2006, 2007 Apple Inc. All rights reserved.
diff --git a/runtime/third_party/jscre/BUILD.gn b/runtime/third_party/jscre/BUILD.gn
deleted file mode 100644
index 59c91a8..0000000
--- a/runtime/third_party/jscre/BUILD.gn
+++ /dev/null
@@ -1,27 +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.
-
-static_library("libjscre") {
-  configs += [ "../..:dart_config", ]
-  defines = [
-    "SUPPORT_UTF8",
-    "SUPPORT_UCP",
-    "NO_RECURSE",
-  ]
-  sources = [
-    "ASCIICType.h",
-    "config.h",
-    "pcre.h",
-    "pcre_internal.h",
-    "ucpinternal.h",
-    "pcre_compile.cpp",
-    "pcre_exec.cpp",
-    "pcre_tables.cpp",
-    "pcre_ucp_searchfuncs.cpp",
-    "pcre_xclass.cpp",
-  ]
-  include_dirs = [
-    ".",
-  ]
-}
diff --git a/runtime/third_party/jscre/COPYING b/runtime/third_party/jscre/COPYING
deleted file mode 100644
index 6ffdc24..0000000
--- a/runtime/third_party/jscre/COPYING
+++ /dev/null
@@ -1,35 +0,0 @@
-PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
-This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed.
-
-Copyright (c) 1997-2005 University of Cambridge. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the name of Apple
-      Inc. nor the names of their contributors may be used to endorse or
-      promote products derived from this software without specific prior
-      written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
diff --git a/runtime/third_party/jscre/LICENSE b/runtime/third_party/jscre/LICENSE
deleted file mode 100644
index 020c45f..0000000
--- a/runtime/third_party/jscre/LICENSE
+++ /dev/null
@@ -1,85 +0,0 @@
------------------------------------------------------------------------------
-The following license text is extracted from the header of the file
-ASCIICType.h and applies only to that file.
------------------------------------------------------------------------------
-
-Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1.  Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
-2.  Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution. 
-3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------
-The following license text is from the file COPYING and applies to the other
-source files in this directory.
------------------------------------------------------------------------------
-
-PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
-This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed.
-
-Copyright (c) 1997-2005 University of Cambridge. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the name of Apple
-      Inc. nor the names of their contributors may be used to endorse or
-      promote products derived from this software without specific prior
-      written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------
-The following copyright lines are found in individual files other than
-ASCIICType.h
------------------------------------------------------------------------------
-
-
-Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-Copyright (C) 2002, 2004, 2006, 2007, 2008 Apple Inc.  All rights reserved.
-Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-Copyright (c) 1997-2005 University of Cambridge
-Copyright (c) 1997-2005 University of Cambridge. All rights reserved.
-Copyright (c) 1997-2006 University of Cambridge
-Copyright (c) 2005, 2006, 2007 Apple Inc. All rights reserved.
diff --git a/runtime/third_party/jscre/config.h b/runtime/third_party/jscre/config.h
deleted file mode 100644
index 5ed9ff1..0000000
--- a/runtime/third_party/jscre/config.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* This is the public header file for JavaScriptCore's variant of the PCRE
-library. While this library started out as a copy of PCRE, many of the
-features of PCRE have been removed. This library now supports only the
-regular expression features required by the JavaScript language
-specification, and has only the functions needed by JavaScriptCore and the
-rest of WebKit.
-
-           Copyright (c) 1997-2005 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* On Unix-like systems config.in is converted by "configure" into config.h.
-Some other environments also support the use of "configure". PCRE is written in
-Standard C, but there are a few non-standard things it can cope with, allowing
-it to run on SunOS4 and other "close to standard" systems.
-
-On a non-Unix-like system you should just copy this file into config.h, and set
-up the macros the way you need them. You should normally change the definitions
-of HAVE_STRERROR and HAVE_MEMMOVE to 1. Unfortunately, because of the way
-autoconf works, these cannot be made the defaults. If your system has bcopy()
-and not memmove(), change the definition of HAVE_BCOPY instead of HAVE_MEMMOVE.
-If your system has neither bcopy() nor memmove(), leave them both as 0; an
-emulation function will be used. */
-
-/* If you are compiling for a system that uses EBCDIC instead of ASCII
-character codes, define this macro as 1. On systems that can use "configure",
-this can be done via --enable-ebcdic. */
-
-#ifndef THIRD_PARTY_JSCRE_CONFIG_H_
-#define THIRD_PARTY_JSCRE_CONFIG_H_
-
-#ifndef EBCDIC
-#define EBCDIC 0
-#endif
-
-/* If you are compiling for a system other than a Unix-like system or Win32,
-and it needs some magic to be inserted before the definition of a function that
-is exported by the library, define this macro to contain the relevant magic. If
-you do not define this macro, it defaults to "extern" for a C compiler and
-"extern C" for a C++ compiler on non-Win32 systems. This macro apears at the
-start of every exported function that is part of the external API. It does not
-appear on functions that are "external" in the C sense, but which are internal
-to the library. */
-
-/* #define PCRE_DATA_SCOPE */
-
-/* Define the following macro to empty if the "const" keyword does not work. */
-
-#undef const
-
-/* Define the following macro to "unsigned" if <stddef.h> does not define
-size_t. */
-
-#undef size_t
-
-/* The following two definitions are mainly for the benefit of SunOS4, which
-does not have the strerror() or memmove() functions that should be present in
-all Standard C libraries. The macros HAVE_STRERROR and HAVE_MEMMOVE should
-normally be defined with the value 1 for other systems, but unfortunately we
-cannot make this the default because "configure" files generated by autoconf
-will only change 0 to 1; they won't change 1 to 0 if the functions are not
-found. */
-
-#define HAVE_STRERROR 1
-#define HAVE_MEMMOVE  1
-
-/* There are some non-Unix-like systems that don't even have bcopy(). If this
-macro is false, an emulation is used. If HAVE_MEMMOVE is set to 1, the value of
-HAVE_BCOPY is not relevant. */
-
-#define HAVE_BCOPY    0
-
-/* The value of NEWLINE determines the newline character. The default is to
-leave it up to the compiler, but some sites want to force a particular value.
-On Unix-like systems, "configure" can be used to override this default. */
-
-#ifndef NEWLINE
-#define NEWLINE '\n'
-#endif
-
-/* The value of LINK_SIZE determines the number of bytes used to store links as
-offsets within the compiled regex. The default is 2, which allows for compiled
-patterns up to 64K long. This covers the vast majority of cases. However, PCRE
-can also be compiled to use 3 or 4 bytes instead. This allows for longer
-patterns in extreme cases. On systems that support it, "configure" can be used
-to override this default. */
-
-#ifndef LINK_SIZE
-#define LINK_SIZE   2
-#endif
-
-/* When calling PCRE via the POSIX interface, additional working storage is
-required for holding the pointers to capturing substrings because PCRE requires
-three integers per substring, whereas the POSIX interface provides only two. If
-the number of expected substrings is small, the wrapper function uses space on
-the stack, because this is faster than using malloc() for each call. The
-threshold above which the stack is no longer used is defined by POSIX_MALLOC_
-THRESHOLD. On systems that support it, "configure" can be used to override this
-default. */
-
-#ifndef POSIX_MALLOC_THRESHOLD
-#define POSIX_MALLOC_THRESHOLD 10
-#endif
-
-/* PCRE uses recursive function calls to handle backtracking while matching.
-This can sometimes be a problem on systems that have stacks of limited size.
-Define NO_RECURSE to get a version that doesn't use recursion in the match()
-function; instead it creates its own stack by steam using pcre_recurse_malloc()
-to obtain memory from the heap. For more detail, see the comments and other
-stuff just above the match() function. On systems that support it, "configure"
-can be used to set this in the Makefile (use --disable-stack-for-recursion). */
-
-/* #define NO_RECURSE */
-
-/* The value of MATCH_LIMIT determines the default number of times the internal
-match() function can be called during a single execution of pcre_exec(). There
-is a runtime interface for setting a different limit. The limit exists in order
-to catch runaway regular expressions that take for ever to determine that they
-do not match. The default is set very large so that it does not accidentally
-catch legitimate cases. On systems that support it, "configure" can be used to
-override this default default. */
-
-#ifndef MATCH_LIMIT
-#define MATCH_LIMIT 10000000
-#endif
-
-/* The above limit applies to all calls of match(), whether or not they
-increase the recursion depth. In some environments it is desirable to limit the
-depth of recursive calls of match() more strictly, in order to restrict the
-maximum amount of stack (or heap, if NO_RECURSE is defined) that is used. The
-value of MATCH_LIMIT_RECURSION applies only to recursive calls of match(). To
-have any useful effect, it must be less than the value of MATCH_LIMIT. There is
-a runtime method for setting a different limit. On systems that support it,
-"configure" can be used to override this default default. */
-
-#ifndef MATCH_LIMIT_RECURSION
-#define MATCH_LIMIT_RECURSION MATCH_LIMIT
-#endif
-
-/* These three limits are parameterized just in case anybody ever wants to
-change them. Care must be taken if they are increased, because they guard
-against integer overflow caused by enormously large patterns. */
-
-#ifndef MAX_NAME_SIZE
-#define MAX_NAME_SIZE 32
-#endif
-
-#ifndef MAX_NAME_COUNT
-#define MAX_NAME_COUNT 10000
-#endif
-
-#ifndef MAX_DUPLENGTH
-#define MAX_DUPLENGTH 30000
-#endif
-
-/* End */
-#endif  // THIRD_PARTY_JSCRE_CONFIG_H_
diff --git a/runtime/third_party/jscre/jscre.gypi b/runtime/third_party/jscre/jscre.gypi
deleted file mode 100644
index acb6d8c..0000000
--- a/runtime/third_party/jscre/jscre.gypi
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2010 Google Inc. All Rights Reserved.
-
-{
-  'targets': [
-    {
-      'target_name': 'libjscre',
-      'type': 'static_library',
-      'toolsets':['target','host'],
-      'dependencies': [
-      ],
-      'include_dirs': [
-        '.',
-      ],
-      'defines': [
-        'SUPPORT_UTF8',
-        'SUPPORT_UCP',
-        'NO_RECURSE',
-      ],
-      'sources': [
-        'ASCIICType.h',
-        'config.h',
-        'pcre.h',
-        'pcre_internal.h',
-        'ucpinternal.h',
-        'pcre_compile.cpp',
-        'pcre_exec.cpp',
-        'pcre_tables.cpp',
-        'pcre_ucp_searchfuncs.cpp',
-        'pcre_xclass.cpp',
-      ],
-    },
-  ],
-}
diff --git a/runtime/third_party/jscre/pcre.h b/runtime/third_party/jscre/pcre.h
deleted file mode 100644
index d854fe0..0000000
--- a/runtime/third_party/jscre/pcre.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* This is the public header file for JavaScriptCore's variant of the PCRE
-library. While this library started out as a copy of PCRE, many of the
-features of PCRE have been removed. This library now supports only the
-regular expression features required by the JavaScript language
-specification, and has only the functions needed by JavaScriptCore and the
-rest of WebKit.
-
-           Copyright (c) 1997-2005 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-#ifndef THIRD_PARTY_JSCRE_PCRE_H_
-#define THIRD_PARTY_JSCRE_PCRE_H_
-
-#if defined(_WIN32)
-typedef unsigned __int16 uint16_t;
-#else
-#include <inttypes.h>
-#include <stdint.h>
-#endif
-
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-// JSCRE is very chatty in debug mode, so in order to keep it slient
-// while still importing v8.h correctly (it contains #ifdef DEBUGs)
-// we allow DEBUG to be set and undef it manually.
-#undef DEBUG
-
-namespace dart { namespace jscre {
-
-typedef uint16_t UChar;
-
-struct JSRegExp;
-typedef struct JSRegExp JscreRegExp;
-
-enum JSRegExpIgnoreCaseOption { JSRegExpDoNotIgnoreCase, JSRegExpIgnoreCase };
-enum JSRegExpMultilineOption { JSRegExpSingleLine, JSRegExpMultiline };
-
-/* jsRegExpExecute error codes */
-const int JSRegExpErrorNoMatch = -1;
-const int JSRegExpErrorHitLimit = -2;
-const int JSRegExpErrorNoMemory = -3;
-const int JSRegExpErrorInternal = -4;
-
-typedef void* malloc_t(size_t size);
-typedef void free_t(void* address);
-
-JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
-    JSRegExpIgnoreCaseOption, JSRegExpMultilineOption,
-    unsigned* numSubpatterns, const char** errorMessage,
-    malloc_t* allocate_function, free_t* free_function);
-
-int jsRegExpExecute(const JSRegExp*,
-    const UChar* subject, int subjectLength, int startOffset,
-    int* offsetsVector, int offsetsVectorLength);
-
-void jsRegExpFree(JSRegExp* regexp);
-
-} }  // namespace dart::jscre
-
-#endif  // THIRD_PARTY_JSCRE_PCRE_H_
diff --git a/runtime/third_party/jscre/pcre_chartables.c b/runtime/third_party/jscre/pcre_chartables.c
deleted file mode 100644
index c5fe2c5..0000000
--- a/runtime/third_party/jscre/pcre_chartables.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*************************************************
-*      Perl-Compatible Regular Expressions       *
-*************************************************/
-
-/* This file is automatically written by the dftables auxiliary 
-program. If you edit it by hand, you might like to edit the Makefile to 
-prevent its ever being regenerated.
-
-This file contains the default tables for characters with codes less than
-128 (ASCII characters). These tables are used when no external tables are
-passed to PCRE. */
-
-const unsigned char kjs_pcre_default_tables[480] = {
-
-/* This table is a lower casing table. */
-
-  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
-  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 
-  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
-  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 
-  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
-  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 
-  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 
-  0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 
-  0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
-  0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 
-  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
-  0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 
-  0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
-  0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 
-  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
-  0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
-
-/* This table is a case flipping table. */
-
-  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
-  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 
-  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
-  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 
-  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
-  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 
-  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 
-  0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 
-  0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
-  0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 
-  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
-  0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 
-  0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
-  0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 
-  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 
-  0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
-
-/* This table contains bit maps for various character classes.
-Each map is 32 bytes long and the bits run from the least
-significant end of each byte. The classes are: space, digit, word. */
-
-  0x00, 0x3E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 
-  0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x07, 
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-/* This table identifies various classes of character by individual bits:
-  0x01   white space character
-  0x08   hexadecimal digit
-  0x10   alphanumeric or '_'
-*/
-
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*   0-  7 */
-  0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,  /*   8- 15 */
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*  16- 23 */
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*  24- 31 */
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*    - '  */
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*  ( - /  */
-  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,  /*  0 - 7  */
-  0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*  8 - ?  */
-  0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10,  /*  @ - G  */
-  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  /*  H - O  */
-  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  /*  P - W  */
-  0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10,  /*  X - _  */
-  0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10,  /*  ` - g  */
-  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  /*  h - o  */
-  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  /*  p - w  */
-  0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}; /*  x -127 */
-
-
-/* End of chartables.c */
diff --git a/runtime/third_party/jscre/pcre_compile.cpp b/runtime/third_party/jscre/pcre_compile.cpp
deleted file mode 100644
index 110a32e..0000000
--- a/runtime/third_party/jscre/pcre_compile.cpp
+++ /dev/null
@@ -1,2675 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-    Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* This module contains the external function jsRegExpExecute(), along with
-supporting internal functions that are not used by other modules. */
-
-#include "config.h"
-
-#include "pcre_internal.h"
-
-#include <string.h>
-#include "ASCIICType.h"
-
-/* Negative values for the firstchar and reqchar variables */
-
-#define REQ_UNSET (-2)
-#define REQ_NONE  (-1)
-
-/*************************************************
-*      Code parameters and static tables         *
-*************************************************/
-
-/* Maximum number of items on the nested bracket stacks at compile time. This
-applies to the nesting of all kinds of parentheses. It does not limit
-un-nested, non-capturing parentheses. This number can be made bigger if
-necessary - it is used to dimension one int and one unsigned char vector at
-compile time. */
-
-#define BRASTACK_SIZE 200
-
-namespace dart { namespace jscre {
-
-/* Table for handling escaped characters in the range '0'-'z'. Positive returns
-are simple data values; negative values are for special things like \d and so
-on. Zero means further processing is needed (for things like \x), or the escape
-is invalid. */
-
-static const short escapes[] = {
-     0,      0,      0,      0,      0,      0,      0,      0,   /* 0 - 7 */
-     0,      0,    ':',    ';',    '<',    '=',    '>',    '?',   /* 8 - ? */
-   '@',      0, -ESC_B,      0, -ESC_D,      0,      0,      0,   /* @ - G */
-     0,      0,      0,      0,      0,      0,      0,      0,   /* H - O */
-     0,      0,      0, -ESC_S,      0,      0,      0, -ESC_W,   /* P - W */
-     0,      0,      0,    '[',   '\\',    ']',    '^',    '_',   /* X - _ */
-   '`',      7, -ESC_b,      0, -ESC_d,      0,   '\f',      0,   /* ` - g */
-     0,      0,      0,      0,      0,      0,   '\n',      0,   /* h - o */
-     0,      0,    '\r', -ESC_s,   '\t',      0,  '\v', -ESC_w,   /* p - w */
-     0,      0,      0                                            /* x - z */
-};
-
-/* Error code numbers. They are given names so that they can more easily be
-tracked. */
-
-enum ErrorCode {
-    ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9,
-    ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17
-};
-
-/* The texts of compile-time error messages. These are "char *" because they
-are passed to the outside world. */
-
-static const char* errorText(ErrorCode code)
-{
-    static const char errorTexts[] =
-      /* 1 */
-      "\\ at end of pattern\0"
-      "\\c at end of pattern\0"
-      "character value in \\x{...} sequence is too large\0"
-      "numbers out of order in {} quantifier\0"
-      /* 5 */
-      "number too big in {} quantifier\0"
-      "missing terminating ] for character class\0"
-      "internal error: code overflow\0"
-      "range out of order in character class\0"
-      "nothing to repeat\0"
-      /* 10 */
-      "unmatched parentheses\0"
-      "internal error: unexpected repeat\0"
-      "unrecognized character after (?\0"
-      "failed to get memory\0"
-      "missing )\0"
-      /* 15 */
-      "reference to non-existent subpattern\0"
-      "regular expression too large\0"
-      "parentheses nested too deeply"
-    ;
-
-    int i = code;
-    const char* text = errorTexts;
-    while (i > 1)
-        i -= !*text++;
-    return text;
-}
-
-/* Structure for passing "static" information around between the functions
-doing the compiling. */
-
-struct CompileData {
-    CompileData() {
-        top_backref = 0;
-        backrefMap = 0;
-        req_varyopt = 0;
-        needOuterBracket = false;
-        numCapturingBrackets = 0;
-    }
-    int top_backref;            /* Maximum back reference */
-    unsigned backrefMap;       /* Bitmap of low back refs */
-    int req_varyopt;            /* "After variable item" flag for reqbyte */
-    bool needOuterBracket;
-    int numCapturingBrackets;
-};
-
-/* Definitions to allow mutual recursion */
-
-static bool compileBracket(int, int*, unsigned char**, const UChar**, const UChar*, ErrorCode*, int, int*, int*, CompileData&);
-static bool bracketIsAnchored(const unsigned char* code);
-static bool bracketNeedsLineStart(const unsigned char* code, unsigned captureMap, unsigned backrefMap);
-static int bracketFindFirstAssertedCharacter(const unsigned char* code, bool inassert);
-
-/*************************************************
-*            Handle escapes                      *
-*************************************************/
-
-/* This function is called when a \ has been encountered. It either returns a
-positive value for a simple escape such as \n, or a negative value which
-encodes one of the more complicated things such as \d. When UTF-8 is enabled,
-a positive value greater than 255 may be returned. On entry, ptr is pointing at
-the \. On exit, it is on the final character of the escape sequence.
-
-Arguments:
-  ptrptr         points to the pattern position pointer
-  errorcodeptr   points to the errorcode variable
-  bracount       number of previous extracting brackets
-  options        the options bits
-  isclass        true if inside a character class
-
-Returns:         zero or positive => a data character
-                 negative => a special escape sequence
-                 on error, errorptr is set
-*/
-
-static int checkEscape(const UChar** ptrptr, const UChar* patternEnd, ErrorCode* errorcodeptr, int bracount, bool isclass)
-{
-    const UChar* ptr = *ptrptr + 1;
-
-    /* If backslash is at the end of the pattern, it's an error. */
-    if (ptr == patternEnd) {
-        *errorcodeptr = ERR1;
-        *ptrptr = ptr;
-        return 0;
-    }
-    
-    int c = *ptr;
-    
-    /* Non-alphamerics are literals. For digits or letters, do an initial lookup in
-     a table. A non-zero result is something that can be returned immediately.
-     Otherwise further processing may be required. */
-    
-    if (c < '0' || c > 'z') { /* Not alphameric */
-    } else if (int escapeValue = escapes[c - '0']) {
-        c = escapeValue;
-        if (isclass) {
-            if (-c == ESC_b)
-                c = '\b'; /* \b is backslash in a class */
-            else if (-c == ESC_B)
-                c = 'B'; /* and \B is a capital B in a class (in browsers event though ECMAScript 15.10.2.19 says it raises an error) */
-        }
-    /* Escapes that need further processing, or are illegal. */
-    
-    } else {
-        switch (c) {
-            case '1':
-            case '2':
-            case '3':
-            case '4':
-            case '5':
-            case '6':
-            case '7':
-            case '8':
-            case '9':
-                /* Escape sequences starting with a non-zero digit are backreferences,
-                 unless there are insufficient brackets, in which case they are octal
-                 escape sequences. Those sequences end on the first non-octal character
-                 or when we overflow 0-255, whichever comes first. */
-                
-                if (!isclass) {
-                    const UChar* oldptr = ptr;
-                    c -= '0';
-                    while ((ptr + 1 < patternEnd) && isASCIIDigit(ptr[1]) && c <= bracount)
-                        c = c * 10 + *(++ptr) - '0';
-                    if (c <= bracount) {
-                        c = -(ESC_REF + c);
-                        break;
-                    }
-                    ptr = oldptr;      /* Put the pointer back and fall through */
-                }
-                
-                /* Handle an octal number following \. If the first digit is 8 or 9,
-                 this is not octal. */
-                
-                if ((c = *ptr) >= '8')
-                    break;
-
-            /* \0 always starts an octal number, but we may drop through to here with a
-             larger first octal digit. */
-
-            case '0': {
-                c -= '0';
-                int i;
-                for (i = 1; i <= 2; ++i) {
-                    if (ptr + i >= patternEnd || ptr[i] < '0' || ptr[i] > '7')
-                        break;
-                    int cc = c * 8 + ptr[i] - '0';
-                    if (cc > 255)
-                        break;
-                    c = cc;
-                }
-                ptr += i - 1;
-                break;
-            }
-
-            case 'x': {
-                c = 0;
-                int i;
-                for (i = 1; i <= 2; ++i) {
-                    if (ptr + i >= patternEnd || !isASCIIHexDigit(ptr[i])) {
-                        c = 'x';
-                        i = 1;
-                        break;
-                    }
-                    int cc = ptr[i];
-                    if (cc >= 'a')
-                        cc -= 32;             /* Convert to upper case */
-                    c = c * 16 + cc - ((cc < 'A') ? '0' : ('A' - 10));
-                }
-                ptr += i - 1;
-                break;
-            }
-
-            case 'u': {
-                c = 0;
-                int i;
-                for (i = 1; i <= 4; ++i) {
-                    if (ptr + i >= patternEnd || !isASCIIHexDigit(ptr[i])) {
-                        c = 'u';
-                        i = 1;
-                        break;
-                    }
-                    int cc = ptr[i];
-                    if (cc >= 'a')
-                        cc -= 32;             /* Convert to upper case */
-                    c = c * 16 + cc - ((cc < 'A') ? '0' : ('A' - 10));
-                }
-                ptr += i - 1;
-                break;
-            }
-
-            case 'c':
-                if (++ptr == patternEnd) {
-                    *errorcodeptr = ERR2;
-                    return 0;
-                }
-                c = *ptr;
-                
-                /* A letter is upper-cased; then the 0x40 bit is flipped. This coding
-                 is ASCII-specific, but then the whole concept of \cx is ASCII-specific. */
-                c = toASCIIUpper(c) ^ 0x40;
-                break;
-            }
-    }
-    
-    *ptrptr = ptr;
-    return c;
-}
-
-/*************************************************
-*            Check for counted repeat            *
-*************************************************/
-
-/* This function is called when a '{' is encountered in a place where it might
-start a quantifier. It looks ahead to see if it really is a quantifier or not.
-It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd}
-where the ddds are digits.
-
-Arguments:
-  p         pointer to the first char after '{'
-
-Returns:    true or false
-*/
-
-static bool isCountedRepeat(const UChar* p, const UChar* patternEnd)
-{
-    if (p >= patternEnd || !isASCIIDigit(*p))
-        return false;
-    p++;
-    while (p < patternEnd && isASCIIDigit(*p))
-        p++;
-    if (p < patternEnd && *p == '}')
-        return true;
-    
-    if (p >= patternEnd || *p++ != ',')
-        return false;
-    if (p < patternEnd && *p == '}')
-        return true;
-    
-    if (p >= patternEnd || !isASCIIDigit(*p))
-        return false;
-    p++;
-    while (p < patternEnd && isASCIIDigit(*p))
-        p++;
-    
-    return (p < patternEnd && *p == '}');
-}
-
-/*************************************************
-*         Read repeat counts                     *
-*************************************************/
-
-/* Read an item of the form {n,m} and return the values. This is called only
-after isCountedRepeat() has confirmed that a repeat-count quantifier exists,
-so the syntax is guaranteed to be correct, but we need to check the values.
-
-Arguments:
-  p              pointer to first char after '{'
-  minp           pointer to int for min
-  maxp           pointer to int for max
-                 returned as -1 if no max
-  errorcodeptr   points to error code variable
-
-Returns:         pointer to '}' on success;
-                 current ptr on error, with errorcodeptr set non-zero
-*/
-
-static const UChar* readRepeatCounts(const UChar* p, int* minp, int* maxp, ErrorCode* errorcodeptr)
-{
-    int min = 0;
-    int max = -1;
-    
-    /* Read the minimum value and do a paranoid check: a negative value indicates
-     an integer overflow. */
-    
-    while (isASCIIDigit(*p))
-        min = min * 10 + *p++ - '0';
-    if (min < 0 || min > 65535) {
-        *errorcodeptr = ERR5;
-        return p;
-    }
-    
-    /* Read the maximum value if there is one, and again do a paranoid on its size.
-     Also, max must not be less than min. */
-    
-    if (*p == '}')
-        max = min;
-    else {
-        if (*(++p) != '}') {
-            max = 0;
-            while (isASCIIDigit(*p))
-                max = max * 10 + *p++ - '0';
-            if (max < 0 || max > 65535) {
-                *errorcodeptr = ERR5;
-                return p;
-            }
-            if (max < min) {
-                *errorcodeptr = ERR4;
-                return p;
-            }
-        }
-    }
-    
-    /* Fill in the required variables, and pass back the pointer to the terminating
-     '}'. */
-    
-    *minp = min;
-    *maxp = max;
-    return p;
-}
-
-/*************************************************
-*      Find first significant op code            *
-*************************************************/
-
-/* This is called by several functions that scan a compiled expression looking
-for a fixed first character, or an anchoring op code etc. It skips over things
-that do not influence this.
-
-Arguments:
-  code         pointer to the start of the group
-Returns:       pointer to the first significant opcode
-*/
-
-static const unsigned char* firstSignificantOpcode(const unsigned char* code)
-{
-    while (*code == OP_BRANUMBER)
-        code += 3;
-    return code;
-}
-
-static const unsigned char* firstSignificantOpcodeSkippingAssertions(const unsigned char* code)
-{
-    while (true) {
-        switch (*code) {
-            case OP_ASSERT_NOT:
-                advanceToEndOfBracket(code);
-                code += 1 + LINK_SIZE;
-                break;
-            case OP_WORD_BOUNDARY:
-            case OP_NOT_WORD_BOUNDARY:
-                ++code;
-                break;
-            case OP_BRANUMBER:
-                code += 3;
-                break;
-            default:
-                return code;
-        }
-    }
-}
-
-/*************************************************
-*           Get othercase range                  *
-*************************************************/
-
-/* This function is passed the start and end of a class range, in UTF-8 mode
-with UCP support. It searches up the characters, looking for internal ranges of
-characters in the "other" case. Each call returns the next one, updating the
-start address.
-
-Arguments:
-  cptr        points to starting character value; updated
-  d           end value
-  ocptr       where to put start of othercase range
-  odptr       where to put end of othercase range
-
-Yield:        true when range returned; false when no more
-*/
-
-static bool getOthercaseRange(int* cptr, int d, int* ocptr, int* odptr)
-{
-    int c, othercase = 0;
-    
-    for (c = *cptr; c <= d; c++) {
-        if ((othercase = kjs_pcre_ucp_othercase(c)) >= 0)
-            break;
-    }
-    
-    if (c > d)
-        return false;
-    
-    *ocptr = othercase;
-    int next = othercase + 1;
-    
-    for (++c; c <= d; c++) {
-        if (kjs_pcre_ucp_othercase(c) != next)
-            break;
-        next++;
-    }
-    
-    *odptr = next - 1;
-    *cptr = c;
-    
-    return true;
-}
-
-/*************************************************
- *       Convert character value to UTF-8         *
- *************************************************/
-
-/* This function takes an integer value in the range 0 - 0x7fffffff
- and encodes it as a UTF-8 character in 0 to 6 bytes.
- 
- Arguments:
- cvalue     the character value
- buffer     pointer to buffer for result - at least 6 bytes long
- 
- Returns:     number of characters placed in the buffer
- */
-
-static int encodeUTF8(int cvalue, unsigned char *buffer)
-{
-    int i;
-    for (i = 0; i < kjs_pcre_utf8_table1_size; i++)
-        if (cvalue <= kjs_pcre_utf8_table1[i])
-            break;
-    buffer += i;
-    for (int j = i; j > 0; j--) {
-        *buffer-- = 0x80 | (cvalue & 0x3f);
-        cvalue >>= 6;
-    }
-    *buffer = kjs_pcre_utf8_table2[i] | cvalue;
-    return i + 1;
-}
-
-/*************************************************
-*           Compile one branch                   *
-*************************************************/
-
-/* Scan the pattern, compiling it into the code vector.
-
-Arguments:
-  options        the option bits
-  brackets       points to number of extracting brackets used
-  codeptr        points to the pointer to the current code point
-  ptrptr         points to the current pattern pointer
-  errorcodeptr   points to error code variable
-  firstbyteptr   set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE)
-  reqbyteptr     set to the last literal character required, else < 0
-  cd             contains pointers to tables etc.
-
-Returns:         true on success
-                 false, with *errorcodeptr set non-zero on error
-*/
-
-static inline bool safelyCheckNextChar(const UChar* ptr, const UChar* patternEnd, UChar expected)
-{
-    return ((ptr + 1 < patternEnd) && ptr[1] == expected);
-}
-
-static bool
-compileBranch(int options, int* brackets, unsigned char** codeptr,
-               const UChar** ptrptr, const UChar* patternEnd, ErrorCode* errorcodeptr, int *firstbyteptr,
-               int* reqbyteptr, CompileData& cd)
-{
-    int repeat_type, op_type;
-    int repeat_min = 0, repeat_max = 0;      /* To please picky compilers */
-    int bravalue = 0;
-    int reqvary, tempreqvary;
-    int c;
-    unsigned char* code = *codeptr;
-    unsigned char* tempcode;
-    bool groupsetfirstbyte = false;
-    const UChar* ptr = *ptrptr;
-    unsigned char* previous = NULL;
-    unsigned char classbits[32];
-    
-    bool class_utf8;
-    unsigned char* class_utf8data;
-    unsigned char utf8_char[6];
-    
-    /* Initialize no first byte, no required byte. REQ_UNSET means "no char
-     matching encountered yet". It gets changed to REQ_NONE if we hit something that
-     matches a non-fixed char first char; reqbyte just remains unset if we never
-     find one.
-     
-     When we hit a repeat whose minimum is zero, we may have to adjust these values
-     to take the zero repeat into account. This is implemented by setting them to
-     zerofirstbyte and zeroreqbyte when such a repeat is encountered. The individual
-     item types that can be repeated set these backoff variables appropriately. */
-    
-    int firstbyte = REQ_UNSET;
-    int reqbyte = REQ_UNSET;
-    int zeroreqbyte = REQ_UNSET;
-    int zerofirstbyte = REQ_UNSET;
-    
-    /* The variable req_caseopt contains either the REQ_IGNORE_CASE value or zero,
-     according to the current setting of the ignores-case flag. REQ_IGNORE_CASE is a bit
-     value > 255. It is added into the firstbyte or reqbyte variables to record the
-     case status of the value. This is used only for ASCII characters. */
-    
-    int req_caseopt = (options & IgnoreCaseOption) ? REQ_IGNORE_CASE : 0;
-    
-    /* Switch on next character until the end of the branch */
-    
-    for (;; ptr++) {
-        bool negate_class;
-        bool should_flip_negation; /* If a negative special such as \S is used, we should negate the whole class to properly support Unicode. */
-        int class_charcount;
-        int class_lastchar;
-        int skipbytes;
-        int subreqbyte;
-        int subfirstbyte;
-        int mclength;
-        unsigned char mcbuffer[8];
-        
-        /* Next byte in the pattern */
-        
-        c = ptr < patternEnd ? *ptr : 0;
-        
-        /* Fill in length of a previous callout, except when the next thing is
-         a quantifier. */
-        
-        bool is_quantifier = c == '*' || c == '+' || c == '?' || (c == '{' && isCountedRepeat(ptr + 1, patternEnd));
-        
-        switch (c) {
-            /* The branch terminates at end of string, |, or ). */
-                
-            case 0:
-                if (ptr < patternEnd)
-                    goto NORMAL_CHAR;
-                // End of string; fall through
-            case '|':
-            case ')':
-                *firstbyteptr = firstbyte;
-                *reqbyteptr = reqbyte;
-                *codeptr = code;
-                *ptrptr = ptr;
-                return true;
-                
-            /* Handle single-character metacharacters. In multiline mode, ^ disables
-             the setting of any following char as a first character. */
-
-            case '^':
-                if (options & MatchAcrossMultipleLinesOption) {
-                    if (firstbyte == REQ_UNSET)
-                        firstbyte = REQ_NONE;
-                    *code++ = OP_BOL;
-                } else
-                    *code++ = OP_CIRC;
-                previous = NULL;
-                break;
-
-            case '$':
-                previous = NULL;
-                if (options & MatchAcrossMultipleLinesOption)
-                  *code++ = OP_EOL;
-                else
-                  *code++ = OP_DOLL;
-                break;
-
-            /* There can never be a first char if '.' is first, whatever happens about
-             repeats. The value of reqbyte doesn't change either. */
-
-            case '.':
-                if (firstbyte == REQ_UNSET)
-                    firstbyte = REQ_NONE;
-                zerofirstbyte = firstbyte;
-                zeroreqbyte = reqbyte;
-                previous = code;
-                *code++ = OP_NOT_NEWLINE;
-                break;
-                
-            /* Character classes. If the included characters are all < 256, we build a
-             32-byte bitmap of the permitted characters, except in the special case
-             where there is only one such character. For negated classes, we build the
-             map as usual, then invert it at the end. However, we use a different opcode
-             so that data characters > 255 can be handled correctly.
-             
-             If the class contains characters outside the 0-255 range, a different
-             opcode is compiled. It may optionally have a bit map for characters < 256,
-             but those above are are explicitly listed afterwards. A flag byte tells
-             whether the bitmap is present, and whether this is a negated class or not.
-             */
-                
-            case '[': {
-                previous = code;
-                should_flip_negation = false;
-                
-                /* PCRE supports POSIX class stuff inside a class. Perl gives an error if
-                 they are encountered at the top level, so we'll do that too. */
-                
-                /* If the first character is '^', set the negation flag and skip it. */
-
-                if (ptr + 1 >= patternEnd) {
-                    *errorcodeptr = ERR6;
-                    return false;
-                }
-
-                if (ptr[1] == '^') {
-                    negate_class = true;
-                    ++ptr;
-                } else
-                    negate_class = false;
-                
-                /* Keep a count of chars with values < 256 so that we can optimize the case
-                 of just a single character (as long as it's < 256). For higher valued UTF-8
-                 characters, we don't yet do any optimization. */
-                
-                class_charcount = 0;
-                class_lastchar = -1;
-                
-                class_utf8 = false;                       /* No chars >= 256 */
-                class_utf8data = code + LINK_SIZE + 34;   /* For UTF-8 items */
-                
-                /* Initialize the 32-char bit map to all zeros. We have to build the
-                 map in a temporary bit of store, in case the class contains only 1
-                 character (< 256), because in that case the compiled code doesn't use the
-                 bit map. */
-                
-                memset(classbits, 0, 32 * sizeof(unsigned char));
-                
-                /* Process characters until ] is reached. The first pass
-                 through the regex checked the overall syntax, so we don't need to be very
-                 strict here. At the start of the loop, c contains the first byte of the
-                 character. */
-
-                while ((++ptr < patternEnd) && (c = *ptr) != ']') {
-                    /* Backslash may introduce a single character, or it may introduce one
-                     of the specials, which just set a flag. Escaped items are checked for
-                     validity in the pre-compiling pass. The sequence \b is a special case.
-                     Inside a class (and only there) it is treated as backspace. Elsewhere
-                     it marks a word boundary. Other escapes have preset maps ready to
-                     or into the one we are building. We assume they have more than one
-                     character in them, so set class_charcount bigger than one. */
-                    
-                    if (c == '\\') {
-                        c = checkEscape(&ptr, patternEnd, errorcodeptr, cd.numCapturingBrackets, true);
-                        if (c < 0) {
-                            class_charcount += 2;     /* Greater than 1 is what matters */
-                            switch (-c) {
-                                case ESC_d:
-                                    for (c = 0; c < 32; c++)
-                                        classbits[c] |= classBitmapForChar(c + cbit_digit);
-                                    continue;
-                                    
-                                case ESC_D:
-                                    should_flip_negation = true;
-                                    for (c = 0; c < 32; c++)
-                                        classbits[c] |= ~classBitmapForChar(c + cbit_digit);
-                                    continue;
-                                    
-                                case ESC_w:
-                                    for (c = 0; c < 32; c++)
-                                        classbits[c] |= classBitmapForChar(c + cbit_word);
-                                    continue;
-                                    
-                                case ESC_W:
-                                    should_flip_negation = true;
-                                    for (c = 0; c < 32; c++)
-                                        classbits[c] |= ~classBitmapForChar(c + cbit_word);
-                                    continue;
-                                    
-                                case ESC_s:
-                                    for (c = 0; c < 32; c++)
-                                         classbits[c] |= classBitmapForChar(c + cbit_space);
-                                    continue;
-                                    
-                                case ESC_S:
-                                    should_flip_negation = true;
-                                    for (c = 0; c < 32; c++)
-                                         classbits[c] |= ~classBitmapForChar(c + cbit_space);
-                                    continue;
-                                    
-                                    /* Unrecognized escapes are faulted if PCRE is running in its
-                                     strict mode. By default, for compatibility with Perl, they are
-                                     treated as literals. */
-                                    
-                                default:
-                                    c = *ptr;              /* The final character */
-                                    class_charcount -= 2;  /* Undo the default count from above */
-                            }
-                        }
-                        
-                        /* Fall through if we have a single character (c >= 0). This may be
-                         > 256 in UTF-8 mode. */
-                        
-                    }   /* End of backslash handling */
-                    
-                    /* A single character may be followed by '-' to form a range. However,
-                     Perl does not permit ']' to be the end of the range. A '-' character
-                     here is treated as a literal. */
-                    
-                    if ((ptr + 2 < patternEnd) && ptr[1] == '-' && ptr[2] != ']') {
-                        ptr += 2;
-                        
-                        int d = *ptr;
-                        
-                        /* The second part of a range can be a single-character escape, but
-                         not any of the other escapes. Perl 5.6 treats a hyphen as a literal
-                         in such circumstances. */
-                        
-                        if (d == '\\') {
-                            const UChar* oldptr = ptr;
-                            d = checkEscape(&ptr, patternEnd, errorcodeptr, cd.numCapturingBrackets, true);
-                            
-                            /* \X is literal X; any other special means the '-' was literal */
-                            if (d < 0) {
-                                ptr = oldptr - 2;
-                                goto LONE_SINGLE_CHARACTER;  /* A few lines below */
-                            }
-                        }
-                        
-                        /* The check that the two values are in the correct order happens in
-                         the pre-pass. Optimize one-character ranges */
-                        
-                        if (d == c)
-                            goto LONE_SINGLE_CHARACTER;  /* A few lines below */
-                        
-                        /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless
-                         matching, we have to use an XCLASS with extra data items. Caseless
-                         matching for characters > 127 is available only if UCP support is
-                         available. */
-                        
-                        if ((d > 255 || ((options & IgnoreCaseOption) && d > 127))) {
-                            class_utf8 = true;
-                            
-                            /* With UCP support, we can find the other case equivalents of
-                             the relevant characters. There may be several ranges. Optimize how
-                             they fit with the basic range. */
-                            
-                            if (options & IgnoreCaseOption) {
-                                int occ, ocd;
-                                int cc = c;
-                                int origd = d;
-                                while (getOthercaseRange(&cc, origd, &occ, &ocd)) {
-                                    if (occ >= c && ocd <= d)
-                                        continue;  /* Skip embedded ranges */
-                                    
-                                    if (occ < c  && ocd >= c - 1)        /* Extend the basic range */
-                                    {                                  /* if there is overlap,   */
-                                        c = occ;                           /* noting that if occ < c */
-                                        continue;                          /* we can't have ocd > d  */
-                                    }                                  /* because a subrange is  */
-                                    if (ocd > d && occ <= d + 1)         /* always shorter than    */
-                                    {                                  /* the basic range.       */
-                                        d = ocd;
-                                        continue;
-                                    }
-                                    
-                                    if (occ == ocd)
-                                        *class_utf8data++ = XCL_SINGLE;
-                                    else {
-                                        *class_utf8data++ = XCL_RANGE;
-                                        class_utf8data += encodeUTF8(occ, class_utf8data);
-                                    }
-                                    class_utf8data += encodeUTF8(ocd, class_utf8data);
-                                }
-                            }
-                            
-                            /* Now record the original range, possibly modified for UCP caseless
-                             overlapping ranges. */
-                            
-                            *class_utf8data++ = XCL_RANGE;
-                            class_utf8data += encodeUTF8(c, class_utf8data);
-                            class_utf8data += encodeUTF8(d, class_utf8data);
-                            
-                            /* With UCP support, we are done. Without UCP support, there is no
-                             caseless matching for UTF-8 characters > 127; we can use the bit map
-                             for the smaller ones. */
-                            
-                            continue;    /* With next character in the class */
-                        }
-                        
-                        /* We use the bit map for all cases when not in UTF-8 mode; else
-                         ranges that lie entirely within 0-127 when there is UCP support; else
-                         for partial ranges without UCP support. */
-                        
-                        for (; c <= d; c++) {
-                            classbits[c/8] |= (1 << (c&7));
-                            if (options & IgnoreCaseOption) {
-                                int uc = flipCase(c);
-                                classbits[uc/8] |= (1 << (uc&7));
-                            }
-                            class_charcount++;                /* in case a one-char range */
-                            class_lastchar = c;
-                        }
-                        
-                        continue;   /* Go get the next char in the class */
-                    }
-                    
-                    /* Handle a lone single character - we can get here for a normal
-                     non-escape char, or after \ that introduces a single character or for an
-                     apparent range that isn't. */
-                    
-                LONE_SINGLE_CHARACTER:
-                    
-                    /* Handle a character that cannot go in the bit map */
-                    
-                    if ((c > 255 || ((options & IgnoreCaseOption) && c > 127))) {
-                        class_utf8 = true;
-                        *class_utf8data++ = XCL_SINGLE;
-                        class_utf8data += encodeUTF8(c, class_utf8data);
-                        
-                        if (options & IgnoreCaseOption) {
-                            int othercase;
-                            if ((othercase = kjs_pcre_ucp_othercase(c)) >= 0) {
-                                *class_utf8data++ = XCL_SINGLE;
-                                class_utf8data += encodeUTF8(othercase, class_utf8data);
-                            }
-                        }
-                    } else {
-                        /* Handle a single-byte character */
-                        classbits[c/8] |= (1 << (c&7));
-                        if (options & IgnoreCaseOption) {
-                            c = flipCase(c);
-                            classbits[c/8] |= (1 << (c&7));
-                        }
-                        class_charcount++;
-                        class_lastchar = c;
-                    }
-                }
-                
-                /* If class_charcount is 1, we saw precisely one character whose value is
-                 less than 256. In non-UTF-8 mode we can always optimize. In UTF-8 mode, we
-                 can optimize the negative case only if there were no characters >= 128
-                 because OP_NOT and the related opcodes like OP_NOTSTAR operate on
-                 single-bytes only. This is an historical hangover. Maybe one day we can
-                 tidy these opcodes to handle multi-byte characters.
-                 
-                 The optimization throws away the bit map. We turn the item into a
-                 1-character OP_CHAR[NC] if it's positive, or OP_NOT if it's negative. Note
-                 that OP_NOT does not support multibyte characters. In the positive case, it
-                 can cause firstbyte to be set. Otherwise, there can be no first char if
-                 this item is first, whatever repeat count may follow. In the case of
-                 reqbyte, save the previous value for reinstating. */
-                
-                if (class_charcount == 1 && (!class_utf8 && (!negate_class || class_lastchar < 128))) {
-                    zeroreqbyte = reqbyte;
-                    
-                    /* The OP_NOT opcode works on one-byte characters only. */
-                    
-                    if (negate_class) {
-                        if (firstbyte == REQ_UNSET)
-                            firstbyte = REQ_NONE;
-                        zerofirstbyte = firstbyte;
-                        *code++ = OP_NOT;
-                        *code++ = class_lastchar;
-                        break;
-                    }
-                    
-                    /* For a single, positive character, get the value into c, and
-                     then we can handle this with the normal one-character code. */
-                    
-                    c = class_lastchar;
-                    goto NORMAL_CHAR;
-                }       /* End of 1-char optimization */
-                
-                /* The general case - not the one-char optimization. If this is the first
-                 thing in the branch, there can be no first char setting, whatever the
-                 repeat count. Any reqbyte setting must remain unchanged after any kind of
-                 repeat. */
-                
-                if (firstbyte == REQ_UNSET) firstbyte = REQ_NONE;
-                zerofirstbyte = firstbyte;
-                zeroreqbyte = reqbyte;
-                
-                /* If there are characters with values > 255, we have to compile an
-                 extended class, with its own opcode. If there are no characters < 256,
-                 we can omit the bitmap. */
-                
-                if (class_utf8 && !should_flip_negation) {
-                    *class_utf8data++ = XCL_END;    /* Marks the end of extra data */
-                    *code++ = OP_XCLASS;
-                    code += LINK_SIZE;
-                    *code = negate_class? XCL_NOT : 0;
-                    
-                    /* If the map is required, install it, and move on to the end of
-                     the extra data */
-                    
-                    if (class_charcount > 0) {
-                        *code++ |= XCL_MAP;
-                        memcpy(code, classbits, 32);
-                        code = class_utf8data;
-                    }
-                    
-                    /* If the map is not required, slide down the extra data. */
-                    
-                    else {
-                        int len = class_utf8data - (code + 33);
-                        memmove(code + 1, code + 33, len);
-                        code += len + 1;
-                    }
-                    
-                    /* Now fill in the complete length of the item */
-                    
-                    putLinkValue(previous + 1, code - previous);
-                    break;   /* End of class handling */
-                }
-                
-                /* If there are no characters > 255, negate the 32-byte map if necessary,
-                 and copy it into the code vector. If this is the first thing in the branch,
-                 there can be no first char setting, whatever the repeat count. Any reqbyte
-                 setting must remain unchanged after any kind of repeat. */
-                
-                *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS;
-                if (negate_class)
-                    for (c = 0; c < 32; c++)
-                        code[c] = ~classbits[c];
-                else
-                    memcpy(code, classbits, 32);
-                code += 32;
-                break;
-            }
-                
-            /* Various kinds of repeat; '{' is not necessarily a quantifier, but this
-             has been tested above. */
-
-            case '{':
-                if (!is_quantifier)
-                    goto NORMAL_CHAR;
-                ptr = readRepeatCounts(ptr + 1, &repeat_min, &repeat_max, errorcodeptr);
-                if (*errorcodeptr)
-                    goto FAILED;
-                goto REPEAT;
-                
-            case '*':
-                repeat_min = 0;
-                repeat_max = -1;
-                goto REPEAT;
-                
-            case '+':
-                repeat_min = 1;
-                repeat_max = -1;
-                goto REPEAT;
-                
-            case '?':
-                repeat_min = 0;
-                repeat_max = 1;
-                
-            REPEAT:
-                if (!previous) {
-                    *errorcodeptr = ERR9;
-                    goto FAILED;
-                }
-                
-                if (repeat_min == 0) {
-                    firstbyte = zerofirstbyte;    /* Adjust for zero repeat */
-                    reqbyte = zeroreqbyte;        /* Ditto */
-                }
-                
-                /* Remember whether this is a variable length repeat */
-                
-                reqvary = (repeat_min == repeat_max) ? 0 : REQ_VARY;
-                
-                op_type = 0;                    /* Default single-char op codes */
-                
-                /* Save start of previous item, in case we have to move it up to make space
-                 for an inserted OP_ONCE for the additional '+' extension. */
-                /* FIXME: Probably don't need this because we don't use OP_ONCE. */
-                
-                tempcode = previous;
-                
-                /* If the next character is '+', we have a possessive quantifier. This
-                 implies greediness, whatever the setting of the PCRE_UNGREEDY option.
-                 If the next character is '?' this is a minimizing repeat, by default,
-                 but if PCRE_UNGREEDY is set, it works the other way round. We change the
-                 repeat type to the non-default. */
-                
-                if (safelyCheckNextChar(ptr, patternEnd, '?')) {
-                    repeat_type = 1;
-                    ptr++;
-                } else
-                    repeat_type = 0;
-                
-                /* If previous was a character match, abolish the item and generate a
-                 repeat item instead. If a char item has a minumum of more than one, ensure
-                 that it is set in reqbyte - it might not be if a sequence such as x{3} is
-                 the first thing in a branch because the x will have gone into firstbyte
-                 instead.  */
-                
-                if (*previous == OP_CHAR || *previous == OP_CHAR_IGNORING_CASE) {
-                    /* Deal with UTF-8 characters that take up more than one byte. It's
-                     easier to write this out separately than try to macrify it. Use c to
-                     hold the length of the character in bytes, plus 0x80 to flag that it's a
-                     length rather than a small character. */
-                    
-                    if (code[-1] & 0x80) {
-                        unsigned char *lastchar = code - 1;
-                        while((*lastchar & 0xc0) == 0x80)
-                            lastchar--;
-                        c = code - lastchar;            /* Length of UTF-8 character */
-                        memcpy(utf8_char, lastchar, c); /* Save the char */
-                        c |= 0x80;                      /* Flag c as a length */
-                    }
-                    else {
-                        c = code[-1];
-                        if (repeat_min > 1)
-                            reqbyte = c | req_caseopt | cd.req_varyopt;
-                    }
-                    
-                    goto OUTPUT_SINGLE_REPEAT;   /* Code shared with single character types */
-                }
-                
-                else if (*previous == OP_ASCII_CHAR || *previous == OP_ASCII_LETTER_IGNORING_CASE) {
-                    c = previous[1];
-                    if (repeat_min > 1)
-                        reqbyte = c | req_caseopt | cd.req_varyopt;
-                    goto OUTPUT_SINGLE_REPEAT;
-                }
-                
-                /* If previous was a single negated character ([^a] or similar), we use
-                 one of the special opcodes, replacing it. The code is shared with single-
-                 character repeats by setting opt_type to add a suitable offset into
-                 repeat_type. OP_NOT is currently used only for single-byte chars. */
-                
-                else if (*previous == OP_NOT) {
-                    op_type = OP_NOTSTAR - OP_STAR;  /* Use "not" opcodes */
-                    c = previous[1];
-                    goto OUTPUT_SINGLE_REPEAT;
-                }
-                
-                /* If previous was a character type match (\d or similar), abolish it and
-                 create a suitable repeat item. The code is shared with single-character
-                 repeats by setting op_type to add a suitable offset into repeat_type. */
-                
-                else if (*previous <= OP_NOT_NEWLINE) {
-                    op_type = OP_TYPESTAR - OP_STAR;  /* Use type opcodes */
-                    c = *previous;
-                    
-                OUTPUT_SINGLE_REPEAT:
-                    int prop_type = -1;
-                    int prop_value = -1;
-                    
-                    unsigned char* oldcode = code;
-                    code = previous;                  /* Usually overwrite previous item */
-                    
-                    /* If the maximum is zero then the minimum must also be zero; Perl allows
-                     this case, so we do too - by simply omitting the item altogether. */
-                    
-                    if (repeat_max == 0)
-                        goto END_REPEAT;
-                    
-                    /* Combine the op_type with the repeat_type */
-                    
-                    repeat_type += op_type;
-                    
-                    /* A minimum of zero is handled either as the special case * or ?, or as
-                     an UPTO, with the maximum given. */
-                    
-                    if (repeat_min == 0) {
-                        if (repeat_max == -1)
-                            *code++ = OP_STAR + repeat_type;
-                        else if (repeat_max == 1)
-                            *code++ = OP_QUERY + repeat_type;
-                        else {
-                            *code++ = OP_UPTO + repeat_type;
-                            put2ByteValueAndAdvance(code, repeat_max);
-                        }
-                    }
-                    
-                    /* A repeat minimum of 1 is optimized into some special cases. If the
-                     maximum is unlimited, we use OP_PLUS. Otherwise, the original item it
-                     left in place and, if the maximum is greater than 1, we use OP_UPTO with
-                     one less than the maximum. */
-                    
-                    else if (repeat_min == 1) {
-                        if (repeat_max == -1)
-                            *code++ = OP_PLUS + repeat_type;
-                        else {
-                            code = oldcode;                 /* leave previous item in place */
-                            if (repeat_max == 1)
-                                goto END_REPEAT;
-                            *code++ = OP_UPTO + repeat_type;
-                            put2ByteValueAndAdvance(code, repeat_max - 1);
-                        }
-                    }
-                    
-                    /* The case {n,n} is just an EXACT, while the general case {n,m} is
-                     handled as an EXACT followed by an UPTO. */
-                    
-                    else {
-                        *code++ = OP_EXACT + op_type;  /* NB EXACT doesn't have repeat_type */
-                        put2ByteValueAndAdvance(code, repeat_min);
-                        
-                        /* If the maximum is unlimited, insert an OP_STAR. Before doing so,
-                         we have to insert the character for the previous code. For a repeated
-                         Unicode property match, there are two extra bytes that define the
-                         required property. In UTF-8 mode, long characters have their length in
-                         c, with the 0x80 bit as a flag. */
-                        
-                        if (repeat_max < 0) {
-                            if (c >= 128) {
-                                memcpy(code, utf8_char, c & 7);
-                                code += c & 7;
-                            } else {
-                                *code++ = c;
-                                if (prop_type >= 0) {
-                                    *code++ = prop_type;
-                                    *code++ = prop_value;
-                                }
-                            }
-                            *code++ = OP_STAR + repeat_type;
-                        }
-                        
-                        /* Else insert an UPTO if the max is greater than the min, again
-                         preceded by the character, for the previously inserted code. */
-                        
-                        else if (repeat_max != repeat_min) {
-                            if (c >= 128) {
-                                memcpy(code, utf8_char, c & 7);
-                                code += c & 7;
-                            } else
-                                *code++ = c;
-                            if (prop_type >= 0) {
-                                *code++ = prop_type;
-                                *code++ = prop_value;
-                            }
-                            repeat_max -= repeat_min;
-                            *code++ = OP_UPTO + repeat_type;
-                            put2ByteValueAndAdvance(code, repeat_max);
-                        }
-                    }
-                    
-                    /* The character or character type itself comes last in all cases. */
-                    
-                    if (c >= 128) {
-                        memcpy(code, utf8_char, c & 7);
-                        code += c & 7;
-                    } else
-                        *code++ = c;
-                    
-                    /* For a repeated Unicode property match, there are two extra bytes that
-                     define the required property. */
-                    
-                    if (prop_type >= 0) {
-                        *code++ = prop_type;
-                        *code++ = prop_value;
-                    }
-                }
-                
-                /* If previous was a character class or a back reference, we put the repeat
-                 stuff after it, but just skip the item if the repeat was {0,0}. */
-                
-                else if (*previous == OP_CLASS ||
-                         *previous == OP_NCLASS ||
-                         *previous == OP_XCLASS ||
-                         *previous == OP_REF)
-                {
-                    if (repeat_max == 0) {
-                        code = previous;
-                        goto END_REPEAT;
-                    }
-                    
-                    if (repeat_min == 0 && repeat_max == -1)
-                        *code++ = OP_CRSTAR + repeat_type;
-                    else if (repeat_min == 1 && repeat_max == -1)
-                        *code++ = OP_CRPLUS + repeat_type;
-                    else if (repeat_min == 0 && repeat_max == 1)
-                        *code++ = OP_CRQUERY + repeat_type;
-                    else {
-                        *code++ = OP_CRRANGE + repeat_type;
-                        put2ByteValueAndAdvance(code, repeat_min);
-                        if (repeat_max == -1)
-                            repeat_max = 0;  /* 2-byte encoding for max */
-                        put2ByteValueAndAdvance(code, repeat_max);
-                    }
-                }
-                
-                /* If previous was a bracket group, we may have to replicate it in certain
-                 cases. */
-                
-                else if (*previous >= OP_BRA) {
-                    int ketoffset = 0;
-                    int len = code - previous;
-                    unsigned char* bralink = NULL;
-                    
-                    /* If the maximum repeat count is unlimited, find the end of the bracket
-                     by scanning through from the start, and compute the offset back to it
-                     from the current code pointer. There may be an OP_OPT setting following
-                     the final KET, so we can't find the end just by going back from the code
-                     pointer. */
-                    
-                    if (repeat_max == -1) {
-                        const unsigned char* ket = previous;
-                        advanceToEndOfBracket(ket);
-                        ketoffset = code - ket;
-                    }
-                    
-                    /* The case of a zero minimum is special because of the need to stick
-                     OP_BRAZERO in front of it, and because the group appears once in the
-                     data, whereas in other cases it appears the minimum number of times. For
-                     this reason, it is simplest to treat this case separately, as otherwise
-                     the code gets far too messy. There are several special subcases when the
-                     minimum is zero. */
-                    
-                    if (repeat_min == 0) {
-                        /* If the maximum is also zero, we just omit the group from the output
-                         altogether. */
-                        
-                        if (repeat_max == 0) {
-                            code = previous;
-                            goto END_REPEAT;
-                        }
-                        
-                        /* If the maximum is 1 or unlimited, we just have to stick in the
-                         BRAZERO and do no more at this point. However, we do need to adjust
-                         any OP_RECURSE calls inside the group that refer to the group itself or
-                         any internal group, because the offset is from the start of the whole
-                         regex. Temporarily terminate the pattern while doing this. */
-                        
-                        if (repeat_max <= 1) {
-                            *code = OP_END;
-                            memmove(previous+1, previous, len);
-                            code++;
-                            *previous++ = OP_BRAZERO + repeat_type;
-                        }
-                        
-                        /* If the maximum is greater than 1 and limited, we have to replicate
-                         in a nested fashion, sticking OP_BRAZERO before each set of brackets.
-                         The first one has to be handled carefully because it's the original
-                         copy, which has to be moved up. The remainder can be handled by code
-                         that is common with the non-zero minimum case below. We have to
-                         adjust the value of repeat_max, since one less copy is required. */
-                        
-                        else {
-                            *code = OP_END;
-                            memmove(previous + 2 + LINK_SIZE, previous, len);
-                            code += 2 + LINK_SIZE;
-                            *previous++ = OP_BRAZERO + repeat_type;
-                            *previous++ = OP_BRA;
-                            
-                            /* We chain together the bracket offset fields that have to be
-                             filled in later when the ends of the brackets are reached. */
-                            
-                            int offset = (!bralink) ? 0 : previous - bralink;
-                            bralink = previous;
-                            putLinkValueAllowZeroAndAdvance(previous, offset);
-                        }
-                        
-                        repeat_max--;
-                    }
-                    
-                    /* If the minimum is greater than zero, replicate the group as many
-                     times as necessary, and adjust the maximum to the number of subsequent
-                     copies that we need. If we set a first char from the group, and didn't
-                     set a required char, copy the latter from the former. */
-                    
-                    else {
-                        if (repeat_min > 1) {
-                            if (groupsetfirstbyte && reqbyte < 0)
-                                reqbyte = firstbyte;
-                            for (int i = 1; i < repeat_min; i++) {
-                                memcpy(code, previous, len);
-                                code += len;
-                            }
-                        }
-                        if (repeat_max > 0)
-                            repeat_max -= repeat_min;
-                    }
-                    
-                    /* This code is common to both the zero and non-zero minimum cases. If
-                     the maximum is limited, it replicates the group in a nested fashion,
-                     remembering the bracket starts on a stack. In the case of a zero minimum,
-                     the first one was set up above. In all cases the repeat_max now specifies
-                     the number of additional copies needed. */
-                    
-                    if (repeat_max >= 0) {
-                        for (int i = repeat_max - 1; i >= 0; i--) {
-                            *code++ = OP_BRAZERO + repeat_type;
-                            
-                            /* All but the final copy start a new nesting, maintaining the
-                             chain of brackets outstanding. */
-                            
-                            if (i != 0) {
-                                *code++ = OP_BRA;
-                                int offset = (!bralink) ? 0 : code - bralink;
-                                bralink = code;
-                                putLinkValueAllowZeroAndAdvance(code, offset);
-                            }
-                            
-                            memcpy(code, previous, len);
-                            code += len;
-                        }
-                        
-                        /* Now chain through the pending brackets, and fill in their length
-                         fields (which are holding the chain links pro tem). */
-                        
-                        while (bralink) {
-                            int offset = code - bralink + 1;
-                            unsigned char* bra = code - offset;
-                            int oldlinkoffset = getLinkValueAllowZero(bra + 1);
-                            bralink = (!oldlinkoffset) ? 0 : bralink - oldlinkoffset;
-                            *code++ = OP_KET;
-                            putLinkValueAndAdvance(code, offset);
-                            putLinkValue(bra + 1, offset);
-                        }
-                    }
-                    
-                    /* If the maximum is unlimited, set a repeater in the final copy. We
-                     can't just offset backwards from the current code point, because we
-                     don't know if there's been an options resetting after the ket. The
-                     correct offset was computed above. */
-                    
-                    else
-                        code[-ketoffset] = OP_KETRMAX + repeat_type;
-                }
-                
-                /* Else there's some kind of shambles */
-                
-                else {
-                    *errorcodeptr = ERR11;
-                    goto FAILED;
-                }
-                
-                /* In all case we no longer have a previous item. We also set the
-                 "follows varying string" flag for subsequently encountered reqbytes if
-                 it isn't already set and we have just passed a varying length item. */
-                
-            END_REPEAT:
-                previous = NULL;
-                cd.req_varyopt |= reqvary;
-                break;
-                
-            /* Start of nested bracket sub-expression, or comment or lookahead or
-             lookbehind or option setting or condition. First deal with special things
-             that can come after a bracket; all are introduced by ?, and the appearance
-             of any of them means that this is not a referencing group. They were
-             checked for validity in the first pass over the string, so we don't have to
-             check for syntax errors here.  */
-                
-            case '(':
-                skipbytes = 0;
-                
-                if (*(++ptr) == '?') {
-                    switch (*(++ptr)) {
-                        case ':':                 /* Non-extracting bracket */
-                            bravalue = OP_BRA;
-                            ptr++;
-                            break;
-                            
-                        case '=':                 /* Positive lookahead */
-                            bravalue = OP_ASSERT;
-                            ptr++;
-                            break;
-                            
-                        case '!':                 /* Negative lookahead */
-                            bravalue = OP_ASSERT_NOT;
-                            ptr++;
-                            break;
-                            
-                        /* Character after (? not specially recognized */
-                            
-                        default:
-                            *errorcodeptr = ERR12;
-                            goto FAILED;
-                        }
-                }
-                
-                /* Else we have a referencing group; adjust the opcode. If the bracket
-                 number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and
-                 arrange for the true number to follow later, in an OP_BRANUMBER item. */
-                
-                else {
-                    if (++(*brackets) > EXTRACT_BASIC_MAX) {
-                        bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1;
-                        code[1 + LINK_SIZE] = OP_BRANUMBER;
-                        put2ByteValue(code + 2 + LINK_SIZE, *brackets);
-                        skipbytes = 3;
-                    }
-                    else
-                        bravalue = OP_BRA + *brackets;
-                }
-                
-                /* Process nested bracketed re. Assertions may not be repeated, but other
-                 kinds can be. We copy code into a non-variable in order to be able
-                 to pass its address because some compilers complain otherwise. Pass in a
-                 new setting for the ims options if they have changed. */
-                
-                previous = (bravalue >= OP_BRAZERO) ? code : 0;
-                *code = bravalue;
-                tempcode = code;
-                tempreqvary = cd.req_varyopt;     /* Save value before bracket */
-                
-                if (!compileBracket(
-                                   options,
-                                   brackets,                     /* Extracting bracket count */
-                                   &tempcode,                    /* Where to put code (updated) */
-                                   &ptr,                         /* Input pointer (updated) */
-                                   patternEnd,
-                                   errorcodeptr,                 /* Where to put an error message */
-                                   skipbytes,                    /* Skip over OP_BRANUMBER */
-                                   &subfirstbyte,                /* For possible first char */
-                                   &subreqbyte,                  /* For possible last char */
-                                   cd))                          /* Tables block */
-                    goto FAILED;
-                
-                /* At the end of compiling, code is still pointing to the start of the
-                 group, while tempcode has been updated to point past the end of the group
-                 and any option resetting that may follow it. The pattern pointer (ptr)
-                 is on the bracket. */
-                
-                /* Handle updating of the required and first characters. Update for normal
-                 brackets of all kinds, and conditions with two branches (see code above).
-                 If the bracket is followed by a quantifier with zero repeat, we have to
-                 back off. Hence the definition of zeroreqbyte and zerofirstbyte outside the
-                 main loop so that they can be accessed for the back off. */
-                
-                zeroreqbyte = reqbyte;
-                zerofirstbyte = firstbyte;
-                groupsetfirstbyte = false;
-                
-                if (bravalue >= OP_BRA) {
-                    /* If we have not yet set a firstbyte in this branch, take it from the
-                     subpattern, remembering that it was set here so that a repeat of more
-                     than one can replicate it as reqbyte if necessary. If the subpattern has
-                     no firstbyte, set "none" for the whole branch. In both cases, a zero
-                     repeat forces firstbyte to "none". */
-                    
-                    if (firstbyte == REQ_UNSET) {
-                        if (subfirstbyte >= 0) {
-                            firstbyte = subfirstbyte;
-                            groupsetfirstbyte = true;
-                        }
-                        else
-                            firstbyte = REQ_NONE;
-                        zerofirstbyte = REQ_NONE;
-                    }
-                    
-                    /* If firstbyte was previously set, convert the subpattern's firstbyte
-                     into reqbyte if there wasn't one, using the vary flag that was in
-                     existence beforehand. */
-                    
-                    else if (subfirstbyte >= 0 && subreqbyte < 0)
-                        subreqbyte = subfirstbyte | tempreqvary;
-                    
-                    /* If the subpattern set a required byte (or set a first byte that isn't
-                     really the first byte - see above), set it. */
-                    
-                    if (subreqbyte >= 0)
-                        reqbyte = subreqbyte;
-                }
-                
-                /* For a forward assertion, we take the reqbyte, if set. This can be
-                 helpful if the pattern that follows the assertion doesn't set a different
-                 char. For example, it's useful for /(?=abcde).+/. We can't set firstbyte
-                 for an assertion, however because it leads to incorrect effect for patterns
-                 such as /(?=a)a.+/ when the "real" "a" would then become a reqbyte instead
-                 of a firstbyte. This is overcome by a scan at the end if there's no
-                 firstbyte, looking for an asserted first char. */
-                
-                else if (bravalue == OP_ASSERT && subreqbyte >= 0)
-                    reqbyte = subreqbyte;
-                
-                /* Now update the main code pointer to the end of the group. */
-                
-                code = tempcode;
-                
-                /* Error if hit end of pattern */
-                
-                if (ptr >= patternEnd || *ptr != ')') {
-                    *errorcodeptr = ERR14;
-                    goto FAILED;
-                }
-                break;
-                
-            /* Check \ for being a real metacharacter; if not, fall through and handle
-             it as a data character at the start of a string. Escape items are checked
-             for validity in the pre-compiling pass. */
-                
-            case '\\':
-                c = checkEscape(&ptr, patternEnd, errorcodeptr, cd.numCapturingBrackets, false);
-                
-                /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values
-                 are arranged to be the negation of the corresponding OP_values. For the
-                 back references, the values are ESC_REF plus the reference number. Only
-                 back references and those types that consume a character may be repeated.
-                 We can test for values between ESC_b and ESC_w for the latter; this may
-                 have to change if any new ones are ever created. */
-                
-                if (c < 0) {
-                    /* For metasequences that actually match a character, we disable the
-                     setting of a first character if it hasn't already been set. */
-                    
-                    if (firstbyte == REQ_UNSET && -c > ESC_b && -c <= ESC_w)
-                        firstbyte = REQ_NONE;
-                    
-                    /* Set values to reset to if this is followed by a zero repeat. */
-                    
-                    zerofirstbyte = firstbyte;
-                    zeroreqbyte = reqbyte;
-                    
-                    /* Back references are handled specially */
-                    
-                    if (-c >= ESC_REF) {
-                        int number = -c - ESC_REF;
-                        previous = code;
-                        *code++ = OP_REF;
-                        put2ByteValueAndAdvance(code, number);
-                    }
-                    
-                    /* For the rest, we can obtain the OP value by negating the escape
-                     value */
-                    
-                    else {
-                        previous = (-c > ESC_b && -c <= ESC_w) ? code : NULL;
-                        *code++ = -c;
-                    }
-                    continue;
-                }
-                
-                /* Fall through. */
-                
-                /* Handle a literal character. It is guaranteed not to be whitespace or #
-                 when the extended flag is set. If we are in UTF-8 mode, it may be a
-                 multi-byte literal character. */
-                
-                default:
-            NORMAL_CHAR:
-                
-                previous = code;
-                
-                if (c < 128) {
-                    mclength = 1;
-                    mcbuffer[0] = c;
-                    
-                    if ((options & IgnoreCaseOption) && (c | 0x20) >= 'a' && (c | 0x20) <= 'z') {
-                        *code++ = OP_ASCII_LETTER_IGNORING_CASE;
-                        *code++ = c | 0x20;
-                    } else {
-                        *code++ = OP_ASCII_CHAR;
-                        *code++ = c;
-                    }
-                } else {
-                    mclength = encodeUTF8(c, mcbuffer);
-                    
-                    *code++ = (options & IgnoreCaseOption) ? OP_CHAR_IGNORING_CASE : OP_CHAR;
-                    for (c = 0; c < mclength; c++)
-                        *code++ = mcbuffer[c];
-                }
-                
-                /* Set the first and required bytes appropriately. If no previous first
-                 byte, set it from this character, but revert to none on a zero repeat.
-                 Otherwise, leave the firstbyte value alone, and don't change it on a zero
-                 repeat. */
-                
-                if (firstbyte == REQ_UNSET) {
-                    zerofirstbyte = REQ_NONE;
-                    zeroreqbyte = reqbyte;
-                    
-                    /* If the character is more than one byte long, we can set firstbyte
-                     only if it is not to be matched caselessly. */
-                    
-                    if (mclength == 1 || req_caseopt == 0) {
-                        firstbyte = mcbuffer[0] | req_caseopt;
-                        if (mclength != 1)
-                            reqbyte = code[-1] | cd.req_varyopt;
-                    }
-                    else
-                        firstbyte = reqbyte = REQ_NONE;
-                }
-                
-                /* firstbyte was previously set; we can set reqbyte only the length is
-                 1 or the matching is caseful. */
-                
-                else {
-                    zerofirstbyte = firstbyte;
-                    zeroreqbyte = reqbyte;
-                    if (mclength == 1 || req_caseopt == 0)
-                        reqbyte = code[-1] | req_caseopt | cd.req_varyopt;
-                }
-                
-                break;            /* End of literal character handling */
-        }
-    }                   /* end of big loop */
-    
-    /* Control never reaches here by falling through, only by a goto for all the
-     error states. Pass back the position in the pattern so that it can be displayed
-     to the user for diagnosing the error. */
-    
-FAILED:
-    *ptrptr = ptr;
-    return false;
-}
-
-/*************************************************
-*     Compile sequence of alternatives           *
-*************************************************/
-
-/* On entry, ptr is pointing past the bracket character, but on return
-it points to the closing bracket, or vertical bar, or end of string.
-The code variable is pointing at the byte into which the BRA operator has been
-stored. If the ims options are changed at the start (for a (?ims: group) or
-during any branch, we need to insert an OP_OPT item at the start of every
-following branch to ensure they get set correctly at run time, and also pass
-the new options into every subsequent branch compile.
-
-Argument:
-  options        option bits, including any changes for this subpattern
-  brackets       -> int containing the number of extracting brackets used
-  codeptr        -> the address of the current code pointer
-  ptrptr         -> the address of the current pattern pointer
-  errorcodeptr   -> pointer to error code variable
-  skipbytes      skip this many bytes at start (for OP_BRANUMBER)
-  firstbyteptr   place to put the first required character, or a negative number
-  reqbyteptr     place to put the last required character, or a negative number
-  cd             points to the data block with tables pointers etc.
-
-Returns:      true on success
-*/
-
-static bool
-compileBracket(int options, int* brackets, unsigned char** codeptr,
-    const UChar** ptrptr, const UChar* patternEnd, ErrorCode* errorcodeptr, int skipbytes,
-    int* firstbyteptr, int* reqbyteptr, CompileData& cd)
-{
-    const UChar* ptr = *ptrptr;
-    unsigned char* code = *codeptr;
-    unsigned char* last_branch = code;
-    unsigned char* start_bracket = code;
-    int firstbyte = REQ_UNSET;
-    int reqbyte = REQ_UNSET;
-    
-    /* Offset is set zero to mark that this bracket is still open */
-    
-    putLinkValueAllowZero(code + 1, 0);
-    code += 1 + LINK_SIZE + skipbytes;
-    
-    /* Loop for each alternative branch */
-    
-    while (true) {
-        /* Now compile the branch */
-        
-        int branchfirstbyte;
-        int branchreqbyte;
-        if (!compileBranch(options, brackets, &code, &ptr, patternEnd, errorcodeptr,
-                            &branchfirstbyte, &branchreqbyte, cd)) {
-            *ptrptr = ptr;
-            return false;
-        }
-        
-        /* If this is the first branch, the firstbyte and reqbyte values for the
-         branch become the values for the regex. */
-        
-        if (*last_branch != OP_ALT) {
-            firstbyte = branchfirstbyte;
-            reqbyte = branchreqbyte;
-        }
-        
-        /* If this is not the first branch, the first char and reqbyte have to
-         match the values from all the previous branches, except that if the previous
-         value for reqbyte didn't have REQ_VARY set, it can still match, and we set
-         REQ_VARY for the regex. */
-        
-        else {
-            /* If we previously had a firstbyte, but it doesn't match the new branch,
-             we have to abandon the firstbyte for the regex, but if there was previously
-             no reqbyte, it takes on the value of the old firstbyte. */
-            
-            if (firstbyte >= 0 && firstbyte != branchfirstbyte) {
-                if (reqbyte < 0)
-                    reqbyte = firstbyte;
-                firstbyte = REQ_NONE;
-            }
-            
-            /* If we (now or from before) have no firstbyte, a firstbyte from the
-             branch becomes a reqbyte if there isn't a branch reqbyte. */
-            
-            if (firstbyte < 0 && branchfirstbyte >= 0 && branchreqbyte < 0)
-                branchreqbyte = branchfirstbyte;
-            
-            /* Now ensure that the reqbytes match */
-            
-            if ((reqbyte & ~REQ_VARY) != (branchreqbyte & ~REQ_VARY))
-                reqbyte = REQ_NONE;
-            else
-                reqbyte |= branchreqbyte;   /* To "or" REQ_VARY */
-        }
-        
-        /* Reached end of expression, either ')' or end of pattern. Go back through
-         the alternative branches and reverse the chain of offsets, with the field in
-         the BRA item now becoming an offset to the first alternative. If there are
-         no alternatives, it points to the end of the group. The length in the
-         terminating ket is always the length of the whole bracketed item. If any of
-         the ims options were changed inside the group, compile a resetting op-code
-         following, except at the very end of the pattern. Return leaving the pointer
-         at the terminating char. */
-        
-        if (ptr >= patternEnd || *ptr != '|') {
-            int length = code - last_branch;
-            do {
-                int prev_length = getLinkValueAllowZero(last_branch + 1);
-                putLinkValue(last_branch + 1, length);
-                length = prev_length;
-                last_branch -= length;
-            } while (length > 0);
-            
-            /* Fill in the ket */
-            
-            *code = OP_KET;
-            putLinkValue(code + 1, code - start_bracket);
-            code += 1 + LINK_SIZE;
-            
-            /* Set values to pass back */
-            
-            *codeptr = code;
-            *ptrptr = ptr;
-            *firstbyteptr = firstbyte;
-            *reqbyteptr = reqbyte;
-            return true;
-        }
-        
-        /* Another branch follows; insert an "or" node. Its length field points back
-         to the previous branch while the bracket remains open. At the end the chain
-         is reversed. It's done like this so that the start of the bracket has a
-         zero offset until it is closed, making it possible to detect recursion. */
-        
-        *code = OP_ALT;
-        putLinkValue(code + 1, code - last_branch);
-        last_branch = code;
-        code += 1 + LINK_SIZE;
-        ptr++;
-    }
-    ASSERT_NOT_REACHED();
-}
-
-/*************************************************
-*          Check for anchored expression         *
-*************************************************/
-
-/* Try to find out if this is an anchored regular expression. Consider each
-alternative branch. If they all start OP_CIRC, or with a bracket
-all of whose alternatives start OP_CIRC (recurse ad lib), then
-it's anchored.
-
-Arguments:
-  code          points to start of expression (the bracket)
-  captureMap    a bitmap of which brackets we are inside while testing; this
-                 handles up to substring 31; all brackets after that share
-                 the zero bit
-  backrefMap    the back reference bitmap
-*/
-
-static bool branchIsAnchored(const unsigned char* code)
-{
-    const unsigned char* scode = firstSignificantOpcode(code);
-    int op = *scode;
-
-    /* Brackets */
-    if (op >= OP_BRA || op == OP_ASSERT)
-        return bracketIsAnchored(scode);
-
-    /* Check for explicit anchoring */    
-    return op == OP_CIRC;
-}
-
-static bool bracketIsAnchored(const unsigned char* code)
-{
-    do {
-        if (!branchIsAnchored(code + 1 + LINK_SIZE))
-            return false;
-        code += getLinkValue(code + 1);
-    } while (*code == OP_ALT);   /* Loop for each alternative */
-    return true;
-}
-
-/*************************************************
-*         Check for starting with ^ or .*        *
-*************************************************/
-
-/* This is called to find out if every branch starts with ^ or .* so that
-"first char" processing can be done to speed things up in multiline
-matching and for non-DOTALL patterns that start with .* (which must start at
-the beginning or after \n)
-
-Except when the .* appears inside capturing parentheses, and there is a
-subsequent back reference to those parentheses. By keeping a bitmap of the
-first 31 back references, we can catch some of the more common cases more
-precisely; all the greater back references share a single bit.
-
-Arguments:
-  code          points to start of expression (the bracket)
-  captureMap    a bitmap of which brackets we are inside while testing; this
-                 handles up to substring 31; all brackets after that share
-                 the zero bit
-  backrefMap    the back reference bitmap
-*/
-
-static bool branchNeedsLineStart(const unsigned char* code, unsigned captureMap, unsigned backrefMap)
-{
-    const unsigned char* scode = firstSignificantOpcode(code);
-    int op = *scode;
-    
-    /* Capturing brackets */
-    if (op > OP_BRA) {
-        int captureNum = op - OP_BRA;
-        if (captureNum > EXTRACT_BASIC_MAX)
-            captureNum = get2ByteValue(scode + 2 + LINK_SIZE);
-        int bracketMask = (captureNum < 32) ? (1 << captureNum) : 1;
-        return bracketNeedsLineStart(scode, captureMap | bracketMask, backrefMap);
-    }
-    
-    /* Other brackets */
-    if (op == OP_BRA || op == OP_ASSERT)
-        return bracketNeedsLineStart(scode, captureMap, backrefMap);
-    
-    /* .* means "start at start or after \n" if it isn't in brackets that
-     may be referenced. */
-    
-    if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR)
-        return scode[1] == OP_NOT_NEWLINE && !(captureMap & backrefMap);
-
-    /* Explicit ^ */
-    return op == OP_CIRC || op == OP_BOL;
-}
-
-static bool bracketNeedsLineStart(const unsigned char* code, unsigned captureMap, unsigned backrefMap)
-{
-    do {
-        if (!branchNeedsLineStart(code + 1 + LINK_SIZE, captureMap, backrefMap))
-            return false;
-        code += getLinkValue(code + 1);
-    } while (*code == OP_ALT);  /* Loop for each alternative */
-    return true;
-}
-
-/*************************************************
-*       Check for asserted fixed first char      *
-*************************************************/
-
-/* During compilation, the "first char" settings from forward assertions are
-discarded, because they can cause conflicts with actual literals that follow.
-However, if we end up without a first char setting for an unanchored pattern,
-it is worth scanning the regex to see if there is an initial asserted first
-char. If all branches start with the same asserted char, or with a bracket all
-of whose alternatives start with the same asserted char (recurse ad lib), then
-we return that char, otherwise -1.
-
-Arguments:
-  code       points to start of expression (the bracket)
-  options    pointer to the options (used to check casing changes)
-  inassert   true if in an assertion
-
-Returns:     -1 or the fixed first char
-*/
-
-static int branchFindFirstAssertedCharacter(const unsigned char* code, bool inassert)
-{
-    const unsigned char* scode = firstSignificantOpcodeSkippingAssertions(code);
-    int op = *scode;
-    
-    if (op >= OP_BRA)
-        op = OP_BRA;
-    
-    switch (op) {
-        default:
-            return -1;
-            
-        case OP_BRA:
-        case OP_ASSERT:
-            return bracketFindFirstAssertedCharacter(scode, op == OP_ASSERT);
-
-        case OP_EXACT:
-            scode += 2;
-            /* Fall through */
-
-        case OP_CHAR:
-        case OP_CHAR_IGNORING_CASE:
-        case OP_ASCII_CHAR:
-        case OP_ASCII_LETTER_IGNORING_CASE:
-        case OP_PLUS:
-        case OP_MINPLUS:
-            if (!inassert)
-                return -1;
-            return scode[1];
-    }
-}
-
-static int bracketFindFirstAssertedCharacter(const unsigned char* code, bool inassert)
-{
-    int c = -1;
-    do {
-        int d = branchFindFirstAssertedCharacter(code + 1 + LINK_SIZE, inassert);
-        if (d < 0)
-            return -1;
-        if (c < 0)
-            c = d;
-        else if (c != d)
-            return -1;
-        code += getLinkValue(code + 1);
-    } while (*code == OP_ALT);
-    return c;
-}
-
-static inline int multiplyWithOverflowCheck(int a, int b)
-{
-    if (!a || !b)
-        return 0;
-    if (a > MAX_PATTERN_SIZE / b)
-        return -1;
-    return a * b;
-}
-
-static int calculateCompiledPatternLength(const UChar* pattern, int patternLength, JSRegExpIgnoreCaseOption ignoreCase,
-    CompileData& cd, ErrorCode& errorcode)
-{
-    /* Make a pass over the pattern to compute the
-     amount of store required to hold the compiled code. This does not have to be
-     perfect as long as errors are overestimates. */
-
-    if (patternLength > MAX_PATTERN_SIZE) {
-        errorcode = ERR16;
-        return -1;
-    }
-
-    int length = 1 + LINK_SIZE;      /* For initial BRA plus length */
-    int branch_extra = 0;
-    int lastitemlength = 0;
-    unsigned brastackptr = 0;
-    int brastack[BRASTACK_SIZE];
-    unsigned char bralenstack[BRASTACK_SIZE];
-    int bracount = 0;
-    
-    const UChar* ptr = reinterpret_cast<const UChar*>(pattern - 1);
-    const UChar* patternEnd = reinterpret_cast<const UChar*>(pattern + patternLength);
-    
-    while (++ptr < patternEnd) {
-        int minRepeats = 0, maxRepeats = 0;
-        int c = *ptr;
-
-        switch (c) {
-            /* A backslashed item may be an escaped data character or it may be a
-             character type. */
-
-            case '\\':
-                c = checkEscape(&ptr, patternEnd, &errorcode, cd.numCapturingBrackets, false);
-                if (errorcode != 0)
-                    return -1;
-                
-                lastitemlength = 1;     /* Default length of last item for repeats */
-                
-                if (c >= 0) {            /* Data character */
-                    length += 2;          /* For a one-byte character */
-                    
-                    if (c > 127) {
-                        int i;
-                        for (i = 0; i < kjs_pcre_utf8_table1_size; i++)
-                            if (c <= kjs_pcre_utf8_table1[i]) break;
-                        length += i;
-                        lastitemlength += i;
-                    }
-                    
-                    continue;
-                }
-                
-                /* Other escapes need one byte */
-                
-                length++;
-                
-                /* A back reference needs an additional 2 bytes, plus either one or 5
-                 bytes for a repeat. We also need to keep the value of the highest
-                 back reference. */
-                
-                if (c <= -ESC_REF) {
-                    int refnum = -c - ESC_REF;
-                    cd.backrefMap |= (refnum < 32) ? (1 << refnum) : 1;
-                    if (refnum > cd.top_backref)
-                        cd.top_backref = refnum;
-                    length += 2;   /* For single back reference */
-                    if (safelyCheckNextChar(ptr, patternEnd, '{') && isCountedRepeat(ptr + 2, patternEnd)) {
-                        ptr = readRepeatCounts(ptr + 2, &minRepeats, &maxRepeats, &errorcode);
-                        if (errorcode)
-                            return -1;
-                        if ((minRepeats == 0 && (maxRepeats == 1 || maxRepeats == -1)) ||
-                            (minRepeats == 1 && maxRepeats == -1))
-                            length++;
-                        else
-                            length += 5;
-                        if (safelyCheckNextChar(ptr, patternEnd, '?'))
-                            ptr++;
-                    }
-                }
-                continue;
-                
-            case '^':     /* Single-byte metacharacters */
-            case '.':
-            case '$':
-                length++;
-                lastitemlength = 1;
-                continue;
-                
-            case '*':            /* These repeats won't be after brackets; */
-            case '+':            /* those are handled separately */
-            case '?':
-                length++;
-                goto POSSESSIVE;
-                
-            /* This covers the cases of braced repeats after a single char, metachar,
-             class, or back reference. */
-
-            case '{':
-                if (!isCountedRepeat(ptr + 1, patternEnd))
-                    goto NORMAL_CHAR;
-                ptr = readRepeatCounts(ptr + 1, &minRepeats, &maxRepeats, &errorcode);
-                if (errorcode != 0)
-                    return -1;
-                
-                /* These special cases just insert one extra opcode */
-                
-                if ((minRepeats == 0 && (maxRepeats == 1 || maxRepeats == -1)) ||
-                    (minRepeats == 1 && maxRepeats == -1))
-                    length++;
-                
-                /* These cases might insert additional copies of a preceding character. */
-                
-                else {
-                    if (minRepeats != 1) {
-                        length -= lastitemlength;   /* Uncount the original char or metachar */
-                        if (minRepeats > 0)
-                            length += 3 + lastitemlength;
-                    }
-                    length += lastitemlength + ((maxRepeats > 0) ? 3 : 1);
-                }
-                
-                if (safelyCheckNextChar(ptr, patternEnd, '?'))
-                    ptr++;      /* Needs no extra length */
-
-            POSSESSIVE:                     /* Test for possessive quantifier */
-                if (safelyCheckNextChar(ptr, patternEnd, '+')) {
-                    ptr++;
-                    length += 2 + 2 * LINK_SIZE;   /* Allow for atomic brackets */
-                }
-                continue;
-                
-            /* An alternation contains an offset to the next branch or ket. If any ims
-             options changed in the previous branch(es), and/or if we are in a
-             lookbehind assertion, extra space will be needed at the start of the
-             branch. This is handled by branch_extra. */
-                
-            case '|':
-                if (brastackptr == 0)
-                    cd.needOuterBracket = true;
-                length += 1 + LINK_SIZE + branch_extra;
-                continue;
-                
-            /* A character class uses 33 characters provided that all the character
-             values are less than 256. Otherwise, it uses a bit map for low valued
-             characters, and individual items for others. Don't worry about character
-             types that aren't allowed in classes - they'll get picked up during the
-             compile. A character class that contains only one single-byte character
-             uses 2 or 3 bytes, depending on whether it is negated or not. Notice this
-             where we can. (In UTF-8 mode we can do this only for chars < 128.) */
-                
-            case '[': {
-                int class_optcount;
-                if (*(++ptr) == '^') {
-                    class_optcount = 10;  /* Greater than one */
-                    ptr++;
-                }
-                else
-                    class_optcount = 0;
-                
-                bool class_utf8 = false;
-                
-                for (; ptr < patternEnd && *ptr != ']'; ++ptr) {
-                    /* Check for escapes */
-                    
-                    if (*ptr == '\\') {
-                        c = checkEscape(&ptr, patternEnd, &errorcode, cd.numCapturingBrackets, true);
-                        if (errorcode != 0)
-                            return -1;
-                        
-                        /* Handle escapes that turn into characters */
-                        
-                        if (c >= 0)
-                            goto NON_SPECIAL_CHARACTER;
-                        
-                        /* Escapes that are meta-things. The normal ones just affect the
-                         bit map, but Unicode properties require an XCLASS extended item. */
-                        
-                        else
-                            class_optcount = 10;         /* \d, \s etc; make sure > 1 */
-                    }
-                    
-                    /* Anything else increments the possible optimization count. We have to
-                     detect ranges here so that we can compute the number of extra ranges for
-                     caseless wide characters when UCP support is available. If there are wide
-                     characters, we are going to have to use an XCLASS, even for single
-                     characters. */
-                    
-                    else {
-                        c = *ptr;
-                        
-                        /* Come here from handling \ above when it escapes to a char value */
-                        
-                    NON_SPECIAL_CHARACTER:
-                        class_optcount++;
-                        
-                        int d = -1;
-                        if (safelyCheckNextChar(ptr, patternEnd, '-')) {
-                            UChar const *hyptr = ptr++;
-                            if (safelyCheckNextChar(ptr, patternEnd, '\\')) {
-                                ptr++;
-                                d = checkEscape(&ptr, patternEnd, &errorcode, cd.numCapturingBrackets, true);
-                                if (errorcode != 0)
-                                    return -1;
-                            }
-                            else if ((ptr + 1 < patternEnd) && ptr[1] != ']')
-                                d = *++ptr;
-                            if (d < 0)
-                                ptr = hyptr;      /* go back to hyphen as data */
-                        }
-                        
-                        /* If d >= 0 we have a range. In UTF-8 mode, if the end is > 255, or >
-                         127 for caseless matching, we will need to use an XCLASS. */
-                        
-                        if (d >= 0) {
-                            class_optcount = 10;     /* Ensure > 1 */
-                            if (d < c) {
-                                errorcode = ERR8;
-                                return -1;
-                            }
-                            
-                            if ((d > 255 || (ignoreCase && d > 127))) {
-                                unsigned char buffer[6];
-                                if (!class_utf8)         /* Allow for XCLASS overhead */
-                                {
-                                    class_utf8 = true;
-                                    length += LINK_SIZE + 2;
-                                }
-                                
-                                /* If we have UCP support, find out how many extra ranges are
-                                 needed to map the other case of characters within this range. We
-                                 have to mimic the range optimization here, because extending the
-                                 range upwards might push d over a boundary that makes it use
-                                 another byte in the UTF-8 representation. */
-                                
-                                if (ignoreCase) {
-                                    int occ, ocd;
-                                    int cc = c;
-                                    int origd = d;
-                                    while (getOthercaseRange(&cc, origd, &occ, &ocd)) {
-                                        if (occ >= c && ocd <= d)
-                                            continue;   /* Skip embedded */
-                                        
-                                        if (occ < c  && ocd >= c - 1)  /* Extend the basic range */
-                                        {                            /* if there is overlap,   */
-                                            c = occ;                     /* noting that if occ < c */
-                                            continue;                    /* we can't have ocd > d  */
-                                        }                            /* because a subrange is  */
-                                        if (ocd > d && occ <= d + 1)   /* always shorter than    */
-                                        {                            /* the basic range.       */
-                                            d = ocd;
-                                            continue;
-                                        }
-                                        
-                                        /* An extra item is needed */
-                                        
-                                        length += 1 + encodeUTF8(occ, buffer) +
-                                        ((occ == ocd) ? 0 : encodeUTF8(ocd, buffer));
-                                    }
-                                }
-                                
-                                /* The length of the (possibly extended) range */
-                                
-                                length += 1 + encodeUTF8(c, buffer) + encodeUTF8(d, buffer);
-                            }
-                            
-                        }
-                        
-                        /* We have a single character. There is nothing to be done unless we
-                         are in UTF-8 mode. If the char is > 255, or 127 when caseless, we must
-                         allow for an XCL_SINGLE item, doubled for caselessness if there is UCP
-                         support. */
-                        
-                        else {
-                            if ((c > 255 || (ignoreCase && c > 127))) {
-                                unsigned char buffer[6];
-                                class_optcount = 10;     /* Ensure > 1 */
-                                if (!class_utf8)         /* Allow for XCLASS overhead */
-                                {
-                                    class_utf8 = true;
-                                    length += LINK_SIZE + 2;
-                                }
-                                length += (ignoreCase ? 2 : 1) * (1 + encodeUTF8(c, buffer));
-                            }
-                        }
-                    }
-                }
-                
-                if (ptr >= patternEnd) {   /* Missing terminating ']' */
-                    errorcode = ERR6;
-                    return -1;
-                }
-                
-                /* We can optimize when there was only one optimizable character.
-                 Note that this does not detect the case of a negated single character.
-                 In that case we do an incorrect length computation, but it's not a serious
-                 problem because the computed length is too large rather than too small. */
-
-                if (class_optcount == 1)
-                    goto NORMAL_CHAR;
-
-                /* Here, we handle repeats for the class opcodes. */
-                {
-                    length += 33;
-                    
-                    /* A repeat needs either 1 or 5 bytes. If it is a possessive quantifier,
-                     we also need extra for wrapping the whole thing in a sub-pattern. */
-                    
-                    if (safelyCheckNextChar(ptr, patternEnd, '{') && isCountedRepeat(ptr + 2, patternEnd)) {
-                        ptr = readRepeatCounts(ptr + 2, &minRepeats, &maxRepeats, &errorcode);
-                        if (errorcode != 0)
-                            return -1;
-                        if ((minRepeats == 0 && (maxRepeats == 1 || maxRepeats == -1)) ||
-                            (minRepeats == 1 && maxRepeats == -1))
-                            length++;
-                        else
-                            length += 5;
-                        if (safelyCheckNextChar(ptr, patternEnd, '+')) {
-                            ptr++;
-                            length += 2 + 2 * LINK_SIZE;
-                        } else if (safelyCheckNextChar(ptr, patternEnd, '?'))
-                            ptr++;
-                    }
-                }
-                continue;
-            }
-
-            /* Brackets may be genuine groups or special things */
-                
-            case '(': {
-                int branch_newextra = 0;
-                int bracket_length = 1 + LINK_SIZE;
-                bool capturing = false;
-                
-                /* Handle special forms of bracket, which all start (? */
-                
-                if (safelyCheckNextChar(ptr, patternEnd, '?')) {
-                    switch (c = (ptr + 2 < patternEnd ? ptr[2] : 0)) {
-                        /* Non-referencing groups and lookaheads just move the pointer on, and
-                         then behave like a non-special bracket, except that they don't increment
-                         the count of extracting brackets. Ditto for the "once only" bracket,
-                         which is in Perl from version 5.005. */
-                            
-                        case ':':
-                        case '=':
-                        case '!':
-                            ptr += 2;
-                            break;
-                            
-                        /* Else loop checking valid options until ) is met. Anything else is an
-                         error. If we are without any brackets, i.e. at top level, the settings
-                         act as if specified in the options, so massage the options immediately.
-                         This is for backward compatibility with Perl 5.004. */
-                            
-                        default:
-                            errorcode = ERR12;
-                            return -1;
-                    }
-                } else
-                    capturing = 1;
-                
-                /* Capturing brackets must be counted so we can process escapes in a
-                 Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to need
-                 an additional 3 bytes of memory per capturing bracket. */
-                
-                if (capturing) {
-                    bracount++;
-                    if (bracount > EXTRACT_BASIC_MAX)
-                        bracket_length += 3;
-                }
-                
-                /* Save length for computing whole length at end if there's a repeat that
-                 requires duplication of the group. Also save the current value of
-                 branch_extra, and start the new group with the new value. If non-zero, this
-                 will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */
-                
-                if (brastackptr >= sizeof(brastack)/sizeof(int)) {
-                    errorcode = ERR17;
-                    return -1;
-                }
-                
-                bralenstack[brastackptr] = branch_extra;
-                branch_extra = branch_newextra;
-                
-                brastack[brastackptr++] = length;
-                length += bracket_length;
-                continue;
-            }
-
-            /* Handle ket. Look for subsequent maxRepeats/minRepeats; for certain sets of values we
-             have to replicate this bracket up to that many times. If brastackptr is
-             0 this is an unmatched bracket which will generate an error, but take care
-             not to try to access brastack[-1] when computing the length and restoring
-             the branch_extra value. */
-
-            case ')': {
-                int duplength;
-                length += 1 + LINK_SIZE;
-                if (brastackptr > 0) {
-                    duplength = length - brastack[--brastackptr];
-                    branch_extra = bralenstack[brastackptr];
-                }
-                else
-                    duplength = 0;
-                
-                /* Leave ptr at the final char; for readRepeatCounts this happens
-                 automatically; for the others we need an increment. */
-                
-                if ((ptr + 1 < patternEnd) && (c = ptr[1]) == '{' && isCountedRepeat(ptr + 2, patternEnd)) {
-                    ptr = readRepeatCounts(ptr + 2, &minRepeats, &maxRepeats, &errorcode);
-                    if (errorcode)
-                        return -1;
-                } else if (c == '*') {
-                    minRepeats = 0;
-                    maxRepeats = -1;
-                    ptr++;
-                } else if (c == '+') {
-                    minRepeats = 1;
-                    maxRepeats = -1;
-                    ptr++;
-                } else if (c == '?') {
-                    minRepeats = 0;
-                    maxRepeats = 1;
-                    ptr++;
-                } else {
-                    minRepeats = 1;
-                    maxRepeats = 1;
-                }
-                
-                /* If the minimum is zero, we have to allow for an OP_BRAZERO before the
-                 group, and if the maximum is greater than zero, we have to replicate
-                 maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting
-                 bracket set. */
-                
-                int repeatsLength;
-                if (minRepeats == 0) {
-                    length++;
-                    if (maxRepeats > 0) {
-                        repeatsLength = multiplyWithOverflowCheck(maxRepeats - 1, duplength + 3 + 2 * LINK_SIZE);
-                        if (repeatsLength < 0) {
-                            errorcode = ERR16;
-                            return -1;
-                        }
-                        length += repeatsLength;
-                        if (length > MAX_PATTERN_SIZE) {
-                            errorcode = ERR16;
-                            return -1;
-                        }
-                    }
-                }
-                
-                /* When the minimum is greater than zero, we have to replicate up to
-                 minval-1 times, with no additions required in the copies. Then, if there
-                 is a limited maximum we have to replicate up to maxval-1 times allowing
-                 for a BRAZERO item before each optional copy and nesting brackets for all
-                 but one of the optional copies. */
-                
-                else {
-                    repeatsLength = multiplyWithOverflowCheck(minRepeats - 1, duplength);
-                    if (repeatsLength < 0) {
-                        errorcode = ERR16;
-                        return -1;
-                    }
-                    length += repeatsLength;
-                    if (maxRepeats > minRepeats) { /* Need this test as maxRepeats=-1 means no limit */
-                        repeatsLength = multiplyWithOverflowCheck(maxRepeats - minRepeats, duplength + 3 + 2 * LINK_SIZE);
-                        if (repeatsLength < 0) {
-                            errorcode = ERR16;
-                            return -1;
-                        }
-                        length += repeatsLength - (2 + 2 * LINK_SIZE);
-                    }
-                    if (length > MAX_PATTERN_SIZE) {
-                        errorcode = ERR16;
-                        return -1;
-                    }
-                }
-                
-                /* Allow space for once brackets for "possessive quantifier" */
-                
-                if (safelyCheckNextChar(ptr, patternEnd, '+')) {
-                    ptr++;
-                    length += 2 + 2 * LINK_SIZE;
-                }
-                continue;
-            }
-
-            /* Non-special character. It won't be space or # in extended mode, so it is
-             always a genuine character. If we are in a \Q...\E sequence, check for the
-             end; if not, we have a literal. */
-                
-            default:
-            NORMAL_CHAR:
-                length += 2;          /* For a one-byte character */
-                lastitemlength = 1;   /* Default length of last item for repeats */
-
-                if (c > 127) {
-                    int i;
-                    for (i = 0; i < kjs_pcre_utf8_table1_size; i++)
-                        if (c <= kjs_pcre_utf8_table1[i])
-                            break;
-                    length += i;
-                    lastitemlength += i;
-                }
-                
-                continue;
-        }
-    }
-    
-    length += 2 + LINK_SIZE;    /* For final KET and END */
-
-    cd.numCapturingBrackets = bracount;
-    return length;
-}
-
-/*************************************************
-*        Compile a Regular Expression            *
-*************************************************/
-
-/* This function takes a string and returns a pointer to a block of store
-holding a compiled version of the expression. The original API for this
-function had no error code return variable; it is retained for backwards
-compatibility. The new function is given a new name.
-
-Arguments:
-  pattern       the regular expression
-  options       various option bits
-  errorcodeptr  pointer to error code variable (pcre_compile2() only)
-                  can be NULL if you don't want a code value
-  errorptr      pointer to pointer to error text
-  erroroffset   ptr offset in pattern where error was detected
-  tables        pointer to character tables or NULL
-
-Returns:        pointer to compiled data block, or NULL on error,
-                with errorptr and erroroffset set
-*/
-
-static inline JSRegExp* returnError(ErrorCode errorcode, const char** errorptr)
-{
-    *errorptr = errorText(errorcode);
-    return 0;
-}
-
-JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
-                JSRegExpIgnoreCaseOption ignoreCase, JSRegExpMultilineOption multiline,
-                unsigned* numSubpatterns, const char** errorptr,
-                malloc_t* allocate_function, free_t* free_function)
-{
-    /* We can't pass back an error message if errorptr is NULL; I guess the best we
-     can do is just return NULL, but we can set a code value if there is a code pointer. */
-    if (!errorptr)
-        return 0;
-    *errorptr = NULL;
-    
-    CompileData cd;
-    
-    ErrorCode errorcode = ERR0;
-    /* Call this once just to count the brackets. */
-    calculateCompiledPatternLength(pattern, patternLength, ignoreCase, cd, errorcode);
-    /* Call it again to compute the length. */
-    int length = calculateCompiledPatternLength(pattern, patternLength, ignoreCase, cd, errorcode);
-    if (errorcode)
-        return returnError(errorcode, errorptr);
-    
-    if (length > MAX_PATTERN_SIZE)
-        return returnError(ERR16, errorptr);
-    
-    size_t size = length + sizeof(JSRegExp);
-    JSRegExp* re = reinterpret_cast<JSRegExp*>((*allocate_function)(size));
-    
-    if (!re)
-        return returnError(ERR13, errorptr);
-    
-    re->options = (ignoreCase ? IgnoreCaseOption : 0) | (multiline ? MatchAcrossMultipleLinesOption : 0);
-    
-    /* The starting points of the name/number translation table and of the code are
-     passed around in the compile data block. */
-    
-    unsigned char* codeStart = reinterpret_cast<unsigned char*>(re + 1);
-    
-    /* Set up a starting, non-extracting bracket, then compile the expression. On
-     error, errorcode will be set non-zero, so we don't need to look at the result
-     of the function here. */
-    
-    const UChar* ptr = reinterpret_cast<const UChar*>(pattern);
-    const UChar* patternEnd = pattern + patternLength;
-    unsigned char* code = reinterpret_cast<unsigned char*>(codeStart);
-    int firstbyte, reqbyte;
-    int bracketCount = 0;
-    if (!cd.needOuterBracket)
-        compileBranch(re->options, &bracketCount, &code, &ptr, patternEnd, &errorcode, &firstbyte, &reqbyte, cd);
-    else {
-        *code = OP_BRA;
-        compileBracket(re->options, &bracketCount, &code, &ptr, patternEnd, &errorcode, 0, &firstbyte, &reqbyte, cd);
-    }
-    re->top_bracket = bracketCount;
-    re->top_backref = cd.top_backref;
-    
-    /* If not reached end of pattern on success, there's an excess bracket. */
-    
-    if (errorcode == 0 && ptr < patternEnd)
-        errorcode = ERR10;
-    
-    /* Fill in the terminating state and check for disastrous overflow, but
-     if debugging, leave the test till after things are printed out. */
-    
-    *code++ = OP_END;
-
-    ASSERT(code - codeStart <= length);
-    if (code - codeStart > length)
-        errorcode = ERR7;
-    
-    /* Give an error if there's back reference to a non-existent capturing
-     subpattern. */
-    
-    if (re->top_backref > re->top_bracket)
-        errorcode = ERR15;
-    
-    /* Failed to compile, or error while post-processing */
-    
-    if (errorcode != ERR0) {
-        (*free_function)(reinterpret_cast<void*>(re));
-        return returnError(errorcode, errorptr);
-    }
-    
-    /* If the anchored option was not passed, set the flag if we can determine that
-     the pattern is anchored by virtue of ^ characters or \A or anything else (such
-     as starting with .* when DOTALL is set).
-     
-     Otherwise, if we know what the first character has to be, save it, because that
-     speeds up unanchored matches no end. If not, see if we can set the
-     UseMultiLineFirstByteOptimizationOption flag. This is helpful for multiline matches when all branches
-     start with ^. and also when all branches start with .* for non-DOTALL matches.
-     */
-    
-    if (cd.needOuterBracket ? bracketIsAnchored(codeStart) : branchIsAnchored(codeStart))
-        re->options |= IsAnchoredOption;
-    else {
-        if (firstbyte < 0) {
-            firstbyte = (cd.needOuterBracket
-                    ? bracketFindFirstAssertedCharacter(codeStart, false)
-                    : branchFindFirstAssertedCharacter(codeStart, false))
-                | ((re->options & IgnoreCaseOption) ? REQ_IGNORE_CASE : 0);
-        }
-        if (firstbyte >= 0) {
-            int ch = firstbyte & 255;
-            if (ch < 127) {
-                re->first_byte = ((firstbyte & REQ_IGNORE_CASE) && flipCase(ch) == ch) ? ch : firstbyte;
-                re->options |= UseFirstByteOptimizationOption;
-            }
-        } else {
-            if (cd.needOuterBracket ? bracketNeedsLineStart(codeStart, 0, cd.backrefMap) : branchNeedsLineStart(codeStart, 0, cd.backrefMap))
-                re->options |= UseMultiLineFirstByteOptimizationOption;
-        }
-    }
-    
-    /* For an anchored pattern, we use the "required byte" only if it follows a
-     variable length item in the regex. Remove the caseless flag for non-caseable
-     bytes. */
-    
-    if (reqbyte >= 0 && (!(re->options & IsAnchoredOption) || (reqbyte & REQ_VARY))) {
-        int ch = reqbyte & 255;
-        if (ch < 127) {
-            re->req_byte = ((reqbyte & REQ_IGNORE_CASE) && flipCase(ch) == ch) ? (reqbyte & ~REQ_IGNORE_CASE) : reqbyte;
-            re->options |= UseRequiredByteOptimizationOption;
-        }
-    }
-    
-    if (numSubpatterns)
-        *numSubpatterns = re->top_bracket;
-    return re;
-}
-
-void jsRegExpFree(JSRegExp* re, free_t* free_function)
-{
-    (*free_function)(reinterpret_cast<void*>(re));
-}
-
-} }  // namespace dart::jscre
diff --git a/runtime/third_party/jscre/pcre_exec.cpp b/runtime/third_party/jscre/pcre_exec.cpp
deleted file mode 100644
index 98e7f15..0000000
--- a/runtime/third_party/jscre/pcre_exec.cpp
+++ /dev/null
@@ -1,2086 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-    Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* This module contains jsRegExpExecute(), the externally visible function
-that does pattern matching using an NFA algorithm, following the rules from
-the JavaScript specification. There are also some supporting functions. */
-
-#include "config.h"
-
-#include "pcre_internal.h"
-
-#include "ASCIICType.h"
-
-#include <ctype.h>
-#include <limits.h>
-#include <string.h> /* for memcpy */
-
-#ifdef __GNUC__
-#define USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-//#define USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-#endif
-
-/* Avoid warnings on Windows. */
-#undef min
-#undef max
-
-namespace dart { namespace jscre {
-
-#ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-typedef int ReturnLocation;
-#else
-typedef void* ReturnLocation;
-#endif
-
-/* Structure for building a chain of data for holding the values of
-the subject pointer at the start of each bracket, used to detect when
-an empty string has been matched by a bracket to break infinite loops. */ 
-struct BracketChainNode {
-    BracketChainNode* previousBracket;
-    const UChar* bracketStart;
-};
-
-struct MatchFrame {
-    ReturnLocation returnLocation;
-    struct MatchFrame* previousFrame;
-    
-    /* Function arguments that may change */
-    struct {
-        const UChar* subjectPtr;
-        const unsigned char* instructionPtr;
-        int offsetTop;
-        BracketChainNode* bracketChain;
-    } args;
-    
-    
-    /* PCRE uses "fake" recursion built off of gotos, thus
-     stack-based local variables are not safe to use.  Instead we have to
-     store local variables on the current MatchFrame. */
-    struct {
-        const unsigned char* data;
-        const unsigned char* startOfRepeatingBracket;
-        const UChar* subjectPtrAtStartOfInstruction; // Several instrutions stash away a subjectPtr here for later compare
-        const unsigned char* instructionPtrAtStartOfOnce;
-        
-        int repeatOthercase;
-        
-        int ctype;
-        int fc;
-        int fi;
-        int length;
-        int max;
-        int number;
-        int offset;
-        int saveOffset1;
-        int saveOffset2;
-        int saveOffset3;
-        
-        BracketChainNode bracketChainNode;
-    } locals;
-};
-
-/* Structure for passing "static" information around between the functions
-doing traditional NFA matching, so that they are thread-safe. */
-
-struct MatchData {
-  int*   offsetVector;         /* Offset vector */
-  int    offsetEnd;            /* One past the end */
-  int    offsetMax;            /* The maximum usable for return data */
-  bool   offsetOverflow;       /* Set if too many extractions */
-  const UChar*  startSubject;         /* Start of the subject string */
-  const UChar*  endSubject;           /* End of the subject string */
-  const UChar*  endMatchPtr;         /* Subject position at end match */
-  int    endOffsetTop;        /* Highwater mark at end of match */
-  bool   multiline;
-  bool   ignoreCase;
-};
-
-/* The maximum remaining length of subject we are prepared to search for a
-req_byte match. */
-
-#define REQ_BYTE_MAX 1000
-
-/* The below limit restricts the number of "recursive" match calls in order to
-avoid spending exponential time on complex regular expressions. */
-
-static const unsigned matchLimit = 100000;
-
-#ifdef DEBUG
-/*************************************************
-*        Debugging function to print chars       *
-*************************************************/
-
-/* Print a sequence of chars in printable format, stopping at the end of the
-subject if the requested.
-
-Arguments:
-  p           points to characters
-  length      number to print
-  isSubject  true if printing from within md.startSubject
-  md          pointer to matching data block, if isSubject is true
-*/
-
-static void pchars(const UChar* p, int length, bool isSubject, const MatchData& md)
-{
-    if (isSubject && length > md.endSubject - p)
-        length = md.endSubject - p;
-    while (length-- > 0) {
-        int c;
-        if (isprint(c = *(p++)))
-            printf("%c", c);
-        else if (c < 256)
-            printf("\\x%02x", c);
-        else
-            printf("\\x{%x}", c);
-    }
-}
-#endif
-
-/*************************************************
-*          Match a back-reference                *
-*************************************************/
-
-/* If a back reference hasn't been set, the length that is passed is greater
-than the number of characters left in the string, so the match fails.
-
-Arguments:
-  offset      index into the offset vector
-  subjectPtr        points into the subject
-  length      length to be matched
-  md          points to match data block
-
-Returns:      true if matched
-*/
-
-static bool matchRef(int offset, const UChar* subjectPtr, int length, const MatchData& md)
-{
-    const UChar* p = md.startSubject + md.offsetVector[offset];
-    
-#ifdef DEBUG
-    if (subjectPtr >= md.endSubject)
-        printf("matching subject <null>");
-    else {
-        printf("matching subject ");
-        pchars(subjectPtr, length, true, md);
-    }
-    printf(" against backref ");
-    pchars(p, length, false, md);
-    printf("\n");
-#endif
-    
-    /* Always fail if not enough characters left */
-    
-    if (length > md.endSubject - subjectPtr)
-        return false;
-    
-    /* Separate the caselesss case for speed */
-    
-    if (md.ignoreCase) {
-        while (length-- > 0) {
-            UChar c = *p++;
-            int othercase = kjs_pcre_ucp_othercase(c);
-            UChar d = *subjectPtr++;
-            if (c != d && othercase != d)
-                return false;
-        }
-    }
-    else {
-        while (length-- > 0)
-            if (*p++ != *subjectPtr++)
-                return false;
-    }
-    
-    return true;
-}
-
-#ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-
-/* Use numbered labels and switch statement at the bottom of the match function. */
-
-#define RMATCH_WHERE(num) num
-#define RRETURN_LABEL RRETURN_SWITCH
-
-#else
-
-/* Use GCC's computed goto extension. */
-
-/* For one test case this is more than 40% faster than the switch statement.
-We could avoid the use of the num argument entirely by using local labels,
-but using it for the GCC case as well as the non-GCC case allows us to share
-a bit more code and notice if we use conflicting numbers.*/
-
-#define RMATCH_WHERE(num) &&RRETURN_##num
-#define RRETURN_LABEL *stack.currentFrame->returnLocation
-
-#endif
-
-#define RECURSIVE_MATCH_COMMON(num) \
-    goto RECURSE;\
-    RRETURN_##num: \
-    stack.popCurrentFrame();
-
-#define RECURSIVE_MATCH(num, ra, rb) \
-    do { \
-        stack.pushNewFrame((ra), (rb), RMATCH_WHERE(num)); \
-        RECURSIVE_MATCH_COMMON(num) \
-    } while (0)
-
-#define RECURSIVE_MATCH_STARTNG_NEW_GROUP(num, ra, rb) \
-    do { \
-        stack.pushNewFrame((ra), (rb), RMATCH_WHERE(num)); \
-        startNewGroup(stack.currentFrame); \
-        RECURSIVE_MATCH_COMMON(num) \
-    } while (0)
-
-#define RRETURN goto RRETURN_LABEL
-
-#define RRETURN_NO_MATCH do { isMatch = false; RRETURN; } while (0)
-
-/*************************************************
-*         Match from current position            *
-*************************************************/
-
-/* On entry instructionPtr points to the first opcode, and subjectPtr to the first character
-in the subject string, while substringStart holds the value of subjectPtr at the start of the
-last bracketed group - used for breaking infinite loops matching zero-length
-strings. This function is called recursively in many circumstances. Whenever it
-returns a negative (error) response, the outer match() call must also return the
-same response.
-
-Arguments:
-   subjectPtr        pointer in subject
-   instructionPtr       position in code
-   offsetTop  current top pointer
-   md          pointer to "static" info for the match
-
-Returns:       1 if matched          )  these values are >= 0
-               0 if failed to match  )
-               a negative error value if aborted by an error condition
-                 (e.g. stopped by repeated call or recursion limit)
-*/
-
-static const unsigned FRAMES_ON_STACK = 16;
-
-struct MatchStack {
-    MatchStack()
-        : framesEnd(frames + FRAMES_ON_STACK)
-        , currentFrame(frames)
-        , size(1) // match() creates accesses the first frame w/o calling pushNewFrame
-    {
-        ASSERT((sizeof(frames) / sizeof(frames[0])) == FRAMES_ON_STACK);
-    }
-    
-    MatchFrame frames[FRAMES_ON_STACK];
-    MatchFrame* framesEnd;
-    MatchFrame* currentFrame;
-    unsigned size;
-    
-    inline bool canUseStackBufferForNextFrame()
-    {
-        return size < FRAMES_ON_STACK;
-    }
-    
-    inline MatchFrame* allocateNextFrame()
-    {
-        if (canUseStackBufferForNextFrame())
-            return currentFrame + 1;
-        return new MatchFrame;
-    }
-    
-    inline void pushNewFrame(const unsigned char* instructionPtr, BracketChainNode* bracketChain, ReturnLocation returnLocation)
-    {
-        MatchFrame* newframe = allocateNextFrame();
-        newframe->previousFrame = currentFrame;
-
-        newframe->args.subjectPtr = currentFrame->args.subjectPtr;
-        newframe->args.offsetTop = currentFrame->args.offsetTop;
-        newframe->args.instructionPtr = instructionPtr;
-        newframe->args.bracketChain = bracketChain;
-        newframe->returnLocation = returnLocation;
-        size++;
-
-        currentFrame = newframe;
-    }
-    
-    inline void popCurrentFrame()
-    {
-        MatchFrame* oldFrame = currentFrame;
-        currentFrame = currentFrame->previousFrame;
-        if (size > FRAMES_ON_STACK)
-            delete oldFrame;
-        size--;
-    }
-
-    void popAllFrames()
-    {
-        while (size)
-            popCurrentFrame();
-    }
-};
-
-static int matchError(int errorCode, MatchStack& stack)
-{
-    stack.popAllFrames();
-    return errorCode;
-}
-
-/* Get the next UTF-8 character, not advancing the pointer, incrementing length
- if there are extra bytes. This is called when we know we are in UTF-8 mode. */
-
-static inline void getUTF8CharAndIncrementLength(int& c, const unsigned char* subjectPtr, int& len)
-{
-    c = *subjectPtr;
-    if ((c & 0xc0) == 0xc0) {
-        int gcaa = kjs_pcre_utf8_table4[c & 0x3f];  /* Number of additional bytes */
-        int gcss = 6 * gcaa;
-        c = (c & kjs_pcre_utf8_table3[gcaa]) << gcss;
-        for (int gcii = 1; gcii <= gcaa; gcii++) {
-            gcss -= 6;
-            c |= (subjectPtr[gcii] & 0x3f) << gcss;
-        }
-        len += gcaa;
-    }
-}
-
-static inline void startNewGroup(MatchFrame* currentFrame)
-{
-    /* At the start of a bracketed group, add the current subject pointer to the
-     stack of such pointers, to be re-instated at the end of the group when we hit
-     the closing ket. When match() is called in other circumstances, we don't add to
-     this stack. */
-    
-    currentFrame->locals.bracketChainNode.previousBracket = currentFrame->args.bracketChain;
-    currentFrame->locals.bracketChainNode.bracketStart = currentFrame->args.subjectPtr;
-    currentFrame->args.bracketChain = &currentFrame->locals.bracketChainNode;
-}
-
-// FIXME: "minimize" means "not greedy", we should invert the callers to ask for "greedy" to be less confusing
-static inline void repeatInformationFromInstructionOffset(short instructionOffset, bool& minimize, int& minimumRepeats, int& maximumRepeats)
-{
-    // Instruction offsets are based off of OP_CRSTAR, OP_STAR, OP_TYPESTAR, OP_NOTSTAR
-    static const char minimumRepeatsFromInstructionOffset[] = { 0, 0, 1, 1, 0, 0 };
-    static const int maximumRepeatsFromInstructionOffset[] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX, 1, 1 };
-
-    ASSERT(instructionOffset >= 0);
-    ASSERT(instructionOffset <= (OP_CRMINQUERY - OP_CRSTAR));
-
-    minimize = (instructionOffset & 1); // this assumes ordering: Instruction, MinimizeInstruction, Instruction2, MinimizeInstruction2
-    minimumRepeats = minimumRepeatsFromInstructionOffset[instructionOffset];
-    maximumRepeats = maximumRepeatsFromInstructionOffset[instructionOffset];
-}
-
-static int match(const UChar* subjectPtr, const unsigned char* instructionPtr, int offsetTop, MatchData& md)
-{
-    bool isMatch = false;
-    int min;
-    bool minimize = false; /* Initialization not really needed, but some compilers think so. */
-    unsigned matchCount = 0;
-    
-    MatchStack stack;
-
-    /* The opcode jump table. */
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-#define EMIT_JUMP_TABLE_ENTRY(opcode) &&LABEL_OP_##opcode,
-    static void* opcodeJumpTable[256] = { FOR_EACH_OPCODE(EMIT_JUMP_TABLE_ENTRY) };
-#undef EMIT_JUMP_TABLE_ENTRY
-#endif
-    
-    /* One-time setup of the opcode jump table. */
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-    for (int i = 255; !opcodeJumpTable[i]; i--)
-        opcodeJumpTable[i] = &&CAPTURING_BRACKET;
-#endif
-    
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-    // Shark shows this as a hot line
-    // Using a static const here makes this line disappear, but makes later access hotter (not sure why)
-    stack.currentFrame->returnLocation = &&RETURN;
-#else
-    stack.currentFrame->returnLocation = 0;
-#endif
-    stack.currentFrame->args.subjectPtr = subjectPtr;
-    stack.currentFrame->args.instructionPtr = instructionPtr;
-    stack.currentFrame->args.offsetTop = offsetTop;
-    stack.currentFrame->args.bracketChain = 0;
-    startNewGroup(stack.currentFrame);
-    
-    /* This is where control jumps back to to effect "recursion" */
-    
-RECURSE:
-    if (++matchCount > matchLimit)
-        return matchError(JSRegExpErrorHitLimit, stack);
-
-    /* Now start processing the operations. */
-    
-#ifndef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-    while (true)
-#endif
-    {
-        
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-#define BEGIN_OPCODE(opcode) LABEL_OP_##opcode
-#define NEXT_OPCODE goto *opcodeJumpTable[*stack.currentFrame->args.instructionPtr]
-#else
-#define BEGIN_OPCODE(opcode) case OP_##opcode
-#define NEXT_OPCODE continue
-#endif
-        
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-        NEXT_OPCODE;
-#else
-        switch (*stack.currentFrame->args.instructionPtr)
-#endif
-        {
-            /* Non-capturing bracket: optimized */
-                
-            BEGIN_OPCODE(BRA):
-            NON_CAPTURING_BRACKET:
-                DPRINTF(("start bracket 0\n"));
-                do {
-                    RECURSIVE_MATCH_STARTNG_NEW_GROUP(2, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                    stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
-                DPRINTF(("bracket 0 failed\n"));
-                RRETURN;
-                
-            /* Skip over large extraction number data if encountered. */
-                
-            BEGIN_OPCODE(BRANUMBER):
-                stack.currentFrame->args.instructionPtr += 3;
-                NEXT_OPCODE;
-                
-            /* End of the pattern. */
-                
-            BEGIN_OPCODE(END):
-                md.endMatchPtr = stack.currentFrame->args.subjectPtr;          /* Record where we ended */
-                md.endOffsetTop = stack.currentFrame->args.offsetTop;   /* and how many extracts were taken */
-                isMatch = true;
-                RRETURN;
-                
-            /* Assertion brackets. Check the alternative branches in turn - the
-             matching won't pass the KET for an assertion. If any one branch matches,
-             the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
-             start of each branch to move the current point backwards, so the code at
-             this level is identical to the lookahead case. */
-                
-            BEGIN_OPCODE(ASSERT):
-                do {
-                    RECURSIVE_MATCH_STARTNG_NEW_GROUP(6, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
-                    if (isMatch)
-                        break;
-                    stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
-                if (*stack.currentFrame->args.instructionPtr == OP_KET)
-                    RRETURN_NO_MATCH;
-                
-                /* Continue from after the assertion, updating the offsets high water
-                 mark, since extracts may have been taken during the assertion. */
-                
-                advanceToEndOfBracket(stack.currentFrame->args.instructionPtr);
-                stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
-                stack.currentFrame->args.offsetTop = md.endOffsetTop;
-                NEXT_OPCODE;
-                
-            /* Negative assertion: all branches must fail to match */
-                
-            BEGIN_OPCODE(ASSERT_NOT):
-                do {
-                    RECURSIVE_MATCH_STARTNG_NEW_GROUP(7, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
-                    if (isMatch)
-                        RRETURN_NO_MATCH;
-                    stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
-                
-                stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
-                NEXT_OPCODE;
-                
-            /* An alternation is the end of a branch; scan along to find the end of the
-             bracketed group and go to there. */
-                
-            BEGIN_OPCODE(ALT):
-                advanceToEndOfBracket(stack.currentFrame->args.instructionPtr);
-                NEXT_OPCODE;
-                
-            /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
-             that it may occur zero times. It may repeat infinitely, or not at all -
-             i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
-             repeat limits are compiled as a number of copies, with the optional ones
-             preceded by BRAZERO or BRAMINZERO. */
-                
-            BEGIN_OPCODE(BRAZERO): {
-                stack.currentFrame->locals.startOfRepeatingBracket = stack.currentFrame->args.instructionPtr + 1;
-                RECURSIVE_MATCH_STARTNG_NEW_GROUP(14, stack.currentFrame->locals.startOfRepeatingBracket, stack.currentFrame->args.bracketChain);
-                if (isMatch)
-                    RRETURN;
-                advanceToEndOfBracket(stack.currentFrame->locals.startOfRepeatingBracket);
-                stack.currentFrame->args.instructionPtr = stack.currentFrame->locals.startOfRepeatingBracket + 1 + LINK_SIZE;
-                NEXT_OPCODE;
-            }
-                
-            BEGIN_OPCODE(BRAMINZERO): {
-                stack.currentFrame->locals.startOfRepeatingBracket = stack.currentFrame->args.instructionPtr + 1;
-                advanceToEndOfBracket(stack.currentFrame->locals.startOfRepeatingBracket);
-                RECURSIVE_MATCH_STARTNG_NEW_GROUP(15, stack.currentFrame->locals.startOfRepeatingBracket + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                if (isMatch)
-                    RRETURN;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-            }
-                
-            /* End of a group, repeated or non-repeating. If we are at the end of
-             an assertion "group", stop matching and return 1, but record the
-             current high water mark for use by positive assertions. Do this also
-             for the "once" (not-backup up) groups. */
-                
-            BEGIN_OPCODE(KET):
-            BEGIN_OPCODE(KETRMIN):
-            BEGIN_OPCODE(KETRMAX):
-                stack.currentFrame->locals.instructionPtrAtStartOfOnce = stack.currentFrame->args.instructionPtr - getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.bracketChain->bracketStart;
-
-                /* Back up the stack of bracket start pointers. */
-
-                stack.currentFrame->args.bracketChain = stack.currentFrame->args.bracketChain->previousBracket;
-
-                if (*stack.currentFrame->locals.instructionPtrAtStartOfOnce == OP_ASSERT || *stack.currentFrame->locals.instructionPtrAtStartOfOnce == OP_ASSERT_NOT) {
-                    md.endOffsetTop = stack.currentFrame->args.offsetTop;
-                    isMatch = true;
-                    RRETURN;
-                }
-                
-                /* In all other cases except a conditional group we have to check the
-                 group number back at the start and if necessary complete handling an
-                 extraction by setting the offsets and bumping the high water mark. */
-                
-                stack.currentFrame->locals.number = *stack.currentFrame->locals.instructionPtrAtStartOfOnce - OP_BRA;
-                
-                /* For extended extraction brackets (large number), we have to fish out
-                 the number from a dummy opcode at the start. */
-                
-                if (stack.currentFrame->locals.number > EXTRACT_BASIC_MAX)
-                    stack.currentFrame->locals.number = get2ByteValue(stack.currentFrame->locals.instructionPtrAtStartOfOnce + 2 + LINK_SIZE);
-                stack.currentFrame->locals.offset = stack.currentFrame->locals.number << 1;
-                
-#ifdef DEBUG
-                printf("end bracket %d", stack.currentFrame->locals.number);
-                printf("\n");
-#endif
-                
-                /* Test for a numbered group. This includes groups called as a result
-                 of recursion. Note that whole-pattern recursion is coded as a recurse
-                 into group 0, so it won't be picked up here. Instead, we catch it when
-                 the OP_END is reached. */
-                
-                if (stack.currentFrame->locals.number > 0) {
-                    if (stack.currentFrame->locals.offset >= md.offsetMax)
-                        md.offsetOverflow = true;
-                    else {
-                        md.offsetVector[stack.currentFrame->locals.offset] =
-                        md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number];
-                        md.offsetVector[stack.currentFrame->locals.offset+1] = stack.currentFrame->args.subjectPtr - md.startSubject;
-                        if (stack.currentFrame->args.offsetTop <= stack.currentFrame->locals.offset)
-                            stack.currentFrame->args.offsetTop = stack.currentFrame->locals.offset + 2;
-                    }
-                }
-                
-                /* For a non-repeating ket, just continue at this level. This also
-                 happens for a repeating ket if no characters were matched in the group.
-                 This is the forcible breaking of infinite loops as implemented in Perl
-                 5.005. If there is an options reset, it will get obeyed in the normal
-                 course of events. */
-                
-                if (*stack.currentFrame->args.instructionPtr == OP_KET || stack.currentFrame->args.subjectPtr == stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
-                    stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
-                    NEXT_OPCODE;
-                }
-                
-                /* The repeating kets try the rest of the pattern or restart from the
-                 preceding bracket, in the appropriate order. */
-                
-                if (*stack.currentFrame->args.instructionPtr == OP_KETRMIN) {
-                    RECURSIVE_MATCH(16, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                    RECURSIVE_MATCH_STARTNG_NEW_GROUP(17, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                } else { /* OP_KETRMAX */
-                    RECURSIVE_MATCH_STARTNG_NEW_GROUP(18, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                    RECURSIVE_MATCH(19, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                }
-                RRETURN;
-                
-            /* Start of subject. */
-
-            BEGIN_OPCODE(CIRC):
-                if (stack.currentFrame->args.subjectPtr != md.startSubject)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            /* After internal newline if multiline. */
-
-            BEGIN_OPCODE(BOL):
-                if (stack.currentFrame->args.subjectPtr != md.startSubject && !isNewline(stack.currentFrame->args.subjectPtr[-1]))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            /* End of subject. */
-
-            BEGIN_OPCODE(DOLL):
-                if (stack.currentFrame->args.subjectPtr < md.endSubject)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            /* Before internal newline if multiline. */
-
-            BEGIN_OPCODE(EOL):
-                if (stack.currentFrame->args.subjectPtr < md.endSubject && !isNewline(*stack.currentFrame->args.subjectPtr))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-                
-            /* Word boundary assertions */
-                
-            BEGIN_OPCODE(NOT_WORD_BOUNDARY):
-            BEGIN_OPCODE(WORD_BOUNDARY): {
-                bool currentCharIsWordChar = false;
-                bool previousCharIsWordChar = false;
-                
-                if (stack.currentFrame->args.subjectPtr > md.startSubject)
-                    previousCharIsWordChar = isWordChar(stack.currentFrame->args.subjectPtr[-1]);
-                if (stack.currentFrame->args.subjectPtr < md.endSubject)
-                    currentCharIsWordChar = isWordChar(*stack.currentFrame->args.subjectPtr);
-                
-                /* Now see if the situation is what we want */
-                bool wordBoundaryDesired = (*stack.currentFrame->args.instructionPtr++ == OP_WORD_BOUNDARY);
-                if (wordBoundaryDesired ? currentCharIsWordChar == previousCharIsWordChar : currentCharIsWordChar != previousCharIsWordChar)
-                    RRETURN_NO_MATCH;
-                NEXT_OPCODE;
-            }
-                
-            /* Match a single character type; inline for speed */
-                
-            BEGIN_OPCODE(NOT_NEWLINE):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (isNewline(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            BEGIN_OPCODE(NOT_DIGIT):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (isASCIIDigit(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            BEGIN_OPCODE(DIGIT):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (!isASCIIDigit(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            BEGIN_OPCODE(NOT_WHITESPACE):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (isSpaceChar(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            BEGIN_OPCODE(WHITESPACE):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (!isSpaceChar(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-                
-            BEGIN_OPCODE(NOT_WORDCHAR):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (isWordChar(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-                
-            BEGIN_OPCODE(WORDCHAR):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (!isWordChar(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-                
-            /* Match a back reference, possibly repeatedly. Look past the end of the
-             item to see if there is repeat information following. The code is similar
-             to that for character classes, but repeated for efficiency. Then obey
-             similar code to character type repeats - written out again for speed.
-             However, if the referenced string is the empty string, always treat
-             it as matched, any number of times (otherwise there could be infinite
-             loops). */
-                
-            BEGIN_OPCODE(REF):
-                stack.currentFrame->locals.offset = get2ByteValue(stack.currentFrame->args.instructionPtr + 1) << 1;               /* Doubled ref number */
-                stack.currentFrame->args.instructionPtr += 3;                                 /* Advance past item */
-                
-                /* If the reference is unset, set the length to be longer than the amount
-                 of subject left; this ensures that every attempt at a match fails. We
-                 can't just fail here, because of the possibility of quantifiers with zero
-                 minima. */
-                
-                if (stack.currentFrame->locals.offset >= stack.currentFrame->args.offsetTop || md.offsetVector[stack.currentFrame->locals.offset] < 0)
-                    stack.currentFrame->locals.length = 0;
-                else
-                    stack.currentFrame->locals.length = md.offsetVector[stack.currentFrame->locals.offset+1] - md.offsetVector[stack.currentFrame->locals.offset];
-                
-                /* Set up for repetition, or handle the non-repeated case */
-                
-                switch (*stack.currentFrame->args.instructionPtr) {
-                    case OP_CRSTAR:
-                    case OP_CRMINSTAR:
-                    case OP_CRPLUS:
-                    case OP_CRMINPLUS:
-                    case OP_CRQUERY:
-                    case OP_CRMINQUERY:
-                        repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
-                        break;
-                        
-                    case OP_CRRANGE:
-                    case OP_CRMINRANGE:
-                        minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
-                        min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                        stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
-                        if (stack.currentFrame->locals.max == 0)
-                            stack.currentFrame->locals.max = INT_MAX;
-                        stack.currentFrame->args.instructionPtr += 5;
-                        break;
-                    
-                    default:               /* No repeat follows */
-                        if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
-                            RRETURN_NO_MATCH;
-                        stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
-                        NEXT_OPCODE;
-                }
-                
-                /* If the length of the reference is zero, just continue with the
-                 main loop. */
-                
-                if (stack.currentFrame->locals.length == 0)
-                    NEXT_OPCODE;
-                
-                /* First, ensure the minimum number of matches are present. */
-                
-                for (int i = 1; i <= min; i++) {
-                    if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
-                        RRETURN_NO_MATCH;
-                    stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
-                }
-                
-                /* If min = max, continue at the same level without recursion.
-                 They are not both allowed to be zero. */
-                
-                if (min == stack.currentFrame->locals.max)
-                    NEXT_OPCODE;
-                
-                /* If minimizing, keep trying and advancing the pointer */
-                
-                if (minimize) {
-                    for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                        RECURSIVE_MATCH(20, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || !matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
-                            RRETURN;
-                        stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
-                    }
-                    /* Control never reaches here */
-                }
-                
-                /* If maximizing, find the longest string and work backwards */
-                
-                else {
-                    stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                    for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                        if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
-                            break;
-                        stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
-                    }
-                    while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
-                        RECURSIVE_MATCH(21, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        stack.currentFrame->args.subjectPtr -= stack.currentFrame->locals.length;
-                    }
-                    RRETURN_NO_MATCH;
-                }
-                /* Control never reaches here */
-                
-            /* Match a bit-mapped character class, possibly repeatedly. This op code is
-             used when all the characters in the class have values in the range 0-255,
-             and either the matching is caseful, or the characters are in the range
-             0-127 when UTF-8 processing is enabled. The only difference between
-             OP_CLASS and OP_NCLASS occurs when a data character outside the range is
-             encountered.
-             
-             First, look past the end of the item to see if there is repeat information
-             following. Then obey similar code to character type repeats - written out
-             again for speed. */
-                
-            BEGIN_OPCODE(NCLASS):
-            BEGIN_OPCODE(CLASS):
-                stack.currentFrame->locals.data = stack.currentFrame->args.instructionPtr + 1;                /* Save for matching */
-                stack.currentFrame->args.instructionPtr += 33;                     /* Advance past the item */
-                
-                switch (*stack.currentFrame->args.instructionPtr) {
-                    case OP_CRSTAR:
-                    case OP_CRMINSTAR:
-                    case OP_CRPLUS:
-                    case OP_CRMINPLUS:
-                    case OP_CRQUERY:
-                    case OP_CRMINQUERY:
-                        repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
-                        break;
-                        
-                    case OP_CRRANGE:
-                    case OP_CRMINRANGE:
-                        minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
-                        min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                        stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
-                        if (stack.currentFrame->locals.max == 0)
-                            stack.currentFrame->locals.max = INT_MAX;
-                        stack.currentFrame->args.instructionPtr += 5;
-                        break;
-                        
-                    default:               /* No repeat follows */
-                        min = stack.currentFrame->locals.max = 1;
-                        break;
-                }
-                
-                /* First, ensure the minimum number of matches are present. */
-                
-                for (int i = 1; i <= min; i++) {
-                    if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                        RRETURN_NO_MATCH;
-                    int c = *stack.currentFrame->args.subjectPtr++;
-                    if (c > 255) {
-                        if (stack.currentFrame->locals.data[-1] == OP_CLASS)
-                            RRETURN_NO_MATCH;
-                    } else {
-                        if (!(stack.currentFrame->locals.data[c / 8] & (1 << (c & 7))))
-                            RRETURN_NO_MATCH;
-                    }
-                }
-                
-                /* If max == min we can continue with the main loop without the
-                 need to recurse. */
-                
-                if (min == stack.currentFrame->locals.max)
-                    NEXT_OPCODE;      
-                
-                /* If minimizing, keep testing the rest of the expression and advancing
-                 the pointer while it matches the class. */
-                if (minimize) {
-                    for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                        RECURSIVE_MATCH(22, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            RRETURN;
-                        int c = *stack.currentFrame->args.subjectPtr++;
-                        if (c > 255) {
-                            if (stack.currentFrame->locals.data[-1] == OP_CLASS)
-                                RRETURN;
-                        } else {
-                            if ((stack.currentFrame->locals.data[c/8] & (1 << (c&7))) == 0)
-                                RRETURN;
-                        }
-                    }
-                    /* Control never reaches here */
-                }
-                /* If maximizing, find the longest possible run, then work backwards. */
-                else {
-                    stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                    
-                    for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                        if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            break;
-                        int c = *stack.currentFrame->args.subjectPtr;
-                        if (c > 255) {
-                            if (stack.currentFrame->locals.data[-1] == OP_CLASS)
-                                break;
-                        } else {
-                            if (!(stack.currentFrame->locals.data[c / 8] & (1 << (c & 7))))
-                                break;
-                        }
-                        ++stack.currentFrame->args.subjectPtr;
-                    }
-                    for (;;) {
-                        RECURSIVE_MATCH(24, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                            break;        /* Stop if tried at original pos */
-                    }
-                    
-                    RRETURN;
-                }
-                /* Control never reaches here */
-                
-            /* Match an extended character class. */
-                
-            BEGIN_OPCODE(XCLASS):
-                stack.currentFrame->locals.data = stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE;                /* Save for matching */
-                stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);                      /* Advance past the item */
-                
-                switch (*stack.currentFrame->args.instructionPtr) {
-                    case OP_CRSTAR:
-                    case OP_CRMINSTAR:
-                    case OP_CRPLUS:
-                    case OP_CRMINPLUS:
-                    case OP_CRQUERY:
-                    case OP_CRMINQUERY:
-                        repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
-                        break;
-                        
-                    case OP_CRRANGE:
-                    case OP_CRMINRANGE:
-                        minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
-                        min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                        stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
-                        if (stack.currentFrame->locals.max == 0)
-                            stack.currentFrame->locals.max = INT_MAX;
-                        stack.currentFrame->args.instructionPtr += 5;
-                        break;
-                        
-                    default:               /* No repeat follows */
-                        min = stack.currentFrame->locals.max = 1;
-                }
-                
-                /* First, ensure the minimum number of matches are present. */
-                
-                for (int i = 1; i <= min; i++) {
-                    if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                        RRETURN_NO_MATCH;
-                    int c = *stack.currentFrame->args.subjectPtr++;
-                    if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
-                        RRETURN_NO_MATCH;
-                }
-                
-                /* If max == min we can continue with the main loop without the
-                 need to recurse. */
-                
-                if (min == stack.currentFrame->locals.max)
-                    NEXT_OPCODE;
-                
-                /* If minimizing, keep testing the rest of the expression and advancing
-                 the pointer while it matches the class. */
-                
-                if (minimize) {
-                    for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                        RECURSIVE_MATCH(26, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            RRETURN;
-                        int c = *stack.currentFrame->args.subjectPtr++;
-                        if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
-                            RRETURN;
-                    }
-                    /* Control never reaches here */
-                }
-                
-                /* If maximizing, find the longest possible run, then work backwards. */
-                
-                else {
-                    stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                    for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                        if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            break;
-                        int c = *stack.currentFrame->args.subjectPtr;
-                        if (!kjs_pcre_xclass(c, stack.currentFrame->locals.data))
-                            break;
-                        ++stack.currentFrame->args.subjectPtr;
-                    }
-                    for(;;) {
-                        RECURSIVE_MATCH(27, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                            break;        /* Stop if tried at original pos */
-                    }
-                    RRETURN;
-                }
-                
-                /* Control never reaches here */
-                
-            /* Match a single character, casefully */
-                
-            BEGIN_OPCODE(CHAR):
-                stack.currentFrame->locals.length = 1;
-                stack.currentFrame->args.instructionPtr++;
-                getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
-                stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (stack.currentFrame->locals.fc != *stack.currentFrame->args.subjectPtr++)
-                    RRETURN_NO_MATCH;
-                NEXT_OPCODE;
-                
-            /* Match a single character, caselessly */
-                
-            BEGIN_OPCODE(CHAR_IGNORING_CASE): {
-                stack.currentFrame->locals.length = 1;
-                stack.currentFrame->args.instructionPtr++;
-                getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
-                stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                int dc = *stack.currentFrame->args.subjectPtr++;
-                if (stack.currentFrame->locals.fc != dc && kjs_pcre_ucp_othercase(stack.currentFrame->locals.fc) != dc)
-                    RRETURN_NO_MATCH;
-                NEXT_OPCODE;
-            }
-                
-            /* Match a single ASCII character. */
-                
-            BEGIN_OPCODE(ASCII_CHAR):
-                if (md.endSubject == stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->args.instructionPtr[1])
-                    RRETURN_NO_MATCH;
-                ++stack.currentFrame->args.subjectPtr;
-                stack.currentFrame->args.instructionPtr += 2;
-                NEXT_OPCODE;
-                
-            /* Match one of two cases of an ASCII letter. */
-                
-            BEGIN_OPCODE(ASCII_LETTER_IGNORING_CASE):
-                if (md.endSubject == stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                if ((*stack.currentFrame->args.subjectPtr | 0x20) != stack.currentFrame->args.instructionPtr[1])
-                    RRETURN_NO_MATCH;
-                ++stack.currentFrame->args.subjectPtr;
-                stack.currentFrame->args.instructionPtr += 2;
-                NEXT_OPCODE;
-                
-            /* Match a single character repeatedly; different opcodes share code. */
-                
-            BEGIN_OPCODE(EXACT):
-                min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = false;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATCHAR;
-                
-            BEGIN_OPCODE(UPTO):
-            BEGIN_OPCODE(MINUPTO):
-                min = 0;
-                stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = *stack.currentFrame->args.instructionPtr == OP_MINUPTO;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATCHAR;
-                
-            BEGIN_OPCODE(STAR):
-            BEGIN_OPCODE(MINSTAR):
-            BEGIN_OPCODE(PLUS):
-            BEGIN_OPCODE(MINPLUS):
-            BEGIN_OPCODE(QUERY):
-            BEGIN_OPCODE(MINQUERY):
-                repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_STAR, minimize, min, stack.currentFrame->locals.max);
-                
-                /* Common code for all repeated single-character matches. We can give
-                 up quickly if there are fewer than the minimum number of characters left in
-                 the subject. */
-                
-            REPEATCHAR:
-                
-                stack.currentFrame->locals.length = 1;
-                getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
-                if (min * (stack.currentFrame->locals.fc > 0xFFFF ? 2 : 1) > md.endSubject - stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
-                
-                if (stack.currentFrame->locals.fc <= 0xFFFF) {
-                    int othercase;
-                    othercase = md.ignoreCase ? kjs_pcre_ucp_othercase(stack.currentFrame->locals.fc) : -1;
-                    
-                    for (int i = 1; i <= min; i++) {
-                        if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != othercase)
-                            RRETURN_NO_MATCH;
-                        ++stack.currentFrame->args.subjectPtr;
-                    }
-                    
-                    if (min == stack.currentFrame->locals.max)
-                        NEXT_OPCODE;
-                    
-                    if (minimize) {
-                        stack.currentFrame->locals.repeatOthercase = othercase;
-                        for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                            RECURSIVE_MATCH(28, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                RRETURN;
-                            if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.repeatOthercase)
-                                RRETURN;
-                            ++stack.currentFrame->args.subjectPtr;
-                        }
-                        /* Control never reaches here */
-                    } else {
-                        stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                        for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                            if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                break;
-                            if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != othercase)
-                                break;
-                            ++stack.currentFrame->args.subjectPtr;
-                        }
-                        while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
-                            RECURSIVE_MATCH(29, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            --stack.currentFrame->args.subjectPtr;
-                        }
-                        RRETURN_NO_MATCH;
-                    }
-                    /* Control never reaches here */
-                } else {
-                    /* No case on surrogate pairs, so no need to bother with "othercase". */
-                    
-                    for (int i = 1; i <= min; i++) {
-                        if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
-                            RRETURN_NO_MATCH;
-                        stack.currentFrame->args.subjectPtr += 2;
-                    }
-                    
-                    if (min == stack.currentFrame->locals.max)
-                        NEXT_OPCODE;
-                    
-                    if (minimize) {
-                        for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                            RECURSIVE_MATCH(30, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                RRETURN;
-                            if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
-                                RRETURN;
-                            stack.currentFrame->args.subjectPtr += 2;
-                        }
-                        /* Control never reaches here */
-                    } else {
-                        stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                        for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                            if (stack.currentFrame->args.subjectPtr > md.endSubject - 2)
-                                break;
-                            if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
-                                break;
-                            stack.currentFrame->args.subjectPtr += 2;
-                        }
-                        while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
-                            RECURSIVE_MATCH(31, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            stack.currentFrame->args.subjectPtr -= 2;
-                        }
-                        RRETURN_NO_MATCH;
-                    }
-                    /* Control never reaches here */
-                }
-                /* Control never reaches here */
-                
-            /* Match a negated single one-byte character. */
-                
-            BEGIN_OPCODE(NOT): {
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                int c = *stack.currentFrame->args.subjectPtr++;
-                if (md.ignoreCase) {
-                    if (c < 128)
-                        c = toLowerCase(c);
-                    if (toLowerCase(*stack.currentFrame->args.instructionPtr++) == c)
-                        RRETURN_NO_MATCH;
-                } else {
-                    if (*stack.currentFrame->args.instructionPtr++ == c)
-                        RRETURN_NO_MATCH;
-                }
-                NEXT_OPCODE;
-            }
-                
-            /* Match a negated single one-byte character repeatedly. This is almost a
-             repeat of the code for a repeated single character, but I haven't found a
-             nice way of commoning these up that doesn't require a test of the
-             positive/negative option for each character match. Maybe that wouldn't add
-             very much to the time taken, but character matching *is* what this is all
-             about... */
-                
-            BEGIN_OPCODE(NOTEXACT):
-                min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = false;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATNOTCHAR;
-                
-            BEGIN_OPCODE(NOTUPTO):
-            BEGIN_OPCODE(NOTMINUPTO):
-                min = 0;
-                stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = *stack.currentFrame->args.instructionPtr == OP_NOTMINUPTO;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATNOTCHAR;
-                
-            BEGIN_OPCODE(NOTSTAR):
-            BEGIN_OPCODE(NOTMINSTAR):
-            BEGIN_OPCODE(NOTPLUS):
-            BEGIN_OPCODE(NOTMINPLUS):
-            BEGIN_OPCODE(NOTQUERY):
-            BEGIN_OPCODE(NOTMINQUERY):
-                repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_NOTSTAR, minimize, min, stack.currentFrame->locals.max);
-                
-            /* Common code for all repeated single-byte matches. We can give up quickly
-             if there are fewer than the minimum number of bytes left in the
-             subject. */
-                
-            REPEATNOTCHAR:
-                if (min > md.endSubject - stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->locals.fc = *stack.currentFrame->args.instructionPtr++;
-                
-                /* The code is duplicated for the caseless and caseful cases, for speed,
-                 since matching characters is likely to be quite common. First, ensure the
-                 minimum number of matches are present. If min = max, continue at the same
-                 level without recursing. Otherwise, if minimizing, keep trying the rest of
-                 the expression and advancing one matching character if failing, up to the
-                 maximum. Alternatively, if maximizing, find the maximum number of
-                 characters and work backwards. */
-                
-                DPRINTF(("negative matching %c{%d,%d}\n", stack.currentFrame->locals.fc, min, stack.currentFrame->locals.max));
-                
-                if (md.ignoreCase) {
-                    if (stack.currentFrame->locals.fc < 128)
-                        stack.currentFrame->locals.fc = toLowerCase(stack.currentFrame->locals.fc);
-                    
-                    for (int i = 1; i <= min; i++) {
-                        int d = *stack.currentFrame->args.subjectPtr++;
-                        if (d < 128)
-                            d = toLowerCase(d);
-                        if (stack.currentFrame->locals.fc == d)
-                            RRETURN_NO_MATCH;
-                    }
-                    
-                    if (min == stack.currentFrame->locals.max)
-                        NEXT_OPCODE;      
-                    
-                    if (minimize) {
-                        for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                            RECURSIVE_MATCH(38, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            int d = *stack.currentFrame->args.subjectPtr++;
-                            if (d < 128)
-                                d = toLowerCase(d);
-                            if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject || stack.currentFrame->locals.fc == d)
-                                RRETURN;
-                        }
-                        /* Control never reaches here */
-                    }
-                    
-                    /* Maximize case */
-                    
-                    else {
-                        stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                        
-                        for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                            if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                break;
-                            int d = *stack.currentFrame->args.subjectPtr;
-                            if (d < 128)
-                                d = toLowerCase(d);
-                            if (stack.currentFrame->locals.fc == d)
-                                break;
-                            ++stack.currentFrame->args.subjectPtr;
-                        }
-                        for (;;) {
-                            RECURSIVE_MATCH(40, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                                break;        /* Stop if tried at original pos */
-                        }
-                        
-                        RRETURN;
-                    }
-                    /* Control never reaches here */
-                }
-                
-                /* Caseful comparisons */
-                
-                else {
-                    for (int i = 1; i <= min; i++) {
-                        int d = *stack.currentFrame->args.subjectPtr++;
-                        if (stack.currentFrame->locals.fc == d)
-                            RRETURN_NO_MATCH;
-                    }
-
-                    if (min == stack.currentFrame->locals.max)
-                        NEXT_OPCODE;
-                    
-                    if (minimize) {
-                        for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                            RECURSIVE_MATCH(42, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            int d = *stack.currentFrame->args.subjectPtr++;
-                            if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject || stack.currentFrame->locals.fc == d)
-                                RRETURN;
-                        }
-                        /* Control never reaches here */
-                    }
-                    
-                    /* Maximize case */
-                    
-                    else {
-                        stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                        
-                        for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                            if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                break;
-                            int d = *stack.currentFrame->args.subjectPtr;
-                            if (stack.currentFrame->locals.fc == d)
-                                break;
-                            ++stack.currentFrame->args.subjectPtr;
-                        }
-                        for (;;) {
-                            RECURSIVE_MATCH(44, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                                break;        /* Stop if tried at original pos */
-                        }
-
-                        RRETURN;
-                    }
-                }
-                /* Control never reaches here */
-                
-            /* Match a single character type repeatedly; several different opcodes
-             share code. This is very similar to the code for single characters, but we
-             repeat it in the interests of efficiency. */
-                
-            BEGIN_OPCODE(TYPEEXACT):
-                min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = true;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATTYPE;
-                
-            BEGIN_OPCODE(TYPEUPTO):
-            BEGIN_OPCODE(TYPEMINUPTO):
-                min = 0;
-                stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = *stack.currentFrame->args.instructionPtr == OP_TYPEMINUPTO;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATTYPE;
-                
-            BEGIN_OPCODE(TYPESTAR):
-            BEGIN_OPCODE(TYPEMINSTAR):
-            BEGIN_OPCODE(TYPEPLUS):
-            BEGIN_OPCODE(TYPEMINPLUS):
-            BEGIN_OPCODE(TYPEQUERY):
-            BEGIN_OPCODE(TYPEMINQUERY):
-                repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_TYPESTAR, minimize, min, stack.currentFrame->locals.max);
-                
-                /* Common code for all repeated single character type matches. Note that
-                 in UTF-8 mode, '.' matches a character of any length, but for the other
-                 character types, the valid characters are all one-byte long. */
-                
-            REPEATTYPE:
-                stack.currentFrame->locals.ctype = *stack.currentFrame->args.instructionPtr++;      /* Code for the character type */
-                
-                /* First, ensure the minimum number of matches are present. Use inline
-                 code for maximizing the speed, and do the type test once at the start
-                 (i.e. keep it out of the loop). Also we can test that there are at least
-                 the minimum number of characters before we start. */
-                
-                if (min > md.endSubject - stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                if (min > 0) {
-                    switch (stack.currentFrame->locals.ctype) {
-                        case OP_NOT_NEWLINE:
-                            for (int i = 1; i <= min; i++) {
-                                if (isNewline(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_DIGIT:
-                            for (int i = 1; i <= min; i++) {
-                                if (isASCIIDigit(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_DIGIT:
-                            for (int i = 1; i <= min; i++) {
-                                if (!isASCIIDigit(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_WHITESPACE:
-                            for (int i = 1; i <= min; i++) {
-                                if (isSpaceChar(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_WHITESPACE:
-                            for (int i = 1; i <= min; i++) {
-                                if (!isSpaceChar(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_WORDCHAR:
-                            for (int i = 1; i <= min; i++) {
-                                if (isWordChar(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_WORDCHAR:
-                            for (int i = 1; i <= min; i++) {
-                                if (!isWordChar(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        default:
-                            ASSERT_NOT_REACHED();
-                            return matchError(JSRegExpErrorInternal, stack);
-                    }  /* End switch(stack.currentFrame->locals.ctype) */
-                }
-                
-                /* If min = max, continue at the same level without recursing */
-                
-                if (min == stack.currentFrame->locals.max)
-                    NEXT_OPCODE;    
-                
-                /* If minimizing, we have to test the rest of the pattern before each
-                 subsequent match. */
-                
-                if (minimize) {
-                    for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                        RECURSIVE_MATCH(48, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            RRETURN;
-                        
-                        int c = *stack.currentFrame->args.subjectPtr++;
-                        switch (stack.currentFrame->locals.ctype) {
-                            case OP_NOT_NEWLINE:
-                                if (isNewline(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_NOT_DIGIT:
-                                if (isASCIIDigit(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_DIGIT:
-                                if (!isASCIIDigit(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_NOT_WHITESPACE:
-                                if (isSpaceChar(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_WHITESPACE:
-                                if (!isSpaceChar(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_NOT_WORDCHAR:
-                                if (isWordChar(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_WORDCHAR:
-                                if (!isWordChar(c))
-                                    RRETURN;
-                                break;
-                                
-                            default:
-                                ASSERT_NOT_REACHED();
-                                return matchError(JSRegExpErrorInternal, stack);
-                        }
-                    }
-                    /* Control never reaches here */
-                }
-                
-                /* If maximizing it is worth using inline code for speed, doing the type
-                 test once at the start (i.e. keep it out of the loop). */
-                
-                else {
-                    stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;  /* Remember where we started */
-                    
-                    switch (stack.currentFrame->locals.ctype) {
-                        case OP_NOT_NEWLINE:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject || isNewline(*stack.currentFrame->args.subjectPtr))
-                                    break;
-                                stack.currentFrame->args.subjectPtr++;
-                            }
-                            break;
-                            
-                        case OP_NOT_DIGIT:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (isASCIIDigit(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_DIGIT:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (!isASCIIDigit(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_WHITESPACE:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (isSpaceChar(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_WHITESPACE:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (!isSpaceChar(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_WORDCHAR:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (isWordChar(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_WORDCHAR:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (!isWordChar(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        default:
-                            ASSERT_NOT_REACHED();
-                            return matchError(JSRegExpErrorInternal, stack);
-                    }
-                    
-                    /* stack.currentFrame->args.subjectPtr is now past the end of the maximum run */
-                    
-                    for (;;) {
-                        RECURSIVE_MATCH(52, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                            break;        /* Stop if tried at original pos */
-                    }
-                    
-                    /* Get here if we can't make it match with any permitted repetitions */
-                    
-                    RRETURN;
-                }
-                /* Control never reaches here */
-                
-            BEGIN_OPCODE(CRMINPLUS):
-            BEGIN_OPCODE(CRMINQUERY):
-            BEGIN_OPCODE(CRMINRANGE):
-            BEGIN_OPCODE(CRMINSTAR):
-            BEGIN_OPCODE(CRPLUS):
-            BEGIN_OPCODE(CRQUERY):
-            BEGIN_OPCODE(CRRANGE):
-            BEGIN_OPCODE(CRSTAR):
-                ASSERT_NOT_REACHED();
-                return matchError(JSRegExpErrorInternal, stack);
-                
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-            CAPTURING_BRACKET:
-#else
-            default:
-#endif
-                /* Opening capturing bracket. If there is space in the offset vector, save
-                 the current subject position in the working slot at the top of the vector. We
-                 mustn't change the current values of the data slot, because they may be set
-                 from a previous iteration of this group, and be referred to by a reference
-                 inside the group.
-                 
-                 If the bracket fails to match, we need to restore this value and also the
-                 values of the final offsets, in case they were set by a previous iteration of
-                 the same bracket.
-                 
-                 If there isn't enough space in the offset vector, treat this as if it were a
-                 non-capturing bracket. Don't worry about setting the flag for the error case
-                 here; that is handled in the code for KET. */
-                
-                ASSERT(*stack.currentFrame->args.instructionPtr > OP_BRA);
-                
-                stack.currentFrame->locals.number = *stack.currentFrame->args.instructionPtr - OP_BRA;
-                
-                /* For extended extraction brackets (large number), we have to fish out the
-                 number from a dummy opcode at the start. */
-                
-                if (stack.currentFrame->locals.number > EXTRACT_BASIC_MAX)
-                    stack.currentFrame->locals.number = get2ByteValue(stack.currentFrame->args.instructionPtr + 2 + LINK_SIZE);
-                stack.currentFrame->locals.offset = stack.currentFrame->locals.number << 1;
-                
-#ifdef DEBUG
-                printf("start bracket %d subject=", stack.currentFrame->locals.number);
-                pchars(stack.currentFrame->args.subjectPtr, 16, true, md);
-                printf("\n");
-#endif
-                
-                if (stack.currentFrame->locals.offset < md.offsetMax) {
-                    stack.currentFrame->locals.saveOffset1 = md.offsetVector[stack.currentFrame->locals.offset];
-                    stack.currentFrame->locals.saveOffset2 = md.offsetVector[stack.currentFrame->locals.offset + 1];
-                    stack.currentFrame->locals.saveOffset3 = md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number];
-                    
-                    DPRINTF(("saving %d %d %d\n", stack.currentFrame->locals.saveOffset1, stack.currentFrame->locals.saveOffset2, stack.currentFrame->locals.saveOffset3));
-                    md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number] = stack.currentFrame->args.subjectPtr - md.startSubject;
-                    
-                    do {
-                        RECURSIVE_MATCH_STARTNG_NEW_GROUP(1, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                    } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
-                    
-                    DPRINTF(("bracket %d failed\n", stack.currentFrame->locals.number));
-                    
-                    md.offsetVector[stack.currentFrame->locals.offset] = stack.currentFrame->locals.saveOffset1;
-                    md.offsetVector[stack.currentFrame->locals.offset + 1] = stack.currentFrame->locals.saveOffset2;
-                    md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number] = stack.currentFrame->locals.saveOffset3;
-                    
-                    RRETURN;
-                }
-                
-                /* Insufficient room for saving captured contents */
-                
-                goto NON_CAPTURING_BRACKET;
-        }
-        
-        /* Do not stick any code in here without much thought; it is assumed
-         that "continue" in the code above comes out to here to repeat the main
-         loop. */
-        
-    } /* End of main loop */
-    
-    ASSERT_NOT_REACHED();
-    
-#ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-    
-RRETURN_SWITCH:
-    switch (stack.currentFrame->returnLocation) {
-        case 0: goto RETURN;
-        case 1: goto RRETURN_1;
-        case 2: goto RRETURN_2;
-        case 6: goto RRETURN_6;
-        case 7: goto RRETURN_7;
-        case 14: goto RRETURN_14;
-        case 15: goto RRETURN_15;
-        case 16: goto RRETURN_16;
-        case 17: goto RRETURN_17;
-        case 18: goto RRETURN_18;
-        case 19: goto RRETURN_19;
-        case 20: goto RRETURN_20;
-        case 21: goto RRETURN_21;
-        case 22: goto RRETURN_22;
-        case 24: goto RRETURN_24;
-        case 26: goto RRETURN_26;
-        case 27: goto RRETURN_27;
-        case 28: goto RRETURN_28;
-        case 29: goto RRETURN_29;
-        case 30: goto RRETURN_30;
-        case 31: goto RRETURN_31;
-        case 38: goto RRETURN_38;
-        case 40: goto RRETURN_40;
-        case 42: goto RRETURN_42;
-        case 44: goto RRETURN_44;
-        case 48: goto RRETURN_48;
-        case 52: goto RRETURN_52;
-    }
-    
-    ASSERT_NOT_REACHED();
-    return matchError(JSRegExpErrorInternal, stack);
-    
-#endif
-    
-RETURN:
-    return isMatch;
-}
-
-
-/*************************************************
-*         Execute a Regular Expression           *
-*************************************************/
-
-/* This function applies a compiled re to a subject string and picks out
-portions of the string if it matches. Two elements in the vector are set for
-each substring: the offsets to the start and end of the substring.
-
-Arguments:
-  re              points to the compiled expression
-  extra_data      points to extra data or is NULL
-  subject         points to the subject string
-  length          length of subject string (may contain binary zeros)
-  start_offset    where to start in the subject string
-  options         option bits
-  offsets         points to a vector of ints to be filled in with offsets
-  offsetcount     the number of elements in the vector
-
-Returns:          > 0 => success; value is the number of elements filled in
-                  = 0 => success, but offsets is not big enough
-                   -1 => failed to match
-                 < -1 => some kind of unexpected problem
-*/
-
-static void tryFirstByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int first_byte, bool first_byte_caseless, bool useMultiLineFirstCharOptimization, const UChar* originalSubjectStart)
-{
-    // If first_byte is set, try scanning to the first instance of that byte
-    // no need to try and match against any earlier part of the subject string.
-    if (first_byte >= 0) {
-        UChar first_char = first_byte;
-        if (first_byte_caseless)
-            while (subjectPtr < endSubject) {
-                int c = *subjectPtr;
-                if (c > 127)
-                    break;
-                if (toLowerCase(c) == first_char)
-                    break;
-                subjectPtr++;
-            }
-        else {
-            while (subjectPtr < endSubject && *subjectPtr != first_char)
-                subjectPtr++;
-        }
-    } else if (useMultiLineFirstCharOptimization) {
-        /* Or to just after \n for a multiline match if possible */
-        // I'm not sure why this != originalSubjectStart check is necessary -- ecs 11/18/07
-        if (subjectPtr > originalSubjectStart) {
-            while (subjectPtr < endSubject && !isNewline(subjectPtr[-1]))
-                subjectPtr++;
-        }
-    }
-}
-
-static bool tryRequiredByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int req_byte, int req_byte2, bool req_byte_caseless, bool hasFirstByte, const UChar*& reqBytePtr)
-{
-    /* If req_byte is set, we know that that character must appear in the subject
-     for the match to succeed. If the first character is set, req_byte must be
-     later in the subject; otherwise the test starts at the match point. This
-     optimization can save a huge amount of backtracking in patterns with nested
-     unlimited repeats that aren't going to match. Writing separate code for
-     cased/caseless versions makes it go faster, as does using an autoincrement
-     and backing off on a match.
-     
-     HOWEVER: when the subject string is very, very long, searching to its end can
-     take a long time, and give bad performance on quite ordinary patterns. This
-     showed up when somebody was matching /^C/ on a 32-megabyte string... so we
-     don't do this when the string is sufficiently long.
-    */
-
-    if (req_byte >= 0 && endSubject - subjectPtr < REQ_BYTE_MAX) {
-        const UChar* p = subjectPtr + (hasFirstByte ? 1 : 0);
-
-        /* We don't need to repeat the search if we haven't yet reached the
-         place we found it at last time. */
-
-        if (p > reqBytePtr) {
-            if (req_byte_caseless) {
-                while (p < endSubject) {
-                    int pp = *p++;
-                    if (pp == req_byte || pp == req_byte2) {
-                        p--;
-                        break;
-                    }
-                }
-            } else {
-                while (p < endSubject) {
-                    if (*p++ == req_byte) {
-                        p--;
-                        break;
-                    }
-                }
-            }
-
-            /* If we can't find the required character, break the matching loop */
-
-            if (p >= endSubject)
-                return true;
-
-            /* If we have found the required character, save the point where we
-             found it, so that we don't search again next time round the loop if
-             the start hasn't passed this character yet. */
-
-            reqBytePtr = p;
-        }
-    }
-    return false;
-}
-
-int jsRegExpExecute(const JSRegExp* re,
-                    const UChar* subject, int length, int start_offset, int* offsets,
-                    int offsetcount)
-{
-    ASSERT(re);
-    ASSERT(subject);
-    ASSERT(offsetcount >= 0);
-    ASSERT(offsets || offsetcount == 0);
-    
-    MatchData matchBlock;
-    matchBlock.startSubject = subject;
-    matchBlock.endSubject = matchBlock.startSubject + length;
-    const UChar* endSubject = matchBlock.endSubject;
-    
-    matchBlock.multiline = (re->options & MatchAcrossMultipleLinesOption);
-    matchBlock.ignoreCase = (re->options & IgnoreCaseOption);
-    
-    /* If the expression has got more back references than the offsets supplied can
-     hold, we get a temporary chunk of working store to use during the matching.
-     Otherwise, we can use the vector supplied, rounding down its size to a multiple
-     of 3. */
-    
-    int ocount = offsetcount - (offsetcount % 3);
-    
-    // FIXME: This is lame that we have to second-guess our caller here.
-    // The API should change to either fail-hard when we don't have enough offset space
-    // or that we shouldn't ask our callers to pre-allocate in the first place.
-    bool using_temporary_offsets = false;
-    if (re->top_backref > 0 && re->top_backref >= ocount/3) {
-        ocount = re->top_backref * 3 + 3;
-        matchBlock.offsetVector = new int[ocount];
-        if (!matchBlock.offsetVector)
-            return JSRegExpErrorNoMemory;
-        using_temporary_offsets = true;
-    } else
-        matchBlock.offsetVector = offsets;
-    
-    matchBlock.offsetEnd = ocount;
-    matchBlock.offsetMax = (2*ocount)/3;
-    matchBlock.offsetOverflow = false;
-    
-    /* Compute the minimum number of offsets that we need to reset each time. Doing
-     this makes a huge difference to execution time when there aren't many brackets
-     in the pattern. */
-    
-    int resetcount = 2 + re->top_bracket * 2;
-    if (resetcount > offsetcount)
-        resetcount = ocount;
-    
-    /* Reset the working variable associated with each extraction. These should
-     never be used unless previously set, but they get saved and restored, and so we
-     initialize them to avoid reading uninitialized locations. */
-    
-    if (matchBlock.offsetVector) {
-        int* iptr = matchBlock.offsetVector + ocount;
-        int* iend = iptr - resetcount/2 + 1;
-        while (--iptr >= iend)
-            *iptr = -1;
-    }
-    
-    /* Set up the first character to match, if available. The first_byte value is
-     never set for an anchored regular expression, but the anchoring may be forced
-     at run time, so we have to test for anchoring. The first char may be unset for
-     an unanchored pattern, of course. If there's no first char and the pattern was
-     studied, there may be a bitmap of possible first characters. */
-    
-    bool first_byte_caseless = false;
-    int first_byte = -1;
-    if (re->options & UseFirstByteOptimizationOption) {
-        first_byte = re->first_byte & 255;
-        if ((first_byte_caseless = (re->first_byte & REQ_IGNORE_CASE)))
-            first_byte = toLowerCase(first_byte);
-    }
-    
-    /* For anchored or unanchored matches, there may be a "last known required
-     character" set. */
-    
-    bool req_byte_caseless = false;
-    int req_byte = -1;
-    int req_byte2 = -1;
-    if (re->options & UseRequiredByteOptimizationOption) {
-        req_byte = re->req_byte & 255; // FIXME: This optimization could be made to work for UTF16 chars as well...
-        req_byte_caseless = (re->req_byte & REQ_IGNORE_CASE);
-        req_byte2 = flipCase(req_byte);
-    }
-    
-    /* Loop for handling unanchored repeated matching attempts; for anchored regexs
-     the loop runs just once. */
-    
-    const UChar* startMatch = subject + start_offset;
-    const UChar* reqBytePtr = startMatch - 1;
-    bool useMultiLineFirstCharOptimization = re->options & UseMultiLineFirstByteOptimizationOption;
-    
-    do {
-        /* Reset the maximum number of extractions we might see. */
-        if (matchBlock.offsetVector) {
-            int* iptr = matchBlock.offsetVector;
-            int* iend = iptr + resetcount;
-            while (iptr < iend)
-                *iptr++ = -1;
-        }
-        
-        tryFirstByteOptimization(startMatch, endSubject, first_byte, first_byte_caseless, useMultiLineFirstCharOptimization, matchBlock.startSubject + start_offset);
-        if (tryRequiredByteOptimization(startMatch, endSubject, req_byte, req_byte2, req_byte_caseless, first_byte >= 0, reqBytePtr))
-            break;
-                
-        /* When a match occurs, substrings will be set for all internal extractions;
-         we just need to set up the whole thing as substring 0 before returning. If
-         there were too many extractions, set the return code to zero. In the case
-         where we had to get some local store to hold offsets for backreferences, copy
-         those back references that we can. In this case there need not be overflow
-         if certain parts of the pattern were not used. */
-        
-        /* The code starts after the JSRegExp block and the capture name table. */
-        const unsigned char* start_code = reinterpret_cast<const unsigned char*>(re + 1);
-        
-        int returnCode = match(startMatch, start_code, 2, matchBlock);
-        
-        /* When the result is no match, advance the pointer to the next character
-         and continue. */
-        if (returnCode == 0) {
-            startMatch++;
-            continue;
-        }
-
-        if (returnCode != 1) {
-            ASSERT(returnCode == JSRegExpErrorHitLimit || returnCode == JSRegExpErrorNoMemory);
-            DPRINTF((">>>> error: returning %d\n", returnCode));
-            return returnCode;
-        }
-        
-        /* We have a match! Copy the offset information from temporary store if
-         necessary */
-        
-        if (using_temporary_offsets) {
-            if (offsetcount >= 4) {
-                memcpy(offsets + 2, matchBlock.offsetVector + 2, (offsetcount - 2) * sizeof(int));
-                DPRINTF(("Copied offsets from temporary memory\n"));
-            }
-            if (matchBlock.endOffsetTop > offsetcount)
-                matchBlock.offsetOverflow = true;
-            
-            DPRINTF(("Freeing temporary memory\n"));
-            delete [] matchBlock.offsetVector;
-        }
-        
-        returnCode = matchBlock.offsetOverflow ? 0 : matchBlock.endOffsetTop / 2;
-        
-        if (offsetcount < 2)
-            returnCode = 0;
-        else {
-            offsets[0] = startMatch - matchBlock.startSubject;
-            offsets[1] = matchBlock.endMatchPtr - matchBlock.startSubject;
-        }
-        
-        DPRINTF((">>>> returning %d\n", returnCode));
-        return returnCode;
-    } while (!(re->options & IsAnchoredOption) && startMatch <= endSubject);
-    
-    if (using_temporary_offsets) {
-        DPRINTF(("Freeing temporary memory\n"));
-        delete [] matchBlock.offsetVector;
-    }
-    
-    DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
-    return JSRegExpErrorNoMatch;
-}
-
-} }  // namespace dart::jscre
diff --git a/runtime/third_party/jscre/pcre_internal.h b/runtime/third_party/jscre/pcre_internal.h
deleted file mode 100644
index 92011f8..0000000
--- a/runtime/third_party/jscre/pcre_internal.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* This header contains definitions that are shared between the different
-modules, but which are not relevant to the exported API. This includes some
-functions whose names all begin with "_pcre_". */
-
-#ifndef THIRD_PARTY_JSCRE_PCRE_INTERNAL_H_
-#define THIRD_PARTY_JSCRE_PCRE_INTERNAL_H_
-
-#if defined(_WIN32)
-typedef unsigned __int32 uint32_t;
-#else
-#include <inttypes.h>
-#include <stdint.h>
-#endif
-
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-/* Bit definitions for entries in the pcre_ctypes table. */
-
-#define ctype_space   0x01
-#define ctype_xdigit  0x08
-#define ctype_word    0x10   /* alphameric or '_' */
-
-/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
-of bits for a class map. Some classes are built by combining these tables. */
-
-#define cbit_space     0      /* \s */
-#define cbit_digit    32      /* \d */
-#define cbit_word     64      /* \w */
-#define cbit_length   96      /* Length of the cbits table */
-
-/* Offsets of the various tables from the base tables pointer, and
-total length. */
-
-#define lcc_offset      0
-#define fcc_offset    128
-#define cbits_offset  256
-#define ctypes_offset (cbits_offset + cbit_length)
-#define tables_length (ctypes_offset + 128)
-
-#ifndef DFTABLES
-
-// TODO(xxx): Hook this up to something that checks assertions.
-#define ASSERT(x) if (!(x)) abort()
-#define ASSERT_NOT_REACHED() abort()
-
-#ifdef WIN32
-#pragma warning(disable: 4232)
-#pragma warning(disable: 4244)
-#endif
-
-#include "./pcre.h"
-
-/* The value of LINK_SIZE determines the number of bytes used to store links as
-offsets within the compiled regex. The default is 2, which allows for compiled
-patterns up to 64K long. */
-
-#define LINK_SIZE   2
-
-/* Define DEBUG to get debugging output on stdout. */
-
-#if 0
-#define DEBUG
-#endif
-
-/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
-inline, and there are *still* stupid compilers about that don't like indented
-pre-processor statements, or at least there were when I first wrote this. After
-all, it had only been about 10 years then... */
-
-#ifdef DEBUG
-#define DPRINTF(p) printf p
-#else
-#define DPRINTF(p) /*nothing*/
-#endif
-
-namespace dart { namespace jscre {
-
-/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored
-in big-endian order) by default. These are used, for example, to link from the
-start of a subpattern to its alternatives and its end. The use of 2 bytes per
-offset limits the size of the compiled regex to around 64K, which is big enough
-for almost everybody. However, I received a request for an even bigger limit.
-For this reason, and also to make the code easier to maintain, the storing and
-loading of offsets from the byte string is now handled by the functions that are
-defined here. */
-
-/* PCRE uses some other 2-byte quantities that do not change when the size of
-offsets changes. There are used for repeat counts and for other things such as
-capturing parenthesis numbers in back references. */
-
-static inline void put2ByteValue(unsigned char* opcodePtr, int value) {
-    ASSERT(value >= 0 && value <= 0xFFFF);
-    opcodePtr[0] = value >> 8;
-    opcodePtr[1] = value;
-}
-
-static inline int get2ByteValue(const unsigned char* opcodePtr) {
-    return (opcodePtr[0] << 8) | opcodePtr[1];
-}
-
-static inline void put2ByteValueAndAdvance(unsigned char*& opcodePtr,
-                                           int value) {
-    put2ByteValue(opcodePtr, value);
-    opcodePtr += 2;
-}
-
-static inline void putLinkValueAllowZero(unsigned char* opcodePtr,
-                                         int value) {
-    put2ByteValue(opcodePtr, value);
-}
-
-static inline int getLinkValueAllowZero(const unsigned char* opcodePtr) {
-    return get2ByteValue(opcodePtr);
-}
-
-#define MAX_PATTERN_SIZE (1 << 16)
-
-static inline void putLinkValue(unsigned char* opcodePtr, int value) {
-    ASSERT(value);
-    putLinkValueAllowZero(opcodePtr, value);
-}
-
-static inline int getLinkValue(const unsigned char* opcodePtr) {
-    int value = getLinkValueAllowZero(opcodePtr);
-    ASSERT(value);
-    return value;
-}
-
-static inline void putLinkValueAndAdvance(unsigned char*& opcodePtr,
-                                          int value) {
-    putLinkValue(opcodePtr, value);
-    opcodePtr += LINK_SIZE;
-}
-
-static inline void putLinkValueAllowZeroAndAdvance(unsigned char*& opcodePtr,
-                                                   int value) {
-    putLinkValueAllowZero(opcodePtr, value);
-    opcodePtr += LINK_SIZE;
-}
-
-// FIXME: These are really more of a "compiled regexp state"
-// than "regexp options"
-enum RegExpOptions {
-    UseFirstByteOptimizationOption = 0x40000000,  /* first_byte is set */
-    UseRequiredByteOptimizationOption = 0x20000000,  /* req_byte is set */
-    UseMultiLineFirstByteOptimizationOption = 0x10000000,
-      /* start after \n for multiline */
-    IsAnchoredOption = 0x02000000,  /* can't use partial with this regex */
-    IgnoreCaseOption = 0x00000001,
-    MatchAcrossMultipleLinesOption = 0x00000002
-};
-
-/* Flags added to firstbyte or reqbyte; a "non-literal" item is either a
-variable-length repeat, or a anything other than literal characters. */
-
-#define REQ_IGNORE_CASE 0x0100    /* indicates should ignore case */
-#define REQ_VARY     0x0200    /* reqbyte followed non-literal item */
-
-/* Miscellaneous definitions */
-
-/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
-contain UTF-8 characters with values greater than 255. */
-
-#define XCL_NOT    0x01    /* Flag: this is a negative class */
-#define XCL_MAP    0x02    /* Flag: a 32-byte map is present */
-
-#define XCL_END       0    /* Marks end of individual items */
-#define XCL_SINGLE    1    /* Single item (one multibyte char) follows */
-#define XCL_RANGE     2    /* A range (two multibyte chars) follows */
-
-/* These are escaped items that aren't just an encoding of a particular data
-value such as \n. They must have non-zero values, as check_escape() returns
-their negation. Also, they must appear in the same order as in the opcode
-definitions below, up to ESC_w. The final one must be
-ESC_REF as subsequent values are used for \1, \2, \3, etc. There is are two
-tests in the code for an escape > ESC_b and <= ESC_w to
-detect the types that may be repeated. These are the types that consume
-characters. If any new escapes are put in between that don't consume a
-character, that code will have to change. */
-
-enum { ESC_B = 1, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w, ESC_REF };
-
-/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
-that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
-OP_EOD must correspond in order to the list of escapes immediately above.
-Note that whenever this list is updated, the two macro definitions that follow
-must also be updated to match. */
-
-#define FOR_EACH_OPCODE(macro) \
-    macro(END) \
-    \
-    macro(NOT_WORD_BOUNDARY) \
-    macro(WORD_BOUNDARY) \
-    macro(NOT_DIGIT) \
-    macro(DIGIT) \
-    macro(NOT_WHITESPACE) \
-    macro(WHITESPACE) \
-    macro(NOT_WORDCHAR) \
-    macro(WORDCHAR) \
-    \
-    macro(NOT_NEWLINE) \
-    \
-    macro(CIRC) \
-    macro(DOLL) \
-    macro(BOL) \
-    macro(EOL) \
-    macro(CHAR) \
-    macro(CHAR_IGNORING_CASE) \
-    macro(ASCII_CHAR) \
-    macro(ASCII_LETTER_IGNORING_CASE) \
-    macro(NOT) \
-    \
-    macro(STAR) \
-    macro(MINSTAR) \
-    macro(PLUS) \
-    macro(MINPLUS) \
-    macro(QUERY) \
-    macro(MINQUERY) \
-    macro(UPTO) \
-    macro(MINUPTO) \
-    macro(EXACT) \
-    \
-    macro(NOTSTAR) \
-    macro(NOTMINSTAR) \
-    macro(NOTPLUS) \
-    macro(NOTMINPLUS) \
-    macro(NOTQUERY) \
-    macro(NOTMINQUERY) \
-    macro(NOTUPTO) \
-    macro(NOTMINUPTO) \
-    macro(NOTEXACT) \
-    \
-    macro(TYPESTAR) \
-    macro(TYPEMINSTAR) \
-    macro(TYPEPLUS) \
-    macro(TYPEMINPLUS) \
-    macro(TYPEQUERY) \
-    macro(TYPEMINQUERY) \
-    macro(TYPEUPTO) \
-    macro(TYPEMINUPTO) \
-    macro(TYPEEXACT) \
-    \
-    macro(CRSTAR) \
-    macro(CRMINSTAR) \
-    macro(CRPLUS) \
-    macro(CRMINPLUS) \
-    macro(CRQUERY) \
-    macro(CRMINQUERY) \
-    macro(CRRANGE) \
-    macro(CRMINRANGE) \
-    \
-    macro(CLASS) \
-    macro(NCLASS) \
-    macro(XCLASS) \
-    \
-    macro(REF) \
-    \
-    macro(ALT) \
-    macro(KET) \
-    macro(KETRMAX) \
-    macro(KETRMIN) \
-    \
-    macro(ASSERT) \
-    macro(ASSERT_NOT) \
-    \
-    macro(BRAZERO) \
-    macro(BRAMINZERO) \
-    macro(BRANUMBER) \
-    macro(BRA)
-
-#define OPCODE_ENUM_VALUE(opcode) OP_##opcode,
-enum { FOR_EACH_OPCODE(OPCODE_ENUM_VALUE) };
-
-/* WARNING WARNING WARNING: There is an implicit assumption in pcre.c and
-study.c that all opcodes are less than 128 in value. This makes handling UTF-8
-character sequences easier. */
-
-/* The highest extraction number before we have to start using additional
-bytes. (Originally PCRE didn't have support for extraction counts higher than
-this number.) The value is limited by the number of opcodes left after OP_BRA,
-i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional
-opcodes. */
-
-/* FIXME: Note that OP_BRA + 100 is > 128, so the two comments above
-are in conflict! */
-
-#define EXTRACT_BASIC_MAX  100
-
-/* The index of names and the
-code vector run on as long as necessary after the end. We store an explicit
-offset to the name table so that if a regex is compiled on one host, saved, and
-then run on another where the size of pointers is different, all might still
-be well. For the case of compiled-on-4 and run-on-8, we include an extra
-pointer that is always NULL.
-*/
-
-struct JSRegExp {
-    uint32_t options;
-
-    uint16_t top_bracket;
-    uint16_t top_backref;
-
-    uint16_t first_byte;
-    uint16_t req_byte;
-};
-
-/* Internal shared data tables. These are tables that are used by more than one
- of the exported public functions. They have to be "external" in the C sense,
- but are not part of the PCRE public API. The data for these tables is in the
- pcre_tables.c module. */
-
-#define kjs_pcre_utf8_table1_size 6
-
-extern const int    kjs_pcre_utf8_table1[6];
-extern const int    kjs_pcre_utf8_table2[6];
-extern const int    kjs_pcre_utf8_table3[6];
-extern const unsigned char kjs_pcre_utf8_table4[0x40];
-
-extern const unsigned char kjs_pcre_default_tables[tables_length];
-
-static inline unsigned char toLowerCase(unsigned char c) {
-    static const unsigned char* lowerCaseChars =
-        kjs_pcre_default_tables + lcc_offset;
-    return lowerCaseChars[c];
-}
-
-static inline unsigned char flipCase(unsigned char c) {
-    static const unsigned char* flippedCaseChars =
-        kjs_pcre_default_tables + fcc_offset;
-    return flippedCaseChars[c];
-}
-
-static inline unsigned char classBitmapForChar(unsigned char c) {
-    static const unsigned char* charClassBitmaps =
-        kjs_pcre_default_tables + cbits_offset;
-    return charClassBitmaps[c];
-}
-
-static inline unsigned char charTypeForChar(unsigned char c) {
-    const unsigned char* charTypeMap = kjs_pcre_default_tables + ctypes_offset;
-    return charTypeMap[c];
-}
-
-static inline bool isWordChar(UChar c) {
-    return c < 128 && (charTypeForChar(c) & ctype_word);
-}
-
-static inline bool isSpaceChar(UChar c) {
-    return (c < 128 && (charTypeForChar(c) & ctype_space));
-}
-
-static inline bool isNewline(UChar nl) {
-    return (nl == 0xA || nl == 0xD || nl == 0x2028 || nl == 0x2029);
-}
-
-static inline bool isBracketStartOpcode(unsigned char opcode) {
-    if (opcode >= OP_BRA)
-        return true;
-    switch (opcode) {
-        case OP_ASSERT:
-        case OP_ASSERT_NOT:
-            return true;
-        default:
-            return false;
-    }
-}
-
-static inline void advanceToEndOfBracket(const unsigned char*& opcodePtr) {
-    ASSERT(isBracketStartOpcode(*opcodePtr) || *opcodePtr == OP_ALT);
-    do
-        opcodePtr += getLinkValue(opcodePtr + 1);
-    while (*opcodePtr == OP_ALT);
-}
-
-/* Internal shared functions. These are functions that are used in more
-that one of the source files. They have to have external linkage, but
-but are not part of the public API and so not exported from the library. */
-
-extern int kjs_pcre_ucp_othercase(unsigned);
-extern bool kjs_pcre_xclass(int, const unsigned char*);
-
-} }  // namespace dart::jscre
-#endif
-
-#endif  // THIRD_PARTY_JSCRE_PCRE_INTERNAL_H_
diff --git a/runtime/third_party/jscre/pcre_tables.cpp b/runtime/third_party/jscre/pcre_tables.cpp
deleted file mode 100644
index 943b80c..0000000
--- a/runtime/third_party/jscre/pcre_tables.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* This module contains some fixed tables that are used by more than one of the
-PCRE code modules. */
-
-#include "pcre_internal.h"
-
-namespace dart { namespace jscre {
-
-/*************************************************
-*           Tables for UTF-8 support             *
-*************************************************/
-
-/* These are the breakpoints for different numbers of bytes in a UTF-8
-character. */
-
-const int kjs_pcre_utf8_table1[6] =
-  { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
-
-/* These are the indicator bits and the mask for the data bits to set in the
-first byte of a character, indexed by the number of additional bytes. */
-
-const int kjs_pcre_utf8_table2[6] = { 0,    0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
-const int kjs_pcre_utf8_table3[6] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
-
-/* Table of the number of extra characters, indexed by the first character
-masked with 0x3f. The highest number for a valid UTF-8 character is in fact
-0x3d. */
-
-const unsigned char kjs_pcre_utf8_table4[0x40] = {
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
-
-#include "pcre_chartables.c"
-
-} }  // namespace dart::jscre
diff --git a/runtime/third_party/jscre/pcre_ucp_searchfuncs.cpp b/runtime/third_party/jscre/pcre_ucp_searchfuncs.cpp
deleted file mode 100644
index 07fa42b..0000000
--- a/runtime/third_party/jscre/pcre_ucp_searchfuncs.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains code for searching the table of Unicode character
-properties. */
-
-#include "pcre_internal.h"
-
-#include "ucpinternal.h"       /* Internal table details */
-#include "ucptable.cpp"        /* The table itself */
-
-namespace dart { namespace jscre {
-
-/*************************************************
-*       Search table and return other case       *
-*************************************************/
-
-/* If the given character is a letter, and there is another case for the
-letter, return the other case. Otherwise, return -1.
-
-Arguments:
-  c           the character value
-
-Returns:      the other case or -1 if none
-*/
-
-int kjs_pcre_ucp_othercase(unsigned c)
-{
-    int bot = 0;
-    int top = sizeof(ucp_table) / sizeof(cnode);
-    int mid;
-    
-    /* The table is searched using a binary chop. You might think that using
-     intermediate variables to hold some of the common expressions would speed
-     things up, but tests with gcc 3.4.4 on Linux showed that, on the contrary, it
-     makes things a lot slower. */
-    
-    for (;;) {
-        if (top <= bot)
-            return -1;
-        mid = (bot + top) >> 1;
-        if (c == (ucp_table[mid].f0 & f0_charmask))
-            break;
-        if (c < (ucp_table[mid].f0 & f0_charmask))
-            top = mid;
-        else {
-            if ((ucp_table[mid].f0 & f0_rangeflag) && (c <= (ucp_table[mid].f0 & f0_charmask) + (ucp_table[mid].f1 & f1_rangemask)))
-                break;
-            bot = mid + 1;
-        }
-    }
-    
-    /* Found an entry in the table. Return -1 for a range entry. Otherwise return
-     the other case if there is one, else -1. */
-    
-    if (ucp_table[mid].f0 & f0_rangeflag)
-        return -1;
-    
-    int offset = ucp_table[mid].f1 & f1_casemask;
-    if (offset & f1_caseneg)
-        offset |= f1_caseneg;
-    return !offset ? -1 : c + offset;
-}
-
-} }  // namespace dart::jscre
diff --git a/runtime/third_party/jscre/pcre_xclass.cpp b/runtime/third_party/jscre/pcre_xclass.cpp
deleted file mode 100644
index 5d170e5..0000000
--- a/runtime/third_party/jscre/pcre_xclass.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-/* This module contains an internal function that is used to match an extended
-class (one that contains characters whose values are > 255). */
-
-#include "pcre_internal.h"
-
-namespace dart { namespace jscre {
-
-/*************************************************
-*       Match character against an XCLASS        *
-*************************************************/
-
-/* This function is called to match a character against an extended class that
-might contain values > 255.
-
-Arguments:
-  c           the character
-  data        points to the flag byte of the XCLASS data
-
-Returns:      true if character matches, else false
-*/
-
-/* Get the next UTF-8 character, advancing the pointer. This is called when we
- know we are in UTF-8 mode. */
-
-static inline void getUTF8CharAndAdvancePointer(int& c, const unsigned char*& subjectPtr)
-{
-    c = *subjectPtr++;
-    if ((c & 0xc0) == 0xc0) {
-        int gcaa = kjs_pcre_utf8_table4[c & 0x3f];  /* Number of additional bytes */
-        int gcss = 6 * gcaa;
-        c = (c & kjs_pcre_utf8_table3[gcaa]) << gcss;
-        while (gcaa-- > 0) {
-            gcss -= 6;
-            c |= (*subjectPtr++ & 0x3f) << gcss;
-        }
-    }
-}
-
-bool kjs_pcre_xclass(int c, const unsigned char* data)
-{
-    bool negated = (*data & XCL_NOT);
-    
-    /* Character values < 256 are matched against a bitmap, if one is present. If
-     not, we still carry on, because there may be ranges that start below 256 in the
-     additional data. */
-    
-    if (c < 256) {
-        if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0)
-            return !negated;   /* char found */
-    }
-    
-    /* First skip the bit map if present. Then match against the list of Unicode
-     properties or large chars or ranges that end with a large char. We won't ever
-     encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */
-    
-    if ((*data++ & XCL_MAP) != 0)
-        data += 32;
-    
-    int t;
-    while ((t = *data++) != XCL_END) {
-        if (t == XCL_SINGLE) {
-            int x;
-            getUTF8CharAndAdvancePointer(x, data);
-            if (c == x)
-                return !negated;
-        }
-        else if (t == XCL_RANGE) {
-            int x, y;
-            getUTF8CharAndAdvancePointer(x, data);
-            getUTF8CharAndAdvancePointer(y, data);
-            if (c >= x && c <= y)
-                return !negated;
-        }
-    }
-    
-    return negated;   /* char did not match */
-}
-
-} }  // namespace dart::jscre
diff --git a/runtime/third_party/jscre/ucpinternal.h b/runtime/third_party/jscre/ucpinternal.h
deleted file mode 100644
index c7b3c46..0000000
--- a/runtime/third_party/jscre/ucpinternal.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 Apple Inc. All rights reserved.
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-#ifndef THIRD_PARTY_JSCRE_UCPINTERNAL_H_
-#define THIRD_PARTY_JSCRE_UCPINTERNAL_H_
-
-/*************************************************
-*           Unicode Property Table handler       *
-*************************************************/
-
-/* Internal header file defining the layout of the bits in each pair of 32-bit
-words that form a data item in the table. */
-
-typedef struct cnode {
-  unsigned f0;
-  unsigned f1;
-} cnode;
-
-/* Things for the f0 field */
-
-#define f0_scriptmask   0xff000000  /* Mask for script field */
-#define f0_scriptshift          24  /* Shift for script value */
-#define f0_rangeflag    0x00f00000  /* Flag for a range item */
-#define f0_charmask     0x001fffff  /* Mask for code point value */
-
-/* Things for the f1 field */
-
-#define f1_typemask     0xfc000000  /* Mask for char type field */
-#define f1_typeshift            26  /* Shift for the type field */
-#define f1_rangemask    0x0000ffff  /* Mask for a range offset */
-#define f1_casemask     0x0000ffff  /* Mask for a case offset */
-#define f1_caseneg      0xffff8000  /* Bits for negation */
-
-/* The data consists of a vector of structures of type cnode. The two unsigned
-32-bit integers are used as follows:
-
-(f0) (1) The most significant byte holds the script number. The numbers are
-         defined by the enum in ucp.h.
-
-     (2) The 0x00800000 bit is set if this entry defines a range of characters.
-         It is not set if this entry defines a single character
-
-     (3) The 0x00600000 bits are spare.
-
-     (4) The 0x001fffff bits contain the code point. No Unicode code point will
-         ever be greater than 0x0010ffff, so this should be OK for ever.
-
-(f1) (1) The 0xfc000000 bits contain the character type number. The numbers are
-         defined by an enum in ucp.h.
-
-     (2) The 0x03ff0000 bits are spare.
-
-     (3) The 0x0000ffff bits contain EITHER the unsigned offset to the top of
-         range if this entry defines a range, OR the *signed* offset to the
-         character's "other case" partner if this entry defines a single
-         character. There is no partner if the value is zero.
-
--------------------------------------------------------------------------------
-| script (8) |.|.|.| codepoint (21) || type (6) |.|.| spare (8) | offset (16) |
--------------------------------------------------------------------------------
-              | | |                              | |
-              | | |-> spare                      | |-> spare
-              | |                                |
-              | |-> spare                        |-> spare
-              |
-              |-> range flag
-
-The upper/lower casing information is set only for characters that come in
-pairs. The non-one-to-one mappings in the Unicode data are ignored.
-
-When searching the data, proceed as follows:
-
-(1) Set up for a binary chop search.
-
-(2) If the top is not greater than the bottom, the character is not in the
-    table. Its type must therefore be "Cn" ("Undefined").
-
-(3) Find the middle vector element.
-
-(4) Extract the code point and compare. If equal, we are done.
-
-(5) If the test character is smaller, set the top to the current point, and
-    goto (2).
-
-(6) If the current entry defines a range, compute the last character by adding
-    the offset, and see if the test character is within the range. If it is,
-    we are done.
-
-(7) Otherwise, set the bottom to one element past the current point and goto
-    (2).
-*/
-
-/* End of ucpinternal.h */
-#endif  // THIRD_PARTY_JSCRE_UCPINTERNAL_H_
diff --git a/runtime/third_party/jscre/ucptable.cpp b/runtime/third_party/jscre/ucptable.cpp
deleted file mode 100644
index 011f7f5..0000000
--- a/runtime/third_party/jscre/ucptable.cpp
+++ /dev/null
@@ -1,2968 +0,0 @@
-/* This source module is automatically generated from the Unicode
-property table. See ucpinternal.h for a description of the layout. */
-
-static const cnode ucp_table[] = {
-  { 0x09800000, 0x0000001f },
-  { 0x09000020, 0x74000000 },
-  { 0x09800021, 0x54000002 },
-  { 0x09000024, 0x5c000000 },
-  { 0x09800025, 0x54000002 },
-  { 0x09000028, 0x58000000 },
-  { 0x09000029, 0x48000000 },
-  { 0x0900002a, 0x54000000 },
-  { 0x0900002b, 0x64000000 },
-  { 0x0900002c, 0x54000000 },
-  { 0x0900002d, 0x44000000 },
-  { 0x0980002e, 0x54000001 },
-  { 0x09800030, 0x34000009 },
-  { 0x0980003a, 0x54000001 },
-  { 0x0980003c, 0x64000002 },
-  { 0x0980003f, 0x54000001 },
-  { 0x21000041, 0x24000020 },
-  { 0x21000042, 0x24000020 },
-  { 0x21000043, 0x24000020 },
-  { 0x21000044, 0x24000020 },
-  { 0x21000045, 0x24000020 },
-  { 0x21000046, 0x24000020 },
-  { 0x21000047, 0x24000020 },
-  { 0x21000048, 0x24000020 },
-  { 0x21000049, 0x24000020 },
-  { 0x2100004a, 0x24000020 },
-  { 0x2100004b, 0x24000020 },
-  { 0x2100004c, 0x24000020 },
-  { 0x2100004d, 0x24000020 },
-  { 0x2100004e, 0x24000020 },
-  { 0x2100004f, 0x24000020 },
-  { 0x21000050, 0x24000020 },
-  { 0x21000051, 0x24000020 },
-  { 0x21000052, 0x24000020 },
-  { 0x21000053, 0x24000020 },
-  { 0x21000054, 0x24000020 },
-  { 0x21000055, 0x24000020 },
-  { 0x21000056, 0x24000020 },
-  { 0x21000057, 0x24000020 },
-  { 0x21000058, 0x24000020 },
-  { 0x21000059, 0x24000020 },
-  { 0x2100005a, 0x24000020 },
-  { 0x0900005b, 0x58000000 },
-  { 0x0900005c, 0x54000000 },
-  { 0x0900005d, 0x48000000 },
-  { 0x0900005e, 0x60000000 },
-  { 0x0900005f, 0x40000000 },
-  { 0x09000060, 0x60000000 },
-  { 0x21000061, 0x1400ffe0 },
-  { 0x21000062, 0x1400ffe0 },
-  { 0x21000063, 0x1400ffe0 },
-  { 0x21000064, 0x1400ffe0 },
-  { 0x21000065, 0x1400ffe0 },
-  { 0x21000066, 0x1400ffe0 },
-  { 0x21000067, 0x1400ffe0 },
-  { 0x21000068, 0x1400ffe0 },
-  { 0x21000069, 0x1400ffe0 },
-  { 0x2100006a, 0x1400ffe0 },
-  { 0x2100006b, 0x1400ffe0 },
-  { 0x2100006c, 0x1400ffe0 },
-  { 0x2100006d, 0x1400ffe0 },
-  { 0x2100006e, 0x1400ffe0 },
-  { 0x2100006f, 0x1400ffe0 },
-  { 0x21000070, 0x1400ffe0 },
-  { 0x21000071, 0x1400ffe0 },
-  { 0x21000072, 0x1400ffe0 },
-  { 0x21000073, 0x1400ffe0 },
-  { 0x21000074, 0x1400ffe0 },
-  { 0x21000075, 0x1400ffe0 },
-  { 0x21000076, 0x1400ffe0 },
-  { 0x21000077, 0x1400ffe0 },
-  { 0x21000078, 0x1400ffe0 },
-  { 0x21000079, 0x1400ffe0 },
-  { 0x2100007a, 0x1400ffe0 },
-  { 0x0900007b, 0x58000000 },
-  { 0x0900007c, 0x64000000 },
-  { 0x0900007d, 0x48000000 },
-  { 0x0900007e, 0x64000000 },
-  { 0x0980007f, 0x00000020 },
-  { 0x090000a0, 0x74000000 },
-  { 0x090000a1, 0x54000000 },
-  { 0x098000a2, 0x5c000003 },
-  { 0x098000a6, 0x68000001 },
-  { 0x090000a8, 0x60000000 },
-  { 0x090000a9, 0x68000000 },
-  { 0x210000aa, 0x14000000 },
-  { 0x090000ab, 0x50000000 },
-  { 0x090000ac, 0x64000000 },
-  { 0x090000ad, 0x04000000 },
-  { 0x090000ae, 0x68000000 },
-  { 0x090000af, 0x60000000 },
-  { 0x090000b0, 0x68000000 },
-  { 0x090000b1, 0x64000000 },
-  { 0x098000b2, 0x3c000001 },
-  { 0x090000b4, 0x60000000 },
-  { 0x090000b5, 0x140002e7 },
-  { 0x090000b6, 0x68000000 },
-  { 0x090000b7, 0x54000000 },
-  { 0x090000b8, 0x60000000 },
-  { 0x090000b9, 0x3c000000 },
-  { 0x210000ba, 0x14000000 },
-  { 0x090000bb, 0x4c000000 },
-  { 0x098000bc, 0x3c000002 },
-  { 0x090000bf, 0x54000000 },
-  { 0x210000c0, 0x24000020 },
-  { 0x210000c1, 0x24000020 },
-  { 0x210000c2, 0x24000020 },
-  { 0x210000c3, 0x24000020 },
-  { 0x210000c4, 0x24000020 },
-  { 0x210000c5, 0x24000020 },
-  { 0x210000c6, 0x24000020 },
-  { 0x210000c7, 0x24000020 },
-  { 0x210000c8, 0x24000020 },
-  { 0x210000c9, 0x24000020 },
-  { 0x210000ca, 0x24000020 },
-  { 0x210000cb, 0x24000020 },
-  { 0x210000cc, 0x24000020 },
-  { 0x210000cd, 0x24000020 },
-  { 0x210000ce, 0x24000020 },
-  { 0x210000cf, 0x24000020 },
-  { 0x210000d0, 0x24000020 },
-  { 0x210000d1, 0x24000020 },
-  { 0x210000d2, 0x24000020 },
-  { 0x210000d3, 0x24000020 },
-  { 0x210000d4, 0x24000020 },
-  { 0x210000d5, 0x24000020 },
-  { 0x210000d6, 0x24000020 },
-  { 0x090000d7, 0x64000000 },
-  { 0x210000d8, 0x24000020 },
-  { 0x210000d9, 0x24000020 },
-  { 0x210000da, 0x24000020 },
-  { 0x210000db, 0x24000020 },
-  { 0x210000dc, 0x24000020 },
-  { 0x210000dd, 0x24000020 },
-  { 0x210000de, 0x24000020 },
-  { 0x210000df, 0x14000000 },
-  { 0x210000e0, 0x1400ffe0 },
-  { 0x210000e1, 0x1400ffe0 },
-  { 0x210000e2, 0x1400ffe0 },
-  { 0x210000e3, 0x1400ffe0 },
-  { 0x210000e4, 0x1400ffe0 },
-  { 0x210000e5, 0x1400ffe0 },
-  { 0x210000e6, 0x1400ffe0 },
-  { 0x210000e7, 0x1400ffe0 },
-  { 0x210000e8, 0x1400ffe0 },
-  { 0x210000e9, 0x1400ffe0 },
-  { 0x210000ea, 0x1400ffe0 },
-  { 0x210000eb, 0x1400ffe0 },
-  { 0x210000ec, 0x1400ffe0 },
-  { 0x210000ed, 0x1400ffe0 },
-  { 0x210000ee, 0x1400ffe0 },
-  { 0x210000ef, 0x1400ffe0 },
-  { 0x210000f0, 0x1400ffe0 },
-  { 0x210000f1, 0x1400ffe0 },
-  { 0x210000f2, 0x1400ffe0 },
-  { 0x210000f3, 0x1400ffe0 },
-  { 0x210000f4, 0x1400ffe0 },
-  { 0x210000f5, 0x1400ffe0 },
-  { 0x210000f6, 0x1400ffe0 },
-  { 0x090000f7, 0x64000000 },
-  { 0x210000f8, 0x1400ffe0 },
-  { 0x210000f9, 0x1400ffe0 },
-  { 0x210000fa, 0x1400ffe0 },
-  { 0x210000fb, 0x1400ffe0 },
-  { 0x210000fc, 0x1400ffe0 },
-  { 0x210000fd, 0x1400ffe0 },
-  { 0x210000fe, 0x1400ffe0 },
-  { 0x210000ff, 0x14000079 },
-  { 0x21000100, 0x24000001 },
-  { 0x21000101, 0x1400ffff },
-  { 0x21000102, 0x24000001 },
-  { 0x21000103, 0x1400ffff },
-  { 0x21000104, 0x24000001 },
-  { 0x21000105, 0x1400ffff },
-  { 0x21000106, 0x24000001 },
-  { 0x21000107, 0x1400ffff },
-  { 0x21000108, 0x24000001 },
-  { 0x21000109, 0x1400ffff },
-  { 0x2100010a, 0x24000001 },
-  { 0x2100010b, 0x1400ffff },
-  { 0x2100010c, 0x24000001 },
-  { 0x2100010d, 0x1400ffff },
-  { 0x2100010e, 0x24000001 },
-  { 0x2100010f, 0x1400ffff },
-  { 0x21000110, 0x24000001 },
-  { 0x21000111, 0x1400ffff },
-  { 0x21000112, 0x24000001 },
-  { 0x21000113, 0x1400ffff },
-  { 0x21000114, 0x24000001 },
-  { 0x21000115, 0x1400ffff },
-  { 0x21000116, 0x24000001 },
-  { 0x21000117, 0x1400ffff },
-  { 0x21000118, 0x24000001 },
-  { 0x21000119, 0x1400ffff },
-  { 0x2100011a, 0x24000001 },
-  { 0x2100011b, 0x1400ffff },
-  { 0x2100011c, 0x24000001 },
-  { 0x2100011d, 0x1400ffff },
-  { 0x2100011e, 0x24000001 },
-  { 0x2100011f, 0x1400ffff },
-  { 0x21000120, 0x24000001 },
-  { 0x21000121, 0x1400ffff },
-  { 0x21000122, 0x24000001 },
-  { 0x21000123, 0x1400ffff },
-  { 0x21000124, 0x24000001 },
-  { 0x21000125, 0x1400ffff },
-  { 0x21000126, 0x24000001 },
-  { 0x21000127, 0x1400ffff },
-  { 0x21000128, 0x24000001 },
-  { 0x21000129, 0x1400ffff },
-  { 0x2100012a, 0x24000001 },
-  { 0x2100012b, 0x1400ffff },
-  { 0x2100012c, 0x24000001 },
-  { 0x2100012d, 0x1400ffff },
-  { 0x2100012e, 0x24000001 },
-  { 0x2100012f, 0x1400ffff },
-  { 0x21000130, 0x2400ff39 },
-  { 0x21000131, 0x1400ff18 },
-  { 0x21000132, 0x24000001 },
-  { 0x21000133, 0x1400ffff },
-  { 0x21000134, 0x24000001 },
-  { 0x21000135, 0x1400ffff },
-  { 0x21000136, 0x24000001 },
-  { 0x21000137, 0x1400ffff },
-  { 0x21000138, 0x14000000 },
-  { 0x21000139, 0x24000001 },
-  { 0x2100013a, 0x1400ffff },
-  { 0x2100013b, 0x24000001 },
-  { 0x2100013c, 0x1400ffff },
-  { 0x2100013d, 0x24000001 },
-  { 0x2100013e, 0x1400ffff },
-  { 0x2100013f, 0x24000001 },
-  { 0x21000140, 0x1400ffff },
-  { 0x21000141, 0x24000001 },
-  { 0x21000142, 0x1400ffff },
-  { 0x21000143, 0x24000001 },
-  { 0x21000144, 0x1400ffff },
-  { 0x21000145, 0x24000001 },
-  { 0x21000146, 0x1400ffff },
-  { 0x21000147, 0x24000001 },
-  { 0x21000148, 0x1400ffff },
-  { 0x21000149, 0x14000000 },
-  { 0x2100014a, 0x24000001 },
-  { 0x2100014b, 0x1400ffff },
-  { 0x2100014c, 0x24000001 },
-  { 0x2100014d, 0x1400ffff },
-  { 0x2100014e, 0x24000001 },
-  { 0x2100014f, 0x1400ffff },
-  { 0x21000150, 0x24000001 },
-  { 0x21000151, 0x1400ffff },
-  { 0x21000152, 0x24000001 },
-  { 0x21000153, 0x1400ffff },
-  { 0x21000154, 0x24000001 },
-  { 0x21000155, 0x1400ffff },
-  { 0x21000156, 0x24000001 },
-  { 0x21000157, 0x1400ffff },
-  { 0x21000158, 0x24000001 },
-  { 0x21000159, 0x1400ffff },
-  { 0x2100015a, 0x24000001 },
-  { 0x2100015b, 0x1400ffff },
-  { 0x2100015c, 0x24000001 },
-  { 0x2100015d, 0x1400ffff },
-  { 0x2100015e, 0x24000001 },
-  { 0x2100015f, 0x1400ffff },
-  { 0x21000160, 0x24000001 },
-  { 0x21000161, 0x1400ffff },
-  { 0x21000162, 0x24000001 },
-  { 0x21000163, 0x1400ffff },
-  { 0x21000164, 0x24000001 },
-  { 0x21000165, 0x1400ffff },
-  { 0x21000166, 0x24000001 },
-  { 0x21000167, 0x1400ffff },
-  { 0x21000168, 0x24000001 },
-  { 0x21000169, 0x1400ffff },
-  { 0x2100016a, 0x24000001 },
-  { 0x2100016b, 0x1400ffff },
-  { 0x2100016c, 0x24000001 },
-  { 0x2100016d, 0x1400ffff },
-  { 0x2100016e, 0x24000001 },
-  { 0x2100016f, 0x1400ffff },
-  { 0x21000170, 0x24000001 },
-  { 0x21000171, 0x1400ffff },
-  { 0x21000172, 0x24000001 },
-  { 0x21000173, 0x1400ffff },
-  { 0x21000174, 0x24000001 },
-  { 0x21000175, 0x1400ffff },
-  { 0x21000176, 0x24000001 },
-  { 0x21000177, 0x1400ffff },
-  { 0x21000178, 0x2400ff87 },
-  { 0x21000179, 0x24000001 },
-  { 0x2100017a, 0x1400ffff },
-  { 0x2100017b, 0x24000001 },
-  { 0x2100017c, 0x1400ffff },
-  { 0x2100017d, 0x24000001 },
-  { 0x2100017e, 0x1400ffff },
-  { 0x2100017f, 0x1400fed4 },
-  { 0x21000180, 0x14000000 },
-  { 0x21000181, 0x240000d2 },
-  { 0x21000182, 0x24000001 },
-  { 0x21000183, 0x1400ffff },
-  { 0x21000184, 0x24000001 },
-  { 0x21000185, 0x1400ffff },
-  { 0x21000186, 0x240000ce },
-  { 0x21000187, 0x24000001 },
-  { 0x21000188, 0x1400ffff },
-  { 0x21000189, 0x240000cd },
-  { 0x2100018a, 0x240000cd },
-  { 0x2100018b, 0x24000001 },
-  { 0x2100018c, 0x1400ffff },
-  { 0x2100018d, 0x14000000 },
-  { 0x2100018e, 0x2400004f },
-  { 0x2100018f, 0x240000ca },
-  { 0x21000190, 0x240000cb },
-  { 0x21000191, 0x24000001 },
-  { 0x21000192, 0x1400ffff },
-  { 0x21000193, 0x240000cd },
-  { 0x21000194, 0x240000cf },
-  { 0x21000195, 0x14000061 },
-  { 0x21000196, 0x240000d3 },
-  { 0x21000197, 0x240000d1 },
-  { 0x21000198, 0x24000001 },
-  { 0x21000199, 0x1400ffff },
-  { 0x2100019a, 0x140000a3 },
-  { 0x2100019b, 0x14000000 },
-  { 0x2100019c, 0x240000d3 },
-  { 0x2100019d, 0x240000d5 },
-  { 0x2100019e, 0x14000082 },
-  { 0x2100019f, 0x240000d6 },
-  { 0x210001a0, 0x24000001 },
-  { 0x210001a1, 0x1400ffff },
-  { 0x210001a2, 0x24000001 },
-  { 0x210001a3, 0x1400ffff },
-  { 0x210001a4, 0x24000001 },
-  { 0x210001a5, 0x1400ffff },
-  { 0x210001a6, 0x240000da },
-  { 0x210001a7, 0x24000001 },
-  { 0x210001a8, 0x1400ffff },
-  { 0x210001a9, 0x240000da },
-  { 0x218001aa, 0x14000001 },
-  { 0x210001ac, 0x24000001 },
-  { 0x210001ad, 0x1400ffff },
-  { 0x210001ae, 0x240000da },
-  { 0x210001af, 0x24000001 },
-  { 0x210001b0, 0x1400ffff },
-  { 0x210001b1, 0x240000d9 },
-  { 0x210001b2, 0x240000d9 },
-  { 0x210001b3, 0x24000001 },
-  { 0x210001b4, 0x1400ffff },
-  { 0x210001b5, 0x24000001 },
-  { 0x210001b6, 0x1400ffff },
-  { 0x210001b7, 0x240000db },
-  { 0x210001b8, 0x24000001 },
-  { 0x210001b9, 0x1400ffff },
-  { 0x210001ba, 0x14000000 },
-  { 0x210001bb, 0x1c000000 },
-  { 0x210001bc, 0x24000001 },
-  { 0x210001bd, 0x1400ffff },
-  { 0x210001be, 0x14000000 },
-  { 0x210001bf, 0x14000038 },
-  { 0x218001c0, 0x1c000003 },
-  { 0x210001c4, 0x24000002 },
-  { 0x210001c5, 0x2000ffff },
-  { 0x210001c6, 0x1400fffe },
-  { 0x210001c7, 0x24000002 },
-  { 0x210001c8, 0x2000ffff },
-  { 0x210001c9, 0x1400fffe },
-  { 0x210001ca, 0x24000002 },
-  { 0x210001cb, 0x2000ffff },
-  { 0x210001cc, 0x1400fffe },
-  { 0x210001cd, 0x24000001 },
-  { 0x210001ce, 0x1400ffff },
-  { 0x210001cf, 0x24000001 },
-  { 0x210001d0, 0x1400ffff },
-  { 0x210001d1, 0x24000001 },
-  { 0x210001d2, 0x1400ffff },
-  { 0x210001d3, 0x24000001 },
-  { 0x210001d4, 0x1400ffff },
-  { 0x210001d5, 0x24000001 },
-  { 0x210001d6, 0x1400ffff },
-  { 0x210001d7, 0x24000001 },
-  { 0x210001d8, 0x1400ffff },
-  { 0x210001d9, 0x24000001 },
-  { 0x210001da, 0x1400ffff },
-  { 0x210001db, 0x24000001 },
-  { 0x210001dc, 0x1400ffff },
-  { 0x210001dd, 0x1400ffb1 },
-  { 0x210001de, 0x24000001 },
-  { 0x210001df, 0x1400ffff },
-  { 0x210001e0, 0x24000001 },
-  { 0x210001e1, 0x1400ffff },
-  { 0x210001e2, 0x24000001 },
-  { 0x210001e3, 0x1400ffff },
-  { 0x210001e4, 0x24000001 },
-  { 0x210001e5, 0x1400ffff },
-  { 0x210001e6, 0x24000001 },
-  { 0x210001e7, 0x1400ffff },
-  { 0x210001e8, 0x24000001 },
-  { 0x210001e9, 0x1400ffff },
-  { 0x210001ea, 0x24000001 },
-  { 0x210001eb, 0x1400ffff },
-  { 0x210001ec, 0x24000001 },
-  { 0x210001ed, 0x1400ffff },
-  { 0x210001ee, 0x24000001 },
-  { 0x210001ef, 0x1400ffff },
-  { 0x210001f0, 0x14000000 },
-  { 0x210001f1, 0x24000002 },
-  { 0x210001f2, 0x2000ffff },
-  { 0x210001f3, 0x1400fffe },
-  { 0x210001f4, 0x24000001 },
-  { 0x210001f5, 0x1400ffff },
-  { 0x210001f6, 0x2400ff9f },
-  { 0x210001f7, 0x2400ffc8 },
-  { 0x210001f8, 0x24000001 },
-  { 0x210001f9, 0x1400ffff },
-  { 0x210001fa, 0x24000001 },
-  { 0x210001fb, 0x1400ffff },
-  { 0x210001fc, 0x24000001 },
-  { 0x210001fd, 0x1400ffff },
-  { 0x210001fe, 0x24000001 },
-  { 0x210001ff, 0x1400ffff },
-  { 0x21000200, 0x24000001 },
-  { 0x21000201, 0x1400ffff },
-  { 0x21000202, 0x24000001 },
-  { 0x21000203, 0x1400ffff },
-  { 0x21000204, 0x24000001 },
-  { 0x21000205, 0x1400ffff },
-  { 0x21000206, 0x24000001 },
-  { 0x21000207, 0x1400ffff },
-  { 0x21000208, 0x24000001 },
-  { 0x21000209, 0x1400ffff },
-  { 0x2100020a, 0x24000001 },
-  { 0x2100020b, 0x1400ffff },
-  { 0x2100020c, 0x24000001 },
-  { 0x2100020d, 0x1400ffff },
-  { 0x2100020e, 0x24000001 },
-  { 0x2100020f, 0x1400ffff },
-  { 0x21000210, 0x24000001 },
-  { 0x21000211, 0x1400ffff },
-  { 0x21000212, 0x24000001 },
-  { 0x21000213, 0x1400ffff },
-  { 0x21000214, 0x24000001 },
-  { 0x21000215, 0x1400ffff },
-  { 0x21000216, 0x24000001 },
-  { 0x21000217, 0x1400ffff },
-  { 0x21000218, 0x24000001 },
-  { 0x21000219, 0x1400ffff },
-  { 0x2100021a, 0x24000001 },
-  { 0x2100021b, 0x1400ffff },
-  { 0x2100021c, 0x24000001 },
-  { 0x2100021d, 0x1400ffff },
-  { 0x2100021e, 0x24000001 },
-  { 0x2100021f, 0x1400ffff },
-  { 0x21000220, 0x2400ff7e },
-  { 0x21000221, 0x14000000 },
-  { 0x21000222, 0x24000001 },
-  { 0x21000223, 0x1400ffff },
-  { 0x21000224, 0x24000001 },
-  { 0x21000225, 0x1400ffff },
-  { 0x21000226, 0x24000001 },
-  { 0x21000227, 0x1400ffff },
-  { 0x21000228, 0x24000001 },
-  { 0x21000229, 0x1400ffff },
-  { 0x2100022a, 0x24000001 },
-  { 0x2100022b, 0x1400ffff },
-  { 0x2100022c, 0x24000001 },
-  { 0x2100022d, 0x1400ffff },
-  { 0x2100022e, 0x24000001 },
-  { 0x2100022f, 0x1400ffff },
-  { 0x21000230, 0x24000001 },
-  { 0x21000231, 0x1400ffff },
-  { 0x21000232, 0x24000001 },
-  { 0x21000233, 0x1400ffff },
-  { 0x21800234, 0x14000005 },
-  { 0x2100023a, 0x24000000 },
-  { 0x2100023b, 0x24000001 },
-  { 0x2100023c, 0x1400ffff },
-  { 0x2100023d, 0x2400ff5d },
-  { 0x2100023e, 0x24000000 },
-  { 0x2180023f, 0x14000001 },
-  { 0x21000241, 0x24000053 },
-  { 0x21800250, 0x14000002 },
-  { 0x21000253, 0x1400ff2e },
-  { 0x21000254, 0x1400ff32 },
-  { 0x21000255, 0x14000000 },
-  { 0x21000256, 0x1400ff33 },
-  { 0x21000257, 0x1400ff33 },
-  { 0x21000258, 0x14000000 },
-  { 0x21000259, 0x1400ff36 },
-  { 0x2100025a, 0x14000000 },
-  { 0x2100025b, 0x1400ff35 },
-  { 0x2180025c, 0x14000003 },
-  { 0x21000260, 0x1400ff33 },
-  { 0x21800261, 0x14000001 },
-  { 0x21000263, 0x1400ff31 },
-  { 0x21800264, 0x14000003 },
-  { 0x21000268, 0x1400ff2f },
-  { 0x21000269, 0x1400ff2d },
-  { 0x2180026a, 0x14000004 },
-  { 0x2100026f, 0x1400ff2d },
-  { 0x21800270, 0x14000001 },
-  { 0x21000272, 0x1400ff2b },
-  { 0x21800273, 0x14000001 },
-  { 0x21000275, 0x1400ff2a },
-  { 0x21800276, 0x14000009 },
-  { 0x21000280, 0x1400ff26 },
-  { 0x21800281, 0x14000001 },
-  { 0x21000283, 0x1400ff26 },
-  { 0x21800284, 0x14000003 },
-  { 0x21000288, 0x1400ff26 },
-  { 0x21000289, 0x14000000 },
-  { 0x2100028a, 0x1400ff27 },
-  { 0x2100028b, 0x1400ff27 },
-  { 0x2180028c, 0x14000005 },
-  { 0x21000292, 0x1400ff25 },
-  { 0x21000293, 0x14000000 },
-  { 0x21000294, 0x1400ffad },
-  { 0x21800295, 0x1400001a },
-  { 0x218002b0, 0x18000011 },
-  { 0x098002c2, 0x60000003 },
-  { 0x098002c6, 0x1800000b },
-  { 0x098002d2, 0x6000000d },
-  { 0x218002e0, 0x18000004 },
-  { 0x098002e5, 0x60000008 },
-  { 0x090002ee, 0x18000000 },
-  { 0x098002ef, 0x60000010 },
-  { 0x1b800300, 0x30000044 },
-  { 0x1b000345, 0x30000054 },
-  { 0x1b800346, 0x30000029 },
-  { 0x13800374, 0x60000001 },
-  { 0x1300037a, 0x18000000 },
-  { 0x0900037e, 0x54000000 },
-  { 0x13800384, 0x60000001 },
-  { 0x13000386, 0x24000026 },
-  { 0x09000387, 0x54000000 },
-  { 0x13000388, 0x24000025 },
-  { 0x13000389, 0x24000025 },
-  { 0x1300038a, 0x24000025 },
-  { 0x1300038c, 0x24000040 },
-  { 0x1300038e, 0x2400003f },
-  { 0x1300038f, 0x2400003f },
-  { 0x13000390, 0x14000000 },
-  { 0x13000391, 0x24000020 },
-  { 0x13000392, 0x24000020 },
-  { 0x13000393, 0x24000020 },
-  { 0x13000394, 0x24000020 },
-  { 0x13000395, 0x24000020 },
-  { 0x13000396, 0x24000020 },
-  { 0x13000397, 0x24000020 },
-  { 0x13000398, 0x24000020 },
-  { 0x13000399, 0x24000020 },
-  { 0x1300039a, 0x24000020 },
-  { 0x1300039b, 0x24000020 },
-  { 0x1300039c, 0x24000020 },
-  { 0x1300039d, 0x24000020 },
-  { 0x1300039e, 0x24000020 },
-  { 0x1300039f, 0x24000020 },
-  { 0x130003a0, 0x24000020 },
-  { 0x130003a1, 0x24000020 },
-  { 0x130003a3, 0x24000020 },
-  { 0x130003a4, 0x24000020 },
-  { 0x130003a5, 0x24000020 },
-  { 0x130003a6, 0x24000020 },
-  { 0x130003a7, 0x24000020 },
-  { 0x130003a8, 0x24000020 },
-  { 0x130003a9, 0x24000020 },
-  { 0x130003aa, 0x24000020 },
-  { 0x130003ab, 0x24000020 },
-  { 0x130003ac, 0x1400ffda },
-  { 0x130003ad, 0x1400ffdb },
-  { 0x130003ae, 0x1400ffdb },
-  { 0x130003af, 0x1400ffdb },
-  { 0x130003b0, 0x14000000 },
-  { 0x130003b1, 0x1400ffe0 },
-  { 0x130003b2, 0x1400ffe0 },
-  { 0x130003b3, 0x1400ffe0 },
-  { 0x130003b4, 0x1400ffe0 },
-  { 0x130003b5, 0x1400ffe0 },
-  { 0x130003b6, 0x1400ffe0 },
-  { 0x130003b7, 0x1400ffe0 },
-  { 0x130003b8, 0x1400ffe0 },
-  { 0x130003b9, 0x1400ffe0 },
-  { 0x130003ba, 0x1400ffe0 },
-  { 0x130003bb, 0x1400ffe0 },
-  { 0x130003bc, 0x1400ffe0 },
-  { 0x130003bd, 0x1400ffe0 },
-  { 0x130003be, 0x1400ffe0 },
-  { 0x130003bf, 0x1400ffe0 },
-  { 0x130003c0, 0x1400ffe0 },
-  { 0x130003c1, 0x1400ffe0 },
-  { 0x130003c2, 0x1400ffe1 },
-  { 0x130003c3, 0x1400ffe0 },
-  { 0x130003c4, 0x1400ffe0 },
-  { 0x130003c5, 0x1400ffe0 },
-  { 0x130003c6, 0x1400ffe0 },
-  { 0x130003c7, 0x1400ffe0 },
-  { 0x130003c8, 0x1400ffe0 },
-  { 0x130003c9, 0x1400ffe0 },
-  { 0x130003ca, 0x1400ffe0 },
-  { 0x130003cb, 0x1400ffe0 },
-  { 0x130003cc, 0x1400ffc0 },
-  { 0x130003cd, 0x1400ffc1 },
-  { 0x130003ce, 0x1400ffc1 },
-  { 0x130003d0, 0x1400ffc2 },
-  { 0x130003d1, 0x1400ffc7 },
-  { 0x138003d2, 0x24000002 },
-  { 0x130003d5, 0x1400ffd1 },
-  { 0x130003d6, 0x1400ffca },
-  { 0x130003d7, 0x14000000 },
-  { 0x130003d8, 0x24000001 },
-  { 0x130003d9, 0x1400ffff },
-  { 0x130003da, 0x24000001 },
-  { 0x130003db, 0x1400ffff },
-  { 0x130003dc, 0x24000001 },
-  { 0x130003dd, 0x1400ffff },
-  { 0x130003de, 0x24000001 },
-  { 0x130003df, 0x1400ffff },
-  { 0x130003e0, 0x24000001 },
-  { 0x130003e1, 0x1400ffff },
-  { 0x0a0003e2, 0x24000001 },
-  { 0x0a0003e3, 0x1400ffff },
-  { 0x0a0003e4, 0x24000001 },
-  { 0x0a0003e5, 0x1400ffff },
-  { 0x0a0003e6, 0x24000001 },
-  { 0x0a0003e7, 0x1400ffff },
-  { 0x0a0003e8, 0x24000001 },
-  { 0x0a0003e9, 0x1400ffff },
-  { 0x0a0003ea, 0x24000001 },
-  { 0x0a0003eb, 0x1400ffff },
-  { 0x0a0003ec, 0x24000001 },
-  { 0x0a0003ed, 0x1400ffff },
-  { 0x0a0003ee, 0x24000001 },
-  { 0x0a0003ef, 0x1400ffff },
-  { 0x130003f0, 0x1400ffaa },
-  { 0x130003f1, 0x1400ffb0 },
-  { 0x130003f2, 0x14000007 },
-  { 0x130003f3, 0x14000000 },
-  { 0x130003f4, 0x2400ffc4 },
-  { 0x130003f5, 0x1400ffa0 },
-  { 0x130003f6, 0x64000000 },
-  { 0x130003f7, 0x24000001 },
-  { 0x130003f8, 0x1400ffff },
-  { 0x130003f9, 0x2400fff9 },
-  { 0x130003fa, 0x24000001 },
-  { 0x130003fb, 0x1400ffff },
-  { 0x130003fc, 0x14000000 },
-  { 0x138003fd, 0x24000002 },
-  { 0x0c000400, 0x24000050 },
-  { 0x0c000401, 0x24000050 },
-  { 0x0c000402, 0x24000050 },
-  { 0x0c000403, 0x24000050 },
-  { 0x0c000404, 0x24000050 },
-  { 0x0c000405, 0x24000050 },
-  { 0x0c000406, 0x24000050 },
-  { 0x0c000407, 0x24000050 },
-  { 0x0c000408, 0x24000050 },
-  { 0x0c000409, 0x24000050 },
-  { 0x0c00040a, 0x24000050 },
-  { 0x0c00040b, 0x24000050 },
-  { 0x0c00040c, 0x24000050 },
-  { 0x0c00040d, 0x24000050 },
-  { 0x0c00040e, 0x24000050 },
-  { 0x0c00040f, 0x24000050 },
-  { 0x0c000410, 0x24000020 },
-  { 0x0c000411, 0x24000020 },
-  { 0x0c000412, 0x24000020 },
-  { 0x0c000413, 0x24000020 },
-  { 0x0c000414, 0x24000020 },
-  { 0x0c000415, 0x24000020 },
-  { 0x0c000416, 0x24000020 },
-  { 0x0c000417, 0x24000020 },
-  { 0x0c000418, 0x24000020 },
-  { 0x0c000419, 0x24000020 },
-  { 0x0c00041a, 0x24000020 },
-  { 0x0c00041b, 0x24000020 },
-  { 0x0c00041c, 0x24000020 },
-  { 0x0c00041d, 0x24000020 },
-  { 0x0c00041e, 0x24000020 },
-  { 0x0c00041f, 0x24000020 },
-  { 0x0c000420, 0x24000020 },
-  { 0x0c000421, 0x24000020 },
-  { 0x0c000422, 0x24000020 },
-  { 0x0c000423, 0x24000020 },
-  { 0x0c000424, 0x24000020 },
-  { 0x0c000425, 0x24000020 },
-  { 0x0c000426, 0x24000020 },
-  { 0x0c000427, 0x24000020 },
-  { 0x0c000428, 0x24000020 },
-  { 0x0c000429, 0x24000020 },
-  { 0x0c00042a, 0x24000020 },
-  { 0x0c00042b, 0x24000020 },
-  { 0x0c00042c, 0x24000020 },
-  { 0x0c00042d, 0x24000020 },
-  { 0x0c00042e, 0x24000020 },
-  { 0x0c00042f, 0x24000020 },
-  { 0x0c000430, 0x1400ffe0 },
-  { 0x0c000431, 0x1400ffe0 },
-  { 0x0c000432, 0x1400ffe0 },
-  { 0x0c000433, 0x1400ffe0 },
-  { 0x0c000434, 0x1400ffe0 },
-  { 0x0c000435, 0x1400ffe0 },
-  { 0x0c000436, 0x1400ffe0 },
-  { 0x0c000437, 0x1400ffe0 },
-  { 0x0c000438, 0x1400ffe0 },
-  { 0x0c000439, 0x1400ffe0 },
-  { 0x0c00043a, 0x1400ffe0 },
-  { 0x0c00043b, 0x1400ffe0 },
-  { 0x0c00043c, 0x1400ffe0 },
-  { 0x0c00043d, 0x1400ffe0 },
-  { 0x0c00043e, 0x1400ffe0 },
-  { 0x0c00043f, 0x1400ffe0 },
-  { 0x0c000440, 0x1400ffe0 },
-  { 0x0c000441, 0x1400ffe0 },
-  { 0x0c000442, 0x1400ffe0 },
-  { 0x0c000443, 0x1400ffe0 },
-  { 0x0c000444, 0x1400ffe0 },
-  { 0x0c000445, 0x1400ffe0 },
-  { 0x0c000446, 0x1400ffe0 },
-  { 0x0c000447, 0x1400ffe0 },
-  { 0x0c000448, 0x1400ffe0 },
-  { 0x0c000449, 0x1400ffe0 },
-  { 0x0c00044a, 0x1400ffe0 },
-  { 0x0c00044b, 0x1400ffe0 },
-  { 0x0c00044c, 0x1400ffe0 },
-  { 0x0c00044d, 0x1400ffe0 },
-  { 0x0c00044e, 0x1400ffe0 },
-  { 0x0c00044f, 0x1400ffe0 },
-  { 0x0c000450, 0x1400ffb0 },
-  { 0x0c000451, 0x1400ffb0 },
-  { 0x0c000452, 0x1400ffb0 },
-  { 0x0c000453, 0x1400ffb0 },
-  { 0x0c000454, 0x1400ffb0 },
-  { 0x0c000455, 0x1400ffb0 },
-  { 0x0c000456, 0x1400ffb0 },
-  { 0x0c000457, 0x1400ffb0 },
-  { 0x0c000458, 0x1400ffb0 },
-  { 0x0c000459, 0x1400ffb0 },
-  { 0x0c00045a, 0x1400ffb0 },
-  { 0x0c00045b, 0x1400ffb0 },
-  { 0x0c00045c, 0x1400ffb0 },
-  { 0x0c00045d, 0x1400ffb0 },
-  { 0x0c00045e, 0x1400ffb0 },
-  { 0x0c00045f, 0x1400ffb0 },
-  { 0x0c000460, 0x24000001 },
-  { 0x0c000461, 0x1400ffff },
-  { 0x0c000462, 0x24000001 },
-  { 0x0c000463, 0x1400ffff },
-  { 0x0c000464, 0x24000001 },
-  { 0x0c000465, 0x1400ffff },
-  { 0x0c000466, 0x24000001 },
-  { 0x0c000467, 0x1400ffff },
-  { 0x0c000468, 0x24000001 },
-  { 0x0c000469, 0x1400ffff },
-  { 0x0c00046a, 0x24000001 },
-  { 0x0c00046b, 0x1400ffff },
-  { 0x0c00046c, 0x24000001 },
-  { 0x0c00046d, 0x1400ffff },
-  { 0x0c00046e, 0x24000001 },
-  { 0x0c00046f, 0x1400ffff },
-  { 0x0c000470, 0x24000001 },
-  { 0x0c000471, 0x1400ffff },
-  { 0x0c000472, 0x24000001 },
-  { 0x0c000473, 0x1400ffff },
-  { 0x0c000474, 0x24000001 },
-  { 0x0c000475, 0x1400ffff },
-  { 0x0c000476, 0x24000001 },
-  { 0x0c000477, 0x1400ffff },
-  { 0x0c000478, 0x24000001 },
-  { 0x0c000479, 0x1400ffff },
-  { 0x0c00047a, 0x24000001 },
-  { 0x0c00047b, 0x1400ffff },
-  { 0x0c00047c, 0x24000001 },
-  { 0x0c00047d, 0x1400ffff },
-  { 0x0c00047e, 0x24000001 },
-  { 0x0c00047f, 0x1400ffff },
-  { 0x0c000480, 0x24000001 },
-  { 0x0c000481, 0x1400ffff },
-  { 0x0c000482, 0x68000000 },
-  { 0x0c800483, 0x30000003 },
-  { 0x0c800488, 0x2c000001 },
-  { 0x0c00048a, 0x24000001 },
-  { 0x0c00048b, 0x1400ffff },
-  { 0x0c00048c, 0x24000001 },
-  { 0x0c00048d, 0x1400ffff },
-  { 0x0c00048e, 0x24000001 },
-  { 0x0c00048f, 0x1400ffff },
-  { 0x0c000490, 0x24000001 },
-  { 0x0c000491, 0x1400ffff },
-  { 0x0c000492, 0x24000001 },
-  { 0x0c000493, 0x1400ffff },
-  { 0x0c000494, 0x24000001 },
-  { 0x0c000495, 0x1400ffff },
-  { 0x0c000496, 0x24000001 },
-  { 0x0c000497, 0x1400ffff },
-  { 0x0c000498, 0x24000001 },
-  { 0x0c000499, 0x1400ffff },
-  { 0x0c00049a, 0x24000001 },
-  { 0x0c00049b, 0x1400ffff },
-  { 0x0c00049c, 0x24000001 },
-  { 0x0c00049d, 0x1400ffff },
-  { 0x0c00049e, 0x24000001 },
-  { 0x0c00049f, 0x1400ffff },
-  { 0x0c0004a0, 0x24000001 },
-  { 0x0c0004a1, 0x1400ffff },
-  { 0x0c0004a2, 0x24000001 },
-  { 0x0c0004a3, 0x1400ffff },
-  { 0x0c0004a4, 0x24000001 },
-  { 0x0c0004a5, 0x1400ffff },
-  { 0x0c0004a6, 0x24000001 },
-  { 0x0c0004a7, 0x1400ffff },
-  { 0x0c0004a8, 0x24000001 },
-  { 0x0c0004a9, 0x1400ffff },
-  { 0x0c0004aa, 0x24000001 },
-  { 0x0c0004ab, 0x1400ffff },
-  { 0x0c0004ac, 0x24000001 },
-  { 0x0c0004ad, 0x1400ffff },
-  { 0x0c0004ae, 0x24000001 },
-  { 0x0c0004af, 0x1400ffff },
-  { 0x0c0004b0, 0x24000001 },
-  { 0x0c0004b1, 0x1400ffff },
-  { 0x0c0004b2, 0x24000001 },
-  { 0x0c0004b3, 0x1400ffff },
-  { 0x0c0004b4, 0x24000001 },
-  { 0x0c0004b5, 0x1400ffff },
-  { 0x0c0004b6, 0x24000001 },
-  { 0x0c0004b7, 0x1400ffff },
-  { 0x0c0004b8, 0x24000001 },
-  { 0x0c0004b9, 0x1400ffff },
-  { 0x0c0004ba, 0x24000001 },
-  { 0x0c0004bb, 0x1400ffff },
-  { 0x0c0004bc, 0x24000001 },
-  { 0x0c0004bd, 0x1400ffff },
-  { 0x0c0004be, 0x24000001 },
-  { 0x0c0004bf, 0x1400ffff },
-  { 0x0c0004c0, 0x24000000 },
-  { 0x0c0004c1, 0x24000001 },
-  { 0x0c0004c2, 0x1400ffff },
-  { 0x0c0004c3, 0x24000001 },
-  { 0x0c0004c4, 0x1400ffff },
-  { 0x0c0004c5, 0x24000001 },
-  { 0x0c0004c6, 0x1400ffff },
-  { 0x0c0004c7, 0x24000001 },
-  { 0x0c0004c8, 0x1400ffff },
-  { 0x0c0004c9, 0x24000001 },
-  { 0x0c0004ca, 0x1400ffff },
-  { 0x0c0004cb, 0x24000001 },
-  { 0x0c0004cc, 0x1400ffff },
-  { 0x0c0004cd, 0x24000001 },
-  { 0x0c0004ce, 0x1400ffff },
-  { 0x0c0004d0, 0x24000001 },
-  { 0x0c0004d1, 0x1400ffff },
-  { 0x0c0004d2, 0x24000001 },
-  { 0x0c0004d3, 0x1400ffff },
-  { 0x0c0004d4, 0x24000001 },
-  { 0x0c0004d5, 0x1400ffff },
-  { 0x0c0004d6, 0x24000001 },
-  { 0x0c0004d7, 0x1400ffff },
-  { 0x0c0004d8, 0x24000001 },
-  { 0x0c0004d9, 0x1400ffff },
-  { 0x0c0004da, 0x24000001 },
-  { 0x0c0004db, 0x1400ffff },
-  { 0x0c0004dc, 0x24000001 },
-  { 0x0c0004dd, 0x1400ffff },
-  { 0x0c0004de, 0x24000001 },
-  { 0x0c0004df, 0x1400ffff },
-  { 0x0c0004e0, 0x24000001 },
-  { 0x0c0004e1, 0x1400ffff },
-  { 0x0c0004e2, 0x24000001 },
-  { 0x0c0004e3, 0x1400ffff },
-  { 0x0c0004e4, 0x24000001 },
-  { 0x0c0004e5, 0x1400ffff },
-  { 0x0c0004e6, 0x24000001 },
-  { 0x0c0004e7, 0x1400ffff },
-  { 0x0c0004e8, 0x24000001 },
-  { 0x0c0004e9, 0x1400ffff },
-  { 0x0c0004ea, 0x24000001 },
-  { 0x0c0004eb, 0x1400ffff },
-  { 0x0c0004ec, 0x24000001 },
-  { 0x0c0004ed, 0x1400ffff },
-  { 0x0c0004ee, 0x24000001 },
-  { 0x0c0004ef, 0x1400ffff },
-  { 0x0c0004f0, 0x24000001 },
-  { 0x0c0004f1, 0x1400ffff },
-  { 0x0c0004f2, 0x24000001 },
-  { 0x0c0004f3, 0x1400ffff },
-  { 0x0c0004f4, 0x24000001 },
-  { 0x0c0004f5, 0x1400ffff },
-  { 0x0c0004f6, 0x24000001 },
-  { 0x0c0004f7, 0x1400ffff },
-  { 0x0c0004f8, 0x24000001 },
-  { 0x0c0004f9, 0x1400ffff },
-  { 0x0c000500, 0x24000001 },
-  { 0x0c000501, 0x1400ffff },
-  { 0x0c000502, 0x24000001 },
-  { 0x0c000503, 0x1400ffff },
-  { 0x0c000504, 0x24000001 },
-  { 0x0c000505, 0x1400ffff },
-  { 0x0c000506, 0x24000001 },
-  { 0x0c000507, 0x1400ffff },
-  { 0x0c000508, 0x24000001 },
-  { 0x0c000509, 0x1400ffff },
-  { 0x0c00050a, 0x24000001 },
-  { 0x0c00050b, 0x1400ffff },
-  { 0x0c00050c, 0x24000001 },
-  { 0x0c00050d, 0x1400ffff },
-  { 0x0c00050e, 0x24000001 },
-  { 0x0c00050f, 0x1400ffff },
-  { 0x01000531, 0x24000030 },
-  { 0x01000532, 0x24000030 },
-  { 0x01000533, 0x24000030 },
-  { 0x01000534, 0x24000030 },
-  { 0x01000535, 0x24000030 },
-  { 0x01000536, 0x24000030 },
-  { 0x01000537, 0x24000030 },
-  { 0x01000538, 0x24000030 },
-  { 0x01000539, 0x24000030 },
-  { 0x0100053a, 0x24000030 },
-  { 0x0100053b, 0x24000030 },
-  { 0x0100053c, 0x24000030 },
-  { 0x0100053d, 0x24000030 },
-  { 0x0100053e, 0x24000030 },
-  { 0x0100053f, 0x24000030 },
-  { 0x01000540, 0x24000030 },
-  { 0x01000541, 0x24000030 },
-  { 0x01000542, 0x24000030 },
-  { 0x01000543, 0x24000030 },
-  { 0x01000544, 0x24000030 },
-  { 0x01000545, 0x24000030 },
-  { 0x01000546, 0x24000030 },
-  { 0x01000547, 0x24000030 },
-  { 0x01000548, 0x24000030 },
-  { 0x01000549, 0x24000030 },
-  { 0x0100054a, 0x24000030 },
-  { 0x0100054b, 0x24000030 },
-  { 0x0100054c, 0x24000030 },
-  { 0x0100054d, 0x24000030 },
-  { 0x0100054e, 0x24000030 },
-  { 0x0100054f, 0x24000030 },
-  { 0x01000550, 0x24000030 },
-  { 0x01000551, 0x24000030 },
-  { 0x01000552, 0x24000030 },
-  { 0x01000553, 0x24000030 },
-  { 0x01000554, 0x24000030 },
-  { 0x01000555, 0x24000030 },
-  { 0x01000556, 0x24000030 },
-  { 0x01000559, 0x18000000 },
-  { 0x0180055a, 0x54000005 },
-  { 0x01000561, 0x1400ffd0 },
-  { 0x01000562, 0x1400ffd0 },
-  { 0x01000563, 0x1400ffd0 },
-  { 0x01000564, 0x1400ffd0 },
-  { 0x01000565, 0x1400ffd0 },
-  { 0x01000566, 0x1400ffd0 },
-  { 0x01000567, 0x1400ffd0 },
-  { 0x01000568, 0x1400ffd0 },
-  { 0x01000569, 0x1400ffd0 },
-  { 0x0100056a, 0x1400ffd0 },
-  { 0x0100056b, 0x1400ffd0 },
-  { 0x0100056c, 0x1400ffd0 },
-  { 0x0100056d, 0x1400ffd0 },
-  { 0x0100056e, 0x1400ffd0 },
-  { 0x0100056f, 0x1400ffd0 },
-  { 0x01000570, 0x1400ffd0 },
-  { 0x01000571, 0x1400ffd0 },
-  { 0x01000572, 0x1400ffd0 },
-  { 0x01000573, 0x1400ffd0 },
-  { 0x01000574, 0x1400ffd0 },
-  { 0x01000575, 0x1400ffd0 },
-  { 0x01000576, 0x1400ffd0 },
-  { 0x01000577, 0x1400ffd0 },
-  { 0x01000578, 0x1400ffd0 },
-  { 0x01000579, 0x1400ffd0 },
-  { 0x0100057a, 0x1400ffd0 },
-  { 0x0100057b, 0x1400ffd0 },
-  { 0x0100057c, 0x1400ffd0 },
-  { 0x0100057d, 0x1400ffd0 },
-  { 0x0100057e, 0x1400ffd0 },
-  { 0x0100057f, 0x1400ffd0 },
-  { 0x01000580, 0x1400ffd0 },
-  { 0x01000581, 0x1400ffd0 },
-  { 0x01000582, 0x1400ffd0 },
-  { 0x01000583, 0x1400ffd0 },
-  { 0x01000584, 0x1400ffd0 },
-  { 0x01000585, 0x1400ffd0 },
-  { 0x01000586, 0x1400ffd0 },
-  { 0x01000587, 0x14000000 },
-  { 0x09000589, 0x54000000 },
-  { 0x0100058a, 0x44000000 },
-  { 0x19800591, 0x30000028 },
-  { 0x198005bb, 0x30000002 },
-  { 0x190005be, 0x54000000 },
-  { 0x190005bf, 0x30000000 },
-  { 0x190005c0, 0x54000000 },
-  { 0x198005c1, 0x30000001 },
-  { 0x190005c3, 0x54000000 },
-  { 0x198005c4, 0x30000001 },
-  { 0x190005c6, 0x54000000 },
-  { 0x190005c7, 0x30000000 },
-  { 0x198005d0, 0x1c00001a },
-  { 0x198005f0, 0x1c000002 },
-  { 0x198005f3, 0x54000001 },
-  { 0x09800600, 0x04000003 },
-  { 0x0000060b, 0x5c000000 },
-  { 0x0980060c, 0x54000001 },
-  { 0x0080060e, 0x68000001 },
-  { 0x00800610, 0x30000005 },
-  { 0x0900061b, 0x54000000 },
-  { 0x0080061e, 0x54000001 },
-  { 0x00800621, 0x1c000019 },
-  { 0x09000640, 0x18000000 },
-  { 0x00800641, 0x1c000009 },
-  { 0x1b80064b, 0x30000013 },
-  { 0x09800660, 0x34000009 },
-  { 0x0080066a, 0x54000003 },
-  { 0x0080066e, 0x1c000001 },
-  { 0x1b000670, 0x30000000 },
-  { 0x00800671, 0x1c000062 },
-  { 0x000006d4, 0x54000000 },
-  { 0x000006d5, 0x1c000000 },
-  { 0x008006d6, 0x30000006 },
-  { 0x090006dd, 0x04000000 },
-  { 0x000006de, 0x2c000000 },
-  { 0x008006df, 0x30000005 },
-  { 0x008006e5, 0x18000001 },
-  { 0x008006e7, 0x30000001 },
-  { 0x000006e9, 0x68000000 },
-  { 0x008006ea, 0x30000003 },
-  { 0x008006ee, 0x1c000001 },
-  { 0x008006f0, 0x34000009 },
-  { 0x008006fa, 0x1c000002 },
-  { 0x008006fd, 0x68000001 },
-  { 0x000006ff, 0x1c000000 },
-  { 0x31800700, 0x5400000d },
-  { 0x3100070f, 0x04000000 },
-  { 0x31000710, 0x1c000000 },
-  { 0x31000711, 0x30000000 },
-  { 0x31800712, 0x1c00001d },
-  { 0x31800730, 0x3000001a },
-  { 0x3180074d, 0x1c000020 },
-  { 0x37800780, 0x1c000025 },
-  { 0x378007a6, 0x3000000a },
-  { 0x370007b1, 0x1c000000 },
-  { 0x0e800901, 0x30000001 },
-  { 0x0e000903, 0x28000000 },
-  { 0x0e800904, 0x1c000035 },
-  { 0x0e00093c, 0x30000000 },
-  { 0x0e00093d, 0x1c000000 },
-  { 0x0e80093e, 0x28000002 },
-  { 0x0e800941, 0x30000007 },
-  { 0x0e800949, 0x28000003 },
-  { 0x0e00094d, 0x30000000 },
-  { 0x0e000950, 0x1c000000 },
-  { 0x0e800951, 0x30000003 },
-  { 0x0e800958, 0x1c000009 },
-  { 0x0e800962, 0x30000001 },
-  { 0x09800964, 0x54000001 },
-  { 0x0e800966, 0x34000009 },
-  { 0x09000970, 0x54000000 },
-  { 0x0e00097d, 0x1c000000 },
-  { 0x02000981, 0x30000000 },
-  { 0x02800982, 0x28000001 },
-  { 0x02800985, 0x1c000007 },
-  { 0x0280098f, 0x1c000001 },
-  { 0x02800993, 0x1c000015 },
-  { 0x028009aa, 0x1c000006 },
-  { 0x020009b2, 0x1c000000 },
-  { 0x028009b6, 0x1c000003 },
-  { 0x020009bc, 0x30000000 },
-  { 0x020009bd, 0x1c000000 },
-  { 0x028009be, 0x28000002 },
-  { 0x028009c1, 0x30000003 },
-  { 0x028009c7, 0x28000001 },
-  { 0x028009cb, 0x28000001 },
-  { 0x020009cd, 0x30000000 },
-  { 0x020009ce, 0x1c000000 },
-  { 0x020009d7, 0x28000000 },
-  { 0x028009dc, 0x1c000001 },
-  { 0x028009df, 0x1c000002 },
-  { 0x028009e2, 0x30000001 },
-  { 0x028009e6, 0x34000009 },
-  { 0x028009f0, 0x1c000001 },
-  { 0x028009f2, 0x5c000001 },
-  { 0x028009f4, 0x3c000005 },
-  { 0x020009fa, 0x68000000 },
-  { 0x15800a01, 0x30000001 },
-  { 0x15000a03, 0x28000000 },
-  { 0x15800a05, 0x1c000005 },
-  { 0x15800a0f, 0x1c000001 },
-  { 0x15800a13, 0x1c000015 },
-  { 0x15800a2a, 0x1c000006 },
-  { 0x15800a32, 0x1c000001 },
-  { 0x15800a35, 0x1c000001 },
-  { 0x15800a38, 0x1c000001 },
-  { 0x15000a3c, 0x30000000 },
-  { 0x15800a3e, 0x28000002 },
-  { 0x15800a41, 0x30000001 },
-  { 0x15800a47, 0x30000001 },
-  { 0x15800a4b, 0x30000002 },
-  { 0x15800a59, 0x1c000003 },
-  { 0x15000a5e, 0x1c000000 },
-  { 0x15800a66, 0x34000009 },
-  { 0x15800a70, 0x30000001 },
-  { 0x15800a72, 0x1c000002 },
-  { 0x14800a81, 0x30000001 },
-  { 0x14000a83, 0x28000000 },
-  { 0x14800a85, 0x1c000008 },
-  { 0x14800a8f, 0x1c000002 },
-  { 0x14800a93, 0x1c000015 },
-  { 0x14800aaa, 0x1c000006 },
-  { 0x14800ab2, 0x1c000001 },
-  { 0x14800ab5, 0x1c000004 },
-  { 0x14000abc, 0x30000000 },
-  { 0x14000abd, 0x1c000000 },
-  { 0x14800abe, 0x28000002 },
-  { 0x14800ac1, 0x30000004 },
-  { 0x14800ac7, 0x30000001 },
-  { 0x14000ac9, 0x28000000 },
-  { 0x14800acb, 0x28000001 },
-  { 0x14000acd, 0x30000000 },
-  { 0x14000ad0, 0x1c000000 },
-  { 0x14800ae0, 0x1c000001 },
-  { 0x14800ae2, 0x30000001 },
-  { 0x14800ae6, 0x34000009 },
-  { 0x14000af1, 0x5c000000 },
-  { 0x2b000b01, 0x30000000 },
-  { 0x2b800b02, 0x28000001 },
-  { 0x2b800b05, 0x1c000007 },
-  { 0x2b800b0f, 0x1c000001 },
-  { 0x2b800b13, 0x1c000015 },
-  { 0x2b800b2a, 0x1c000006 },
-  { 0x2b800b32, 0x1c000001 },
-  { 0x2b800b35, 0x1c000004 },
-  { 0x2b000b3c, 0x30000000 },
-  { 0x2b000b3d, 0x1c000000 },
-  { 0x2b000b3e, 0x28000000 },
-  { 0x2b000b3f, 0x30000000 },
-  { 0x2b000b40, 0x28000000 },
-  { 0x2b800b41, 0x30000002 },
-  { 0x2b800b47, 0x28000001 },
-  { 0x2b800b4b, 0x28000001 },
-  { 0x2b000b4d, 0x30000000 },
-  { 0x2b000b56, 0x30000000 },
-  { 0x2b000b57, 0x28000000 },
-  { 0x2b800b5c, 0x1c000001 },
-  { 0x2b800b5f, 0x1c000002 },
-  { 0x2b800b66, 0x34000009 },
-  { 0x2b000b70, 0x68000000 },
-  { 0x2b000b71, 0x1c000000 },
-  { 0x35000b82, 0x30000000 },
-  { 0x35000b83, 0x1c000000 },
-  { 0x35800b85, 0x1c000005 },
-  { 0x35800b8e, 0x1c000002 },
-  { 0x35800b92, 0x1c000003 },
-  { 0x35800b99, 0x1c000001 },
-  { 0x35000b9c, 0x1c000000 },
-  { 0x35800b9e, 0x1c000001 },
-  { 0x35800ba3, 0x1c000001 },
-  { 0x35800ba8, 0x1c000002 },
-  { 0x35800bae, 0x1c00000b },
-  { 0x35800bbe, 0x28000001 },
-  { 0x35000bc0, 0x30000000 },
-  { 0x35800bc1, 0x28000001 },
-  { 0x35800bc6, 0x28000002 },
-  { 0x35800bca, 0x28000002 },
-  { 0x35000bcd, 0x30000000 },
-  { 0x35000bd7, 0x28000000 },
-  { 0x35800be6, 0x34000009 },
-  { 0x35800bf0, 0x3c000002 },
-  { 0x35800bf3, 0x68000005 },
-  { 0x35000bf9, 0x5c000000 },
-  { 0x35000bfa, 0x68000000 },
-  { 0x36800c01, 0x28000002 },
-  { 0x36800c05, 0x1c000007 },
-  { 0x36800c0e, 0x1c000002 },
-  { 0x36800c12, 0x1c000016 },
-  { 0x36800c2a, 0x1c000009 },
-  { 0x36800c35, 0x1c000004 },
-  { 0x36800c3e, 0x30000002 },
-  { 0x36800c41, 0x28000003 },
-  { 0x36800c46, 0x30000002 },
-  { 0x36800c4a, 0x30000003 },
-  { 0x36800c55, 0x30000001 },
-  { 0x36800c60, 0x1c000001 },
-  { 0x36800c66, 0x34000009 },
-  { 0x1c800c82, 0x28000001 },
-  { 0x1c800c85, 0x1c000007 },
-  { 0x1c800c8e, 0x1c000002 },
-  { 0x1c800c92, 0x1c000016 },
-  { 0x1c800caa, 0x1c000009 },
-  { 0x1c800cb5, 0x1c000004 },
-  { 0x1c000cbc, 0x30000000 },
-  { 0x1c000cbd, 0x1c000000 },
-  { 0x1c000cbe, 0x28000000 },
-  { 0x1c000cbf, 0x30000000 },
-  { 0x1c800cc0, 0x28000004 },
-  { 0x1c000cc6, 0x30000000 },
-  { 0x1c800cc7, 0x28000001 },
-  { 0x1c800cca, 0x28000001 },
-  { 0x1c800ccc, 0x30000001 },
-  { 0x1c800cd5, 0x28000001 },
-  { 0x1c000cde, 0x1c000000 },
-  { 0x1c800ce0, 0x1c000001 },
-  { 0x1c800ce6, 0x34000009 },
-  { 0x24800d02, 0x28000001 },
-  { 0x24800d05, 0x1c000007 },
-  { 0x24800d0e, 0x1c000002 },
-  { 0x24800d12, 0x1c000016 },
-  { 0x24800d2a, 0x1c00000f },
-  { 0x24800d3e, 0x28000002 },
-  { 0x24800d41, 0x30000002 },
-  { 0x24800d46, 0x28000002 },
-  { 0x24800d4a, 0x28000002 },
-  { 0x24000d4d, 0x30000000 },
-  { 0x24000d57, 0x28000000 },
-  { 0x24800d60, 0x1c000001 },
-  { 0x24800d66, 0x34000009 },
-  { 0x2f800d82, 0x28000001 },
-  { 0x2f800d85, 0x1c000011 },
-  { 0x2f800d9a, 0x1c000017 },
-  { 0x2f800db3, 0x1c000008 },
-  { 0x2f000dbd, 0x1c000000 },
-  { 0x2f800dc0, 0x1c000006 },
-  { 0x2f000dca, 0x30000000 },
-  { 0x2f800dcf, 0x28000002 },
-  { 0x2f800dd2, 0x30000002 },
-  { 0x2f000dd6, 0x30000000 },
-  { 0x2f800dd8, 0x28000007 },
-  { 0x2f800df2, 0x28000001 },
-  { 0x2f000df4, 0x54000000 },
-  { 0x38800e01, 0x1c00002f },
-  { 0x38000e31, 0x30000000 },
-  { 0x38800e32, 0x1c000001 },
-  { 0x38800e34, 0x30000006 },
-  { 0x09000e3f, 0x5c000000 },
-  { 0x38800e40, 0x1c000005 },
-  { 0x38000e46, 0x18000000 },
-  { 0x38800e47, 0x30000007 },
-  { 0x38000e4f, 0x54000000 },
-  { 0x38800e50, 0x34000009 },
-  { 0x38800e5a, 0x54000001 },
-  { 0x20800e81, 0x1c000001 },
-  { 0x20000e84, 0x1c000000 },
-  { 0x20800e87, 0x1c000001 },
-  { 0x20000e8a, 0x1c000000 },
-  { 0x20000e8d, 0x1c000000 },
-  { 0x20800e94, 0x1c000003 },
-  { 0x20800e99, 0x1c000006 },
-  { 0x20800ea1, 0x1c000002 },
-  { 0x20000ea5, 0x1c000000 },
-  { 0x20000ea7, 0x1c000000 },
-  { 0x20800eaa, 0x1c000001 },
-  { 0x20800ead, 0x1c000003 },
-  { 0x20000eb1, 0x30000000 },
-  { 0x20800eb2, 0x1c000001 },
-  { 0x20800eb4, 0x30000005 },
-  { 0x20800ebb, 0x30000001 },
-  { 0x20000ebd, 0x1c000000 },
-  { 0x20800ec0, 0x1c000004 },
-  { 0x20000ec6, 0x18000000 },
-  { 0x20800ec8, 0x30000005 },
-  { 0x20800ed0, 0x34000009 },
-  { 0x20800edc, 0x1c000001 },
-  { 0x39000f00, 0x1c000000 },
-  { 0x39800f01, 0x68000002 },
-  { 0x39800f04, 0x5400000e },
-  { 0x39800f13, 0x68000004 },
-  { 0x39800f18, 0x30000001 },
-  { 0x39800f1a, 0x68000005 },
-  { 0x39800f20, 0x34000009 },
-  { 0x39800f2a, 0x3c000009 },
-  { 0x39000f34, 0x68000000 },
-  { 0x39000f35, 0x30000000 },
-  { 0x39000f36, 0x68000000 },
-  { 0x39000f37, 0x30000000 },
-  { 0x39000f38, 0x68000000 },
-  { 0x39000f39, 0x30000000 },
-  { 0x39000f3a, 0x58000000 },
-  { 0x39000f3b, 0x48000000 },
-  { 0x39000f3c, 0x58000000 },
-  { 0x39000f3d, 0x48000000 },
-  { 0x39800f3e, 0x28000001 },
-  { 0x39800f40, 0x1c000007 },
-  { 0x39800f49, 0x1c000021 },
-  { 0x39800f71, 0x3000000d },
-  { 0x39000f7f, 0x28000000 },
-  { 0x39800f80, 0x30000004 },
-  { 0x39000f85, 0x54000000 },
-  { 0x39800f86, 0x30000001 },
-  { 0x39800f88, 0x1c000003 },
-  { 0x39800f90, 0x30000007 },
-  { 0x39800f99, 0x30000023 },
-  { 0x39800fbe, 0x68000007 },
-  { 0x39000fc6, 0x30000000 },
-  { 0x39800fc7, 0x68000005 },
-  { 0x39000fcf, 0x68000000 },
-  { 0x39800fd0, 0x54000001 },
-  { 0x26801000, 0x1c000021 },
-  { 0x26801023, 0x1c000004 },
-  { 0x26801029, 0x1c000001 },
-  { 0x2600102c, 0x28000000 },
-  { 0x2680102d, 0x30000003 },
-  { 0x26001031, 0x28000000 },
-  { 0x26001032, 0x30000000 },
-  { 0x26801036, 0x30000001 },
-  { 0x26001038, 0x28000000 },
-  { 0x26001039, 0x30000000 },
-  { 0x26801040, 0x34000009 },
-  { 0x2680104a, 0x54000005 },
-  { 0x26801050, 0x1c000005 },
-  { 0x26801056, 0x28000001 },
-  { 0x26801058, 0x30000001 },
-  { 0x100010a0, 0x24001c60 },
-  { 0x100010a1, 0x24001c60 },
-  { 0x100010a2, 0x24001c60 },
-  { 0x100010a3, 0x24001c60 },
-  { 0x100010a4, 0x24001c60 },
-  { 0x100010a5, 0x24001c60 },
-  { 0x100010a6, 0x24001c60 },
-  { 0x100010a7, 0x24001c60 },
-  { 0x100010a8, 0x24001c60 },
-  { 0x100010a9, 0x24001c60 },
-  { 0x100010aa, 0x24001c60 },
-  { 0x100010ab, 0x24001c60 },
-  { 0x100010ac, 0x24001c60 },
-  { 0x100010ad, 0x24001c60 },
-  { 0x100010ae, 0x24001c60 },
-  { 0x100010af, 0x24001c60 },
-  { 0x100010b0, 0x24001c60 },
-  { 0x100010b1, 0x24001c60 },
-  { 0x100010b2, 0x24001c60 },
-  { 0x100010b3, 0x24001c60 },
-  { 0x100010b4, 0x24001c60 },
-  { 0x100010b5, 0x24001c60 },
-  { 0x100010b6, 0x24001c60 },
-  { 0x100010b7, 0x24001c60 },
-  { 0x100010b8, 0x24001c60 },
-  { 0x100010b9, 0x24001c60 },
-  { 0x100010ba, 0x24001c60 },
-  { 0x100010bb, 0x24001c60 },
-  { 0x100010bc, 0x24001c60 },
-  { 0x100010bd, 0x24001c60 },
-  { 0x100010be, 0x24001c60 },
-  { 0x100010bf, 0x24001c60 },
-  { 0x100010c0, 0x24001c60 },
-  { 0x100010c1, 0x24001c60 },
-  { 0x100010c2, 0x24001c60 },
-  { 0x100010c3, 0x24001c60 },
-  { 0x100010c4, 0x24001c60 },
-  { 0x100010c5, 0x24001c60 },
-  { 0x108010d0, 0x1c00002a },
-  { 0x090010fb, 0x54000000 },
-  { 0x100010fc, 0x18000000 },
-  { 0x17801100, 0x1c000059 },
-  { 0x1780115f, 0x1c000043 },
-  { 0x178011a8, 0x1c000051 },
-  { 0x0f801200, 0x1c000048 },
-  { 0x0f80124a, 0x1c000003 },
-  { 0x0f801250, 0x1c000006 },
-  { 0x0f001258, 0x1c000000 },
-  { 0x0f80125a, 0x1c000003 },
-  { 0x0f801260, 0x1c000028 },
-  { 0x0f80128a, 0x1c000003 },
-  { 0x0f801290, 0x1c000020 },
-  { 0x0f8012b2, 0x1c000003 },
-  { 0x0f8012b8, 0x1c000006 },
-  { 0x0f0012c0, 0x1c000000 },
-  { 0x0f8012c2, 0x1c000003 },
-  { 0x0f8012c8, 0x1c00000e },
-  { 0x0f8012d8, 0x1c000038 },
-  { 0x0f801312, 0x1c000003 },
-  { 0x0f801318, 0x1c000042 },
-  { 0x0f00135f, 0x30000000 },
-  { 0x0f001360, 0x68000000 },
-  { 0x0f801361, 0x54000007 },
-  { 0x0f801369, 0x3c000013 },
-  { 0x0f801380, 0x1c00000f },
-  { 0x0f801390, 0x68000009 },
-  { 0x088013a0, 0x1c000054 },
-  { 0x07801401, 0x1c00026b },
-  { 0x0780166d, 0x54000001 },
-  { 0x0780166f, 0x1c000007 },
-  { 0x28001680, 0x74000000 },
-  { 0x28801681, 0x1c000019 },
-  { 0x2800169b, 0x58000000 },
-  { 0x2800169c, 0x48000000 },
-  { 0x2d8016a0, 0x1c00004a },
-  { 0x098016eb, 0x54000002 },
-  { 0x2d8016ee, 0x38000002 },
-  { 0x32801700, 0x1c00000c },
-  { 0x3280170e, 0x1c000003 },
-  { 0x32801712, 0x30000002 },
-  { 0x18801720, 0x1c000011 },
-  { 0x18801732, 0x30000002 },
-  { 0x09801735, 0x54000001 },
-  { 0x06801740, 0x1c000011 },
-  { 0x06801752, 0x30000001 },
-  { 0x33801760, 0x1c00000c },
-  { 0x3380176e, 0x1c000002 },
-  { 0x33801772, 0x30000001 },
-  { 0x1f801780, 0x1c000033 },
-  { 0x1f8017b4, 0x04000001 },
-  { 0x1f0017b6, 0x28000000 },
-  { 0x1f8017b7, 0x30000006 },
-  { 0x1f8017be, 0x28000007 },
-  { 0x1f0017c6, 0x30000000 },
-  { 0x1f8017c7, 0x28000001 },
-  { 0x1f8017c9, 0x3000000a },
-  { 0x1f8017d4, 0x54000002 },
-  { 0x1f0017d7, 0x18000000 },
-  { 0x1f8017d8, 0x54000002 },
-  { 0x1f0017db, 0x5c000000 },
-  { 0x1f0017dc, 0x1c000000 },
-  { 0x1f0017dd, 0x30000000 },
-  { 0x1f8017e0, 0x34000009 },
-  { 0x1f8017f0, 0x3c000009 },
-  { 0x25801800, 0x54000005 },
-  { 0x25001806, 0x44000000 },
-  { 0x25801807, 0x54000003 },
-  { 0x2580180b, 0x30000002 },
-  { 0x2500180e, 0x74000000 },
-  { 0x25801810, 0x34000009 },
-  { 0x25801820, 0x1c000022 },
-  { 0x25001843, 0x18000000 },
-  { 0x25801844, 0x1c000033 },
-  { 0x25801880, 0x1c000028 },
-  { 0x250018a9, 0x30000000 },
-  { 0x22801900, 0x1c00001c },
-  { 0x22801920, 0x30000002 },
-  { 0x22801923, 0x28000003 },
-  { 0x22801927, 0x30000001 },
-  { 0x22801929, 0x28000002 },
-  { 0x22801930, 0x28000001 },
-  { 0x22001932, 0x30000000 },
-  { 0x22801933, 0x28000005 },
-  { 0x22801939, 0x30000002 },
-  { 0x22001940, 0x68000000 },
-  { 0x22801944, 0x54000001 },
-  { 0x22801946, 0x34000009 },
-  { 0x34801950, 0x1c00001d },
-  { 0x34801970, 0x1c000004 },
-  { 0x27801980, 0x1c000029 },
-  { 0x278019b0, 0x28000010 },
-  { 0x278019c1, 0x1c000006 },
-  { 0x278019c8, 0x28000001 },
-  { 0x278019d0, 0x34000009 },
-  { 0x278019de, 0x54000001 },
-  { 0x1f8019e0, 0x6800001f },
-  { 0x05801a00, 0x1c000016 },
-  { 0x05801a17, 0x30000001 },
-  { 0x05801a19, 0x28000002 },
-  { 0x05801a1e, 0x54000001 },
-  { 0x21801d00, 0x1400002b },
-  { 0x21801d2c, 0x18000035 },
-  { 0x21801d62, 0x14000015 },
-  { 0x0c001d78, 0x18000000 },
-  { 0x21801d79, 0x14000021 },
-  { 0x21801d9b, 0x18000024 },
-  { 0x1b801dc0, 0x30000003 },
-  { 0x21001e00, 0x24000001 },
-  { 0x21001e01, 0x1400ffff },
-  { 0x21001e02, 0x24000001 },
-  { 0x21001e03, 0x1400ffff },
-  { 0x21001e04, 0x24000001 },
-  { 0x21001e05, 0x1400ffff },
-  { 0x21001e06, 0x24000001 },
-  { 0x21001e07, 0x1400ffff },
-  { 0x21001e08, 0x24000001 },
-  { 0x21001e09, 0x1400ffff },
-  { 0x21001e0a, 0x24000001 },
-  { 0x21001e0b, 0x1400ffff },
-  { 0x21001e0c, 0x24000001 },
-  { 0x21001e0d, 0x1400ffff },
-  { 0x21001e0e, 0x24000001 },
-  { 0x21001e0f, 0x1400ffff },
-  { 0x21001e10, 0x24000001 },
-  { 0x21001e11, 0x1400ffff },
-  { 0x21001e12, 0x24000001 },
-  { 0x21001e13, 0x1400ffff },
-  { 0x21001e14, 0x24000001 },
-  { 0x21001e15, 0x1400ffff },
-  { 0x21001e16, 0x24000001 },
-  { 0x21001e17, 0x1400ffff },
-  { 0x21001e18, 0x24000001 },
-  { 0x21001e19, 0x1400ffff },
-  { 0x21001e1a, 0x24000001 },
-  { 0x21001e1b, 0x1400ffff },
-  { 0x21001e1c, 0x24000001 },
-  { 0x21001e1d, 0x1400ffff },
-  { 0x21001e1e, 0x24000001 },
-  { 0x21001e1f, 0x1400ffff },
-  { 0x21001e20, 0x24000001 },
-  { 0x21001e21, 0x1400ffff },
-  { 0x21001e22, 0x24000001 },
-  { 0x21001e23, 0x1400ffff },
-  { 0x21001e24, 0x24000001 },
-  { 0x21001e25, 0x1400ffff },
-  { 0x21001e26, 0x24000001 },
-  { 0x21001e27, 0x1400ffff },
-  { 0x21001e28, 0x24000001 },
-  { 0x21001e29, 0x1400ffff },
-  { 0x21001e2a, 0x24000001 },
-  { 0x21001e2b, 0x1400ffff },
-  { 0x21001e2c, 0x24000001 },
-  { 0x21001e2d, 0x1400ffff },
-  { 0x21001e2e, 0x24000001 },
-  { 0x21001e2f, 0x1400ffff },
-  { 0x21001e30, 0x24000001 },
-  { 0x21001e31, 0x1400ffff },
-  { 0x21001e32, 0x24000001 },
-  { 0x21001e33, 0x1400ffff },
-  { 0x21001e34, 0x24000001 },
-  { 0x21001e35, 0x1400ffff },
-  { 0x21001e36, 0x24000001 },
-  { 0x21001e37, 0x1400ffff },
-  { 0x21001e38, 0x24000001 },
-  { 0x21001e39, 0x1400ffff },
-  { 0x21001e3a, 0x24000001 },
-  { 0x21001e3b, 0x1400ffff },
-  { 0x21001e3c, 0x24000001 },
-  { 0x21001e3d, 0x1400ffff },
-  { 0x21001e3e, 0x24000001 },
-  { 0x21001e3f, 0x1400ffff },
-  { 0x21001e40, 0x24000001 },
-  { 0x21001e41, 0x1400ffff },
-  { 0x21001e42, 0x24000001 },
-  { 0x21001e43, 0x1400ffff },
-  { 0x21001e44, 0x24000001 },
-  { 0x21001e45, 0x1400ffff },
-  { 0x21001e46, 0x24000001 },
-  { 0x21001e47, 0x1400ffff },
-  { 0x21001e48, 0x24000001 },
-  { 0x21001e49, 0x1400ffff },
-  { 0x21001e4a, 0x24000001 },
-  { 0x21001e4b, 0x1400ffff },
-  { 0x21001e4c, 0x24000001 },
-  { 0x21001e4d, 0x1400ffff },
-  { 0x21001e4e, 0x24000001 },
-  { 0x21001e4f, 0x1400ffff },
-  { 0x21001e50, 0x24000001 },
-  { 0x21001e51, 0x1400ffff },
-  { 0x21001e52, 0x24000001 },
-  { 0x21001e53, 0x1400ffff },
-  { 0x21001e54, 0x24000001 },
-  { 0x21001e55, 0x1400ffff },
-  { 0x21001e56, 0x24000001 },
-  { 0x21001e57, 0x1400ffff },
-  { 0x21001e58, 0x24000001 },
-  { 0x21001e59, 0x1400ffff },
-  { 0x21001e5a, 0x24000001 },
-  { 0x21001e5b, 0x1400ffff },
-  { 0x21001e5c, 0x24000001 },
-  { 0x21001e5d, 0x1400ffff },
-  { 0x21001e5e, 0x24000001 },
-  { 0x21001e5f, 0x1400ffff },
-  { 0x21001e60, 0x24000001 },
-  { 0x21001e61, 0x1400ffff },
-  { 0x21001e62, 0x24000001 },
-  { 0x21001e63, 0x1400ffff },
-  { 0x21001e64, 0x24000001 },
-  { 0x21001e65, 0x1400ffff },
-  { 0x21001e66, 0x24000001 },
-  { 0x21001e67, 0x1400ffff },
-  { 0x21001e68, 0x24000001 },
-  { 0x21001e69, 0x1400ffff },
-  { 0x21001e6a, 0x24000001 },
-  { 0x21001e6b, 0x1400ffff },
-  { 0x21001e6c, 0x24000001 },
-  { 0x21001e6d, 0x1400ffff },
-  { 0x21001e6e, 0x24000001 },
-  { 0x21001e6f, 0x1400ffff },
-  { 0x21001e70, 0x24000001 },
-  { 0x21001e71, 0x1400ffff },
-  { 0x21001e72, 0x24000001 },
-  { 0x21001e73, 0x1400ffff },
-  { 0x21001e74, 0x24000001 },
-  { 0x21001e75, 0x1400ffff },
-  { 0x21001e76, 0x24000001 },
-  { 0x21001e77, 0x1400ffff },
-  { 0x21001e78, 0x24000001 },
-  { 0x21001e79, 0x1400ffff },
-  { 0x21001e7a, 0x24000001 },
-  { 0x21001e7b, 0x1400ffff },
-  { 0x21001e7c, 0x24000001 },
-  { 0x21001e7d, 0x1400ffff },
-  { 0x21001e7e, 0x24000001 },
-  { 0x21001e7f, 0x1400ffff },
-  { 0x21001e80, 0x24000001 },
-  { 0x21001e81, 0x1400ffff },
-  { 0x21001e82, 0x24000001 },
-  { 0x21001e83, 0x1400ffff },
-  { 0x21001e84, 0x24000001 },
-  { 0x21001e85, 0x1400ffff },
-  { 0x21001e86, 0x24000001 },
-  { 0x21001e87, 0x1400ffff },
-  { 0x21001e88, 0x24000001 },
-  { 0x21001e89, 0x1400ffff },
-  { 0x21001e8a, 0x24000001 },
-  { 0x21001e8b, 0x1400ffff },
-  { 0x21001e8c, 0x24000001 },
-  { 0x21001e8d, 0x1400ffff },
-  { 0x21001e8e, 0x24000001 },
-  { 0x21001e8f, 0x1400ffff },
-  { 0x21001e90, 0x24000001 },
-  { 0x21001e91, 0x1400ffff },
-  { 0x21001e92, 0x24000001 },
-  { 0x21001e93, 0x1400ffff },
-  { 0x21001e94, 0x24000001 },
-  { 0x21001e95, 0x1400ffff },
-  { 0x21801e96, 0x14000004 },
-  { 0x21001e9b, 0x1400ffc5 },
-  { 0x21001ea0, 0x24000001 },
-  { 0x21001ea1, 0x1400ffff },
-  { 0x21001ea2, 0x24000001 },
-  { 0x21001ea3, 0x1400ffff },
-  { 0x21001ea4, 0x24000001 },
-  { 0x21001ea5, 0x1400ffff },
-  { 0x21001ea6, 0x24000001 },
-  { 0x21001ea7, 0x1400ffff },
-  { 0x21001ea8, 0x24000001 },
-  { 0x21001ea9, 0x1400ffff },
-  { 0x21001eaa, 0x24000001 },
-  { 0x21001eab, 0x1400ffff },
-  { 0x21001eac, 0x24000001 },
-  { 0x21001ead, 0x1400ffff },
-  { 0x21001eae, 0x24000001 },
-  { 0x21001eaf, 0x1400ffff },
-  { 0x21001eb0, 0x24000001 },
-  { 0x21001eb1, 0x1400ffff },
-  { 0x21001eb2, 0x24000001 },
-  { 0x21001eb3, 0x1400ffff },
-  { 0x21001eb4, 0x24000001 },
-  { 0x21001eb5, 0x1400ffff },
-  { 0x21001eb6, 0x24000001 },
-  { 0x21001eb7, 0x1400ffff },
-  { 0x21001eb8, 0x24000001 },
-  { 0x21001eb9, 0x1400ffff },
-  { 0x21001eba, 0x24000001 },
-  { 0x21001ebb, 0x1400ffff },
-  { 0x21001ebc, 0x24000001 },
-  { 0x21001ebd, 0x1400ffff },
-  { 0x21001ebe, 0x24000001 },
-  { 0x21001ebf, 0x1400ffff },
-  { 0x21001ec0, 0x24000001 },
-  { 0x21001ec1, 0x1400ffff },
-  { 0x21001ec2, 0x24000001 },
-  { 0x21001ec3, 0x1400ffff },
-  { 0x21001ec4, 0x24000001 },
-  { 0x21001ec5, 0x1400ffff },
-  { 0x21001ec6, 0x24000001 },
-  { 0x21001ec7, 0x1400ffff },
-  { 0x21001ec8, 0x24000001 },
-  { 0x21001ec9, 0x1400ffff },
-  { 0x21001eca, 0x24000001 },
-  { 0x21001ecb, 0x1400ffff },
-  { 0x21001ecc, 0x24000001 },
-  { 0x21001ecd, 0x1400ffff },
-  { 0x21001ece, 0x24000001 },
-  { 0x21001ecf, 0x1400ffff },
-  { 0x21001ed0, 0x24000001 },
-  { 0x21001ed1, 0x1400ffff },
-  { 0x21001ed2, 0x24000001 },
-  { 0x21001ed3, 0x1400ffff },
-  { 0x21001ed4, 0x24000001 },
-  { 0x21001ed5, 0x1400ffff },
-  { 0x21001ed6, 0x24000001 },
-  { 0x21001ed7, 0x1400ffff },
-  { 0x21001ed8, 0x24000001 },
-  { 0x21001ed9, 0x1400ffff },
-  { 0x21001eda, 0x24000001 },
-  { 0x21001edb, 0x1400ffff },
-  { 0x21001edc, 0x24000001 },
-  { 0x21001edd, 0x1400ffff },
-  { 0x21001ede, 0x24000001 },
-  { 0x21001edf, 0x1400ffff },
-  { 0x21001ee0, 0x24000001 },
-  { 0x21001ee1, 0x1400ffff },
-  { 0x21001ee2, 0x24000001 },
-  { 0x21001ee3, 0x1400ffff },
-  { 0x21001ee4, 0x24000001 },
-  { 0x21001ee5, 0x1400ffff },
-  { 0x21001ee6, 0x24000001 },
-  { 0x21001ee7, 0x1400ffff },
-  { 0x21001ee8, 0x24000001 },
-  { 0x21001ee9, 0x1400ffff },
-  { 0x21001eea, 0x24000001 },
-  { 0x21001eeb, 0x1400ffff },
-  { 0x21001eec, 0x24000001 },
-  { 0x21001eed, 0x1400ffff },
-  { 0x21001eee, 0x24000001 },
-  { 0x21001eef, 0x1400ffff },
-  { 0x21001ef0, 0x24000001 },
-  { 0x21001ef1, 0x1400ffff },
-  { 0x21001ef2, 0x24000001 },
-  { 0x21001ef3, 0x1400ffff },
-  { 0x21001ef4, 0x24000001 },
-  { 0x21001ef5, 0x1400ffff },
-  { 0x21001ef6, 0x24000001 },
-  { 0x21001ef7, 0x1400ffff },
-  { 0x21001ef8, 0x24000001 },
-  { 0x21001ef9, 0x1400ffff },
-  { 0x13001f00, 0x14000008 },
-  { 0x13001f01, 0x14000008 },
-  { 0x13001f02, 0x14000008 },
-  { 0x13001f03, 0x14000008 },
-  { 0x13001f04, 0x14000008 },
-  { 0x13001f05, 0x14000008 },
-  { 0x13001f06, 0x14000008 },
-  { 0x13001f07, 0x14000008 },
-  { 0x13001f08, 0x2400fff8 },
-  { 0x13001f09, 0x2400fff8 },
-  { 0x13001f0a, 0x2400fff8 },
-  { 0x13001f0b, 0x2400fff8 },
-  { 0x13001f0c, 0x2400fff8 },
-  { 0x13001f0d, 0x2400fff8 },
-  { 0x13001f0e, 0x2400fff8 },
-  { 0x13001f0f, 0x2400fff8 },
-  { 0x13001f10, 0x14000008 },
-  { 0x13001f11, 0x14000008 },
-  { 0x13001f12, 0x14000008 },
-  { 0x13001f13, 0x14000008 },
-  { 0x13001f14, 0x14000008 },
-  { 0x13001f15, 0x14000008 },
-  { 0x13001f18, 0x2400fff8 },
-  { 0x13001f19, 0x2400fff8 },
-  { 0x13001f1a, 0x2400fff8 },
-  { 0x13001f1b, 0x2400fff8 },
-  { 0x13001f1c, 0x2400fff8 },
-  { 0x13001f1d, 0x2400fff8 },
-  { 0x13001f20, 0x14000008 },
-  { 0x13001f21, 0x14000008 },
-  { 0x13001f22, 0x14000008 },
-  { 0x13001f23, 0x14000008 },
-  { 0x13001f24, 0x14000008 },
-  { 0x13001f25, 0x14000008 },
-  { 0x13001f26, 0x14000008 },
-  { 0x13001f27, 0x14000008 },
-  { 0x13001f28, 0x2400fff8 },
-  { 0x13001f29, 0x2400fff8 },
-  { 0x13001f2a, 0x2400fff8 },
-  { 0x13001f2b, 0x2400fff8 },
-  { 0x13001f2c, 0x2400fff8 },
-  { 0x13001f2d, 0x2400fff8 },
-  { 0x13001f2e, 0x2400fff8 },
-  { 0x13001f2f, 0x2400fff8 },
-  { 0x13001f30, 0x14000008 },
-  { 0x13001f31, 0x14000008 },
-  { 0x13001f32, 0x14000008 },
-  { 0x13001f33, 0x14000008 },
-  { 0x13001f34, 0x14000008 },
-  { 0x13001f35, 0x14000008 },
-  { 0x13001f36, 0x14000008 },
-  { 0x13001f37, 0x14000008 },
-  { 0x13001f38, 0x2400fff8 },
-  { 0x13001f39, 0x2400fff8 },
-  { 0x13001f3a, 0x2400fff8 },
-  { 0x13001f3b, 0x2400fff8 },
-  { 0x13001f3c, 0x2400fff8 },
-  { 0x13001f3d, 0x2400fff8 },
-  { 0x13001f3e, 0x2400fff8 },
-  { 0x13001f3f, 0x2400fff8 },
-  { 0x13001f40, 0x14000008 },
-  { 0x13001f41, 0x14000008 },
-  { 0x13001f42, 0x14000008 },
-  { 0x13001f43, 0x14000008 },
-  { 0x13001f44, 0x14000008 },
-  { 0x13001f45, 0x14000008 },
-  { 0x13001f48, 0x2400fff8 },
-  { 0x13001f49, 0x2400fff8 },
-  { 0x13001f4a, 0x2400fff8 },
-  { 0x13001f4b, 0x2400fff8 },
-  { 0x13001f4c, 0x2400fff8 },
-  { 0x13001f4d, 0x2400fff8 },
-  { 0x13001f50, 0x14000000 },
-  { 0x13001f51, 0x14000008 },
-  { 0x13001f52, 0x14000000 },
-  { 0x13001f53, 0x14000008 },
-  { 0x13001f54, 0x14000000 },
-  { 0x13001f55, 0x14000008 },
-  { 0x13001f56, 0x14000000 },
-  { 0x13001f57, 0x14000008 },
-  { 0x13001f59, 0x2400fff8 },
-  { 0x13001f5b, 0x2400fff8 },
-  { 0x13001f5d, 0x2400fff8 },
-  { 0x13001f5f, 0x2400fff8 },
-  { 0x13001f60, 0x14000008 },
-  { 0x13001f61, 0x14000008 },
-  { 0x13001f62, 0x14000008 },
-  { 0x13001f63, 0x14000008 },
-  { 0x13001f64, 0x14000008 },
-  { 0x13001f65, 0x14000008 },
-  { 0x13001f66, 0x14000008 },
-  { 0x13001f67, 0x14000008 },
-  { 0x13001f68, 0x2400fff8 },
-  { 0x13001f69, 0x2400fff8 },
-  { 0x13001f6a, 0x2400fff8 },
-  { 0x13001f6b, 0x2400fff8 },
-  { 0x13001f6c, 0x2400fff8 },
-  { 0x13001f6d, 0x2400fff8 },
-  { 0x13001f6e, 0x2400fff8 },
-  { 0x13001f6f, 0x2400fff8 },
-  { 0x13001f70, 0x1400004a },
-  { 0x13001f71, 0x1400004a },
-  { 0x13001f72, 0x14000056 },
-  { 0x13001f73, 0x14000056 },
-  { 0x13001f74, 0x14000056 },
-  { 0x13001f75, 0x14000056 },
-  { 0x13001f76, 0x14000064 },
-  { 0x13001f77, 0x14000064 },
-  { 0x13001f78, 0x14000080 },
-  { 0x13001f79, 0x14000080 },
-  { 0x13001f7a, 0x14000070 },
-  { 0x13001f7b, 0x14000070 },
-  { 0x13001f7c, 0x1400007e },
-  { 0x13001f7d, 0x1400007e },
-  { 0x13001f80, 0x14000008 },
-  { 0x13001f81, 0x14000008 },
-  { 0x13001f82, 0x14000008 },
-  { 0x13001f83, 0x14000008 },
-  { 0x13001f84, 0x14000008 },
-  { 0x13001f85, 0x14000008 },
-  { 0x13001f86, 0x14000008 },
-  { 0x13001f87, 0x14000008 },
-  { 0x13001f88, 0x2000fff8 },
-  { 0x13001f89, 0x2000fff8 },
-  { 0x13001f8a, 0x2000fff8 },
-  { 0x13001f8b, 0x2000fff8 },
-  { 0x13001f8c, 0x2000fff8 },
-  { 0x13001f8d, 0x2000fff8 },
-  { 0x13001f8e, 0x2000fff8 },
-  { 0x13001f8f, 0x2000fff8 },
-  { 0x13001f90, 0x14000008 },
-  { 0x13001f91, 0x14000008 },
-  { 0x13001f92, 0x14000008 },
-  { 0x13001f93, 0x14000008 },
-  { 0x13001f94, 0x14000008 },
-  { 0x13001f95, 0x14000008 },
-  { 0x13001f96, 0x14000008 },
-  { 0x13001f97, 0x14000008 },
-  { 0x13001f98, 0x2000fff8 },
-  { 0x13001f99, 0x2000fff8 },
-  { 0x13001f9a, 0x2000fff8 },
-  { 0x13001f9b, 0x2000fff8 },
-  { 0x13001f9c, 0x2000fff8 },
-  { 0x13001f9d, 0x2000fff8 },
-  { 0x13001f9e, 0x2000fff8 },
-  { 0x13001f9f, 0x2000fff8 },
-  { 0x13001fa0, 0x14000008 },
-  { 0x13001fa1, 0x14000008 },
-  { 0x13001fa2, 0x14000008 },
-  { 0x13001fa3, 0x14000008 },
-  { 0x13001fa4, 0x14000008 },
-  { 0x13001fa5, 0x14000008 },
-  { 0x13001fa6, 0x14000008 },
-  { 0x13001fa7, 0x14000008 },
-  { 0x13001fa8, 0x2000fff8 },
-  { 0x13001fa9, 0x2000fff8 },
-  { 0x13001faa, 0x2000fff8 },
-  { 0x13001fab, 0x2000fff8 },
-  { 0x13001fac, 0x2000fff8 },
-  { 0x13001fad, 0x2000fff8 },
-  { 0x13001fae, 0x2000fff8 },
-  { 0x13001faf, 0x2000fff8 },
-  { 0x13001fb0, 0x14000008 },
-  { 0x13001fb1, 0x14000008 },
-  { 0x13001fb2, 0x14000000 },
-  { 0x13001fb3, 0x14000009 },
-  { 0x13001fb4, 0x14000000 },
-  { 0x13801fb6, 0x14000001 },
-  { 0x13001fb8, 0x2400fff8 },
-  { 0x13001fb9, 0x2400fff8 },
-  { 0x13001fba, 0x2400ffb6 },
-  { 0x13001fbb, 0x2400ffb6 },
-  { 0x13001fbc, 0x2000fff7 },
-  { 0x13001fbd, 0x60000000 },
-  { 0x13001fbe, 0x1400e3db },
-  { 0x13801fbf, 0x60000002 },
-  { 0x13001fc2, 0x14000000 },
-  { 0x13001fc3, 0x14000009 },
-  { 0x13001fc4, 0x14000000 },
-  { 0x13801fc6, 0x14000001 },
-  { 0x13001fc8, 0x2400ffaa },
-  { 0x13001fc9, 0x2400ffaa },
-  { 0x13001fca, 0x2400ffaa },
-  { 0x13001fcb, 0x2400ffaa },
-  { 0x13001fcc, 0x2000fff7 },
-  { 0x13801fcd, 0x60000002 },
-  { 0x13001fd0, 0x14000008 },
-  { 0x13001fd1, 0x14000008 },
-  { 0x13801fd2, 0x14000001 },
-  { 0x13801fd6, 0x14000001 },
-  { 0x13001fd8, 0x2400fff8 },
-  { 0x13001fd9, 0x2400fff8 },
-  { 0x13001fda, 0x2400ff9c },
-  { 0x13001fdb, 0x2400ff9c },
-  { 0x13801fdd, 0x60000002 },
-  { 0x13001fe0, 0x14000008 },
-  { 0x13001fe1, 0x14000008 },
-  { 0x13801fe2, 0x14000002 },
-  { 0x13001fe5, 0x14000007 },
-  { 0x13801fe6, 0x14000001 },
-  { 0x13001fe8, 0x2400fff8 },
-  { 0x13001fe9, 0x2400fff8 },
-  { 0x13001fea, 0x2400ff90 },
-  { 0x13001feb, 0x2400ff90 },
-  { 0x13001fec, 0x2400fff9 },
-  { 0x13801fed, 0x60000002 },
-  { 0x13001ff2, 0x14000000 },
-  { 0x13001ff3, 0x14000009 },
-  { 0x13001ff4, 0x14000000 },
-  { 0x13801ff6, 0x14000001 },
-  { 0x13001ff8, 0x2400ff80 },
-  { 0x13001ff9, 0x2400ff80 },
-  { 0x13001ffa, 0x2400ff82 },
-  { 0x13001ffb, 0x2400ff82 },
-  { 0x13001ffc, 0x2000fff7 },
-  { 0x13801ffd, 0x60000001 },
-  { 0x09802000, 0x7400000a },
-  { 0x0980200b, 0x04000004 },
-  { 0x09802010, 0x44000005 },
-  { 0x09802016, 0x54000001 },
-  { 0x09002018, 0x50000000 },
-  { 0x09002019, 0x4c000000 },
-  { 0x0900201a, 0x58000000 },
-  { 0x0980201b, 0x50000001 },
-  { 0x0900201d, 0x4c000000 },
-  { 0x0900201e, 0x58000000 },
-  { 0x0900201f, 0x50000000 },
-  { 0x09802020, 0x54000007 },
-  { 0x09002028, 0x6c000000 },
-  { 0x09002029, 0x70000000 },
-  { 0x0980202a, 0x04000004 },
-  { 0x0900202f, 0x74000000 },
-  { 0x09802030, 0x54000008 },
-  { 0x09002039, 0x50000000 },
-  { 0x0900203a, 0x4c000000 },
-  { 0x0980203b, 0x54000003 },
-  { 0x0980203f, 0x40000001 },
-  { 0x09802041, 0x54000002 },
-  { 0x09002044, 0x64000000 },
-  { 0x09002045, 0x58000000 },
-  { 0x09002046, 0x48000000 },
-  { 0x09802047, 0x5400000a },
-  { 0x09002052, 0x64000000 },
-  { 0x09002053, 0x54000000 },
-  { 0x09002054, 0x40000000 },
-  { 0x09802055, 0x54000009 },
-  { 0x0900205f, 0x74000000 },
-  { 0x09802060, 0x04000003 },
-  { 0x0980206a, 0x04000005 },
-  { 0x09002070, 0x3c000000 },
-  { 0x21002071, 0x14000000 },
-  { 0x09802074, 0x3c000005 },
-  { 0x0980207a, 0x64000002 },
-  { 0x0900207d, 0x58000000 },
-  { 0x0900207e, 0x48000000 },
-  { 0x2100207f, 0x14000000 },
-  { 0x09802080, 0x3c000009 },
-  { 0x0980208a, 0x64000002 },
-  { 0x0900208d, 0x58000000 },
-  { 0x0900208e, 0x48000000 },
-  { 0x21802090, 0x18000004 },
-  { 0x098020a0, 0x5c000015 },
-  { 0x1b8020d0, 0x3000000c },
-  { 0x1b8020dd, 0x2c000003 },
-  { 0x1b0020e1, 0x30000000 },
-  { 0x1b8020e2, 0x2c000002 },
-  { 0x1b8020e5, 0x30000006 },
-  { 0x09802100, 0x68000001 },
-  { 0x09002102, 0x24000000 },
-  { 0x09802103, 0x68000003 },
-  { 0x09002107, 0x24000000 },
-  { 0x09802108, 0x68000001 },
-  { 0x0900210a, 0x14000000 },
-  { 0x0980210b, 0x24000002 },
-  { 0x0980210e, 0x14000001 },
-  { 0x09802110, 0x24000002 },
-  { 0x09002113, 0x14000000 },
-  { 0x09002114, 0x68000000 },
-  { 0x09002115, 0x24000000 },
-  { 0x09802116, 0x68000002 },
-  { 0x09802119, 0x24000004 },
-  { 0x0980211e, 0x68000005 },
-  { 0x09002124, 0x24000000 },
-  { 0x09002125, 0x68000000 },
-  { 0x13002126, 0x2400e2a3 },
-  { 0x09002127, 0x68000000 },
-  { 0x09002128, 0x24000000 },
-  { 0x09002129, 0x68000000 },
-  { 0x2100212a, 0x2400df41 },
-  { 0x2100212b, 0x2400dfba },
-  { 0x0980212c, 0x24000001 },
-  { 0x0900212e, 0x68000000 },
-  { 0x0900212f, 0x14000000 },
-  { 0x09802130, 0x24000001 },
-  { 0x09002132, 0x68000000 },
-  { 0x09002133, 0x24000000 },
-  { 0x09002134, 0x14000000 },
-  { 0x09802135, 0x1c000003 },
-  { 0x09002139, 0x14000000 },
-  { 0x0980213a, 0x68000001 },
-  { 0x0980213c, 0x14000001 },
-  { 0x0980213e, 0x24000001 },
-  { 0x09802140, 0x64000004 },
-  { 0x09002145, 0x24000000 },
-  { 0x09802146, 0x14000003 },
-  { 0x0900214a, 0x68000000 },
-  { 0x0900214b, 0x64000000 },
-  { 0x0900214c, 0x68000000 },
-  { 0x09802153, 0x3c00000c },
-  { 0x09002160, 0x38000010 },
-  { 0x09002161, 0x38000010 },
-  { 0x09002162, 0x38000010 },
-  { 0x09002163, 0x38000010 },
-  { 0x09002164, 0x38000010 },
-  { 0x09002165, 0x38000010 },
-  { 0x09002166, 0x38000010 },
-  { 0x09002167, 0x38000010 },
-  { 0x09002168, 0x38000010 },
-  { 0x09002169, 0x38000010 },
-  { 0x0900216a, 0x38000010 },
-  { 0x0900216b, 0x38000010 },
-  { 0x0900216c, 0x38000010 },
-  { 0x0900216d, 0x38000010 },
-  { 0x0900216e, 0x38000010 },
-  { 0x0900216f, 0x38000010 },
-  { 0x09002170, 0x3800fff0 },
-  { 0x09002171, 0x3800fff0 },
-  { 0x09002172, 0x3800fff0 },
-  { 0x09002173, 0x3800fff0 },
-  { 0x09002174, 0x3800fff0 },
-  { 0x09002175, 0x3800fff0 },
-  { 0x09002176, 0x3800fff0 },
-  { 0x09002177, 0x3800fff0 },
-  { 0x09002178, 0x3800fff0 },
-  { 0x09002179, 0x3800fff0 },
-  { 0x0900217a, 0x3800fff0 },
-  { 0x0900217b, 0x3800fff0 },
-  { 0x0900217c, 0x3800fff0 },
-  { 0x0900217d, 0x3800fff0 },
-  { 0x0900217e, 0x3800fff0 },
-  { 0x0900217f, 0x3800fff0 },
-  { 0x09802180, 0x38000003 },
-  { 0x09802190, 0x64000004 },
-  { 0x09802195, 0x68000004 },
-  { 0x0980219a, 0x64000001 },
-  { 0x0980219c, 0x68000003 },
-  { 0x090021a0, 0x64000000 },
-  { 0x098021a1, 0x68000001 },
-  { 0x090021a3, 0x64000000 },
-  { 0x098021a4, 0x68000001 },
-  { 0x090021a6, 0x64000000 },
-  { 0x098021a7, 0x68000006 },
-  { 0x090021ae, 0x64000000 },
-  { 0x098021af, 0x6800001e },
-  { 0x098021ce, 0x64000001 },
-  { 0x098021d0, 0x68000001 },
-  { 0x090021d2, 0x64000000 },
-  { 0x090021d3, 0x68000000 },
-  { 0x090021d4, 0x64000000 },
-  { 0x098021d5, 0x6800001e },
-  { 0x098021f4, 0x6400010b },
-  { 0x09802300, 0x68000007 },
-  { 0x09802308, 0x64000003 },
-  { 0x0980230c, 0x68000013 },
-  { 0x09802320, 0x64000001 },
-  { 0x09802322, 0x68000006 },
-  { 0x09002329, 0x58000000 },
-  { 0x0900232a, 0x48000000 },
-  { 0x0980232b, 0x68000050 },
-  { 0x0900237c, 0x64000000 },
-  { 0x0980237d, 0x6800001d },
-  { 0x0980239b, 0x64000018 },
-  { 0x090023b4, 0x58000000 },
-  { 0x090023b5, 0x48000000 },
-  { 0x090023b6, 0x54000000 },
-  { 0x098023b7, 0x68000024 },
-  { 0x09802400, 0x68000026 },
-  { 0x09802440, 0x6800000a },
-  { 0x09802460, 0x3c00003b },
-  { 0x0980249c, 0x68000019 },
-  { 0x090024b6, 0x6800001a },
-  { 0x090024b7, 0x6800001a },
-  { 0x090024b8, 0x6800001a },
-  { 0x090024b9, 0x6800001a },
-  { 0x090024ba, 0x6800001a },
-  { 0x090024bb, 0x6800001a },
-  { 0x090024bc, 0x6800001a },
-  { 0x090024bd, 0x6800001a },
-  { 0x090024be, 0x6800001a },
-  { 0x090024bf, 0x6800001a },
-  { 0x090024c0, 0x6800001a },
-  { 0x090024c1, 0x6800001a },
-  { 0x090024c2, 0x6800001a },
-  { 0x090024c3, 0x6800001a },
-  { 0x090024c4, 0x6800001a },
-  { 0x090024c5, 0x6800001a },
-  { 0x090024c6, 0x6800001a },
-  { 0x090024c7, 0x6800001a },
-  { 0x090024c8, 0x6800001a },
-  { 0x090024c9, 0x6800001a },
-  { 0x090024ca, 0x6800001a },
-  { 0x090024cb, 0x6800001a },
-  { 0x090024cc, 0x6800001a },
-  { 0x090024cd, 0x6800001a },
-  { 0x090024ce, 0x6800001a },
-  { 0x090024cf, 0x6800001a },
-  { 0x090024d0, 0x6800ffe6 },
-  { 0x090024d1, 0x6800ffe6 },
-  { 0x090024d2, 0x6800ffe6 },
-  { 0x090024d3, 0x6800ffe6 },
-  { 0x090024d4, 0x6800ffe6 },
-  { 0x090024d5, 0x6800ffe6 },
-  { 0x090024d6, 0x6800ffe6 },
-  { 0x090024d7, 0x6800ffe6 },
-  { 0x090024d8, 0x6800ffe6 },
-  { 0x090024d9, 0x6800ffe6 },
-  { 0x090024da, 0x6800ffe6 },
-  { 0x090024db, 0x6800ffe6 },
-  { 0x090024dc, 0x6800ffe6 },
-  { 0x090024dd, 0x6800ffe6 },
-  { 0x090024de, 0x6800ffe6 },
-  { 0x090024df, 0x6800ffe6 },
-  { 0x090024e0, 0x6800ffe6 },
-  { 0x090024e1, 0x6800ffe6 },
-  { 0x090024e2, 0x6800ffe6 },
-  { 0x090024e3, 0x6800ffe6 },
-  { 0x090024e4, 0x6800ffe6 },
-  { 0x090024e5, 0x6800ffe6 },
-  { 0x090024e6, 0x6800ffe6 },
-  { 0x090024e7, 0x6800ffe6 },
-  { 0x090024e8, 0x6800ffe6 },
-  { 0x090024e9, 0x6800ffe6 },
-  { 0x098024ea, 0x3c000015 },
-  { 0x09802500, 0x680000b6 },
-  { 0x090025b7, 0x64000000 },
-  { 0x098025b8, 0x68000008 },
-  { 0x090025c1, 0x64000000 },
-  { 0x098025c2, 0x68000035 },
-  { 0x098025f8, 0x64000007 },
-  { 0x09802600, 0x6800006e },
-  { 0x0900266f, 0x64000000 },
-  { 0x09802670, 0x6800002c },
-  { 0x098026a0, 0x68000011 },
-  { 0x09802701, 0x68000003 },
-  { 0x09802706, 0x68000003 },
-  { 0x0980270c, 0x6800001b },
-  { 0x09802729, 0x68000022 },
-  { 0x0900274d, 0x68000000 },
-  { 0x0980274f, 0x68000003 },
-  { 0x09002756, 0x68000000 },
-  { 0x09802758, 0x68000006 },
-  { 0x09802761, 0x68000006 },
-  { 0x09002768, 0x58000000 },
-  { 0x09002769, 0x48000000 },
-  { 0x0900276a, 0x58000000 },
-  { 0x0900276b, 0x48000000 },
-  { 0x0900276c, 0x58000000 },
-  { 0x0900276d, 0x48000000 },
-  { 0x0900276e, 0x58000000 },
-  { 0x0900276f, 0x48000000 },
-  { 0x09002770, 0x58000000 },
-  { 0x09002771, 0x48000000 },
-  { 0x09002772, 0x58000000 },
-  { 0x09002773, 0x48000000 },
-  { 0x09002774, 0x58000000 },
-  { 0x09002775, 0x48000000 },
-  { 0x09802776, 0x3c00001d },
-  { 0x09002794, 0x68000000 },
-  { 0x09802798, 0x68000017 },
-  { 0x098027b1, 0x6800000d },
-  { 0x098027c0, 0x64000004 },
-  { 0x090027c5, 0x58000000 },
-  { 0x090027c6, 0x48000000 },
-  { 0x098027d0, 0x64000015 },
-  { 0x090027e6, 0x58000000 },
-  { 0x090027e7, 0x48000000 },
-  { 0x090027e8, 0x58000000 },
-  { 0x090027e9, 0x48000000 },
-  { 0x090027ea, 0x58000000 },
-  { 0x090027eb, 0x48000000 },
-  { 0x098027f0, 0x6400000f },
-  { 0x04802800, 0x680000ff },
-  { 0x09802900, 0x64000082 },
-  { 0x09002983, 0x58000000 },
-  { 0x09002984, 0x48000000 },
-  { 0x09002985, 0x58000000 },
-  { 0x09002986, 0x48000000 },
-  { 0x09002987, 0x58000000 },
-  { 0x09002988, 0x48000000 },
-  { 0x09002989, 0x58000000 },
-  { 0x0900298a, 0x48000000 },
-  { 0x0900298b, 0x58000000 },
-  { 0x0900298c, 0x48000000 },
-  { 0x0900298d, 0x58000000 },
-  { 0x0900298e, 0x48000000 },
-  { 0x0900298f, 0x58000000 },
-  { 0x09002990, 0x48000000 },
-  { 0x09002991, 0x58000000 },
-  { 0x09002992, 0x48000000 },
-  { 0x09002993, 0x58000000 },
-  { 0x09002994, 0x48000000 },
-  { 0x09002995, 0x58000000 },
-  { 0x09002996, 0x48000000 },
-  { 0x09002997, 0x58000000 },
-  { 0x09002998, 0x48000000 },
-  { 0x09802999, 0x6400003e },
-  { 0x090029d8, 0x58000000 },
-  { 0x090029d9, 0x48000000 },
-  { 0x090029da, 0x58000000 },
-  { 0x090029db, 0x48000000 },
-  { 0x098029dc, 0x6400001f },
-  { 0x090029fc, 0x58000000 },
-  { 0x090029fd, 0x48000000 },
-  { 0x098029fe, 0x64000101 },
-  { 0x09802b00, 0x68000013 },
-  { 0x11002c00, 0x24000030 },
-  { 0x11002c01, 0x24000030 },
-  { 0x11002c02, 0x24000030 },
-  { 0x11002c03, 0x24000030 },
-  { 0x11002c04, 0x24000030 },
-  { 0x11002c05, 0x24000030 },
-  { 0x11002c06, 0x24000030 },
-  { 0x11002c07, 0x24000030 },
-  { 0x11002c08, 0x24000030 },
-  { 0x11002c09, 0x24000030 },
-  { 0x11002c0a, 0x24000030 },
-  { 0x11002c0b, 0x24000030 },
-  { 0x11002c0c, 0x24000030 },
-  { 0x11002c0d, 0x24000030 },
-  { 0x11002c0e, 0x24000030 },
-  { 0x11002c0f, 0x24000030 },
-  { 0x11002c10, 0x24000030 },
-  { 0x11002c11, 0x24000030 },
-  { 0x11002c12, 0x24000030 },
-  { 0x11002c13, 0x24000030 },
-  { 0x11002c14, 0x24000030 },
-  { 0x11002c15, 0x24000030 },
-  { 0x11002c16, 0x24000030 },
-  { 0x11002c17, 0x24000030 },
-  { 0x11002c18, 0x24000030 },
-  { 0x11002c19, 0x24000030 },
-  { 0x11002c1a, 0x24000030 },
-  { 0x11002c1b, 0x24000030 },
-  { 0x11002c1c, 0x24000030 },
-  { 0x11002c1d, 0x24000030 },
-  { 0x11002c1e, 0x24000030 },
-  { 0x11002c1f, 0x24000030 },
-  { 0x11002c20, 0x24000030 },
-  { 0x11002c21, 0x24000030 },
-  { 0x11002c22, 0x24000030 },
-  { 0x11002c23, 0x24000030 },
-  { 0x11002c24, 0x24000030 },
-  { 0x11002c25, 0x24000030 },
-  { 0x11002c26, 0x24000030 },
-  { 0x11002c27, 0x24000030 },
-  { 0x11002c28, 0x24000030 },
-  { 0x11002c29, 0x24000030 },
-  { 0x11002c2a, 0x24000030 },
-  { 0x11002c2b, 0x24000030 },
-  { 0x11002c2c, 0x24000030 },
-  { 0x11002c2d, 0x24000030 },
-  { 0x11002c2e, 0x24000030 },
-  { 0x11002c30, 0x1400ffd0 },
-  { 0x11002c31, 0x1400ffd0 },
-  { 0x11002c32, 0x1400ffd0 },
-  { 0x11002c33, 0x1400ffd0 },
-  { 0x11002c34, 0x1400ffd0 },
-  { 0x11002c35, 0x1400ffd0 },
-  { 0x11002c36, 0x1400ffd0 },
-  { 0x11002c37, 0x1400ffd0 },
-  { 0x11002c38, 0x1400ffd0 },
-  { 0x11002c39, 0x1400ffd0 },
-  { 0x11002c3a, 0x1400ffd0 },
-  { 0x11002c3b, 0x1400ffd0 },
-  { 0x11002c3c, 0x1400ffd0 },
-  { 0x11002c3d, 0x1400ffd0 },
-  { 0x11002c3e, 0x1400ffd0 },
-  { 0x11002c3f, 0x1400ffd0 },
-  { 0x11002c40, 0x1400ffd0 },
-  { 0x11002c41, 0x1400ffd0 },
-  { 0x11002c42, 0x1400ffd0 },
-  { 0x11002c43, 0x1400ffd0 },
-  { 0x11002c44, 0x1400ffd0 },
-  { 0x11002c45, 0x1400ffd0 },
-  { 0x11002c46, 0x1400ffd0 },
-  { 0x11002c47, 0x1400ffd0 },
-  { 0x11002c48, 0x1400ffd0 },
-  { 0x11002c49, 0x1400ffd0 },
-  { 0x11002c4a, 0x1400ffd0 },
-  { 0x11002c4b, 0x1400ffd0 },
-  { 0x11002c4c, 0x1400ffd0 },
-  { 0x11002c4d, 0x1400ffd0 },
-  { 0x11002c4e, 0x1400ffd0 },
-  { 0x11002c4f, 0x1400ffd0 },
-  { 0x11002c50, 0x1400ffd0 },
-  { 0x11002c51, 0x1400ffd0 },
-  { 0x11002c52, 0x1400ffd0 },
-  { 0x11002c53, 0x1400ffd0 },
-  { 0x11002c54, 0x1400ffd0 },
-  { 0x11002c55, 0x1400ffd0 },
-  { 0x11002c56, 0x1400ffd0 },
-  { 0x11002c57, 0x1400ffd0 },
-  { 0x11002c58, 0x1400ffd0 },
-  { 0x11002c59, 0x1400ffd0 },
-  { 0x11002c5a, 0x1400ffd0 },
-  { 0x11002c5b, 0x1400ffd0 },
-  { 0x11002c5c, 0x1400ffd0 },
-  { 0x11002c5d, 0x1400ffd0 },
-  { 0x11002c5e, 0x1400ffd0 },
-  { 0x0a002c80, 0x24000001 },
-  { 0x0a002c81, 0x1400ffff },
-  { 0x0a002c82, 0x24000001 },
-  { 0x0a002c83, 0x1400ffff },
-  { 0x0a002c84, 0x24000001 },
-  { 0x0a002c85, 0x1400ffff },
-  { 0x0a002c86, 0x24000001 },
-  { 0x0a002c87, 0x1400ffff },
-  { 0x0a002c88, 0x24000001 },
-  { 0x0a002c89, 0x1400ffff },
-  { 0x0a002c8a, 0x24000001 },
-  { 0x0a002c8b, 0x1400ffff },
-  { 0x0a002c8c, 0x24000001 },
-  { 0x0a002c8d, 0x1400ffff },
-  { 0x0a002c8e, 0x24000001 },
-  { 0x0a002c8f, 0x1400ffff },
-  { 0x0a002c90, 0x24000001 },
-  { 0x0a002c91, 0x1400ffff },
-  { 0x0a002c92, 0x24000001 },
-  { 0x0a002c93, 0x1400ffff },
-  { 0x0a002c94, 0x24000001 },
-  { 0x0a002c95, 0x1400ffff },
-  { 0x0a002c96, 0x24000001 },
-  { 0x0a002c97, 0x1400ffff },
-  { 0x0a002c98, 0x24000001 },
-  { 0x0a002c99, 0x1400ffff },
-  { 0x0a002c9a, 0x24000001 },
-  { 0x0a002c9b, 0x1400ffff },
-  { 0x0a002c9c, 0x24000001 },
-  { 0x0a002c9d, 0x1400ffff },
-  { 0x0a002c9e, 0x24000001 },
-  { 0x0a002c9f, 0x1400ffff },
-  { 0x0a002ca0, 0x24000001 },
-  { 0x0a002ca1, 0x1400ffff },
-  { 0x0a002ca2, 0x24000001 },
-  { 0x0a002ca3, 0x1400ffff },
-  { 0x0a002ca4, 0x24000001 },
-  { 0x0a002ca5, 0x1400ffff },
-  { 0x0a002ca6, 0x24000001 },
-  { 0x0a002ca7, 0x1400ffff },
-  { 0x0a002ca8, 0x24000001 },
-  { 0x0a002ca9, 0x1400ffff },
-  { 0x0a002caa, 0x24000001 },
-  { 0x0a002cab, 0x1400ffff },
-  { 0x0a002cac, 0x24000001 },
-  { 0x0a002cad, 0x1400ffff },
-  { 0x0a002cae, 0x24000001 },
-  { 0x0a002caf, 0x1400ffff },
-  { 0x0a002cb0, 0x24000001 },
-  { 0x0a002cb1, 0x1400ffff },
-  { 0x0a002cb2, 0x24000001 },
-  { 0x0a002cb3, 0x1400ffff },
-  { 0x0a002cb4, 0x24000001 },
-  { 0x0a002cb5, 0x1400ffff },
-  { 0x0a002cb6, 0x24000001 },
-  { 0x0a002cb7, 0x1400ffff },
-  { 0x0a002cb8, 0x24000001 },
-  { 0x0a002cb9, 0x1400ffff },
-  { 0x0a002cba, 0x24000001 },
-  { 0x0a002cbb, 0x1400ffff },
-  { 0x0a002cbc, 0x24000001 },
-  { 0x0a002cbd, 0x1400ffff },
-  { 0x0a002cbe, 0x24000001 },
-  { 0x0a002cbf, 0x1400ffff },
-  { 0x0a002cc0, 0x24000001 },
-  { 0x0a002cc1, 0x1400ffff },
-  { 0x0a002cc2, 0x24000001 },
-  { 0x0a002cc3, 0x1400ffff },
-  { 0x0a002cc4, 0x24000001 },
-  { 0x0a002cc5, 0x1400ffff },
-  { 0x0a002cc6, 0x24000001 },
-  { 0x0a002cc7, 0x1400ffff },
-  { 0x0a002cc8, 0x24000001 },
-  { 0x0a002cc9, 0x1400ffff },
-  { 0x0a002cca, 0x24000001 },
-  { 0x0a002ccb, 0x1400ffff },
-  { 0x0a002ccc, 0x24000001 },
-  { 0x0a002ccd, 0x1400ffff },
-  { 0x0a002cce, 0x24000001 },
-  { 0x0a002ccf, 0x1400ffff },
-  { 0x0a002cd0, 0x24000001 },
-  { 0x0a002cd1, 0x1400ffff },
-  { 0x0a002cd2, 0x24000001 },
-  { 0x0a002cd3, 0x1400ffff },
-  { 0x0a002cd4, 0x24000001 },
-  { 0x0a002cd5, 0x1400ffff },
-  { 0x0a002cd6, 0x24000001 },
-  { 0x0a002cd7, 0x1400ffff },
-  { 0x0a002cd8, 0x24000001 },
-  { 0x0a002cd9, 0x1400ffff },
-  { 0x0a002cda, 0x24000001 },
-  { 0x0a002cdb, 0x1400ffff },
-  { 0x0a002cdc, 0x24000001 },
-  { 0x0a002cdd, 0x1400ffff },
-  { 0x0a002cde, 0x24000001 },
-  { 0x0a002cdf, 0x1400ffff },
-  { 0x0a002ce0, 0x24000001 },
-  { 0x0a002ce1, 0x1400ffff },
-  { 0x0a002ce2, 0x24000001 },
-  { 0x0a002ce3, 0x1400ffff },
-  { 0x0a002ce4, 0x14000000 },
-  { 0x0a802ce5, 0x68000005 },
-  { 0x0a802cf9, 0x54000003 },
-  { 0x0a002cfd, 0x3c000000 },
-  { 0x0a802cfe, 0x54000001 },
-  { 0x10002d00, 0x1400e3a0 },
-  { 0x10002d01, 0x1400e3a0 },
-  { 0x10002d02, 0x1400e3a0 },
-  { 0x10002d03, 0x1400e3a0 },
-  { 0x10002d04, 0x1400e3a0 },
-  { 0x10002d05, 0x1400e3a0 },
-  { 0x10002d06, 0x1400e3a0 },
-  { 0x10002d07, 0x1400e3a0 },
-  { 0x10002d08, 0x1400e3a0 },
-  { 0x10002d09, 0x1400e3a0 },
-  { 0x10002d0a, 0x1400e3a0 },
-  { 0x10002d0b, 0x1400e3a0 },
-  { 0x10002d0c, 0x1400e3a0 },
-  { 0x10002d0d, 0x1400e3a0 },
-  { 0x10002d0e, 0x1400e3a0 },
-  { 0x10002d0f, 0x1400e3a0 },
-  { 0x10002d10, 0x1400e3a0 },
-  { 0x10002d11, 0x1400e3a0 },
-  { 0x10002d12, 0x1400e3a0 },
-  { 0x10002d13, 0x1400e3a0 },
-  { 0x10002d14, 0x1400e3a0 },
-  { 0x10002d15, 0x1400e3a0 },
-  { 0x10002d16, 0x1400e3a0 },
-  { 0x10002d17, 0x1400e3a0 },
-  { 0x10002d18, 0x1400e3a0 },
-  { 0x10002d19, 0x1400e3a0 },
-  { 0x10002d1a, 0x1400e3a0 },
-  { 0x10002d1b, 0x1400e3a0 },
-  { 0x10002d1c, 0x1400e3a0 },
-  { 0x10002d1d, 0x1400e3a0 },
-  { 0x10002d1e, 0x1400e3a0 },
-  { 0x10002d1f, 0x1400e3a0 },
-  { 0x10002d20, 0x1400e3a0 },
-  { 0x10002d21, 0x1400e3a0 },
-  { 0x10002d22, 0x1400e3a0 },
-  { 0x10002d23, 0x1400e3a0 },
-  { 0x10002d24, 0x1400e3a0 },
-  { 0x10002d25, 0x1400e3a0 },
-  { 0x3a802d30, 0x1c000035 },
-  { 0x3a002d6f, 0x18000000 },
-  { 0x0f802d80, 0x1c000016 },
-  { 0x0f802da0, 0x1c000006 },
-  { 0x0f802da8, 0x1c000006 },
-  { 0x0f802db0, 0x1c000006 },
-  { 0x0f802db8, 0x1c000006 },
-  { 0x0f802dc0, 0x1c000006 },
-  { 0x0f802dc8, 0x1c000006 },
-  { 0x0f802dd0, 0x1c000006 },
-  { 0x0f802dd8, 0x1c000006 },
-  { 0x09802e00, 0x54000001 },
-  { 0x09002e02, 0x50000000 },
-  { 0x09002e03, 0x4c000000 },
-  { 0x09002e04, 0x50000000 },
-  { 0x09002e05, 0x4c000000 },
-  { 0x09802e06, 0x54000002 },
-  { 0x09002e09, 0x50000000 },
-  { 0x09002e0a, 0x4c000000 },
-  { 0x09002e0b, 0x54000000 },
-  { 0x09002e0c, 0x50000000 },
-  { 0x09002e0d, 0x4c000000 },
-  { 0x09802e0e, 0x54000008 },
-  { 0x09002e17, 0x44000000 },
-  { 0x09002e1c, 0x50000000 },
-  { 0x09002e1d, 0x4c000000 },
-  { 0x16802e80, 0x68000019 },
-  { 0x16802e9b, 0x68000058 },
-  { 0x16802f00, 0x680000d5 },
-  { 0x09802ff0, 0x6800000b },
-  { 0x09003000, 0x74000000 },
-  { 0x09803001, 0x54000002 },
-  { 0x09003004, 0x68000000 },
-  { 0x16003005, 0x18000000 },
-  { 0x09003006, 0x1c000000 },
-  { 0x16003007, 0x38000000 },
-  { 0x09003008, 0x58000000 },
-  { 0x09003009, 0x48000000 },
-  { 0x0900300a, 0x58000000 },
-  { 0x0900300b, 0x48000000 },
-  { 0x0900300c, 0x58000000 },
-  { 0x0900300d, 0x48000000 },
-  { 0x0900300e, 0x58000000 },
-  { 0x0900300f, 0x48000000 },
-  { 0x09003010, 0x58000000 },
-  { 0x09003011, 0x48000000 },
-  { 0x09803012, 0x68000001 },
-  { 0x09003014, 0x58000000 },
-  { 0x09003015, 0x48000000 },
-  { 0x09003016, 0x58000000 },
-  { 0x09003017, 0x48000000 },
-  { 0x09003018, 0x58000000 },
-  { 0x09003019, 0x48000000 },
-  { 0x0900301a, 0x58000000 },
-  { 0x0900301b, 0x48000000 },
-  { 0x0900301c, 0x44000000 },
-  { 0x0900301d, 0x58000000 },
-  { 0x0980301e, 0x48000001 },
-  { 0x09003020, 0x68000000 },
-  { 0x16803021, 0x38000008 },
-  { 0x1b80302a, 0x30000005 },
-  { 0x09003030, 0x44000000 },
-  { 0x09803031, 0x18000004 },
-  { 0x09803036, 0x68000001 },
-  { 0x16803038, 0x38000002 },
-  { 0x1600303b, 0x18000000 },
-  { 0x0900303c, 0x1c000000 },
-  { 0x0900303d, 0x54000000 },
-  { 0x0980303e, 0x68000001 },
-  { 0x1a803041, 0x1c000055 },
-  { 0x1b803099, 0x30000001 },
-  { 0x0980309b, 0x60000001 },
-  { 0x1a80309d, 0x18000001 },
-  { 0x1a00309f, 0x1c000000 },
-  { 0x090030a0, 0x44000000 },
-  { 0x1d8030a1, 0x1c000059 },
-  { 0x090030fb, 0x54000000 },
-  { 0x098030fc, 0x18000002 },
-  { 0x1d0030ff, 0x1c000000 },
-  { 0x03803105, 0x1c000027 },
-  { 0x17803131, 0x1c00005d },
-  { 0x09803190, 0x68000001 },
-  { 0x09803192, 0x3c000003 },
-  { 0x09803196, 0x68000009 },
-  { 0x038031a0, 0x1c000017 },
-  { 0x098031c0, 0x6800000f },
-  { 0x1d8031f0, 0x1c00000f },
-  { 0x17803200, 0x6800001e },
-  { 0x09803220, 0x3c000009 },
-  { 0x0980322a, 0x68000019 },
-  { 0x09003250, 0x68000000 },
-  { 0x09803251, 0x3c00000e },
-  { 0x17803260, 0x6800001f },
-  { 0x09803280, 0x3c000009 },
-  { 0x0980328a, 0x68000026 },
-  { 0x098032b1, 0x3c00000e },
-  { 0x098032c0, 0x6800003e },
-  { 0x09803300, 0x680000ff },
-  { 0x16803400, 0x1c0019b5 },
-  { 0x09804dc0, 0x6800003f },
-  { 0x16804e00, 0x1c0051bb },
-  { 0x3c80a000, 0x1c000014 },
-  { 0x3c00a015, 0x18000000 },
-  { 0x3c80a016, 0x1c000476 },
-  { 0x3c80a490, 0x68000036 },
-  { 0x0980a700, 0x60000016 },
-  { 0x3080a800, 0x1c000001 },
-  { 0x3000a802, 0x28000000 },
-  { 0x3080a803, 0x1c000002 },
-  { 0x3000a806, 0x30000000 },
-  { 0x3080a807, 0x1c000003 },
-  { 0x3000a80b, 0x30000000 },
-  { 0x3080a80c, 0x1c000016 },
-  { 0x3080a823, 0x28000001 },
-  { 0x3080a825, 0x30000001 },
-  { 0x3000a827, 0x28000000 },
-  { 0x3080a828, 0x68000003 },
-  { 0x1780ac00, 0x1c002ba3 },
-  { 0x0980d800, 0x1000037f },
-  { 0x0980db80, 0x1000007f },
-  { 0x0980dc00, 0x100003ff },
-  { 0x0980e000, 0x0c0018ff },
-  { 0x1680f900, 0x1c00012d },
-  { 0x1680fa30, 0x1c00003a },
-  { 0x1680fa70, 0x1c000069 },
-  { 0x2180fb00, 0x14000006 },
-  { 0x0180fb13, 0x14000004 },
-  { 0x1900fb1d, 0x1c000000 },
-  { 0x1900fb1e, 0x30000000 },
-  { 0x1980fb1f, 0x1c000009 },
-  { 0x1900fb29, 0x64000000 },
-  { 0x1980fb2a, 0x1c00000c },
-  { 0x1980fb38, 0x1c000004 },
-  { 0x1900fb3e, 0x1c000000 },
-  { 0x1980fb40, 0x1c000001 },
-  { 0x1980fb43, 0x1c000001 },
-  { 0x1980fb46, 0x1c00006b },
-  { 0x0080fbd3, 0x1c00016a },
-  { 0x0900fd3e, 0x58000000 },
-  { 0x0900fd3f, 0x48000000 },
-  { 0x0080fd50, 0x1c00003f },
-  { 0x0080fd92, 0x1c000035 },
-  { 0x0080fdf0, 0x1c00000b },
-  { 0x0000fdfc, 0x5c000000 },
-  { 0x0900fdfd, 0x68000000 },
-  { 0x1b80fe00, 0x3000000f },
-  { 0x0980fe10, 0x54000006 },
-  { 0x0900fe17, 0x58000000 },
-  { 0x0900fe18, 0x48000000 },
-  { 0x0900fe19, 0x54000000 },
-  { 0x1b80fe20, 0x30000003 },
-  { 0x0900fe30, 0x54000000 },
-  { 0x0980fe31, 0x44000001 },
-  { 0x0980fe33, 0x40000001 },
-  { 0x0900fe35, 0x58000000 },
-  { 0x0900fe36, 0x48000000 },
-  { 0x0900fe37, 0x58000000 },
-  { 0x0900fe38, 0x48000000 },
-  { 0x0900fe39, 0x58000000 },
-  { 0x0900fe3a, 0x48000000 },
-  { 0x0900fe3b, 0x58000000 },
-  { 0x0900fe3c, 0x48000000 },
-  { 0x0900fe3d, 0x58000000 },
-  { 0x0900fe3e, 0x48000000 },
-  { 0x0900fe3f, 0x58000000 },
-  { 0x0900fe40, 0x48000000 },
-  { 0x0900fe41, 0x58000000 },
-  { 0x0900fe42, 0x48000000 },
-  { 0x0900fe43, 0x58000000 },
-  { 0x0900fe44, 0x48000000 },
-  { 0x0980fe45, 0x54000001 },
-  { 0x0900fe47, 0x58000000 },
-  { 0x0900fe48, 0x48000000 },
-  { 0x0980fe49, 0x54000003 },
-  { 0x0980fe4d, 0x40000002 },
-  { 0x0980fe50, 0x54000002 },
-  { 0x0980fe54, 0x54000003 },
-  { 0x0900fe58, 0x44000000 },
-  { 0x0900fe59, 0x58000000 },
-  { 0x0900fe5a, 0x48000000 },
-  { 0x0900fe5b, 0x58000000 },
-  { 0x0900fe5c, 0x48000000 },
-  { 0x0900fe5d, 0x58000000 },
-  { 0x0900fe5e, 0x48000000 },
-  { 0x0980fe5f, 0x54000002 },
-  { 0x0900fe62, 0x64000000 },
-  { 0x0900fe63, 0x44000000 },
-  { 0x0980fe64, 0x64000002 },
-  { 0x0900fe68, 0x54000000 },
-  { 0x0900fe69, 0x5c000000 },
-  { 0x0980fe6a, 0x54000001 },
-  { 0x0080fe70, 0x1c000004 },
-  { 0x0080fe76, 0x1c000086 },
-  { 0x0900feff, 0x04000000 },
-  { 0x0980ff01, 0x54000002 },
-  { 0x0900ff04, 0x5c000000 },
-  { 0x0980ff05, 0x54000002 },
-  { 0x0900ff08, 0x58000000 },
-  { 0x0900ff09, 0x48000000 },
-  { 0x0900ff0a, 0x54000000 },
-  { 0x0900ff0b, 0x64000000 },
-  { 0x0900ff0c, 0x54000000 },
-  { 0x0900ff0d, 0x44000000 },
-  { 0x0980ff0e, 0x54000001 },
-  { 0x0980ff10, 0x34000009 },
-  { 0x0980ff1a, 0x54000001 },
-  { 0x0980ff1c, 0x64000002 },
-  { 0x0980ff1f, 0x54000001 },
-  { 0x2100ff21, 0x24000020 },
-  { 0x2100ff22, 0x24000020 },
-  { 0x2100ff23, 0x24000020 },
-  { 0x2100ff24, 0x24000020 },
-  { 0x2100ff25, 0x24000020 },
-  { 0x2100ff26, 0x24000020 },
-  { 0x2100ff27, 0x24000020 },
-  { 0x2100ff28, 0x24000020 },
-  { 0x2100ff29, 0x24000020 },
-  { 0x2100ff2a, 0x24000020 },
-  { 0x2100ff2b, 0x24000020 },
-  { 0x2100ff2c, 0x24000020 },
-  { 0x2100ff2d, 0x24000020 },
-  { 0x2100ff2e, 0x24000020 },
-  { 0x2100ff2f, 0x24000020 },
-  { 0x2100ff30, 0x24000020 },
-  { 0x2100ff31, 0x24000020 },
-  { 0x2100ff32, 0x24000020 },
-  { 0x2100ff33, 0x24000020 },
-  { 0x2100ff34, 0x24000020 },
-  { 0x2100ff35, 0x24000020 },
-  { 0x2100ff36, 0x24000020 },
-  { 0x2100ff37, 0x24000020 },
-  { 0x2100ff38, 0x24000020 },
-  { 0x2100ff39, 0x24000020 },
-  { 0x2100ff3a, 0x24000020 },
-  { 0x0900ff3b, 0x58000000 },
-  { 0x0900ff3c, 0x54000000 },
-  { 0x0900ff3d, 0x48000000 },
-  { 0x0900ff3e, 0x60000000 },
-  { 0x0900ff3f, 0x40000000 },
-  { 0x0900ff40, 0x60000000 },
-  { 0x2100ff41, 0x1400ffe0 },
-  { 0x2100ff42, 0x1400ffe0 },
-  { 0x2100ff43, 0x1400ffe0 },
-  { 0x2100ff44, 0x1400ffe0 },
-  { 0x2100ff45, 0x1400ffe0 },
-  { 0x2100ff46, 0x1400ffe0 },
-  { 0x2100ff47, 0x1400ffe0 },
-  { 0x2100ff48, 0x1400ffe0 },
-  { 0x2100ff49, 0x1400ffe0 },
-  { 0x2100ff4a, 0x1400ffe0 },
-  { 0x2100ff4b, 0x1400ffe0 },
-  { 0x2100ff4c, 0x1400ffe0 },
-  { 0x2100ff4d, 0x1400ffe0 },
-  { 0x2100ff4e, 0x1400ffe0 },
-  { 0x2100ff4f, 0x1400ffe0 },
-  { 0x2100ff50, 0x1400ffe0 },
-  { 0x2100ff51, 0x1400ffe0 },
-  { 0x2100ff52, 0x1400ffe0 },
-  { 0x2100ff53, 0x1400ffe0 },
-  { 0x2100ff54, 0x1400ffe0 },
-  { 0x2100ff55, 0x1400ffe0 },
-  { 0x2100ff56, 0x1400ffe0 },
-  { 0x2100ff57, 0x1400ffe0 },
-  { 0x2100ff58, 0x1400ffe0 },
-  { 0x2100ff59, 0x1400ffe0 },
-  { 0x2100ff5a, 0x1400ffe0 },
-  { 0x0900ff5b, 0x58000000 },
-  { 0x0900ff5c, 0x64000000 },
-  { 0x0900ff5d, 0x48000000 },
-  { 0x0900ff5e, 0x64000000 },
-  { 0x0900ff5f, 0x58000000 },
-  { 0x0900ff60, 0x48000000 },
-  { 0x0900ff61, 0x54000000 },
-  { 0x0900ff62, 0x58000000 },
-  { 0x0900ff63, 0x48000000 },
-  { 0x0980ff64, 0x54000001 },
-  { 0x1d80ff66, 0x1c000009 },
-  { 0x0900ff70, 0x18000000 },
-  { 0x1d80ff71, 0x1c00002c },
-  { 0x0980ff9e, 0x18000001 },
-  { 0x1780ffa0, 0x1c00001e },
-  { 0x1780ffc2, 0x1c000005 },
-  { 0x1780ffca, 0x1c000005 },
-  { 0x1780ffd2, 0x1c000005 },
-  { 0x1780ffda, 0x1c000002 },
-  { 0x0980ffe0, 0x5c000001 },
-  { 0x0900ffe2, 0x64000000 },
-  { 0x0900ffe3, 0x60000000 },
-  { 0x0900ffe4, 0x68000000 },
-  { 0x0980ffe5, 0x5c000001 },
-  { 0x0900ffe8, 0x68000000 },
-  { 0x0980ffe9, 0x64000003 },
-  { 0x0980ffed, 0x68000001 },
-  { 0x0980fff9, 0x04000002 },
-  { 0x0980fffc, 0x68000001 },
-  { 0x23810000, 0x1c00000b },
-  { 0x2381000d, 0x1c000019 },
-  { 0x23810028, 0x1c000012 },
-  { 0x2381003c, 0x1c000001 },
-  { 0x2381003f, 0x1c00000e },
-  { 0x23810050, 0x1c00000d },
-  { 0x23810080, 0x1c00007a },
-  { 0x09810100, 0x54000001 },
-  { 0x09010102, 0x68000000 },
-  { 0x09810107, 0x3c00002c },
-  { 0x09810137, 0x68000008 },
-  { 0x13810140, 0x38000034 },
-  { 0x13810175, 0x3c000003 },
-  { 0x13810179, 0x68000010 },
-  { 0x1301018a, 0x3c000000 },
-  { 0x29810300, 0x1c00001e },
-  { 0x29810320, 0x3c000003 },
-  { 0x12810330, 0x1c000019 },
-  { 0x1201034a, 0x38000000 },
-  { 0x3b810380, 0x1c00001d },
-  { 0x3b01039f, 0x54000000 },
-  { 0x2a8103a0, 0x1c000023 },
-  { 0x2a8103c8, 0x1c000007 },
-  { 0x2a0103d0, 0x68000000 },
-  { 0x2a8103d1, 0x38000004 },
-  { 0x0d010400, 0x24000028 },
-  { 0x0d010401, 0x24000028 },
-  { 0x0d010402, 0x24000028 },
-  { 0x0d010403, 0x24000028 },
-  { 0x0d010404, 0x24000028 },
-  { 0x0d010405, 0x24000028 },
-  { 0x0d010406, 0x24000028 },
-  { 0x0d010407, 0x24000028 },
-  { 0x0d010408, 0x24000028 },
-  { 0x0d010409, 0x24000028 },
-  { 0x0d01040a, 0x24000028 },
-  { 0x0d01040b, 0x24000028 },
-  { 0x0d01040c, 0x24000028 },
-  { 0x0d01040d, 0x24000028 },
-  { 0x0d01040e, 0x24000028 },
-  { 0x0d01040f, 0x24000028 },
-  { 0x0d010410, 0x24000028 },
-  { 0x0d010411, 0x24000028 },
-  { 0x0d010412, 0x24000028 },
-  { 0x0d010413, 0x24000028 },
-  { 0x0d010414, 0x24000028 },
-  { 0x0d010415, 0x24000028 },
-  { 0x0d010416, 0x24000028 },
-  { 0x0d010417, 0x24000028 },
-  { 0x0d010418, 0x24000028 },
-  { 0x0d010419, 0x24000028 },
-  { 0x0d01041a, 0x24000028 },
-  { 0x0d01041b, 0x24000028 },
-  { 0x0d01041c, 0x24000028 },
-  { 0x0d01041d, 0x24000028 },
-  { 0x0d01041e, 0x24000028 },
-  { 0x0d01041f, 0x24000028 },
-  { 0x0d010420, 0x24000028 },
-  { 0x0d010421, 0x24000028 },
-  { 0x0d010422, 0x24000028 },
-  { 0x0d010423, 0x24000028 },
-  { 0x0d010424, 0x24000028 },
-  { 0x0d010425, 0x24000028 },
-  { 0x0d010426, 0x24000028 },
-  { 0x0d010427, 0x24000028 },
-  { 0x0d010428, 0x1400ffd8 },
-  { 0x0d010429, 0x1400ffd8 },
-  { 0x0d01042a, 0x1400ffd8 },
-  { 0x0d01042b, 0x1400ffd8 },
-  { 0x0d01042c, 0x1400ffd8 },
-  { 0x0d01042d, 0x1400ffd8 },
-  { 0x0d01042e, 0x1400ffd8 },
-  { 0x0d01042f, 0x1400ffd8 },
-  { 0x0d010430, 0x1400ffd8 },
-  { 0x0d010431, 0x1400ffd8 },
-  { 0x0d010432, 0x1400ffd8 },
-  { 0x0d010433, 0x1400ffd8 },
-  { 0x0d010434, 0x1400ffd8 },
-  { 0x0d010435, 0x1400ffd8 },
-  { 0x0d010436, 0x1400ffd8 },
-  { 0x0d010437, 0x1400ffd8 },
-  { 0x0d010438, 0x1400ffd8 },
-  { 0x0d010439, 0x1400ffd8 },
-  { 0x0d01043a, 0x1400ffd8 },
-  { 0x0d01043b, 0x1400ffd8 },
-  { 0x0d01043c, 0x1400ffd8 },
-  { 0x0d01043d, 0x1400ffd8 },
-  { 0x0d01043e, 0x1400ffd8 },
-  { 0x0d01043f, 0x1400ffd8 },
-  { 0x0d010440, 0x1400ffd8 },
-  { 0x0d010441, 0x1400ffd8 },
-  { 0x0d010442, 0x1400ffd8 },
-  { 0x0d010443, 0x1400ffd8 },
-  { 0x0d010444, 0x1400ffd8 },
-  { 0x0d010445, 0x1400ffd8 },
-  { 0x0d010446, 0x1400ffd8 },
-  { 0x0d010447, 0x1400ffd8 },
-  { 0x0d010448, 0x1400ffd8 },
-  { 0x0d010449, 0x1400ffd8 },
-  { 0x0d01044a, 0x1400ffd8 },
-  { 0x0d01044b, 0x1400ffd8 },
-  { 0x0d01044c, 0x1400ffd8 },
-  { 0x0d01044d, 0x1400ffd8 },
-  { 0x0d01044e, 0x1400ffd8 },
-  { 0x0d01044f, 0x1400ffd8 },
-  { 0x2e810450, 0x1c00004d },
-  { 0x2c8104a0, 0x34000009 },
-  { 0x0b810800, 0x1c000005 },
-  { 0x0b010808, 0x1c000000 },
-  { 0x0b81080a, 0x1c00002b },
-  { 0x0b810837, 0x1c000001 },
-  { 0x0b01083c, 0x1c000000 },
-  { 0x0b01083f, 0x1c000000 },
-  { 0x1e010a00, 0x1c000000 },
-  { 0x1e810a01, 0x30000002 },
-  { 0x1e810a05, 0x30000001 },
-  { 0x1e810a0c, 0x30000003 },
-  { 0x1e810a10, 0x1c000003 },
-  { 0x1e810a15, 0x1c000002 },
-  { 0x1e810a19, 0x1c00001a },
-  { 0x1e810a38, 0x30000002 },
-  { 0x1e010a3f, 0x30000000 },
-  { 0x1e810a40, 0x3c000007 },
-  { 0x1e810a50, 0x54000008 },
-  { 0x0981d000, 0x680000f5 },
-  { 0x0981d100, 0x68000026 },
-  { 0x0981d12a, 0x6800003a },
-  { 0x0981d165, 0x28000001 },
-  { 0x1b81d167, 0x30000002 },
-  { 0x0981d16a, 0x68000002 },
-  { 0x0981d16d, 0x28000005 },
-  { 0x0981d173, 0x04000007 },
-  { 0x1b81d17b, 0x30000007 },
-  { 0x0981d183, 0x68000001 },
-  { 0x1b81d185, 0x30000006 },
-  { 0x0981d18c, 0x6800001d },
-  { 0x1b81d1aa, 0x30000003 },
-  { 0x0981d1ae, 0x6800002f },
-  { 0x1381d200, 0x68000041 },
-  { 0x1381d242, 0x30000002 },
-  { 0x1301d245, 0x68000000 },
-  { 0x0981d300, 0x68000056 },
-  { 0x0981d400, 0x24000019 },
-  { 0x0981d41a, 0x14000019 },
-  { 0x0981d434, 0x24000019 },
-  { 0x0981d44e, 0x14000006 },
-  { 0x0981d456, 0x14000011 },
-  { 0x0981d468, 0x24000019 },
-  { 0x0981d482, 0x14000019 },
-  { 0x0901d49c, 0x24000000 },
-  { 0x0981d49e, 0x24000001 },
-  { 0x0901d4a2, 0x24000000 },
-  { 0x0981d4a5, 0x24000001 },
-  { 0x0981d4a9, 0x24000003 },
-  { 0x0981d4ae, 0x24000007 },
-  { 0x0981d4b6, 0x14000003 },
-  { 0x0901d4bb, 0x14000000 },
-  { 0x0981d4bd, 0x14000006 },
-  { 0x0981d4c5, 0x1400000a },
-  { 0x0981d4d0, 0x24000019 },
-  { 0x0981d4ea, 0x14000019 },
-  { 0x0981d504, 0x24000001 },
-  { 0x0981d507, 0x24000003 },
-  { 0x0981d50d, 0x24000007 },
-  { 0x0981d516, 0x24000006 },
-  { 0x0981d51e, 0x14000019 },
-  { 0x0981d538, 0x24000001 },
-  { 0x0981d53b, 0x24000003 },
-  { 0x0981d540, 0x24000004 },
-  { 0x0901d546, 0x24000000 },
-  { 0x0981d54a, 0x24000006 },
-  { 0x0981d552, 0x14000019 },
-  { 0x0981d56c, 0x24000019 },
-  { 0x0981d586, 0x14000019 },
-  { 0x0981d5a0, 0x24000019 },
-  { 0x0981d5ba, 0x14000019 },
-  { 0x0981d5d4, 0x24000019 },
-  { 0x0981d5ee, 0x14000019 },
-  { 0x0981d608, 0x24000019 },
-  { 0x0981d622, 0x14000019 },
-  { 0x0981d63c, 0x24000019 },
-  { 0x0981d656, 0x14000019 },
-  { 0x0981d670, 0x24000019 },
-  { 0x0981d68a, 0x1400001b },
-  { 0x0981d6a8, 0x24000018 },
-  { 0x0901d6c1, 0x64000000 },
-  { 0x0981d6c2, 0x14000018 },
-  { 0x0901d6db, 0x64000000 },
-  { 0x0981d6dc, 0x14000005 },
-  { 0x0981d6e2, 0x24000018 },
-  { 0x0901d6fb, 0x64000000 },
-  { 0x0981d6fc, 0x14000018 },
-  { 0x0901d715, 0x64000000 },
-  { 0x0981d716, 0x14000005 },
-  { 0x0981d71c, 0x24000018 },
-  { 0x0901d735, 0x64000000 },
-  { 0x0981d736, 0x14000018 },
-  { 0x0901d74f, 0x64000000 },
-  { 0x0981d750, 0x14000005 },
-  { 0x0981d756, 0x24000018 },
-  { 0x0901d76f, 0x64000000 },
-  { 0x0981d770, 0x14000018 },
-  { 0x0901d789, 0x64000000 },
-  { 0x0981d78a, 0x14000005 },
-  { 0x0981d790, 0x24000018 },
-  { 0x0901d7a9, 0x64000000 },
-  { 0x0981d7aa, 0x14000018 },
-  { 0x0901d7c3, 0x64000000 },
-  { 0x0981d7c4, 0x14000005 },
-  { 0x0981d7ce, 0x34000031 },
-  { 0x16820000, 0x1c00a6d6 },
-  { 0x1682f800, 0x1c00021d },
-  { 0x090e0001, 0x04000000 },
-  { 0x098e0020, 0x0400005f },
-  { 0x1b8e0100, 0x300000ef },
-  { 0x098f0000, 0x0c00fffd },
-  { 0x09900000, 0x0c00fffd },
-};
diff --git a/runtime/tools/create_snapshot_bin.py b/runtime/tools/create_snapshot_bin.py
index 71b72e1..19c2943 100755
--- a/runtime/tools/create_snapshot_bin.py
+++ b/runtime/tools/create_snapshot_bin.py
@@ -24,9 +24,14 @@
   result.add_option("--executable",
       action="store", type="string",
       help="path to snapshot generator executable")
+  result.add_option("--vm_output_bin",
+      action="store", type="string",
+      help="output file name into which vm isolate snapshot in binary form " +
+           "is generated")
   result.add_option("--output_bin",
       action="store", type="string",
-      help="output file name into which snapshot in binary form is generated")
+      help="output file name into which isolate snapshot in binary form " +
+           "is generated")
   result.add_option("--script",
       action="store", type="string",
       help="Dart script for which snapshot is to be generated")
@@ -54,6 +59,9 @@
   if not options.executable:
     sys.stderr.write('--executable not specified\n')
     return False
+  if not options.vm_output_bin:
+    sys.stderr.write('--vm_output_bin not specified\n')
+    return False
   if not options.output_bin:
     sys.stderr.write('--output_bin not specified\n')
     return False
@@ -83,8 +91,10 @@
   if options.package_root:
     script_args.append(''.join([ "--package_root=", options.package_root]))
 
-  # First setup the snapshot output filename.
-  script_args.append(''.join([ "--snapshot=", options.output_bin ]))
+  # First setup the vm isolate and regular isolate snapshot output filename.
+  script_args.append(''.join([ "--vm_isolate_snapshot=",
+                               options.vm_output_bin ]))
+  script_args.append(''.join([ "--isolate_snapshot=", options.output_bin ]))
 
   # Next setup all url mapping options specified.
   for url_arg in options.url_mapping:
diff --git a/runtime/tools/create_snapshot_file.py b/runtime/tools/create_snapshot_file.py
index 98b3f82..d31cc06 100755
--- a/runtime/tools/create_snapshot_file.py
+++ b/runtime/tools/create_snapshot_file.py
@@ -20,9 +20,12 @@
 
 def BuildOptions():
   result = optparse.OptionParser()
+  result.add_option("--vm_input_bin",
+      action="store", type="string",
+      help="input file name of the vm isolate snapshot in binary form")
   result.add_option("--input_bin",
       action="store", type="string",
-      help="input file name of the snapshot in binary form")
+      help="input file name of the isolate snapshot in binary form")
   result.add_option("--input_cc",
       action="store", type="string",
       help="input file name which contains the C buffer template")
@@ -36,6 +39,9 @@
 
 
 def ProcessOptions(options):
+  if not options.vm_input_bin:
+    sys.stderr.write('--vm_input_bin not specified\n')
+    return False
   if not options.input_bin:
     sys.stderr.write('--input_bin not specified\n')
     return False
@@ -63,9 +69,11 @@
   return result
 
 
-def makeFile(output_file, input_cc_file, input_file):
+def makeFile(output_file, input_cc_file,
+             vm_isolate_input_file, isolate_input_file):
   snapshot_cc_text = open(input_cc_file).read()
-  snapshot_cc_text = snapshot_cc_text % makeString(input_file)
+  snapshot_cc_text = snapshot_cc_text % (makeString(vm_isolate_input_file),
+                                         makeString(isolate_input_file))
   open(output_file, 'w').write(snapshot_cc_text)
   return True
 
@@ -83,7 +91,8 @@
     parser.print_help()
     return 1
 
-  if not makeFile(options.output, options.input_cc, options.input_bin):
+  if not makeFile(options.output, options.input_cc,
+                  options.vm_input_bin, options.input_bin):
     print "Unable to generate snapshot in C buffer form"
     return -1
 
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 1ec6a6e..ff60bdf 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -410,13 +410,8 @@
 void Assembler::mla(Register rd, Register rn,
                     Register rm, Register ra, Condition cond) {
   // rd <- ra + rn * rm.
-  if (TargetCPUFeatures::arm_version() == ARMv7) {
-    // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
-    EmitMulOp(cond, B21, ra, rd, rn, rm);
-  } else {
-    mul(IP, rn, rm, cond);
-    add(rd, ra, Operand(IP), cond);
-  }
+  // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
+  EmitMulOp(cond, B21, ra, rd, rn, rm);
 }
 
 
@@ -435,7 +430,6 @@
 
 void Assembler::smull(Register rd_lo, Register rd_hi,
                       Register rn, Register rm, Condition cond) {
-  ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
   // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
   EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm);
 }
@@ -443,33 +437,33 @@
 
 void Assembler::umull(Register rd_lo, Register rd_hi,
                       Register rn, Register rm, Condition cond) {
-  ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
   // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
   EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
 }
 
 
-void Assembler::smlal(Register rd_lo, Register rd_hi,
-                      Register rn, Register rm, Condition cond) {
-  ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
-  // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
-  EmitMulOp(cond, B23 | B22 | B21, rd_lo, rd_hi, rn, rm);
-}
-
-
 void Assembler::umlal(Register rd_lo, Register rd_hi,
                       Register rn, Register rm, Condition cond) {
-  ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
   // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
   EmitMulOp(cond, B23 | B21, rd_lo, rd_hi, rn, rm);
 }
 
 
 void Assembler::umaal(Register rd_lo, Register rd_hi,
-                      Register rn, Register rm, Condition cond) {
-  ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
-  // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
-  EmitMulOp(cond, B22, rd_lo, rd_hi, rn, rm);
+                      Register rn, Register rm) {
+  ASSERT(rd_lo != IP);
+  ASSERT(rd_hi != IP);
+  ASSERT(rn != IP);
+  ASSERT(rm != IP);
+  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
+    // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+    EmitMulOp(AL, B22, rd_lo, rd_hi, rn, rm);
+  } else {
+    mov(IP, Operand(0));
+    umlal(rd_lo, IP, rn, rm);
+    adds(rd_lo, rd_lo, Operand(rd_hi));
+    adc(rd_hi, IP, Operand(0));
+  }
 }
 
 
@@ -540,15 +534,27 @@
 }
 
 
-void Assembler::ldrd(Register rd, Address ad, Condition cond) {
+void Assembler::ldrd(Register rd, Register rn, int32_t offset, Condition cond) {
   ASSERT((rd % 2) == 0);
-  EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, ad);
+  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
+    const Register rd2 = static_cast<Register>(static_cast<int32_t>(rd) + 1);
+    ldr(rd, Address(rn, offset), cond);
+    ldr(rd2, Address(rn, offset + kWordSize), cond);
+  } else {
+    EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, Address(rn, offset));
+  }
 }
 
 
-void Assembler::strd(Register rd, Address ad, Condition cond) {
+void Assembler::strd(Register rd, Register rn, int32_t offset, Condition cond) {
   ASSERT((rd % 2) == 0);
-  EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, ad);
+  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
+    const Register rd2 = static_cast<Register>(static_cast<int32_t>(rd) + 1);
+    str(rd, Address(rn, offset), cond);
+    str(rd2, Address(rn, offset + kWordSize), cond);
+  } else {
+    EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, Address(rn, offset));
+  }
 }
 
 
@@ -556,11 +562,6 @@
                     Condition cond) {
   ASSERT(regs != 0);
   EmitMultiMemOp(cond, am, true, base, regs);
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-    // On ARMv5, touching a "banked" register after an ldm gives undefined
-    // behavior, so we just add a nop here to make that case easy to avoid.
-    nop();
-  }
 }
 
 
@@ -568,11 +569,6 @@
                     Condition cond) {
   ASSERT(regs != 0);
   EmitMultiMemOp(cond, am, false, base, regs);
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-    // On ARMv5, touching a "banked" register after an stm gives undefined
-    // behavior, so we just add a nop here to make that case easy to avoid.
-    nop();
-  }
 }
 
 
@@ -1676,10 +1672,10 @@
     ASSERT(base != value_odd);
     Operand shadow(GetVerifiedMemoryShadow());
     add(base, base, shadow, cond);
-    strd(value_even, Address(base, offset), cond);
+    strd(value_even, base, offset, cond);
     sub(base, base, shadow, cond);
   }
-  strd(value_even, Address(base, offset), cond);
+  strd(value_even, base, offset, cond);
 }
 
 
@@ -2794,7 +2790,7 @@
       ldr(reg, Address(base, offset), cond);
       break;
     case kWordPair:
-      ldrd(reg, Address(base, offset), cond);
+      ldrd(reg, base, offset, cond);
       break;
     default:
       UNREACHABLE();
@@ -2826,7 +2822,7 @@
       str(reg, Address(base, offset), cond);
       break;
     case kWordPair:
-      strd(reg, Address(base, offset), cond);
+      strd(reg, base, offset, cond);
       break;
     default:
       UNREACHABLE();
@@ -3132,60 +3128,6 @@
 }
 
 
-// If we aren't on ARMv7, there is no smull, and we have to check for overflow
-// manually.
-void Assembler::CheckMultSignedOverflow(Register left,
-                                        Register right,
-                                        Register tmp,
-                                        DRegister dtmp0, DRegister dtmp1,
-                                        Label* overflow) {
-  Label done, left_neg, left_pos_right_neg, left_neg_right_pos;
-
-  CompareImmediate(left, 0);
-  b(&left_neg, LT);
-  b(&done, EQ);
-  CompareImmediate(right, 0);
-  b(&left_pos_right_neg, LT);
-  b(&done, EQ);
-
-  // Both positive.
-  LoadImmediate(tmp, INT_MAX);
-  IntegerDivide(tmp, tmp, left, dtmp0, dtmp1);
-  cmp(tmp, Operand(right));
-  b(overflow, LT);
-  b(&done);
-
-  // left positive, right non-positive.
-  Bind(&left_pos_right_neg);
-  LoadImmediate(tmp, INT_MIN);
-  IntegerDivide(tmp, tmp, left, dtmp0, dtmp1);
-  cmp(tmp, Operand(right));
-  b(overflow, GT);
-  b(&done);
-
-  Bind(&left_neg);
-  CompareImmediate(right, 0);
-  b(&left_neg_right_pos, GT);
-  b(&done, EQ);
-
-  // both negative.
-  LoadImmediate(tmp, INT_MAX);
-  IntegerDivide(tmp, tmp, left, dtmp0, dtmp1);
-  cmp(tmp, Operand(right));
-  b(overflow, GT);
-  b(&done);
-
-  // left non-positive, right positive.
-  Bind(&left_neg_right_pos);
-  LoadImmediate(tmp, INT_MIN);
-  IntegerDivide(tmp, tmp, right, dtmp0, dtmp1);
-  cmp(tmp, Operand(left));
-  b(overflow, GT);
-
-  Bind(&done);
-}
-
-
 static int NumRegsBelowFP(RegList regs) {
   int count = 0;
   for (int i = 0; i < FP; i++) {
@@ -3323,7 +3265,10 @@
 // optimized function and there may be extra space for spill slots to
 // allocate. We must also set up the pool pointer for the function.
 void Assembler::EnterOsrFrame(intptr_t extra_size) {
-  const intptr_t offset = CodeSize();
+  // mov(IP, Operand(PC)) loads PC + Instr::kPCReadOffset (8). This may be
+  // different from EntryPointToPcMarkerOffset().
+  const intptr_t offset =
+      CodeSize() + Instr::kPCReadOffset - EntryPointToPcMarkerOffset();
 
   Comment("EnterOsrFrame");
   mov(IP, Operand(PC));
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index aef4a6b..76317d2 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -438,8 +438,11 @@
              Condition cond = AL);
   void umlal(Register rd_lo, Register rd_hi, Register rn, Register rm,
              Condition cond = AL);
-  void umaal(Register rd_lo, Register rd_hi, Register rn, Register rm,
-             Condition cond = AL);
+
+  // Emulation of this instruction uses IP and the condition codes. Therefore,
+  // none of the registers can be IP, and the instruction can only be used
+  // unconditionally.
+  void umaal(Register rd_lo, Register rd_hi, Register rn, Register rm);
 
   // Division instructions.
   void sdiv(Register rd, Register rn, Register rm, Condition cond = AL);
@@ -458,8 +461,11 @@
   void ldrsb(Register rd, Address ad, Condition cond = AL);
   void ldrsh(Register rd, Address ad, Condition cond = AL);
 
-  void ldrd(Register rd, Address ad, Condition cond = AL);
-  void strd(Register rd, Address ad, Condition cond = AL);
+  // ldrd and strd actually support the full range of addressing modes, but
+  // we don't use them, and we need to split them up into two instructions for
+  // ARMv5TE, so we only support the base + offset mode.
+  void ldrd(Register rd, Register rn, int32_t offset, Condition cond = AL);
+  void strd(Register rd, Register rn, int32_t offset, Condition cond = AL);
 
   void ldm(BlockAddressMode am, Register base,
            RegList regs, Condition cond = AL);
@@ -635,13 +641,6 @@
   void IntegerDivide(Register result, Register left, Register right,
                      DRegister tmpl, DRegister tmpr);
 
-  // If we aren't on ARMv7, there is no smull.
-  void CheckMultSignedOverflow(Register left,
-                               Register right,
-                               Register tmp,
-                               DRegister dtmp0, DRegister dtmp1,
-                               Label* overflow);
-
   // Load and Store.
   // These three do not clobber IP.
   void LoadPatchableImmediate(Register rd, int32_t value, Condition cond = AL);
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index f870156..dc1b56d 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -110,8 +110,6 @@
     __ vmovdr(D3, 1, R1);  // D3[1] == S7 = R1, S6:S7 == 41:43
     __ vmovrrd(R0, R1, D3);  // R0:R1 = D3, R0:R1 == 41:43
     __ sub(R0, R1, Operand(R0));  // 43-41
-  } else {
-    __ LoadImmediate(R0, 2);
   }
   __ bx(LR);
 }
@@ -119,8 +117,10 @@
 
 ASSEMBLER_TEST_RUN(Vmov, test) {
   EXPECT(test != NULL);
-  typedef int (*Vmov)() DART_UNUSED;
-  EXPECT_EQ(2, EXECUTE_TEST_CODE_INT32(Vmov, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*Vmov)() DART_UNUSED;
+    EXPECT_EQ(2, EXECUTE_TEST_CODE_INT32(Vmov, test->entry()));
+  }
 }
 
 
@@ -133,8 +133,6 @@
     __ vadds(S0, S0, S0);
     __ vstrs(S0, Address(R2, (-kWordSize * 30)));
     __ ldr(R0, Address(SP, (kWordSize * 30), Address::PostIndex));
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -146,9 +144,6 @@
     typedef float (*SingleVLoadStore)() DART_UNUSED;
     float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry());
     EXPECT_FLOAT_EQ(2*12.3f, res, 0.001f);
-  } else {
-    typedef int (*SingleVLoadStore)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SingleVLoadStore, test->entry()));
   }
 }
 
@@ -167,8 +162,6 @@
     // Expressing __ldr(R0, Address(SP, (kWordSize * 32), Address::PostIndex));
     // as:
     __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -180,9 +173,6 @@
     typedef float (*SingleVLoadStore)() DART_UNUSED;
     float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry());
     EXPECT_FLOAT_EQ(2*12.3f, res, 0.001f);
-  } else {
-    typedef int (*SingleVLoadStore)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SingleVLoadStore, test->entry()));
   }
 }
 
@@ -200,8 +190,6 @@
     __ vstrd(D0, Address(R2, (-kWordSize * 30)));
     __ ldr(R1, Address(R2, (-kWordSize * 29)));
     __ ldr(R0, Address(SP, (kWordSize * 30), Address::PostIndex));
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -213,9 +201,6 @@
     typedef double (*DoubleVLoadStore)() DART_UNUSED;
     float res = EXECUTE_TEST_CODE_DOUBLE(DoubleVLoadStore, test->entry());
     EXPECT_FLOAT_EQ(2*12.3f, res, 0.001f);
-  } else {
-    typedef int (*DoubleVLoadStore)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleVLoadStore, test->entry()));
   }
 }
 
@@ -231,8 +216,6 @@
     __ vsubs(S0, S0, S1);  // 49.98f
     __ vdivs(S0, S0, S1);  // 14.7f
     __ vsqrts(S0, S0);  // 3.8340579f
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -244,9 +227,6 @@
     typedef float (*SingleFPOperations)() DART_UNUSED;
     float res = EXECUTE_TEST_CODE_FLOAT(SingleFPOperations, test->entry());
     EXPECT_FLOAT_EQ(3.8340579f, res, 0.001f);
-  } else {
-    typedef int (*SingleFPOperations)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SingleFPOperations, test->entry()));
   }
 }
 
@@ -262,8 +242,6 @@
     __ vsubd(D0, D0, D1);  // 49.98
     __ vdivd(D0, D0, D1);  // 14.7
     __ vsqrtd(D0, D0);  // 3.8340579
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -275,9 +253,6 @@
     typedef double (*DoubleFPOperations)() DART_UNUSED;
     double res = EXECUTE_TEST_CODE_DOUBLE(DoubleFPOperations, test->entry());
     EXPECT_FLOAT_EQ(3.8340579, res, 0.001);
-  } else {
-    typedef int (*DoubleFPOperations)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleFPOperations, test->entry()));
   }
 }
 
@@ -291,8 +266,6 @@
     __ vmstat();
     __ mov(R0, Operand(1), VS);
     __ mov(R0, Operand(0), VC);
-  } else {
-    __ LoadImmediate(R0, 1);
   }
   __ Ret();
 }
@@ -300,8 +273,10 @@
 
 ASSEMBLER_TEST_RUN(DoubleSqrtNeg, test) {
   EXPECT(test != NULL);
-  typedef int (*DoubleSqrtNeg)() DART_UNUSED;
-  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(DoubleSqrtNeg, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*DoubleSqrtNeg)() DART_UNUSED;
+    EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(DoubleSqrtNeg, test->entry()));
+  }
 }
 
 
@@ -310,8 +285,6 @@
     __ mov(R3, Operand(6));
     __ vmovsr(S3, R3);
     __ vcvtdi(D0, S3);
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -324,10 +297,6 @@
     double res = EXECUTE_TEST_CODE_DOUBLE(IntToDoubleConversionCode,
                                           test->entry());
     EXPECT_FLOAT_EQ(6.0, res, 0.001);
-  } else {
-    typedef int (*IntToDoubleConversionCode)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(IntToDoubleConversionCode,
-                                         test->entry()));
   }
 }
 
@@ -343,8 +312,6 @@
     __ vcvtdi(D1, S2);
     __ LoadDImmediate(D2, 1.0 * (1LL << 32), R0);
     __ vmlad(D0, D1, D2);
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -357,10 +324,6 @@
     double res = EXECUTE_TEST_CODE_DOUBLE(LongToDoubleConversionCode,
                                           test->entry());
     EXPECT_FLOAT_EQ(60000000000.0, res, 0.001);
-  } else {
-    typedef int (*LongToDoubleConversionCode)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(LongToDoubleConversionCode,
-                                         test->entry()));
   }
 }
 
@@ -370,8 +333,6 @@
     __ mov(R3, Operand(6));
     __ vmovsr(S3, R3);
     __ vcvtsi(S0, S3);
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -384,10 +345,6 @@
     float res = EXECUTE_TEST_CODE_FLOAT(IntToFloatConversionCode,
                                         test->entry());
     EXPECT_FLOAT_EQ(6.0, res, 0.001);
-  } else {
-    typedef int (*IntToFloatConversionCode)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(IntToFloatConversionCode,
-                                         test->entry()));
   }
 }
 
@@ -396,8 +353,6 @@
   if (TargetCPUFeatures::vfp_supported()) {
     __ vcvtis(S1, S0);
     __ vmovrs(R0, S1);
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -416,9 +371,6 @@
     EXPECT_EQ(INT_MAX,
               EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion, test->entry(),
                                         FLT_MAX));
-  } else {
-    typedef int (*FloatToIntConversion)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(FloatToIntConversion, test->entry()));
   }
 }
 
@@ -427,8 +379,6 @@
   if (TargetCPUFeatures::vfp_supported()) {
     __ vcvtid(S0, D0);
     __ vmovrs(R0, S0);
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -447,26 +397,27 @@
     EXPECT_EQ(INT_MAX,
               EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion, test->entry(),
                                         DBL_MAX));
-  } else {
-    typedef int (*DoubleToIntConversion)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleToIntConversion, test->entry()));
   }
 }
 
 
 ASSEMBLER_TEST_GENERATE(FloatToDoubleConversion, assembler) {
-  __ LoadSImmediate(S2, 12.8f);
-  __ vcvtds(D0, S2);
+  if (TargetCPUFeatures::vfp_supported()) {
+    __ LoadSImmediate(S2, 12.8f);
+    __ vcvtds(D0, S2);
+  }
   __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(FloatToDoubleConversion, test) {
-  typedef double (*FloatToDoubleConversionCode)() DART_UNUSED;
-  EXPECT(test != NULL);
-  double res = EXECUTE_TEST_CODE_DOUBLE(FloatToDoubleConversionCode,
-                                        test->entry());
-  EXPECT_FLOAT_EQ(12.8, res, 0.001);
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef double (*FloatToDoubleConversionCode)() DART_UNUSED;
+    EXPECT(test != NULL);
+    double res = EXECUTE_TEST_CODE_DOUBLE(FloatToDoubleConversionCode,
+                                          test->entry());
+    EXPECT_FLOAT_EQ(12.8, res, 0.001);
+  }
 }
 
 
@@ -474,8 +425,6 @@
   if (TargetCPUFeatures::vfp_supported()) {
     __ LoadDImmediate(D1, 12.8, R0);
     __ vcvtsd(S0, D1);
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -488,10 +437,6 @@
     float res = EXECUTE_TEST_CODE_FLOAT(DoubleToFloatConversionCode,
                                         test->entry());
     EXPECT_FLOAT_EQ(12.8, res, 0.001);
-  } else {
-    typedef int (*DoubleToFloatConversionCode)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleToFloatConversionCode,
-                                         test->entry()));
   }
 }
 
@@ -519,8 +464,6 @@
     __ vmstat();
     // Error if not unordered (not Nan).
     __ add(R0, R0, Operand(16), VC);
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   // R0 is 0 if all tests passed.
   __ bx(LR);
@@ -529,8 +472,10 @@
 
 ASSEMBLER_TEST_RUN(FloatCompare, test) {
   EXPECT(test != NULL);
-  typedef int (*FloatCompare)() DART_UNUSED;
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(FloatCompare, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*FloatCompare)() DART_UNUSED;
+    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(FloatCompare, test->entry()));
+  }
 }
 
 
@@ -557,8 +502,6 @@
     __ vmstat();
     // Error if not unordered (not Nan).
     __ add(R0, R0, Operand(16), VC);
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   // R0 is 0 if all tests passed.
   __ bx(LR);
@@ -567,8 +510,10 @@
 
 ASSEMBLER_TEST_RUN(DoubleCompare, test) {
   EXPECT(test != NULL);
-  typedef int (*DoubleCompare)() DART_UNUSED;
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleCompare, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*DoubleCompare)() DART_UNUSED;
+    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(DoubleCompare, test->entry()));
+  }
 }
 
 
@@ -667,10 +612,7 @@
 
 
 ASSEMBLER_TEST_GENERATE(Semaphore, assembler) {
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-    __ mov(R0, Operand(42));
-    __ bx(LR);
-  } else {
+  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
     __ mov(R0, Operand(40));
     __ mov(R1, Operand(42));
     __ Push(R0);
@@ -681,23 +623,22 @@
     __ tst(IP, Operand(0));
     __ b(&retry, NE);  // NE if context switch occurred between ldrex and strex.
     __ Pop(R0);  // 42
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Semaphore, test) {
   EXPECT(test != NULL);
-  typedef int (*Semaphore)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Semaphore, test->entry()));
+  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
+    typedef int (*Semaphore)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Semaphore, test->entry()));
+  }
 }
 
 
 ASSEMBLER_TEST_GENERATE(FailedSemaphore, assembler) {
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-    __ mov(R0, Operand(41));
-    __ bx(LR);
-  } else {
+  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
     __ mov(R0, Operand(40));
     __ mov(R1, Operand(42));
     __ Push(R0);
@@ -706,15 +647,17 @@
     __ strex(IP, R1, SP);  // IP == 1, failure
     __ Pop(R0);  // 40
     __ add(R0, R0, Operand(IP));
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(FailedSemaphore, test) {
   EXPECT(test != NULL);
-  typedef int (*FailedSemaphore)() DART_UNUSED;
-  EXPECT_EQ(41, EXECUTE_TEST_CODE_INT32(FailedSemaphore, test->entry()));
+  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
+    typedef int (*FailedSemaphore)() DART_UNUSED;
+    EXPECT_EQ(41, EXECUTE_TEST_CODE_INT32(FailedSemaphore, test->entry()));
+  }
 }
 
 
@@ -883,8 +826,6 @@
     __ vcvtid(S0, D0);
     __ vmovrs(R1, S0);  // r1 = r0/r2
     __ mls(R0, R1, R2, R0);  // r0 = r0 - r1*r2
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -898,34 +839,19 @@
     EXPECT_EQ(0x1000400000da8LL,
               EXECUTE_TEST_CODE_INT64_LL(QuotientRemainder, test->entry(),
                                          0x12345678, 0x1234));
-  } else {
-    typedef int (*QuotientRemainder)() DART_UNUSED;
-    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(QuotientRemainder, test->entry()));
   }
 }
 
 
 ASSEMBLER_TEST_GENERATE(Multiply64To64, assembler) {
-#if defined(USING_SIMULATOR)
-  const ARMVersion version = TargetCPUFeatures::arm_version();
-  HostCPUFeatures::set_arm_version(ARMv7);
-#endif
-  if (TargetCPUFeatures::arm_version() == ARMv7) {
-    __ Push(R4);
-    __ mov(IP, Operand(R0));
-    __ mul(R4, R2, R1);
-    __ umull(R0, R1, R2, IP);
-    __ mla(R2, IP, R3, R4);
-    __ add(R1, R2, Operand(R1));
-    __ Pop(R4);
-  } else {
-    __ LoadImmediate(R0, 6);
-    __ LoadImmediate(R1, 0);
-  }
+  __ Push(R4);
+  __ mov(IP, Operand(R0));
+  __ mul(R4, R2, R1);
+  __ umull(R0, R1, R2, IP);
+  __ mla(R2, IP, R3, R4);
+  __ add(R1, R2, Operand(R1));
+  __ Pop(R4);
   __ bx(LR);
-#if defined(USING_SIMULATOR)
-  HostCPUFeatures::set_arm_version(version);
-#endif
 }
 
 
@@ -939,20 +865,8 @@
 
 
 ASSEMBLER_TEST_GENERATE(Multiply32To64, assembler) {
-#if defined(USING_SIMULATOR)
-  const ARMVersion version = TargetCPUFeatures::arm_version();
-  HostCPUFeatures::set_arm_version(ARMv7);
-#endif
-  if (TargetCPUFeatures::arm_version() == ARMv7) {
-    __ smull(R0, R1, R0, R2);
-  } else {
-    __ LoadImmediate(R0, 6);
-    __ LoadImmediate(R1, 0);
-  }
+  __ smull(R0, R1, R0, R2);
   __ bx(LR);
-#if defined(USING_SIMULATOR)
-  HostCPUFeatures::set_arm_version(version);
-#endif
 }
 
 
@@ -965,48 +879,9 @@
 }
 
 
-ASSEMBLER_TEST_GENERATE(MultiplyAccum32To64, assembler) {
-#if defined(USING_SIMULATOR)
-  const ARMVersion version = TargetCPUFeatures::arm_version();
-  HostCPUFeatures::set_arm_version(ARMv7);
-#endif
-  if (TargetCPUFeatures::arm_version() == ARMv7) {
-    __ smlal(R0, R1, R0, R2);
-  } else {
-    __ LoadImmediate(R0, 3);
-    __ LoadImmediate(R1, 0);
-  }
-  __ bx(LR);
-#if defined(USING_SIMULATOR)
-  HostCPUFeatures::set_arm_version(version);
-#endif
-}
-
-
-ASSEMBLER_TEST_RUN(MultiplyAccum32To64, test) {
-  EXPECT(test != NULL);
-  typedef int64_t (*MultiplyAccum32To64)
-      (int64_t operand0, int64_t operand1) DART_UNUSED;
-  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT64_LL(MultiplyAccum32To64, test->entry(),
-                                          -3, -2));
-}
-
-
 ASSEMBLER_TEST_GENERATE(MultiplyAccumAccum32To64, assembler) {
-#if defined(USING_SIMULATOR)
-  const ARMVersion version = TargetCPUFeatures::arm_version();
-  HostCPUFeatures::set_arm_version(ARMv7);
-#endif
-  if (TargetCPUFeatures::arm_version() == ARMv7) {
-    __ umaal(R0, R1, R2, R3);
-  } else {
-    __ LoadImmediate(R0, 3 + 7 + 5 * 11);
-    __ LoadImmediate(R1, 0);
-  }
+  __ umaal(R0, R1, R2, R3);
   __ bx(LR);
-#if defined(USING_SIMULATOR)
-  HostCPUFeatures::set_arm_version(version);
-#endif
 }
 
 
@@ -1274,10 +1149,12 @@
 
 ASSEMBLER_TEST_GENERATE(Ldrd, assembler) {
   __ mov(IP, Operand(SP));
-  __ strd(R2, Address(SP, (-kWordSize * 30), Address::PreIndex));
-  __ strd(R0, Address(IP, (-kWordSize * 28)));
-  __ ldrd(R2, Address(IP, (-kWordSize * 28)));
-  __ ldrd(R0, Address(SP, (kWordSize * 30), Address::PostIndex));
+  __ sub(SP, SP, Operand(kWordSize*30));
+  __ strd(R2, SP, 0);
+  __ strd(R0, IP, (-kWordSize*28));
+  __ ldrd(R2, IP, (-kWordSize*28));
+  __ ldrd(R0, SP, 0);
+  __ add(SP, SP, Operand(kWordSize*30));
   __ sub(R0, R0, Operand(R2));
   __ add(R1, R1, Operand(R3));
   __ bx(LR);
@@ -1476,8 +1353,6 @@
     __ vcmpd(D1, D5);
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
-  } else {
-    __ LoadImmediate(R0, 42);
   }
   __ bx(LR);
 }
@@ -1485,8 +1360,10 @@
 
 ASSEMBLER_TEST_RUN(VstmdVldmd, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1532,8 +1409,6 @@
     __ vcmps(S1, S5);
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
-  } else {
-    __ LoadImmediate(R0, 42);
   }
   __ bx(LR);
 }
@@ -1541,8 +1416,10 @@
 
 ASSEMBLER_TEST_RUN(VstmsVldms, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1587,8 +1464,6 @@
     __ vcmpd(D1, D5);
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
-  } else {
-    __ LoadImmediate(R0, 42);
   }
   __ bx(LR);
 }
@@ -1596,8 +1471,10 @@
 
 ASSEMBLER_TEST_RUN(VstmdVldmd1, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1641,8 +1518,6 @@
     __ vcmps(S1, S5);
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
-  } else {
-    __ LoadImmediate(R0, 42);
   }
   __ bx(LR);
 }
@@ -1650,8 +1525,10 @@
 
 ASSEMBLER_TEST_RUN(VstmsVldms1, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1706,8 +1583,6 @@
 
     // Restore used callee-saved FPU registers.
     __ vldmd(IA_W, SP, D8, 3);
-  } else {
-    __ LoadImmediate(R0, 42);
   }
   __ bx(LR);
 }
@@ -1715,8 +1590,10 @@
 
 ASSEMBLER_TEST_RUN(VstmdVldmd_off, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1764,8 +1641,6 @@
     __ vcmps(S5, S10);
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
-  } else {
-    __ LoadImmediate(R0, 42);
   }
   __ bx(LR);
 }
@@ -1773,8 +1648,10 @@
 
 ASSEMBLER_TEST_RUN(VstmsVldms_off, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::vfp_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1784,8 +1661,6 @@
     __ mov(R1, Operand(9));
     __ udiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
-  } else {
-    __ mov(R0, Operand(3));
   }
   __ bx(LR);
 }
@@ -1793,8 +1668,10 @@
 
 ASSEMBLER_TEST_RUN(Udiv, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::integer_division_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1804,8 +1681,6 @@
     __ LoadImmediate(R1, -9);
     __ sdiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
-  } else {
-    __ LoadImmediate(R0, -3);
   }
   __ bx(LR);
 }
@@ -1813,8 +1688,10 @@
 
 ASSEMBLER_TEST_RUN(Sdiv, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::integer_division_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1824,8 +1701,6 @@
     __ mov(R1, Operand(0));
     __ udiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -1833,8 +1708,10 @@
 
 ASSEMBLER_TEST_RUN(Udiv_zero, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::integer_division_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1844,8 +1721,6 @@
     __ mov(R1, Operand(0));
     __ sdiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -1853,8 +1728,10 @@
 
 ASSEMBLER_TEST_RUN(Sdiv_zero, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::integer_division_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1864,8 +1741,6 @@
     __ LoadImmediate(R1, 0xffffffff);
     __ udiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
-  } else {
-    __ LoadImmediate(R0, 0);
   }
   __ bx(LR);
 }
@@ -1873,8 +1748,10 @@
 
 ASSEMBLER_TEST_RUN(Udiv_corner, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::integer_division_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1884,8 +1761,6 @@
     __ LoadImmediate(R1, 0xffffffff);
     __ sdiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
-  } else {
-    __ LoadImmediate(R0, 0x80000000);
   }
   __ bx(LR);
 }
@@ -1893,9 +1768,11 @@
 
 ASSEMBLER_TEST_RUN(Sdiv_corner, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(static_cast<int32_t>(0x80000000),
-            EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::integer_division_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(static_cast<int32_t>(0x80000000),
+              EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1909,9 +1786,11 @@
   HostCPUFeatures::set_integer_division_supported(orig);
   __ bx(LR);
 #else
-  __ mov(R0, Operand(27));
-  __ mov(R1, Operand(9));
-  __ IntegerDivide(R0, R0, R1, D0, D1);
+  if (TargetCPUFeatures::can_divide()) {
+    __ mov(R0, Operand(27));
+    __ mov(R1, Operand(9));
+    __ IntegerDivide(R0, R0, R1, D0, D1);
+  }
   __ bx(LR);
 #endif
 }
@@ -1919,8 +1798,10 @@
 
 ASSEMBLER_TEST_RUN(IntDiv_supported, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::can_divide()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1934,9 +1815,11 @@
   HostCPUFeatures::set_integer_division_supported(orig);
   __ bx(LR);
 #else
-  __ mov(R0, Operand(27));
-  __ mov(R1, Operand(9));
-  __ IntegerDivide(R0, R0, R1, D0, D1);
+  if (TargetCPUFeatures::can_divide()) {
+    __ mov(R0, Operand(27));
+    __ mov(R1, Operand(9));
+    __ IntegerDivide(R0, R0, R1, D0, D1);
+  }
   __ bx(LR);
 #endif
 }
@@ -1944,8 +1827,10 @@
 
 ASSEMBLER_TEST_RUN(IntDiv_unsupported, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::can_divide()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -1994,18 +1879,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 36);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vaddqi8, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2038,18 +1922,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 36);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vaddqi16, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2082,18 +1965,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 36);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vaddqi32, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2114,18 +1996,17 @@
     __ vmovrs(R2, S10);
 
     __ add(R0, R0, Operand(R2));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 10);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vaddqi64, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2152,18 +2033,17 @@
 
     __ LoadImmediate(R0, 1);
     __ Bind(&fail);
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 1);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vshlqu64, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2190,18 +2070,17 @@
 
     __ LoadImmediate(R0, 1);
     __ Bind(&fail);
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 1);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vshlqi64, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2248,8 +2127,6 @@
 
     __ Bind(&fail);
     __ LoadImmediate(R0, 0);
-  } else {
-    __ LoadImmediate(R0, 1);
   }
   __ bx(LR);
 }
@@ -2257,8 +2134,10 @@
 
 ASSEMBLER_TEST_RUN(Mint_shl_ok, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2305,8 +2184,6 @@
 
     __ Bind(&fail);
     __ LoadImmediate(R0, 1);
-  } else {
-    __ LoadImmediate(R0, 1);
   }
   __ bx(LR);
 }
@@ -2314,8 +2191,10 @@
 
 ASSEMBLER_TEST_RUN(Mint_shl_overflow, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2348,18 +2227,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 10);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vsubqi8, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2392,18 +2270,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 10);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vsubqi16, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2436,18 +2313,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 10);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vsubqi32, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2468,18 +2344,17 @@
     __ vmovrs(R2, S10);
 
     __ add(R0, R0, Operand(R2));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 3);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vsubqi64, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2512,18 +2387,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 70);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vmulqi8, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2556,18 +2430,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 70);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vmulqi16, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2600,18 +2473,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 70);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vmulqi32, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2634,19 +2506,17 @@
 
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
-
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 36);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vaddqs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(36, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2669,19 +2539,17 @@
 
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
-
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 10);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vsubqs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(10, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2704,19 +2572,17 @@
 
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
-
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 70);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vmulqs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(70, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2748,18 +2614,17 @@
     __ CompareImmediate(R3, 1);
     __ bx(LR, NE);
     __ LoadImmediate(R0, 42);
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 42);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(VtblX, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2791,18 +2656,17 @@
     __ CompareImmediate(R3, 1);
     __ bx(LR, NE);
     __ LoadImmediate(R0, 42);
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 42);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(VtblY, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2834,18 +2698,17 @@
     __ CompareImmediate(R3, 1);
     __ bx(LR, NE);
     __ LoadImmediate(R0, 42);
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 42);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(VtblZ, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2877,18 +2740,17 @@
     __ CompareImmediate(R3, 1);
     __ bx(LR, NE);
     __ LoadImmediate(R0, 42);
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 42);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(VtblW, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2919,18 +2781,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -8);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Veorq, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -2961,18 +2822,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 60);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vornq, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(60, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(60, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3003,18 +2863,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -4);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vorrq, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3045,18 +2904,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 4);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vandq, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3082,19 +2940,17 @@
     __ vadds(S4, S4, S7);
     __ vcvtis(S0, S4);
     __ vmovrs(R0, S0);
-
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 4);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vmovq, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3105,18 +2961,17 @@
     __ vmvnq(Q1, Q0);  // Q1 <- ~Q0.
     __ vmvnq(Q2, Q1);  // Q2 <- ~Q1.
     __ vmovrs(R0, S10);  // Now R0 should be 42 again.
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 42);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vmvnq, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3138,18 +2993,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -4);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vdupb, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3171,18 +3025,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -4);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vduph, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3204,18 +3057,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -4);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vdupw, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3237,19 +3089,18 @@
     __ vadds(S0, S0, S1);
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, 8.0);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vzipqw, test) {
   EXPECT(test != NULL);
-  typedef float (*Vzipqw)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(Vzipqw, test->entry());
-  EXPECT_FLOAT_EQ(8.0, res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*Vzipqw)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(Vzipqw, test->entry());
+    EXPECT_FLOAT_EQ(8.0, res, 0.0001f);
+  }
 }
 
 
@@ -3282,18 +3133,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -2);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vceqqi32, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3318,18 +3168,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -2);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vceqqs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3362,18 +3211,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -2);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vcgeqi32, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3406,18 +3254,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -2);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vcugeqi32, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3442,18 +3289,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -2);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vcgeqs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3486,18 +3332,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -2);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vcgtqi32, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3530,18 +3375,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -2);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vcugtqi32, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3566,18 +3410,17 @@
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, -2);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vcgtqs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3601,18 +3444,17 @@
 
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 8);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vminqs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3636,18 +3478,17 @@
 
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
-    __ bx(LR);
-  } else {
-    __ LoadImmediate(R0, 14);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vmaxqs, test) {
   EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(14, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(14, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
 }
 
 
@@ -3692,22 +3533,19 @@
     __ vmovs(S5, S4);
     __ vmovs(S6, S4);
     __ vmovs(S7, S4);
-
     __ vrecpeqs(Q0, Q1);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, arm_recip_estimate(147.0));
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vrecpeqs, test) {
   EXPECT(test != NULL);
-  typedef float (*Vrecpeqs)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(Vrecpeqs, test->entry());
-  EXPECT_FLOAT_EQ(arm_recip_estimate(147.0), res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*Vrecpeqs)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(Vrecpeqs, test->entry());
+    EXPECT_FLOAT_EQ(arm_recip_estimate(147.0), res, 0.0001f);
+  }
 }
 
 
@@ -3724,20 +3562,18 @@
     __ LoadSImmediate(S11, 3.0);
 
     __ vrecpsqs(Q0, Q1, Q2);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, 2.0 - 10.0 * 5.0);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vrecpsqs, test) {
   EXPECT(test != NULL);
-  typedef float (*Vrecpsqs)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(Vrecpsqs, test->entry());
-  EXPECT_FLOAT_EQ(2.0 - 10.0 * 5.0, res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*Vrecpsqs)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(Vrecpsqs, test->entry());
+    EXPECT_FLOAT_EQ(2.0 - 10.0 * 5.0, res, 0.0001f);
+  }
 }
 
 
@@ -3755,20 +3591,18 @@
     __ vmulqs(Q0, Q0, Q2);
     __ vrecpsqs(Q2, Q1, Q0);
     __ vmulqs(Q0, Q0, Q2);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, 1.0/147000.0);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Reciprocal, test) {
   EXPECT(test != NULL);
-  typedef float (*Reciprocal)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(Reciprocal, test->entry());
-  EXPECT_FLOAT_EQ(1.0/147000.0, res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*Reciprocal)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(Reciprocal, test->entry());
+    EXPECT_FLOAT_EQ(1.0/147000.0, res, 0.0001f);
+  }
 }
 
 
@@ -3831,20 +3665,18 @@
     __ vmovs(S7, S4);
 
     __ vrsqrteqs(Q0, Q1);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, arm_reciprocal_sqrt_estimate(147.0));
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vrsqrteqs, test) {
   EXPECT(test != NULL);
-  typedef float (*Vrsqrteqs)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(Vrsqrteqs, test->entry());
-  EXPECT_FLOAT_EQ(arm_reciprocal_sqrt_estimate(147.0), res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*Vrsqrteqs)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(Vrsqrteqs, test->entry());
+    EXPECT_FLOAT_EQ(arm_reciprocal_sqrt_estimate(147.0), res, 0.0001f);
+  }
 }
 
 
@@ -3861,20 +3693,18 @@
     __ LoadSImmediate(S11, 3.0);
 
     __ vrsqrtsqs(Q0, Q1, Q2);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, (3.0 - 10.0 * 5.0) / 2.0);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vrsqrtsqs, test) {
   EXPECT(test != NULL);
-  typedef float (*Vrsqrtsqs)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(Vrsqrtsqs, test->entry());
-  EXPECT_FLOAT_EQ((3.0 - 10.0 * 5.0)/2.0, res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*Vrsqrtsqs)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(Vrsqrtsqs, test->entry());
+    EXPECT_FLOAT_EQ((3.0 - 10.0 * 5.0)/2.0, res, 0.0001f);
+  }
 }
 
 
@@ -3896,20 +3726,18 @@
     __ vmulqs(Q2, Q0, Q0);
     __ vrsqrtsqs(Q2, Q1, Q2);
     __ vmulqs(Q0, Q0, Q2);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, 1.0/sqrt(147000.0));
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(ReciprocalSqrt, test) {
   EXPECT(test != NULL);
-  typedef float (*ReciprocalSqrt)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(ReciprocalSqrt, test->entry());
-  EXPECT_FLOAT_EQ(1.0/sqrt(147000.0), res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*ReciprocalSqrt)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(ReciprocalSqrt, test->entry());
+    EXPECT_FLOAT_EQ(1.0/sqrt(147000.0), res, 0.0001f);
+  }
 }
 
 
@@ -3941,20 +3769,18 @@
     __ vmulqs(Q0, Q0, Q2);
     __ vrecpsqs(Q2, Q1, Q0);
     __ vmulqs(Q0, Q0, Q2);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, sqrt(147000.0));
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(SIMDSqrt, test) {
   EXPECT(test != NULL);
-  typedef float (*SIMDSqrt)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(SIMDSqrt, test->entry());
-  EXPECT_FLOAT_EQ(sqrt(147000.0), res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*SIMDSqrt)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(SIMDSqrt, test->entry());
+    EXPECT_FLOAT_EQ(sqrt(147000.0), res, 0.0001f);
+  }
 }
 
 
@@ -3990,20 +3816,18 @@
     __ vadds(S0, S0, S1);
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, 10.0);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(SIMDSqrt2, test) {
   EXPECT(test != NULL);
-  typedef float (*SIMDSqrt2)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(SIMDSqrt2, test->entry());
-  EXPECT_FLOAT_EQ(10.0, res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*SIMDSqrt2)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(SIMDSqrt2, test->entry());
+    EXPECT_FLOAT_EQ(10.0, res, 0.0001f);
+  }
 }
 
 
@@ -4031,20 +3855,18 @@
     __ vadds(S0, S0, S1);
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, 16.0);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(SIMDDiv, test) {
   EXPECT(test != NULL);
-  typedef float (*SIMDDiv)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(SIMDDiv, test->entry());
-  EXPECT_FLOAT_EQ(16.0, res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*SIMDDiv)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(SIMDDiv, test->entry());
+    EXPECT_FLOAT_EQ(16.0, res, 0.0001f);
+  }
 }
 
 
@@ -4060,20 +3882,18 @@
     __ vadds(S0, S0, S1);
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, 4.0);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vabsqs, test) {
   EXPECT(test != NULL);
-  typedef float (*Vabsqs)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(Vabsqs, test->entry());
-  EXPECT_FLOAT_EQ(4.0, res, 0.0001f);
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*Vabsqs)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(Vabsqs, test->entry());
+    EXPECT_FLOAT_EQ(4.0, res, 0.0001f);
+  }
 }
 
 
@@ -4089,114 +3909,18 @@
     __ vadds(S0, S0, S1);
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
-
-    __ bx(LR);
-  } else {
-    __ LoadSImmediate(S0, 2.0);
-    __ bx(LR);
   }
+  __ bx(LR);
 }
 
 
 ASSEMBLER_TEST_RUN(Vnegqs, test) {
   EXPECT(test != NULL);
-  typedef float (*Vnegqs)() DART_UNUSED;
-  float res = EXECUTE_TEST_CODE_FLOAT(Vnegqs, test->entry());
-  EXPECT_FLOAT_EQ(2.0, res, 0.0001f);
-}
-
-
-ASSEMBLER_TEST_GENERATE(MultCheckOverflow, assembler) {
-  // Both positive, no overflow
-  Label overflow1, test1;
-  __ LoadImmediate(R0, 42);
-  __ LoadImmediate(R1, 0xff);
-  __ LoadImmediate(R2, 0xf0);
-  __ CheckMultSignedOverflow(R1, R2, R3, D0, D1, &overflow1);
-  __ b(&test1);
-  __ Bind(&overflow1);
-  __ LoadImmediate(R0, 1);
-  __ Ret();
-
-
-  // Left negative no overflow.
-  __ Bind(&test1);
-  Label overflow2, test2;
-  __ LoadImmediate(R1, -0xff);
-  __ LoadImmediate(R2, 0xf0);
-  __ CheckMultSignedOverflow(R1, R2, R3, D0, D1, &overflow2);
-  __ b(&test2);
-  __ Bind(&overflow2);
-  __ LoadImmediate(R0, 2);
-  __ Ret();
-
-  // Right negative no overflow
-  Label overflow3, test3;
-  __ Bind(&test2);
-  __ LoadImmediate(R1, 0xff);
-  __ LoadImmediate(R2, -0xf0);
-  __ CheckMultSignedOverflow(R1, R2, R3, D0, D1, &overflow3);
-  __ b(&test3);
-  __ Bind(&overflow3);
-  __ LoadImmediate(R0, 3);
-  __ Ret();
-
-  // Both negative no overflow.
-  Label overflow4, test4;
-  __ Bind(&test3);
-  __ LoadImmediate(R1, -0xff);
-  __ LoadImmediate(R2, -0xf0);
-  __ CheckMultSignedOverflow(R1, R2, R3, D0, D1, &overflow4);
-  __ b(&test4);
-  __ Bind(&overflow4);
-  __ LoadImmediate(R0, 4);
-  __ Ret();
-
-  // Both positive with overflow.
-  Label test5;
-  __ Bind(&test4);
-  __ LoadImmediate(R1, 0x0fffffff);
-  __ LoadImmediate(R2, 0xffff);
-  __ CheckMultSignedOverflow(R1, R2, R3, D0, D1, &test5);
-  __ LoadImmediate(R0, 5);
-  __ Ret();
-
-  // left negative with overflow.
-  Label test6;
-  __ Bind(&test5);
-  __ LoadImmediate(R1, -0x0fffffff);
-  __ LoadImmediate(R2, 0xffff);
-  __ CheckMultSignedOverflow(R1, R2, R3, D0, D1, &test6);
-  __ LoadImmediate(R0, 6);
-  __ Ret();
-
-  // right negative with overflow.
-  Label test7;
-  __ Bind(&test6);
-  __ LoadImmediate(R1, 0x0fffffff);
-  __ LoadImmediate(R2, -0xffff);
-  __ CheckMultSignedOverflow(R1, R2, R3, D0, D1, &test7);
-  __ LoadImmediate(R0, 7);
-  __ Ret();
-
-  // both negative with overflow.
-  Label test8;
-  __ Bind(&test7);
-  __ LoadImmediate(R1, -0x0fffffff);
-  __ LoadImmediate(R2, -0xffff);
-  __ CheckMultSignedOverflow(R1, R2, R3, D0, D1, &test8);
-  __ LoadImmediate(R0, 8);
-  __ Ret();
-
-  __ Bind(&test8);
-  __ Ret();
-}
-
-
-ASSEMBLER_TEST_RUN(MultCheckOverflow, test) {
-  EXPECT(test != NULL);
-  typedef int (*Tst)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  if (TargetCPUFeatures::neon_supported()) {
+    typedef float (*Vnegqs)() DART_UNUSED;
+    float res = EXECUTE_TEST_CODE_FLOAT(Vnegqs, test->entry());
+    EXPECT_FLOAT_EQ(2.0, res, 0.0001f);
+  }
 }
 
 
@@ -4267,7 +3991,6 @@
 #undef RANGE_OF
 }
 
-
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index b6e3a68..4295cb1 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -1067,7 +1067,7 @@
 
   SetPrologueOffset();
 
-  TraceSimMsg("EnterCallRuntimeFrame");
+  Comment("EnterCallRuntimeFrame");
 
   // Save volatile CPU and FPU registers on the stack:
   // -------------
@@ -1108,7 +1108,7 @@
       2 * kWordSize +  // FP and RA.
       kDartVolatileFpuRegCount * kWordSize;
 
-  TraceSimMsg("LeaveCallRuntimeFrame");
+  Comment("LeaveCallRuntimeFrame");
 
   // SP might have been modified to reserve space for arguments
   // and ensure proper alignment of the stack frame.
@@ -1213,21 +1213,6 @@
   break_(Instr::kStopMessageCode);
 }
 
-
-void Assembler::TraceSimMsg(const char* message) {
-  // Don't bother adding in the messages unless tracing is enabled, and we are
-  // running in the simulator.
-#if defined(USING_SIMULATOR)
-  if (FLAG_trace_sim_after != -1) {
-    Label msg;
-    b(&msg);
-    Emit(reinterpret_cast<int32_t>(message));
-    Bind(&msg);
-    break_(Instr::kSimulatorMessageCode);
-  }
-#endif
-}
-
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 86cd17f..62dd303 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -325,10 +325,6 @@
 
   // Debugging and bringup support.
   void Stop(const char* message);
-
-  // TODO(zra): TraceSimMsg enables printing of helpful messages when
-  // --trace_sim is given. Eventually these calls will be changed to Comment.
-  void TraceSimMsg(const char* message);
   void Unimplemented(const char* message);
   void Untested(const char* message);
   void Unreachable(const char* message);
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index dcf41c2..7b2d914 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -2299,6 +2299,28 @@
 }
 
 
+void Assembler::shldq(Register dst, Register src, Register shifter) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  ASSERT(shifter == RCX);
+  Operand operand(src);
+  EmitOperandREX(dst, operand, REX_W);
+  EmitUint8(0x0F);
+  EmitUint8(0xA5);
+  EmitOperand(src & 7, Operand(dst));
+}
+
+
+void Assembler::shrdq(Register dst, Register src, Register shifter) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  ASSERT(shifter == RCX);
+  Operand operand(src);
+  EmitOperandREX(dst, operand, REX_W);
+  EmitUint8(0x0F);
+  EmitUint8(0xAD);
+  EmitOperand(src & 7, Operand(dst));
+}
+
+
 void Assembler::incl(const Address& address) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   Operand operand(address);
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 93ddd1f..861ccc5 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -627,6 +627,8 @@
   void sarq(Register reg, const Immediate& imm);
   void sarq(Register operand, Register shifter);
   void shldq(Register dst, Register src, const Immediate& imm);
+  void shldq(Register dst, Register src, Register shifter);
+  void shrdq(Register dst, Register src, Register shifter);
 
   void incl(const Address& address);
   void decl(const Address& address);
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc
index 3a35086..85ee637 100644
--- a/runtime/vm/assembler_x64_test.cc
+++ b/runtime/vm/assembler_x64_test.cc
@@ -1389,6 +1389,42 @@
     __ Bind(&donetest15b);
   }
 
+  {
+    Label donetest15c;
+    const int64_t left = 0xff00000000000000;
+    const int64_t right = 0xffffffffffffffff;
+    const int64_t shifted = 0xf000000000000003;
+    __ movq(RDX, Immediate(left));
+    __ movq(RAX, Immediate(right));
+    __ movq(RCX, Immediate(2));
+    __ shlq(RDX, RCX);  // RDX = 0xff00000000000000 << 2 == 0xfc00000000000000
+    __ shldq(RDX, RAX, RCX);
+    // RDX = high64(0xfc00000000000000:0xffffffffffffffff << 2)
+    //     == 0xf000000000000003
+    __ cmpq(RDX, Immediate(shifted));
+    __ j(EQUAL, &donetest15c);
+    __ int3();
+    __ Bind(&donetest15c);
+  }
+
+  {
+    Label donetest15d;
+    const int64_t left = 0xff00000000000000;
+    const int64_t right = 0xffffffffffffffff;
+    const int64_t shifted = 0xcff0000000000000;
+    __ movq(RDX, Immediate(left));
+    __ movq(RAX, Immediate(right));
+    __ movq(RCX, Immediate(2));
+    __ shrq(RDX, RCX);  // RDX = 0xff00000000000000 >> 2 == 0x3fc0000000000000
+    __ shrdq(RDX, RAX, RCX);
+    // RDX = low64(0xffffffffffffffff:0x3fc0000000000000 >> 2)
+    //     == 0xcff0000000000000
+    __ cmpq(RDX, Immediate(shifted));
+    __ j(EQUAL, &donetest15d);
+    __ int3();
+    __ Bind(&donetest15d);
+  }
+
   __ movl(RAX, Immediate(0));
   __ ret();
 }
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 7527d48..1ac1186 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -60,6 +60,7 @@
   const int kNumIterations = 1000;
   Timer timer(true, "CorelibIsolateStartup");
   Isolate* isolate = Isolate::Current();
+  Thread::ExitIsolate();
   for (int i = 0; i < kNumIterations; i++) {
     timer.Start();
     TestCase::CreateTestIsolate();
@@ -67,7 +68,7 @@
     Dart_ShutdownIsolate();
   }
   benchmark->set_score(timer.TotalElapsedTime() / kNumIterations);
-  Isolate::SetCurrent(isolate);
+  Thread::EnterIsolate(isolate);
 }
 
 
@@ -428,16 +429,19 @@
       "\n";
 
   // Start an Isolate, load a script and create a full snapshot.
-  uint8_t* buffer;
+  uint8_t* vm_isolate_snapshot_buffer;
+  uint8_t* isolate_snapshot_buffer;
   // Need to load the script into the dart: core library due to
   // the import of dart:_internal.
   TestCase::LoadCoreTestScript(kScriptChars, NULL);
   Api::CheckAndFinalizePendingClasses(Isolate::Current());
 
   // Write snapshot with object content.
-  FullSnapshotWriter writer(&buffer, &malloc_allocator);
+  FullSnapshotWriter writer(&vm_isolate_snapshot_buffer,
+                            &isolate_snapshot_buffer,
+                            &malloc_allocator);
   writer.WriteFullSnapshot();
-  const Snapshot* snapshot = Snapshot::SetupFromBuffer(buffer);
+  const Snapshot* snapshot = Snapshot::SetupFromBuffer(isolate_snapshot_buffer);
   ASSERT(snapshot->kind() == Snapshot::kFull);
   benchmark->set_score(snapshot->length());
 }
@@ -459,16 +463,19 @@
       "\n";
 
   // Start an Isolate, load a script and create a full snapshot.
-  uint8_t* buffer;
+  uint8_t* vm_isolate_snapshot_buffer;
+  uint8_t* isolate_snapshot_buffer;
   // Need to load the script into the dart: core library due to
   // the import of dart:_internal.
   TestCase::LoadCoreTestScript(kScriptChars, NULL);
   Api::CheckAndFinalizePendingClasses(Isolate::Current());
 
   // Write snapshot with object content.
-  FullSnapshotWriter writer(&buffer, &malloc_allocator);
+  FullSnapshotWriter writer(&vm_isolate_snapshot_buffer,
+                            &isolate_snapshot_buffer,
+                            &malloc_allocator);
   writer.WriteFullSnapshot();
-  const Snapshot* snapshot = Snapshot::SetupFromBuffer(buffer);
+  const Snapshot* snapshot = Snapshot::SetupFromBuffer(isolate_snapshot_buffer);
   ASSERT(snapshot->kind() == Snapshot::kFull);
   benchmark->set_score(snapshot->length());
 }
diff --git a/runtime/vm/benchmark_test.h b/runtime/vm/benchmark_test.h
index 18ea0a5..b26a139 100644
--- a/runtime/vm/benchmark_test.h
+++ b/runtime/vm/benchmark_test.h
@@ -19,10 +19,14 @@
 DECLARE_FLAG(int, code_heap_size);
 DECLARE_FLAG(int, old_gen_growth_space_ratio);
 
-// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
-// it is initialized to NULL.
 namespace bin {
-extern const uint8_t* snapshot_buffer;
+// vm_isolate_snapshot_buffer points to a snapshot for the vm isolate if we
+// link in a snapshot otherwise it is initialized to NULL.
+extern const uint8_t* vm_isolate_snapshot_buffer;
+
+// isolate_snapshot_buffer points to a snapshot for an isolate if we link in a
+// snapshot otherwise it is initialized to NULL.
+extern const uint8_t* isolate_snapshot_buffer;
 }
 
 // The BENCHMARK macros are used for benchmarking a specific functionality
@@ -109,7 +113,7 @@
 class BenchmarkIsolateScope {
  public:
   explicit BenchmarkIsolateScope(Benchmark* benchmark) : benchmark_(benchmark) {
-    benchmark_->CreateIsolate(bin::snapshot_buffer);
+    benchmark_->CreateIsolate(bin::isolate_snapshot_buffer);
     Dart_EnterScope();  // Create a Dart API scope for unit benchmarks.
   }
   ~BenchmarkIsolateScope() {
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index c33cd26..f0ff462 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -314,8 +314,8 @@
   V(ClassMirror_interfaces_instantiated, 1)                                    \
   V(ClassMirror_mixin, 1)                                                      \
   V(ClassMirror_mixin_instantiated, 2)                                         \
-  V(ClassMirror_members, 2)                                                    \
-  V(ClassMirror_constructors, 2)                                               \
+  V(ClassMirror_members, 3)                                                    \
+  V(ClassMirror_constructors, 3)                                               \
   V(LibraryMirror_members, 2)                                                  \
   V(LibraryMirror_libraryDependencies, 2)                                      \
   V(ClassMirror_invoke, 5)                                                     \
@@ -334,7 +334,7 @@
   V(FunctionTypeMirror_call_method, 2)                                         \
   V(FunctionTypeMirror_parameters, 2)                                          \
   V(FunctionTypeMirror_return_type, 2)                                         \
-  V(MethodMirror_owner, 1)                                                     \
+  V(MethodMirror_owner, 2)                                                     \
   V(MethodMirror_parameters, 2)                                                \
   V(MethodMirror_return_type, 2)                                               \
   V(MethodMirror_source, 1)                                                    \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index a7468b9..1ea33f3 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -510,6 +510,10 @@
 void ClassFinalizer::FinalizeTypeParameters(
     const Class& cls,
     GrowableObjectArray* pending_types) {
+  if (FLAG_trace_type_finalization) {
+    OS::Print("Finalizing type parameters of '%s'\n",
+              String::Handle(cls.Name()).ToCString());
+  }
   if (cls.IsMixinApplication()) {
     // Setup the type parameters of the mixin application and finalize the
     // mixin type.
@@ -817,6 +821,15 @@
       if (error.IsNull() &&
           !(type_arg.Equals(type_param) &&
             instantiated_bound.Equals(declared_bound))) {
+        // If type_arg is a type parameter, its declared bound may not be
+        // resolved yet.
+        if (type_arg.IsTypeParameter()) {
+          const Class& type_arg_cls = Class::Handle(
+              TypeParameter::Cast(type_arg).parameterized_class());
+          const AbstractType& bound = AbstractType::Handle(
+              TypeParameter::Cast(type_arg).bound());
+          ResolveType(type_arg_cls, bound);
+        }
         if (!type_param.CheckBound(type_arg, instantiated_bound, &error) &&
             error.IsNull()) {
           // The bound cannot be checked at compile time; postpone to run time.
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 1be6b66..aa4671f 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1436,10 +1436,11 @@
   ASSERT(optimized_code.is_optimized());
   ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown;
   uint32_t deopt_flags = 0;
-  const DeoptInfo& deopt_info = DeoptInfo::Handle(
+  const TypedData& deopt_info = TypedData::Handle(
       optimized_code.GetDeoptInfoAtPc(pc, &deopt_reason, &deopt_flags));
   ASSERT(!deopt_info.IsNull());
   const Function& function = Function::Handle(optimized_code.function());
+  Compiler::EnsureUnoptimizedCode(Thread::Current(), function);
   const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
   ASSERT(!unoptimized_code.IsNull());
   // The switch to unoptimized code may have already occurred.
@@ -1573,9 +1574,7 @@
     ASSERT(code.raw() == optimized_code.raw());
 
     // Some sanity checking of the optimized/unoptimized code.
-    const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
     ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
-    ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized());
   }
 #endif
 
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 77eb89f..47bd2ba 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -178,10 +178,10 @@
 
 
 RawError* Compiler::Compile(const Library& library, const Script& script) {
-  Isolate* volatile isolate = Isolate::Current();
-  StackZone zone(isolate);
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
+    Isolate* const isolate = Isolate::Current();
+    StackZone zone(isolate);
     if (FLAG_trace_compiler) {
       const String& script_url = String::Handle(script.url());
       // TODO(iposva): Extract script kind.
@@ -192,6 +192,8 @@
     Parser::ParseCompilationUnit(library, script);
     return Error::null();
   } else {
+    Isolate* const isolate = Isolate::Current();
+    StackZone zone(isolate);
     Error& error = Error::Handle();
     error = isolate->object_store()->sticky_error();
     isolate->object_store()->clear_sticky_error();
@@ -279,7 +281,7 @@
     }
   }
 
-  Isolate* volatile isolate = Isolate::Current();
+  Isolate* const isolate = Isolate::Current();
   // We remember all the classes that are being compiled in these lists. This
   // also allows us to reset the marked_for_parsing state in case we see an
   // error.
@@ -291,9 +293,9 @@
       GrowableObjectArray::Handle(isolate, GrowableObjectArray::New(4));
 
   // Parse the class and all the interfaces it implements and super classes.
-  StackZone zone(isolate);
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
+    StackZone zone(isolate);
     if (FLAG_trace_compiler) {
       ISL_Print("Compiling Class %s '%s'\n", "", cls.ToCString());
     }
@@ -352,7 +354,8 @@
         parse_class.reset_is_marked_for_parsing();
       }
     }
-
+    Isolate* const isolate = Isolate::Current();
+    StackZone zone(isolate);
     Error& error = Error::Handle(isolate);
     error = isolate->object_store()->sticky_error();
     isolate->object_store()->clear_sticky_error();
@@ -374,9 +377,9 @@
   }
   TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer);
   bool is_compiled = false;
-  Thread* volatile thread = Thread::Current();
-  Zone* volatile zone = thread->zone();
-  Isolate* volatile isolate = thread->isolate();
+  Thread* const thread = Thread::Current();
+  Zone* const zone = thread->zone();
+  Isolate* const isolate = thread->isolate();
   HANDLESCOPE(isolate);
 
   // We may reattempt compilation if the function needs to be assembled using
@@ -842,7 +845,7 @@
   if (deopt_table_length > 0) {
     ISL_Print("DeoptInfo: {\n");
     Smi& offset = Smi::Handle();
-    DeoptInfo& info = DeoptInfo::Handle();
+    TypedData& info = TypedData::Handle();
     Smi& reason_and_flags = Smi::Handle();
     for (intptr_t i = 0; i < deopt_table_length; ++i) {
       DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags);
@@ -852,7 +855,7 @@
       ISL_Print("%4" Pd ": 0x%" Px "  %s  (%s)\n",
                 i,
                 start + offset.Value(),
-                info.ToCString(),
+                DeoptInfo::ToCString(deopt_table, info),
                 DeoptReasonToCString(
                     static_cast<ICData::DeoptReasonId>(reason)));
     }
@@ -964,12 +967,12 @@
                                        const Function& function,
                                        bool optimized,
                                        intptr_t osr_id) {
-  Thread* volatile thread = Thread::Current();
-  Isolate* volatile isolate = thread->isolate();
-  StackZone stack_zone(isolate);
-  Zone* volatile zone = stack_zone.GetZone();
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
+    Thread* const thread = Thread::Current();
+    Isolate* const isolate = thread->isolate();
+    StackZone stack_zone(isolate);
+    Zone* const zone = stack_zone.GetZone();
     TIMERSCOPE(isolate, time_compilation);
     Timer per_compile_timer(FLAG_trace_compiler, "Compilation time");
     per_compile_timer.Start();
@@ -1032,6 +1035,9 @@
     }
     return Error::null();
   } else {
+    Thread* const thread = Thread::Current();
+    Isolate* const isolate = thread->isolate();
+    StackZone stack_zone(isolate);
     Error& error = Error::Handle();
     // We got an error during compilation.
     error = isolate->object_store()->sticky_error();
@@ -1052,6 +1058,35 @@
 }
 
 
+void Compiler::EnsureUnoptimizedCode(Thread* thread,
+                                     const Function& function) {
+  if (function.unoptimized_code() != Object::null()) {
+    return;
+  }
+  Code& original_code = Code::ZoneHandle(thread->zone());
+  if (function.HasCode()) {
+    original_code = function.CurrentCode();
+  }
+  CompilationPipeline* pipeline =
+      CompilationPipeline::New(thread->zone(), function);
+  const Error& error = Error::Handle(
+      CompileFunctionHelper(pipeline, function, false, Isolate::kNoDeoptId));
+  if (!error.IsNull()) {
+    Exceptions::PropagateError(error);
+  }
+  // Since CompileFunctionHelper replaces the current code, re-attach the
+  // the original code if the function was already compiled.
+  if (!original_code.IsNull() &&
+      (original_code.raw() != function.CurrentCode())) {
+    function.AttachCode(original_code);
+  }
+  ASSERT(function.unoptimized_code() != Object::null());
+  if (FLAG_trace_compiler) {
+    ISL_Print("Ensure unoptimized code for %s\n", function.ToCString());
+  }
+}
+
+
 RawError* Compiler::CompileOptimizedFunction(Thread* thread,
                                              const Function& function,
                                              intptr_t osr_id) {
@@ -1065,7 +1100,6 @@
 // This is only used from unit tests.
 RawError* Compiler::CompileParsedFunction(
     ParsedFunction* parsed_function) {
-  Isolate* volatile isolate = Isolate::Current();
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     // Non-optimized code generator.
@@ -1079,6 +1113,7 @@
     }
     return Error::null();
   } else {
+    Isolate* const isolate = Isolate::Current();
     Error& error = Error::Handle();
     // We got an error during compilation.
     error = isolate->object_store()->sticky_error();
@@ -1142,10 +1177,10 @@
   // The VM sets the field's value to transiton_sentinel prior to
   // evaluating the initializer value.
   ASSERT(field.value() == Object::transition_sentinel().raw());
-  Isolate* volatile isolate = Isolate::Current();
-  StackZone zone(isolate);
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
+    Isolate* const isolate = Isolate::Current();
+    StackZone zone(isolate);
     ParsedFunction* parsed_function =
         Parser::ParseStaticFieldInitializer(field);
 
@@ -1163,6 +1198,8 @@
         DartEntry::InvokeFunction(initializer, Object::empty_array()));
     return result.raw();
   } else {
+    Isolate* const isolate = Isolate::Current();
+    StackZone zone(isolate);
     const Error& error =
         Error::Handle(isolate, isolate->object_store()->sticky_error());
     isolate->object_store()->clear_sticky_error();
@@ -1175,10 +1212,9 @@
 
 
 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
-  Thread* volatile thread = Thread::Current();
-  Isolate* volatile isolate = thread->isolate();
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
+    Thread* const thread = Thread::Current();
     if (FLAG_trace_compiler) {
       ISL_Print("compiling expression: ");
       AstPrinter::PrintNode(fragment);
@@ -1228,6 +1264,8 @@
         DartEntry::InvokeFunction(func, Object::empty_array()));
     return result.raw();
   } else {
+    Thread* const thread = Thread::Current();
+    Isolate* const isolate = thread->isolate();
     const Object& result =
       PassiveObject::Handle(isolate->object_store()->sticky_error());
     isolate->object_store()->clear_sticky_error();
diff --git a/runtime/vm/compiler.h b/runtime/vm/compiler.h
index f9cc682..0e1f144 100644
--- a/runtime/vm/compiler.h
+++ b/runtime/vm/compiler.h
@@ -41,6 +41,9 @@
   // Returns Error::null() if there is no compilation error.
   static RawError* CompileFunction(Thread* thread, const Function& function);
 
+  // Generates unoptimized code if not present, current code is unchanged.
+  static void EnsureUnoptimizedCode(Thread* thread, const Function& function);
+
   // Generates optimized code for function.
   //
   // Returns Error::null() if there is no compilation error.
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index 62d0164..49af1e6 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -101,7 +101,6 @@
     // This is for the DGBox. For the time-being, assume it is similar to the
     // Lego Mindstorm.
     arm_version_ = ARMv5TE;
-    // TODO(zra): Verify with DGLogik that this is correct.
     store_pc_read_offset_ = 12;
   } else if (CpuInfo::FieldContains(kCpuInfoProcessor, "ARMv6") ||
              CpuInfo::FieldContains(kCpuInfoModel, "ARMv6")) {
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index ffae666..a19208a 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -75,7 +75,8 @@
 };
 
 
-const char* Dart::InitOnce(Dart_IsolateCreateCallback create,
+const char* Dart::InitOnce(const uint8_t* vm_isolate_snapshot,
+                           Dart_IsolateCreateCallback create,
                            Dart_IsolateInterruptCallback interrupt,
                            Dart_IsolateUnhandledExceptionCallback unhandled,
                            Dart_IsolateShutdownCallback shutdown,
@@ -138,6 +139,10 @@
       return "SSE2 is required.";
     }
 #endif
+    if (vm_isolate_snapshot != NULL) {
+      // Initializing the VM isolate from a snapshot is not implemented yet.
+      USE(vm_isolate_snapshot);
+    }
     Object::FinalizeVMIsolate(vm_isolate_);
   }
   // There is a planned and known asymmetry here: We enter one scope for the VM
@@ -146,7 +151,7 @@
   Dart_EnterScope();
   Api::InitHandles();
 
-  Isolate::SetCurrent(NULL);  // Unregister the VM isolate from this thread.
+  Thread::ExitIsolate();  // Unregister the VM isolate from this thread.
   Isolate::SetCreateCallback(create);
   Isolate::SetInterruptCallback(interrupt);
   Isolate::SetUnhandledExceptionCallback(unhandled);
@@ -175,7 +180,7 @@
   thread_pool_ = NULL;
 
   // Set the VM isolate as current isolate.
-  Isolate::SetCurrent(vm_isolate_);
+  Thread::EnterIsolate(vm_isolate_);
 
   // There is a planned and known asymmetry here: We exit one scope for the VM
   // isolate to account for the scope that was entered in Dart_InitOnce.
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 135c6b0..470b3ff 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -20,6 +20,7 @@
 class Dart : public AllStatic {
  public:
   static const char* InitOnce(
+      const uint8_t* vm_isolate_snapshot,
       Dart_IsolateCreateCallback create,
       Dart_IsolateInterruptCallback interrupt,
       Dart_IsolateUnhandledExceptionCallback unhandled,
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 6dd2be2..f30f365 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1200,6 +1200,7 @@
 }
 
 DART_EXPORT bool Dart_Initialize(
+    const uint8_t* vm_isolate_snapshot,
     Dart_IsolateCreateCallback create,
     Dart_IsolateInterruptCallback interrupt,
     Dart_IsolateUnhandledExceptionCallback unhandled,
@@ -1209,7 +1210,8 @@
     Dart_FileWriteCallback file_write,
     Dart_FileCloseCallback file_close,
     Dart_EntropySource entropy_source) {
-  const char* err_msg = Dart::InitOnce(create, interrupt, unhandled, shutdown,
+  const char* err_msg = Dart::InitOnce(vm_isolate_snapshot,
+                                       create, interrupt, unhandled, shutdown,
                                        file_open, file_read, file_write,
                                        file_close, entropy_source);
   if (err_msg != NULL) {
@@ -1284,7 +1286,7 @@
                                             const uint8_t* snapshot,
                                             void* callback_data,
                                             char** error) {
-  TRACE_API_CALL(CURRENT_FUNC);
+  CHECK_NO_ISOLATE(Isolate::Current());
   char* isolate_name = BuildIsolateName(script_uri, main);
   Isolate* isolate = Dart::CreateIsolate(isolate_name);
   free(isolate_name);
@@ -1356,7 +1358,10 @@
   CHECK_NO_ISOLATE(Isolate::Current());
   // TODO(16615): Validate isolate parameter.
   Isolate* iso = reinterpret_cast<Isolate*>(isolate);
-  Isolate::SetCurrent(iso);
+  if (iso->mutator_thread() != NULL) {
+    FATAL("Multiple mutators within one isolate is not supported.");
+  }
+  Thread::EnterIsolate(iso);
 }
 
 
@@ -1384,7 +1389,7 @@
 
 DART_EXPORT void Dart_ExitIsolate() {
   CHECK_ISOLATE(Isolate::Current());
-  Isolate::SetCurrent(NULL);
+  Thread::ExitIsolate();
 }
 
 
@@ -1408,16 +1413,25 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_CreateSnapshot(uint8_t** buffer,
-                                            intptr_t* size) {
+DART_EXPORT Dart_Handle Dart_CreateSnapshot(
+    uint8_t** vm_isolate_snapshot_buffer,
+    intptr_t* vm_isolate_snapshot_size,
+    uint8_t** isolate_snapshot_buffer,
+    intptr_t* isolate_snapshot_size) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   TIMERSCOPE(isolate, time_creating_snapshot);
-  if (buffer == NULL) {
-    RETURN_NULL_ERROR(buffer);
+  if (vm_isolate_snapshot_buffer == NULL) {
+    RETURN_NULL_ERROR(vm_isolate_snapshot_buffer);
   }
-  if (size == NULL) {
-    RETURN_NULL_ERROR(size);
+  if (vm_isolate_snapshot_size == NULL) {
+    RETURN_NULL_ERROR(vm_isolate_snapshot_size);
+  }
+  if (isolate_snapshot_buffer == NULL) {
+    RETURN_NULL_ERROR(isolate_snapshot_buffer);
+  }
+  if (isolate_snapshot_size == NULL) {
+    RETURN_NULL_ERROR(isolate_snapshot_size);
   }
   // Finalize all classes if needed.
   Dart_Handle state = Api::CheckAndFinalizePendingClasses(isolate);
@@ -1426,9 +1440,12 @@
   }
   // Since this is only a snapshot the root library should not be set.
   isolate->object_store()->set_root_library(Library::Handle(isolate));
-  FullSnapshotWriter writer(buffer, ApiReallocate);
+  FullSnapshotWriter writer(vm_isolate_snapshot_buffer,
+                            isolate_snapshot_buffer,
+                            ApiReallocate);
   writer.WriteFullSnapshot();
-  *size = writer.BytesWritten();
+  *vm_isolate_snapshot_size = writer.VmIsolateSnapshotSize();
+  *isolate_snapshot_size = writer.IsolateSnapshotSize();
   return Api::Success();
 }
 
@@ -1594,6 +1611,9 @@
 DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle handle) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
+  if (port_id == ILLEGAL_PORT) {
+    return false;
+  }
   const Object& object = Object::Handle(isolate, Api::UnwrapHandle(handle));
   uint8_t* data = NULL;
   MessageWriter writer(&data, &allocator, false);
@@ -1608,6 +1628,11 @@
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   CHECK_CALLBACK_STATE(isolate);
+  if (port_id == ILLEGAL_PORT) {
+    return Api::NewError("%s: illegal port_id %" Pd64 ".",
+                         CURRENT_FUNC,
+                         port_id);
+  }
   return Api::NewHandle(isolate, SendPort::New(port_id));
 }
 
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index c3f9fb5..46f85aa 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -291,7 +291,10 @@
       : saved_isolate_(current_isolate) {
   }
   ~IsolateSaver() {
-    Isolate::SetCurrent(saved_isolate_);
+    // TODO(koda): Audit users; they should know whether they're in an isolate.
+    if (saved_isolate_ != NULL) {
+      Thread::EnterIsolate(saved_isolate_);
+    }
   }
  private:
   Isolate* saved_isolate_;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index fe7c5ea..c439b41 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -20,6 +20,7 @@
 namespace dart {
 
 DECLARE_FLAG(bool, enable_type_checks);
+DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, verify_acquired_data);
 
 TEST_CASE(ErrorHandleBasics) {
@@ -1742,6 +1743,74 @@
 }
 
 
+static const intptr_t kOptExtLength = 16;
+static int8_t opt_data[kOptExtLength] = { 0x01, 0x02, 0x03, 0x04,
+                                          0x05, 0x06, 0x07, 0x08,
+                                          0x09, 0x0a, 0x0b, 0x0c,
+                                          0x0d, 0x0e, 0x0f, 0x10, };
+
+static void OptExternalByteDataNativeFunction(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle external_byte_data = Dart_NewExternalTypedData(
+      Dart_TypedData_kByteData, opt_data, 16);
+  EXPECT_VALID(external_byte_data);
+  EXPECT_EQ(Dart_TypedData_kByteData,
+            Dart_GetTypeOfTypedData(external_byte_data));
+  Dart_SetReturnValue(args, external_byte_data);
+  Dart_ExitScope();
+}
+
+
+static Dart_NativeFunction OptExternalByteDataNativeResolver(
+    Dart_Handle name, int arg_count, bool* auto_setup_scope) {
+  ASSERT(auto_setup_scope != NULL);
+  *auto_setup_scope = false;
+  return &OptExternalByteDataNativeFunction;
+}
+
+
+TEST_CASE(OptimizedExternalByteDataAccess) {
+  const char* kScriptChars =
+      "import 'dart:typed_data';\n"
+      "class Expect {\n"
+      "  static equals(a, b) {\n"
+      "    if (a != b) {\n"
+      "      throw 'not equal. expected: $a, got: $b';\n"
+      "    }\n"
+      "  }\n"
+      "}\n"
+      "ByteData createExternalByteData() native 'CreateExternalByteData';"
+      "access(ByteData a) {"
+      "  Expect.equals(0x04030201, a.getUint32(0, Endianness.LITTLE_ENDIAN));"
+      "  Expect.equals(0x08070605, a.getUint32(4, Endianness.LITTLE_ENDIAN));"
+      "  Expect.equals(0x0c0b0a09, a.getUint32(8, Endianness.LITTLE_ENDIAN));"
+      "  Expect.equals(0x100f0e0d, a.getUint32(12, Endianness.LITTLE_ENDIAN));"
+      "}"
+      "ByteData main() {"
+      "  var length = 16;"
+      "  var a = createExternalByteData();"
+      "  Expect.equals(length, a.lengthInBytes);"
+      "  for (int i = 0; i < 20; i++) {"
+      "    access(a);"
+      "  }"
+      "  return a;"
+      "}\n";
+  // Create a test library and Load up a test script in it.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+
+  Dart_Handle result = Dart_SetNativeResolver(
+      lib, &OptExternalByteDataNativeResolver, NULL);
+  EXPECT_VALID(result);
+
+  // Invoke 'main' function.
+  int old_oct = FLAG_optimization_counter_threshold;
+  FLAG_optimization_counter_threshold = 5;
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  FLAG_optimization_counter_threshold = old_oct;
+}
+
+
 static void TestTypedDataDirectAccess() {
   Dart_Handle str = Dart_NewStringFromCString("junk");
   Dart_Handle byte_array = Dart_NewTypedData(Dart_TypedData_kUint8, 10);
@@ -3619,7 +3688,7 @@
   intptr_t mydata = 12345;
   char* err;
   Dart_Isolate isolate =
-      Dart_CreateIsolate(NULL, NULL, bin::snapshot_buffer,
+      Dart_CreateIsolate(NULL, NULL, bin::isolate_snapshot_buffer,
                          reinterpret_cast<void*>(mydata),
                          &err);
   EXPECT(isolate != NULL);
@@ -7141,6 +7210,20 @@
 }
 
 
+TEST_CASE(IllegalNewSendPort) {
+  Dart_Handle error = Dart_NewSendPort(ILLEGAL_PORT);
+  EXPECT(Dart_IsError(error));
+  EXPECT(Dart_IsApiError(error));
+}
+
+
+TEST_CASE(IllegalPost) {
+  Dart_Handle message = Dart_True();
+  bool success = Dart_Post(ILLEGAL_PORT, message);
+  EXPECT(!success);
+}
+
+
 UNIT_TEST_CASE(NewNativePort) {
   // Create a port with a bogus handler.
   Dart_Port error_port = Dart_NewNativePort("Foo", NULL, true);
@@ -7378,7 +7461,7 @@
     MonitorLocker ml(sync);
     char* error = NULL;
     shared_isolate = Dart_CreateIsolate(NULL, NULL,
-                                        bin::snapshot_buffer,
+                                        bin::isolate_snapshot_buffer,
                                         NULL, &error);
     EXPECT(shared_isolate != NULL);
     Dart_EnterScope();
@@ -7506,7 +7589,7 @@
   // Create an isolate.
   char* err;
   Dart_Isolate isolate = Dart_CreateIsolate(NULL, NULL,
-                                            bin::snapshot_buffer,
+                                            bin::isolate_snapshot_buffer,
                                             my_data, &err);
   if (isolate == NULL) {
     OS::Print("Creation of isolate failed '%s'\n", err);
@@ -7556,7 +7639,7 @@
   // Create an isolate.
   char* err;
   Dart_Isolate isolate = Dart_CreateIsolate(NULL, NULL,
-                                            bin::snapshot_buffer,
+                                            bin::isolate_snapshot_buffer,
                                             NULL, &err);
   if (isolate == NULL) {
     OS::Print("Creation of isolate failed '%s'\n", err);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 3ffa06b..75a2b1c 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -221,7 +221,7 @@
 
 
 bool Debugger::HasEventHandler() {
-  return (event_handler_ != NULL) || Service::NeedsDebuggerEvents();
+  return (event_handler_ != NULL) || Service::NeedsEvents();
 }
 
 
@@ -233,7 +233,7 @@
   //
   // kBreakpointResolved events are handled differently in the vm
   // service, so suppress them here.
-  if (Service::NeedsDebuggerEvents() &&
+  if (Service::NeedsEvents() &&
       (event->type() != DebuggerEvent::kBreakpointResolved)) {
     ServiceEvent service_event(event);
     Service::HandleEvent(&service_event);
@@ -243,7 +243,7 @@
     (*event_handler_)(event);
   }
 
-  if (Service::NeedsDebuggerEvents() && event->IsPauseEvent()) {
+  if (Service::NeedsEvents() && event->IsPauseEvent()) {
     // If we were paused, notify the service that we have resumed.
     ServiceEvent service_event(event->isolate(), ServiceEvent::kResume);
     service_event.set_top_frame(event->top_frame());
@@ -286,7 +286,7 @@
 // than the regular debugger breakpoint notifications.
 static void SendServiceBreakpointEvent(ServiceEvent::EventType type,
                                        SourceBreakpoint* bpt) {
-  if (Service::NeedsDebuggerEvents() /*&& !bpt->IsOneShot()*/) {
+  if (Service::NeedsEvents()) {
     ServiceEvent service_event(Isolate::Current(), type);
     service_event.set_breakpoint(bpt);
     Service::HandleEvent(&service_event);
@@ -1643,8 +1643,7 @@
         for (intptr_t pos = 0; pos < num_functions; pos++) {
           function ^= functions.At(pos);
           ASSERT(!function.IsNull());
-          if (function.is_debuggable() &&
-              FunctionContains(function, script, token_pos)) {
+          if (FunctionContains(function, script, token_pos)) {
             SelectBestFit(&best_fit, &function);
           }
         }
@@ -1656,8 +1655,7 @@
         for (intptr_t pos = 0; pos < num_closures; pos++) {
           function ^= closures.At(pos);
           ASSERT(!function.IsNull());
-          if (function.is_debuggable() &&
-              FunctionContains(function, script, token_pos)) {
+          if (FunctionContains(function, script, token_pos)) {
             SelectBestFit(&best_fit, &function);
           }
         }
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index ef76a00..2727f10 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -4,12 +4,15 @@
 
 #include "vm/deferred_objects.h"
 
+#include "vm/code_patcher.h"
+#include "vm/compiler.h"
 #include "vm/deopt_instructions.h"
 #include "vm/flags.h"
 #include "vm/object.h"
 
 namespace dart {
 
+DECLARE_FLAG(bool, trace_deoptimization);
 DECLARE_FLAG(bool, trace_deoptimization_verbose);
 
 
@@ -97,6 +100,112 @@
 }
 
 
+void DeferredRetAddr::Materialize(DeoptContext* deopt_context) {
+  Function& function = Function::Handle(deopt_context->zone());
+  function ^= deopt_context->ObjectAt(index_);
+  Compiler::EnsureUnoptimizedCode(deopt_context->thread(), function);
+  const Code& code =
+      Code::Handle(deopt_context->zone(), function.unoptimized_code());
+  // Check that deopt_id exists.
+  // TODO(vegorov): verify after deoptimization targets as well.
+#ifdef DEBUG
+  ASSERT(Isolate::IsDeoptAfter(deopt_id_) ||
+         (code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kDeopt) != 0));
+#endif
+
+  uword continue_at_pc = code.GetPcForDeoptId(deopt_id_,
+                                              RawPcDescriptors::kDeopt);
+  ASSERT(continue_at_pc != 0);
+  uword* dest_addr = reinterpret_cast<uword*>(slot());
+  *dest_addr = continue_at_pc;
+
+  if (FLAG_trace_deoptimization_verbose) {
+    OS::PrintErr("materializing return addr at 0x%" Px ": 0x%" Px "\n",
+                 reinterpret_cast<uword>(slot()), continue_at_pc);
+  }
+
+  uword pc = code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kIcCall);
+  if (pc != 0) {
+    // If the deoptimization happened at an IC call, update the IC data
+    // to avoid repeated deoptimization at the same site next time around.
+    ICData& ic_data = ICData::Handle();
+    CodePatcher::GetInstanceCallAt(pc, code, &ic_data);
+    if (!ic_data.IsNull()) {
+      ic_data.AddDeoptReason(deopt_context->deopt_reason());
+    }
+  } else {
+    if (deopt_context->HasDeoptFlag(ICData::kHoisted)) {
+      // Prevent excessive deoptimization.
+      function.set_allows_hoisting_check_class(false);
+    }
+
+    if (deopt_context->HasDeoptFlag(ICData::kGeneralized)) {
+      function.set_allows_bounds_check_generalization(false);
+    }
+  }
+}
+
+
+void DeferredPcMarker::Materialize(DeoptContext* deopt_context) {
+  uword* dest_addr = reinterpret_cast<uword*>(slot());
+  Function& function = Function::Handle(deopt_context->zone());
+  function ^= deopt_context->ObjectAt(index_);
+  if (function.IsNull()) {
+    // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0.
+    *dest_addr = 0;
+    return;
+  }
+  Compiler::EnsureUnoptimizedCode(deopt_context->thread(), function);
+  const Code& code =
+      Code::Handle(deopt_context->zone(), function.unoptimized_code());
+  ASSERT(!code.IsNull());
+  ASSERT(function.HasCode());
+  const intptr_t pc_marker =
+      code.EntryPoint() + Assembler::EntryPointToPcMarkerOffset();
+  *dest_addr = pc_marker;
+
+  if (FLAG_trace_deoptimization_verbose) {
+    OS::PrintErr("materializing pc marker at 0x%" Px ": %s, %s\n",
+                 reinterpret_cast<uword>(slot()), code.ToCString(),
+                 function.ToCString());
+  }
+
+  // Increment the deoptimization counter. This effectively increments each
+  // function occurring in the optimized frame.
+  function.set_deoptimization_counter(function.deoptimization_counter() + 1);
+  if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
+    OS::PrintErr("Deoptimizing %s (count %d)\n",
+        function.ToFullyQualifiedCString(),
+        function.deoptimization_counter());
+  }
+  // Clear invocation counter so that hopefully the function gets reoptimized
+  // only after more feedback has been collected.
+  function.set_usage_counter(0);
+  if (function.HasOptimizedCode()) {
+    function.SwitchToUnoptimizedCode();
+  }
+}
+
+
+void DeferredPp::Materialize(DeoptContext* deopt_context) {
+  Function& function = Function::Handle(deopt_context->zone());
+  function ^= deopt_context->ObjectAt(index_);
+  ASSERT(!function.IsNull());
+  Compiler::EnsureUnoptimizedCode(deopt_context->thread(), function);
+  const Code& code =
+      Code::Handle(deopt_context->zone(), function.unoptimized_code());
+  ASSERT(!code.IsNull());
+  ASSERT(code.ObjectPool() != Object::null());
+  *slot() = code.ObjectPool();
+
+  if (FLAG_trace_deoptimization_verbose) {
+    OS::PrintErr("materializing pp at 0x%" Px ": 0x%" Px "\n",
+                 reinterpret_cast<uword>(slot()),
+                 reinterpret_cast<uword>(code.ObjectPool()));
+  }
+}
+
+
 RawObject* DeferredObject::object() {
   if (object_ == NULL) {
     Create();
diff --git a/runtime/vm/deferred_objects.h b/runtime/vm/deferred_objects.h
index 0077388..35556f8 100644
--- a/runtime/vm/deferred_objects.h
+++ b/runtime/vm/deferred_objects.h
@@ -140,6 +140,58 @@
 };
 
 
+class DeferredRetAddr : public DeferredSlot {
+ public:
+  DeferredRetAddr(intptr_t index,
+                  intptr_t deopt_id,
+                  RawObject** slot,
+                  DeferredSlot* next)
+      : DeferredSlot(slot, next), index_(index), deopt_id_(deopt_id) { }
+
+  virtual void Materialize(DeoptContext* deopt_context);
+
+  intptr_t index() const { return index_; }
+
+ private:
+  const intptr_t index_;
+  const intptr_t deopt_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeferredRetAddr);
+};
+
+
+class DeferredPcMarker : public DeferredSlot {
+ public:
+  DeferredPcMarker(intptr_t index, RawObject** slot, DeferredSlot* next)
+      : DeferredSlot(slot, next), index_(index) { }
+
+  virtual void Materialize(DeoptContext* deopt_context);
+
+  intptr_t index() const { return index_; }
+
+ private:
+  const intptr_t index_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeferredPcMarker);
+};
+
+
+class DeferredPp : public DeferredSlot {
+ public:
+  DeferredPp(intptr_t index, RawObject** slot, DeferredSlot* next)
+      : DeferredSlot(slot, next), index_(index) { }
+
+  virtual void Materialize(DeoptContext* deopt_context);
+
+  intptr_t index() const { return index_; }
+
+ private:
+  const intptr_t index_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeferredPp);
+};
+
+
 // Describes an object which allocation was removed by AllocationSinking pass.
 // Arguments for materialization are stored as a part of expression stack
 // for the bottommost deoptimized frame so that GC could discover them.
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 26b0066..401f2ba 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -6,6 +6,7 @@
 
 #include "vm/assembler.h"
 #include "vm/code_patcher.h"
+#include "vm/compiler.h"
 #include "vm/intermediate_language.h"
 #include "vm/locations.h"
 #include "vm/parser.h"
@@ -27,7 +28,7 @@
                            intptr_t* cpu_registers)
     : code_(code.raw()),
       object_table_(code.object_table()),
-      deopt_info_(DeoptInfo::null()),
+      deopt_info_(TypedData::null()),
       dest_frame_is_allocated_(false),
       dest_frame_(NULL),
       dest_frame_size_(0),
@@ -43,7 +44,7 @@
       deferred_slots_(NULL),
       deferred_objects_count_(0),
       deferred_objects_(NULL) {
-  const DeoptInfo& deopt_info = DeoptInfo::Handle(
+  const TypedData& deopt_info = TypedData::Handle(
       code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_));
   ASSERT(!deopt_info.IsNull());
   deopt_info_ = deopt_info.raw();
@@ -80,7 +81,7 @@
   }
   caller_fp_ = GetSourceFp();
 
-  dest_frame_size_ = deopt_info.FrameSize();
+  dest_frame_size_ = DeoptInfo::FrameSize(deopt_info);
 
   if (dest_options == kDestIsAllocated) {
     dest_frame_ = new intptr_t[dest_frame_size_];
@@ -203,7 +204,6 @@
     case DeoptInstr::kCallerPc:
       return false;
 
-    case DeoptInstr::kSuffix:
     case DeoptInstr::kMaterializeObject:
     default:
       // We should not encounter these instructions when filling stack slots.
@@ -217,15 +217,15 @@
 
 void DeoptContext::FillDestFrame() {
   const Code& code = Code::Handle(code_);
-  const DeoptInfo& deopt_info = DeoptInfo::Handle(deopt_info_);
+  const TypedData& deopt_info = TypedData::Handle(deopt_info_);
 
-  const intptr_t len = deopt_info.TranslationLength();
-  GrowableArray<DeoptInstr*> deopt_instructions(len);
+  GrowableArray<DeoptInstr*> deopt_instructions;
   const Array& deopt_table = Array::Handle(code.deopt_info_array());
   ASSERT(!deopt_table.IsNull());
-  deopt_info.ToInstructions(deopt_table, &deopt_instructions);
+  DeoptInfo::Unpack(deopt_table, deopt_info, &deopt_instructions);
 
-  const intptr_t frame_size = deopt_info.FrameSize();
+  const intptr_t len = deopt_instructions.length();
+  const intptr_t frame_size = dest_frame_size_;
 
   // For now, we never place non-objects in the deoptimized frame if
   // the destination frame is a copy.  This allows us to copy the
@@ -240,7 +240,8 @@
   // described as part of the expression stack for the bottom-most deoptimized
   // frame. They will be used during materialization and removed from the stack
   // right before control switches to the unoptimized code.
-  const intptr_t num_materializations = deopt_info.NumMaterializations();
+  const intptr_t num_materializations =
+      DeoptInfo::NumMaterializations(deopt_instructions);
   PrepareForDeferredMaterialization(num_materializations);
   for (intptr_t from_index = 0, to_index = kDartFrameFixedSize;
        from_index < num_materializations;
@@ -377,34 +378,9 @@
   }
 
   void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
-    Code& code = Code::Handle(deopt_context->zone());
-    code ^= deopt_context->ObjectAt(object_table_index_);
-    ASSERT(!code.IsNull());
-    uword continue_at_pc = code.GetPcForDeoptId(deopt_id_,
-                                                RawPcDescriptors::kDeopt);
-    ASSERT(continue_at_pc != 0);
-    *dest_addr = continue_at_pc;
-
-    uword pc = code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::kIcCall);
-    if (pc != 0) {
-      // If the deoptimization happened at an IC call, update the IC data
-      // to avoid repeated deoptimization at the same site next time around.
-      ICData& ic_data = ICData::Handle();
-      CodePatcher::GetInstanceCallAt(pc, code, &ic_data);
-      if (!ic_data.IsNull()) {
-        ic_data.AddDeoptReason(deopt_context->deopt_reason());
-      }
-    } else {
-      const Function& function = Function::Handle(code.function());
-      if (deopt_context->HasDeoptFlag(ICData::kHoisted)) {
-        // Prevent excessive deoptimization.
-        function.set_allows_hoisting_check_class(false);
-      }
-
-      if (deopt_context->HasDeoptFlag(ICData::kGeneralized)) {
-        function.set_allows_bounds_check_generalization(false);
-      }
-    }
+    *dest_addr = Smi::RawValue(0);
+    deopt_context->DeferRetAddrMaterialization(
+        object_table_index_, deopt_id_, dest_addr);
   }
 
   intptr_t object_table_index() const { return object_table_index_; }
@@ -641,33 +617,9 @@
   }
 
   void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
-    Code& code = Code::Handle(deopt_context->zone());
-    code ^= deopt_context->ObjectAt(object_table_index_);
-    if (code.IsNull()) {
-      // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0.
-      *dest_addr = 0;
-      return;
-    }
-    const Function& function =
-        Function::Handle(deopt_context->zone(), code.function());
-    ASSERT(function.HasCode());
-    const intptr_t pc_marker =
-        code.EntryPoint() + Assembler::EntryPointToPcMarkerOffset();
-    *dest_addr = pc_marker;
-    // Increment the deoptimization counter. This effectively increments each
-    // function occurring in the optimized frame.
-    function.set_deoptimization_counter(function.deoptimization_counter() + 1);
-    if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
-      OS::PrintErr("Deoptimizing %s (count %d)\n",
-          function.ToFullyQualifiedCString(),
-          function.deoptimization_counter());
-    }
-    // Clear invocation counter so that hopefully the function gets reoptimized
-    // only after more feedback has been collected.
-    function.set_usage_counter(0);
-    if (function.HasOptimizedCode()) {
-      function.SwitchToUnoptimizedCode();
-    }
+    *dest_addr = Smi::RawValue(0);
+    deopt_context->DeferPcMarkerMaterialization(
+        object_table_index_, dest_addr);
   }
 
  private:
@@ -695,11 +647,9 @@
   }
 
   void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
-    Code& code = Code::Handle(deopt_context->zone());
-    code ^= deopt_context->ObjectAt(object_table_index_);
-    ASSERT(!code.IsNull());
-    const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool());
-    *dest_addr = pp;
+    *dest_addr = Smi::RawValue(0);
+    deopt_context->DeferPpMaterialization(object_table_index_,
+        reinterpret_cast<RawObject**>(dest_addr));
   }
 
  private:
@@ -763,56 +713,6 @@
 };
 
 
-// Deoptimization instruction that indicates the rest of this DeoptInfo is a
-// suffix of another one.  The suffix contains the info number (0 based
-// index in the deopt table of the DeoptInfo to share) and the length of the
-// suffix.
-class DeoptSuffixInstr : public DeoptInstr {
- public:
-  DeoptSuffixInstr(intptr_t info_number, intptr_t suffix_length)
-      : info_number_(info_number), suffix_length_(suffix_length) {
-    ASSERT(info_number >= 0);
-    ASSERT(suffix_length >= 0);
-  }
-
-  explicit DeoptSuffixInstr(intptr_t source_index)
-      : info_number_(InfoNumber::decode(source_index)),
-        suffix_length_(SuffixLength::decode(source_index)) {
-  }
-
-  virtual intptr_t source_index() const {
-    return InfoNumber::encode(info_number_) |
-        SuffixLength::encode(suffix_length_);
-  }
-  virtual DeoptInstr::Kind kind() const { return kSuffix; }
-
-  virtual const char* ArgumentsToCString() const {
-    return Thread::Current()->zone()->PrintToString(
-        "%" Pd ":%" Pd, info_number_, suffix_length_);
-  }
-
-  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
-    // The deoptimization info is uncompressed by translating away suffixes
-    // before executing the instructions.
-    UNREACHABLE();
-  }
-
- private:
-  // Static decoder functions in DeoptInstr have access to the bitfield
-  // definitions.
-  friend class DeoptInstr;
-
-  static const intptr_t kFieldWidth = kBitsPerWord / 2;
-  class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { };
-  class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
-
-  const intptr_t info_number_;
-  const intptr_t suffix_length_;
-
-  DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr);
-};
-
-
 // Write reference to a materialized object with the given index into the
 // stack slot.
 class DeoptMaterializedObjectRefInstr : public DeoptInstr {
@@ -873,13 +773,6 @@
 };
 
 
-intptr_t DeoptInstr::DecodeSuffix(intptr_t source_index,
-                                  intptr_t* info_number) {
-  *info_number = DeoptSuffixInstr::InfoNumber::decode(source_index);
-  return DeoptSuffixInstr::SuffixLength::decode(source_index);
-}
-
-
 uword DeoptInstr::GetRetAddress(DeoptInstr* instr,
                                 const Array& object_table,
                                 Code* code) {
@@ -890,8 +783,11 @@
   // from the simulator.
   ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id()));
   ASSERT(!object_table.IsNull());
+  Function& function = Function::Handle();
+  function ^= object_table.At(ret_address_instr->object_table_index());
   ASSERT(code != NULL);
-  *code ^= object_table.At(ret_address_instr->object_table_index());
+  Compiler::EnsureUnoptimizedCode(Thread::Current(), function);
+  *code ^= function.unoptimized_code();
   ASSERT(!code->IsNull());
   uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(),
                                     RawPcDescriptors::kDeopt);
@@ -935,8 +831,6 @@
       return new DeoptCallerPpInstr();
     case kCallerPc:
       return new DeoptCallerPcInstr();
-    case kSuffix:
-      return new DeoptSuffixInstr(source_index);
     case kMaterializedObjectRef:
       return new DeoptMaterializedObjectRefInstr(source_index);
     case kMaterializeObject:
@@ -980,8 +874,6 @@
       return "callerpp";
     case kCallerPc:
       return "callerpc";
-    case kSuffix:
-      return "suffix";
     case kMaterializedObjectRef:
       return "ref";
     case kMaterializeObject:
@@ -1083,33 +975,27 @@
   }
 }
 
-void DeoptInfoBuilder::AddReturnAddress(const Code& code,
+void DeoptInfoBuilder::AddReturnAddress(const Function& function,
                                         intptr_t deopt_id,
                                         intptr_t dest_index) {
-  // Check that deopt_id exists.
-  // TODO(vegorov): verify after deoptimization targets as well.
-#ifdef DEBUG
-  ASSERT(Isolate::IsDeoptAfter(deopt_id) ||
-         (code.GetPcForDeoptId(deopt_id, RawPcDescriptors::kDeopt) != 0));
-#endif
-  const intptr_t object_table_index = FindOrAddObjectInTable(code);
+  const intptr_t object_table_index = FindOrAddObjectInTable(function);
   ASSERT(dest_index == FrameSize());
   instructions_.Add(
       new(zone()) DeoptRetAddressInstr(object_table_index, deopt_id));
 }
 
 
-void DeoptInfoBuilder::AddPcMarker(const Code& code,
+void DeoptInfoBuilder::AddPcMarker(const Function& function,
                                    intptr_t dest_index) {
-  intptr_t object_table_index = FindOrAddObjectInTable(code);
+  intptr_t object_table_index = FindOrAddObjectInTable(function);
   ASSERT(dest_index == FrameSize());
   instructions_.Add(new(zone()) DeoptPcMarkerInstr(object_table_index));
 }
 
 
-void DeoptInfoBuilder::AddPp(const Code& code,
+void DeoptInfoBuilder::AddPp(const Function& function,
                              intptr_t dest_index) {
-  intptr_t object_table_index = FindOrAddObjectInTable(code);
+  intptr_t object_table_index = FindOrAddObjectInTable(function);
   ASSERT(dest_index == FrameSize());
   instructions_.Add(new(zone()) DeoptPpInstr(object_table_index));
 }
@@ -1269,19 +1155,22 @@
 }
 
 
-RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
-  // TODO(vegorov): enable compression of deoptimization info containing object
-  // materialization instructions.
-  const bool disable_compression =
-      (instructions_[0]->kind() == DeoptInstr::kMaterializeObject);
+static uint8_t* ZoneReAlloc(uint8_t* ptr,
+                            intptr_t old_size,
+                            intptr_t new_size) {
+  return Isolate::Current()->current_zone()->Realloc<uint8_t>(
+      ptr, old_size, new_size);
+}
 
+
+RawTypedData* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
   intptr_t length = instructions_.length();
 
   // Count the number of instructions that are a shared suffix of some deopt
   // info already written.
   TrieNode* suffix = trie_root_;
   intptr_t suffix_length = 0;
-  if (FLAG_compress_deopt_info && !disable_compression) {
+  if (FLAG_compress_deopt_info) {
     for (intptr_t i = length - 1; i >= 0; --i) {
       TrieNode* node = suffix->FindChild(*instructions_[i]);
       if (node == NULL) break;
@@ -1290,33 +1179,51 @@
     }
   }
 
+
   // Allocate space for the translation.  If the shared suffix is longer
   // than one instruction, we replace it with a single suffix instruction.
-  if (suffix_length > 1) length -= (suffix_length - 1);
-  const DeoptInfo& deopt_info =
-      DeoptInfo::Handle(zone(), DeoptInfo::New(length));
+  const bool use_suffix = suffix_length > 1;
+  if (use_suffix) {
+    length -= (suffix_length - 1);
+  }
+
+  uint8_t* buffer;
+  typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
+  WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize);
+
+  Writer::Write(&stream, FrameSize());
+
+  if (use_suffix) {
+    Writer::Write(&stream, suffix_length);
+    Writer::Write(&stream, suffix->info_number());
+  } else {
+    Writer::Write(&stream, 0);
+  }
 
   // Write the unshared instructions and build their sub-tree.
-  TrieNode* node = NULL;
-  intptr_t write_count = (suffix_length > 1) ? length - 1 : length;
-  for (intptr_t i = 0; i < write_count; ++i) {
+  TrieNode* node = use_suffix ? suffix : trie_root_;
+  const intptr_t write_count = use_suffix ? length - 1 : length;
+  for (intptr_t i = write_count - 1; i >= 0; --i) {
     DeoptInstr* instr = instructions_[i];
-    deopt_info.SetAt(i, instr->kind(), instr->source_index());
-    TrieNode* child = node;
-    node = new(zone()) TrieNode(instr, current_info_number_);
+    Writer::Write(&stream, instr->kind());
+    Writer::Write(&stream, instr->source_index());
+
+    TrieNode* child = new(zone()) TrieNode(instr, current_info_number_);
     node->AddChild(child);
+    node = child;
   }
 
-  if (suffix_length > 1) {
-    suffix->AddChild(node);
-    DeoptInstr* instr =
-        new(zone()) DeoptSuffixInstr(suffix->info_number(), suffix_length);
-    deopt_info.SetAt(length - 1, instr->kind(), instr->source_index());
-  } else {
-    trie_root_->AddChild(node);
+  const TypedData& deopt_info = TypedData::Handle(zone(), TypedData::New(
+      kTypedDataUint8ArrayCid, stream.bytes_written(), Heap::kOld));
+  {
+    NoSafepointScope no_safepoint;
+    memmove(deopt_info.DataAddr(0),
+            stream.buffer(),
+            stream.bytes_written());
   }
 
-  ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table));
+  ASSERT(DeoptInfo::VerifyDecompression(
+      instructions_, deopt_table, deopt_info));
   instructions_.Clear();
   materializations_.Clear();
   frame_start_ = -1;
@@ -1333,7 +1240,7 @@
 void DeoptTable::SetEntry(const Array& table,
                           intptr_t index,
                           const Smi& offset,
-                          const DeoptInfo& info,
+                          const TypedData& info,
                           const Smi& reason) {
   ASSERT((table.Length() % kEntrySize) == 0);
   intptr_t i = index * kEntrySize;
@@ -1352,7 +1259,7 @@
 void DeoptTable::GetEntry(const Array& table,
                           intptr_t index,
                           Smi* offset,
-                          DeoptInfo* info,
+                          TypedData* info,
                           Smi* reason) {
   intptr_t i = index * kEntrySize;
   *offset ^= table.At(i);
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 6154e06..f2927f5 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -85,6 +85,7 @@
     dest_frame_ = dest_frame;
   }
 
+  Thread* thread() const { return thread_; }
   Zone* zone() const { return thread_->zone(); }
 
   intptr_t source_frame_size() const { return source_frame_size_; }
@@ -97,7 +98,7 @@
     return (deopt_flags_ & flag) != 0;
   }
 
-  RawDeoptInfo* deopt_info() const { return deopt_info_; }
+  RawTypedData* deopt_info() const { return deopt_info_; }
 
   // Fills the destination frame but defers materialization of
   // objects.
@@ -153,6 +154,27 @@
         deferred_slots_);
   }
 
+  void DeferRetAddrMaterialization(intptr_t index,
+                                   intptr_t deopt_id,
+                                   intptr_t* slot) {
+    deferred_slots_ = new DeferredRetAddr(
+        index,
+        deopt_id,
+        reinterpret_cast<RawObject**>(slot),
+        deferred_slots_);
+  }
+
+  void DeferPcMarkerMaterialization(intptr_t index, intptr_t* slot) {
+    deferred_slots_ = new DeferredPcMarker(
+        index,
+        reinterpret_cast<RawObject**>(slot),
+        deferred_slots_);
+  }
+
+  void DeferPpMaterialization(intptr_t index, RawObject** slot) {
+    deferred_slots_ = new DeferredPp(index, slot, deferred_slots_);
+  }
+
   DeferredObject* GetDeferredObject(intptr_t idx) const {
     return deferred_objects_[idx];
   }
@@ -184,7 +206,7 @@
 
   RawCode* code_;
   RawArray* object_table_;
-  RawDeoptInfo* deopt_info_;
+  RawTypedData* deopt_info_;
   bool dest_frame_is_allocated_;
   intptr_t* dest_frame_;
   intptr_t dest_frame_size_;
@@ -235,7 +257,6 @@
     kCallerFp,
     kCallerPp,
     kCallerPc,
-    kSuffix,
     kMaterializedObjectRef,
     kMaterializeObject
   };
@@ -263,10 +284,6 @@
     return (kind() == other.kind()) && (source_index() == other.source_index());
   }
 
-  // Decode the payload of a suffix command.  Return the suffix length and
-  // set the output parameter info_number to the index of the shared suffix.
-  static intptr_t DecodeSuffix(intptr_t source_index, intptr_t* info_number);
-
   // Get the code and return address which is encoded in this
   // kRetAfterAddress deopt instruction.
   static uword GetRetAddress(DeoptInstr* instr,
@@ -409,14 +426,14 @@
   const GrowableObjectArray& object_table() { return object_table_; }
 
   // Return address before instruction.
-  void AddReturnAddress(const Code& code,
+  void AddReturnAddress(const Function& function,
                         intptr_t deopt_id,
                         intptr_t dest_index);
 
   // Copy from optimized frame to unoptimized.
   void AddCopy(Value* value, const Location& source_loc, intptr_t dest_index);
-  void AddPcMarker(const Code& code, intptr_t dest_index);
-  void AddPp(const Code& code, intptr_t dest_index);
+  void AddPcMarker(const Function& function, intptr_t dest_index);
+  void AddPp(const Function& function, intptr_t dest_index);
   void AddCallerFp(intptr_t dest_index);
   void AddCallerPp(intptr_t dest_index);
   void AddCallerPc(intptr_t dest_index);
@@ -435,7 +452,7 @@
   // Returns the index of the next stack slot. Used for verification.
   intptr_t EmitMaterializationArguments(intptr_t dest_index);
 
-  RawDeoptInfo* CreateDeoptInfo(const Array& deopt_table);
+  RawTypedData* CreateDeoptInfo(const Array& deopt_table);
 
   // Mark the actual start of the frame description after all materialization
   // instructions were emitted. Used for verification purposes.
@@ -486,6 +503,8 @@
 // stored in an Array in the heap.  It consists of triples of (PC offset,
 // info, reason).  Elements of each entry are stored consecutively in the
 // array.
+// TODO(vegorov): consider compressing the whole table into a single TypedData
+// object.
 class DeoptTable : public AllStatic {
  public:
   // Return the array size in elements for a given number of table entries.
@@ -495,7 +514,7 @@
   static void SetEntry(const Array& table,
                        intptr_t index,
                        const Smi& offset,
-                       const DeoptInfo& info,
+                       const TypedData& info,
                        const Smi& reason_and_flags);
 
   // Return the length of the table in entries.
@@ -506,7 +525,7 @@
   static void GetEntry(const Array& table,
                        intptr_t index,
                        Smi* offset,
-                       DeoptInfo* info,
+                       TypedData* info,
                        Smi* reason_and_flags);
 
   static RawSmi* EncodeReasonAndFlags(ICData::DeoptReasonId reason,
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index 5e95d92..7ab11d4 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -696,12 +696,6 @@
       }
     } else if (instr->IsMultiplyOrSyncPrimitive()) {
       if (instr->Bit(24) == 0) {
-        if ((TargetCPUFeatures::arm_version() != ARMv7) &&
-            (instr->Bits(21, 3) != 0)) {
-          // mla ... smlal only supported on armv7.
-          Unknown(instr);
-          return;
-        }
         // multiply instructions
         switch (instr->Bits(21, 3)) {
           case 0: {
@@ -715,11 +709,19 @@
             break;
           }
           case 2: {
+            if (TargetCPUFeatures::arm_version() == ARMv5TE) {
+              Unknown(instr);
+              return;
+            }
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             Format(instr, "umaal'cond's 'rd, 'rn, 'rm, 'rs");
             break;
           }
           case 3: {
+            if (TargetCPUFeatures::arm_version() != ARMv7) {
+              Unknown(instr);
+              return;
+            }
             // Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
             Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
             break;
@@ -739,17 +741,17 @@
             Format(instr, "smull'cond's 'rd, 'rn, 'rm, 'rs");
             break;
           }
-          case 7: {
-            // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
-            Format(instr, "smlal'cond's 'rd, 'rn, 'rm, 'rs");
-            break;
-          }
           default: {
             Unknown(instr);  // Not used.
             break;
           }
         }
       } else {
+        if (TargetCPUFeatures::arm_version() == ARMv5TE) {
+          // strex and ldrex are only supported after ARMv6.
+          Unknown(instr);
+          return;
+        }
         // synchronization primitives
         switch (instr->Bits(20, 4)) {
           case 8: {
@@ -1470,7 +1472,8 @@
   Instr* instr = Instr::At(pc);
 
   if (instr->ConditionField() == kSpecialCondition) {
-    if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
+    if ((instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) &&
+        (TargetCPUFeatures::arm_version() != ARMv5TE)) {
       Format(instr, "clrex");
     } else {
       if (instr->IsSIMDDataProcessing()) {
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index c305ad1..6aec343 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -463,8 +463,6 @@
 void Flags::PrintJSON(JSONStream* js) {
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "FlagList");
-  jsobj.AddProperty("id", "flags");
-
   {
     JSONArray jsarr(&jsobj, "unmodifiedFlags");
     for (intptr_t i = 0; i < num_flags_; ++i) {
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index db4b32e..616807c 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2382,6 +2382,8 @@
     node->InitializerAt(i)->Visit(&for_value);
     Append(for_value);
     Value* temp_val = for_value.value();
+    ASSERT(!node->TempAt(i)->HasIndex() ||
+           (node->TempAt(i)->index() == GetCurrentTempLocalIndex()));
     node->TempAt(i)->set_index(GetCurrentTempLocalIndex());
     Do(new(Z) PushTempInstr(temp_val));
     owner()->AllocateTemp();
@@ -3436,10 +3438,11 @@
 void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) {
   // If the right hand side is an expression that does not contain
   // a safe point for the debugger to stop, add an explicit stub
-  // call. Exception: don't do this when assigning to internal variables,
-  // or for generated code that has no source position.
+  // call. Exception: don't do this when assigning to or from internal
+  // variables, or for generated code that has no source position.
   if ((node->value()->IsLiteralNode() ||
-      node->value()->IsLoadLocalNode() ||
+      (node->value()->IsLoadLocalNode() &&
+          !node->value()->AsLoadLocalNode()->local().IsInternal()) ||
       node->value()->IsClosureNode()) &&
       !node->local().IsInternal() &&
       (node->token_pos() != Scanner::kNoSourcePos)) {
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 146b2ec..04141c1 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -862,7 +862,7 @@
     const Array& array =
         Array::Handle(Array::New(deopt_info_table_size, Heap::kOld));
     Smi& offset = Smi::Handle();
-    DeoptInfo& info = DeoptInfo::Handle();
+    TypedData& info = TypedData::Handle();
     Smi& reason_and_flags = Smi::Handle();
     for (intptr_t i = 0; i < deopt_infos_.length(); i++) {
       offset = Smi::New(deopt_infos_[i]->pc_offset());
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 31b6176..9fa51ad 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -126,7 +126,7 @@
   }
   virtual ~CompilerDeoptInfo() { }
 
-  RawDeoptInfo* CreateDeoptInfo(FlowGraphCompiler* compiler,
+  RawTypedData* CreateDeoptInfo(FlowGraphCompiler* compiler,
                                 DeoptInfoBuilder* builder,
                                 const Array& deopt_table);
 
@@ -279,6 +279,7 @@
   static bool SupportsUnboxedMints();
   static bool SupportsSinCos();
   static bool SupportsUnboxedSimd128();
+  static bool SupportsHardwareDivision();
 
   // Accessors.
   Assembler* assembler() const { return assembler_; }
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 8f93df9..5ea34ba 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -59,6 +59,11 @@
 }
 
 
+bool FlowGraphCompiler::SupportsHardwareDivision() {
+  return TargetCPUFeatures::can_divide();
+}
+
+
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
@@ -73,12 +78,12 @@
 }
 
 
-RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder,
                                                  const Array& deopt_table) {
   if (deopt_env_ == NULL) {
     ++builder->current_info_number_;
-    return DeoptInfo::null();
+    return TypedData::null();
   }
 
   intptr_t stack_height = compiler->StackSize();
@@ -95,12 +100,14 @@
   builder->MarkFrameStart();
 
   // Current PP, FP, and PC.
-  builder->AddPp(current->code(), slot_ix++);
+  builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
+  builder->AddReturnAddress(Function::Handle(current->code().function()),
+                            deopt_id(),
+                            slot_ix++);
 
   // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
-  builder->AddPcMarker(Code::Handle(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
 
   // Emit all values that are needed for materialization as a part of the
   // expression stack for the bottom-most frame. This guarantees that GC
@@ -118,17 +125,18 @@
   current = current->outer();
   while (current != NULL) {
     // PP, FP, and PC.
-    builder->AddPp(current->code(), slot_ix++);
+    builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(current->code(),
+    builder->AddReturnAddress(Function::Handle(current->code().function()),
                               Isolate::ToDeoptAfter(current->deopt_id()),
                               slot_ix++);
 
     // PC marker.
-    builder->AddPcMarker(previous->code(), slot_ix++);
+    builder->AddPcMarker(Function::Handle(previous->code().function()),
+                         slot_ix++);
 
     // The values of outgoing arguments can be changed from the inlined call so
     // we must read them from the previous environment.
@@ -160,7 +168,8 @@
   builder->AddCallerPc(slot_ix++);
 
   // PC marker.
-  builder->AddPcMarker(previous->code(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(previous->code().function()),
+                       slot_ix++);
 
   // For the outermost environment, set the incoming arguments.
   for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
@@ -1263,9 +1272,6 @@
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
-#if defined(DEBUG)
-  __ LoadImmediate(R4, kInvalidObjectPointer);
-#endif
 }
 
 
@@ -1348,10 +1354,6 @@
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
   __ Drop(argument_count);
-#if defined(DEBUG)
-  __ LoadImmediate(R4, kInvalidObjectPointer);
-  __ LoadImmediate(R5, kInvalidObjectPointer);
-#endif
 }
 
 
@@ -1428,13 +1430,6 @@
                            Isolate::kNoDeoptId,
                            token_pos);
     }
-#if defined(DEBUG)
-    if (!is_optimizing()) {
-      // Do this *after* adding the pc descriptor!
-      __ LoadImmediate(R4, kInvalidObjectPointer);
-      __ LoadImmediate(R5, kInvalidObjectPointer);
-    }
-#endif
     // Stub returns result in flags (result of a cmp, we need Z computed).
     __ Pop(right);
     __ Pop(left);
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 1e1bb66..1d684f6 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -55,6 +55,11 @@
 }
 
 
+bool FlowGraphCompiler::SupportsHardwareDivision() {
+  return true;
+}
+
+
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
@@ -69,12 +74,12 @@
 }
 
 
-RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder,
                                                  const Array& deopt_table) {
   if (deopt_env_ == NULL) {
     ++builder->current_info_number_;
-    return DeoptInfo::null();
+    return TypedData::null();
   }
 
   intptr_t stack_height = compiler->StackSize();
@@ -91,10 +96,12 @@
   builder->MarkFrameStart();
 
   // Current PP, FP, and PC.
-  builder->AddPp(current->code(), slot_ix++);
-  builder->AddPcMarker(Code::Handle(), slot_ix++);
+  builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
+  builder->AddReturnAddress(Function::Handle(current->code().function()),
+                            deopt_id(),
+                            slot_ix++);
 
   // Emit all values that are needed for materialization as a part of the
   // expression stack for the bottom-most frame. This guarantees that GC
@@ -112,13 +119,14 @@
   current = current->outer();
   while (current != NULL) {
     // PP, FP, and PC.
-    builder->AddPp(current->code(), slot_ix++);
-    builder->AddPcMarker(previous->code(), slot_ix++);
+    builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
+    builder->AddPcMarker(Function::Handle(previous->code().function()),
+                         slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(current->code(),
+    builder->AddReturnAddress(Function::Handle(current->code().function()),
                               Isolate::ToDeoptAfter(current->deopt_id()),
                               slot_ix++);
 
@@ -149,7 +157,8 @@
   // For the outermost environment, set caller PC, caller PP, and caller FP.
   builder->AddCallerPp(slot_ix++);
   // PC marker.
-  builder->AddPcMarker(previous->code(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(previous->code().function()),
+                       slot_ix++);
   builder->AddCallerFp(slot_ix++);
   builder->AddCallerPc(slot_ix++);
 
@@ -1244,9 +1253,6 @@
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
-#if defined(DEBUG)
-  __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP);
-#endif
 }
 
 
@@ -1328,10 +1334,6 @@
                    &target_label,
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
-#if defined(DEBUG)
-  __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP);
-  __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP);
-#endif
   __ Drop(argument_count);
 }
 
@@ -1409,13 +1411,6 @@
                            Isolate::kNoDeoptId,
                            token_pos);
     }
-#if defined(DEBUG)
-    if (!is_optimizing()) {
-      // Do this *after* adding the pc descriptor!
-      __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP);
-      __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP);
-    }
-#endif
     // Stub returns result in flags (result of a cmp, we need Z computed).
     __ Pop(right);
     __ Pop(left);
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index b6a6b94..1193e78 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -61,6 +61,11 @@
 }
 
 
+bool FlowGraphCompiler::SupportsHardwareDivision() {
+  return true;
+}
+
+
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
@@ -73,12 +78,12 @@
 }
 
 
-RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder,
                                                  const Array& deopt_table) {
   if (deopt_env_ == NULL) {
     ++builder->current_info_number_;
-    return DeoptInfo::null();
+    return TypedData::null();
   }
 
   intptr_t stack_height = compiler->StackSize();
@@ -95,11 +100,13 @@
   builder->MarkFrameStart();
 
   // Callee's PC marker is not used anymore. Pass Code::null() to set to 0.
-  builder->AddPcMarker(Code::Handle(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
 
   // Current FP and PC.
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
+  builder->AddReturnAddress(Function::Handle(current->code().function()),
+                            deopt_id(),
+                            slot_ix++);
 
   // Emit all values that are needed for materialization as a part of the
   // expression stack for the bottom-most frame. This guarantees that GC
@@ -114,7 +121,7 @@
   }
 
   // Current PC marker and caller FP.
-  builder->AddPcMarker(current->code(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(current->code().function()), slot_ix++);
   builder->AddCallerFp(slot_ix++);
 
   Environment* previous = current;
@@ -122,7 +129,7 @@
   while (current != NULL) {
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(current->code(),
+    builder->AddReturnAddress(Function::Handle(current->code().function()),
                               Isolate::ToDeoptAfter(current->deopt_id()),
                               slot_ix++);
 
@@ -144,7 +151,8 @@
     }
 
     // PC marker and caller FP.
-    builder->AddPcMarker(current->code(), slot_ix++);
+    builder->AddPcMarker(Function::Handle(current->code().function()),
+                         slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // Iterate on the outer environment.
@@ -1216,10 +1224,6 @@
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
   __ Drop(argument_count);
-#if defined(DEBUG)
-  __ movl(ECX, Immediate(kInvalidObjectPointer));
-  __ movl(EDX, Immediate(kInvalidObjectPointer));
-#endif
 }
 
 
@@ -1290,9 +1294,6 @@
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count);
-#if defined(DEBUG)
-  __ movl(EDX, Immediate(kInvalidObjectPointer));
-#endif
 }
 
 
@@ -1435,13 +1436,6 @@
                            Isolate::kNoDeoptId,
                            token_pos);
     }
-#if defined(DEBUG)
-    if (!is_optimizing()) {
-      // Do this *after* adding the pc descriptor!
-      __ movl(EDX, Immediate(kInvalidObjectPointer));
-      __ movl(ECX, Immediate(kInvalidObjectPointer));
-    }
-#endif
     // Stub returns result in flags (result of a cmpl, we need ZF computed).
     __ popl(right);
     __ popl(left);
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 1f09dc0..c7ebddf 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -54,6 +54,11 @@
 }
 
 
+bool FlowGraphCompiler::SupportsHardwareDivision() {
+  return true;
+}
+
+
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
@@ -68,12 +73,12 @@
 }
 
 
-RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder,
                                                  const Array& deopt_table) {
   if (deopt_env_ == NULL) {
     ++builder->current_info_number_;
-    return DeoptInfo::null();
+    return TypedData::null();
   }
 
   intptr_t stack_height = compiler->StackSize();
@@ -90,12 +95,14 @@
   builder->MarkFrameStart();
 
   // Current PP, FP, and PC.
-  builder->AddPp(current->code(), slot_ix++);
+  builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
+  builder->AddReturnAddress(Function::Handle(current->code().function()),
+                            deopt_id(),
+                            slot_ix++);
 
   // Callee's PC marker is not used anymore. Pass Code::null() to set to 0.
-  builder->AddPcMarker(Code::Handle(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
 
   // Emit all values that are needed for materialization as a part of the
   // expression stack for the bottom-most frame. This guarantees that GC
@@ -113,17 +120,18 @@
   current = current->outer();
   while (current != NULL) {
     // PP, FP, and PC.
-    builder->AddPp(current->code(), slot_ix++);
+    builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(current->code(),
+    builder->AddReturnAddress(Function::Handle(current->code().function()),
                               Isolate::ToDeoptAfter(current->deopt_id()),
                               slot_ix++);
 
     // PC marker.
-    builder->AddPcMarker(previous->code(), slot_ix++);
+    builder->AddPcMarker(Function::Handle(previous->code().function()),
+                         slot_ix++);
 
     // The values of outgoing arguments can be changed from the inlined call so
     // we must read them from the previous environment.
@@ -155,7 +163,8 @@
   builder->AddCallerPc(slot_ix++);
 
   // PC marker.
-  builder->AddPcMarker(previous->code(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(previous->code().function()),
+                       slot_ix++);
 
   // For the outermost environment, set the incoming arguments.
   for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
@@ -194,7 +203,7 @@
 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
                                            Label* is_true,
                                            Label* is_false) {
-  __ TraceSimMsg("BoolToJump");
+  __ Comment("BoolToJump");
   Label fall_through;
   __ BranchEqual(bool_register, Object::null_object(), &fall_through);
   __ BranchEqual(bool_register, Bool::True(), is_true);
@@ -212,7 +221,7 @@
     Register temp_reg,
     Label* is_instance_lbl,
     Label* is_not_instance_lbl) {
-  __ TraceSimMsg("CallSubtypeTestStub");
+  __ Comment("CallSubtypeTestStub");
   ASSERT(instance_reg == A0);
   ASSERT(temp_reg == kNoRegister);  // Unused on MIPS.
   const SubtypeTestCache& type_test_cache =
@@ -321,7 +330,7 @@
                                       const GrowableArray<intptr_t>& class_ids,
                                       Label* is_equal_lbl,
                                       Label* is_not_equal_lbl) {
-  __ TraceSimMsg("CheckClassIds");
+  __ Comment("CheckClassIds");
   for (intptr_t i = 0; i < class_ids.length(); i++) {
     __ BranchEqual(class_id_reg, Immediate(class_ids[i]), is_equal_lbl);
   }
@@ -339,7 +348,6 @@
     const AbstractType& type,
     Label* is_instance_lbl,
     Label* is_not_instance_lbl) {
-  __ TraceSimMsg("InstantiatedTypeNoArgumentsTest");
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
   const Class& type_class = Class::Handle(type.type_class());
@@ -404,7 +412,6 @@
     const Class& type_class,
     Label* is_instance_lbl,
     Label* is_not_instance_lbl) {
-  __ TraceSimMsg("Subtype1TestCacheLookup");
   __ Comment("Subtype1TestCacheLookup");
   const Register kInstanceReg = A0;
   __ LoadClass(T0, kInstanceReg);
@@ -432,7 +439,6 @@
     const AbstractType& type,
     Label* is_instance_lbl,
     Label* is_not_instance_lbl) {
-  __ TraceSimMsg("UninstantiatedTypeTest");
   __ Comment("UninstantiatedTypeTest");
   ASSERT(!type.IsInstantiated());
   // Skip check if destination is a dynamic type.
@@ -512,7 +518,6 @@
     const AbstractType& type,
     Label* is_instance_lbl,
     Label* is_not_instance_lbl) {
-  __ TraceSimMsg("InlineInstanceof");
   __ Comment("InlineInstanceof");
   if (type.IsVoidType()) {
     // A non-null value is returned from a void function, which will result in a
@@ -656,7 +661,7 @@
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
                                                  LocationSummary* locs) {
-  __ TraceSimMsg("AssertAssignable");
+  __ Comment("AssertAssignable");
   ASSERT(token_pos >= 0);
   ASSERT(!dst_type.IsNull());
   ASSERT(dst_type.IsFinalized());
@@ -749,7 +754,6 @@
 // Input parameters:
 //   S4: arguments descriptor array.
 void FlowGraphCompiler::CopyParameters() {
-  __ TraceSimMsg("CopyParameters");
   __ Comment("Copy parameters");
   const Function& function = parsed_function().function();
   LocalScope* scope = parsed_function().node_sequence()->scope();
@@ -1078,7 +1082,6 @@
         function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
 #endif
     if (check_arguments) {
-      __ TraceSimMsg("Check argument count");
       __ Comment("Check argument count");
       // Check that exactly num_fixed arguments are passed in.
       Label correct_num_arguments, wrong_num_arguments;
@@ -1115,7 +1118,6 @@
   // null.
   if (!is_optimizing()) {
     ASSERT(num_locals > 0);  // There is always at least context_var.
-    __ TraceSimMsg("Initialize spill slots");
     __ Comment("Initialize spill slots");
     const intptr_t slot_base = parsed_function().first_stack_local_index();
     const intptr_t context_index =
@@ -1245,7 +1247,7 @@
   // top-level function (parsed_function().function()) which could be
   // reoptimized and which counter needs to be incremented.
   // Pass the function explicitly, it is used in IC stub.
-  __ TraceSimMsg("OptimizedInstanceCall");
+  __ Comment("OptimizedInstanceCall");
   __ LoadObject(T0, parsed_function().function());
   __ LoadObject(S5, ic_data);
   GenerateDartCall(deopt_id,
@@ -1264,18 +1266,15 @@
                                          intptr_t token_pos,
                                          LocationSummary* locs) {
   ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
-  __ TraceSimMsg("InstanceCall");
+  __ Comment("InstanceCall");
   __ LoadObject(S5, ic_data);
   GenerateDartCall(deopt_id,
                    token_pos,
                    target_label,
                    RawPcDescriptors::kIcCall,
                    locs);
-  __ TraceSimMsg("InstanceCall return");
+  __ Comment("InstanceCall return");
   __ Drop(argument_count);
-#if defined(DEBUG)
-  __ LoadImmediate(S4, kInvalidObjectPointer);
-#endif
 }
 
 
@@ -1292,7 +1291,7 @@
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
   const MegamorphicCache& cache =
       MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
-  __ TraceSimMsg("MegamorphicInstanceCall");
+  __ Comment("MegamorphicInstanceCall");
   __ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
   __ LoadTaggedClassIdMayBeSmi(T0, T0);
 
@@ -1359,10 +1358,6 @@
                    &target_label,
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
-#if defined(DEBUG)
-  __ LoadImmediate(S4, kInvalidObjectPointer);
-  __ LoadImmediate(S5, kInvalidObjectPointer);
-#endif
   __ Drop(argument_count);
 }
 
@@ -1375,7 +1370,7 @@
     intptr_t token_pos,
     LocationSummary* locs) {
   StubCode* stub_code = isolate()->stub_code();
-  __ TraceSimMsg("StaticCall");
+  __ Comment("StaticCall");
   __ LoadObject(S4, arguments_descriptor);
   // 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.
@@ -1394,7 +1389,7 @@
     const Object& obj,
     bool needs_number_check,
     intptr_t token_pos) {
-  __ TraceSimMsg("EqualityRegConstCompare");
+  __ Comment("EqualityRegConstCompare");
   ASSERT(!needs_number_check ||
          (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()));
   if (needs_number_check) {
@@ -1416,7 +1411,7 @@
                            Isolate::kNoDeoptId,
                            token_pos);
     }
-    __ TraceSimMsg("EqualityRegConstCompare return");
+    __ Comment("EqualityRegConstCompare return");
     // Stub returns result in CMPRES1 (if it is 0, then reg and obj are equal).
     __ lw(reg, Address(SP, 1 * kWordSize));  // Restore 'reg'.
     __ addiu(SP, SP, Immediate(2 * kWordSize));  // Discard constant.
@@ -1433,7 +1428,6 @@
                                                        Register right,
                                                        bool needs_number_check,
                                                        intptr_t token_pos) {
-  __ TraceSimMsg("EqualityRegRegCompare");
   __ Comment("EqualityRegRegCompare");
   if (needs_number_check) {
     StubCode* stub_code = isolate()->stub_code();
@@ -1452,14 +1446,7 @@
                            Isolate::kNoDeoptId,
                            token_pos);
     }
-#if defined(DEBUG)
-    if (!is_optimizing()) {
-      // Do this *after* adding the pc descriptor!
-      __ LoadImmediate(S4, kInvalidObjectPointer);
-      __ LoadImmediate(S5, kInvalidObjectPointer);
-    }
-#endif
-    __ TraceSimMsg("EqualityRegRegCompare return");
+    __ Comment("EqualityRegRegCompare return");
     // Stub returns result in CMPRES1 (if it is 0, then left and right are
     // equal).
     __ lw(right, Address(SP, 0 * kWordSize));
@@ -1480,7 +1467,7 @@
   ClobberDeadTempRegisters(locs);
 #endif
 
-  __ TraceSimMsg("SaveLiveRegisters");
+  __ Comment("SaveLiveRegisters");
   // TODO(vegorov): consider saving only caller save (volatile) registers.
   const intptr_t fpu_regs_count = locs->live_registers()->FpuRegisterCount();
   if (fpu_regs_count > 0) {
@@ -1522,7 +1509,7 @@
 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
   // General purpose registers have the highest register number at the
   // lowest address.
-  __ TraceSimMsg("RestoreLiveRegisters");
+  __ Comment("RestoreLiveRegisters");
   const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
   ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
   const int register_count = Utils::CountOneBits(cpu_registers);
@@ -1592,7 +1579,6 @@
                                                  argument_names));
   StubCode* stub_code = isolate()->stub_code();
 
-  __ TraceSimMsg("EmitTestAndCall");
   __ Comment("EmitTestAndCall");
   __ LoadObject(S4, arguments_descriptor);
   for (intptr_t i = 0; i < len; i++) {
@@ -1630,7 +1616,7 @@
   MoveOperands* move = moves_[index];
   const Location source = move->src();
   const Location destination = move->dest();
-  __ TraceSimMsg("ParallelMoveResolver::EmitMove");
+  __ Comment("ParallelMoveResolver::EmitMove");
 
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
@@ -1785,14 +1771,14 @@
 
 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
                                               const Address& src) {
-  __ TraceSimMsg("ParallelMoveResolver::MoveMemoryToMemory");
+  __ Comment("ParallelMoveResolver::MoveMemoryToMemory");
   __ lw(TMP, src);
   __ sw(TMP, dst);
 }
 
 
 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
-  __ TraceSimMsg("ParallelMoveResolver::StoreObject");
+  __ Comment("ParallelMoveResolver::StoreObject");
   __ LoadObject(TMP, obj);
   __ sw(TMP, dst);
 }
@@ -1836,26 +1822,26 @@
 
 
 void ParallelMoveResolver::SpillScratch(Register reg) {
-  __ TraceSimMsg("ParallelMoveResolver::SpillScratch");
+  __ Comment("ParallelMoveResolver::SpillScratch");
   __ Push(reg);
 }
 
 
 void ParallelMoveResolver::RestoreScratch(Register reg) {
-  __ TraceSimMsg("ParallelMoveResolver::RestoreScratch");
+  __ Comment("ParallelMoveResolver::RestoreScratch");
   __ Pop(reg);
 }
 
 
 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
-  __ TraceSimMsg("ParallelMoveResolver::SpillFpuScratch");
+  __ Comment("ParallelMoveResolver::SpillFpuScratch");
   __ AddImmediate(SP, -kDoubleSize);
   __ StoreDToOffset(reg, SP, 0);
 }
 
 
 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
-  __ TraceSimMsg("ParallelMoveResolver::RestoreFpuScratch");
+  __ Comment("ParallelMoveResolver::RestoreFpuScratch");
   __ LoadDFromOffset(reg, SP, 0);
   __ AddImmediate(SP, kDoubleSize);
 }
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index c24d2ef..562f0c3 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -59,6 +59,11 @@
 }
 
 
+bool FlowGraphCompiler::SupportsHardwareDivision() {
+  return true;
+}
+
+
 void FlowGraphCompiler::EnterIntrinsicMode() {
   ASSERT(!intrinsic_mode());
   intrinsic_mode_ = true;
@@ -73,12 +78,12 @@
 }
 
 
-RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
+RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder,
                                                  const Array& deopt_table) {
   if (deopt_env_ == NULL) {
     ++builder->current_info_number_;
-    return DeoptInfo::null();
+    return TypedData::null();
   }
 
   intptr_t stack_height = compiler->StackSize();
@@ -95,10 +100,12 @@
   builder->MarkFrameStart();
 
   // Current PP, FP, and PC.
-  builder->AddPp(current->code(), slot_ix++);
-  builder->AddPcMarker(Code::Handle(), slot_ix++);
+  builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
+  builder->AddPcMarker(Function::Handle(), slot_ix++);
   builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
+  builder->AddReturnAddress(Function::Handle(current->code().function()),
+                            deopt_id(),
+                            slot_ix++);
 
   // Emit all values that are needed for materialization as a part of the
   // expression stack for the bottom-most frame. This guarantees that GC
@@ -116,13 +123,14 @@
   current = current->outer();
   while (current != NULL) {
     // PP, FP, and PC.
-    builder->AddPp(current->code(), slot_ix++);
-    builder->AddPcMarker(previous->code(), slot_ix++);
+    builder->AddPp(Function::Handle(current->code().function()), slot_ix++);
+    builder->AddPcMarker(Function::Handle(previous->code().function()),
+                         slot_ix++);
     builder->AddCallerFp(slot_ix++);
 
     // For any outer environment the deopt id is that of the call instruction
     // which is recorded in the outer environment.
-    builder->AddReturnAddress(current->code(),
+    builder->AddReturnAddress(Function::Handle(current->code().function()),
                               Isolate::ToDeoptAfter(current->deopt_id()),
                               slot_ix++);
 
@@ -153,7 +161,8 @@
   // For the outermost environment, set caller PC, caller PP, and caller FP.
   builder->AddCallerPp(slot_ix++);
   // PC marker.
-  builder->AddPcMarker(previous->code(), slot_ix++);
+  builder->AddPcMarker(Function::Handle(previous->code().function()),
+                       slot_ix++);
   builder->AddCallerFp(slot_ix++);
   builder->AddCallerPc(slot_ix++);
 
@@ -1223,10 +1232,6 @@
                    RawPcDescriptors::kUnoptStaticCall,
                    locs);
   __ Drop(argument_count, RCX);
-#if defined(DEBUG)
-  __ movq(RBX, Immediate(kInvalidObjectPointer));
-  __ movq(R10, Immediate(kInvalidObjectPointer));
-#endif
 }
 
 
@@ -1297,9 +1302,6 @@
                    RawPcDescriptors::kIcCall,
                    locs);
   __ Drop(argument_count, RCX);
-#if defined(DEBUG)
-  __ movq(R10, Immediate(kInvalidObjectPointer));
-#endif
 }
 
 
@@ -1441,13 +1443,6 @@
                            Isolate::kNoDeoptId,
                            token_pos);
     }
-#if defined(DEBUG)
-    // Do this *after* adding the pc descriptor!
-    if (!is_optimizing()) {
-      __ movq(R10, Immediate(kInvalidObjectPointer));
-      __ movq(RBX, Immediate(kInvalidObjectPointer));
-    }
-#endif
     // Stub returns result in flags (result of a cmpq, we need ZF computed).
     __ popq(right);
     __ popq(left);
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 04bb036..1b33345 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -2035,6 +2035,7 @@
       }
       break;
     case Token::kDIV:
+      if (!FlowGraphCompiler::SupportsHardwareDivision()) return false;
       if (ShouldSpecializeForDouble(ic_data) ||
           HasOnlyTwoOf(ic_data, kSmiCid)) {
         operands_type = kDoubleCid;
@@ -2087,6 +2088,7 @@
       break;
     case Token::kMOD:
     case Token::kTRUNCDIV:
+      if (!FlowGraphCompiler::SupportsHardwareDivision()) return false;
       if (HasOnlyTwoOf(ic_data, kSmiCid)) {
         if (ic_data.HasDeoptReason(ICData::kDeoptBinarySmiOp)) {
           return false;
diff --git a/runtime/vm/freelist.cc b/runtime/vm/freelist.cc
index 00a4691..b8df851 100644
--- a/runtime/vm/freelist.cc
+++ b/runtime/vm/freelist.cc
@@ -70,7 +70,7 @@
 
 
 uword FreeList::TryAllocateLocked(intptr_t size, bool is_protected) {
-  DEBUG_ASSERT(mutex_->Owner() == Isolate::Current());
+  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
   // Precondition: is_protected is false or else all free list elements are
   // in non-writable pages.
 
@@ -183,7 +183,7 @@
 
 
 void FreeList::FreeLocked(uword addr, intptr_t size) {
-  DEBUG_ASSERT(mutex_->Owner() == Isolate::Current());
+  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
   // Precondition required by AsElement and EnqueueElement: the (page
   // containing the) header of the freed block should be writable.  This is
   // the case when called for newly allocated pages because they are
@@ -249,7 +249,7 @@
 
 
 intptr_t FreeList::LengthLocked(int index) const {
-  DEBUG_ASSERT(mutex_->Owner() == Isolate::Current());
+  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
   ASSERT(index >= 0);
   ASSERT(index < kNumLists);
   intptr_t result = 0;
@@ -362,7 +362,7 @@
 
 
 FreeListElement* FreeList::TryAllocateLargeLocked(intptr_t minimum_size) {
-  DEBUG_ASSERT(mutex_->Owner() == Isolate::Current());
+  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
   FreeListElement* previous = NULL;
   FreeListElement* current = free_lists_[kNumLists];
   // TODO(koda): Find largest.
@@ -384,7 +384,7 @@
 
 
 uword FreeList::TryAllocateSmallLocked(intptr_t size) {
-  DEBUG_ASSERT(mutex_->Owner() == Isolate::Current());
+  DEBUG_ASSERT(mutex_->IsOwnedByCurrentThread());
   if (size > last_free_small_size_) {
     return 0;
   }
diff --git a/runtime/vm/gc_sweeper.cc b/runtime/vm/gc_sweeper.cc
index 270c9cc..b9b5835 100644
--- a/runtime/vm/gc_sweeper.cc
+++ b/runtime/vm/gc_sweeper.cc
@@ -113,7 +113,7 @@
   }
 
   virtual void Run() {
-    Isolate::SetCurrent(task_isolate_);
+    Thread::EnterIsolate(task_isolate_);
     GCSweeper sweeper;
 
     HeapPage* page = first_;
@@ -143,7 +143,7 @@
       old_space_->set_tasks(old_space_->tasks() - 1);
       ml.Notify();
     }
-    Isolate::SetCurrent(NULL);
+    Thread::ExitIsolate();
     delete task_isolate_;
   }
 
diff --git a/runtime/vm/growable_array.h b/runtime/vm/growable_array.h
index 81a946b..ba6f807 100644
--- a/runtime/vm/growable_array.h
+++ b/runtime/vm/growable_array.h
@@ -90,6 +90,15 @@
     data_[idx] = value;
   }
 
+  void Reverse() {
+    for (intptr_t i = 0; i < length_ / 2; i++) {
+      const intptr_t j = length_ - 1 - i;
+      T temp = data_[i];
+      data_[i] = data_[j];
+      data_[j] = temp;
+    }
+  }
+
   // The content is uninitialized after calling it.
   void SetLength(intptr_t new_length);
 
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index a8f35f4..2443369 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -639,7 +639,7 @@
   stats_.after_.old_ = old_space_->GetCurrentUsage();
   ASSERT(gc_in_progress_);
   gc_in_progress_ = false;
-  if (Service::NeedsGCEvents()) {
+  if (Service::NeedsEvents()) {
     GCEvent event(stats_);
     Service::HandleGCEvent(&event);
   }
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 840b45e..eea43c4 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -191,7 +191,7 @@
 }
 
 
-bool CheckClassInstr::IsNullCheck() const {
+bool CheckClassInstr::DeoptIfNull() const {
   if (unary_checks().NumberOfChecks() != 1) {
     return false;
   }
@@ -203,6 +203,19 @@
 }
 
 
+// Null object is a singleton of null-class (except for some sentinel,
+// transitional temporaries). Instead of checking against the null class only
+// we can check against null instance instead.
+bool CheckClassInstr::DeoptIfNotNull() const {
+  if (unary_checks().NumberOfChecks() != 1) {
+    return false;
+  }
+  const intptr_t cid = unary_checks().GetCidAt(0);
+  return cid == kNullCid;
+}
+
+
+
 bool CheckClassInstr::IsDenseSwitch() const {
   if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) return false;
   if (cids_.length() > 2 &&
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index b8bf6dd..72ebed1 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -7592,7 +7592,12 @@
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
-  bool IsNullCheck() const;
+  bool IsNullCheck() const {
+    return  DeoptIfNull() || DeoptIfNotNull();
+  }
+
+  bool DeoptIfNull() const;
+  bool DeoptIfNotNull() const;
 
   bool IsDenseSwitch() const;
   intptr_t ComputeCidMask() const;
@@ -8015,7 +8020,9 @@
         fixed_parameter_count_(fixed_parameter_count),
         deopt_id_(deopt_id),
         parsed_function_(parsed_function),
-        outer_(outer) { }
+        outer_(outer) {
+    ASSERT(!parsed_function_.code().IsNull());
+  }
 
 
   GrowableArray<Value*> values_;
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 6dc5ac0..f576dc8 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -1283,9 +1283,6 @@
   if ((representation() == kUnboxedUint32) ||
       (representation() == kUnboxedInt32)) {
     Register result = locs()->out(0).reg();
-    if ((index_scale() == 1) && index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
     switch (class_id()) {
       case kTypedDataInt32ArrayCid:
         ASSERT(representation() == kUnboxedInt32);
@@ -3054,9 +3051,6 @@
   } else if (((op_kind() == Token::kSHL) && can_overflow()) ||
              (op_kind() == Token::kSHR)) {
     num_temps = 1;
-  } else if ((op_kind() == Token::kMUL) &&
-             (TargetCPUFeatures::arm_version() != ARMv7)) {
-    num_temps = 1;
   }
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, num_temps, LocationSummary::kNoCall);
@@ -3088,11 +3082,6 @@
       (op_kind() == Token::kSHR)) {
     summary->set_temp(0, Location::RequiresRegister());
   }
-  if (op_kind() == Token::kMUL) {
-    if (TargetCPUFeatures::arm_version() != ARMv7) {
-      summary->set_temp(0, Location::RequiresFpuRegister());
-    }
-  }
   // We make use of 3-operand instructions by not requiring result register
   // to be identical to first input register as on Intel.
   summary->set_out(0, Location::RequiresRegister());
@@ -3145,24 +3134,11 @@
           __ LoadImmediate(IP, value);
           __ mul(result, left, IP);
         } else {
-          if (TargetCPUFeatures::arm_version() == ARMv7) {
-            __ LoadImmediate(IP, value);
-            __ smull(result, IP, left, IP);
-            // IP: result bits 32..63.
-            __ cmp(IP, Operand(result, ASR, 31));
-            __ b(deopt, NE);
-          } else if (TargetCPUFeatures::can_divide()) {
-            const QRegister qtmp = locs()->temp(0).fpu_reg();
-            const DRegister dtmp0 = EvenDRegisterOf(qtmp);
-            const DRegister dtmp1 = OddDRegisterOf(qtmp);
-            __ LoadImmediate(IP, value);
-            __ CheckMultSignedOverflow(left, IP, result, dtmp0, dtmp1, deopt);
-            __ mul(result, left, IP);
-          } else {
-           // TODO(vegorov): never emit this instruction if hardware does not
-           // support it! This will lead to deopt cycle penalizing the code.
-            __ b(deopt);
-          }
+          __ LoadImmediate(IP, value);
+          __ smull(result, IP, left, IP);
+          // IP: result bits 32..63.
+          __ cmp(IP, Operand(result, ASR, 31));
+          __ b(deopt, NE);
         }
         break;
       }
@@ -3262,22 +3238,10 @@
       if (deopt == NULL) {
         __ mul(result, IP, right);
       } else {
-        if (TargetCPUFeatures::arm_version() == ARMv7) {
-          __ smull(result, IP, IP, right);
-          // IP: result bits 32..63.
-          __ cmp(IP, Operand(result, ASR, 31));
-          __ b(deopt, NE);
-        } else if (TargetCPUFeatures::can_divide()) {
-          const QRegister qtmp = locs()->temp(0).fpu_reg();
-          const DRegister dtmp0 = EvenDRegisterOf(qtmp);
-          const DRegister dtmp1 = OddDRegisterOf(qtmp);
-          __ CheckMultSignedOverflow(IP, right, result, dtmp0, dtmp1, deopt);
-          __ mul(result, IP, right);
-        } else {
-          // TODO(vegorov): never emit this instruction if hardware does not
-          // support it! This will lead to deopt cycle penalizing the code.
-          __ b(deopt);
-        }
+        __ smull(result, IP, IP, right);
+        // IP: result bits 32..63.
+        __ cmp(IP, Operand(result, ASR, 31));
+        __ b(deopt, NE);
       }
       break;
     }
@@ -3297,22 +3261,17 @@
       break;
     }
     case Token::kTRUNCDIV: {
+      ASSERT(TargetCPUFeatures::can_divide());
       if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
         // Handle divide by zero in runtime.
         __ cmp(right, Operand(0));
         __ b(deopt, EQ);
       }
       const Register temp = locs()->temp(0).reg();
-      if (TargetCPUFeatures::can_divide()) {
-        const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
-        __ SmiUntag(temp, left);
-        __ SmiUntag(IP, right);
-        __ IntegerDivide(result, temp, IP, dtemp, DTMP);
-      } else {
-        // TODO(vegorov): never emit this instruction if hardware does not
-        // support it! This will lead to deopt cycle penalizing the code.
-        __ b(deopt);
-      }
+      const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
+      __ SmiUntag(temp, left);
+      __ SmiUntag(IP, right);
+      __ IntegerDivide(result, temp, IP, dtemp, DTMP);
 
       // Check the corner case of dividing the 'MIN_SMI' with -1, in which
       // case we cannot tag the result.
@@ -3322,22 +3281,17 @@
       break;
     }
     case Token::kMOD: {
+      ASSERT(TargetCPUFeatures::can_divide());
       if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
         // Handle divide by zero in runtime.
         __ cmp(right, Operand(0));
         __ b(deopt, EQ);
       }
       const Register temp = locs()->temp(0).reg();
-      if (TargetCPUFeatures::can_divide()) {
-        const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
-        __ SmiUntag(temp, left);
-        __ SmiUntag(IP, right);
-        __ IntegerDivide(result, temp, IP, dtemp, DTMP);
-      } else {
-        // TODO(vegorov): never emit this instruction if hardware does not
-        // support it! This will lead to deopt cycle penalizing the code.
-        __ b(deopt);
-      }
+      const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
+      __ SmiUntag(temp, left);
+      __ SmiUntag(IP, right);
+      __ IntegerDivide(result, temp, IP, dtemp, DTMP);
       __ SmiUntag(IP, right);
       __ mls(result, IP, result, temp);  // result <- left - right * result
       __ SmiTag(result);
@@ -3432,9 +3386,6 @@
   if (((op_kind() == Token::kSHL) && can_overflow()) ||
       (op_kind() == Token::kSHR)) {
     num_temps = 1;
-  } else if ((op_kind() == Token::kMUL) &&
-             (TargetCPUFeatures::arm_version() != ARMv7)) {
-    num_temps = 1;
   }
   LocationSummary* summary = new(zone) LocationSummary(
       zone, kNumInputs, num_temps, LocationSummary::kNoCall);
@@ -3444,11 +3395,6 @@
       (op_kind() == Token::kSHR)) {
     summary->set_temp(0, Location::RequiresRegister());
   }
-  if (op_kind() == Token::kMUL) {
-    if (TargetCPUFeatures::arm_version() != ARMv7) {
-      summary->set_temp(0, Location::RequiresFpuRegister());
-    }
-  }
   // We make use of 3-operand instructions by not requiring result register
   // to be identical to first input register as on Intel.
   summary->set_out(0, Location::RequiresRegister());
@@ -3499,24 +3445,11 @@
           __ LoadImmediate(IP, value);
           __ mul(result, left, IP);
         } else {
-          if (TargetCPUFeatures::arm_version() == ARMv7) {
-            __ LoadImmediate(IP, value);
-            __ smull(result, IP, left, IP);
-            // IP: result bits 32..63.
-            __ cmp(IP, Operand(result, ASR, 31));
-            __ b(deopt, NE);
-          } else if (TargetCPUFeatures::can_divide()) {
-            const QRegister qtmp = locs()->temp(0).fpu_reg();
-            const DRegister dtmp0 = EvenDRegisterOf(qtmp);
-            const DRegister dtmp1 = OddDRegisterOf(qtmp);
-            __ LoadImmediate(IP, value);
-            __ CheckMultSignedOverflow(left, IP, result, dtmp0, dtmp1, deopt);
-            __ mul(result, left, IP);
-          } else {
-            // TODO(vegorov): never emit this instruction if hardware does not
-            // support it! This will lead to deopt cycle penalizing the code.
-            __ b(deopt);
-          }
+          __ LoadImmediate(IP, value);
+          __ smull(result, IP, left, IP);
+          // IP: result bits 32..63.
+          __ cmp(IP, Operand(result, ASR, 31));
+          __ b(deopt, NE);
         }
         break;
       }
@@ -3593,22 +3526,10 @@
       if (deopt == NULL) {
         __ mul(result, left, right);
       } else {
-        if (TargetCPUFeatures::arm_version() == ARMv7) {
-          __ smull(result, IP, left, right);
-          // IP: result bits 32..63.
-          __ cmp(IP, Operand(result, ASR, 31));
-          __ b(deopt, NE);
-        } else if (TargetCPUFeatures::can_divide()) {
-          const QRegister qtmp = locs()->temp(0).fpu_reg();
-          const DRegister dtmp0 = EvenDRegisterOf(qtmp);
-          const DRegister dtmp1 = OddDRegisterOf(qtmp);
-          __ CheckMultSignedOverflow(left, right, result, dtmp0, dtmp1, deopt);
-          __ mul(result, left, right);
-        } else {
-          // TODO(vegorov): never emit this instruction if hardware does not
-          // support it! This will lead to deopt cycle penalizing the code.
-          __ b(deopt);
-        }
+        __ smull(result, IP, left, right);
+        // IP: result bits 32..63.
+        __ cmp(IP, Operand(result, ASR, 31));
+        __ b(deopt, NE);
       }
       break;
     }
@@ -5880,6 +5801,7 @@
     deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
   }
   if (kind() == MergedMathInstr::kTruncDivMod) {
+    ASSERT(TargetCPUFeatures::can_divide());
     const Register left = locs()->in(0).reg();
     const Register right = locs()->in(1).reg();
     ASSERT(locs()->out(0).IsPairLocation());
@@ -5893,16 +5815,10 @@
       __ b(deopt, EQ);
     }
     const Register temp = locs()->temp(0).reg();
-    if (TargetCPUFeatures::can_divide()) {
-      const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
-      __ SmiUntag(temp, left);
-      __ SmiUntag(IP, right);
-      __ IntegerDivide(result_div, temp, IP, dtemp, DTMP);
-    } else {
-      // TODO(vegorov): never emit this instruction if hardware does not
-      // support it! This will lead to deopt cycle penalizing the code.
-      __ b(deopt);
-    }
+    const DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
+    __ SmiUntag(temp, left);
+    __ SmiUntag(IP, right);
+    __ IntegerDivide(result_div, temp, IP, dtemp, DTMP);
 
     // Check the corner case of dividing the 'MIN_SMI' with -1, in which
     // case we cannot tag the result.
@@ -6020,7 +5936,9 @@
   if (IsNullCheck()) {
     __ CompareImmediate(locs()->in(0).reg(),
                         reinterpret_cast<intptr_t>(Object::null()));
-    __ b(deopt, EQ);
+    ASSERT(DeoptIfNull() || DeoptIfNotNull());
+    Condition cond = DeoptIfNull() ? EQ : NE;
+    __ b(deopt, cond);
     return;
   }
 
@@ -6261,16 +6179,10 @@
       // result without causing overflow.
       // We deopt on larger inputs.
       // TODO(regis): Range analysis may eliminate the deopt check.
-      if (TargetCPUFeatures::arm_version() == ARMv7) {
-        __ cmp(left_hi, Operand(left_lo, ASR, 31));
-        __ cmp(right_hi, Operand(right_lo, ASR, 31), EQ);
-        __ b(deopt, NE);
-        __ smull(out_lo, out_hi, left_lo, right_lo);
-      } else {
-        // TODO(vegorov): never emit this instruction if hardware does not
-        // support it! This will lead to deopt cycle penalizing the code.
-        __ b(deopt);
-      }
+      __ cmp(left_hi, Operand(left_lo, ASR, 31));
+      __ cmp(right_hi, Operand(right_lo, ASR, 31), EQ);
+      __ b(deopt, NE);
+      __ smull(out_lo, out_hi, left_lo, right_lo);
       break;
     }
     default:
@@ -6935,10 +6847,6 @@
   StubCode* stub_code = compiler->isolate()->stub_code();
   const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
   compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
-#if defined(DEBUG)
-  __ LoadImmediate(R4, kInvalidObjectPointer);
-  __ LoadImmediate(R5, kInvalidObjectPointer);
-#endif
 }
 
 
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 846414a..3956689 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -5090,7 +5090,9 @@
                                         licm_hoisted_ ? ICData::kHoisted : 0);
   if (IsNullCheck()) {
     __ CompareObject(locs()->in(0).reg(), Object::null_object(), PP);
-    __ b(deopt, EQ);
+    ASSERT(DeoptIfNull() || DeoptIfNotNull());
+    Condition cond = DeoptIfNull() ? EQ : NE;
+    __ b(deopt, cond);
     return;
   }
 
@@ -5607,10 +5609,6 @@
   StubCode* stub_code = compiler->isolate()->stub_code();
   const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
   compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
-#if defined(DEBUG)
-  __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP);
-  __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP);
-#endif
 }
 
 
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index d9e565a..6d70aa4 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -5763,7 +5763,9 @@
     const Immediate& raw_null =
         Immediate(reinterpret_cast<intptr_t>(Object::null()));
     __ cmpl(locs()->in(0).reg(), raw_null);
-    __ j(EQUAL, deopt);
+    ASSERT(DeoptIfNull() || DeoptIfNotNull());
+    Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL;
+    __ j(cond, deopt);
     return;
   }
 
@@ -6843,9 +6845,6 @@
   StubCode* stub_code = compiler->isolate()->stub_code();
   const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
   compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
-#if defined(DEBUG)
-  __ movl(EDX, Immediate(kInvalidObjectPointer));
-#endif
 }
 
 
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 5bf3c7d..2274bf8 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -54,7 +54,7 @@
 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
   // where PushArgument is handled by BindInstr::EmitNativeCode.
-  __ TraceSimMsg("PushArgumentInstr");
+  __ Comment("PushArgumentInstr");
   if (compiler->is_optimizing()) {
     Location value = locs()->in(0);
     if (value.IsRegister()) {
@@ -86,7 +86,7 @@
 // The entry needs to be patchable, no inlined objects are allowed in the area
 // that will be overwritten by the patch instructions: a branch macro sequence.
 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("ReturnInstr");
+  __ Comment("ReturnInstr");
   Register result = locs()->in(0).reg();
   ASSERT(result == V0);
 
@@ -99,7 +99,6 @@
 #if defined(DEBUG)
   Label stack_ok;
   __ Comment("Stack Check");
-  __ TraceSimMsg("Stack Check");
   const intptr_t fp_sp_dist =
       (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize;
   ASSERT(fp_sp_dist <= 0);
@@ -309,7 +308,7 @@
 
 
 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("LoadLocalInstr");
+  __ Comment("LoadLocalInstr");
   Register result = locs()->out(0).reg();
   __ LoadFromOffset(result, FP, local().index() * kWordSize);
 }
@@ -325,7 +324,7 @@
 
 
 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("StoreLocalInstr");
+  __ Comment("StoreLocalInstr");
   Register value = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
   ASSERT(result == value);  // Assert that register assignment is correct.
@@ -345,7 +344,7 @@
 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // The register allocator drops constant definitions that have no uses.
   if (!locs()->out(0).IsInvalid()) {
-    __ TraceSimMsg("ConstantInstr");
+    __ Comment("ConstantInstr");
     Register result = locs()->out(0).reg();
     __ LoadObject(result, value());
   }
@@ -457,7 +456,7 @@
   Register obj = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
 
-  __ TraceSimMsg("AssertBooleanInstr");
+  __ Comment("AssertBooleanInstr");
   EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
   ASSERT(obj == result);
 }
@@ -508,7 +507,7 @@
                          Register value_cid_reg,
                          Register value_reg,
                          Label* value_is_smi = NULL) {
-  __ TraceSimMsg("LoadValueCid");
+  __ Comment("LoadValueCid");
   Label done;
   if (value_is_smi == NULL) {
     __ LoadImmediate(value_cid_reg, kSmiCid);
@@ -558,7 +557,7 @@
 static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
                                   Condition true_condition,
                                   BranchLabels labels) {
-  __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition");
+  __ Comment("ControlInstruction::EmitBranchOnCondition");
   if (labels.fall_through == labels.false_label) {
     // If the next block is the false successor, fall through to it.
     __ BranchOnCondition(true_condition, labels.true_label);
@@ -577,7 +576,6 @@
 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
                                      const LocationSummary& locs,
                                      Token::Kind kind) {
-  __ TraceSimMsg("EmitSmiComparisonOp");
   __ Comment("EmitSmiComparisonOp");
   const Location left = locs.in(0);
   const Location right = locs.in(1);
@@ -598,7 +596,6 @@
                                            const LocationSummary& locs,
                                            Token::Kind kind,
                                            BranchLabels labels) {
-  __ TraceSimMsg("EmitUnboxedMintEqualityOp");
   __ Comment("EmitUnboxedMintEqualityOp");
   ASSERT(Token::IsEqualityOperator(kind));
   PairLocation* left_pair = locs.in(0).AsPairLocation();
@@ -630,7 +627,6 @@
                                              const LocationSummary& locs,
                                              Token::Kind kind,
                                              BranchLabels labels) {
-  __ TraceSimMsg("EmitUnboxedMintComparisonOp");
   __ Comment("EmitUnboxedMintComparisonOp");
   PairLocation* left_pair = locs.in(0).AsPairLocation();
   Register left_lo = left_pair->At(0).reg();
@@ -773,8 +769,7 @@
 
 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
                                           BranchInstr* branch) {
-  __ TraceSimMsg("EqualityCompareInstr");
-  __ Comment("EqualityCompareInstr:BranchCode");
+  __ Comment("EqualityCompareInstr::EmitBranchCode");
   ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
 
   BranchLabels labels = compiler->CreateBranchLabels(branch);
@@ -950,7 +945,7 @@
 
 
 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("RelationalOpInstr");
+  __ Comment("RelationalOpInstr");
 
   Label is_true, is_false;
   BranchLabels labels = { &is_true, &is_false, &is_false };
@@ -970,7 +965,7 @@
 
 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
                                        BranchInstr* branch) {
-  __ TraceSimMsg("RelationalOpInstr");
+  __ Comment("RelationalOpInstr");
 
   BranchLabels labels = compiler->CreateBranchLabels(branch);
   Condition true_condition = EmitComparisonCode(compiler, labels);
@@ -985,7 +980,7 @@
 
 
 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("NativeCallInstr");
+  __ Comment("NativeCallInstr");
   Register result = locs()->out(0).reg();
 
   // Push the result place holder initialized to NULL.
@@ -1049,7 +1044,7 @@
   Register char_code = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
 
-  __ TraceSimMsg("StringFromCharCodeInstr");
+  __ Comment("StringFromCharCodeInstr");
 
   __ LoadImmediate(result,
                    reinterpret_cast<uword>(Symbols::PredefinedAddress()));
@@ -1071,7 +1066,7 @@
 
 
 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("StringToCharCodeInstr");
+  __ Comment("StringToCharCodeInstr");
 
   ASSERT(cid_ == kOneByteStringCid);
   Register str = locs()->in(0).reg();
@@ -1262,7 +1257,7 @@
 
 
 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("LoadIndexedInstr");
+  __ Comment("LoadIndexedInstr");
   // The array register points to the backing store for external arrays.
   const Register array = locs()->in(0).reg();
   const Location index = locs()->in(1);
@@ -1300,9 +1295,6 @@
   if ((representation() == kUnboxedUint32) ||
       (representation() == kUnboxedInt32)) {
     const Register result = locs()->out(0).reg();
-    if ((index_scale() == 1) && index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
     switch (class_id()) {
       case kTypedDataInt32ArrayCid:
         ASSERT(representation() == kUnboxedInt32);
@@ -1488,7 +1480,7 @@
 
 
 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("StoreIndexedInstr");
+  __ Comment("StoreIndexedInstr");
   // The array register points to the backing store for external arrays.
   const Register array = locs()->in(0).reg();
   const Location index = locs()->in(1);
@@ -1620,7 +1612,7 @@
 
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("GuardFieldClassInstr");
+  __ Comment("GuardFieldClassInstr");
 
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
@@ -2093,7 +2085,7 @@
 //
 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize.
 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("LoadStaticFieldInstr");
+  __ Comment("LoadStaticFieldInstr");
   Register field = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
   __ LoadFromOffset(result, field, Field::value_offset() - kHeapObjectTag);
@@ -2112,7 +2104,7 @@
 
 
 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("StoreStaticFieldInstr");
+  __ Comment("StoreStaticFieldInstr");
   Register value = locs()->in(0).reg();
   Register temp = locs()->temp(0).reg();
 
@@ -2226,7 +2218,7 @@
 
 
 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("CreateArrayInstr");
+  __ Comment("CreateArrayInstr");
   const Register kLengthReg = A1;
   const Register kElemTypeReg = A0;
   const Register kResultReg = V0;
@@ -2375,7 +2367,7 @@
 
 
 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("InstantiateTypeInstr");
+  __ Comment("InstantiateTypeInstr");
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out(0).reg();
 
@@ -2416,7 +2408,7 @@
 
 void InstantiateTypeArgumentsInstr::EmitNativeCode(
     FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("InstantiateTypeArgumentsInstr");
+  __ Comment("InstantiateTypeArgumentsInstr");
   Register instantiator_reg = locs()->in(0).reg();
   Register result_reg = locs()->out(0).reg();
   ASSERT(instantiator_reg == T0);
@@ -2566,7 +2558,7 @@
   ASSERT(locs()->temp(0).reg() == T1);
   ASSERT(locs()->out(0).reg() == V0);
 
-  __ TraceSimMsg("AllocateContextInstr");
+  __ Comment("AllocateContextInstr");
   __ LoadImmediate(T1, num_context_variables());
   StubCode* stub_code = compiler->isolate()->stub_code();
   const ExternalLabel label(stub_code->AllocateContextEntryPoint());
@@ -2594,7 +2586,7 @@
   Register temp = locs()->temp(0).reg();
 
   Label call_runtime, no_call;
-  __ TraceSimMsg("InitStaticFieldInstr");
+  __ Comment("InitStaticFieldInstr");
 
   __ lw(temp, FieldAddress(field, Field::value_offset()));
   __ BranchEqual(temp, Object::sentinel(), &call_runtime);
@@ -2634,7 +2626,7 @@
   Register context_value = locs()->in(0).reg();
   Register result = locs()->out(0).reg();
 
-  __ TraceSimMsg("CloneContextInstr");
+  __ Comment("CloneContextInstr");
 
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ LoadObject(TMP, Object::null_object());  // Make room for the result.
@@ -2714,14 +2706,12 @@
     if (FLAG_use_osr) {
       uword flags_address = Isolate::Current()->stack_overflow_flags_address();
       Register value = instruction_->locs()->temp(0).reg();
-      __ TraceSimMsg("CheckStackOverflowSlowPathOsr");
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
       __ LoadImmediate(TMP, flags_address);
       __ LoadImmediate(value, Isolate::kOsrRequest);
       __ sw(value, Address(TMP));
     }
-    __ TraceSimMsg("CheckStackOverflowSlowPath");
     __ Comment("CheckStackOverflowSlowPath");
     __ Bind(entry_label());
     compiler->SaveLiveRegisters(instruction_->locs());
@@ -2759,7 +2749,7 @@
 
 
 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("CheckStackOverflowInstr");
+  __ Comment("CheckStackOverflowInstr");
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
@@ -2794,7 +2784,7 @@
       compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
       : NULL;
 
-  __ TraceSimMsg("EmitSmiShiftLeft");
+  __ Comment("EmitSmiShiftLeft");
 
   if (locs.in(1).IsConstant()) {
     const Object& constant = locs.in(1).constant();
@@ -2933,7 +2923,7 @@
 
 
 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("BinarySmiOpInstr");
+  __ Comment("BinarySmiOpInstr");
   if (op_kind() == Token::kSHL) {
     EmitSmiShiftLeft(compiler, this);
     return;
@@ -2962,7 +2952,7 @@
         break;
       }
       case Token::kSUB: {
-        __ TraceSimMsg("kSUB imm");
+        __ Comment("kSUB imm");
         if (deopt == NULL) {
           __ AddImmediate(result, left, -imm);
         } else {
@@ -3022,7 +3012,7 @@
         // sarl operation masks the count to 5 bits.
         const intptr_t kCountLimit = 0x1F;
         const intptr_t value = Smi::Cast(constant).Value();
-        __ TraceSimMsg("kSHR");
+        __ Comment("kSHR");
         __ sra(result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit));
         __ SmiTag(result);
         break;
@@ -3049,7 +3039,7 @@
       break;
     }
     case Token::kSUB: {
-      __ TraceSimMsg("kSUB");
+      __ Comment("kSUB");
       if (deopt == NULL) {
         __ subu(result, left, right);
       } else {
@@ -3059,7 +3049,7 @@
       break;
     }
     case Token::kMUL: {
-      __ TraceSimMsg("kMUL");
+      __ Comment("kMUL");
       __ sra(TMP, left, kSmiTagSize);
       __ mult(TMP, right);
       __ mflo(result);
@@ -4598,7 +4588,7 @@
 
 
 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("PolymorphicInstanceCallInstr");
+  __ Comment("PolymorphicInstanceCallInstr");
   ASSERT(ic_data().NumArgsTested() == 1);
   if (!with_checks()) {
     ASSERT(ic_data().HasOneTarget());
@@ -4642,7 +4632,7 @@
 
 
 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("BranchInstr");
+  __ Comment("BranchInstr");
   comparison()->EmitBranchCode(compiler, this);
 }
 
@@ -4670,7 +4660,12 @@
                                         ICData::kDeoptCheckClass,
                                         licm_hoisted_ ? ICData::kHoisted : 0);
   if (IsNullCheck()) {
-    __ BranchEqual(locs()->in(0).reg(), Object::null_object(), deopt);
+    if (DeoptIfNull()) {
+      __ BranchEqual(locs()->in(0).reg(), Object::null_object(), deopt);
+    } else {
+      ASSERT(DeoptIfNotNull());
+      __ BranchNotEqual(locs()->in(0).reg(), Object::null_object(), deopt);
+    }
     return;
   }
 
@@ -4739,7 +4734,7 @@
 
 
 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("CheckSmiInstr");
+  __ Comment("CheckSmiInstr");
   Register value = locs()->in(0).reg();
   Label* deopt = compiler->AddDeoptStub(deopt_id(),
                                         ICData::kDeoptCheckSmi,
@@ -5004,6 +4999,14 @@
     // Code for a variable shift amount.
     Register shift = locs()->in(1).reg();
 
+    // Code below assumes shift amount is not 0 (cannot shift by 32 - 0).
+    Label non_zero_shift, done;
+    __ bne(shift, ZR, &non_zero_shift);
+    __ delay_slot()->mov(out_lo, left_lo);
+    __ b(&done);
+    __ delay_slot()->mov(out_hi, left_hi);
+    __ Bind(&non_zero_shift);
+
     // Deopt if shift is larger than 63 or less than 0.
     if (has_shift_count_check()) {
       __ sltiu(CMPRES1, shift, Immediate(2*(kMintShiftCountLimit + 1)));
@@ -5017,11 +5020,11 @@
 
     switch (op_kind()) {
       case Token::kSHR: {
-        Label large_shift, done;
+        Label large_shift;
         __ sltiu(CMPRES1, shift, Immediate(32));
         __ beq(CMPRES1, ZR, &large_shift);
 
-        // shift < 32.
+        // 0 < shift < 32.
         __ delay_slot()->ori(TMP, ZR, Immediate(32));
         __ subu(TMP, TMP, shift);  // TMP = 32 - shift; 0 < TMP <= 31.
         __ sllv(out_lo, left_hi, TMP);
@@ -5035,15 +5038,14 @@
         __ sra(out_hi, left_hi, 31);
         __ srav(out_lo, left_hi, shift);  // Only 5 low bits of shift used.
 
-        __ Bind(&done);
         break;
       }
       case Token::kSHL: {
-        Label large_shift, done;
+        Label large_shift;
         __ sltiu(CMPRES1, shift, Immediate(32));
         __ beq(CMPRES1, ZR, &large_shift);
 
-        // shift < 32.
+        // 0 < shift < 32.
         __ delay_slot()->ori(TMP, ZR, Immediate(32));
         __ subu(TMP, TMP, shift);  // TMP = 32 - shift; 0 < TMP <= 31.
         __ srlv(out_hi, left_lo, TMP);
@@ -5077,12 +5079,12 @@
         } else {
           __ mov(out_lo, ZR);
         }
-        __ Bind(&done);
         break;
       }
       default:
         UNREACHABLE();
     }
+    __ Bind(&done);
   }
 }
 
@@ -5393,7 +5395,7 @@
 
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("GotoInstr");
+  __ Comment("GotoInstr");
   if (!compiler->is_optimizing()) {
     if (FLAG_emit_edge_counters) {
       compiler->EmitEdgeCounter();
@@ -5508,7 +5510,6 @@
 
 
 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("StrictCompareInstr");
   __ Comment("StrictCompareInstr");
   ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
 
@@ -5530,7 +5531,7 @@
 
 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
                                         BranchInstr* branch) {
-  __ TraceSimMsg("StrictCompareInstr::EmitBranchCode");
+  __ Comment("StrictCompareInstr::EmitBranchCode");
   ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
 
   BranchLabels labels = compiler->CreateBranchLabels(branch);
@@ -5566,7 +5567,6 @@
 
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  __ TraceSimMsg("AllocateObjectInstr");
   __ Comment("AllocateObjectInstr");
   Isolate* isolate = compiler->isolate();
   StubCode* stub_code = isolate->stub_code();
@@ -5587,10 +5587,6 @@
   StubCode* stub_code = compiler->isolate()->stub_code();
   const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
   compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
-#if defined(DEBUG)
-  __ LoadImmediate(S4, kInvalidObjectPointer);
-  __ LoadImmediate(S5, kInvalidObjectPointer);
-#endif
 }
 
 
@@ -5609,7 +5605,7 @@
 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register typed_data = locs()->in(0).reg();
   const Register result = locs()->out(0).reg();
-  __ TraceSimMsg("GrowRegExpStackInstr");
+  __ Comment("GrowRegExpStackInstr");
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
   __ LoadObject(TMP, Object::null_object());
   __ sw(TMP, Address(SP, 1 * kWordSize));
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index ee1a43b..9e81b43 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -5503,7 +5503,8 @@
   if (IsNullCheck()) {
     __ CompareObject(locs()->in(0).reg(),
                      Object::null_object(), PP);
-    __ j(EQUAL, deopt);
+    Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL;
+    __ j(cond, deopt);
     return;
   }
 
@@ -6410,10 +6411,6 @@
   StubCode* stub_code = compiler->isolate()->stub_code();
   const ExternalLabel label(stub_code->DebugStepCheckEntryPoint());
   compiler->GenerateCall(token_pos(), &label, stub_kind_, locs());
-#if defined(DEBUG)
-  __ movq(R10, Immediate(kInvalidObjectPointer));
-  __ movq(RBX, Immediate(kInvalidObjectPointer));
-#endif
 }
 
 
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index b5b3ccf..5705f29 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -261,7 +261,7 @@
   __ Bind(&init_loop);                                                         \
   __ AddImmediate(R3, 2 * kWordSize);                                          \
   __ cmp(R3, Operand(R1));                                                     \
-  __ strd(R6, Address(R3, -2 * kWordSize), LS);                                \
+  __ strd(R6, R3, -2 * kWordSize, LS);                                         \
   __ b(&init_loop, CC);                                                        \
   __ str(R6, Address(R3, -2 * kWordSize), HI);                                 \
                                                                                \
@@ -348,23 +348,13 @@
 
 
 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
-  if (TargetCPUFeatures::arm_version() == ARMv7) {
-    Label fall_through;
-    TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
-    __ SmiUntag(R0);  // Untags R6. We only want result shifted by one.
-    __ smull(R0, IP, R0, R1);  // IP:R0 <- R0 * R1.
-    __ cmp(IP, Operand(R0, ASR, 31));
-    __ bx(LR, EQ);
-    __ Bind(&fall_through);  // Fall through on overflow.
-  } else if (TargetCPUFeatures::can_divide()) {
-    Label fall_through;
-    TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
-    __ SmiUntag(R0);  // Untags R6. We only want result shifted by one.
-    __ CheckMultSignedOverflow(R0, R1, IP, D0, D1, &fall_through);
-    __ mul(R0, R0, R1);
-    __ Ret();
-    __ Bind(&fall_through);  // Fall through on overflow.
-  }
+  Label fall_through;
+  TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
+  __ SmiUntag(R0);  // Untags R6. We only want result shifted by one.
+  __ smull(R0, IP, R0, R1);  // IP:R0 <- R0 * R1.
+  __ cmp(IP, Operand(R0, ASR, 31));
+  __ bx(LR, EQ);
+  __ Bind(&fall_through);  // Fall through on overflow.
 }
 
 
@@ -800,18 +790,28 @@
 }
 
 
+void Intrinsifier::Bigint_lsh(Assembler* assembler) {
+  // TODO(regis): Implement.
+}
+
+
+void Intrinsifier::Bigint_rsh(Assembler* assembler) {
+  // TODO(regis): Implement.
+}
+
+
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
 
   // R2 = used, R3 = digits
-  __ ldrd(R2, Address(SP, 3 * kWordSize));
+  __ ldrd(R2, SP, 3 * kWordSize);
   // R3 = &digits[0]
   __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
 
   // R4 = a_used, R5 = a_digits
-  __ ldrd(R4, Address(SP, 1 * kWordSize));
+  __ ldrd(R4, SP, 1 * kWordSize);
   // R5 = &a_digits[0]
   __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag));
 
@@ -866,12 +866,12 @@
   //                     Uint32List r_digits)
 
   // R2 = used, R3 = digits
-  __ ldrd(R2, Address(SP, 3 * kWordSize));
+  __ ldrd(R2, SP, 3 * kWordSize);
   // R3 = &digits[0]
   __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
 
   // R4 = a_used, R5 = a_digits
-  __ ldrd(R4, Address(SP, 1 * kWordSize));
+  __ ldrd(R4, SP, 1 * kWordSize);
   // R5 = &a_digits[0]
   __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag));
 
@@ -917,9 +917,6 @@
 
 
 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) {
-  if (TargetCPUFeatures::arm_version() != ARMv7) {
-    return;
-  }
   // Pseudo code:
   // static int _mulAdd(Uint32List x_digits, int xi,
   //                    Uint32List m_digits, int i,
@@ -949,7 +946,7 @@
 
   Label done;
   // R3 = x, no_op if x == 0
-  __ ldrd(R0, Address(SP, 5 * kWordSize));  // R0 = xi as Smi, R1 = x_digits.
+  __ ldrd(R0, SP, 5 * kWordSize);  // R0 = xi as Smi, R1 = x_digits.
   __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R3, FieldAddress(R1, TypedData::data_offset()));
   __ tst(R3, Operand(R3));
@@ -961,12 +958,12 @@
   __ b(&done, EQ);
 
   // R4 = mip = &m_digits[i >> 1]
-  __ ldrd(R0, Address(SP, 3 * kWordSize));  // R0 = i as Smi, R1 = m_digits.
+  __ ldrd(R0, SP, 3 * kWordSize);  // R0 = i as Smi, R1 = m_digits.
   __ add(R1, R1, Operand(R0, LSL, 1));
   __ add(R4, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
 
   // R5 = ajp = &a_digits[j >> 1]
-  __ ldrd(R0, Address(SP, 1 * kWordSize));  // R0 = j as Smi, R1 = a_digits.
+  __ ldrd(R0, SP, 1 * kWordSize);  // R0 = j as Smi, R1 = a_digits.
   __ add(R1, R1, Operand(R0, LSL, 1));
   __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
 
@@ -1022,9 +1019,6 @@
 
 
 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) {
-  if (TargetCPUFeatures::arm_version() != ARMv7) {
-    return;
-  }
   // Pseudo code:
   // static int _sqrAdd(Uint32List x_digits, int i,
   //                    Uint32List a_digits, int used) {
@@ -1052,7 +1046,7 @@
   // }
 
   // R4 = xip = &x_digits[i >> 1]
-  __ ldrd(R2, Address(SP, 2 * kWordSize));  // R2 = i as Smi, R3 = x_digits
+  __ ldrd(R2, SP, 2 * kWordSize);  // R2 = i as Smi, R3 = x_digits
   __ add(R3, R3, Operand(R2, LSL, 1));
   __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
 
@@ -1130,7 +1124,7 @@
 
   // *ajp = low32(t) = R6
   // *(ajp + 1) = high32(t) = R7
-  __ strd(R6, Address(R5, 0));
+  __ strd(R6, R5, 0);
 
   __ Bind(&x_zero);
   __ mov(R0, Operand(Smi::RawValue(1)));  // One digit processed.
@@ -1144,9 +1138,6 @@
 
 
 void Intrinsifier::Montgomery_mulMod(Assembler* assembler) {
-  if (TargetCPUFeatures::arm_version() != ARMv7) {
-    return;
-  }
   // Pseudo code:
   // static int _mulMod(Uint32List args, Uint32List digits, int i) {
   //   uint32_t rho = args[_RHO];  // _RHO == 2.
@@ -1164,7 +1155,7 @@
                           TypedData::data_offset() + 2*Bigint::kBytesPerDigit));
 
   // R2 = digits[i >> 1]
-  __ ldrd(R0, Address(SP, 0 * kWordSize));  // R0 = i as Smi, R1 = digits
+  __ ldrd(R0, SP, 0 * kWordSize);  // R0 = i as Smi, R1 = digits
   __ add(R1, R1, Operand(R0, LSL, 1));
   __ ldr(R2, FieldAddress(R1, TypedData::data_offset()));
 
@@ -1444,44 +1435,41 @@
 //    _state[kSTATE_LO] = state & _MASK_32;
 //    _state[kSTATE_HI] = state >> 32;
 void Intrinsifier::Random_nextState(Assembler* assembler) {
-  // No 32x32 -> 64 bit multiply/accumulate on ARMv5 or ARMv6.
-  if (TargetCPUFeatures::arm_version() == ARMv7) {
-    const Library& math_lib = Library::Handle(Library::MathLibrary());
-    ASSERT(!math_lib.IsNull());
-    const Class& random_class = Class::Handle(
-        math_lib.LookupClassAllowPrivate(Symbols::_Random()));
-    ASSERT(!random_class.IsNull());
-    const Field& state_field = Field::ZoneHandle(
-        random_class.LookupInstanceField(Symbols::_state()));
-    ASSERT(!state_field.IsNull());
-    const Field& random_A_field = Field::ZoneHandle(
-        random_class.LookupStaticField(Symbols::_A()));
-    ASSERT(!random_A_field.IsNull());
-    ASSERT(random_A_field.is_const());
-    const Instance& a_value = Instance::Handle(random_A_field.value());
-    const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
-    // 'a_int_value' is a mask.
-    ASSERT(Utils::IsUint(32, a_int_value));
-    int32_t a_int32_value = static_cast<int32_t>(a_int_value);
+  const Library& math_lib = Library::Handle(Library::MathLibrary());
+  ASSERT(!math_lib.IsNull());
+  const Class& random_class = Class::Handle(
+      math_lib.LookupClassAllowPrivate(Symbols::_Random()));
+  ASSERT(!random_class.IsNull());
+  const Field& state_field = Field::ZoneHandle(
+      random_class.LookupInstanceField(Symbols::_state()));
+  ASSERT(!state_field.IsNull());
+  const Field& random_A_field = Field::ZoneHandle(
+      random_class.LookupStaticField(Symbols::_A()));
+  ASSERT(!random_A_field.IsNull());
+  ASSERT(random_A_field.is_const());
+  const Instance& a_value = Instance::Handle(random_A_field.value());
+  const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
+  // 'a_int_value' is a mask.
+  ASSERT(Utils::IsUint(32, a_int_value));
+  int32_t a_int32_value = static_cast<int32_t>(a_int_value);
 
-    __ ldr(R0, Address(SP, 0 * kWordSize));  // Receiver.
-    __ ldr(R1, FieldAddress(R0, state_field.Offset()));  // Field '_state'.
-    // Addresses of _state[0] and _state[1].
+  __ ldr(R0, Address(SP, 0 * kWordSize));  // Receiver.
+  __ ldr(R1, FieldAddress(R0, state_field.Offset()));  // Field '_state'.
+  // Addresses of _state[0] and _state[1].
 
-    const int64_t disp_0 = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
-    const int64_t disp_1 = disp_0 +
-        Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
+  const int64_t disp_0 = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
+  const int64_t disp_1 = disp_0 +
+      Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
 
-    __ LoadImmediate(R0, a_int32_value);
-    __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag);
-    __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag);
-    __ mov(R6, Operand(0));  // Zero extend unsigned _state[kSTATE_HI].
-    // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3.
-    __ umlal(R3, R6, R0, R2);  // R6:R3 <- R6:R3 + R0 * R2.
-    __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag);
-    __ StoreToOffset(kWord, R6, R1, disp_1 - kHeapObjectTag);
-    __ Ret();
-  }
+  __ LoadImmediate(R0, a_int32_value);
+  __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag);
+  __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag);
+  __ mov(R6, Operand(0));  // Zero extend unsigned _state[kSTATE_HI].
+  // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3.
+  __ umlal(R3, R6, R0, R2);  // R6:R3 <- R6:R3 + R0 * R2.
+  __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag);
+  __ StoreToOffset(kWord, R6, R1, disp_1 - kHeapObjectTag);
+  __ Ret();
 }
 
 
@@ -1886,9 +1874,6 @@
 
 
 void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
-  if (FLAG_use_jscre) {
-    return;
-  }
   static const intptr_t kRegExpParamOffset = 2 * kWordSize;
   static const intptr_t kStringParamOffset = 1 * kWordSize;
   // start_index smi is located at offset 0.
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index f85b09b..baf7a66 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -689,6 +689,16 @@
 }
 
 
+void Intrinsifier::Bigint_lsh(Assembler* assembler) {
+  // TODO(regis): Implement.
+}
+
+
+void Intrinsifier::Bigint_rsh(Assembler* assembler) {
+  // TODO(regis): Implement.
+}
+
+
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
@@ -1937,9 +1947,6 @@
 
 
 void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
-  if (FLAG_use_jscre) {
-    return;
-  }
   static const intptr_t kRegExpParamOffset = 2 * kWordSize;
   static const intptr_t kStringParamOffset = 1 * kWordSize;
   // start_index smi is located at offset 0.
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index bd4ee51..a73612d 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -805,6 +805,16 @@
 }
 
 
+void Intrinsifier::Bigint_lsh(Assembler* assembler) {
+  // TODO(regis): Implement.
+}
+
+
+void Intrinsifier::Bigint_rsh(Assembler* assembler) {
+  // TODO(regis): Implement.
+}
+
+
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
@@ -1931,9 +1941,6 @@
 
 
 void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
-  if (FLAG_use_jscre) {
-    return;
-  }
   static const intptr_t kRegExpParamOffset = 3 * kWordSize;
   static const intptr_t kStringParamOffset = 2 * kWordSize;
   // start_index smi is located at offset 1.
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 61d2799..63c7ac0 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -783,6 +783,16 @@
 }
 
 
+void Intrinsifier::Bigint_lsh(Assembler* assembler) {
+  // TODO(regis): Implement.
+}
+
+
+void Intrinsifier::Bigint_rsh(Assembler* assembler) {
+  // TODO(regis): Implement.
+}
+
+
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
@@ -1959,9 +1969,6 @@
 
 
 void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
-  if (FLAG_use_jscre) {
-    return;
-  }
   static const intptr_t kRegExpParamOffset = 2 * kWordSize;
   static const intptr_t kStringParamOffset = 1 * kWordSize;
   // start_index smi is located at 0.
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index c1d8171..9a5baf3 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -725,6 +725,84 @@
 }
 
 
+void Intrinsifier::Bigint_lsh(Assembler* assembler) {
+  // static void _lsh(Uint32List x_digits, int x_used, int n,
+  //                  Uint32List r_digits)
+
+  __ movq(RDI, Address(RSP, 4 * kWordSize));  // x_digits
+  __ movq(R8, Address(RSP, 3 * kWordSize));  // x_used is Smi
+  __ subq(R8, Immediate(2));  // x_used > 0, Smi. R8 = x_used - 1, round up.
+  __ sarq(R8, Immediate(2));  // R8 + 1 = number of digit pairs to read.
+  __ movq(RCX, Address(RSP, 2 * kWordSize));  // n is Smi
+  __ SmiUntag(RCX);
+  __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
+  __ movq(RSI, RCX);
+  __ sarq(RSI, Immediate(6));  // RSI = n ~/ (2*_DIGIT_BITS).
+  __ leaq(RBX, FieldAddress(RBX, RSI, TIMES_8, TypedData::data_offset()));
+  __ xorq(RAX, RAX);  // RAX = 0.
+  __ movq(RDX, FieldAddress(RDI, R8, TIMES_8, TypedData::data_offset()));
+  __ shldq(RAX, RDX, RCX);
+  __ movq(Address(RBX, R8, TIMES_8, 2 * Bigint::kBytesPerDigit), RAX);
+  Label last;
+  __ cmpq(R8, Immediate(0));
+  __ j(EQUAL, &last, Assembler::kNearJump);
+  Label loop;
+  __ Bind(&loop);
+  __ movq(RAX, RDX);
+  __ movq(RDX,
+          FieldAddress(RDI, R8, TIMES_8,
+                       TypedData::data_offset() - 2 * Bigint::kBytesPerDigit));
+  __ shldq(RAX, RDX, RCX);
+  __ movq(Address(RBX, R8, TIMES_8, 0), RAX);
+  __ decq(R8);
+  __ j(NOT_ZERO, &loop, Assembler::kNearJump);
+  __ Bind(&last);
+  __ xorq(RAX, RAX);  // RAX = 0.
+  __ shldq(RDX, RAX, RCX);
+  __ movq(Address(RBX, 0), RDX);
+  // Returning Object::null() is not required, since this method is private.
+  __ ret();
+}
+
+
+void Intrinsifier::Bigint_rsh(Assembler* assembler) {
+  // static void _rsh(Uint32List x_digits, int x_used, int n,
+  //                  Uint32List r_digits)
+
+  __ movq(RDI, Address(RSP, 4 * kWordSize));  // x_digits
+  __ movq(R8, Address(RSP, 3 * kWordSize));  // x_used is Smi
+  __ subq(R8, Immediate(2));  // x_used > 0, Smi. R8 = x_used - 1, round up.
+  __ sarq(R8, Immediate(2));
+  __ movq(RCX, Address(RSP, 2 * kWordSize));  // n is Smi
+  __ SmiUntag(RCX);
+  __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
+  __ movq(RSI, RCX);
+  __ sarq(RSI, Immediate(6));  // RSI = n ~/ (2*_DIGIT_BITS).
+  __ leaq(RDI, FieldAddress(RDI, RSI, TIMES_8, TypedData::data_offset()));
+  __ movq(RDX, Address(RDI, 0));
+  __ subq(R8, RSI);  // R8 + 1 = number of digit pairs to read.
+  Label last;
+  __ cmpq(R8, Immediate(0));
+  __ j(EQUAL, &last, Assembler::kNearJump);
+  __ xorq(R9, R9);  // R9 = 0.
+  Label loop;
+  __ Bind(&loop);
+  __ movq(RAX, RDX);
+  __ movq(RDX, Address(RDI, R9, TIMES_8, 2 * Bigint::kBytesPerDigit));
+  __ shrdq(RAX, RDX, RCX);
+  __ movq(FieldAddress(RBX, R9, TIMES_8, TypedData::data_offset()), RAX);
+  __ incq(R9);
+  __ cmpq(R9, R8);
+  __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
+  __ Bind(&last);
+  __ xorq(RAX, RAX);  // RAX = 0.
+  __ shrdq(RDX, RAX, RCX);
+  __ movq(FieldAddress(RBX, R8, TIMES_8, TypedData::data_offset()), RDX);
+  // Returning Object::null() is not required, since this method is private.
+  __ ret();
+}
+
+
 void Intrinsifier::Bigint_absAdd(Assembler* assembler) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
@@ -1836,9 +1914,6 @@
 
 
 void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
-  if (FLAG_use_jscre) {
-    return;
-  }
   static const intptr_t kRegExpParamOffset = 3 * kWordSize;
   static const intptr_t kStringParamOffset = 2 * kWordSize;
   // start_index smi is located at offset 1.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 806c712..abc5343 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -536,11 +536,12 @@
   object##_handle_(NULL),
 
 Isolate::Isolate()
-  :   mutator_thread_(new Thread(this)),
+  :   mutator_thread_(NULL),
       vm_tag_(0),
       store_buffer_(),
       message_notify_callback_(NULL),
       name_(NULL),
+      debugger_name_(NULL),
       start_time_(OS::GetCurrentTimeMicros()),
       main_port_(0),
       origin_id_(0),
@@ -603,12 +604,13 @@
 }
 
 Isolate::Isolate(Isolate* original)
-  :   mutator_thread_(new Thread(this)),
+  :   mutator_thread_(NULL),
       vm_tag_(0),
       store_buffer_(true),
       class_table_(original->class_table()),
       message_notify_callback_(NULL),
       name_(NULL),
+      debugger_name_(NULL),
       start_time_(OS::GetCurrentTimeMicros()),
       main_port_(0),
       pause_capability_(0),
@@ -666,6 +668,7 @@
 
 Isolate::~Isolate() {
   free(name_);
+  free(debugger_name_);
   delete heap_;
   delete object_store_;
   delete api_state_;
@@ -682,7 +685,6 @@
   delete spawn_state_;
   delete log_;
   log_ = NULL;
-  delete mutator_thread_;
 }
 
 
@@ -693,31 +695,6 @@
 #endif  // DEBUG
 
 
-void Isolate::SetCurrent(Isolate* current) {
-  Isolate* old_current = Current();
-  if (old_current != NULL) {
-    old_current->set_vm_tag(VMTag::kIdleTagId);
-    old_current->set_thread_state(NULL);
-    Profiler::EndExecution(old_current);
-  }
-  if (current != NULL) {
-    Thread::SetCurrent(current->mutator_thread());
-    ASSERT(current->thread_state() == NULL);
-    InterruptableThreadState* thread_state =
-        ThreadInterrupter::GetCurrentThreadState();
-#if defined(DEBUG)
-    CheckForDuplicateThreadState(thread_state);
-#endif
-    ASSERT(thread_state != NULL);
-    Profiler::BeginExecution(current);
-    current->set_thread_state(thread_state);
-    current->set_vm_tag(VMTag::kVMTagId);
-  } else {
-    Thread::SetCurrent(NULL);
-  }
-}
-
-
 void Isolate::InitOnce() {
   create_callback_ = NULL;
   isolates_list_monitor_ = new Monitor();
@@ -737,7 +714,7 @@
 
   // TODO(5411455): For now just set the recently created isolate as
   // the current isolate.
-  SetCurrent(result);
+  Thread::EnterIsolate(result);
 
   // Setup the isolate specific resuable handles.
 #define REUSABLE_HANDLE_ALLOCATION(object)                                     \
@@ -771,7 +748,6 @@
   result->set_terminate_capability(result->random()->NextUInt64());
 
   result->BuildName(name_prefix);
-
   result->debugger_ = new Debugger();
   result->debugger_->Initialize(result);
   if (FLAG_trace_isolates) {
@@ -815,11 +791,18 @@
 }
 
 
+void Isolate::set_debugger_name(const char* name) {
+  free(debugger_name_);
+  debugger_name_ = strdup(name);
+}
+
+
 void Isolate::BuildName(const char* name_prefix) {
   ASSERT(name_ == NULL);
   if (name_prefix == NULL) {
     name_prefix = "isolate";
   }
+  set_debugger_name(name_prefix);
   if (ServiceIsolate::NameEquals(name_prefix)) {
     name_ = strdup(name_prefix);
     return;
@@ -931,6 +914,7 @@
 
 bool Isolate::MakeRunnable() {
   ASSERT(Isolate::Current() == NULL);
+
   MutexLocker ml(mutex_);
   // Check if we are in a valid state to make the isolate runnable.
   if (is_runnable_ == true) {
@@ -1191,16 +1175,19 @@
     ASSERT(result.IsFunction());
     Function& func = Function::Handle(isolate);
     func ^= result.raw();
-    func = func.ImplicitClosureFunction();
 
     // TODO(turnidge): Currently we need a way to force a one-time
     // breakpoint for all spawned isolates to support isolate
     // debugging.  Remove this once the vmservice becomes the standard
-    // way to debug.
+    // way to debug. Set the breakpoint on the static function instead
+    // of its implicit closure function because that latter is merely
+    // a dispatcher that is marked as undebuggable.
     if (FLAG_break_at_isolate_spawn) {
       isolate->debugger()->OneTimeBreakAtEntry(func);
     }
 
+    func = func.ImplicitClosureFunction();
+
     const Array& capabilities = Array::Handle(Array::New(2));
     Capability& capability = Capability::Handle();
     capability = Capability::New(isolate->pause_capability());
@@ -1428,7 +1415,7 @@
 
   // TODO(5411455): For now just make sure there are no current isolates
   // as we are shutting down the isolate.
-  SetCurrent(NULL);
+  Thread::ExitIsolate();
   Profiler::ShutdownProfilingForIsolate(this);
 }
 
@@ -1532,23 +1519,16 @@
   jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate"));
   jsobj.AddPropertyF("id", "isolates/%" Pd "",
                      static_cast<intptr_t>(main_port()));
-  jsobj.AddPropertyF("mainPort", "%" Pd "",
-                     static_cast<intptr_t>(main_port()));
 
-  // Assign an isolate name based on the entry function.
-  IsolateSpawnState* state = spawn_state();
-  if (state == NULL) {
-    jsobj.AddPropertyF("name", "root");
-  } else if (state->class_name() != NULL) {
-    jsobj.AddPropertyF("name", "%s.%s",
-                       state->class_name(),
-                       state->function_name());
-  } else {
-    jsobj.AddPropertyF("name", "%s", state->function_name());
-  }
+  jsobj.AddProperty("name", debugger_name());
+  jsobj.AddPropertyF("number", "%" Pd "",
+                     static_cast<intptr_t>(main_port()));
   if (ref) {
     return;
   }
+  int64_t start_time_millis = start_time() / kMicrosecondsPerMillisecond;
+  jsobj.AddProperty64("startTime", start_time_millis);
+  IsolateSpawnState* state = spawn_state();
   if (state != NULL) {
     const Object& entry = Object::Handle(this, state->ResolveFunction());
     if (!entry.IsNull() && entry.IsFunction()) {
@@ -1603,12 +1583,6 @@
     jsobj.AddProperty("error", error, false);
   }
 
-  {
-    JSONObject typeargsRef(&jsobj, "canonicalTypeArguments");
-    typeargsRef.AddProperty("type", "@TypeArgumentsList");
-    typeargsRef.AddProperty("id", "typearguments");
-    typeargsRef.AddProperty("name", "canonical type arguments");
-  }
   bool is_io_enabled = false;
   {
     const GrowableObjectArray& libs =
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 54c92fe..beafd96 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -122,7 +122,6 @@
     Thread* thread = Thread::Current();
     return thread == NULL ? NULL : thread->isolate();
   }
-  static void SetCurrent(Isolate* isolate);
 
   static void InitOnce();
   static Isolate* Init(const char* name_prefix, bool is_vm_isolate = false);
@@ -170,7 +169,7 @@
   // No other threads operating on this isolate may execute Dart code.
   // TODO(koda): Remove after caching current thread in generated code.
   Thread* mutator_thread() {
-    DEBUG_ASSERT(IsIsolateOf(mutator_thread_));
+    DEBUG_ASSERT(mutator_thread_ == NULL || IsIsolateOf(mutator_thread_));
     return mutator_thread_;
   }
 #if defined(DEBUG)
@@ -178,6 +177,9 @@
 #endif  // DEBUG
 
   const char* name() const { return name_; }
+  const char* debugger_name() const { return debugger_name_; }
+  void set_debugger_name(const char* name);
+
   // TODO(koda): Move to Thread.
   class Log* Log() const;
 
@@ -680,6 +682,10 @@
     user_tag_ = tag;
   }
 
+  void set_mutator_thread(Thread* thread) {
+    mutator_thread_ = thread;
+  }
+
   template<class T> T* AllocateReusableHandle();
 
   Thread* mutator_thread_;
@@ -689,6 +695,7 @@
   MegamorphicCacheTable megamorphic_cache_table_;
   Dart_MessageNotifyCallback message_notify_callback_;
   char* name_;
+  char* debugger_name_;
   int64_t start_time_;
   Dart_Port main_port_;
   Dart_Port origin_id_;  // Isolates created by spawnFunc have some origin id.
@@ -799,7 +806,8 @@
   static void AddIsolateTolist(Isolate* isolate);
   static void RemoveIsolateFromList(Isolate* isolate);
   static void CheckForDuplicateThreadState(InterruptableThreadState* state);
-  static Monitor* isolates_list_monitor_;
+
+  static Monitor* isolates_list_monitor_;  // Protects isolates_list_head_
   static Isolate* isolates_list_head_;
 
 #define REUSABLE_FRIEND_DECLARATION(name)                                      \
@@ -820,13 +828,14 @@
  public:
   explicit StartIsolateScope(Isolate* new_isolate)
       : new_isolate_(new_isolate), saved_isolate_(Isolate::Current()) {
+    // TODO(koda): Audit users; passing NULL goes against naming of this class.
     if (new_isolate_ == NULL) {
       // Do nothing.
       return;
     }
     if (saved_isolate_ != new_isolate_) {
       ASSERT(Isolate::Current() == NULL);
-      Isolate::SetCurrent(new_isolate_);
+      Thread::EnterIsolate(new_isolate_);
       new_isolate_->SetStackLimitFromStackBase(
           Isolate::GetCurrentStackPointer());
     }
@@ -839,7 +848,10 @@
     }
     if (saved_isolate_ != new_isolate_) {
       new_isolate_->ClearStackLimit();
-      Isolate::SetCurrent(saved_isolate_);
+      Thread::ExitIsolate();
+      if (saved_isolate_ != NULL) {
+        Thread::EnterIsolate(saved_isolate_);
+      }
     }
   }
 
@@ -860,9 +872,12 @@
         saved_isolate_(Isolate::Current()),
         saved_stack_limit_(saved_isolate_
                            ? saved_isolate_->saved_stack_limit() : 0) {
+    // TODO(koda): Audit users; why would these two ever be equal?
     if (saved_isolate_ != new_isolate_) {
-      Isolate::SetCurrent(new_isolate_);
-      if (new_isolate_ != NULL) {
+      if (new_isolate_ == NULL) {
+        Thread::ExitIsolate();
+      } else {
+        Thread::EnterIsolate(new_isolate_);
         // Don't allow dart code to execute.
         new_isolate_->SetStackLimit(~static_cast<uword>(0));
       }
@@ -871,8 +886,11 @@
 
   ~SwitchIsolateScope() {
     if (saved_isolate_ != new_isolate_) {
-      Isolate::SetCurrent(saved_isolate_);
+      if (new_isolate_ != NULL) {
+        Thread::ExitIsolate();
+      }
       if (saved_isolate_ != NULL) {
+        Thread::EnterIsolate(saved_isolate_);
         saved_isolate_->SetStackLimit(saved_stack_limit_);
       }
     }
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 388c0d3..06c13fc 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -274,12 +274,14 @@
 
 
 void JSONStream::PrintProperty(const char* name, intptr_t i) {
+  ASSERT(Utils::IsJavascriptInt(i));
   PrintPropertyName(name);
   PrintValue(i);
 }
 
 
 void JSONStream::PrintProperty64(const char* name, int64_t i) {
+  ASSERT(Utils::IsJavascriptInt64(i));
   PrintPropertyName(name);
   PrintValue64(i);
 }
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 08260c3..d62c588 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -155,6 +155,8 @@
 #define CORE_LIB_INTRINSIC_LIST(V)                                             \
   V(_Smi, ~, Smi_bitNegate, 134149043)                                         \
   V(_Smi, get:bitLength, Smi_bitLength, 869986288)                             \
+  V(_Bigint, _lsh, Bigint_lsh, 1318834243)                                     \
+  V(_Bigint, _rsh, Bigint_rsh, 1239668932)                                     \
   V(_Bigint, _absAdd, Bigint_absAdd, 222437051)                                \
   V(_Bigint, _absSub, Bigint_absSub, 599465997)                                \
   V(_Bigint, _mulAdd, Bigint_mulAdd, 1696801459)                               \
@@ -367,8 +369,8 @@
   V(_ByteDataView, setUint32, ByteDataViewSetUint32, 284405389)                \
   V(_ByteDataView, setInt64, ByteDataViewSetInt64, 486916661)                  \
   V(_ByteDataView, setUint64, ByteDataViewSetUint64, 1432663320)               \
-  V(_ByteDataView, setFloat32, ByteDataViewSetFloat32, 733187060)              \
-  V(_ByteDataView, setFloat64, ByteDataViewSetFloat64, 1138577739)             \
+  V(_ByteDataView, setFloat32, ByteDataViewSetFloat32, 344976311)              \
+  V(_ByteDataView, setFloat64, ByteDataViewSetFloat64, 1480166018)             \
   V(_ByteDataView, getInt8, ByteDataViewGetInt8, 1383732403)                   \
   V(_ByteDataView, getUint8, ByteDataViewGetUint8, 806641537)                  \
   V(_ByteDataView, getInt16, ByteDataViewGetInt16, 76281079)                   \
@@ -377,8 +379,8 @@
   V(_ByteDataView, getUint32, ByteDataViewGetUint32, 760435927)                \
   V(_ByteDataView, getInt64, ByteDataViewGetInt64, 364361487)                  \
   V(_ByteDataView, getUint64, ByteDataViewGetUint64, 565678407)                \
-  V(_ByteDataView, getFloat32, ByteDataViewGetFloat32, 924006540)              \
-  V(_ByteDataView, getFloat64, ByteDataViewGetFloat64, 1863927528)             \
+  V(_ByteDataView, getFloat32, ByteDataViewGetFloat32, 1979131043)             \
+  V(_ByteDataView, getFloat64, ByteDataViewGetFloat64, 164756117)              \
   V(::, asin, MathASin, 1651042633)                                            \
   V(::, acos, MathACos, 1139647090)                                            \
   V(::, atan, MathATan, 1668754384)                                            \
@@ -399,6 +401,8 @@
 
 // A list of core function that should never be inlined.
 #define INLINE_BLACK_LIST(V)                                                   \
+  V(_Bigint, _lsh, Bigint_lsh, 1318834243)                                     \
+  V(_Bigint, _rsh, Bigint_rsh, 1239668932)                                     \
   V(_Bigint, _absAdd, Bigint_absAdd, 222437051)                                \
   V(_Bigint, _absSub, Bigint_absSub, 599465997)                                \
   V(_Bigint, _mulAdd, Bigint_mulAdd, 1696801459)                               \
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index f7ff985..a3cd5c1 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -48,7 +48,7 @@
   }
   // Start the native port without a current isolate.
   IsolateSaver saver(Isolate::Current());
-  Isolate::SetCurrent(NULL);
+  Thread::ExitIsolate();
 
   NativeMessageHandler* nmh = new NativeMessageHandler(name, handler);
   Dart_Port port_id = PortMap::CreatePort(nmh);
@@ -60,7 +60,7 @@
 DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id) {
   // Close the native port without a current isolate.
   IsolateSaver saver(Isolate::Current());
-  Isolate::SetCurrent(NULL);
+  Thread::ExitIsolate();
 
   // TODO(turnidge): Check that the port is native before trying to close.
   return PortMap::ClosePort(native_port_id);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 103a394..f80f10b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -142,7 +142,6 @@
     reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::exception_handlers_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
-RawClass* Object::deopt_info_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::context_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -559,9 +558,6 @@
   cls = Class::New<ExceptionHandlers>();
   exception_handlers_class_ = cls.raw();
 
-  cls = Class::New<DeoptInfo>();
-  deopt_info_class_ = cls.raw();
-
   cls = Class::New<Context>();
   context_class_ = cls.raw();
 
@@ -816,7 +812,6 @@
   SET_CLASS_NAME(stackmap, Stackmap);
   SET_CLASS_NAME(var_descriptors, LocalVarDescriptors);
   SET_CLASS_NAME(exception_handlers, ExceptionHandlers);
-  SET_CLASS_NAME(deopt_info, DeoptInfo);
   SET_CLASS_NAME(context, Context);
   SET_CLASS_NAME(context_scope, ContextScope);
   SET_CLASS_NAME(icdata, ICData);
@@ -2817,7 +2812,9 @@
   const String& func_src =
       String::Handle(BuildClosureSource(param_names, expr));
   Script& script = Script::Handle();
-  script = Script::New(Symbols::Empty(), func_src, RawScript::kSourceTag);
+  script = Script::New(Symbols::EvalSourceUri(),
+                       func_src,
+                       RawScript::kSourceTag);
   // 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());
@@ -3207,8 +3204,6 @@
       return Symbols::LocalVarDescriptors().raw();
     case kExceptionHandlersCid:
       return Symbols::ExceptionHandlers().raw();
-    case kDeoptInfoCid:
-      return Symbols::DeoptInfo().raw();
     case kContextCid:
       return Symbols::Context().raw();
     case kContextScopeCid:
@@ -4120,16 +4115,10 @@
     JSONArray interfaces_array(&jsobj, "interfaces");
     const Array& interface_array = Array::Handle(interfaces());
     Type& interface_type = Type::Handle();
-    Class& interface_cls = Class::Handle();
     if (!interface_array.IsNull()) {
       for (intptr_t i = 0; i < interface_array.Length(); ++i) {
-        // TODO(turnidge): Use the Type directly once regis has added
-        // types to the vmservice.
         interface_type ^= interface_array.At(i);
-        if (interface_type.HasResolvedTypeClass()) {
-          interface_cls = interface_type.type_class();
-          interfaces_array.AddValue(interface_cls);
-        }
+        interfaces_array.AddValue(interface_type);
       }
     }
   }
@@ -4430,8 +4419,6 @@
   const String& user_name = String::Handle(PrettyName());
   const String& vm_name = String::Handle(Name());
   AddNameProperties(&jsobj, user_name, vm_name);
-  jsobj.AddProperty("length", Length());
-  jsobj.AddProperty("numInstantiations", NumInstantiations());
   if (ref) {
     return;
   }
@@ -4444,7 +4431,7 @@
     }
   }
   if (!IsInstantiated()) {
-    JSONArray jsarr(&jsobj, "instantiations");
+    JSONArray jsarr(&jsobj, "_instantiations");
     Array& prior_instantiations = Array::Handle(instantiations());
     ASSERT(prior_instantiations.Length() > 0);  // Always at least a sentinel.
     TypeArguments& type_args = TypeArguments::Handle();
@@ -5107,7 +5094,7 @@
   Isolate* isolate = Isolate::Current();
   const Code& current_code = Code::Handle(isolate, CurrentCode());
 
-  if (FLAG_trace_disabling_optimized_code) {
+  if (FLAG_trace_deoptimization) {
     OS::Print("Disabling optimized code: '%s' entry: %#" Px "\n",
       ToFullyQualifiedCString(),
       current_code.EntryPoint());
@@ -5308,43 +5295,43 @@
 const char* Function::KindToCString(RawFunction::Kind kind) {
   switch (kind) {
     case RawFunction::kRegularFunction:
-      return "kRegularFunction";
+      return "RegularFunction";
       break;
     case RawFunction::kClosureFunction:
-      return "kClosureFunction";
+      return "ClosureFunction";
       break;
     case RawFunction::kSignatureFunction:
-      return "kSignatureFunction";
+      return "SignatureFunction";
       break;
     case RawFunction::kGetterFunction:
-      return "kGetterFunction";
+      return "GetterFunction";
       break;
     case RawFunction::kSetterFunction:
-      return "kSetterFunction";
+      return "SetterFunction";
       break;
     case RawFunction::kConstructor:
-      return "kConstructor";
+      return "Constructor";
       break;
     case RawFunction::kImplicitGetter:
-      return "kImplicitGetter";
+      return "ImplicitGetter";
       break;
     case RawFunction::kImplicitSetter:
-      return "kImplicitSetter";
+      return "ImplicitSetter";
       break;
     case RawFunction::kImplicitStaticFinalGetter:
-      return "kImplicitStaticFinalGetter";
+      return "ImplicitStaticFinalGetter";
       break;
     case RawFunction::kMethodExtractor:
-      return "kMethodExtractor";
+      return "MethodExtractor";
       break;
     case RawFunction::kNoSuchMethodDispatcher:
-      return "kNoSuchMethodDispatcher";
+      return "NoSuchMethodDispatcher";
       break;
     case RawFunction::kInvokeFieldDispatcher:
-      return "kInvokeFieldDispatcher";
+      return "InvokeFieldDispatcher";
       break;
     case RawFunction::kIrregexpFunction:
-      return "kIrregexpFunction";
+      return "IrregexpFunction";
       break;
     default:
       UNREACHABLE();
@@ -6824,16 +6811,16 @@
   const String& user_name = String::Handle(PrettyName());
   const String& vm_name = String::Handle(name());
   AddNameProperties(&jsobj, user_name, vm_name);
-  if (cls.IsTopLevel()) {
-    const Library& library = Library::Handle(cls.library());
-    jsobj.AddProperty("owningLibrary", library);
-  } else {
-    jsobj.AddProperty("owningClass", cls);
-  }
   const Function& parent = Function::Handle(parent_function());
   if (!parent.IsNull()) {
-    jsobj.AddProperty("parent", parent);
+    jsobj.AddProperty("owner", parent);
+  } else if (cls.IsTopLevel()) {
+    const Library& library = Library::Handle(cls.library());
+    jsobj.AddProperty("owner", library);
+  } else {
+    jsobj.AddProperty("owner", cls);
   }
+
   const char* kind_string = Function::KindToCString(kind());
   jsobj.AddProperty("kind", kind_string);
   if (ref) {
@@ -6841,13 +6828,19 @@
   }
   jsobj.AddProperty("static", is_static());
   jsobj.AddProperty("const", is_const());
-  jsobj.AddProperty("optimizable", is_optimizable());
-  jsobj.AddProperty("inlinable", CanBeInlined());
-  jsobj.AddProperty("unoptimizedCode", Object::Handle(unoptimized_code()));
-  jsobj.AddProperty("usageCounter", usage_counter());
-  jsobj.AddProperty("optimizedCallSiteCount", optimized_call_site_count());
-  jsobj.AddProperty("code", Object::Handle(CurrentCode()));
-  jsobj.AddProperty("deoptimizations",
+  Code& code = Code::Handle(CurrentCode());
+  if (!code.IsNull()) {
+    jsobj.AddProperty("code", code);
+  }
+  jsobj.AddProperty("_optimizable", is_optimizable());
+  jsobj.AddProperty("_inlinable", CanBeInlined());
+  code = unoptimized_code();
+  if (!code.IsNull()) {
+    jsobj.AddProperty("_unoptimizedCode", code);
+  }
+  jsobj.AddProperty("_usageCounter", usage_counter());
+  jsobj.AddProperty("_optimizedCallSiteCount", optimized_call_site_count());
+  jsobj.AddProperty("_deoptimizations",
                     static_cast<intptr_t>(deoptimization_counter()));
 
   const Script& script = Script::Handle(this->script());
@@ -7196,23 +7189,23 @@
   if (ref) {
     return;
   }
-  jsobj.AddProperty("guardNullable", is_nullable());
+  jsobj.AddProperty("_guardNullable", is_nullable());
   if (guarded_cid() == kIllegalCid) {
-    jsobj.AddProperty("guardClass", "unknown");
+    jsobj.AddProperty("_guardClass", "unknown");
   } else if (guarded_cid() == kDynamicCid) {
-    jsobj.AddProperty("guardClass", "dynamic");
+    jsobj.AddProperty("_guardClass", "dynamic");
   } else {
     ClassTable* table = Isolate::Current()->class_table();
     ASSERT(table->IsValidIndex(guarded_cid()));
     cls ^= table->At(guarded_cid());
-    jsobj.AddProperty("guardClass", cls);
+    jsobj.AddProperty("_guardClass", cls);
   }
   if (guarded_list_length() == kUnknownFixedLength) {
-    jsobj.AddProperty("guardLength", "unknown");
+    jsobj.AddProperty("_guardLength", "unknown");
   } else if (guarded_list_length() == kNoFixedLength) {
-    jsobj.AddProperty("guardLength", "variable");
+    jsobj.AddProperty("_guardLength", "variable");
   } else {
-    jsobj.AddProperty("guardLength", guarded_list_length());
+    jsobj.AddProperty("_guardLength", guarded_list_length());
   }
   const Class& origin_cls = Class::Handle(origin());
   const Script& script = Script::Handle(origin_cls.script());
@@ -8427,6 +8420,12 @@
   }
 
   while (scan_position != length) {
+    if (snippet_start == -1) {
+      if ((line == from_line) && (column == from_column)) {
+        snippet_start = scan_position;
+      }
+    }
+
     char c = src.CharAt(scan_position);
     if (c == '\n') {
       line++;
@@ -8442,11 +8441,7 @@
     scan_position++;
     column++;
 
-    if (snippet_start == -1) {
-      if ((line == from_line) && (column == from_column)) {
-        snippet_start = scan_position;
-      }
-    } else if ((line == to_line) && (column == to_column)) {
+    if ((line == to_line) && (column == to_column)) {
       snippet_end = scan_position;
       break;
     }
@@ -8522,7 +8517,7 @@
   if (ref) {
     return;
   }
-  jsobj.AddProperty("owningLibrary", lib);
+  jsobj.AddProperty("library", lib);
   const String& source = String::Handle(Source());
   jsobj.AddPropertyStr("source", source);
 
@@ -8750,7 +8745,7 @@
 static RawString* MakeFunctionMetaName(const Function& func) {
   const String& cname =
       String::Handle(MakeClassMetaName(Class::Handle(func.origin())));
-  String& fname = String::Handle(func.name());
+  String& fname = String::Handle(func.QualifiedPrettyName());
   fname = String::Concat(Symbols::At(), fname);
   return String::Concat(cname, fname);
 }
@@ -11140,113 +11135,104 @@
 }
 
 
-intptr_t DeoptInfo::Length() const {
-  return Smi::Value(raw_ptr()->length_);
-}
-
-
-intptr_t DeoptInfo::FromIndex(intptr_t index) const {
+intptr_t DeoptInfo::FrameSize(const TypedData& packed) {
   NoSafepointScope no_safepoint;
-  return *(EntryAddr(index, kFromIndex));
+  typedef ReadStream::Raw<sizeof(intptr_t), intptr_t> Reader;
+  ReadStream read_stream(reinterpret_cast<uint8_t*>(packed.DataAddr(0)),
+                         packed.LengthInBytes());
+  return Reader::Read(&read_stream);
 }
 
 
-intptr_t DeoptInfo::Instruction(intptr_t index) const {
+intptr_t DeoptInfo::NumMaterializations(
+    const GrowableArray<DeoptInstr*>& unpacked) {
+  intptr_t num = 0;
+  while (unpacked[num]->kind() == DeoptInstr::kMaterializeObject) {
+    num++;
+  }
+  return num;
+}
+
+
+void DeoptInfo::UnpackInto(const Array& table,
+                           const TypedData& packed,
+                           GrowableArray<DeoptInstr*>* unpacked,
+                           intptr_t length) {
   NoSafepointScope no_safepoint;
-  return *(EntryAddr(index, kInstruction));
-}
+  typedef ReadStream::Raw<sizeof(intptr_t), intptr_t> Reader;
+  ReadStream read_stream(reinterpret_cast<uint8_t*>(packed.DataAddr(0)),
+                         packed.LengthInBytes());
+  const intptr_t frame_size = Reader::Read(&read_stream);  // Skip frame size.
+  USE(frame_size);
 
+  const intptr_t suffix_length = Reader::Read(&read_stream);
+  if (suffix_length != 0) {
+    ASSERT(suffix_length > 1);
+    const intptr_t info_number = Reader::Read(&read_stream);
 
-intptr_t DeoptInfo::FrameSize() const {
-  return TranslationLength() - NumMaterializations();
-}
-
-
-intptr_t DeoptInfo::TranslationLength() const {
-  intptr_t length = Length();
-  if (Instruction(length - 1) != DeoptInstr::kSuffix) return length;
-
-  // If the last command is a suffix, add in the length of the suffix and
-  // do not count the suffix command as a translation command.
-  intptr_t ignored = 0;
-  intptr_t suffix_length =
-      DeoptInstr::DecodeSuffix(FromIndex(length - 1), &ignored);
-  return length + suffix_length - 1;
-}
-
-
-intptr_t DeoptInfo::NumMaterializations() const {
-  intptr_t pos = 0;
-  while (Instruction(pos) == DeoptInstr::kMaterializeObject) {
-    pos++;
+    TypedData& suffix = TypedData::Handle();
+    Smi& offset = Smi::Handle();
+    Smi& reason_and_flags = Smi::Handle();
+    DeoptTable::GetEntry(
+      table, info_number, &offset, &suffix, &reason_and_flags);
+    UnpackInto(table, suffix, unpacked, suffix_length);
   }
-  return pos;
-}
 
-
-void DeoptInfo::ToInstructions(const Array& table,
-                               GrowableArray<DeoptInstr*>* instructions) const {
-  ASSERT(instructions->is_empty());
-  Smi& offset = Smi::Handle();
-  DeoptInfo& info = DeoptInfo::Handle(raw());
-  Smi& reason_and_flags = Smi::Handle();
-  intptr_t index = 0;
-  intptr_t length = TranslationLength();
-  while (index < length) {
-    intptr_t instruction = info.Instruction(index);
-    intptr_t from_index = info.FromIndex(index);
-    if (instruction == DeoptInstr::kSuffix) {
-      // Suffix instructions cause us to 'jump' to another translation,
-      // changing info, length and index.
-      intptr_t info_number = 0;
-      intptr_t suffix_length =
-          DeoptInstr::DecodeSuffix(from_index, &info_number);
-      DeoptTable::GetEntry(
-          table, info_number, &offset, &info, &reason_and_flags);
-      length = info.TranslationLength();
-      index = length - suffix_length;
-    } else {
-      instructions->Add(DeoptInstr::Create(instruction, from_index));
-      ++index;
-    }
+  while ((read_stream.PendingBytes() > 0) &&
+         (unpacked->length() < length)) {
+    const intptr_t instruction = Reader::Read(&read_stream);
+    const intptr_t from_index = Reader::Read(&read_stream);
+    unpacked->Add(DeoptInstr::Create(instruction, from_index));
   }
 }
 
 
-const char* DeoptInfo::ToCString() const {
-  if (Length() == 0) {
-    return "No DeoptInfo";
-  }
-  // Convert to DeoptInstr.
-  GrowableArray<DeoptInstr*> deopt_instrs(Length());
-  for (intptr_t i = 0; i < Length(); i++) {
-    deopt_instrs.Add(DeoptInstr::Create(Instruction(i), FromIndex(i)));
-  }
+void DeoptInfo::Unpack(const Array& table,
+                       const TypedData& packed,
+                       GrowableArray<DeoptInstr*>* unpacked) {
+  ASSERT(unpacked->is_empty());
+
+  // Pass kMaxInt32 as the length to unpack all instructions from the
+  // packed stream.
+  UnpackInto(table, packed, unpacked, kMaxInt32);
+
+  unpacked->Reverse();
+}
+
+
+const char* DeoptInfo::ToCString(const Array& deopt_table,
+                                 const TypedData& packed) {
+  GrowableArray<DeoptInstr*> deopt_instrs;
+  Unpack(deopt_table, packed, &deopt_instrs);
+
   // Compute the buffer size required.
   intptr_t len = 1;  // Trailing '\0'.
-  for (intptr_t i = 0; i < Length(); i++) {
+  for (intptr_t i = 0; i < deopt_instrs.length(); i++) {
     len += OS::SNPrint(NULL, 0, "[%s]", deopt_instrs[i]->ToCString());
   }
+
   // Allocate the buffer.
   char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
+
   // Layout the fields in the buffer.
   intptr_t index = 0;
-  for (intptr_t i = 0; i < Length(); i++) {
+  for (intptr_t i = 0; i < deopt_instrs.length(); i++) {
     index += OS::SNPrint((buffer + index),
                          (len - index),
                          "[%s]",
                          deopt_instrs[i]->ToCString());
   }
+
   return buffer;
 }
 
 
 // Returns a bool so it can be asserted.
 bool DeoptInfo::VerifyDecompression(const GrowableArray<DeoptInstr*>& original,
-                                    const Array& deopt_table) const {
-  intptr_t length = TranslationLength();
-  GrowableArray<DeoptInstr*> unpacked(length);
-  ToInstructions(deopt_table, &unpacked);
+                                    const Array& deopt_table,
+                                    const TypedData& packed) {
+  GrowableArray<DeoptInstr*> unpacked;
+  Unpack(deopt_table, packed, &unpacked);
   ASSERT(unpacked.length() == original.length());
   for (intptr_t i = 0; i < unpacked.length(); ++i) {
     ASSERT(unpacked[i]->Equals(*original[i]));
@@ -11255,47 +11241,6 @@
 }
 
 
-void DeoptInfo::PrintJSONImpl(JSONStream* stream, bool ref) const {
-  Object::PrintJSONImpl(stream, ref);
-}
-
-
-RawDeoptInfo* DeoptInfo::New(intptr_t num_commands) {
-  ASSERT(Object::deopt_info_class() != Class::null());
-  if ((num_commands < 0) || (num_commands > kMaxElements)) {
-    FATAL1("Fatal error in DeoptInfo::New(): invalid num_commands %" Pd "\n",
-           num_commands);
-  }
-  DeoptInfo& result = DeoptInfo::Handle();
-  {
-    uword size = DeoptInfo::InstanceSize(num_commands);
-    RawObject* raw = Object::Allocate(DeoptInfo::kClassId,
-                                      size,
-                                      Heap::kOld);
-    NoSafepointScope no_safepoint;
-    result ^= raw;
-    result.SetLength(num_commands);
-  }
-  return result.raw();
-}
-
-
-void DeoptInfo::SetLength(intptr_t value) const {
-  // This is only safe because we create a new Smi, which does not cause
-  // heap allocation.
-  StoreSmi(&raw_ptr()->length_, Smi::New(value));
-}
-
-
-void DeoptInfo::SetAt(intptr_t index,
-                      intptr_t instr_kind,
-                      intptr_t from_index) const {
-  NoSafepointScope no_safepoint;
-  *(EntryAddr(index, kInstruction)) = instr_kind;
-  *(EntryAddr(index, kFromIndex)) = from_index;
-}
-
-
 const char* ICData::ToCString() const {
   const char* kFormat = "ICData target:'%s' num-args: %" Pd
                         " num-checks: %" Pd "";
@@ -12108,7 +12053,7 @@
 }
 
 
-RawDeoptInfo* Code::GetDeoptInfoAtPc(uword pc,
+RawTypedData* Code::GetDeoptInfoAtPc(uword pc,
                                      ICData::DeoptReasonId* deopt_reason,
                                      uint32_t* deopt_flags) const {
   ASSERT(is_optimized());
@@ -12120,7 +12065,7 @@
   intptr_t length = DeoptTable::GetLength(table);
   Smi& offset = Smi::Handle();
   Smi& reason_and_flags = Smi::Handle();
-  DeoptInfo& info = DeoptInfo::Handle();
+  TypedData& info = TypedData::Handle();
   for (intptr_t i = 0; i < length; ++i) {
     DeoptTable::GetEntry(table, i, &offset, &info, &reason_and_flags);
     if (pc == (code_entry + offset.Value())) {
@@ -12131,7 +12076,7 @@
     }
   }
   *deopt_reason = ICData::kDeoptUnknown;
-  return DeoptInfo::null();
+  return TypedData::null();
 }
 
 
@@ -12542,20 +12487,20 @@
   AddTypeProperties(&jsobj, "Code", JSONType(), ref);
   jsobj.AddPropertyF("id", "code/%" Px64"-%" Px "", compile_timestamp(),
                      EntryPoint());
-  jsobj.AddPropertyF("start", "%" Px "", EntryPoint());
-  jsobj.AddPropertyF("end", "%" Px "", EntryPoint() + Size());
-  jsobj.AddProperty("optimized", is_optimized());
-  jsobj.AddProperty("alive", is_alive());
-  const Object& obj = Object::Handle(owner());
+  const String& user_name = String::Handle(PrettyName());
+  const String& vm_name = String::Handle(Name());
+  AddNameProperties(&jsobj, user_name, vm_name);
   const bool is_stub = IsStubCode() || IsAllocationStubCode();
   if (is_stub) {
     jsobj.AddProperty("kind", "Stub");
   } else {
     jsobj.AddProperty("kind", "Dart");
   }
-  const String& user_name = String::Handle(PrettyName());
-  const String& vm_name = String::Handle(Name());
-  AddNameProperties(&jsobj, user_name, vm_name);
+  jsobj.AddProperty("_optimized", is_optimized());
+  if (ref) {
+    return;
+  }
+  const Object& obj = Object::Handle(owner());
   if (obj.IsFunction()) {
     jsobj.AddProperty("function", obj);
   } else {
@@ -12566,13 +12511,13 @@
     func.AddProperty("name", user_name.ToCString());
     AddNameProperties(&func, user_name, vm_name);
   }
-  if (ref) {
-    return;
-  }
+  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);
+  jsobj.AddProperty("_objectPool", array);
   {
-    JSONArray jsarr(&jsobj, "disassembly");
+    JSONArray jsarr(&jsobj, "_disassembly");
     if (is_alive()) {
       // Only disassemble alive code objects.
       DisassembleToJSONStream formatter(jsarr);
@@ -12581,12 +12526,12 @@
   }
   const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
   if (!descriptors.IsNull()) {
-    JSONObject desc(&jsobj, "descriptors");
+    JSONObject desc(&jsobj, "_descriptors");
     descriptors.PrintToJSONObject(&desc, false);
   }
   const Array& inlined_function_table = Array::Handle(inlined_id_to_function());
   if (!inlined_function_table.IsNull()) {
-    JSONArray inlined_functions(&jsobj, "inlinedFunctions");
+    JSONArray inlined_functions(&jsobj, "_inlinedFunctions");
     Function& function = Function::Handle();
     for (intptr_t i = 0; i < inlined_function_table.Length(); i++) {
       function ^= inlined_function_table.At(i);
@@ -12599,7 +12544,7 @@
     Smi& start = Smi::Handle();
     Smi& end = Smi::Handle();
     Smi& temp_smi = Smi::Handle();
-    JSONArray inline_intervals(&jsobj, "inlinedIntervals");
+    JSONArray inline_intervals(&jsobj, "_inlinedIntervals");
     for (intptr_t i = 0; i < intervals.Length() - Code::kInlIntNumEntries;
          i += Code::kInlIntNumEntries) {
       start ^= intervals.At(i + Code::kInlIntStart);
@@ -15946,18 +15891,11 @@
 }
 
 
-// dart2js represents integers as double precision floats, which can represent
-// anything in the range -2^53 ... 2^53.
-static bool IsJavascriptInt(int64_t value) {
-  return ((-0x20000000000000LL <= value) && (value <= 0x20000000000000LL));
-}
-
-
 RawInteger* Integer::New(int64_t value, Heap::Space space, const bool silent) {
   const bool is_smi = Smi::IsValid(value);
   if (!silent &&
       FLAG_throw_on_javascript_int_overflow &&
-      !IsJavascriptInt(value)) {
+      !Utils::IsJavascriptInt64(value)) {
     const Integer& i = is_smi ?
         Integer::Handle(Smi::New(static_cast<intptr_t>(value))) :
         Integer::Handle(Mint::New(value, space));
@@ -16055,7 +15993,7 @@
       value = AsInt64Value();
     }
   }
-  return !IsJavascriptInt(value);
+  return !Utils::IsJavascriptInt64(value);
 }
 
 
@@ -20083,6 +20021,7 @@
 RawReceivePort* ReceivePort::New(Dart_Port id,
                                  bool is_control_port,
                                  Heap::Space space) {
+  ASSERT(id != ILLEGAL_PORT);
   Isolate* isolate = Isolate::Current();
   const SendPort& send_port =
       SendPort::Handle(isolate, SendPort::New(id, isolate->origin_id()));
@@ -20123,6 +20062,7 @@
 RawSendPort* SendPort::New(Dart_Port id,
                            Dart_Port origin_id,
                            Heap::Space space) {
+  ASSERT(id != ILLEGAL_PORT);
   SendPort& result = SendPort::Handle();
   {
     RawObject* raw = Object::Allocate(SendPort::kClassId,
@@ -20406,21 +20346,16 @@
 }
 
 
-RawJSRegExp* JSRegExp::New(intptr_t len, Heap::Space space) {
-  if (len < 0 || len > kMaxElements) {
-    // This should be caught before we reach here.
-    FATAL1("Fatal error in JSRegexp::New: invalid len %" Pd "\n", len);
-  }
+RawJSRegExp* JSRegExp::New(Heap::Space space) {
   JSRegExp& result = JSRegExp::Handle();
   {
     RawObject* raw = Object::Allocate(JSRegExp::kClassId,
-                                      JSRegExp::InstanceSize(len),
+                                      JSRegExp::InstanceSize(),
                                       space);
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.set_type(kUnitialized);
     result.set_flags(0);
-    result.SetLength(len);
   }
   return result.raw();
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 4ca6980..289cceb 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1797,9 +1797,6 @@
 
   RawCode* unoptimized_code() const { return raw_ptr()->unoptimized_code_; }
   void set_unoptimized_code(const Code& value) const;
-  static intptr_t unoptimized_code_offset() {
-    return OFFSET_OF(RawFunction, unoptimized_code_);
-  }
   bool HasCode() const;
 
   static intptr_t instructions_offset() {
@@ -3545,81 +3542,38 @@
 // field-value pairs) are added as artificial slots to the expression stack
 // of the bottom-most frame. They are removed from the stack at the very end
 // of deoptimization by the deoptimization stub.
-class DeoptInfo : public Object {
- private:
-  // Describes the layout of deopt info data. The index of a deopt-info entry
-  // is implicitly the target slot in which the value is written into.
-  enum {
-    kInstruction = 0,
-    kFromIndex,
-    kNumberOfEntries,
-  };
-
+class DeoptInfo : public AllStatic {
  public:
-  // The number of instructions.
-  intptr_t Length() const;
-
-  // The number of real (non-suffix) instructions needed to execute the
-  // deoptimization translation.
-  intptr_t TranslationLength() const;
-
   // Size of the frame part of the translation not counting kMaterializeObject
   // instructions in the prefix.
-  intptr_t FrameSize() const;
+  static intptr_t FrameSize(const TypedData& packed);
 
   // Returns the number of kMaterializeObject instructions in the prefix.
-  intptr_t NumMaterializations() const;
-
-  static RawDeoptInfo* New(intptr_t num_commands);
-
-  static const intptr_t kBytesPerElement = (kNumberOfEntries * kWordSize);
-  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
-
-  static intptr_t InstanceSize() {
-    ASSERT(sizeof(RawDeoptInfo) ==
-           OFFSET_OF_RETURNED_VALUE(RawDeoptInfo, data));
-    return 0;
-  }
-
-  static intptr_t InstanceSize(intptr_t len) {
-    ASSERT(0 <= len && len <= kMaxElements);
-    return RoundedAllocationSize(sizeof(RawDeoptInfo) +
-                                 (len * kBytesPerElement));
-  }
-
-  // 'index' corresponds to target, to-index.
-  void SetAt(intptr_t index,
-             intptr_t instr_kind,
-             intptr_t from_index) const;
-
-  intptr_t Instruction(intptr_t index) const;
-  intptr_t FromIndex(intptr_t index) const;
-  intptr_t ToIndex(intptr_t index) const {
-    return index;
-  }
+  static intptr_t NumMaterializations(const GrowableArray<DeoptInstr*>&);
 
   // Unpack the entire translation into an array of deoptimization
   // instructions.  This copies any shared suffixes into the array.
-  void ToInstructions(const Array& table,
-                      GrowableArray<DeoptInstr*>* instructions) const;
+  static void Unpack(const Array& table,
+                     const TypedData& packed,
+                     GrowableArray<DeoptInstr*>* instructions);
 
+  // Size of the frame part of the translation not counting kMaterializeObject
+  // instructions in the prefix.
+  static const char* ToCString(const Array& table,
+                               const TypedData& packed);
 
   // Returns true iff decompression yields the same instructions as the
   // original.
-  bool VerifyDecompression(const GrowableArray<DeoptInstr*>& original,
-                           const Array& deopt_table) const;
+  static bool VerifyDecompression(const GrowableArray<DeoptInstr*>& original,
+                                  const Array& deopt_table,
+                                  const TypedData& packed);
+
 
  private:
-  intptr_t* EntryAddr(intptr_t index, intptr_t entry_offset) const {
-    ASSERT((index >=0) && (index < Length()));
-    intptr_t data_index = (index * kNumberOfEntries) + entry_offset;
-    return &UnsafeMutableNonPointer(raw_ptr()->data())[data_index];
-  }
-
-  void SetLength(intptr_t value) const;
-
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(DeoptInfo, Object);
-  friend class Class;
+  static void UnpackInto(const Array& table,
+                         const TypedData& packed,
+                         GrowableArray<DeoptInstr*>* instructions,
+                         intptr_t length);
 };
 
 
@@ -4015,7 +3969,7 @@
     return raw_ptr()->static_calls_target_table_;
   }
 
-  RawDeoptInfo* GetDeoptInfoAtPc(uword pc,
+  RawTypedData* GetDeoptInfoAtPc(uword pc,
                                  ICData::DeoptReasonId* deopt_reason,
                                  uint32_t* deopt_flags) const;
 
@@ -7542,24 +7496,11 @@
 
   virtual bool CanonicalizeEquals(const Instance& other) const;
 
-  static const intptr_t kBytesPerElement = 1;
-  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
-
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(RawJSRegExp) == OFFSET_OF_RETURNED_VALUE(RawJSRegExp, data));
-    if (FLAG_use_jscre) {
-      return 0;
-    }
     return RoundedAllocationSize(sizeof(RawJSRegExp));
   }
 
-  static intptr_t InstanceSize(intptr_t len) {
-    ASSERT(0 <= len && len <= kMaxElements);
-    return RoundedAllocationSize(
-        sizeof(RawJSRegExp) + (len * kBytesPerElement));
-  }
-
-  static RawJSRegExp* New(intptr_t length, Heap::Space space = Heap::kNew);
+  static RawJSRegExp* New(Heap::Space space = Heap::kNew);
 
  private:
   void set_type(RegExType type) const {
@@ -7578,12 +7519,6 @@
     return FlagsBits::decode(raw_ptr()->type_flags_);
   }
 
-  void SetLength(intptr_t value) const {
-    // This is only safe because we create a new Smi, which does not cause
-    // heap allocation.
-    StoreSmi(&raw_ptr()->data_length_, Smi::New(value));
-  }
-
   FINAL_HEAP_OBJECT_IMPLEMENTATION(JSRegExp, Instance);
   friend class Class;
 };
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 1a349ed..7b23600 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2645,6 +2645,7 @@
   if (!FLAG_write_protect_code) {
     // Since this test is expected to crash, crash if write protection of code
     // is switched off.
+    // TODO(regis, fschneider): Should this be FATAL() instead?
     OS::DebugBreak();
   }
 }
@@ -4209,8 +4210,8 @@
     elideSubstring("classes", js.ToCString(), buffer);
     EXPECT_STREQ(
         "{\"type\":\"@Function\",\"id\":\"\",\"name\":\"toString\","
-        "\"owningClass\":{\"type\":\"@Class\",\"id\":\"\",\"name\":\"bool\"},"
-        "\"kind\":\"kRegularFunction\"}",
+        "\"owner\":{\"type\":\"@Class\",\"id\":\"\",\"name\":\"bool\"},"
+        "\"kind\":\"RegularFunction\"}",
         buffer);
   }
   // Library reference
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 3d513ec..55c6c36 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -504,11 +504,16 @@
 }
 
 
+// TODO(regis, iposva): When this function is no longer called from the
+// CodeImmutability test in object_test.cc, it will be called only from the
+// simulator, which means that only the Intel implementation is needed.
 void OS::DebugBreak() {
 #if defined(HOST_ARCH_X64) || defined(HOST_ARCH_IA32)
   asm("int $3");
-#elif defined(HOST_ARCH_ARM)
+#elif defined(HOST_ARCH_ARM) && !defined(__THUMBEL__)
   asm("svc #0x9f0001");  // __ARM_NR_breakpoint
+#elif defined(HOST_ARCH_ARM) && defined(__THUMBEL__)
+  UNIMPLEMENTED();
 #elif defined(HOST_ARCH_MIPS) || defined(HOST_ARCH_ARM64)
   UNIMPLEMENTED();
 #else
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 457f06e..e55380c 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -23,8 +23,6 @@
 
 namespace dart {
 
-class Isolate;
-
 // Low-level operations on OS platform threads.
 class OSThread : AllStatic {
  public:
@@ -63,13 +61,15 @@
   void Unlock();
 
 #if defined(DEBUG)
-  Isolate* Owner() const { return owner_; }
+  bool IsOwnedByCurrentThread() const {
+    return owner_ == OSThread::GetCurrentThreadId();
+  }
 #endif  // defined(DEBUG)
 
  private:
   MutexData data_;
 #if defined(DEBUG)
-  Isolate* owner_;
+  ThreadId owner_;
 #endif  // defined(DEBUG)
 
   DISALLOW_COPY_AND_ASSIGN(Mutex);
diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc
index f4b5233..57de1b0 100644
--- a/runtime/vm/os_thread_android.cc
+++ b/runtime/vm/os_thread_android.cc
@@ -11,7 +11,6 @@
 #include <sys/time.h>  // NOLINT
 
 #include "platform/assert.h"
-#include "vm/isolate.h"
 
 namespace dart {
 
@@ -197,7 +196,7 @@
 
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = NULL;
+  owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
 }
 
@@ -209,7 +208,7 @@
 
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  ASSERT(owner_ == NULL);
+  ASSERT(owner_ == OSThread::kInvalidThreadId);
 #endif  // defined(DEBUG)
 }
 
@@ -221,7 +220,7 @@
   ASSERT(result == 0);  // Verify no other errors.
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = Isolate::Current();
+  owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
 }
 
@@ -235,7 +234,7 @@
   ASSERT(result == 0);  // Verify no other errors.
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = Isolate::Current();
+  owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
   return true;
 }
@@ -244,8 +243,8 @@
 void Mutex::Unlock() {
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  ASSERT(owner_ == Isolate::Current());
-  owner_ = NULL;
+  ASSERT(IsOwnedByCurrentThread());
+  owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
   int result = pthread_mutex_unlock(data_.mutex());
   // Specifically check for wrong thread unlocking to aid debugging.
diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc
index a2b3cff..b1b97fd 100644
--- a/runtime/vm/os_thread_linux.cc
+++ b/runtime/vm/os_thread_linux.cc
@@ -12,7 +12,6 @@
 #include <sys/time.h>  // NOLINT
 
 #include "platform/assert.h"
-#include "vm/isolate.h"
 
 namespace dart {
 
@@ -198,7 +197,7 @@
 
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = NULL;
+  owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
 }
 
@@ -210,7 +209,7 @@
 
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  ASSERT(owner_ == NULL);
+  ASSERT(owner_ == OSThread::kInvalidThreadId);
 #endif  // defined(DEBUG)
 }
 
@@ -222,7 +221,7 @@
   ASSERT(result == 0);  // Verify no other errors.
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = Isolate::Current();
+  owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
 }
 
@@ -236,7 +235,7 @@
   ASSERT(result == 0);  // Verify no other errors.
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = Isolate::Current();
+  owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
   return true;
 }
@@ -245,8 +244,8 @@
 void Mutex::Unlock() {
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  ASSERT(owner_ == Isolate::Current());
-  owner_ = NULL;
+  ASSERT(IsOwnedByCurrentThread());
+  owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
   int result = pthread_mutex_unlock(data_.mutex());
   // Specifically check for wrong thread unlocking to aid debugging.
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index 279425a..2102887 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -19,7 +19,6 @@
 #include <mach/thread_act.h>  // NOLINT
 
 #include "platform/assert.h"
-#include "vm/isolate.h"
 
 namespace dart {
 
@@ -203,7 +202,7 @@
 
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = NULL;
+  owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
 }
 
@@ -215,7 +214,7 @@
 
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  ASSERT(owner_ == NULL);
+  ASSERT(owner_ == OSThread::kInvalidThreadId);
 #endif  // defined(DEBUG)
 }
 
@@ -227,7 +226,7 @@
   ASSERT(result == 0);  // Verify no other errors.
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = Isolate::Current();
+  owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
 }
 
@@ -241,7 +240,7 @@
   ASSERT(result == 0);  // Verify no other errors.
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = Isolate::Current();
+  owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
   return true;
 }
@@ -250,8 +249,8 @@
 void Mutex::Unlock() {
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  ASSERT(owner_ == Isolate::Current());
-  owner_ = NULL;
+  ASSERT(IsOwnedByCurrentThread());
+  owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
   int result = pthread_mutex_unlock(data_.mutex());
   // Specifically check for wrong thread unlocking to aid debugging.
diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc
index e240b50..ff6ced0 100644
--- a/runtime/vm/os_thread_win.cc
+++ b/runtime/vm/os_thread_win.cc
@@ -10,7 +10,6 @@
 #include <process.h>  // NOLINT
 
 #include "platform/assert.h"
-#include "vm/isolate.h"
 
 namespace dart {
 
@@ -173,7 +172,7 @@
   }
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = NULL;
+  owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
 }
 
@@ -182,7 +181,7 @@
   CloseHandle(data_.semaphore_);
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  ASSERT(owner_ == NULL);
+  ASSERT(owner_ == OSThread::kInvalidThreadId);
 #endif  // defined(DEBUG)
 }
 
@@ -194,7 +193,7 @@
   }
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  owner_ = Isolate::Current();
+  owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
 }
 
@@ -205,7 +204,7 @@
   if (result == WAIT_OBJECT_0) {
     // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-    owner_ = Isolate::Current();
+    owner_ = OSThread::GetCurrentThreadId();
 #endif  // defined(DEBUG)
     return true;
   }
@@ -220,8 +219,8 @@
 void Mutex::Unlock() {
   // When running with assertions enabled we do track the owner.
 #if defined(DEBUG)
-  ASSERT(owner_ == Isolate::Current());
-  owner_ = NULL;
+  ASSERT(IsOwnedByCurrentThread());
+  owner_ = OSThread::kInvalidThreadId;
 #endif  // defined(DEBUG)
   BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL);
   if (result == 0) {
diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h
index 06abc31..c6b4f38 100644
--- a/runtime/vm/pages.h
+++ b/runtime/vm/pages.h
@@ -10,6 +10,7 @@
 #include "vm/lockers.h"
 #include "vm/ring_buffer.h"
 #include "vm/spaces.h"
+#include "vm/thread.h"
 #include "vm/virtual_memory.h"
 
 namespace dart {
@@ -226,7 +227,7 @@
      IncreaseCapacityInWordsLocked(increase_in_words);
   }
   void IncreaseCapacityInWordsLocked(intptr_t increase_in_words) {
-    DEBUG_ASSERT(pages_lock_->Owner() == Isolate::Current());
+    DEBUG_ASSERT(pages_lock_->IsOwnedByCurrentThread());
     usage_.capacity_in_words += increase_in_words;
   }
   intptr_t ExternalInWords() const {
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 0a2b0fb..6bfd9c8 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -62,7 +62,7 @@
 
 
 // Quick access to the current isolate and zone.
-#define I (thread()->isolate())
+#define I (isolate())
 #define Z (zone())
 
 
@@ -318,7 +318,7 @@
 
 // For parsing a compilation unit.
 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos)
-    : thread_(Thread::Current()),
+    : isolate_(Thread::Current()->isolate()),
       script_(Script::Handle(zone(), script.raw())),
       tokens_iterator_(TokenStream::Handle(zone(), script.tokens()),
                        token_pos),
@@ -347,7 +347,7 @@
 Parser::Parser(const Script& script,
                ParsedFunction* parsed_function,
                intptr_t token_position)
-    : thread_(Thread::Current()),
+    : isolate_(Thread::Current()->isolate()),
       script_(Script::Handle(zone(), script.raw())),
       tokens_iterator_(TokenStream::Handle(zone(), script.tokens()),
                        token_position),
@@ -764,18 +764,6 @@
 };
 
 
-static bool HasReturnNode(SequenceNode* seq) {
-  if (seq->length() == 0) {
-    return false;
-  } else if ((seq->length()) == 1 &&
-             (seq->NodeAt(seq->length() - 1)->IsSequenceNode())) {
-    return HasReturnNode(seq->NodeAt(seq->length() - 1)->AsSequenceNode());
-  } else {
-    return seq->NodeAt(seq->length() - 1)->IsReturnNode();
-  }
-}
-
-
 void Parser::ParseClass(const Class& cls) {
   if (!cls.is_synthesized_class()) {
     Isolate* isolate = Isolate::Current();
@@ -906,16 +894,6 @@
       UNREACHABLE();
   }
 
-  if (!HasReturnNode(node_sequence)) {
-    // Add implicit return node. The implicit return value of synchronous
-    // generator closures is false, to indicate that there are no more
-    // elements in the iterable. In other cases the implicit return value
-    // is null.
-    AstNode* return_value = func.IsSyncGenClosure()
-        ? new LiteralNode(func.end_token_pos(), Bool::False())
-        : new LiteralNode(func.end_token_pos(), Instance::ZoneHandle());
-    node_sequence->Add(new ReturnNode(func.end_token_pos(), return_value));
-  }
   if (parsed_function->has_expression_temp_var()) {
     node_sequence->scope()->AddVariable(parsed_function->expression_temp_var());
   }
@@ -1566,16 +1544,21 @@
 }
 
 
-void Parser::SkipBlock() {
-  ASSERT(CurrentToken() == Token::kLBRACE);
+void Parser::SkipToMatching() {
+  Token::Kind opening_token = CurrentToken();
+  ASSERT((opening_token == Token::kLBRACE) ||
+         (opening_token == Token::kLPAREN));
   GrowableArray<Token::Kind> token_stack(8);
-  // Adding the first kLBRACE here, because it will be consumed in the loop
-  // right away.
-  token_stack.Add(CurrentToken());
-  const intptr_t block_start_pos = TokenPos();
+  GrowableArray<intptr_t> token_pos_stack(8);
+  // Adding the first opening brace here, because it will be consumed
+  // in the loop right away.
+  token_stack.Add(opening_token);
+  const intptr_t start_pos =  TokenPos();
+  intptr_t opening_pos = start_pos;
+  token_pos_stack.Add(start_pos);
   bool is_match = true;
   bool unexpected_token_found = false;
-  Token::Kind token;
+  Token::Kind token = opening_token;
   intptr_t token_pos;
   do {
     ConsumeToken();
@@ -1586,15 +1569,22 @@
       case Token::kLPAREN:
       case Token::kLBRACK:
         token_stack.Add(token);
+        token_pos_stack.Add(token_pos);
         break;
       case Token::kRBRACE:
-        is_match = token_stack.RemoveLast() == Token::kLBRACE;
+        opening_token = token_stack.RemoveLast();
+        opening_pos = token_pos_stack.RemoveLast();
+        is_match = opening_token == Token::kLBRACE;
         break;
       case Token::kRPAREN:
-        is_match = token_stack.RemoveLast() == Token::kLPAREN;
+        opening_token = token_stack.RemoveLast();
+        opening_pos = token_pos_stack.RemoveLast();
+        is_match = opening_token == Token::kLPAREN;
         break;
       case Token::kRBRACK:
-        is_match = token_stack.RemoveLast() == Token::kLBRACK;
+        opening_token = token_stack.RemoveLast();
+        opening_pos = token_pos_stack.RemoveLast();
+        is_match = opening_token == Token::kLBRACK;
         break;
       case Token::kEOS:
         unexpected_token_found = true;
@@ -1605,13 +1595,34 @@
     }
   } while (!token_stack.is_empty() && is_match && !unexpected_token_found);
   if (!is_match) {
-    ReportError(token_pos, "unbalanced '%s'", Token::Str(token));
+    const Error& error = Error::Handle(
+        LanguageError::NewFormatted(Error::Handle(),
+            script_, opening_pos, Report::kWarning, Heap::kNew,
+            "unbalanced '%s' opens here", Token::Str(opening_token)));
+    ReportErrors(error, script_, token_pos,
+                 "unbalanced '%s'", Token::Str(token));
   } else if (unexpected_token_found) {
-    ReportError(block_start_pos, "unterminated block");
+    ReportError(start_pos, "unterminated '%s'", Token::Str(opening_token));
   }
 }
 
 
+
+void Parser::SkipBlock() {
+  ASSERT(CurrentToken() == Token::kLBRACE);
+  SkipToMatching();
+}
+
+
+// Skips tokens up to and including matching closing parenthesis.
+void Parser::SkipToMatchingParenthesis() {
+  ASSERT(CurrentToken() == Token::kLPAREN);
+  SkipToMatching();
+  ASSERT(CurrentToken() == Token::kRPAREN);
+  ConsumeToken();
+}
+
+
 void Parser::ParseFormalParameter(bool allow_explicit_default_value,
                                   bool evaluate_metadata,
                                   ParamList* params) {
@@ -3346,6 +3357,7 @@
   } else if (func.IsAsyncGenClosure()) {
     body = CloseAsyncGeneratorClosure(body);
   }
+  EnsureHasReturnStatement(body, end_token_pos);
   current_block_->statements->Add(body);
   innermost_function_ = saved_innermost_function.raw();
   last_used_try_index_ = saved_try_index;
@@ -3388,23 +3400,6 @@
 }
 
 
-// Skips tokens up to matching closing parenthesis.
-void Parser::SkipToMatchingParenthesis() {
-  Token::Kind current_token = CurrentToken();
-  ASSERT(current_token == Token::kLPAREN);
-  int level = 0;
-  do {
-    if (current_token == Token::kLPAREN) {
-      level++;
-    } else if (current_token == Token::kRPAREN) {
-      level--;
-    }
-    ConsumeToken();
-    current_token = CurrentToken();
-  } while ((level > 0) && (current_token != Token::kEOS));
-}
-
-
 void Parser::SkipInitializers() {
   ASSERT(CurrentToken() == Token::kCOLON);
   do {
@@ -6837,6 +6832,22 @@
 }
 
 
+// Add a return node to the sequence if necessary.
+void Parser::EnsureHasReturnStatement(SequenceNode* seq, intptr_t return_pos) {
+  if ((seq->length() == 0) ||
+      !seq->NodeAt(seq->length() - 1)->IsReturnNode()) {
+    const Function& func = innermost_function();
+    // The implicit return value of synchronous generator closures is false,
+    // to indicate that there are no more elements in the iterable.
+    // In other cases the implicit return value is null.
+    AstNode* return_value = func.IsSyncGenClosure()
+        ? new LiteralNode(return_pos, Bool::False())
+        : new LiteralNode(return_pos, Instance::ZoneHandle());
+    seq->Add(new ReturnNode(return_pos, return_value));
+  }
+}
+
+
 SequenceNode* Parser::CloseBlock() {
   SequenceNode* statements = current_block_->statements;
   if (current_block_->scope != NULL) {
@@ -7306,10 +7317,12 @@
   result_type = Type::DynamicType();
 
   const intptr_t function_pos = TokenPos();
+  intptr_t metadata_pos = -1;
   if (is_literal) {
     ASSERT(CurrentToken() == Token::kLPAREN);
     function_name = &Symbols::AnonymousClosure();
   } else {
+    metadata_pos = SkipMetadata();
     if (CurrentToken() == Token::kVOID) {
       ConsumeToken();
       result_type = Type::VoidType();
@@ -7359,6 +7372,9 @@
                                             innermost_function(),
                                             function_pos);
     function.set_result_type(result_type);
+    if (metadata_pos >= 0) {
+      library_.AddFunctionMetadata(function, metadata_pos);
+    }
   }
 
   // The function type needs to be finalized at compile time, since the closure
@@ -7722,6 +7738,7 @@
 bool Parser::IsFunctionDeclaration() {
   const intptr_t saved_pos = TokenPos();
   bool is_external = false;
+  SkipMetadata();
   if (is_top_level_) {
     if (is_patch_source() &&
         (CurrentToken() == Token::kIDENT) &&
@@ -8293,6 +8310,23 @@
 }
 
 
+// Build an AST node for static call to Dart function print(str).
+// Used during debugging to insert print in generated dart code.
+AstNode* Parser::DartPrint(const char* str) {
+  const Library& lib = Library::Handle(Library::CoreLibrary());
+  const Function& print_fn = Function::ZoneHandle(
+      Z, lib.LookupFunctionAllowPrivate(Symbols::print()));
+  ASSERT(!print_fn.IsNull());
+  ArgumentListNode* one_arg = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
+  String& msg = String::Handle(String::NewFormatted("%s", str));
+  one_arg->Add(new(Z) LiteralNode(Scanner::kNoSourcePos,
+               String::ZoneHandle(Symbols::New(msg))));
+  AstNode* print_call =
+      new(Z) StaticCallNode(Scanner::kNoSourcePos, print_fn, one_arg);
+  return print_call;
+}
+
+
 AstNode* Parser::ParseAwaitForStatement(String* label_name) {
   TRACE_PARSER("ParseAwaitForStatement");
   ASSERT(IsAwaitKeyword());
@@ -8460,7 +8494,6 @@
                                                loop_var_assignment_pos);
     ASSERT(loop_var_assignment != NULL);
   }
-
   current_block_->statements->Add(loop_var_assignment);
 
   // Now parse the for-in loop statement or block.
@@ -10621,8 +10654,8 @@
   } else {
     arguments = implicit_arguments;
   }
-  const GrowableObjectArray& names = GrowableObjectArray::Handle(Z,
-      GrowableObjectArray::New(Heap::kOld));
+  const GrowableObjectArray& names =
+      GrowableObjectArray::Handle(Z, GrowableObjectArray::New(Heap::kOld));
   bool named_argument_seen = false;
   if (LookaheadToken(1) != Token::kRPAREN) {
     String& arg_name = String::Handle(Z);
@@ -10642,7 +10675,7 @@
             ReportError("duplicate named argument");
           }
         }
-        names.Add(*CurrentLiteral());
+        names.Add(*CurrentLiteral(), Heap::kOld);
         ConsumeToken();  // ident.
         ConsumeToken();  // colon.
       } else if (named_argument_seen) {
@@ -11040,16 +11073,11 @@
           if (primary_node->IsSuper()) {
             ReportError(primary_pos, "illegal use of super");
           }
-          String& name = String::CheckedZoneHandle(
-              primary_node->primary().raw());
+          String& name =
+              String::CheckedZoneHandle(primary_node->primary().raw());
           if (current_function().is_static()) {
-            selector = ThrowNoSuchMethodError(primary_pos,
-                                              current_class(),
-                                              name,
-                                              NULL,  // No arguments.
-                                              InvocationMirror::kStatic,
-                                              InvocationMirror::kMethod,
-                                              NULL);  // No existing function.
+            // The static call will be converted to throwing a NSM error.
+            selector = ParseStaticCall(current_class(), name, primary_pos);
           } else {
             // Treat as call to unresolved (instance) method.
             selector = ParseInstanceCall(LoadReceiver(primary_pos),
@@ -11904,15 +11932,28 @@
           "using '%s' in this context is invalid",
           type_name.ToCString());
     }
-    if (!prefix.IsNull() && prefix.is_deferred_load() && !allow_deferred_type) {
-      ParseTypeArguments(ClassFinalizer::kIgnore);
-      return ClassFinalizer::NewFinalizedMalformedType(
-          Error::Handle(Z),  // No previous error.
-          script_,
-          ident_pos,
-          "using deferred type '%s.%s' is invalid",
-          String::Handle(Z, prefix.name()).ToCString(),
-          type_name.ToCString());
+    if (!prefix.IsNull() && prefix.is_deferred_load()) {
+      // If deferred prefixes are allowed but it is not yet loaded,
+      // remember that this function depends on the prefix.
+      if (allow_deferred_type && !prefix.is_loaded()) {
+        ASSERT(parsed_function() != NULL);
+        parsed_function()->AddDeferredPrefix(prefix);
+      }
+      // If the deferred prefixes are not allowed, or if the prefix
+      // is not yet loaded, return a malformed type. Otherwise, handle
+      // resolution below, as needed.
+      if (!prefix.is_loaded() || !allow_deferred_type) {
+        ParseTypeArguments(ClassFinalizer::kIgnore);
+        return ClassFinalizer::NewFinalizedMalformedType(
+            Error::Handle(Z),  // No previous error.
+            script_,
+            ident_pos,
+            !prefix.is_loaded()
+                ? "deferred type '%s.%s' is not yet loaded"
+                : "using deferred type '%s.%s' is invalid",
+            String::Handle(Z, prefix.name()).ToCString(),
+            type_name.ToCString());
+      }
     }
   }
   Object& type_class = Object::Handle(Z);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index cfb6a76..3b81d0b 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -41,7 +41,7 @@
 class ParsedFunction : public ZoneAllocated {
  public:
   ParsedFunction(Thread* thread, const Function& function)
-      : thread_(thread),
+      : isolate_(thread->isolate()),
         function_(function),
         code_(Code::Handle(zone(), function.unoptimized_code())),
         node_sequence_(NULL),
@@ -150,12 +150,11 @@
   void record_await() { have_seen_await_expr_ = true; }
   bool have_seen_await() const { return have_seen_await_expr_; }
 
-  Thread* thread() const { return thread_; }
-  Isolate* isolate() const { return thread()->isolate(); }
-  Zone* zone() const { return thread()->zone(); }
+  Isolate* isolate() const { return isolate_; }
+  Zone* zone() const { return isolate()->current_zone(); }
 
  private:
-  Thread* thread_;
+  Isolate* isolate_;
   const Function& function_;
   Code& code_;
   SequenceNode* node_sequence_;
@@ -325,9 +324,10 @@
   bool IsYieldKeyword();
 
   void SkipIf(Token::Kind);
+  void SkipToMatching();
+  void SkipToMatchingParenthesis();
   void SkipBlock();
   intptr_t SkipMetadata();
-  void SkipToMatchingParenthesis();
   void SkipTypeArguments();
   void SkipType(bool allow_void);
   void SkipInitializers();
@@ -350,6 +350,8 @@
   void SkipQualIdent();
   void SkipFunctionPreamble();
 
+  AstNode* DartPrint(const char* str);
+
   void CheckConstructorCallTypeArguments(intptr_t pos,
                                          const Function& constructor,
                                          const TypeArguments& type_arguments);
@@ -533,6 +535,7 @@
                             const ArgumentsDescriptor& desc,
                             Array* default_values);
 
+  void EnsureHasReturnStatement(SequenceNode* seq, intptr_t return_pos);
   void ChainNewBlock(LocalScope* outer_scope);
   void OpenBlock();
   void OpenLoopBlock();
@@ -796,11 +799,10 @@
 
   RawInstance* TryCanonicalize(const Instance& instance, intptr_t token_pos);
 
-  Thread* thread() const { return thread_; }
-  Isolate* isolate() const { return thread()->isolate(); }
-  Zone* zone() const { return thread()->zone(); }
+  Isolate* isolate() const { return isolate_; }
+  Zone* zone() const { return isolate()->current_zone(); }
 
-  Thread* thread_;  // Cached current thread.
+  Isolate* isolate_;  // Cached current isolate.
 
   Script& script_;
   TokenStream::Iterator tokens_iterator_;
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index cfb9ac8..5a75068 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -25,6 +25,14 @@
 
 
 intptr_t PortMap::FindPort(Dart_Port port) {
+  // ILLEGAL_PORT (0) is used as a sentinel value in Entry.port. The loop below
+  // could return the index to a deleted port when we are searching for
+  // port id ILLEGAL_PORT. Return -1 immediately to indicate the port
+  // does not exist.
+  if (port == ILLEGAL_PORT) {
+    return -1;
+  }
+  ASSERT(port != ILLEGAL_PORT);
   intptr_t index = port % capacity_;
   intptr_t start_index = index;
   Entry entry = map_[index];
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 0ef0d80a..d0b327e 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -169,20 +169,6 @@
       instance_size = ExceptionHandlers::InstanceSize(num_handlers);
       break;
     }
-    case kDeoptInfoCid: {
-      const RawDeoptInfo* raw_deopt_info =
-          reinterpret_cast<const RawDeoptInfo*>(this);
-      intptr_t num_entries = Smi::Value(raw_deopt_info->ptr()->length_);
-      instance_size = DeoptInfo::InstanceSize(num_entries);
-      break;
-    }
-    case kJSRegExpCid: {
-      const RawJSRegExp* raw_jsregexp =
-          reinterpret_cast<const RawJSRegExp*>(this);
-      intptr_t data_length = Smi::Value(raw_jsregexp->ptr()->data_length_);
-      instance_size = JSRegExp::InstanceSize(data_length);
-      break;
-    }
     case kFreeListElement: {
       uword addr = RawObject::ToAddr(const_cast<RawObject*>(this));
       FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
@@ -586,15 +572,6 @@
 }
 
 
-intptr_t RawDeoptInfo::VisitDeoptInfoPointers(
-    RawDeoptInfo* raw_obj, ObjectPointerVisitor* visitor) {
-  RawDeoptInfo* obj = raw_obj->ptr();
-  intptr_t length = Smi::Value(obj->length_);
-  visitor->VisitPointer(reinterpret_cast<RawObject**>(&obj->length_));
-  return DeoptInfo::InstanceSize(length);
-}
-
-
 intptr_t RawContext::VisitContextPointers(RawContext* raw_obj,
                                           ObjectPointerVisitor* visitor) {
   intptr_t num_variables = raw_obj->ptr()->num_variables_;
@@ -904,9 +881,8 @@
                                             ObjectPointerVisitor* visitor) {
   // Make sure that we got here with the tagged pointer as this.
   ASSERT(raw_obj->IsHeapObject());
-  intptr_t length = Smi::Value(raw_obj->ptr()->data_length_);
   visitor->VisitPointers(raw_obj->from(), raw_obj->to());
-  return JSRegExp::InstanceSize(length);
+  return JSRegExp::InstanceSize();
 }
 
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index f4a537f..b0ace7c 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -35,7 +35,6 @@
   V(Stackmap)                                                                  \
   V(LocalVarDescriptors)                                                       \
   V(ExceptionHandlers)                                                         \
-  V(DeoptInfo)                                                                 \
   V(Context)                                                                   \
   V(ContextScope)                                                              \
   V(ICData)                                                                    \
@@ -186,10 +185,6 @@
   kSmiTagShift = 1,
 };
 
-enum {
-  kInvalidObjectPointer = kHeapObjectTag,
-};
-
 enum TypedDataElementType {
 #define V(name) k##name##Element,
 CLASS_LIST_TYPED_DATA(V)
@@ -1244,19 +1239,6 @@
 };
 
 
-// Contains an array of deoptimization commands, e.g., move a specific register
-// into a specific slot of unoptimized frame.
-class RawDeoptInfo : public RawObject {
-  RAW_HEAP_OBJECT_IMPLEMENTATION(DeoptInfo);
-
-  RawSmi* length_;  // Number of deoptimization commands
-
-  // Variable length data follows here.
-  intptr_t* data() { OPEN_ARRAY_START(intptr_t, intptr_t); }
-  const intptr_t* data() const { OPEN_ARRAY_START(intptr_t, intptr_t); }
-};
-
-
 class RawContext : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Context);
 
@@ -1886,9 +1868,8 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(JSRegExp);
 
   RawObject** from() {
-    return reinterpret_cast<RawObject**>(&ptr()->data_length_);
+    return reinterpret_cast<RawObject**>(&ptr()->num_bracket_expressions_);
   }
-  RawSmi* data_length_;
   RawSmi* num_bracket_expressions_;
   RawString* pattern_;  // Pattern to be used for matching.
   RawFunction* one_byte_function_;
@@ -1903,9 +1884,6 @@
   // type: Uninitialized, simple or complex.
   // flags: Represents global/local, case insensitive, multiline.
   int8_t type_flags_;
-
-  // Variable length data follows here.
-  uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
 };
 
 
@@ -2154,7 +2132,6 @@
          (index == kStackmapCid) ||
          (index == kLocalVarDescriptorsCid) ||
          (index == kExceptionHandlersCid) ||
-         (index == kDeoptInfoCid) ||
          (index == kCodeCid) ||
          (index == kContextScopeCid) ||
          (index == kInstanceCid) ||
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 6a9c490..838145c 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1342,22 +1342,6 @@
 }
 
 
-RawDeoptInfo* DeoptInfo::ReadFrom(SnapshotReader* reader,
-                                  intptr_t object_id,
-                                  intptr_t tags,
-                                  Snapshot::Kind kind) {
-  UNREACHABLE();
-  return DeoptInfo::null();
-}
-
-
-void RawDeoptInfo::WriteTo(SnapshotWriter* writer,
-                           intptr_t object_id,
-                           Snapshot::Kind kind) {
-  UNREACHABLE();
-}
-
-
 RawContext* Context::ReadFrom(SnapshotReader* reader,
                               intptr_t object_id,
                               intptr_t tags,
@@ -2767,12 +2751,9 @@
   ASSERT(reader != NULL);
   ASSERT(kind == Snapshot::kMessage);
 
-  // Read the length so that we can determine instance size to allocate.
-  intptr_t len = reader->ReadSmiValue();
-
   // Allocate JSRegExp object.
   JSRegExp& regex = JSRegExp::ZoneHandle(
-      reader->zone(), JSRegExp::New(len, HEAP_SPACE(kind)));
+      reader->zone(), JSRegExp::New(HEAP_SPACE(kind)));
   reader->AddBackRef(object_id, &regex, kIsDeserialized);
 
   // Set the object tags.
@@ -2786,8 +2767,7 @@
   regex.StoreNonPointer(&regex.raw_ptr()->type_flags_,
                         reader->Read<int8_t>());
 
-  // TODO(5411462): Need to implement a way of recompiling the regex.
-
+  // TODO(18854): Need to implement a way of recreating the irrexp functions.
   return regex.raw();
 }
 
@@ -2805,15 +2785,10 @@
   writer->WriteIndexedObject(kJSRegExpCid);
   writer->WriteTags(writer->GetObjectTags(this));
 
-  // Write out the data length field.
-  writer->Write<RawObject*>(ptr()->data_length_);
-
   // Write out all the other fields.
   writer->Write<RawObject*>(ptr()->num_bracket_expressions_);
   writer->WriteObjectImpl(ptr()->pattern_);
   writer->Write<int8_t>(ptr()->type_flags_);
-
-  // Do not write out the data part which is native.
 }
 
 
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index d251935..47e296d 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5148,7 +5148,7 @@
                                           const String& pattern,
                                           bool multi_line,
                                           bool ignore_case) {
-  const JSRegExp& regexp = JSRegExp::Handle(JSRegExp::New(0));
+  const JSRegExp& regexp = JSRegExp::Handle(JSRegExp::New());
 
   regexp.set_pattern(pattern);
 
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index 9db51dd..03abf5a 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -673,7 +673,7 @@
   // Start with captures started previous to current position
   intptr_t capture_count = captures_started();
   // Add count of captures after this position.
-  intptr_t n;
+  uintptr_t n;
   while ((n = current()) != kEndMarker) {
     Advance();
     switch (n) {
@@ -681,7 +681,7 @@
         Advance();
         break;
       case '[': {
-        intptr_t c;
+        uintptr_t c;
         while ((c = current()) != kEndMarker) {
           Advance();
           if (c == '\\') {
diff --git a/runtime/vm/regexp_test.cc b/runtime/vm/regexp_test.cc
index b8b962f..a0f5621 100644
--- a/runtime/vm/regexp_test.cc
+++ b/runtime/vm/regexp_test.cc
@@ -25,9 +25,6 @@
 }
 
 TEST_CASE(RegExp_OneByteString) {
-  if (FLAG_use_jscre)
-    return;
-
   uint8_t chars[] = { 'a', 'b', 'c', 'b', 'a' };
   intptr_t len = ARRAY_SIZE(chars);
   const String& str = String::Handle(
@@ -49,9 +46,6 @@
 }
 
 TEST_CASE(RegExp_TwoByteString) {
-  if (FLAG_use_jscre)
-    return;
-
   uint16_t chars[] = { 'a', 'b', 'c', 'b', 'a' };
   intptr_t len = ARRAY_SIZE(chars);
   const String& str = String::Handle(
@@ -73,9 +67,6 @@
 }
 
 TEST_CASE(RegExp_ExternalOneByteString) {
-  if (FLAG_use_jscre)
-    return;
-
   uint8_t chars[] = { 'a', 'b', 'c', 'b', 'a' };
   intptr_t len = ARRAY_SIZE(chars);
   const String& str = String::Handle(
@@ -97,9 +88,6 @@
 }
 
 TEST_CASE(RegExp_ExternalTwoByteString) {
-  if (FLAG_use_jscre)
-    return;
-
   uint16_t chars[] = { 'a', 'b', 'c', 'b', 'a' };
   intptr_t len = ARRAY_SIZE(chars);
   const String& str = String::Handle(
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 5cb1721..e120572 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -44,7 +44,6 @@
 // TODO(johnmccutchan): Unify embedder service handler lists and their APIs.
 EmbedderServiceHandler* Service::isolate_service_handler_head_ = NULL;
 EmbedderServiceHandler* Service::root_service_handler_head_ = NULL;
-uint32_t Service::event_mask_ = 0;
 struct ServiceMethodDescriptor;
 ServiceMethodDescriptor* FindMethod(const char* method_name);
 
@@ -501,34 +500,14 @@
 }
 
 
-bool Service::EventMaskHas(uint32_t mask) {
-  return (event_mask_ & mask) != 0;
-}
-
-
 bool Service::NeedsEvents() {
   return ServiceIsolate::IsRunning();
 }
 
 
-bool Service::NeedsDebuggerEvents() {
-  return NeedsEvents() && EventMaskHas(kEventFamilyDebugMask);
-}
-
-
-bool Service::NeedsGCEvents() {
-  return NeedsEvents() && EventMaskHas(kEventFamilyGCMask);
-}
-
-
-void Service::SetEventMask(uint32_t mask) {
-  event_mask_ = mask;
-}
-
-
-void Service::SendEvent(intptr_t eventFamilyId,
-                        intptr_t eventType,
+void Service::SendEvent(intptr_t eventType,
                         const Object& eventMessage) {
+  ASSERT(!ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current()));
   if (!ServiceIsolate::IsRunning()) {
     return;
   }
@@ -536,18 +515,10 @@
   ASSERT(isolate != NULL);
   HANDLESCOPE(isolate);
 
-  // Construct a list of the form [eventFamilyId, eventMessage].
-  //
-  // TODO(turnidge): Revisit passing the eventFamilyId here at all.
-  const Array& list = Array::Handle(Array::New(2));
-  ASSERT(!list.IsNull());
-  list.SetAt(0, Integer::Handle(Integer::New(eventFamilyId)));
-  list.SetAt(1, eventMessage);
-
   // Push the event to port_.
   uint8_t* data = NULL;
   MessageWriter writer(&data, &allocator, false);
-  writer.WriteMessage(list);
+  writer.WriteMessage(eventMessage);
   intptr_t len = writer.BytesWritten();
   if (FLAG_trace_service) {
     OS::Print("vm-service: Pushing event of type %" Pd ", len %" Pd "\n",
@@ -559,8 +530,7 @@
 }
 
 
-void Service::SendEvent(intptr_t eventFamilyId,
-                        const String& meta,
+void Service::SendEvent(const String& meta,
                         const uint8_t* data,
                         intptr_t size) {
   // Bitstream: [meta data size (big-endian 64 bit)] [meta data (UTF-8)] [data]
@@ -586,16 +556,19 @@
   }
   ASSERT(offset == total_bytes);
   // TODO(turnidge): Pass the real eventType here.
-  SendEvent(eventFamilyId, 0, message);
+  SendEvent(0, message);
 }
 
 
 void Service::HandleGCEvent(GCEvent* event) {
+  if (ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current())) {
+    return;
+  }
   JSONStream js;
   event->PrintJSON(&js);
   const String& message = String::Handle(String::New(js.ToCString()));
   // TODO(turnidge): Pass the real eventType here.
-  SendEvent(kEventFamilyGC, 0, message);
+  SendEvent(0, message);
 }
 
 
@@ -603,7 +576,7 @@
   JSONStream js;
   event->PrintJSON(&js);
   const String& message = String::Handle(String::New(js.ToCString()));
-  SendEvent(kEventFamilyDebug, event->type(), message);
+  SendEvent(event->type(), message);
 }
 
 
@@ -798,8 +771,7 @@
   }
   const String& message = String::Handle(String::New(js.ToCString()));
   uint8_t data[] = {0, 128, 255};
-  // TODO(koda): Add 'testing' event family.
-  SendEvent(kEventFamilyDebug, message, data, sizeof(data));
+  SendEvent(message, data, sizeof(data));
 }
 
 
@@ -2232,12 +2204,11 @@
   {
     JSONObject jsobj(&js);
     jsobj.AddProperty("type", "ServiceEvent");
-    jsobj.AddPropertyF("id", "_graphEvent");
     jsobj.AddProperty("eventType", "_Graph");
     jsobj.AddProperty("isolate", isolate);
   }
   const String& message = String::Handle(String::New(js.ToCString()));
-  SendEvent(kEventFamilyDebug, message, buffer, stream.bytes_written());
+  SendEvent(message, buffer, stream.bytes_written());
 }
 
 
@@ -2415,7 +2386,7 @@
 
   void VisitIsolate(Isolate* isolate) {
     if ((isolate != Dart::vm_isolate()) &&
-        !ServiceIsolate::IsServiceIsolate(isolate)) {
+        !ServiceIsolate::IsServiceIsolateDescendant(isolate)) {
       jsarr_->AddValue(isolate);
     }
   }
@@ -2434,24 +2405,19 @@
 static bool GetVM(Isolate* isolate, JSONStream* js) {
   JSONObject jsobj(js);
   jsobj.AddProperty("type", "VM");
-  jsobj.AddProperty("id", "vm");
   jsobj.AddProperty("architectureBits", static_cast<intptr_t>(kBitsPerWord));
   jsobj.AddProperty("targetCPU", CPU::Id());
   jsobj.AddProperty("hostCPU", HostCPUFeatures::hardware());
-  jsobj.AddPropertyF("date", "%" Pd64 "", OS::GetCurrentTimeMillis());
   jsobj.AddProperty("version", Version::String());
   // Send pid as a string because it allows us to avoid any issues with
   // pids > 53-bits (when consumed by JavaScript).
   // TODO(johnmccutchan): Codify how integers are sent across the service.
   jsobj.AddPropertyF("pid", "%" Pd "", OS::ProcessId());
-  jsobj.AddProperty("assertsEnabled", isolate->AssertsEnabled());
-  jsobj.AddProperty("typeChecksEnabled", isolate->TypeChecksEnabled());
-  int64_t start_time_micros = Dart::vm_isolate()->start_time();
-  int64_t uptime_micros = (OS::GetCurrentTimeMicros() - start_time_micros);
-  double seconds = (static_cast<double>(uptime_micros) /
-                    static_cast<double>(kMicrosecondsPerSecond));
-  jsobj.AddProperty("uptime", seconds);
-
+  jsobj.AddProperty("_assertsEnabled", isolate->AssertsEnabled());
+  jsobj.AddProperty("_typeChecksEnabled", isolate->TypeChecksEnabled());
+  int64_t start_time_millis = (Dart::vm_isolate()->start_time() /
+                               kMicrosecondsPerMillisecond);
+  jsobj.AddProperty64("startTime", start_time_millis);
   // Construct the isolate list.
   {
     JSONArray jsarr(&jsobj, "isolates");
@@ -2506,6 +2472,25 @@
 }
 
 
+static const MethodParameter* set_name_params[] = {
+  ISOLATE_PARAMETER,
+  new MethodParameter("name", true),
+  NULL,
+};
+
+
+static bool SetName(Isolate* isolate, JSONStream* js) {
+  isolate->set_debugger_name(js->LookupParam("name"));
+  {
+    ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate);
+    Service::HandleEvent(&event);
+  }
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Success");
+  return true;
+}
+
+
 static ServiceMethodDescriptor service_methods_[] = {
   { "_echo", _Echo,
     NULL },
@@ -2527,7 +2512,7 @@
     eval_frame_params },
   { "getAllocationProfile", GetAllocationProfile,
     get_allocation_profile_params },
-  { "getCallSiteData", GetCallSiteData,
+  { "_getCallSiteData", GetCallSiteData,
     get_call_site_data_params },
   { "getClassList", GetClassList,
     get_class_list_params },
@@ -2577,8 +2562,10 @@
     resume_params },
   { "requestHeapSnapshot", RequestHeapSnapshot,
     request_heap_snapshot_params },
-  { "setFlag", SetFlag ,
+  { "setFlag", SetFlag,
     set_flags_params },
+  { "setName", SetName,
+    set_name_params },
 };
 
 
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index c63f15d..28e02a6 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -31,11 +31,7 @@
   // Handles a message which is directed to a particular isolate.
   static void HandleIsolateMessage(Isolate* isolate, const Array& message);
 
-  static bool EventMaskHas(uint32_t mask);
-  static void SetEventMask(uint32_t mask);
   static bool NeedsEvents();
-  static bool NeedsDebuggerEvents();
-  static bool NeedsGCEvents();
 
   static void HandleEvent(ServiceEvent* event);
   static void HandleGCEvent(GCEvent* event);
@@ -56,31 +52,21 @@
  private:
   static void InvokeMethod(Isolate* isolate, const Array& message);
 
-  // These must be kept in sync with service/constants.dart
-  static const int kEventFamilyDebug = 0;
-  static const int kEventFamilyGC = 1;
-  static const uint32_t kEventFamilyDebugMask = (1 << kEventFamilyDebug);
-  static const uint32_t kEventFamilyGCMask = (1 << kEventFamilyGC);
-
   static void EmbedderHandleMessage(EmbedderServiceHandler* handler,
                                     JSONStream* js);
 
   static EmbedderServiceHandler* FindIsolateEmbedderHandler(const char* name);
   static EmbedderServiceHandler* FindRootEmbedderHandler(const char* name);
 
-  static void SendEvent(intptr_t eventFamilyId,
-                        intptr_t eventType,
+  static void SendEvent(intptr_t eventType,
                         const Object& eventMessage);
   // Does not take ownership of 'data'.
-  static void SendEvent(intptr_t eventId,
-                        const String& meta,
+  static void SendEvent(const String& meta,
                         const uint8_t* data,
                         intptr_t size);
 
   static EmbedderServiceHandler* isolate_service_handler_head_;
   static EmbedderServiceHandler* root_service_handler_head_;
-
-  static uint32_t event_mask_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/service/client.dart b/runtime/vm/service/client.dart
index 1fd4f44..0d0b253 100644
--- a/runtime/vm/service/client.dart
+++ b/runtime/vm/service/client.dart
@@ -6,20 +6,16 @@
 
 // A service client.
 abstract class Client {
-  /// A port for receipt of asynchronous service events.
-  final RawReceivePort eventPort = new RawReceivePort();
   final VMService service;
+  final bool sendEvents;
 
-  Client(this.service) {
-    eventPort.handler = (response) {
-      post(null, response);
-    };
+  Client(this.service, { bool sendEvents: true })
+      : this.sendEvents = sendEvents {
     service._addClient(this);
   }
 
   /// When implementing, call [close] when the network connection closes.
   void close() {
-    eventPort.close();
     service._removeClient(this);
   }
 
@@ -37,8 +33,8 @@
     }
   }
 
-  /// When implementing, responsible for sending [response] to the client.
-  void post(var seq, dynamic response);
+  // Sends a result to the client.  Implemented in subclasses.
+  void post(var seq, dynamic result);
 
   dynamic toJson() {
     return {
diff --git a/runtime/vm/service/constants.dart b/runtime/vm/service/constants.dart
index 8804863..92390e6 100644
--- a/runtime/vm/service/constants.dart
+++ b/runtime/vm/service/constants.dart
@@ -9,12 +9,4 @@
   static const int SERVICE_EXIT_MESSAGE_ID = 0;
   static const int ISOLATE_STARTUP_MESSAGE_ID = 1;
   static const int ISOLATE_SHUTDOWN_MESSAGE_ID = 2;
-
-  // Event family ids.
-  static const int EVENT_FAMILY_DEBUG = 0;
-  static const int EVENT_FAMILY_GC = 1;
-
-  // Event family masks.
-  static const int EVENT_FAMILY_DEBUG_MASK = (1 << EVENT_FAMILY_DEBUG);
-  static const int EVENT_FAMILY_DEBUG_GC = (1 << EVENT_FAMILY_GC);
 }
diff --git a/runtime/vm/service/service.idl b/runtime/vm/service/service.idl
index 1b825a19..4850a1c 100644
--- a/runtime/vm/service/service.idl
+++ b/runtime/vm/service/service.idl
@@ -1,14 +1,100 @@
+// <h2>Connecting to the VM Service</h2>
 //
-// TODO(turnidge): Finish writing an idl description of the service protocol.
+// TODO(turnidge): Describe how to connect, etc.
 //
+// <h2>Types</h2>
+//
+// Every non-error response returned by the VM Service has the
+// <code>type</code> property.  This allows the client distinguish
+// between different kinds of responses.
+//
+// If the type name of a response begins with an <code>@</code>
+// character then that response is a _reference_.  If the type name of
+// a response does not begin with an <code>@</code> character then
+// that response is an _object_ (or sometimes _full object_).  A
+// reference is meant to be a subset of a full object with just enough
+// information for the client to generate a reasonable-looking link.
+//
+// For example, an isolate reference may look like this...
+//
+//     {
+//       type: "@Isolate",
+//       id: "isolates/123",
+//       name: "worker"
+//     }
+//
+// ... and a full isolate object would have additional properties:
+//
+//     {
+//       type: "Isolate",
+//       id: "isolates/123",
+//       name: "worker"
+//       entry: ...
+//       heaps: ...
+//       topFrame: ...
+//       ...
+//     }
+//
+// <h2>IDs and Names</h2>
+//
+// Many responses returned by the VM Service have an <code>id</code>
+// property.  This is an identifier used to request an object from an
+// isolate using the <code>getObject</code> rpc.  If two responses
+// have the same id then they refer to the same object.  The converse
+// is not true: the same object may occasionally be returned with two
+// different ids.
+//
+// The client must not parse ids -- they must be treated as opaque
+// strings.  We reserve the right to change the ids of objects.
+//
+// TODO(turnidge): Describe id/handle expiration.  Provide guidance on
+// which responses are cacheable/constant.  Perhaps this needs to be
+// signaled in the Response itself.
+//
+// Many responses have the <code>name</code> property.  Names are
+// provided so that objects can be displayed in a way that a Dart
+// language programmer would find sensible.
+//
+// Note that names are not unique.  Many objects will have the same
+// name.
+//
+// <h2>Private Properties</h2>
+//
+// Some properties returned by the VM Service begin with an underscore
+// (&#95;) character.  These properties are called _private
+// properties_.  Private properties provide private information
+// specific to the VM's implementation.  Private properties may be
+// added, removed, or changed at any time with any release of the VM.
+// They are provided for those tools that need this level of internal
+// access, such as the Observatory.
+//
+// For example, some responses will have the <code>_vmType</code>
+// property.  This provides the VM-internal type name of an object,
+// and is provided only when this type name differs from the
+// <code>type</code> property.
+//
+// <b>If your application relies on private properties, you should expect
+// to update it when new versions of the VM are released.</b>
+//
+// <hr>
 
 interface Service {
+  // Returns global information about the Dart VM.
   getVM() VM
 
+  // Changes the debugging name for some isolate.
+  setName(isolateId string, name string) Response
+
+  // Returns information about an isolate.
+  getIsolate(isolateId string) Isolate
+
+  // Returns a list of vm flags and their values.
   getFlagList() FlagList
 
+  // Sets the value of a vm flag
   setFlag(name string, value string) Response
 
+  // Loads an object by id from an isolate.
   getObject(isolateId string, objectId string) Object
 
   // The response is a subtype of Object or ObjectRef.
@@ -48,7 +134,7 @@
   getCoverage(isolateId string, targetId string) CodeCoverage
 
   // Returns call site cache information for a function.
-  getCallSiteData(isolateId string, targetId string) _CallSiteData
+  _getCallSiteData(isolateId string, targetId string) _CallSiteData
 
   // Returns a full cpu profile for an isolate.
   //
@@ -97,21 +183,27 @@
   getTypeArgumentsList(isolateId string,
                        onlyWithInstantiations bool) TypeArgumentsList
 
+  // Gets a list of isolate metrics.
   getIsolateMetricList(isolateId string,
                        type MetricSelector) MetricList
 
+  // Gets a specific isolate metric by id.
   getIsolateMetric(isolateId string,
                    metricId string) Metric
 
+  // Gets a list of vm metrics.
   getVMMetricList() MetricList
 
+  // Gets a specific vm metric by id.
   getVMMetric(metricId string) Metric
 
+  // A test rpc for vm requests.
+  _echoVM(text string) _EchoResponse
+
+  // A test rpc for isolate requests.
   _echo(isolateId string,
         text string) _EchoResponse
 
-  _echoVM(text string) _EchoResponse
-
   // Triggers a ServiceEvent with EventType '_Echo'.
   _triggerEchoEvent(isolateId string,
                     text string) _EchoResponse
@@ -124,10 +216,10 @@
 }
 
 
-// Every top level response returned by the Service interface extends
-// <code>Response</code>.  This allows the client to distinguish
-// between different kinds of responses by using the <code>type</code>
-// property.
+// Every non-error top level response returned by the Service
+// interface extends <code>Response</code>.  This allows the client to
+// distinguish between different kinds of responses by using the
+// <code>type</code> property.
 struct Response {
   // Every response returned by the VM Service has the
   // <code>type</code> property.  This allows the client distinguish
@@ -142,32 +234,683 @@
 }
 
 
+// An asynchronous notification from the VM Service.
+struct ServiceEvent extends Response {
+  // What kind of event is this?
+  eventType ServiceEventType
+
+  // The isolate with which this event is associated.
+  isolate IsolateRef
+
+  // The breakpoint associated with this event, if applicable.
+  //
+  // This is provided for the events:
+  //   <code>PauseBreakpoint</code>
+  //   <code>BreakpointAdded</code>
+  //   <code>BreakpointRemoved</code>
+  //   <code>BreakpointResolved</code>
+  breakpoint Breakpoint [optional]
+
+  // The top stack frame associated with this event, if applicable.
+  //
+  // This is provided for the events:
+  //   <code>PauseBreakpoint</code>
+  //   <code>PauseInterrupted</code>
+  //   <code>PauseException</code>
+  //
+  // For the <code>Resume</code> event, the top frame is provided at
+  // all times except for the initial resume event that is delivered
+  // when an isolate begins execution.
+  topFrame Frame [optional]
+
+  // The exception associated with this event, if this is a
+  // <code>PauseException</code> event.
+  exception InstanceRef [optional]
+}
+
+
+// The type of a service event.
+enum ServiceEventType {
+  // Notification that a new isolate has started.
+  IsolateStart
+
+  // Notification that an isolate has exited.
+  IsolateExit
+
+  // Notification that isolate identifying information has changed.
+  // Currently used to notify of changes to the isolate debugging name
+  // via <code>setName</code>.
+  IsolateUpdate
+
+  // An isolate has paused at start, before executing code.
+  PauseStart
+
+  // An isolate has paused at exit, before terminating.
+  PauseExit
+
+  // An isolate has paused at a breakpoint or due to stepping.
+  PauseBreakpoint
+
+  // An isolate has paused due to interruption via <code>pause</code>.
+  PauseInterrupted
+
+  // An isolate has paused due to an exception.
+  //
+  // TODO(turnidge): Allow user to toggle pause-on-exceptions.
+  PauseException
+
+  // An isolate has started or resumed execution.
+  Resume
+
+  // A breakpoint has been added for an isolate.
+  BreakpointAdded
+
+  // An unresolved breakpoint has been resolved for an isolate.
+  BreakpointResolved
+
+  // A breakpoint has been removed.
+  BreakpointRemoved
+
+  // A garbage collection event.
+  GC
+
+  // The object graph is being delivered.  This is triggered via
+  // <code>requestHeapSnapshot</code>.
+  _Graph
+}
+
+
 struct VM extends Response {
-  placeholder int
+  // Word length on target architecture (e.g. 32, 64).
+  architectureBits int
+
+  // The CPU we are generating code for.
+  targetCPU string
+
+  // The CPU we are actually running on.
+  hostCPU string
+
+  // The Dart VM version string.
+  version string
+
+  // The process id for the VM.
+  pid string
+
+  // The time that the VM started in milliseconds since the epoch.
+  //
+  // Suitable to pass to DateTime.fromMillisecondsSinceEpoch.
+  startTime int
+
+  // A list of isolates running in the VM.
+  isolates []IsolateRef
+
+  // Are assertions enabled in the VM?
+  //
+  // TODO(turnidge): Move to some sort of general settings list?
+  _assertsEnabled bool
+
+  // Are type checks enabled in the VM?
+  //
+  // TODO(turnidge): Move to some sort of general settings list?
+  _typeChecksEnabled bool
 }
 
 
+// A reference to an an isolate.
+struct IsolateRef extends Object {
+  // A numeric id for this isolate, represented as a string.  Unique.
+  number string
+
+  // A name identifying this isolate.  Not guaranteed to be unique.
+  name string
+}
+
+
+// An isolate running in the VM.
+struct Isolate {
+  // A numeric id for this isolate, represented as a string.  Unique.
+  number string
+
+  // A name identifying this isolate.  Not guaranteed to be unique.
+  name string
+
+  // The time that the VM started in milliseconds since the epoch.
+  //
+  // Suitable to pass to DateTime.fromMillisecondsSinceEpoch.
+  startTime int
+
+  // The entry function for this isolate.
+  entry FunctionRef [optional]
+
+  // The number of live ports for this isolate.
+  livePorts int
+
+  // Will this isolate pause when exiting?
+  pauseOnExit bool
+
+  // The last pause event delivered to the isolate.  If the isolate is
+  // running, this will be a resume event.
+  pauseEvent ServiceEvent
+
+  // The error that is causing this isolate to exit, if applicable.
+  error Error [optional]
+
+  // The root library for this isolate.
+  rootLib LibraryRef
+
+  // A list of all libraries for this isolate.
+  libraries []LibraryRef
+
+  // A list of all breakpoints for this isolate.
+  breakpoints []Breakpoint
+
+  // A list of features enabled for this isolate.
+  features []string
+
+  // TODO
+  heaps int
+
+  // TODO
+  tagCounters int
+}
+
+
+// A list of flags.
 struct FlagList extends Response {
-  placeholder int
+  // A list of all flags which are set to default values.
+  unmodifiedFlags []Flag
+
+  // A list of all flags which have been modified by the user.
+  modifiedFlags []Flag
 }
 
 
-struct _EchoResponse extends Response {
-  text string
+// A single flag.
+struct Flag {
+  // The name of the flag.
+  name string
+
+  // A description of the flag.
+  comment string
+
+  // The type of the flag.
+  flagType FlagType
 }
 
 
-// Persistent objects in the vm are returned as subclasses of Object.
+// The type of a flag.
+enum FlagType {
+  bool
+  int
+  uint64_t
+  string
+}
+
+
+// A reference to a persistent object that lives in some isolate.
+struct ObjectRef extends Response {
+  // A unique identifier for an object.  Passed to
+  // <code>getObject</code> to load the full object.
+  id string
+}
+
+
+// A persistent object that lives in some isolate.
 struct Object extends Response {
-  // The object <code>id</code> can be used to refer to a persistent
-  // object inside the vm or an isolate.
-  id  string
+  // A unique identifier for this object.
+  id string
+}
+
+
+// TODO(turnidge): null type
+// TODO(turnidge): VMObject.
+
+
+// A reference to a Dart language library.
+struct LibraryRef extends ObjectRef {
+  // The name of this library.
+  name string
+
+  // The url of this library.
+  url string
+}
+
+
+// A Dart language library.
+struct Library extends Object {
+  // The name of this library.
+  name string
+
+  // The url of this library.
+  url string
+
+  // A list of the imports for this library.
+  imports []LibraryRef
+
+  // A list of the scripts which constitute this library.
+  scripts []ScriptRef
+
+  // A list of the top-level variables in this library.
+  variables []FieldRef
+
+  // A list of the top-level functions in this library.
+  functions []FunctionRef
+
+  // A list of all classes in this library.
+  classes []ClassRef
+}
+
+
+// A reference to a Dart language script.
+struct ScriptRef extends ObjectRef {
+  // A name for this script.
+  name string
+
+  // What kind of script is this?
+  kind ScriptKind
+}
+
+
+// A  Dart language script.
+struct Script extends Object {
+  // A name for this script.
+  name string
+
+  // What kind of script is this?
+  kind ScriptKind
+
+  // The library which owns this script.
+  library LibraryRef
+
+  // The source code for this script.  For certain built-in scripts,
+  // this may be reconstructed without source comments.
+  source string
+
+  // A table encoding a mapping from token position to line and column.
+  //
+  // Each entry in the array consists of a line number followed by
+  // (tokenPos, columnNumber) pairs:
+  //
+  //    [lineNumber, (tokenPos, columnNumber)*]
+  // 
+  // For example, the following table:
+  //
+  //    [[1, 100, 5, 101, 8],[2, 102, 7]]
+  //
+  // Encodes the following mapping:
+  //
+  //    tokenPos  line   column
+  //    --------  ------ ------
+  //    100       1      5
+  //    101       1      8
+  //    102       2      7
+  //
+  // TODO(turnidge): The tool I'm using does not support [][].
+  // tokenPosTable [][]int
+  tokenPosTable int
+}
+
+
+enum ScriptKind {
+  script
+  library
+  source
+  patch
+}
+
+
+// A reference to a Dart language class.
+struct ClassRef extends ObjectRef {
+  // The name of this class.
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string [optional]
+}
+
+
+// A Dart language class.
+struct Class extends Object {
+  // The name of this class.
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string [optional]
+
+  // The error which occurred during class finalization, if it exists.
+  error InstanceRef [optional]
+
+  // Is this an abstract class?
+  abstract bool
+
+  // Is this a const class?
+  const bool
+
+  // Has this class been finalized?
+  finalized bool
+
+  // Is this class implemented?
+  implemented bool
+
+  // Is this a vm patch class?
+  patch bool
+
+  // The library which contains this class.
+  library LibraryRef
+
+  // The script which defines this class.  May be missing for some
+  // classes.
+  script ScriptRef
+
+  // The superclass of this class, if any.
+  super ClassRef [optional]
+
+  // A list of interface types for this class.
+  interfaces []TypeRef
+
+  // A list of fields in this class.  Does not include fields from
+  // superclasses.
+  fields []FieldRef
+
+  // A list of functions in this class.  Does not include functions
+  // from superclasses.
+  functions []FunctionRef
+
+  // A list of subclasses of this class.
+  subclasses []ClassRef
+
+  // Allocation statistics for this class, if available.
+  allocationStats ClassHeapStats [optional]
+}
+
+
+struct ClassHeapStats extends Response {
+  TODO int
+}
+
+
+// A reference to a Dart language field or variable.
+struct FieldRef extends ObjectRef {
+  // The name of this field.
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string [optional]
+
+  // The value of this field, if the field is static.
+  value InstanceRef [optional]
+
+  // The owner of this field, which can be either a LibraryRef for a
+  // ClassRef.
+  owner ObjectRef
+
+  // The declared type of this field.
+  declaredType TypeRef
+
+  // Is this field const?
+  const bool
+
+  // Is this field final?
+  final bool
+
+  // Is this field static?
+  static bool
+}
+
+
+// A Dart language field or variable.
+struct Field extends ObjectRef {
+  // The name of this field.
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string [optional]
+
+  // The value of this field, if the field is static.
+  value InstanceRef [optional]
+
+  // The owner of this field, which can be either a LibraryRef for a
+  // ClassRef.
+  owner ObjectRef
+
+  // The declared type of this field.
+  declaredType TypeRef
+
+  // Is this field const?
+  const bool
+
+  // Is this field final?
+  final bool
+
+  // Is this field static?
+  static bool
+
+  // The script containing this feild.
+  script ScriptRef [optional]
+
+  // The token position of this field.
+  tokenPos int [optional]
+
+  // Have we seen null assigned to this field?
+  _guardNullable bool
+
+  // Have we seen a single class assigned to this field?
+  //
+  // TODO(johnmccutchan): This can actually be a string 'unknown' or
+  // 'dynamic' or a ClassRef.  Change how this is encoded.
+  _guardClass string
+
+  // Have we seen a fixed length list assigned to this field?
+  //
+  // TODO(johnmccutchan): This can actually be a string 'unknown' or
+  // 'dynamic' or a ClassRef.  Change how this is encoded.
+  _guardLength string
+}
+
+
+// A reference to a Dart language function.
+struct FunctionRef extends ObjectRef {
+  // The name of this function.
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string [optional]
+
+  // The owner of this field, which can be a LibraryRef, ClassRef, or
+  // a FunctionRef.
+  owner ObjectRef
+
+  // What kind of function is this?
+  kind FunctionKind
+}
+
+
+// A Dart language function.
+struct Function extends ObjectRef {
+  // The name of this function.
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string [optional]
+
+  // What kind of function is this?
+  kind FunctionKind
+
+  // The owner of this field, which can be a LibraryRef, ClassRef, or
+  // a FunctionRef.
+  owner ObjectRef
+
+  // Is this function static?
+  //
+  // TODO(turnidge): This is inconsistent with FieldRef.
+  static bool
+
+  // Is this function const?
+  const bool
+
+  // The script containing this function.
+  script ScriptRef [optional]
+
+  // The first token position of this function.
+  tokenPos int [optional]
+
+  // The last token position of this function.
+  endTokenPos int [optional]
+
+  // The compiled code associated with this function.
+  code CodeRef [optional]
+
+  // Are we able to generate optimized code for this function?
+  _optimizable bool
+
+  // Are we able to inline this function?
+  _inlinable bool
+
+  // The unoptimized version of this function, if retained.
+  _unoptimizedCode CodeRef [optional]
+
+  // An indicator of how actively this function is used.
+  _usageCounter int
+
+  // TODO(johnmccutchan): Document.
+  _optimizedCallSiteCount int
+
+  // How many times has this function been deoptimized?
+  _deoptimizations int
+}
+
+
+enum FunctionKind {
+  RegularFunction
+  ClosureFunction
+  GetterFunction
+  SetterFunction
+  Constructor
+  ImplicitGetter
+  ImplicitSetter
+  ImplicitStaticFinalGetter
+  IrregexpFunction
+  StaticInitializer
+  MethodExtractor
+  NoSuchMethodDispatcher
+  InvokeFieldDispatcher
+  Collected
+  Native
+  Stub
+  Tag
+}
+
+
+// A reference to a compiled code object in the Dart VM.
+struct CodeRef extends ObjectRef {
+  // A name for this code object
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string [optional]
+
+  // What kind of code object is this?
+  kind CodeKind
+
+  // Was this code generated using the optimizing compiler?
+  _optimized bool
+}
+
+
+// A compiled code object in the Dart VM.
+struct Code extends Object {
+  // A name for this code object
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string [optional]
+
+  // What kind of code object is this?
+  kind CodeKind
+
+  // Was this code generated using the optimizing compiler?
+  _optimized bool
+
+  // The function which corresponds to this compiled code.
+  function FunctionRef
+
+  // The start address of the generated code as a hex string.
+  _startAddress string
+
+  // The end address of the generated code as a hex string.
+  _endAddress string
+
+  // The object pool associated with this code object.
+  _objectPool UNDOCUMENTED [optional]
+
+  // The disassembly of this code object.
+  _disassembly UNDOCUMENTED [optional]
+
+  // The pc descriptor table for this code object.
+  _descriptors UNDOCUMENTED [optional]
+
+  // The inlined function table for this code object.
+  _inlinedFunctions UNDOCUMENTED [optional]
+
+  // Inline interval information for this code object.
+  _inlinedIntervals UNDOCUMENTED [optional]
+}
+
+
+enum CodeKind {
+  Dart
+  Native
+  Stub
+  Tag
+  Collected
+}
+
+
+// A reference to a type arguments vector.
+struct TypeArgumentsRef extends ObjectRef {
+  // A name for this type argument list.
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string
+}
+
+
+// The type argument vector for some instantiated generic type.
+struct TypeArguments extends Object {
+  // A name for this type argument list.
+  name string
+
+  // A vm internal name, provided only when it is different than name.
+  _vmName string
+
+  // A list of types.
+  types []TypeRef
+}
+
+
+// Represents an error object inside the VM.
+struct Error extends Object {
+  // An error message
+  message string
+}
+
+
+// A <code>InstanceRef</code> encodes a reference to a
+// <code>Instance</code> object.
+struct InstanceRef extends ObjectRef {
+  TODO int
+}
+
+
+struct TypeRef extends InstanceRef {
+  TODO2 int
 }
 
 
 // An <code>Instance</code> represents a Dart-language object.
 struct Instance extends Object {
-  placeholder int
+  TODO int
 }
 
 
@@ -179,65 +922,6 @@
 }
 
 
-// References to persistent objects in the vm are returned as
-// subclasses of ObjectRef.
-struct ObjectRef extends Response {
-  // The object <code>id</code> can be used to refer to a persistent
-  // object inside the vm or an isolate.
-  id  string
-}
-
-
-// A <code>CodeRef</code> encodes a reference to a <code>Code</code> object.
-struct CodeRef extends ObjectRef {
-  placeholder int
-}
-
-
-struct ClassRef extends ObjectRef {
-  placeholder int
-}
-
-
-struct TypeArgumentsRef extends ObjectRef {
-  placeholder int
-}
-
-
-// A <code>FunctionRef</code> encodes a reference to a <code>Function</code> object.
-struct FunctionRef extends ObjectRef {
-  placeholder int
-}
-
-
-// A <code>FieldRef</code> encodes a reference to a <code>Field</code> object.
-struct FieldRef extends ObjectRef {
-  placeholder int
-}
-
-
-// A <code>InstanceRef</code> encodes a reference to a <code>Instance</code> object.
-struct InstanceRef extends ObjectRef {
-  placeholder int
-}
-
-
-// A <code>ScriptRef</code> encodes a reference to a <code>Script</code> object.
-struct ScriptRef extends ObjectRef {
-  placeholder int
-}
-
-
-struct Class extends Object {
-  placeholder int
-}
-
-
-struct TypeArguments extends Object {
-  placeholder int
-}
-
-
 // A <code>Location</code> encodes a location withing a dart script.
 //
 // TODO(turnidge): Should this really be broken out as its own type?
@@ -273,7 +957,7 @@
 
 
 struct CodeCoverage extends Response {
-  placeholder int
+  TODO int
 }
 
 
@@ -392,14 +1076,14 @@
 
 
 struct Gauge extends Metric {
-  value double
-  min double
-  max double
+  value float
+  min float
+  max float
 }
 
 
 struct Counter extends Metric {
-  value double
+  value float
 }
 
 
@@ -430,6 +1114,16 @@
 // A <code>MetricSelector</code> is used to indicate which list of metrics
 // should be retrieved from an isolate.
 enum MetricSelector {
-  Dart,
-  Native,
+  Dart
+  Native
 }
+
+
+struct _EchoResponse extends Response {
+  text string
+}
+
+
+struct UNDOCUMENTED {
+  TODO int
+}
\ No newline at end of file
diff --git a/runtime/vm/service/vmservice.dart b/runtime/vm/service/vmservice.dart
index 934bd6f..95254a3 100644
--- a/runtime/vm/service/vmservice.dart
+++ b/runtime/vm/service/vmservice.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:isolate';
+import 'dart:typed_data';
 
 part 'client.dart';
 part 'constants.dart';
@@ -22,12 +23,10 @@
 
 class VMService extends MessageRouter {
   static VMService _instance;
+
   /// Collection of currently connected clients.
   final Set<Client> clients = new Set<Client>();
 
-  // A map encoding which clients are interested in which kinds of events.
-  final Map<int, Set<Client>> eventMap = new Map<int, Set<Client>>();
-
   /// Collection of currently running isolates.
   RunningIsolates runningIsolates = new RunningIsolates();
 
@@ -44,85 +43,71 @@
     clients.remove(client);
   }
 
-  int eventTypeCode(String eventType) {
-    switch(eventType) {
-      case 'debug':
-        return Constants.EVENT_FAMILY_DEBUG;
-      case 'gc':
-        return Constants.EVENT_FAMILY_GC;
-      default:
-        return -1;
-    }
-  }
-
-  void _updateEventMask() {
-    int mask = 0;
-    for (var key in eventMap.keys) {
-      var subscribers = eventMap[key];
-      if (subscribers.isNotEmpty) {
-        mask |= (1 << key);
+  void _eventMessageHandler(dynamic eventMessage) {
+    for (var client in clients) {
+      if (client.sendEvents) {
+        client.post(null, eventMessage);
       }
     }
-    _setEventMask(mask);
-  }
-
-  void subscribe(String eventType, Client client) {
-    int eventCode = eventTypeCode(eventType);
-    assert(eventCode >= 0);
-    var subscribers = eventMap.putIfAbsent(eventCode, () => new Set<Client>());
-    subscribers.add(client);
-    _updateEventMask();
   }
 
   void _controlMessageHandler(int code,
-                              int port_id,
+                              int portId,
                               SendPort sp,
                               String name) {
     switch (code) {
       case Constants.ISOLATE_STARTUP_MESSAGE_ID:
-        runningIsolates.isolateStartup(port_id, sp, name);
+        runningIsolates.isolateStartup(portId, sp, name);
       break;
       case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID:
-        runningIsolates.isolateShutdown(port_id, sp);
+        runningIsolates.isolateShutdown(portId, sp);
       break;
     }
   }
 
-  void _eventMessageHandler(int eventType, dynamic eventMessage) {
-    var subscribers = eventMap[eventType];
-    if (subscribers == null) {
-      return;
-    }
-    for (var subscriber in subscribers) {
-      subscriber.post(null, eventMessage);
-    }
-  }
-
   void _exit() {
     if (onShutdown != null) {
       onShutdown();
     }
     isolateLifecyclePort.close();
     scriptLoadPort.close();
-    var clientList = clients.toList();
-    for (var client in clientList) {
+    for (var client in clients) {
       client.close();
     }
     _onExit();
   }
 
   void messageHandler(message) {
-    assert(message is List);
-    if (message is List && (message.length == 4)) {
-      _controlMessageHandler(message[0], message[1], message[2], message[3]);
-    } else if (message is List && (message.length == 2)) {
-      _eventMessageHandler(message[0], message[1]);
-    } else if (message is List && (message.length == 1)) {
-      assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID);
-      _exit();
-    } else {
-      Logger.root.severe('Unexpected message: $message');
+    if (message is String) {
+      // This is an event intended for all clients.
+      _eventMessageHandler(message);
+      return;
     }
+    if (message is Uint8List) {
+      // This is "raw" data intended for a specific client.
+      //
+      // TODO(turnidge): Do not broadcast this data to all clients.
+      _eventMessageHandler(message);
+      return;
+    }
+    if (message is List) {
+      // This is an internal vm service event.
+      if (message.length == 1) {
+        // This is a control message directing the vm service to exit.
+        assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID);
+        _exit();
+        return;
+      }
+      if (message.length == 4) {
+        // This is a message informing us of the birth or death of an
+        // isolate.
+        _controlMessageHandler(message[0], message[1], message[2], message[3]);
+        return;
+      }
+    }
+
+    Logger.root.severe(
+        'Internal vm-service error: ignoring illegal message: $message');
   }
 
   void _notSupported(_) {
@@ -180,9 +165,6 @@
   service.runningIsolates.isolateStartup(port_id, sp, name);
 }
 
-void _setEventMask(int mask)
-    native "VMService_SetEventMask";
-
 void _onStart() native "VMService_OnStart";
 
 void _onExit() native "VMService_OnExit";
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 9f7c63d..3dfe66b 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -58,6 +58,8 @@
       return "IsolateStart";
     case kIsolateExit:
       return "IsolateExit";
+    case kIsolateUpdate:
+      return "IsolateUpdate";
     case kPauseStart:
       return "PauseStart";
     case kPauseExit:
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index b55d0a8..c7f41e8 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -16,6 +16,7 @@
   enum EventType {
     kIsolateStart,       // New isolate has started
     kIsolateExit,        // Isolate has exited
+    kIsolateUpdate,      // Isolate identity information has changed
 
     kPauseStart,         // --pause-isolates-on-start
     kPauseExit,          // --pause-isolates-on-exit
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index c9a47c2..3494b12 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -149,6 +149,7 @@
 Isolate* ServiceIsolate::isolate_ = NULL;
 Dart_Port ServiceIsolate::port_ = ILLEGAL_PORT;
 Dart_Port ServiceIsolate::load_port_ = ILLEGAL_PORT;
+Dart_Port ServiceIsolate::origin_ = ILLEGAL_PORT;
 Dart_IsolateCreateCallback ServiceIsolate::create_callback_ = NULL;
 uint8_t* ServiceIsolate::exit_message_ = NULL;
 intptr_t ServiceIsolate::exit_message_length_ = 0;
@@ -180,9 +181,9 @@
 
   virtual void VisitIsolate(Isolate* isolate) {
     ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current()));
-    if (ServiceIsolate::IsServiceIsolate(isolate) ||
+    if (ServiceIsolate::IsServiceIsolateDescendant(isolate) ||
         (isolate == Dart::vm_isolate())) {
-      // We do not register the service or vm isolate.
+      // We do not register the service (and descendants) or the vm-isolate.
       return;
     }
     // Setup arguments for call.
@@ -250,16 +251,6 @@
     Service::HandleRootMessage(message);
   }
 
-  static void SetEventMask(Dart_NativeArguments args) {
-    NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
-    Isolate* isolate = arguments->isolate();
-    StackZone stack_zone(isolate);
-    Zone* zone = stack_zone.GetZone();  // Used by GET_NON_NULL_NATIVE_ARGUMENT.
-    HANDLESCOPE(isolate);
-    GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(0));
-    Service::SetEventMask(mask.AsTruncatedUint32Value());
-  }
-
   static void OnStart(Dart_NativeArguments args) {
     NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
     Isolate* isolate = arguments->isolate();
@@ -320,8 +311,6 @@
     ServiceIsolateNatives::SendIsolateServiceMessage},
   {"VMService_SendRootServiceMessage", 1,
     ServiceIsolateNatives::SendRootServiceMessage},
-  {"VMService_SetEventMask", 1,
-    ServiceIsolateNatives::SetEventMask},
   {"VMService_OnStart", 0,
     ServiceIsolateNatives::OnStart },
   {"VMService_OnExit", 0,
@@ -377,6 +366,12 @@
 }
 
 
+bool ServiceIsolate::IsServiceIsolateDescendant(Isolate* isolate) {
+  MonitorLocker ml(monitor_);
+  return isolate->origin_id() == origin_;
+}
+
+
 Dart_Port ServiceIsolate::Port() {
   MonitorLocker ml(monitor_);
   return port_;
@@ -405,7 +400,7 @@
     return false;
   }
   Isolate* isolate = Isolate::Current();
-  if (IsServiceIsolate(isolate)) {
+  if (IsServiceIsolateDescendant(isolate)) {
     return false;
   }
   ASSERT(isolate != NULL);
@@ -436,7 +431,7 @@
     return false;
   }
   Isolate* isolate = Isolate::Current();
-  if (IsServiceIsolate(isolate)) {
+  if (IsServiceIsolateDescendant(isolate)) {
     return false;
   }
   ASSERT(isolate != NULL);
@@ -490,6 +485,9 @@
   isolate_ = isolate;
   if (isolate_ != NULL) {
     isolate_->is_service_isolate_ = true;
+    origin_ = isolate_->origin_id();
+  } else {
+    origin_ = ILLEGAL_PORT;
   }
 }
 
@@ -611,7 +609,7 @@
       return;
     }
 
-    Isolate::SetCurrent(NULL);
+    Thread::ExitIsolate();
 
     ServiceIsolate::ConstructExitMessageAndCache(isolate);
 
diff --git a/runtime/vm/service_isolate.h b/runtime/vm/service_isolate.h
index e71027f..fbcd136 100644
--- a/runtime/vm/service_isolate.h
+++ b/runtime/vm/service_isolate.h
@@ -20,6 +20,7 @@
   static bool Exists();
   static bool IsRunning();
   static bool IsServiceIsolate(Isolate* isolate);
+  static bool IsServiceIsolateDescendant(Isolate* isolate);
   static Dart_Port Port();
 
   static Dart_Port WaitForLoadPort();
@@ -56,6 +57,7 @@
   static Isolate* isolate_;
   static Dart_Port port_;
   static Dart_Port load_port_;
+  static Dart_Port origin_;
 
   friend class Dart;
   friend class RunServiceTask;
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index eadd7fa..b3a70f4 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -290,7 +290,7 @@
   handler.filterMsg("size");
   EXPECT_STREQ(
       "{\"type\":\"bool\","
-      "\"class\":{\"type\":\"@Class\",\"id\":\"classes\\/46\","
+      "\"class\":{\"type\":\"@Class\",\"id\":\"classes\\/45\","
       "\"name\":\"bool\"},"
       "\"fields\":[],\"id\":\"objects\\/bool-true\","
       "\"valueAsString\":\"true\"}",
@@ -304,7 +304,7 @@
   handler.filterMsg("_vmName");
   EXPECT_STREQ(
       "{\"type\":\"int\",\"_vmType\":\"Smi\","
-      "\"class\":{\"type\":\"@Class\",\"id\":\"classes\\/42\","
+      "\"class\":{\"type\":\"@Class\",\"id\":\"classes\\/41\","
       "\"name\":\"_Smi\",},"
       "\"fields\":[],"
       "\"id\":\"objects\\/int-123\","
@@ -1079,11 +1079,11 @@
 
   Service::HandleRootMessage(service_msg);
   handler.HandleNextMessage();
-  EXPECT_SUBSTRING("\"type\":\"VM\",\"id\":\"vm\"", handler.msg());
+  EXPECT_SUBSTRING("\"type\":\"VM\"", handler.msg());
   EXPECT_SUBSTRING("\"targetCPU\"", handler.msg());
   EXPECT_SUBSTRING("\"hostCPU\"", handler.msg());
   EXPECT_SUBSTRING("\"version\"", handler.msg());
-  EXPECT_SUBSTRING("\"uptime\"", handler.msg());
+  EXPECT_SUBSTRING("\"startTime\"", handler.msg());
   EXPECT_SUBSTRING("\"isolates\"", handler.msg());
 }
 
@@ -1112,7 +1112,7 @@
   // Make sure we can get the FlagList.
   Service::HandleRootMessage(service_msg);
   handler.HandleNextMessage();
-  EXPECT_SUBSTRING("\"type\":\"FlagList\",\"id\":\"flags\"", handler.msg());
+  EXPECT_SUBSTRING("\"type\":\"FlagList\"", handler.msg());
   EXPECT_SUBSTRING(
       "\"name\":\"service_testing_flag\",\"comment\":\"Comment\","
       "\"flagType\":\"bool\",\"valueAsString\":\"false\"",
@@ -1173,7 +1173,7 @@
       "\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\","
       "\"name\":\"test-lib\","
       "\"kind\":\"script\","
-      "\"owningLibrary\":{\"type\":\"@Library\","
+      "\"library\":{\"type\":\"@Library\","
       "\"id\":\"libraries\\/%" Pd "\",\"name\":\"\","
       "\"url\":\"test-lib\"},"
       "\"source\":\"var port;\\n\\nmain() {\\n}\","
diff --git a/runtime/vm/signal_handler.h b/runtime/vm/signal_handler.h
index b5329bc..b204c55 100644
--- a/runtime/vm/signal_handler.h
+++ b/runtime/vm/signal_handler.h
@@ -44,6 +44,7 @@
 class SignalHandler : public AllStatic {
  public:
   static void Install(SignalAction action);
+  static void Remove();
   static uintptr_t GetProgramCounter(const mcontext_t& mcontext);
   static uintptr_t GetFramePointer(const mcontext_t& mcontext);
   static uintptr_t GetCStackPointer(const mcontext_t& mcontext);
diff --git a/runtime/vm/signal_handler_android.cc b/runtime/vm/signal_handler_android.cc
index d8ea14e..1ac0b8c 100644
--- a/runtime/vm/signal_handler_android.cc
+++ b/runtime/vm/signal_handler_android.cc
@@ -84,11 +84,21 @@
   struct sigaction act;
   memset(&act, 0, sizeof(act));
   act.sa_sigaction = action;
-  act.sa_flags = SA_RESTART | SA_SIGINFO;
   sigemptyset(&act.sa_mask);
-  // TODO(johnmccutchan): Do we care about restoring the signal handler?
-  struct sigaction old_act;
-  int r = sigaction(SIGPROF, &act, &old_act);
+  act.sa_flags = SA_RESTART | SA_SIGINFO;
+  int r = sigaction(SIGPROF, &act, NULL);
+  ASSERT(r == 0);
+}
+
+
+void SignalHandler::Remove() {
+  // Ignore future SIGPROF signals because by default SIGPROF will terminate
+  // the process and we may have some signals in flight.
+  struct sigaction act;
+  memset(&act, 0, sizeof(act));
+  act.sa_handler = SIG_IGN;
+  sigemptyset(&act.sa_mask);
+  int r = sigaction(SIGPROF, &act, NULL);
   ASSERT(r == 0);
 }
 
diff --git a/runtime/vm/signal_handler_linux.cc b/runtime/vm/signal_handler_linux.cc
index 957edda..960b417 100644
--- a/runtime/vm/signal_handler_linux.cc
+++ b/runtime/vm/signal_handler_linux.cc
@@ -129,9 +129,19 @@
   act.sa_sigaction = action;
   sigemptyset(&act.sa_mask);
   act.sa_flags = SA_RESTART | SA_SIGINFO;
-  // TODO(johnmccutchan): Do we care about restoring the signal handler?
-  struct sigaction old_act;
-  int r = sigaction(SIGPROF, &act, &old_act);
+  int r = sigaction(SIGPROF, &act, NULL);
+  ASSERT(r == 0);
+}
+
+
+void SignalHandler::Remove() {
+  // Ignore future SIGPROF signals because by default SIGPROF will terminate
+  // the process and we may have some signals in flight.
+  struct sigaction act;
+  act.sa_handler = SIG_IGN;
+  sigemptyset(&act.sa_mask);
+  act.sa_flags = 0;
+  int r = sigaction(SIGPROF, &act, NULL);
   ASSERT(r == 0);
 }
 
diff --git a/runtime/vm/signal_handler_macos.cc b/runtime/vm/signal_handler_macos.cc
index 3bb6101..79117c2 100644
--- a/runtime/vm/signal_handler_macos.cc
+++ b/runtime/vm/signal_handler_macos.cc
@@ -110,9 +110,19 @@
   act.sa_sigaction = action;
   sigemptyset(&act.sa_mask);
   act.sa_flags = SA_RESTART | SA_SIGINFO;
-  // TODO(johnmccutchan): Do we care about restoring the signal handler?
-  struct sigaction old_act;
-  int r = sigaction(SIGPROF, &act, &old_act);
+  int r = sigaction(SIGPROF, &act, NULL);
+  ASSERT(r == 0);
+}
+
+
+void SignalHandler::Remove() {
+  // Ignore future SIGPROF signals because by default SIGPROF will terminate
+  // the process and we may have some signals in flight.
+  struct sigaction act;
+  act.sa_handler = SIG_IGN;
+  sigemptyset(&act.sa_mask);
+  act.sa_flags = 0;
+  int r = sigaction(SIGPROF, &act, NULL);
   ASSERT(r == 0);
 }
 
diff --git a/runtime/vm/signal_handler_win.cc b/runtime/vm/signal_handler_win.cc
index a1f8fe0..e3164f4 100644
--- a/runtime/vm/signal_handler_win.cc
+++ b/runtime/vm/signal_handler_win.cc
@@ -43,6 +43,11 @@
 }
 
 
+void SignalHandler::Remove() {
+  UNIMPLEMENTED();
+}
+
+
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_WINDOWS)
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 477ee78..30e70f8 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1082,13 +1082,13 @@
 
 // Synchronization primitives support.
 void Simulator::SetExclusiveAccess(uword addr) {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
-  DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate);
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
+  DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
   int i = 0;
-  // Find an entry for this isolate in the exclusive access state.
+  // Find an entry for this thread in the exclusive access state.
   while ((i < kNumAddressTags) &&
-         (exclusive_access_state_[i].isolate != isolate)) {
+         (exclusive_access_state_[i].thread != thread)) {
     i++;
   }
   // Round-robin replacement of previously used entries.
@@ -1097,7 +1097,7 @@
     if (++next_address_tag_ == kNumAddressTags) {
       next_address_tag_ = 0;
     }
-    exclusive_access_state_[i].isolate = isolate;
+    exclusive_access_state_[i].thread = thread;
   }
   // Remember the address being reserved.
   exclusive_access_state_[i].addr = addr;
@@ -1105,20 +1105,20 @@
 
 
 bool Simulator::HasExclusiveAccessAndOpen(uword addr) {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
   ASSERT(addr != 0);
-  DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate);
+  DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
   bool result = false;
   for (int i = 0; i < kNumAddressTags; i++) {
-    if (exclusive_access_state_[i].isolate == isolate) {
-      // Check whether the current isolate's address reservation matches.
+    if (exclusive_access_state_[i].thread == thread) {
+      // Check whether the current thread's address reservation matches.
       if (exclusive_access_state_[i].addr == addr) {
         result = true;
       }
       exclusive_access_state_[i].addr = 0;
     } else if (exclusive_access_state_[i].addr == addr) {
-      // Other isolates with matching address lose their reservations.
+      // Other threads with matching address lose their reservations.
       exclusive_access_state_[i].addr = 0;
     }
   }
@@ -1128,7 +1128,7 @@
 
 void Simulator::ClearExclusive() {
   MutexLocker ml(exclusive_access_lock_);
-  // Remove the reservation for this isolate.
+  // Remove the reservation for this thread.
   SetExclusiveAccess(NULL);
 }
 
@@ -1156,7 +1156,7 @@
                                  uword new_value) {
   MutexLocker ml(exclusive_access_lock_);
   // We do not get a reservation as it would be guaranteed to be found when
-  // writing below. No other isolate is able to make a reservation while we
+  // writing below. No other thread is able to make a reservation while we
   // hold the lock.
   uword value = *address;
   if (value == compare_value) {
@@ -1713,12 +1713,6 @@
       }
     } else if (instr->IsMultiplyOrSyncPrimitive()) {
       if (instr->Bit(24) == 0) {
-        if ((TargetCPUFeatures::arm_version() != ARMv7) &&
-            (instr->Bits(21, 3) != 0)) {
-          // mla ... smlal only supported on armv7.
-          UnimplementedInstruction(instr);
-          return;
-        }
         // multiply instructions.
         Register rn = instr->RnField();
         Register rd = instr->RdField();
@@ -1734,6 +1728,10 @@
           case 3: {
             // Registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
             // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
+            if (TargetCPUFeatures::arm_version() != ARMv7) {
+              UnimplementedInstruction(instr);
+              break;
+            }
             rd_val = get_register(rd);
             // fall through
           }
@@ -1785,6 +1783,10 @@
           case 2:
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             // Format(instr, "umaal'cond's 'rd, 'rn, 'rm, 'rs");
+            if (TargetCPUFeatures::arm_version() == ARMv5TE) {
+              // umaal is only in ARMv6 and above.
+              UnimplementedInstruction(instr);
+            }
           case 5:
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             // Format(instr, "umlal'cond's 'rd, 'rn, 'rm, 'rs");
@@ -3584,7 +3586,7 @@
 void Simulator::InstructionDecode(Instr* instr) {
   pc_modified_ = false;
   if (IsTracingExecution()) {
-    OS::Print("%"Pu64, icount_);
+    OS::Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
     Disassembler::Disassemble(start, end);
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index a846d60..250ac5d 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -24,6 +24,7 @@
 class Mutex;
 class RawObject;
 class SimulatorSetjmpBuffer;
+class Thread;
 
 typedef struct {
   union {
@@ -216,31 +217,30 @@
   intptr_t ReadExclusiveW(uword addr, Instr* instr);
   intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr);
 
-  // In Dart, there is at most one thread per isolate.
-  // We keep track of 16 exclusive access address tags across all isolates.
+  // We keep track of 16 exclusive access address tags across all threads.
   // Since we cannot simulate a native context switch, which clears
   // the exclusive access state of the local monitor (using the CLREX
-  // instruction), we associate the isolate requesting exclusive access to the
-  // address tag. Multiple isolates requesting exclusive access (using the LDREX
+  // instruction), we associate the thread requesting exclusive access to the
+  // address tag. Multiple threads requesting exclusive access (using the LDREX
   // instruction) to the same address will result in multiple address tags being
-  // created for the same address, one per isolate.
-  // At any given time, each isolate is associated to at most one address tag.
+  // created for the same address, one per thread.
+  // At any given time, each thread is associated to at most one address tag.
   static Mutex* exclusive_access_lock_;
   static const int kNumAddressTags = 16;
   static struct AddressTag {
-    Isolate* isolate;
+    Thread* thread;
     uword addr;
   } exclusive_access_state_[kNumAddressTags];
   static int next_address_tag_;
 
-  // Set access to given address to 'exclusive state' for current isolate.
+  // Set access to given address to 'exclusive state' for current thread.
   static void SetExclusiveAccess(uword addr);
 
-  // Returns true if the current isolate has exclusive access to given address,
+  // Returns true if the current thread has exclusive access to given address,
   // returns false otherwise. In either case, set access to given address to
-  // 'open state' for all isolates.
+  // 'open state' for all threads.
   // If given addr is NULL, set access to 'open state' for current
-  // isolate (CLREX).
+  // thread (CLREX).
   static bool HasExclusiveAccessAndOpen(uword addr);
 
   // Executing is handled based on the instruction type.
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 763bc75..4acdce0 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -1164,13 +1164,13 @@
 
 // Synchronization primitives support.
 void Simulator::SetExclusiveAccess(uword addr) {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
-  DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate);
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
+  DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
   int i = 0;
-  // Find an entry for this isolate in the exclusive access state.
+  // Find an entry for this thread in the exclusive access state.
   while ((i < kNumAddressTags) &&
-         (exclusive_access_state_[i].isolate != isolate)) {
+         (exclusive_access_state_[i].thread != thread)) {
     i++;
   }
   // Round-robin replacement of previously used entries.
@@ -1179,7 +1179,7 @@
     if (++next_address_tag_ == kNumAddressTags) {
       next_address_tag_ = 0;
     }
-    exclusive_access_state_[i].isolate = isolate;
+    exclusive_access_state_[i].thread = thread;
   }
   // Remember the address being reserved.
   exclusive_access_state_[i].addr = addr;
@@ -1187,20 +1187,20 @@
 
 
 bool Simulator::HasExclusiveAccessAndOpen(uword addr) {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
   ASSERT(addr != 0);
-  DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate);
+  DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
   bool result = false;
   for (int i = 0; i < kNumAddressTags; i++) {
-    if (exclusive_access_state_[i].isolate == isolate) {
-      // Check whether the current isolates address reservation matches.
+    if (exclusive_access_state_[i].thread == thread) {
+      // Check whether the current threads address reservation matches.
       if (exclusive_access_state_[i].addr == addr) {
         result = true;
       }
       exclusive_access_state_[i].addr = 0;
     } else if (exclusive_access_state_[i].addr == addr) {
-      // Other isolates with matching address lose their reservations.
+      // Other threads with matching address lose their reservations.
       exclusive_access_state_[i].addr = 0;
     }
   }
@@ -1210,7 +1210,7 @@
 
 void Simulator::ClearExclusive() {
   MutexLocker ml(exclusive_access_lock_);
-  // Remove the reservation for this isolate.
+  // Remove the reservation for this thread.
   SetExclusiveAccess(NULL);
 }
 
@@ -1238,7 +1238,7 @@
                                  uword new_value) {
   MutexLocker ml(exclusive_access_lock_);
   // We do not get a reservation as it would be guaranteed to be found when
-  // writing below. No other isolate is able to make a reservation while we
+  // writing below. No other thread is able to make a reservation while we
   // hold the lock.
   uword value = *address;
   if (value == compare_value) {
@@ -3300,7 +3300,7 @@
 void Simulator::InstructionDecode(Instr* instr) {
   pc_modified_ = false;
   if (IsTracingExecution()) {
-    OS::Print("%" Pu64, icount_);
+    OS::Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
     Disassembler::Disassemble(start, end);
diff --git a/runtime/vm/simulator_arm64.h b/runtime/vm/simulator_arm64.h
index 83459bb..97e40c4 100644
--- a/runtime/vm/simulator_arm64.h
+++ b/runtime/vm/simulator_arm64.h
@@ -24,6 +24,7 @@
 class Mutex;
 class RawObject;
 class SimulatorSetjmpBuffer;
+class Thread;
 
 typedef struct {
   union {
@@ -185,19 +186,18 @@
   inline intptr_t ReadX(uword addr, Instr* instr);
   inline void WriteX(uword addr, intptr_t value, Instr* instr);
 
-  // In Dart, there is at most one thread per isolate.
-  // We keep track of 16 exclusive access address tags across all isolates.
+  // We keep track of 16 exclusive access address tags across all threads.
   // Since we cannot simulate a native context switch, which clears
   // the exclusive access state of the local monitor (using the CLREX
-  // instruction), we associate the isolate requesting exclusive access to the
-  // address tag. Multiple isolates requesting exclusive access (using the LDREX
+  // instruction), we associate the thread requesting exclusive access to the
+  // address tag. Multiple threads requesting exclusive access (using the LDREX
   // instruction) to the same address will result in multiple address tags being
-  // created for the same address, one per isolate.
-  // At any given time, each isolate is associated to at most one address tag.
+  // created for the same address, one per thread.
+  // At any given time, each thread is associated to at most one address tag.
   static Mutex* exclusive_access_lock_;
   static const int kNumAddressTags = 16;
   static struct AddressTag {
-    Isolate* isolate;
+    Thread* thread;
     uword addr;
   } exclusive_access_state_[kNumAddressTags];
   static int next_address_tag_;
@@ -207,14 +207,14 @@
   intptr_t ReadExclusiveW(uword addr, Instr* instr);
   intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr);
 
-  // Set access to given address to 'exclusive state' for current isolate.
+  // Set access to given address to 'exclusive state' for current thread.
   static void SetExclusiveAccess(uword addr);
 
-  // Returns true if the current isolate has exclusive access to given address,
+  // Returns true if the current thread has exclusive access to given address,
   // returns false otherwise. In either case, set access to given address to
-  // 'open state' for all isolates.
+  // 'open state' for all threads.
   // If given addr is NULL, set access to 'open state' for current
-  // isolate (CLREX).
+  // thread (CLREX).
   static bool HasExclusiveAccessAndOpen(uword addr);
 
   // Helper functions to set the conditional flags in the architecture state.
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 634eed1..1cc6487 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1102,13 +1102,13 @@
 
 // Synchronization primitives support.
 void Simulator::SetExclusiveAccess(uword addr) {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
-  DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate);
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
+  DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
   int i = 0;
-  // Find an entry for this isolate in the exclusive access state.
+  // Find an entry for this thread in the exclusive access state.
   while ((i < kNumAddressTags) &&
-         (exclusive_access_state_[i].isolate != isolate)) {
+         (exclusive_access_state_[i].thread != thread)) {
     i++;
   }
   // Round-robin replacement of previously used entries.
@@ -1117,7 +1117,7 @@
     if (++next_address_tag_ == kNumAddressTags) {
       next_address_tag_ = 0;
     }
-    exclusive_access_state_[i].isolate = isolate;
+    exclusive_access_state_[i].thread = thread;
   }
   // Remember the address being reserved.
   exclusive_access_state_[i].addr = addr;
@@ -1125,20 +1125,20 @@
 
 
 bool Simulator::HasExclusiveAccessAndOpen(uword addr) {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
+  Thread* thread = Thread::Current();
+  ASSERT(thread != NULL);
   ASSERT(addr != 0);
-  DEBUG_ASSERT(exclusive_access_lock_->Owner() == isolate);
+  DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
   bool result = false;
   for (int i = 0; i < kNumAddressTags; i++) {
-    if (exclusive_access_state_[i].isolate == isolate) {
-      // Check whether the current isolate's address reservation matches.
+    if (exclusive_access_state_[i].thread == thread) {
+      // Check whether the current thread's address reservation matches.
       if (exclusive_access_state_[i].addr == addr) {
         result = true;
       }
       exclusive_access_state_[i].addr = 0;
     } else if (exclusive_access_state_[i].addr == addr) {
-      // Other isolates with matching address lose their reservations.
+      // Other threads with matching address lose their reservations.
       exclusive_access_state_[i].addr = 0;
     }
   }
@@ -1148,7 +1148,7 @@
 
 void Simulator::ClearExclusive() {
   MutexLocker ml(exclusive_access_lock_);
-  // Remove the reservation for this isolate.
+  // Remove the reservation for this thread.
   SetExclusiveAccess(NULL);
 }
 
@@ -1176,7 +1176,7 @@
                                  uword new_value) {
   MutexLocker ml(exclusive_access_lock_);
   // We do not get a reservation as it would be guaranteed to be found when
-  // writing below. No other isolate is able to make a reservation while we
+  // writing below. No other thread is able to make a reservation while we
   // hold the lock.
   uword value = *address;
   if (value == compare_value) {
@@ -1982,7 +1982,7 @@
 
 void Simulator::InstructionDecode(Instr* instr) {
   if (IsTracingExecution()) {
-    OS::Print("%" Pu64, icount_);
+    OS::Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
     Disassembler::Disassemble(start, end);
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index 901059dc..16e4728 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -24,6 +24,7 @@
 class Mutex;
 class RawObject;
 class SimulatorSetjmpBuffer;
+class Thread;
 
 class Simulator {
  public:
@@ -197,19 +198,18 @@
   inline double ReadD(uword addr, Instr* instr);
   inline void WriteD(uword addr, double value, Instr* instr);
 
-  // In Dart, there is at most one thread per isolate.
-  // We keep track of 16 exclusive access address tags across all isolates.
+  // We keep track of 16 exclusive access address tags across all threads.
   // Since we cannot simulate a native context switch, which clears
-  // the exclusive access state of the local monitor, we associate the isolate
+  // the exclusive access state of the local monitor, we associate the thread
   // requesting exclusive access to the address tag.
-  // Multiple isolates requesting exclusive access (using the LL instruction)
+  // Multiple threads requesting exclusive access (using the LL instruction)
   // to the same address will result in multiple address tags being created for
-  // the same address, one per isolate.
-  // At any given time, each isolate is associated to at most one address tag.
+  // the same address, one per thread.
+  // At any given time, each thread is associated to at most one address tag.
   static Mutex* exclusive_access_lock_;
   static const int kNumAddressTags = 16;
   static struct AddressTag {
-    Isolate* isolate;
+    Thread* thread;
     uword addr;
   } exclusive_access_state_[kNumAddressTags];
   static int next_address_tag_;
@@ -219,14 +219,14 @@
   intptr_t ReadExclusiveW(uword addr, Instr* instr);
   intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr);
 
-  // Set access to given address to 'exclusive state' for current isolate.
+  // Set access to given address to 'exclusive state' for current thread.
   static void SetExclusiveAccess(uword addr);
 
-  // Returns true if the current isolate has exclusive access to given address,
+  // Returns true if the current thread has exclusive access to given address,
   // returns false otherwise. In either case, set access to given address to
-  // 'open state' for all isolates.
+  // 'open state' for all threads.
   // If given addr is NULL, set access to 'open state' for current
-  // isolate (CLREX).
+  // thread (CLREX).
   static bool HasExclusiveAccessAndOpen(uword addr);
 
   void DoBranch(Instr* instr, bool taken, bool likely);
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 37a6d1e..9539362 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -677,9 +677,16 @@
 class FullSnapshotWriter : public SnapshotWriter {
  public:
   static const intptr_t kInitialSize = 64 * KB;
-  FullSnapshotWriter(uint8_t** buffer, ReAlloc alloc)
-      : SnapshotWriter(Snapshot::kFull, buffer, alloc, kInitialSize, true) {
-    ASSERT(buffer != NULL);
+  FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
+                     uint8_t** isolate_snapshot_buffer,
+                     ReAlloc alloc)
+      : SnapshotWriter(Snapshot::kFull,
+                       isolate_snapshot_buffer,
+                       alloc,
+                       kInitialSize,
+                       true) {
+    ASSERT(vm_isolate_snapshot_buffer != NULL);
+    ASSERT(isolate_snapshot_buffer != NULL);
     ASSERT(alloc != NULL);
   }
   ~FullSnapshotWriter() { }
@@ -687,6 +694,9 @@
   // Writes a full snapshot of the Isolate.
   void WriteFullSnapshot();
 
+  intptr_t VmIsolateSnapshotSize() const { return 0; }
+  intptr_t IsolateSnapshotSize() const { return BytesWritten(); }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(FullSnapshotWriter);
 };
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 94d6d08..965772a 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1029,7 +1029,8 @@
       "}\n";
   Dart_Handle result;
 
-  uint8_t* buffer;
+  uint8_t* vm_isolate_snapshot_buffer;
+  uint8_t* isolate_snapshot_buffer;
 
   // Start an Isolate, load a script and create a full snapshot.
   Timer timer1(true, "Snapshot_test");
@@ -1048,7 +1049,9 @@
     OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
 
     // Write snapshot with object content.
-    FullSnapshotWriter writer(&buffer, &malloc_allocator);
+    FullSnapshotWriter writer(&vm_isolate_snapshot_buffer,
+                              &isolate_snapshot_buffer,
+                              &malloc_allocator);
     writer.WriteFullSnapshot();
   }
 
@@ -1056,7 +1059,7 @@
   // from the script.
   Timer timer2(true, "Snapshot_test");
   timer2.Start();
-  TestCase::CreateTestIsolateFromSnapshot(buffer);
+  TestCase::CreateTestIsolateFromSnapshot(isolate_snapshot_buffer);
   {
     Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
     timer2.Stop();
@@ -1070,7 +1073,7 @@
     Dart_ExitScope();
   }
   Dart_ShutdownIsolate();
-  free(buffer);
+  free(isolate_snapshot_buffer);
 }
 
 
@@ -1083,7 +1086,8 @@
   };
   const char* kScriptChars = kFullSnapshotScriptChars;
 
-  uint8_t* buffer;
+  uint8_t* vm_isolate_snapshot_buffer;
+  uint8_t* isolate_snapshot_buffer;
 
   // Start an Isolate, load a script and create a full snapshot.
   Timer timer1(true, "Snapshot_test");
@@ -1102,7 +1106,9 @@
     OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
 
     // Write snapshot with object content.
-    FullSnapshotWriter writer(&buffer, &malloc_allocator);
+    FullSnapshotWriter writer(&vm_isolate_snapshot_buffer,
+                              &isolate_snapshot_buffer,
+                              &malloc_allocator);
     writer.WriteFullSnapshot();
 
     // Invoke a function which returns an object.
@@ -1115,7 +1121,7 @@
   // from the script.
   Timer timer2(true, "Snapshot_test");
   timer2.Start();
-  TestCase::CreateTestIsolateFromSnapshot(buffer);
+  TestCase::CreateTestIsolateFromSnapshot(isolate_snapshot_buffer);
   {
     Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
     timer2.Stop();
@@ -1133,7 +1139,7 @@
     Dart_ExitScope();
   }
   Dart_ShutdownIsolate();
-  free(buffer);
+  free(isolate_snapshot_buffer);
 }
 
 
@@ -1183,6 +1189,10 @@
 
   uint8_t* buffer;
   intptr_t size;
+  uint8_t* vm_isolate_snapshot = NULL;
+  intptr_t vm_isolate_snapshot_size;
+  uint8_t* isolate_snapshot = NULL;
+  intptr_t isolate_snapshot_size;
   uint8_t* full_snapshot = NULL;
   uint8_t* script_snapshot = NULL;
   intptr_t expected_num_libs;
@@ -1194,10 +1204,13 @@
     Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
 
     // Write out the script snapshot.
-    result = Dart_CreateSnapshot(&buffer, &size);
+    result = Dart_CreateSnapshot(&vm_isolate_snapshot,
+                                 &vm_isolate_snapshot_size,
+                                 &isolate_snapshot,
+                                 &isolate_snapshot_size);
     EXPECT_VALID(result);
-    full_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
-    memmove(full_snapshot, buffer, size);
+    full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
+    memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
     Dart_ExitScope();
   }
 
@@ -1275,6 +1288,10 @@
   Dart_Handle result;
   uint8_t* buffer;
   intptr_t size;
+  uint8_t* vm_isolate_snapshot = NULL;
+  intptr_t vm_isolate_snapshot_size;
+  uint8_t* isolate_snapshot = NULL;
+  intptr_t isolate_snapshot_size;
   uint8_t* full_snapshot = NULL;
   uint8_t* script_snapshot = NULL;
 
@@ -1284,10 +1301,13 @@
     Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
 
     // Write out the script snapshot.
-    result = Dart_CreateSnapshot(&buffer, &size);
+    result = Dart_CreateSnapshot(&vm_isolate_snapshot,
+                                 &vm_isolate_snapshot_size,
+                                 &isolate_snapshot,
+                                 &isolate_snapshot_size);
     EXPECT_VALID(result);
-    full_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
-    memmove(full_snapshot, buffer, size);
+    full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
+    memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
     Dart_ExitScope();
   }
 
@@ -1352,6 +1372,10 @@
 
   uint8_t* buffer;
   intptr_t size;
+  uint8_t* vm_isolate_snapshot = NULL;
+  intptr_t vm_isolate_snapshot_size;
+  uint8_t* isolate_snapshot = NULL;
+  intptr_t isolate_snapshot_size;
   uint8_t* full_snapshot = NULL;
   uint8_t* script_snapshot = NULL;
 
@@ -1365,10 +1389,13 @@
     Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
 
     // Write out the script snapshot.
-    result = Dart_CreateSnapshot(&buffer, &size);
+    result = Dart_CreateSnapshot(&vm_isolate_snapshot,
+                                 &vm_isolate_snapshot_size,
+                                 &isolate_snapshot,
+                                 &isolate_snapshot_size);
     EXPECT_VALID(result);
-    full_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
-    memmove(full_snapshot, buffer, size);
+    full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
+    memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
     Dart_ExitScope();
   }
 
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index f8537c3..8e3806c 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -430,7 +430,7 @@
   : index_(0),
     num_materializations_(0),
     code_(Code::Handle(code.raw())),
-    deopt_info_(DeoptInfo::Handle()),
+    deopt_info_(TypedData::Handle()),
     function_(Function::Handle()),
     pc_(pc),
     deopt_instructions_(),
@@ -450,8 +450,8 @@
     // Unpack deopt info into instructions (translate away suffixes).
     const Array& deopt_table = Array::Handle(code_.deopt_info_array());
     ASSERT(!deopt_table.IsNull());
-    deopt_info_.ToInstructions(deopt_table, &deopt_instructions_);
-    num_materializations_ = deopt_info_.NumMaterializations();
+    DeoptInfo::Unpack(deopt_table, deopt_info_, &deopt_instructions_);
+    num_materializations_ = DeoptInfo::NumMaterializations(deopt_instructions_);
     object_table_ = code_.object_table();
     Advance();
   }
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 2195d81..a3cc4a0 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -319,7 +319,7 @@
   intptr_t index_;
   intptr_t num_materializations_;
   Code& code_;
-  DeoptInfo& deopt_info_;
+  TypedData& deopt_info_;
   Function& function_;
   uword pc_;
   GrowableArray<DeoptInstr*> deopt_instructions_;
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index d8d9371..01a07c7 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -531,7 +531,8 @@
   // Frame is fully rewritten at this point and it is safe to perform a GC.
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
-  __ EnterStubFrame();
+  // Enter stub frame with loading PP. The caller's PP is not materialized yet.
+  __ EnterStubFrame(true);
   if (preserve_result) {
     __ Push(R1);  // Preserve result, it will be GC-d here.
   }
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 6621689..033ef48 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -539,7 +539,8 @@
   // Frame is fully rewritten at this point and it is safe to perform a GC.
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
-  __ EnterStubFrame();
+  // Enter stub frame with loading PP. The caller's PP is not materialized yet.
+  __ EnterStubFrame(true);
   if (preserve_result) {
     __ Push(ZR);  // Workaround for dropped stack slot during GC.
     __ Push(R1);  // Preserve result, it will be GC-d here.
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index a00fd1f..bab5cdf 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -41,7 +41,7 @@
   const intptr_t exitframe_last_param_slot_from_fp = 2;
 
   __ SetPrologueOffset();
-  __ TraceSimMsg("CallToRuntimeStub");
+  __ 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));
@@ -101,7 +101,7 @@
     ASSERT(retval_offset == 3 * kWordSize);
   // Retval is next to 1st argument.
   __ delay_slot()->addiu(A3, A2, Immediate(kWordSize));
-  __ TraceSimMsg("CallToRuntimeStub return");
+  __ Comment("CallToRuntimeStub return");
 
   // Mark that the isolate is executing Dart code.
   __ LoadImmediate(A2, VMTag::kDartTagId);
@@ -150,7 +150,7 @@
   const intptr_t retval_offset = NativeArguments::retval_offset();
 
   __ SetPrologueOffset();
-  __ TraceSimMsg("CallNativeCFunctionStub");
+  __ 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));
@@ -218,7 +218,7 @@
 #else
   __ BranchLink(&NativeEntry::NativeCallWrapperLabel());
 #endif
-  __ TraceSimMsg("CallNativeCFunctionStub return");
+  __ Comment("CallNativeCFunctionStub return");
 
   // Mark that the isolate is executing Dart code.
   __ LoadImmediate(A2, VMTag::kDartTagId);
@@ -248,7 +248,7 @@
   const intptr_t retval_offset = NativeArguments::retval_offset();
 
   __ SetPrologueOffset();
-  __ TraceSimMsg("CallNativeCFunctionStub");
+  __ 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));
@@ -311,7 +311,7 @@
   // the MIPS ABI.
   __ mov(T9, T5);
   __ jalr(T9);
-  __ TraceSimMsg("CallNativeCFunctionStub return");
+  __ Comment("CallNativeCFunctionStub return");
 
   // Mark that the isolate is executing Dart code.
   __ LoadImmediate(A2, VMTag::kDartTagId);
@@ -331,7 +331,7 @@
 // Input parameters:
 //   S4: arguments descriptor array.
 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
-  __ TraceSimMsg("CallStaticFunctionStub");
+  __ Comment("CallStaticFunctionStub");
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
 
@@ -341,7 +341,7 @@
   __ sw(TMP, Address(SP, 0 * kWordSize));
 
   __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
-  __ TraceSimMsg("CallStaticFunctionStub return");
+  __ Comment("CallStaticFunctionStub return");
 
   // Get Code object result and restore arguments descriptor array.
   __ lw(T0, Address(SP, 0 * kWordSize));
@@ -362,7 +362,7 @@
 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
-  __ TraceSimMsg("FixCallersTarget");
+  __ Comment("FixCallersTarget");
   __ EnterStubFrame();
   // Setup space on stack for return value and preserve arguments descriptor.
   __ addiu(SP, SP, Immediate(-2 * kWordSize));
@@ -387,7 +387,7 @@
 // Called from object allocate instruction when the allocation stub has been
 // disabled.
 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
-  __ TraceSimMsg("FixAllocationStubTarget");
+  __ Comment("FixAllocationStubTarget");
   __ EnterStubFrame();
   // Setup space on stack for return value.
   __ addiu(SP, SP, Immediate(-1 * kWordSize));
@@ -412,7 +412,7 @@
 // A0: element type (preserved).
 // A1: length (preserved).
 void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) {
-  __ TraceSimMsg("FixAllocationStubTarget");
+  __ Comment("FixAllocationStubTarget");
   __ EnterStubFrame();
   // Setup space on stack for return value.
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
@@ -441,7 +441,7 @@
 //   FP[kParamEndSlotFromFp + 1]: Last argument.
 static void PushArgumentsArray(Assembler* assembler) {
   StubCode* stub_code = Isolate::Current()->stub_code();
-  __ TraceSimMsg("PushArgumentsArray");
+  __ Comment("PushArgumentsArray");
   // Allocate array to store arguments of caller.
   __ LoadImmediate(A0, reinterpret_cast<intptr_t>(Object::null()));
   // A0: Null element type for raw Array.
@@ -449,7 +449,7 @@
   const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
   const ExternalLabel array_label(array_stub.EntryPoint());
   __ BranchLink(&array_label);
-  __ TraceSimMsg("PushArgumentsArray return");
+  __ Comment("PushArgumentsArray return");
   // V0: newly allocated array.
   // A1: Smi-tagged argument count, may be zero (was preserved by the stub).
   __ Push(V0);  // Array is in V0 and on top of stack.
@@ -513,7 +513,7 @@
       kNumberOfFRegisters * kWordSize;
 
   __ SetPrologueOffset();
-  __ TraceSimMsg("GenerateDeoptimizationSequence");
+  __ Comment("GenerateDeoptimizationSequence");
   // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
   // is no need to set the correct PC marker or load PP, since they get patched.
   __ addiu(SP, SP, Immediate(-kPushedRegistersSize * kWordSize));
@@ -588,7 +588,8 @@
   // Frame is fully rewritten at this point and it is safe to perform a GC.
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
-  __ EnterStubFrame();
+  // Enter stub frame with loading PP. The caller's PP is not materialized yet.
+  __ EnterStubFrame(true);
   if (preserve_result) {
     __ Push(T1);  // Preserve result, it will be GC-d here.
   }
@@ -669,7 +670,7 @@
 // The newly allocated object is returned in V0.
 void StubCode::GeneratePatchableAllocateArrayStub(Assembler* assembler,
     uword* entry_patch_offset, uword* patch_code_pc_offset) {
-  __ TraceSimMsg("AllocateArrayStub");
+  __ Comment("AllocateArrayStub");
   *entry_patch_offset = assembler->CodeSize();
   Label slow_case;
 
@@ -792,7 +793,7 @@
   __ sw(A1, Address(SP, 1 * kWordSize));
   __ sw(A0, Address(SP, 0 * kWordSize));
   __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
-  __ TraceSimMsg("AllocateArrayStub return");
+  __ Comment("AllocateArrayStub return");
   // Pop arguments; result is popped in IP.
   __ lw(V0, Address(SP, 2 * kWordSize));
   __ lw(A1, Address(SP, 1 * kWordSize));
@@ -814,7 +815,7 @@
 //   A2 : arguments array.
 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
   // Save frame pointer coming in.
-  __ TraceSimMsg("InvokeDartCodeStub");
+  __ Comment("InvokeDartCodeStub");
   __ EnterFrame();
 
   // Save new context and C++ ABI callee-saved registers.
@@ -900,7 +901,7 @@
   // We are calling into Dart code, here, so there is no need to call through
   // T9 to match the ABI.
   __ jalr(A0);  // S4 is the arguments descriptor array.
-  __ TraceSimMsg("InvokeDartCodeStub return");
+  __ Comment("InvokeDartCodeStub return");
 
   // Get rid of arguments pushed on the stack.
   __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize);
@@ -947,7 +948,7 @@
 // Output:
 //   V0: new allocated RawContext object.
 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
-  __ TraceSimMsg("AllocateContext");
+  __ Comment("AllocateContext");
   if (FLAG_inline_alloc) {
     Label slow_case;
     Heap* heap = Isolate::Current()->heap();
@@ -1066,7 +1067,7 @@
 //   T0: Address (i.e. object) being stored into.
 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
   // Save values being destroyed.
-  __ TraceSimMsg("UpdateStoreBufferStub");
+  __ Comment("UpdateStoreBufferStub");
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
   __ sw(T3, Address(SP, 2 * kWordSize));
   __ sw(T2, Address(SP, 1 * kWordSize));
@@ -1126,7 +1127,7 @@
   __ EnterCallRuntimeFrame(1 * kWordSize);
   __ LoadIsolate(A0);
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
-  __ TraceSimMsg("UpdateStoreBufferStub return");
+  __ Comment("UpdateStoreBufferStub return");
   // Restore callee-saved registers, tear down frame.
   __ LeaveCallRuntimeFrame();
   __ Ret();
@@ -1142,7 +1143,7 @@
 void StubCode::GenerateAllocationStubForClass(
     Assembler* assembler, const Class& cls,
     uword* entry_patch_offset, uword* patch_code_pc_offset) {
-  __ TraceSimMsg("AllocationStubForClass");
+  __ Comment("AllocationStubForClass");
   *entry_patch_offset = assembler->CodeSize();
   // The generated code is different if the class is parameterized.
   const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
@@ -1258,7 +1259,7 @@
     __ sw(T7, Address(SP, 0 * kWordSize));
   }
   __ CallRuntime(kAllocateObjectRuntimeEntry, 2);  // Allocate object.
-  __ TraceSimMsg("AllocationStubForClass return");
+  __ Comment("AllocationStubForClass return");
   // Pop result (newly allocated object).
   __ lw(V0, Address(SP, 2 * kWordSize));
   __ addiu(SP, SP, Immediate(3 * kWordSize));  // Pop arguments.
@@ -1311,7 +1312,7 @@
 // Cannot use function object from ICData as it may be the inlined
 // function and not the top-scope function.
 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
-  __ TraceSimMsg("OptimizedUsageCounterIncrement");
+  __ Comment("OptimizedUsageCounterIncrement");
   Register ic_reg = S5;
   Register func_reg = T0;
   if (FLAG_trace_optimized_ic_calls) {
@@ -1336,7 +1337,7 @@
 // Loads function into 'temp_reg'.
 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
                                              Register temp_reg) {
-  __ TraceSimMsg("UsageCounterIncrement");
+  __ Comment("UsageCounterIncrement");
   Register ic_reg = S5;
   Register func_reg = temp_reg;
   ASSERT(temp_reg == T0);
@@ -1432,7 +1433,7 @@
     const RuntimeEntry& handle_ic_miss,
     Token::Kind kind,
     RangeCollectionMode range_collection_mode) {
-  __ TraceSimMsg("NArgsCheckInlineCacheStub");
+  __ Comment("NArgsCheckInlineCacheStub");
   ASSERT(num_args > 0);
 #if defined(DEBUG)
   { Label ok;
@@ -1571,7 +1572,7 @@
   // Pass IC data object.
   __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize));
   __ CallRuntime(handle_ic_miss, num_args + 1);
-  __ TraceSimMsg("NArgsCheckInlineCacheStub return");
+  __ Comment("NArgsCheckInlineCacheStub return");
   // Pop returned function object into T3.
   // Restore arguments descriptor array and IC data array.
   __ lw(T3, Address(SP, (num_slots - 3) * kWordSize));
@@ -1759,7 +1760,7 @@
 // S5: ICData
 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, T0);
-  __ TraceSimMsg("UnoptimizedStaticCallStub");
+  __ Comment("UnoptimizedStaticCallStub");
 #if defined(DEBUG)
   { Label ok;
     // Check that the IC data array has NumArgsTested() == 0.
@@ -1951,7 +1952,7 @@
 // A2: cache array.
 // Result in V0: null -> not found, otherwise result (true or false).
 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
-  __ TraceSimMsg("SubtypeNTestCacheStub");
+  __ Comment("SubtypeNTestCacheStub");
   ASSERT((1 <= n) && (n <= 3));
   if (n > 1) {
     // Get instance type arguments.
@@ -2094,7 +2095,7 @@
 // T0: function to be reoptimized.
 // S4: argument descriptor (preserved).
 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
-  __ TraceSimMsg("OptimizeFunctionStub");
+  __ Comment("OptimizeFunctionStub");
   __ EnterStubFrame();
   __ addiu(SP, SP, Immediate(-3 * kWordSize));
   __ sw(S4, Address(SP, 2 * kWordSize));
@@ -2103,7 +2104,7 @@
   __ sw(TMP, Address(SP, 1 * kWordSize));
   __ sw(T0, Address(SP, 0 * kWordSize));
   __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
-  __ TraceSimMsg("OptimizeFunctionStub return");
+  __ Comment("OptimizeFunctionStub return");
   __ lw(T0, Address(SP, 1 * kWordSize));  // Get Code object
   __ lw(S4, Address(SP, 2 * kWordSize));  // Restore argument descriptor.
   __ addiu(SP, SP, Immediate(3 * kWordSize));  // Discard argument.
@@ -2131,7 +2132,6 @@
                                                     const Register right,
                                                     const Register temp1,
                                                     const Register temp2) {
-  __ TraceSimMsg("IdenticalWithNumberCheckStub");
   __ Comment("IdenticalWithNumberCheckStub");
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
@@ -2190,7 +2190,7 @@
   __ mov(A0, left);
   __ mov(A1, right);
   __ CallRuntime(kBigintCompareRuntimeEntry, 2);
-  __ TraceSimMsg("IdenticalWithNumberCheckStub return");
+  __ Comment("IdenticalWithNumberCheckStub return");
   // Result in V0, 0 means equal.
   __ LeaveStubFrame();
   __ b(&done);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 8132e99..4be0ca2 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -483,7 +483,8 @@
   // Frame is fully rewritten at this point and it is safe to perform a GC.
   // Materialize any objects that were deferred by FillFrame because they
   // require allocation.
-  __ EnterStubFrame();
+  // Enter stub frame with loading PP. The caller's PP is not materialized yet.
+  __ EnterStubFrame(true);
   if (preserve_result) {
     __ pushq(Immediate(0));  // Workaround for dropped stack slot during GC.
     __ pushq(RBX);  // Preserve result, it will be GC-d here.
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index a55bcfb..f52e20a 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -16,7 +16,6 @@
 
 // One-character symbols are added implicitly.
 #define PREDEFINED_SYMBOLS_LIST(V)                                             \
-  V(Empty, "")                                                                 \
   V(EqualOperator, "==")                                                       \
   V(GreaterEqualOperator, ">=")                                                \
   V(LessEqualOperator, "<=")                                                   \
@@ -31,9 +30,7 @@
   V(AssignIndexToken, "[]=")                                                   \
   V(TopLevel, "::")                                                            \
   V(DefaultLabel, ":L")                                                        \
-  V(This, "this")                                                              \
   V(Other, "other")                                                            \
-  V(Super, "super")                                                            \
   V(Call, "call")                                                              \
   V(Current, "current")                                                        \
   V(MoveNext, "moveNext")                                                      \
@@ -57,6 +54,7 @@
   V(_EnumNames, "_enum_names")                                                 \
   V(ExprTemp, ":expr_temp")                                                    \
   V(AnonymousClosure, "<anonymous closure>")                                   \
+  V(ImplicitClosure, "<implicit closure>")                                     \
   V(ClosureParameter, ":closure")                                              \
   V(PhaseParameter, ":phase")                                                  \
   V(TypeArgumentsParameter, ":type_arguments")                                 \
@@ -92,7 +90,6 @@
   V(SavedStackTraceVar, ":saved_stack_trace_var")                              \
   V(ListLiteralElement, "list literal element")                                \
   V(ForInIter, ":for-in-iter")                                                 \
-  V(Library, "library")                                                        \
   V(LoadLibrary, "loadLibrary")                                                \
   V(_LibraryPrefix, "_LibraryPrefix")                                          \
   V(On, "on")                                                                  \
@@ -129,7 +126,6 @@
   V(Class, "Class")                                                            \
   V(Null, "Null")                                                              \
   V(Dynamic, "dynamic")                                                        \
-  V(Void, "void")                                                              \
   V(UnresolvedClass, "UnresolvedClass")                                        \
   V(Type, "_Type")                                                             \
   V(TypeRef, "_TypeRef")                                                       \
@@ -176,8 +172,6 @@
   V(_Bigint, "_Bigint")                                                        \
   V(_Double, "_Double")                                                        \
   V(Bool, "bool")                                                              \
-  V(True, "true")                                                              \
-  V(False, "false")                                                            \
   V(_List, "_List")                                                            \
   V(_ListFactory, "_List.")                                                    \
   V(_GrowableList, "_GrowableList")                                            \
@@ -334,6 +328,7 @@
   V(DartVMService, "dart:vmservice")                                           \
   V(DartProfiler, "dart:profiler")                                             \
   V(DartIOLibName, "dart.io")                                                  \
+  V(EvalSourceUri, "evaluate:source")                                          \
   V(_Random, "_Random")                                                        \
   V(_state, "_state")                                                          \
   V(_A, "_A")                                                                  \
@@ -511,6 +506,14 @@
     return *(symbol_handles_[kNullCharId + '~']);
   }
 
+  static const String& Empty() { return *(symbol_handles_[kKwTableStart]); }
+  static const String& False() { return *(symbol_handles_[kFALSEId]); }
+  static const String& Library() { return *(symbol_handles_[kLIBRARYId]); }
+  static const String& Super() { return *(symbol_handles_[kSUPERId]); }
+  static const String& This() { return *(symbol_handles_[kTHISId]); }
+  static const String& True() { return *(symbol_handles_[kTRUEId]); }
+  static const String& Void() { return *(symbol_handles_[kVOIDId]); }
+
   // Access methods for symbol handles stored in the vm isolate.
 #define DEFINE_SYMBOL_HANDLE_ACCESSOR(symbol, literal)                         \
   static const String& symbol() { return *(symbol_handles_[k##symbol##Id]); }
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 199fd78..c319b51 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -6,6 +6,8 @@
 
 #include "vm/isolate.h"
 #include "vm/os_thread.h"
+#include "vm/profiler.h"
+#include "vm/thread_interrupter.h"
 
 
 namespace dart {
@@ -13,18 +15,76 @@
 // The single thread local key which stores all the thread local data
 // for a thread.
 // TODO(koda): Can we merge this with ThreadInterrupter::thread_state_key_?
-ThreadLocalKey Thread::thread_key = OSThread::kUnsetThreadLocalKey;
+ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey;
 
 
 void Thread::InitOnce() {
-  ASSERT(thread_key == OSThread::kUnsetThreadLocalKey);
-  thread_key = OSThread::CreateThreadLocal();
-  ASSERT(thread_key != OSThread::kUnsetThreadLocalKey);
+  ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey);
+  thread_key_ = OSThread::CreateThreadLocal();
+  ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey);
 }
 
 
 void Thread::SetCurrent(Thread* current) {
-  OSThread::SetThreadLocal(thread_key, reinterpret_cast<uword>(current));
+  OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current));
 }
 
+
+void Thread::EnsureInit() {
+  if (Thread::Current() == NULL) {
+    SetCurrent(new Thread());
+  }
+}
+
+
+void Thread::CleanUp() {
+  // We currently deallocate the Thread, to ensure that embedder threads don't
+  // leak the Thread structure. An alternative approach would be to clear and
+  // reuse it, but register a destructor at the OS level.
+  Thread* current = Current();
+  if (current != NULL) {
+    delete current;
+  }
+  SetCurrent(NULL);
+}
+
+
+void Thread::EnterIsolate(Isolate* isolate) {
+  EnsureInit();
+  Thread* thread = Thread::Current();
+  ASSERT(thread->isolate() == NULL);
+  ASSERT(isolate->mutator_thread() == NULL);
+  isolate->set_mutator_thread(thread);
+  // TODO(koda): Migrate thread_state_ and profile_data_ to Thread, to allow
+  // helper threads concurrent with mutator.
+  ASSERT(isolate->thread_state() == NULL);
+  InterruptableThreadState* thread_state =
+      ThreadInterrupter::GetCurrentThreadState();
+#if defined(DEBUG)
+  Isolate::CheckForDuplicateThreadState(thread_state);
+#endif
+  ASSERT(thread_state != NULL);
+  Profiler::BeginExecution(isolate);
+  isolate->set_thread_state(thread_state);
+  isolate->set_vm_tag(VMTag::kVMTagId);
+  thread->isolate_ = isolate;
+}
+
+
+void Thread::ExitIsolate() {
+  Thread* thread = Thread::Current();
+  // TODO(koda): Audit callers; they should know whether they're in an isolate.
+  if (thread == NULL) return;
+  Isolate* isolate = thread->isolate();
+  ASSERT(isolate != NULL);
+  isolate->set_vm_tag(VMTag::kIdleTagId);
+  isolate->set_thread_state(NULL);
+  Profiler::EndExecution(isolate);
+  isolate->set_mutator_thread(NULL);
+  thread->isolate_ = NULL;
+  ASSERT(Isolate::Current() == NULL);
+  CleanUp();
+}
+
+
 }  // namespace dart
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index bc5c998..8218fba 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -15,19 +15,28 @@
 class Isolate;
 
 // A VM thread; may be executing Dart code or performing helper tasks like
-// garbage collection or compilation.
+// garbage collection or compilation. The Thread structure associated with
+// a thread is allocated when the thread enters an isolate, and destroyed
+// upon exiting an isolate or an explicit call to CleanUp.
 class Thread {
  public:
-  explicit Thread(Isolate* isolate)
-      : isolate_(isolate),
-        cha_(NULL) {}
-
-  static void InitOnce();
-
+  // The currently executing thread, or NULL if not yet initialized.
   static Thread* Current() {
-    return reinterpret_cast<Thread*>(OSThread::GetThreadLocal(thread_key));
+    return reinterpret_cast<Thread*>(OSThread::GetThreadLocal(thread_key_));
   }
-  static void SetCurrent(Thread* current);
+
+  // Makes the current thread enter 'isolate'. Also calls EnsureInit.
+  static void EnterIsolate(Isolate* isolate);
+  // Makes the current thread exit its isolate. Also calls CleanUp.
+  static void ExitIsolate();
+
+  // Initializes the current thread as a VM thread, if not already done.
+  static void EnsureInit();
+  // Clears the state of the current thread.
+  static void CleanUp();
+
+  // Called at VM startup.
+  static void InitOnce();
 
   // The topmost zone used for allocation in this thread.
   Zone* zone() {
@@ -42,11 +51,17 @@
   void set_cha(CHA* value) { cha_ = value; }
 
  private:
-  static ThreadLocalKey thread_key;
+  static ThreadLocalKey thread_key_;
 
   Isolate* isolate_;
   CHA* cha_;
 
+  Thread()
+      : isolate_(NULL),
+        cha_(NULL) {}
+
+  static void SetCurrent(Thread* current);
+
   DISALLOW_COPY_AND_ASSIGN(Thread);
 };
 
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
index b2f5f1c..10cff89 100644
--- a/runtime/vm/thread_interrupter.cc
+++ b/runtime/vm/thread_interrupter.cc
@@ -314,6 +314,7 @@
       ASSERT(current_wait_time_ != Monitor::kNoTimeout);
     }
   }
+  RemoveSignalHandler();
   if (FLAG_trace_thread_interrupter) {
     OS::Print("ThreadInterrupter thread exiting.\n");
   }
diff --git a/runtime/vm/thread_interrupter.h b/runtime/vm/thread_interrupter.h
index 2d9e336..2d3d1b3 100644
--- a/runtime/vm/thread_interrupter.h
+++ b/runtime/vm/thread_interrupter.h
@@ -92,6 +92,8 @@
 
   static void InstallSignalHandler();
 
+  static void RemoveSignalHandler();
+
   friend class ThreadInterrupterVisitIsolates;
 };
 
diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc
index 237d783..fd27d53 100644
--- a/runtime/vm/thread_interrupter_android.cc
+++ b/runtime/vm/thread_interrupter_android.cc
@@ -59,6 +59,11 @@
       ThreadInterrupterAndroid::ThreadInterruptSignalHandler);
 }
 
+
+void ThreadInterrupter::RemoveSignalHandler() {
+  SignalHandler::Remove();
+}
+
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_ANDROID)
diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc
index 67eee89..5ff3c92 100644
--- a/runtime/vm/thread_interrupter_linux.cc
+++ b/runtime/vm/thread_interrupter_linux.cc
@@ -56,6 +56,12 @@
   SignalHandler::Install(ThreadInterrupterLinux::ThreadInterruptSignalHandler);
 }
 
+
+void ThreadInterrupter::RemoveSignalHandler() {
+  SignalHandler::Remove();
+}
+
+
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc
index 4d72afa..b5beeeb 100644
--- a/runtime/vm/thread_interrupter_macos.cc
+++ b/runtime/vm/thread_interrupter_macos.cc
@@ -55,6 +55,11 @@
   SignalHandler::Install(ThreadInterrupterMacOS::ThreadInterruptSignalHandler);
 }
 
+
+void ThreadInterrupter::RemoveSignalHandler() {
+  SignalHandler::Remove();
+}
+
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc
index 8f0ed95..07feed0 100644
--- a/runtime/vm/thread_interrupter_win.cc
+++ b/runtime/vm/thread_interrupter_win.cc
@@ -110,6 +110,12 @@
   // Nothing to do on Windows.
 }
 
+
+void ThreadInterrupter::RemoveSignalHandler() {
+  // Nothing to do on Windows.
+}
+
+
 }  // namespace dart
 
 #endif  // defined(TARGET_OS_WINDOWS)
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index 9e819b9..f81f99a 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -274,7 +274,11 @@
 
     // Release monitor while handling the task.
     monitor_.Exit();
+    Thread::EnsureInit();
     task->Run();
+    ASSERT(Isolate::Current() == NULL);
+    // Prevent unintended sharing of state between tasks.
+    Thread::CleanUp();
     delete task;
     monitor_.Enter();
 
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 41695ed..e554b5a 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -217,10 +217,14 @@
 class VirtualMemory;
 
 
-// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
-// it is initialized to NULL.
 namespace bin {
-extern const uint8_t* snapshot_buffer;
+// vm_isolate_snapshot_buffer points to a snapshot for the vm isolate if we
+// link in a snapshot otherwise it is initialized to NULL.
+extern const uint8_t* vm_isolate_snapshot_buffer;
+
+// isolate_snapshot_buffer points to a snapshot for an isolate if we link in a
+// snapshot otherwise it is initialized to NULL.
+extern const uint8_t* isolate_snapshot_buffer;
 }
 
 
@@ -269,7 +273,7 @@
     return CreateIsolate(buffer, name);
   }
   static Dart_Isolate CreateTestIsolate(const char* name = NULL) {
-    return CreateIsolate(bin::snapshot_buffer, name);
+    return CreateIsolate(bin::isolate_snapshot_buffer, name);
   }
   static Dart_Handle library_handler(Dart_LibraryTag tag,
                                      Dart_Handle library,
diff --git a/sdk/api_readme.md b/sdk/api_readme.md
new file mode 100644
index 0000000..e11030d
--- /dev/null
+++ b/sdk/api_readme.md
@@ -0,0 +1,42 @@
+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):
+    Core functionality such as strings, numbers, collections, errors,
+    dates, and URIs.
+  * [dart:html](./dart_html/index.html):
+    DOM manipulation for web apps.
+  * [dart:io](./dart_io/index.html):
+    I/O for command-line apps.
+  
+Except for dart:core, you must import a library before you can use it.
+Here's an example of importing dart:html, dart:math, and a
+third popular library called [polymer.dart](https://www.dartlang.org/polymer-dart/):
+  
+    import 'dart:html';
+    import 'dart:math';
+    import 'package:polymer/polymer.dart';
+  
+Polymer.dart is an example of a library that isn't
+included in the Dart download,
+but is easy to get and update using the _pub package manager_.
+For information on finding, using, and publishing libraries (and more)
+with pub, see [pub.dartlang.org](https://pub.dartlang.org).
+  
+The main site for learning and using Dart is
+[www.dartlang.org](https://www.dartlang.org).
+Check out these pages:
+  
+  * [Dart homepage](https://www.dartlang.org)
+  * [Tutorials](https://www.dartlang.org/docs/tutorials/)
+  * [Programmer's Guide](https://www.dartlang.org/docs/)
+  * [Samples](https://www.dartlang.org/samples/)
+  * [A Tour of the Dart Libraries](https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html)
+  
+This API reference is automatically generated from the source code in the
+[Dart project](https://code.google.com/p/dart/).
+If you'd like to contribute to this documentation, see
+[Contributing](https://code.google.com/p/dart/wiki/Contributing)
+and
+[Writing API Documentation](https://code.google.com/p/dart/wiki/WritingApiDocumentation).
\ No newline at end of file
diff --git a/sdk/lib/_internal/compiler/js_lib/js_array.dart b/sdk/lib/_internal/compiler/js_lib/js_array.dart
index 981cbd2..5763242 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_array.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_array.dart
@@ -544,13 +544,16 @@
 
   String toString() => ListBase.listToString(this);
 
-  List<E> toList({ bool growable: true }) {
-    if (growable) {
-      return new JSArray<E>.markGrowable(JS('', '#.slice()', this));
-    } else {
-      return new JSArray<E>.markFixed(JS('', '#.slice()', this));
-    }
-  }
+  List<E> toList({ bool growable: true }) =>
+      growable
+        ? _toListGrowable()
+        : _toListFixed();
+
+  List<E> _toListGrowable() =>
+      new JSArray<E>.markGrowable(JS('', '#.slice()', this));
+
+  List<E> _toListFixed() =>
+      new JSArray<E>.markFixed(JS('', '#.slice()', this));
 
   Set<E> toSet() => new Set<E>.from(this);
 
diff --git a/sdk/lib/_internal/compiler/js_lib/js_helper.dart b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
index 1e83b62..163833b 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_helper.dart
@@ -673,7 +673,9 @@
   @NoInline()
   static double _parseDoubleError(String source,
                                   double handleError(String source)) {
-    if (handleError == null) throw new FormatException(source);
+    if (handleError == null) {
+      throw new FormatException("Invalid double", source);
+    }
     return handleError(source);
   }
 
diff --git a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
index 9fc50b7..c69e159 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_mirrors.dart
@@ -991,7 +991,7 @@
       case JSInvocationMirror.METHOD:
         if (namedArguments.isNotEmpty) return '$name*';
         int nbArgs = positionalArguments.length as int;
-        return "$name:$nbArgs:0";
+        return "$name:$nbArgs";
     }
     throw new RuntimeError("Could not compute reflective name for $name");
   }
@@ -1685,7 +1685,7 @@
       // reflection with metadata.
       if (simpleName == null) continue;
       var function = JS('', '#[#]', prototype, key);
-      if (isNoSuchMethodStub(function)) continue;
+      if (!isOrdinaryReflectableMethod(function)) continue;
       if (isAliasedSuperMethod(function, key)) continue;
       var mirror =
           new JsMethodMirror.fromUnmangledName(
@@ -2331,8 +2331,11 @@
         requiredParameterCount = 0;
       }
     } else {
-      requiredParameterCount = int.parse(info[1]);
-      optionalParameterCount = int.parse(info[2]);
+      ReflectionInfo reflectionInfo = new ReflectionInfo(jsFunction);
+      requiredParameterCount = reflectionInfo.requiredParameterCount;
+      optionalParameterCount = reflectionInfo.optionalParameterCount;
+      assert(int.parse(info[1]) == requiredParameterCount
+          + optionalParameterCount);
     }
     return new JsMethodMirror(
         s(name), jsFunction, requiredParameterCount, optionalParameterCount,
@@ -2959,8 +2962,10 @@
   return firstChar == '*' || firstChar == '+';
 }
 
-bool isNoSuchMethodStub(var jsFunction) {
-  return JS('bool', r'#.$reflectable == 2', jsFunction);
+/// Returns `true` if [jsFunction] is an ordinary reflectable method and
+/// not a (potentially reflectable) stub or otherwise non-reflectable method.
+bool isOrdinaryReflectableMethod(var jsFunction) {
+  return JS('bool', r'#.$reflectable === 1', jsFunction);
 }
 
 /// Returns true if [key] is only an aliased entry for [function] in the
diff --git a/sdk/lib/_internal/compiler/js_lib/js_names.dart b/sdk/lib/_internal/compiler/js_lib/js_names.dart
index 76c72be..708b873 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_names.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_names.dart
@@ -130,7 +130,8 @@
     return result;
   }
 
-  int get _jsMangledNamesLength => JS('int', '#.length', _jsMangledNames);
+  int get _jsMangledNamesLength => JS('int', 'Object.keys(#).length',
+      _jsMangledNames);
 
   String operator[](String key) {
     if (_cache == null || _jsMangledNamesLength != _cacheLength) {
diff --git a/sdk/lib/_internal/compiler/js_lib/regexp_helper.dart b/sdk/lib/_internal/compiler/js_lib/regexp_helper.dart
index 4bdf754..e99810a 100644
--- a/sdk/lib/_internal/compiler/js_lib/regexp_helper.dart
+++ b/sdk/lib/_internal/compiler/js_lib/regexp_helper.dart
@@ -101,7 +101,7 @@
     // Dart exception.
     String errorMessage = JS('String', r'String(#)', regexp);
     throw new FormatException(
-        "Illegal RegExp pattern: $source, $errorMessage");
+        "Illegal RegExp pattern ($errorMessage)", source);
   }
 
   Match firstMatch(String string) {
diff --git a/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart b/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart
index 0105cbf..dfca127 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/dependency_computer.dart
@@ -75,7 +75,7 @@
           return phase.expand((config) {
             var id = config.id;
             if (id.isBuiltInTransformer) return [];
-            if (id.package != _graph.entrypoint.root.name &&
+            if (package.name != _graph.entrypoint.root.name &&
                 !config.canTransformPublicFiles) {
               return [];
             }
diff --git a/sdk/lib/_internal/pub/lib/src/command/run.dart b/sdk/lib/_internal/pub/lib/src/command/run.dart
index eca10b9..55cc957 100644
--- a/sdk/lib/_internal/pub/lib/src/command/run.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/run.dart
@@ -12,6 +12,7 @@
 import '../command.dart';
 import '../executable.dart';
 import '../io.dart';
+import '../log.dart' as log;
 import '../utils.dart';
 
 /// Handles the `run` pub command.
@@ -51,6 +52,21 @@
         usageException("Cannot run an executable in a subdirectory of a " +
             "dependency.");
       }
+    } else if (onlyIdentifierRegExp.hasMatch(executable)) {
+      // "pub run foo" means the same thing as "pub run foo:foo" as long as
+      // "foo" is a valid Dart identifier (and thus package name).
+
+      // TODO(nweiz): Remove this after Dart 1.10 ships.
+      var localPath = p.join("bin", "$executable.dart");
+      if (fileExists(localPath) && executable != entrypoint.root.name) {
+        log.warning(
+            'In future releases, "pub run $executable" will mean the same '
+                'thing as "pub run $executable:$executable".\n'
+            'Run "pub run ${p.join("bin", executable)}" explicitly to run the '
+                'local executable.');
+      } else {
+        package = executable;
+      }
     }
 
     var mode;
diff --git a/sdk/lib/_internal/pub/lib/src/executable.dart b/sdk/lib/_internal/pub/lib/src/executable.dart
index 1c22b80..1b36468 100644
--- a/sdk/lib/_internal/pub/lib/src/executable.dart
+++ b/sdk/lib/_internal/pub/lib/src/executable.dart
@@ -18,6 +18,23 @@
 import 'log.dart' as log;
 import 'utils.dart';
 
+/// All signals that can be caught by a Dart process.
+///
+/// This intentionally omits SIGINT. SIGINT usually comes from a user pressing
+/// Control+C on the terminal, and the terminal automatically passes the signal
+/// to all processes in the process tree. If we forwarded it manually, the
+/// subprocess would see two instances, which could cause problems. Instead, we
+/// just ignore it and let the terminal pass it to the subprocess.
+final _catchableSignals = Platform.isWindows
+    ? [ProcessSignal.SIGHUP]
+    : [
+        ProcessSignal.SIGHUP,
+        ProcessSignal.SIGTERM,
+        ProcessSignal.SIGUSR1,
+        ProcessSignal.SIGUSR2,
+        ProcessSignal.SIGWINCH,
+      ];
+
 /// Runs [executable] from [package] reachable from [entrypoint].
 ///
 /// The executable string is a relative Dart file path using native path
@@ -132,6 +149,9 @@
   vmArgs.addAll(args);
 
   var process = await Process.start(Platform.executable, vmArgs);
+
+  _forwardSignals(process);
+
   // Note: we're not using process.std___.pipe(std___) here because
   // that prevents pub from also writing to the output streams.
   process.stderr.listen(stderr.add);
@@ -176,6 +196,8 @@
   runProcess(input) async {
     var process = await Process.start(Platform.executable, vmArgs);
 
+    _forwardSignals(process);
+
     // Note: we're not using process.std___.pipe(std___) here because
     // that prevents pub from also writing to the output streams.
     process.stderr.listen(stderr.add);
@@ -194,6 +216,20 @@
   return runProcess(stdin2);
 }
 
+/// Forwards all catchable signals to [process].
+void _forwardSignals(Process process) {
+  // See [_catchableSignals].
+  ProcessSignal.SIGINT.watch().listen(
+      (_) => log.fine("Ignoring SIGINT in pub."));
+
+  for (var signal in _catchableSignals) {
+    signal.watch().listen((_) {
+      log.fine("Forwarding $signal to running process.");
+      process.kill(signal);
+    });
+  }
+}
+
 /// Runs the executable snapshot at [snapshotPath].
 Future<int> _runCachedExecutable(Entrypoint entrypoint, String snapshotPath,
     List<String> args) {
diff --git a/sdk/lib/_internal/pub/lib/src/http.dart b/sdk/lib/_internal/pub/lib/src/http.dart
index 4fe118e..3d0453a 100644
--- a/sdk/lib/_internal/pub/lib/src/http.dart
+++ b/sdk/lib/_internal/pub/lib/src/http.dart
@@ -11,6 +11,7 @@
 
 import 'package:http/http.dart' as http;
 import 'package:http_throttle/http_throttle.dart';
+import 'package:stack_trace/stack_trace.dart';
 
 import 'io.dart';
 import 'log.dart' as log;
@@ -107,6 +108,9 @@
         throw new PubHttpException(response);
       });
     }).catchError((error, stackTrace) {
+      // Work around issue 23008.
+      if (stackTrace == null) stackTrace = new Chain.current();
+
       if (error is SocketException &&
           error.osError != null) {
         if (error.osError.errorCode == 8 ||
diff --git a/sdk/lib/_internal/pub/lib/src/preprocess.dart b/sdk/lib/_internal/pub/lib/src/preprocess.dart
index a77b9bd..738829f 100644
--- a/sdk/lib/_internal/pub/lib/src/preprocess.dart
+++ b/sdk/lib/_internal/pub/lib/src/preprocess.dart
@@ -7,6 +7,8 @@
 import 'package:pub_semver/pub_semver.dart';
 import 'package:string_scanner/string_scanner.dart';
 
+import 'utils.dart';
+
 /// Runs a simple preprocessor over [input] to remove sections that are
 /// incompatible with the available barback version.
 ///
@@ -102,7 +104,7 @@
   /// Handle an `if` operator.
   void _if() {
     _scanner.expect(new RegExp(r"if[ \t]+"), name: "if statement");
-    _scanner.expect(new RegExp(r"[a-zA-Z0-9_]+"), name: "package name");
+    _scanner.expect(identifierRegExp, name: "package name");
     var package = _scanner.lastMatch[0];
 
     _scanner.scan(new RegExp(r"[ \t]*"));
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index 09575d7..14d81a6 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -23,6 +23,15 @@
 
 export '../../asset/dart/utils.dart';
 
+/// A regular expression matching a Dart identifier.
+///
+/// This also matches a package name, since they must be Dart identifiers.
+final identifierRegExp = new RegExp(r"[a-zA-Z_][a-zA-Z0-9_]+");
+
+/// Like [identifierRegExp], but anchored so that it only matches strings that
+/// are *just* Dart identifiers.
+final onlyIdentifierRegExp = new RegExp("^${identifierRegExp.pattern}\$");
+
 /// A pair of values.
 class Pair<E, F> {
   E first;
diff --git a/sdk/lib/_internal/pub/lib/src/validator/size.dart b/sdk/lib/_internal/pub/lib/src/validator/size.dart
index 0b8d05f..b3da388 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/size.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/size.dart
@@ -10,8 +10,8 @@
 import '../entrypoint.dart';
 import '../validator.dart';
 
-/// The maximum size of the package to upload (10 MB).
-const _MAX_SIZE = 10 * 1024 * 1024;
+/// The maximum size of the package to upload (100 MB).
+const _MAX_SIZE = 100 * 1024 * 1024;
 
 /// A validator that validates that a package isn't too big.
 class SizeValidator extends Validator {
@@ -25,7 +25,7 @@
       if (size <= _MAX_SIZE) return;
       var sizeInMb = (size / math.pow(2, 20)).toStringAsPrecision(4);
       errors.add("Your package is $sizeInMb MB. Hosted packages must be "
-          "smaller than 10 MB.");
+          "smaller than 100 MB.");
     });
   }
 }
diff --git a/sdk/lib/_internal/pub/pub.status b/sdk/lib/_internal/pub/pub.status
index a9f84bd..5571320 100644
--- a/sdk/lib/_internal/pub/pub.status
+++ b/sdk/lib/_internal/pub/pub.status
@@ -16,4 +16,4 @@
 
 [ $runtime == vm && $system == windows ]
 test/run/app_can_read_from_stdin_test: Fail # Issue 19448
-test/lish/many_files_test: Fail # Issue 22996
+test/run/forwards_signal_posix_test: SkipByDesign
diff --git a/sdk/lib/_internal/pub/test/dependency_computer/dev_transformers_test.dart b/sdk/lib/_internal/pub/test/dependency_computer/dev_transformers_test.dart
index db1671c..6daa90b 100644
--- a/sdk/lib/_internal/pub/test/dependency_computer/dev_transformers_test.dart
+++ b/sdk/lib/_internal/pub/test/dependency_computer/dev_transformers_test.dart
@@ -47,6 +47,28 @@
     expectDependencies({"myapp": []});
   });
 
+  integration("does return a dependency's transformer that the root package "
+      "uses", () {
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dependencies": {"foo": {"path": "../foo"}},
+        "transformers": [{"foo": {"\$include": "test/myapp_test.dart"}}]
+      }),
+      d.dir("test", [d.file("myapp_test.dart", "")])
+    ]).create();
+
+    d.dir("foo", [
+      d.pubspec({
+        "name": "foo",
+        "version": "1.0.0"
+      }),
+      d.dir("lib", [d.file("foo.dart", transformer())])
+    ]).create();
+
+    expectDependencies({"foo": []});
+  });
+
   integration("doesn't return a dependency's transformer that can run on bin",
       () {
     d.dir(appPath, [
diff --git a/sdk/lib/_internal/pub/test/get/cache_transformed_dependency_test.dart b/sdk/lib/_internal/pub/test/get/cache_transformed_dependency_test.dart
index f197805..5d0d354 100644
--- a/sdk/lib/_internal/pub/test/get/cache_transformed_dependency_test.dart
+++ b/sdk/lib/_internal/pub/test/get/cache_transformed_dependency_test.dart
@@ -294,7 +294,7 @@
       ])
     ]).create();
 
-    var pub = pubRun(args: ["script"]);
+    var pub = pubRun(args: ["bin/script"]);
     pub.stdout.expect("Modified!");
     pub.shouldExit();
   });
@@ -334,7 +334,7 @@
       ])
     ]).create();
 
-    var pub = pubRun(args: ["script"]);
+    var pub = pubRun(args: ["bin/script"]);
     pub.stdout.expect("Hello!");
     pub.shouldExit();
   });
diff --git a/sdk/lib/_internal/pub/test/lish/many_files_test.dart b/sdk/lib/_internal/pub/test/lish/many_files_test.dart
index 1adec26..776779a 100644
--- a/sdk/lib/_internal/pub/test/lish/many_files_test.dart
+++ b/sdk/lib/_internal/pub/test/lish/many_files_test.dart
@@ -19,10 +19,14 @@
 /// The maximum number of bytes in an entire path.
 ///
 /// This is [Windows's number][MAX_PATH], which is a much tighter constraint
-/// than OS X or Linux. We use it everywhere for consistency.
+/// than OS X or Linux. We subtract one because Windows counts it as the number
+/// of bytes in a path C string including the terminating NUL but we only count
+/// characters here.
+///
+/// We use this limit on all platforms for consistency.
 ///
 /// [MAX_PATH]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383130(v=vs.85).aspx
-const _pathMax = 260;
+const _pathMax = 260 - 1;
 
 main() {
   initConfig();
diff --git a/sdk/lib/_internal/pub/test/run/app_can_read_from_stdin_test.dart b/sdk/lib/_internal/pub/test/run/app_can_read_from_stdin_test.dart
index 3a31604..933de2c 100644
--- a/sdk/lib/_internal/pub/test/run/app_can_read_from_stdin_test.dart
+++ b/sdk/lib/_internal/pub/test/run/app_can_read_from_stdin_test.dart
@@ -28,7 +28,7 @@
       ])
     ]).create();
 
-    var pub = pubRun(args: ["script"]);
+    var pub = pubRun(args: ["bin/script"]);
 
     pub.stdout.expect("started");
     pub.writeLine("first");
diff --git a/sdk/lib/_internal/pub/test/run/displays_transformer_logs_test.dart b/sdk/lib/_internal/pub/test/run/displays_transformer_logs_test.dart
index 1614175..1dff2d2 100644
--- a/sdk/lib/_internal/pub/test/run/displays_transformer_logs_test.dart
+++ b/sdk/lib/_internal/pub/test/run/displays_transformer_logs_test.dart
@@ -66,7 +66,7 @@
 
       createLockFile('myapp', pkg: ['barback']);
 
-      var pub = pubRun(args: ["script"]);
+      var pub = pubRun(args: ["bin/script"]);
 
       // Note that the info log is only displayed here because the test
       // harness runs pub in verbose mode. By default, only the warning would
diff --git a/sdk/lib/_internal/pub/test/run/does_not_run_on_transformer_error_test.dart b/sdk/lib/_internal/pub/test/run/does_not_run_on_transformer_error_test.dart
index 3ae0a1e..51985a3 100644
--- a/sdk/lib/_internal/pub/test/run/does_not_run_on_transformer_error_test.dart
+++ b/sdk/lib/_internal/pub/test/run/does_not_run_on_transformer_error_test.dart
@@ -50,7 +50,7 @@
 
       createLockFile('myapp', pkg: ['barback']);
 
-      var pub = pubRun(args: ["script"]);
+      var pub = pubRun(args: ["bin/script"]);
 
       pub.stderr.expect("[Error from Failing]:");
       pub.stderr.expect("myapp|bin/script.dart.");
diff --git a/sdk/lib/_internal/pub/test/run/doesnt_load_an_unnecessary_transformer_test.dart b/sdk/lib/_internal/pub/test/run/doesnt_load_an_unnecessary_transformer_test.dart
index 098b166..1be2487 100644
--- a/sdk/lib/_internal/pub/test/run/doesnt_load_an_unnecessary_transformer_test.dart
+++ b/sdk/lib/_internal/pub/test/run/doesnt_load_an_unnecessary_transformer_test.dart
@@ -47,7 +47,7 @@
       // This shouldn't load the transformer, since it doesn't transform
       // anything that the entrypoint imports. If it did load the transformer,
       // we'd know since it would throw an exception.
-      var pub = pubRun(args: ["hi"]);
+      var pub = pubRun(args: ["bin/hi"]);
       pub.stdout.expect("Hello!");
       pub.shouldExit();
     });
diff --git a/sdk/lib/_internal/pub/test/run/forwards_signal_posix_test.dart b/sdk/lib/_internal/pub/test/run/forwards_signal_posix_test.dart
new file mode 100644
index 0000000..6b9e222
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/run/forwards_signal_posix_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 '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+const _catchableSignals = const [
+  ProcessSignal.SIGHUP,
+  ProcessSignal.SIGTERM,
+  ProcessSignal.SIGUSR1,
+  ProcessSignal.SIGUSR2,
+  ProcessSignal.SIGWINCH,
+];
+
+const SCRIPT = """
+import 'dart:io';
+
+main() {
+  ProcessSignal.SIGHUP.watch().first.then(print);
+  ProcessSignal.SIGTERM.watch().first.then(print);
+  ProcessSignal.SIGUSR1.watch().first.then(print);
+  ProcessSignal.SIGUSR2.watch().first.then(print);
+  ProcessSignal.SIGWINCH.watch().first.then(print);
+
+  print("ready");
+}
+""";
+
+main() {
+  initConfig();
+  integration('forwards signals to the inner script', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("bin", [
+        d.file("script.dart", SCRIPT)
+      ])
+    ]).create();
+
+    var pub = pubRun(args: ["bin/script"]);
+
+    pub.stdout.expect("ready");
+    for (var signal in _catchableSignals) {
+      pub.signal(signal);
+      pub.stdout.expect(signal.toString());
+    }
+
+    pub.kill();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/run/ignores_explicit_dart2js_transformer_test.dart b/sdk/lib/_internal/pub/test/run/ignores_explicit_dart2js_transformer_test.dart
index ffeb779..a5bcdb3 100644
--- a/sdk/lib/_internal/pub/test/run/ignores_explicit_dart2js_transformer_test.dart
+++ b/sdk/lib/_internal/pub/test/run/ignores_explicit_dart2js_transformer_test.dart
@@ -18,7 +18,7 @@
       ])
     ]).create();
 
-    var pub = pubRun(args: ["script"]);
+    var pub = pubRun(args: ["bin/script"]);
     pub.stdout.expect("Hello!");
     pub.shouldExit(0);
   });
diff --git a/sdk/lib/_internal/pub/test/run/mode_test.dart b/sdk/lib/_internal/pub/test/run/mode_test.dart
index f6c60ff..ff8fd4b 100644
--- a/sdk/lib/_internal/pub/test/run/mode_test.dart
+++ b/sdk/lib/_internal/pub/test/run/mode_test.dart
@@ -43,12 +43,12 @@
       createLockFile('myapp', pkg: ['barback']);
 
       // By default it should run in debug mode.
-      var pub = pubRun(args: ["script"]);
+      var pub = pubRun(args: ["bin/script"]);
       pub.stdout.expect("debug");
       pub.shouldExit();
 
       // A custom mode should be specifiable.
-      pub = pubRun(args: ["--mode", "custom-mode", "script"]);
+      pub = pubRun(args: ["--mode", "custom-mode", "bin/script"]);
       pub.stdout.expect("custom-mode");
       pub.shouldExit();
     });
diff --git a/sdk/lib/_internal/pub/test/run/nonexistent_script_test.dart b/sdk/lib/_internal/pub/test/run/nonexistent_script_test.dart
index ce385fc..7704fdf 100644
--- a/sdk/lib/_internal/pub/test/run/nonexistent_script_test.dart
+++ b/sdk/lib/_internal/pub/test/run/nonexistent_script_test.dart
@@ -15,7 +15,7 @@
       d.appPubspec()
     ]).create();
 
-    var pub = pubRun(args: ["script"]);
+    var pub = pubRun(args: [p.join("bin", "script")]);
     pub.stderr.expect("Could not find ${p.join("bin", "script.dart")}.");
     pub.shouldExit(exit_codes.NO_INPUT);
   });
diff --git a/sdk/lib/_internal/pub/test/run/passes_along_arguments_test.dart b/sdk/lib/_internal/pub/test/run/passes_along_arguments_test.dart
index 711d64b..4f16a0c 100644
--- a/sdk/lib/_internal/pub/test/run/passes_along_arguments_test.dart
+++ b/sdk/lib/_internal/pub/test/run/passes_along_arguments_test.dart
@@ -23,7 +23,7 @@
 
     // Use some args that would trip up pub's arg parser to ensure that it
     // isn't trying to look at them.
-    var pub = pubRun(args: ["args", "--verbose", "-m", "--", "help"]);
+    var pub = pubRun(args: ["bin/args", "--verbose", "-m", "--", "help"]);
 
     pub.stdout.expect("--verbose -m -- help");
     pub.shouldExit();
diff --git a/sdk/lib/_internal/pub/test/run/runs_a_generated_script_test.dart b/sdk/lib/_internal/pub/test/run/runs_a_generated_script_test.dart
index cd29aa7..ab136b9 100644
--- a/sdk/lib/_internal/pub/test/run/runs_a_generated_script_test.dart
+++ b/sdk/lib/_internal/pub/test/run/runs_a_generated_script_test.dart
@@ -40,7 +40,7 @@
 
       createLockFile('myapp', pkg: ['barback']);
 
-      var pub = pubRun(args: ["script"]);
+      var pub = pubRun(args: ["bin/script"]);
 
       pub.stdout.expect("generated");
       pub.shouldExit();
diff --git a/sdk/lib/_internal/pub/test/run/runs_app_in_entrypoint_test.dart b/sdk/lib/_internal/pub/test/run/runs_app_in_entrypoint_test.dart
index e3cb233..2aaaa29 100644
--- a/sdk/lib/_internal/pub/test/run/runs_app_in_entrypoint_test.dart
+++ b/sdk/lib/_internal/pub/test/run/runs_app_in_entrypoint_test.dart
@@ -25,7 +25,7 @@
       ])
     ]).create();
 
-    var pub = pubRun(args: ["script"]);
+    var pub = pubRun(args: ["bin/script"]);
     pub.stdout.expect("stdout output");
     pub.stderr.expect("stderr output");
     pub.shouldExit(123);
diff --git a/sdk/lib/_internal/pub/test/run/runs_app_in_entrypoint_with_warning_test.dart b/sdk/lib/_internal/pub/test/run/runs_app_in_entrypoint_with_warning_test.dart
new file mode 100644
index 0000000..922525b
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/run/runs_app_in_entrypoint_with_warning_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:path/path.dart' as p;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+const SCRIPT = """
+import 'dart:io';
+
+main() {
+  stdout.writeln("stdout output");
+  stderr.writeln("stderr output");
+  exitCode = 123;
+}
+""";
+
+main() {
+  initConfig();
+  integration('runs a Dart application in the entrypoint package', () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("bin", [
+        d.file("script.dart", SCRIPT)
+      ])
+    ]).create();
+
+    var pub = pubRun(args: ["script"]);
+    pub.stdout.expect("stdout output");
+    pub.stderr.expect(
+        'In future releases, "pub run script" will mean the same thing as "pub '
+            'run script:script".');
+    pub.stderr.expect(
+        'Run "pub run ${p.join('bin', 'script')}" explicitly to run the local '
+            'executable.');
+    pub.stderr.expect("stderr output");
+    pub.shouldExit(123);
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/run/runs_shorthand_app_in_dependency_test.dart b/sdk/lib/_internal/pub/test/run/runs_shorthand_app_in_dependency_test.dart
new file mode 100644
index 0000000..6c9f64b
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/run/runs_shorthand_app_in_dependency_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('runs a shorthand Dart application in a dependency', () {
+    d.dir("foo", [
+      d.libPubspec("foo", "1.0.0"),
+      d.dir("bin", [
+        d.file("foo.dart", "main() => print('foo');")
+      ])
+    ]).create();
+
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "foo": {"path": "../foo"}
+        }
+      })
+    ]).create();
+
+    pubGet();
+
+    var pub = pubRun(args: ["foo"]);
+    pub.stdout.expect("foo");
+    pub.shouldExit();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/run/runs_transformer_in_entrypoint_test.dart b/sdk/lib/_internal/pub/test/run/runs_transformer_in_entrypoint_test.dart
index 07df36f..f367433 100644
--- a/sdk/lib/_internal/pub/test/run/runs_transformer_in_entrypoint_test.dart
+++ b/sdk/lib/_internal/pub/test/run/runs_transformer_in_entrypoint_test.dart
@@ -32,7 +32,7 @@
 
       createLockFile('myapp', pkg: ['barback']);
 
-      var pub = pubRun(args: ["hi"]);
+      var pub = pubRun(args: ["bin/hi"]);
 
       pub.stdout.expect("(hi, transformed)");
       pub.shouldExit();
diff --git a/sdk/lib/_internal/pub/test/serve/404_page_test.dart b/sdk/lib/_internal/pub/test/serve/404_page_test.dart
index d37c387..7a77c40 100644
--- a/sdk/lib/_internal/pub/test/serve/404_page_test.dart
+++ b/sdk/lib/_internal/pub/test/serve/404_page_test.dart
@@ -39,7 +39,7 @@
       expect(response.statusCode, equals(404));
 
       // Should mention the asset that can't be found.
-      expect(response.body, contains('&quot;&#x2F;packages&quot;'));
+      expect(response.body, contains('&quot;/packages&quot;'));
     });
 
     endPubServe();
diff --git a/sdk/lib/_internal/pub/test/validator/size_test.dart b/sdk/lib/_internal/pub/test/validator/size_test.dart
index 9949280..37b9eab 100644
--- a/sdk/lib/_internal/pub/test/validator/size_test.dart
+++ b/sdk/lib/_internal/pub/test/validator/size_test.dart
@@ -22,12 +22,12 @@
 
   setUp(d.validPackage.create);
 
-  integration('should consider a package valid if it is <= 10 MB', () {
+  integration('considers a package valid if it is <= 100 MB', () {
     expectNoValidationError(size(100));
-    expectNoValidationError(size(10 * math.pow(2, 20)));
+    expectNoValidationError(size(100 * math.pow(2, 20)));
   });
 
-  integration('should consider a package invalid if it is more than 10 MB', () {
-    expectValidationError(size(10 * math.pow(2, 20) + 1));
+  integration('considers a package invalid if it is more than 100 MB', () {
+    expectValidationError(size(100 * math.pow(2, 20) + 1));
   });
 }
diff --git a/sdk/lib/convert/html_escape.dart b/sdk/lib/convert/html_escape.dart
index 512d9c3..f4be4c6 100644
--- a/sdk/lib/convert/html_escape.dart
+++ b/sdk/lib/convert/html_escape.dart
@@ -7,39 +7,125 @@
 // TODO(floitsch) - Document - Issue 13097
 const HtmlEscape HTML_ESCAPE = const HtmlEscape();
 
+/**
+ * HTML escape modes.
+ *
+ * Allows specifying a mode for HTML escaping that depend on the context
+ * where the escaped result is going to be used.
+ * The relevant contexts are:
+ *
+ * * as text content of an HTML element.
+ * * as value of a (single- or double-) quoted attribute value.
+ *
+ * All modes require escaping of `&` (ampersand) characters, and may
+ * enable escaping of more characters.
+ */
 class HtmlEscapeMode {
   final String _name;
+  /** Whether to escape '<' and '>'. */
   final bool escapeLtGt;
+  /** Whether to escape '"' (quote). */
   final bool escapeQuot;
+  /** Whether to escape "'" (apostrophe). */
   final bool escapeApos;
-  final bool escapeSlash;
 
-  // TODO(floitsch) - Document - Issue 13097
+  /**
+   * Default escaping mode which escape all characters.
+   *
+   * The result of such an escaping is usable both in element content and
+   * in any attribute value.
+   *
+   * The escaping only works for elements with normal HTML content,
+   * and not for, for example, script or style element content,
+   * which require escapes matching their particular content syntax.
+   */
   static const HtmlEscapeMode UNKNOWN =
-    const HtmlEscapeMode._('unknown', true, true, true, true);
+      const HtmlEscapeMode._('unknown', true, true, true);
 
-  // TODO(floitsch) - Document - Issue 13097
+  /**
+   * Escaping mode for text going into double-quoted HTML attribute values.
+   *
+   * The result should not be used as the content of an unquoted
+   * or single-quoted attribute value.
+   *
+   * Escapes only double quotes (`"`) but not single quotes (`'`).
+   */
   static const HtmlEscapeMode ATTRIBUTE =
-    const HtmlEscapeMode._('attribute', false, true, false, false);
+      const HtmlEscapeMode._('attribute', false, true, false);
 
-  // TODO(floitsch) - Document - Issue 13097
+  /**
+   * Escaping mode for text going into single-quoted HTML attribute values.
+   *
+   * The result should not be used as the content of an unquoted
+   * or double-quoted attribute value.
+   *
+   * Escapes only single quotes (`'`) but not double quotes (`"`).
+   */
+  static const HtmlEscapeMode SQ_ATTRIBUTE =
+      const HtmlEscapeMode._('attribute', false, false, true);
+
+  /**
+   * Escaping mode for text going into HTML element content.
+   *
+   * The escaping only works for elements with normal HTML content,
+   * and not for, for example, script or style element content,
+   * which require escapes matching their particular content syntax.
+   *
+   * Escapes `<` and `>` characters.
+   */
   static const HtmlEscapeMode ELEMENT =
-    const HtmlEscapeMode._('element', true, false, false, true);
+      const HtmlEscapeMode._('element', true, false, false);
 
-  // TODO(floitsch) - Document - Issue 13097
-  const HtmlEscapeMode._(this._name, this.escapeLtGt, this.escapeQuot,
-    this.escapeApos, this.escapeSlash);
+  const HtmlEscapeMode._(
+      this._name, this.escapeLtGt, this.escapeQuot, this.escapeApos);
+
+  /**
+   * Create a custom escaping mode.
+   *
+   * All modes escape `&`.
+   * The mode can further be set to escape `<` and `>` ([escapeLtGt]),
+   * `"` ([escapeQuot]) and/or `'` ([escapeApos]).
+   */
+  const HtmlEscapeMode({String name: "custom",
+                        this.escapeLtGt: false,
+                        this.escapeQuot: false,
+                        this.escapeApos: false}) : _name = name;
 
   String toString() => _name;
 }
 
-  // TODO(floitsch) - Document - Issue 13097
+/**
+ * Converter which escapes characters with special meaning in HTML.
+ *
+ * The converter finds characters that are siginificant in HTML source and
+ * replaces them with corresponding HTML entities.
+ *
+ * The characters that need escaping in HTML are:
+ *
+ * * `&` (ampersand) always need to be escaped.
+ * * `<` (less than) and '>' (greater than) when inside an element.
+ * * `"` (quote) when inside a double-quoted attribute value.
+ * * `'` (apostrophe) when inside a single-quoted attribute value.
+ *       Apostrophe is escaped as `&#39;` instead of `&apos;` since
+ *       not all browsers understand `&apos;`.
+ *
+ * Escaping `>` (greater than) isn't necessary, but the result is often
+ * found to be easier to read if greater-than is also escaped whenever
+ * less-than is.
+ */
 class HtmlEscape extends Converter<String, String> {
 
-  // TODO(floitsch) - Document - Issue 13097
+  /** The [HtmlEscapeMode] used by the converter. */
   final HtmlEscapeMode mode;
 
-  // TODO(floitsch) - Document - Issue 13097
+  /**
+   * Create converter that escapes HTML characters.
+   *
+   * If [mode] is provided as either [HtmlEscapeMode.ATTRIBUTE] or
+   * [HtmlEscapeMode.ELEMENT], only the corresponding subset of HTML
+   * characters are escaped.
+   * The default is to escape all HTML characters.
+   */
   const HtmlEscape([this.mode = HtmlEscapeMode.UNKNOWN]);
 
   String convert(String text) {
@@ -47,29 +133,34 @@
     return val == null ? text : val;
   }
 
+  /**
+   * Converts the substring of text from start to end.
+   *
+   * Returns `null` if no changes were necessary, otherwise returns
+   * the converted string.
+   */
   String _convert(String text, int start, int end) {
     StringBuffer result = null;
     for (int i = start; i < end; i++) {
       var ch = text[i];
-      String replace = null;
+      String replacement = null;
       switch (ch) {
-        case '&': replace = '&amp;'; break;
-        case '\u00A0'/*NO-BREAK SPACE*/: replace = '&nbsp;'; break;
-        case '"': if (mode.escapeQuot) replace = '&quot;'; break;
-        case "'": if (mode.escapeApos) replace = '&#x27;'; break;
-        case '<': if (mode.escapeLtGt) replace = '&lt;'; break;
-        case '>': if (mode.escapeLtGt) replace = '&gt;'; break;
-        case '/': if (mode.escapeSlash) replace = '&#x2F;'; break;
+        case '&': replacement = '&amp;'; break;
+        case '"': if (mode.escapeQuot) replacement = '&quot;'; break;
+        case "'": if (mode.escapeApos) replacement = '&#39;'; break;
+        case '<': if (mode.escapeLtGt) replacement = '&lt;'; break;
+        case '>': if (mode.escapeLtGt) replacement = '&gt;'; break;
       }
-      if (replace != null) {
-        if (result == null) result = new StringBuffer(text.substring(start, i));
-        result.write(replace);
-      } else if (result != null) {
-        result.write(ch);
+      if (replacement != null) {
+        if (result == null) result = new StringBuffer();
+        if (i > start) result.write(text.substring(start, i));
+        result.write(replacement);
+        start = i + 1;
       }
     }
-
-    return result != null ? result.toString() : null;
+    if (result == null) return null;
+    if (end > start) result.write(text.substring(start, end));
+    return result.toString();
   }
 
   StringConversionSink startChunkedConversion(Sink<String> sink) {
diff --git a/sdk/lib/core/exceptions.dart b/sdk/lib/core/exceptions.dart
index 3ca1fb3..38af7af 100644
--- a/sdk/lib/core/exceptions.dart
+++ b/sdk/lib/core/exceptions.dart
@@ -46,7 +46,7 @@
   final String message;
 
   /**
-   * The actual source input that caused the error.
+   * The actual source input which caused the error.
    *
    * This is usually a [String], but can be other types too.
    * If it is a string, parts of it may be included in the [toString] message.
@@ -73,8 +73,8 @@
   /**
    * Creates a new FormatException with an optional error [message].
    *
-   * Optionally also supply the actual [source] that had the incorrect format,
-   * and an [offset] in the format where a problem was detected.
+   * Optionally also supply the actual [source] with the incorrect format,
+   * and the [offset] in the format where a problem was detected.
    */
   const FormatException([this.message = "", this.source, this.offset]);
 
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index 06bb3ca..14e2d80 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -146,11 +146,14 @@
   /**
    * Creates a new `Uri` object by parsing a URI string.
    *
+   * If [start] and [end] are provided, only the substring from `start`
+   * to `end` is parsed as a URI.
+   *
    * If the string is not valid as a URI or URI reference,
    * invalid characters will be percent escaped where possible.
    * The resulting `Uri` will represent a valid URI or URI reference.
    */
-  static Uri parse(String uri) {
+  static Uri parse(String uri, [int start = 0, int end]) {
     // This parsing will not validate percent-encoding, IPv6, etc. When done
     // it will call `new Uri(...)` which will perform these validations.
     // This is purely splitting up the URI string into components.
@@ -216,14 +219,15 @@
     String path = null;
     String query = null;
     String fragment = null;
+    if (end == null) end = uri.length;
 
-    int index = 0;
-    int pathStart = 0;
+    int index = start;
+    int pathStart = start;
     // End of input-marker.
     int char = EOI;
 
     void parseAuth() {
-      if (index == uri.length) {
+      if (index == end) {
         char = EOI;
         return;
       }
@@ -231,7 +235,7 @@
       int lastColon = -1;
       int lastAt = -1;
       char = uri.codeUnitAt(index);
-      while (index < uri.length) {
+      while (index < end) {
         char = uri.codeUnitAt(index);
         if (char == _SLASH || char == _QUESTION || char == _NUMBER_SIGN) {
           break;
@@ -245,7 +249,7 @@
           lastColon = -1;
           int endBracket = uri.indexOf(']', index + 1);
           if (endBracket == -1) {
-            index = uri.length;
+            index = end;
             char = EOI;
             break;
           } else {
@@ -277,7 +281,7 @@
         hostEnd = lastColon;
       }
       host = _makeHost(uri, hostStart, hostEnd, true);
-      if (index < uri.length) {
+      if (index < end) {
         char = uri.codeUnitAt(index);
       }
     }
@@ -298,22 +302,22 @@
     // All other breaks set their own state.
     int state = NOT_IN_PATH;
     int i = index;  // Temporary alias for index to avoid bug 19550 in dart2js.
-    while (i < uri.length) {
+    while (i < end) {
       char = uri.codeUnitAt(i);
       if (char == _QUESTION || char == _NUMBER_SIGN) {
         state = NOT_IN_PATH;
         break;
       }
       if (char == _SLASH) {
-        state = (i == 0) ? ALLOW_AUTH : IN_PATH;
+        state = (i == start) ? ALLOW_AUTH : IN_PATH;
         break;
       }
       if (char == _COLON) {
-        if (i == 0) _fail(uri, 0, "Invalid empty scheme");
-        scheme = _makeScheme(uri, i);
+        if (i == start) _fail(uri, start, "Invalid empty scheme");
+        scheme = _makeScheme(uri, start, i);
         i++;
         pathStart = i;
-        if (i == uri.length) {
+        if (i == end) {
           char = EOI;
           state = NOT_IN_PATH;
         } else {
@@ -338,7 +342,7 @@
       // Have seen one slash either at start or right after scheme.
       // If two slashes, it's an authority, otherwise it's just the path.
       index++;
-      if (index == uri.length) {
+      if (index == end) {
         char = EOI;
         state = NOT_IN_PATH;
       } else {
@@ -360,7 +364,7 @@
     if (state == IN_PATH) {
       // Characters from pathStart to index (inclusive) are known
       // to be part of the path.
-      while (++index < uri.length) {
+      while (++index < end) {
         char = uri.codeUnitAt(index);
         if (char == _QUESTION || char == _NUMBER_SIGN) {
           break;
@@ -376,15 +380,21 @@
     path = _makePath(uri, pathStart, index, null, ensureLeadingSlash, isFile);
 
     if (char == _QUESTION) {
-      int numberSignIndex = uri.indexOf('#', index + 1);
+      int numberSignIndex = -1;
+      for (int i = index + 1; i < end; i++) {
+        if (uri.codeUnitAt(i) == _NUMBER_SIGN) {
+          numberSignIndex = i;
+          break;
+        }
+      }
       if (numberSignIndex < 0) {
-        query = _makeQuery(uri, index + 1, uri.length, null);
+        query = _makeQuery(uri, index + 1, end, null);
       } else {
         query = _makeQuery(uri, index + 1, numberSignIndex, null);
-        fragment = _makeFragment(uri, numberSignIndex + 1, uri.length);
+        fragment = _makeFragment(uri, numberSignIndex + 1, end);
       }
     } else if (char == _NUMBER_SIGN) {
-      fragment = _makeFragment(uri, index + 1, uri.length);
+      fragment = _makeFragment(uri, index + 1, end);
     }
     return new Uri._internal(scheme,
                              userinfo,
@@ -482,7 +492,7 @@
                String query,
                Map<String, String> queryParameters,
                String fragment}) {
-    scheme = _makeScheme(scheme, _stringOrNullLength(scheme));
+    scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme));
     userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
     host = _makeHost(host, 0, _stringOrNullLength(host), false);
     // Special case this constructor for backwards compatibility.
@@ -872,7 +882,7 @@
     // to check even the existing port.
     bool schemeChanged = false;
     if (scheme != null) {
-      scheme = _makeScheme(scheme, scheme.length);
+      scheme = _makeScheme(scheme, 0, scheme.length);
       schemeChanged = true;
     } else {
       scheme = this.scheme;
@@ -1100,14 +1110,14 @@
    *
    * Schemes are converted to lower case. They cannot contain escapes.
    */
-  static String _makeScheme(String scheme, int end) {
-    if (end == 0) return "";
-    final int firstCodeUnit = scheme.codeUnitAt(0);
+  static String _makeScheme(String scheme, int start, int end) {
+    if (start == end) return "";
+    final int firstCodeUnit = scheme.codeUnitAt(start);
     if (!_isAlphabeticCharacter(firstCodeUnit)) {
-      _fail(scheme, 0, "Scheme not starting with alphabetic character");
+      _fail(scheme, start, "Scheme not starting with alphabetic character");
     }
     bool allLowercase = firstCodeUnit >= _LOWER_CASE_A;
-    for (int i = 0; i < end; i++) {
+    for (int i = start; i < end; i++) {
       final int codeUnit = scheme.codeUnitAt(i);
       if (!_isSchemeCharacter(codeUnit)) {
         _fail(scheme, i, "Illegal scheme character");
@@ -1116,7 +1126,7 @@
         allLowercase = false;
       }
     }
-    scheme = scheme.substring(0, end);
+    scheme = scheme.substring(start, end);
     if (!allLowercase) scheme = scheme.toLowerCase();
     return scheme;
   }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index c08cc44..e780d2e 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -55,12 +55,14 @@
 // Not actually used, but imported since dart:html can generate these objects.
 import 'dart:_js_helper' show
     convertDartClosureToJS, Creates, JavaScriptIndexingBehavior,
-    JSName, Native, Null, Returns,
+    JSName, Native, Null, Returns, Inline, ForceInline,
     findDispatchTagForInterceptorClass, setNativeSubclassDispatchRecord,
     makeLeafDispatchRecord;
 import 'dart:_interceptors' show
-    Interceptor, JSExtendableArray, findInterceptorConstructorForType,
-    findConstructorForNativeSubclassType, getNativeInterceptor,
+    Interceptor, JSExtendableArray, JSUInt31,
+    findInterceptorConstructorForType,
+    findConstructorForNativeSubclassType,
+    getNativeInterceptor,
     setDispatchProperty;
 
 export 'dart:math' show Rectangle, Point;
@@ -3315,7 +3317,7 @@
 
 @DomName('CSSStyleDeclaration')
 @Native("CSSStyleDeclaration,MSStyleCSSProperties,CSS2Properties")
- class CssStyleDeclaration  extends Interceptor with
+class CssStyleDeclaration  extends Interceptor with
     CssStyleDeclarationBase  {
   factory CssStyleDeclaration() => new CssStyleDeclaration.css('');
 
@@ -3357,12 +3359,27 @@
 
   @DomName('CSSStyleDeclaration.setProperty')
   void setProperty(String propertyName, String value, [String priority]) {
+    return _setPropertyHelper(_browserPropertyName(propertyName),
+      value, priority);
+  }
+
+  String _browserPropertyName(String propertyName) {
+    String name = _readCache(propertyName);
+    if (name is String) return name;
     if (_supportsProperty(_camelCase(propertyName))) {
-      return _setPropertyHelper(propertyName, value, priority);
+      name = propertyName;
     } else {
-      return _setPropertyHelper(Device.cssPrefix + propertyName, value,
-          priority);
+      name = Device.cssPrefix + propertyName;
     }
+    _writeCache(propertyName, name);
+    return name;
+  }
+
+  static final _propertyCache = JS('', '{}');
+  static String _readCache(String key) =>
+    JS('String|Null', '#[#]', _propertyCache, key);
+  static void _writeCache(String key, String value) {
+    JS('void', '#[#] = #', _propertyCache, key, value);
   }
 
   static String _camelCase(String hyphenated) {
@@ -3374,18 +3391,9 @@
   }
 
   void _setPropertyHelper(String propertyName, String value, [String priority]) {
-    // try/catch for IE9 which throws on unsupported values.
-    try {
-      if (value == null) value = '';
-      if (priority == null) {
-        priority = '';
-      }
-      JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
-      // Bug #2772, IE9 requires a poke to actually apply the value.
-      if (JS('bool', '!!#.setAttribute', this)) {
-        JS('void', '#.setAttribute(#, #)', this, propertyName, value);
-      }
-    } catch (e) {}
+    if (value == null) value = '';
+    if (priority == null) priority = '';
+    JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
   }
 
   /**
@@ -3435,6 +3443,997 @@
   @DocsEditable()
   String removeProperty(String propertyName) native;
 
+
+  /** Gets the value of "background" */
+  String get background => this._background;
+
+  /** Sets the value of "background" */
+  void set background(String value) {
+    _background = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('background')
+  String _background;
+    
+  /** Gets the value of "background-attachment" */
+  String get backgroundAttachment => this._backgroundAttachment;
+
+  /** Sets the value of "background-attachment" */
+  void set backgroundAttachment(String value) {
+    _backgroundAttachment = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundAttachment')
+  String _backgroundAttachment;
+    
+  /** Gets the value of "background-color" */
+  String get backgroundColor => this._backgroundColor;
+
+  /** Sets the value of "background-color" */
+  void set backgroundColor(String value) {
+    _backgroundColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundColor')
+  String _backgroundColor;
+    
+  /** Gets the value of "background-image" */
+  String get backgroundImage => this._backgroundImage;
+
+  /** Sets the value of "background-image" */
+  void set backgroundImage(String value) {
+    _backgroundImage = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundImage')
+  String _backgroundImage;
+    
+  /** Gets the value of "background-position" */
+  String get backgroundPosition => this._backgroundPosition;
+
+  /** Sets the value of "background-position" */
+  void set backgroundPosition(String value) {
+    _backgroundPosition = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundPosition')
+  String _backgroundPosition;
+    
+  /** Gets the value of "background-repeat" */
+  String get backgroundRepeat => this._backgroundRepeat;
+
+  /** Sets the value of "background-repeat" */
+  void set backgroundRepeat(String value) {
+    _backgroundRepeat = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundRepeat')
+  String _backgroundRepeat;
+    
+  /** Gets the value of "border" */
+  String get border => this._border;
+
+  /** Sets the value of "border" */
+  void set border(String value) {
+    _border = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('border')
+  String _border;
+    
+  /** Gets the value of "border-bottom" */
+  String get borderBottom => this._borderBottom;
+
+  /** Sets the value of "border-bottom" */
+  void set borderBottom(String value) {
+    _borderBottom = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderBottom')
+  String _borderBottom;
+    
+  /** Gets the value of "border-bottom-color" */
+  String get borderBottomColor => this._borderBottomColor;
+
+  /** Sets the value of "border-bottom-color" */
+  void set borderBottomColor(String value) {
+    _borderBottomColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderBottomColor')
+  String _borderBottomColor;
+    
+  /** Gets the value of "border-bottom-style" */
+  String get borderBottomStyle => this._borderBottomStyle;
+
+  /** Sets the value of "border-bottom-style" */
+  void set borderBottomStyle(String value) {
+    _borderBottomStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderBottomStyle')
+  String _borderBottomStyle;
+    
+  /** Gets the value of "border-bottom-width" */
+  String get borderBottomWidth => this._borderBottomWidth;
+
+  /** Sets the value of "border-bottom-width" */
+  void set borderBottomWidth(String value) {
+    _borderBottomWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderBottomWidth')
+  String _borderBottomWidth;
+    
+  /** Gets the value of "border-collapse" */
+  String get borderCollapse => this._borderCollapse;
+
+  /** Sets the value of "border-collapse" */
+  void set borderCollapse(String value) {
+    _borderCollapse = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderCollapse')
+  String _borderCollapse;
+    
+  /** Gets the value of "border-color" */
+  String get borderColor => this._borderColor;
+
+  /** Sets the value of "border-color" */
+  void set borderColor(String value) {
+    _borderColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderColor')
+  String _borderColor;
+    
+  /** Gets the value of "border-left" */
+  String get borderLeft => this._borderLeft;
+
+  /** Sets the value of "border-left" */
+  void set borderLeft(String value) {
+    _borderLeft = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderLeft')
+  String _borderLeft;
+    
+  /** Gets the value of "border-left-color" */
+  String get borderLeftColor => this._borderLeftColor;
+
+  /** Sets the value of "border-left-color" */
+  void set borderLeftColor(String value) {
+    _borderLeftColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderLeftColor')
+  String _borderLeftColor;
+    
+  /** Gets the value of "border-left-style" */
+  String get borderLeftStyle => this._borderLeftStyle;
+
+  /** Sets the value of "border-left-style" */
+  void set borderLeftStyle(String value) {
+    _borderLeftStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderLeftStyle')
+  String _borderLeftStyle;
+    
+  /** Gets the value of "border-left-width" */
+  String get borderLeftWidth => this._borderLeftWidth;
+
+  /** Sets the value of "border-left-width" */
+  void set borderLeftWidth(String value) {
+    _borderLeftWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderLeftWidth')
+  String _borderLeftWidth;
+    
+  /** Gets the value of "border-right" */
+  String get borderRight => this._borderRight;
+
+  /** Sets the value of "border-right" */
+  void set borderRight(String value) {
+    _borderRight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderRight')
+  String _borderRight;
+    
+  /** Gets the value of "border-right-color" */
+  String get borderRightColor => this._borderRightColor;
+
+  /** Sets the value of "border-right-color" */
+  void set borderRightColor(String value) {
+    _borderRightColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderRightColor')
+  String _borderRightColor;
+    
+  /** Gets the value of "border-right-style" */
+  String get borderRightStyle => this._borderRightStyle;
+
+  /** Sets the value of "border-right-style" */
+  void set borderRightStyle(String value) {
+    _borderRightStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderRightStyle')
+  String _borderRightStyle;
+    
+  /** Gets the value of "border-right-width" */
+  String get borderRightWidth => this._borderRightWidth;
+
+  /** Sets the value of "border-right-width" */
+  void set borderRightWidth(String value) {
+    _borderRightWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderRightWidth')
+  String _borderRightWidth;
+    
+  /** Gets the value of "border-spacing" */
+  String get borderSpacing => this._borderSpacing;
+
+  /** Sets the value of "border-spacing" */
+  void set borderSpacing(String value) {
+    _borderSpacing = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderSpacing')
+  String _borderSpacing;
+    
+  /** Gets the value of "border-style" */
+  String get borderStyle => this._borderStyle;
+
+  /** Sets the value of "border-style" */
+  void set borderStyle(String value) {
+    _borderStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderStyle')
+  String _borderStyle;
+    
+  /** Gets the value of "border-top" */
+  String get borderTop => this._borderTop;
+
+  /** Sets the value of "border-top" */
+  void set borderTop(String value) {
+    _borderTop = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderTop')
+  String _borderTop;
+    
+  /** Gets the value of "border-top-color" */
+  String get borderTopColor => this._borderTopColor;
+
+  /** Sets the value of "border-top-color" */
+  void set borderTopColor(String value) {
+    _borderTopColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderTopColor')
+  String _borderTopColor;
+    
+  /** Gets the value of "border-top-style" */
+  String get borderTopStyle => this._borderTopStyle;
+
+  /** Sets the value of "border-top-style" */
+  void set borderTopStyle(String value) {
+    _borderTopStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderTopStyle')
+  String _borderTopStyle;
+    
+  /** Gets the value of "border-top-width" */
+  String get borderTopWidth => this._borderTopWidth;
+
+  /** Sets the value of "border-top-width" */
+  void set borderTopWidth(String value) {
+    _borderTopWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderTopWidth')
+  String _borderTopWidth;
+    
+  /** Gets the value of "border-width" */
+  String get borderWidth => this._borderWidth;
+
+  /** Sets the value of "border-width" */
+  void set borderWidth(String value) {
+    _borderWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderWidth')
+  String _borderWidth;
+    
+  /** Gets the value of "bottom" */
+  String get bottom => this._bottom;
+
+  /** Sets the value of "bottom" */
+  void set bottom(String value) {
+    _bottom = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('bottom')
+  String _bottom;
+    
+  /** Gets the value of "caption-side" */
+  String get captionSide => this._captionSide;
+
+  /** Sets the value of "caption-side" */
+  void set captionSide(String value) {
+    _captionSide = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('captionSide')
+  String _captionSide;
+    
+  /** Gets the value of "clear" */
+  String get clear => this._clear;
+
+  /** Sets the value of "clear" */
+  void set clear(String value) {
+    _clear = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('clear')
+  String _clear;
+    
+  /** Gets the value of "clip" */
+  String get clip => this._clip;
+
+  /** Sets the value of "clip" */
+  void set clip(String value) {
+    _clip = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('clip')
+  String _clip;
+    
+  /** Gets the value of "color" */
+  String get color => this._color;
+
+  /** Sets the value of "color" */
+  void set color(String value) {
+    _color = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('color')
+  String _color;
+    
+  /** Gets the value of "content" */
+  String get content => this._content;
+
+  /** Sets the value of "content" */
+  void set content(String value) {
+    _content = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('content')
+  String _content;
+    
+  /** Gets the value of "cursor" */
+  String get cursor => this._cursor;
+
+  /** Sets the value of "cursor" */
+  void set cursor(String value) {
+    _cursor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('cursor')
+  String _cursor;
+    
+  /** Gets the value of "direction" */
+  String get direction => this._direction;
+
+  /** Sets the value of "direction" */
+  void set direction(String value) {
+    _direction = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('direction')
+  String _direction;
+    
+  /** Gets the value of "display" */
+  String get display => this._display;
+
+  /** Sets the value of "display" */
+  void set display(String value) {
+    _display = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('display')
+  String _display;
+    
+  /** Gets the value of "empty-cells" */
+  String get emptyCells => this._emptyCells;
+
+  /** Sets the value of "empty-cells" */
+  void set emptyCells(String value) {
+    _emptyCells = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('emptyCells')
+  String _emptyCells;
+    
+  /** Gets the value of "font" */
+  String get font => this._font;
+
+  /** Sets the value of "font" */
+  void set font(String value) {
+    _font = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('font')
+  String _font;
+    
+  /** Gets the value of "font-family" */
+  String get fontFamily => this._fontFamily;
+
+  /** Sets the value of "font-family" */
+  void set fontFamily(String value) {
+    _fontFamily = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontFamily')
+  String _fontFamily;
+    
+  /** Gets the value of "font-size" */
+  String get fontSize => this._fontSize;
+
+  /** Sets the value of "font-size" */
+  void set fontSize(String value) {
+    _fontSize = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontSize')
+  String _fontSize;
+    
+  /** Gets the value of "font-style" */
+  String get fontStyle => this._fontStyle;
+
+  /** Sets the value of "font-style" */
+  void set fontStyle(String value) {
+    _fontStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontStyle')
+  String _fontStyle;
+    
+  /** Gets the value of "font-variant" */
+  String get fontVariant => this._fontVariant;
+
+  /** Sets the value of "font-variant" */
+  void set fontVariant(String value) {
+    _fontVariant = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontVariant')
+  String _fontVariant;
+    
+  /** Gets the value of "font-weight" */
+  String get fontWeight => this._fontWeight;
+
+  /** Sets the value of "font-weight" */
+  void set fontWeight(String value) {
+    _fontWeight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontWeight')
+  String _fontWeight;
+    
+  /** Gets the value of "height" */
+  String get height => this._height;
+
+  /** Sets the value of "height" */
+  void set height(String value) {
+    _height = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('height')
+  String _height;
+    
+  /** Gets the value of "left" */
+  String get left => this._left;
+
+  /** Sets the value of "left" */
+  void set left(String value) {
+    _left = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('left')
+  String _left;
+    
+  /** Gets the value of "letter-spacing" */
+  String get letterSpacing => this._letterSpacing;
+
+  /** Sets the value of "letter-spacing" */
+  void set letterSpacing(String value) {
+    _letterSpacing = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('letterSpacing')
+  String _letterSpacing;
+    
+  /** Gets the value of "line-height" */
+  String get lineHeight => this._lineHeight;
+
+  /** Sets the value of "line-height" */
+  void set lineHeight(String value) {
+    _lineHeight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('lineHeight')
+  String _lineHeight;
+    
+  /** Gets the value of "list-style" */
+  String get listStyle => this._listStyle;
+
+  /** Sets the value of "list-style" */
+  void set listStyle(String value) {
+    _listStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('listStyle')
+  String _listStyle;
+    
+  /** Gets the value of "list-style-image" */
+  String get listStyleImage => this._listStyleImage;
+
+  /** Sets the value of "list-style-image" */
+  void set listStyleImage(String value) {
+    _listStyleImage = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('listStyleImage')
+  String _listStyleImage;
+    
+  /** Gets the value of "list-style-position" */
+  String get listStylePosition => this._listStylePosition;
+
+  /** Sets the value of "list-style-position" */
+  void set listStylePosition(String value) {
+    _listStylePosition = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('listStylePosition')
+  String _listStylePosition;
+    
+  /** Gets the value of "list-style-type" */
+  String get listStyleType => this._listStyleType;
+
+  /** Sets the value of "list-style-type" */
+  void set listStyleType(String value) {
+    _listStyleType = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('listStyleType')
+  String _listStyleType;
+    
+  /** Gets the value of "margin" */
+  String get margin => this._margin;
+
+  /** Sets the value of "margin" */
+  void set margin(String value) {
+    _margin = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('margin')
+  String _margin;
+    
+  /** Gets the value of "margin-bottom" */
+  String get marginBottom => this._marginBottom;
+
+  /** Sets the value of "margin-bottom" */
+  void set marginBottom(String value) {
+    _marginBottom = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('marginBottom')
+  String _marginBottom;
+    
+  /** Gets the value of "margin-left" */
+  String get marginLeft => this._marginLeft;
+
+  /** Sets the value of "margin-left" */
+  void set marginLeft(String value) {
+    _marginLeft = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('marginLeft')
+  String _marginLeft;
+    
+  /** Gets the value of "margin-right" */
+  String get marginRight => this._marginRight;
+
+  /** Sets the value of "margin-right" */
+  void set marginRight(String value) {
+    _marginRight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('marginRight')
+  String _marginRight;
+    
+  /** Gets the value of "margin-top" */
+  String get marginTop => this._marginTop;
+
+  /** Sets the value of "margin-top" */
+  void set marginTop(String value) {
+    _marginTop = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('marginTop')
+  String _marginTop;
+    
+  /** Gets the value of "max-height" */
+  String get maxHeight => this._maxHeight;
+
+  /** Sets the value of "max-height" */
+  void set maxHeight(String value) {
+    _maxHeight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('maxHeight')
+  String _maxHeight;
+    
+  /** Gets the value of "max-width" */
+  String get maxWidth => this._maxWidth;
+
+  /** Sets the value of "max-width" */
+  void set maxWidth(String value) {
+    _maxWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('maxWidth')
+  String _maxWidth;
+    
+  /** Gets the value of "min-height" */
+  String get minHeight => this._minHeight;
+
+  /** Sets the value of "min-height" */
+  void set minHeight(String value) {
+    _minHeight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('minHeight')
+  String _minHeight;
+    
+  /** Gets the value of "min-width" */
+  String get minWidth => this._minWidth;
+
+  /** Sets the value of "min-width" */
+  void set minWidth(String value) {
+    _minWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('minWidth')
+  String _minWidth;
+    
+  /** Gets the value of "outline" */
+  String get outline => this._outline;
+
+  /** Sets the value of "outline" */
+  void set outline(String value) {
+    _outline = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('outline')
+  String _outline;
+    
+  /** Gets the value of "outline-color" */
+  String get outlineColor => this._outlineColor;
+
+  /** Sets the value of "outline-color" */
+  void set outlineColor(String value) {
+    _outlineColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('outlineColor')
+  String _outlineColor;
+    
+  /** Gets the value of "outline-style" */
+  String get outlineStyle => this._outlineStyle;
+
+  /** Sets the value of "outline-style" */
+  void set outlineStyle(String value) {
+    _outlineStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('outlineStyle')
+  String _outlineStyle;
+    
+  /** Gets the value of "outline-width" */
+  String get outlineWidth => this._outlineWidth;
+
+  /** Sets the value of "outline-width" */
+  void set outlineWidth(String value) {
+    _outlineWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('outlineWidth')
+  String _outlineWidth;
+    
+  /** Gets the value of "overflow" */
+  String get overflow => this._overflow;
+
+  /** Sets the value of "overflow" */
+  void set overflow(String value) {
+    _overflow = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('overflow')
+  String _overflow;
+    
+  /** Gets the value of "padding" */
+  String get padding => this._padding;
+
+  /** Sets the value of "padding" */
+  void set padding(String value) {
+    _padding = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('padding')
+  String _padding;
+    
+  /** Gets the value of "padding-bottom" */
+  String get paddingBottom => this._paddingBottom;
+
+  /** Sets the value of "padding-bottom" */
+  void set paddingBottom(String value) {
+    _paddingBottom = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('paddingBottom')
+  String _paddingBottom;
+    
+  /** Gets the value of "padding-left" */
+  String get paddingLeft => this._paddingLeft;
+
+  /** Sets the value of "padding-left" */
+  void set paddingLeft(String value) {
+    _paddingLeft = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('paddingLeft')
+  String _paddingLeft;
+    
+  /** Gets the value of "padding-right" */
+  String get paddingRight => this._paddingRight;
+
+  /** Sets the value of "padding-right" */
+  void set paddingRight(String value) {
+    _paddingRight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('paddingRight')
+  String _paddingRight;
+    
+  /** Gets the value of "padding-top" */
+  String get paddingTop => this._paddingTop;
+
+  /** Sets the value of "padding-top" */
+  void set paddingTop(String value) {
+    _paddingTop = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('paddingTop')
+  String _paddingTop;
+    
+  /** Gets the value of "page-break-after" */
+  String get pageBreakAfter => this._pageBreakAfter;
+
+  /** Sets the value of "page-break-after" */
+  void set pageBreakAfter(String value) {
+    _pageBreakAfter = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('pageBreakAfter')
+  String _pageBreakAfter;
+    
+  /** Gets the value of "page-break-before" */
+  String get pageBreakBefore => this._pageBreakBefore;
+
+  /** Sets the value of "page-break-before" */
+  void set pageBreakBefore(String value) {
+    _pageBreakBefore = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('pageBreakBefore')
+  String _pageBreakBefore;
+    
+  /** Gets the value of "page-break-inside" */
+  String get pageBreakInside => this._pageBreakInside;
+
+  /** Sets the value of "page-break-inside" */
+  void set pageBreakInside(String value) {
+    _pageBreakInside = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('pageBreakInside')
+  String _pageBreakInside;
+    
+  /** Gets the value of "position" */
+  String get position => this._position;
+
+  /** Sets the value of "position" */
+  void set position(String value) {
+    _position = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('position')
+  String _position;
+    
+  /** Gets the value of "quotes" */
+  String get quotes => this._quotes;
+
+  /** Sets the value of "quotes" */
+  void set quotes(String value) {
+    _quotes = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('quotes')
+  String _quotes;
+    
+  /** Gets the value of "right" */
+  String get right => this._right;
+
+  /** Sets the value of "right" */
+  void set right(String value) {
+    _right = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('right')
+  String _right;
+    
+  /** Gets the value of "table-layout" */
+  String get tableLayout => this._tableLayout;
+
+  /** Sets the value of "table-layout" */
+  void set tableLayout(String value) {
+    _tableLayout = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('tableLayout')
+  String _tableLayout;
+    
+  /** Gets the value of "text-align" */
+  String get textAlign => this._textAlign;
+
+  /** Sets the value of "text-align" */
+  void set textAlign(String value) {
+    _textAlign = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('textAlign')
+  String _textAlign;
+    
+  /** Gets the value of "text-decoration" */
+  String get textDecoration => this._textDecoration;
+
+  /** Sets the value of "text-decoration" */
+  void set textDecoration(String value) {
+    _textDecoration = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('textDecoration')
+  String _textDecoration;
+    
+  /** Gets the value of "text-indent" */
+  String get textIndent => this._textIndent;
+
+  /** Sets the value of "text-indent" */
+  void set textIndent(String value) {
+    _textIndent = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('textIndent')
+  String _textIndent;
+    
+  /** Gets the value of "text-transform" */
+  String get textTransform => this._textTransform;
+
+  /** Sets the value of "text-transform" */
+  void set textTransform(String value) {
+    _textTransform = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('textTransform')
+  String _textTransform;
+    
+  /** Gets the value of "top" */
+  String get top => this._top;
+
+  /** Sets the value of "top" */
+  void set top(String value) {
+    _top = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('top')
+  String _top;
+    
+  /** Gets the value of "unicode-bidi" */
+  String get unicodeBidi => this._unicodeBidi;
+
+  /** Sets the value of "unicode-bidi" */
+  void set unicodeBidi(String value) {
+    _unicodeBidi = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('unicodeBidi')
+  String _unicodeBidi;
+    
+  /** Gets the value of "vertical-align" */
+  String get verticalAlign => this._verticalAlign;
+
+  /** Sets the value of "vertical-align" */
+  void set verticalAlign(String value) {
+    _verticalAlign = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('verticalAlign')
+  String _verticalAlign;
+    
+  /** Gets the value of "visibility" */
+  String get visibility => this._visibility;
+
+  /** Sets the value of "visibility" */
+  void set visibility(String value) {
+    _visibility = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('visibility')
+  String _visibility;
+    
+  /** Gets the value of "white-space" */
+  String get whiteSpace => this._whiteSpace;
+
+  /** Sets the value of "white-space" */
+  void set whiteSpace(String value) {
+    _whiteSpace = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('whiteSpace')
+  String _whiteSpace;
+    
+  /** Gets the value of "width" */
+  String get width => this._width;
+
+  /** Sets the value of "width" */
+  void set width(String value) {
+    _width = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('width')
+  String _width;
+    
+  /** Gets the value of "word-spacing" */
+  String get wordSpacing => this._wordSpacing;
+
+  /** Sets the value of "word-spacing" */
+  void set wordSpacing(String value) {
+    _wordSpacing = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('wordSpacing')
+  String _wordSpacing;
+    
+  /** Gets the value of "z-index" */
+  String get zIndex => this._zIndex;
+
+  /** Sets the value of "z-index" */
+  void set zIndex(String value) {
+    _zIndex = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('zIndex')
+  String _zIndex;
+    
 }
 
 class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
@@ -3454,6 +4453,466 @@
     _elementCssStyleDeclarationSetIterable.forEach((e) =>
         e.setProperty(propertyName, value, priority));
   }
+
+
+  void _setAll(String propertyName, String value) {
+    value = value == null ? '' : value;
+    for (Element element in _elementIterable) {
+      JS('void', '#.style[#] = #', element, propertyName, value);
+    }
+  }
+
+  /** Sets the value of "background" */
+  void set background(String value) {
+    _setAll('background', value);
+  }
+    
+  /** Sets the value of "background-attachment" */
+  void set backgroundAttachment(String value) {
+    _setAll('backgroundAttachment', value);
+  }
+    
+  /** Sets the value of "background-color" */
+  void set backgroundColor(String value) {
+    _setAll('backgroundColor', value);
+  }
+    
+  /** Sets the value of "background-image" */
+  void set backgroundImage(String value) {
+    _setAll('backgroundImage', value);
+  }
+    
+  /** Sets the value of "background-position" */
+  void set backgroundPosition(String value) {
+    _setAll('backgroundPosition', value);
+  }
+    
+  /** Sets the value of "background-repeat" */
+  void set backgroundRepeat(String value) {
+    _setAll('backgroundRepeat', value);
+  }
+    
+  /** Sets the value of "border" */
+  void set border(String value) {
+    _setAll('border', value);
+  }
+    
+  /** Sets the value of "border-bottom" */
+  void set borderBottom(String value) {
+    _setAll('borderBottom', value);
+  }
+    
+  /** Sets the value of "border-bottom-color" */
+  void set borderBottomColor(String value) {
+    _setAll('borderBottomColor', value);
+  }
+    
+  /** Sets the value of "border-bottom-style" */
+  void set borderBottomStyle(String value) {
+    _setAll('borderBottomStyle', value);
+  }
+    
+  /** Sets the value of "border-bottom-width" */
+  void set borderBottomWidth(String value) {
+    _setAll('borderBottomWidth', value);
+  }
+    
+  /** Sets the value of "border-collapse" */
+  void set borderCollapse(String value) {
+    _setAll('borderCollapse', value);
+  }
+    
+  /** Sets the value of "border-color" */
+  void set borderColor(String value) {
+    _setAll('borderColor', value);
+  }
+    
+  /** Sets the value of "border-left" */
+  void set borderLeft(String value) {
+    _setAll('borderLeft', value);
+  }
+    
+  /** Sets the value of "border-left-color" */
+  void set borderLeftColor(String value) {
+    _setAll('borderLeftColor', value);
+  }
+    
+  /** Sets the value of "border-left-style" */
+  void set borderLeftStyle(String value) {
+    _setAll('borderLeftStyle', value);
+  }
+    
+  /** Sets the value of "border-left-width" */
+  void set borderLeftWidth(String value) {
+    _setAll('borderLeftWidth', value);
+  }
+    
+  /** Sets the value of "border-right" */
+  void set borderRight(String value) {
+    _setAll('borderRight', value);
+  }
+    
+  /** Sets the value of "border-right-color" */
+  void set borderRightColor(String value) {
+    _setAll('borderRightColor', value);
+  }
+    
+  /** Sets the value of "border-right-style" */
+  void set borderRightStyle(String value) {
+    _setAll('borderRightStyle', value);
+  }
+    
+  /** Sets the value of "border-right-width" */
+  void set borderRightWidth(String value) {
+    _setAll('borderRightWidth', value);
+  }
+    
+  /** Sets the value of "border-spacing" */
+  void set borderSpacing(String value) {
+    _setAll('borderSpacing', value);
+  }
+    
+  /** Sets the value of "border-style" */
+  void set borderStyle(String value) {
+    _setAll('borderStyle', value);
+  }
+    
+  /** Sets the value of "border-top" */
+  void set borderTop(String value) {
+    _setAll('borderTop', value);
+  }
+    
+  /** Sets the value of "border-top-color" */
+  void set borderTopColor(String value) {
+    _setAll('borderTopColor', value);
+  }
+    
+  /** Sets the value of "border-top-style" */
+  void set borderTopStyle(String value) {
+    _setAll('borderTopStyle', value);
+  }
+    
+  /** Sets the value of "border-top-width" */
+  void set borderTopWidth(String value) {
+    _setAll('borderTopWidth', value);
+  }
+    
+  /** Sets the value of "border-width" */
+  void set borderWidth(String value) {
+    _setAll('borderWidth', value);
+  }
+    
+  /** Sets the value of "bottom" */
+  void set bottom(String value) {
+    _setAll('bottom', value);
+  }
+    
+  /** Sets the value of "caption-side" */
+  void set captionSide(String value) {
+    _setAll('captionSide', value);
+  }
+    
+  /** Sets the value of "clear" */
+  void set clear(String value) {
+    _setAll('clear', value);
+  }
+    
+  /** Sets the value of "clip" */
+  void set clip(String value) {
+    _setAll('clip', value);
+  }
+    
+  /** Sets the value of "color" */
+  void set color(String value) {
+    _setAll('color', value);
+  }
+    
+  /** Sets the value of "content" */
+  void set content(String value) {
+    _setAll('content', value);
+  }
+    
+  /** Sets the value of "cursor" */
+  void set cursor(String value) {
+    _setAll('cursor', value);
+  }
+    
+  /** Sets the value of "direction" */
+  void set direction(String value) {
+    _setAll('direction', value);
+  }
+    
+  /** Sets the value of "display" */
+  void set display(String value) {
+    _setAll('display', value);
+  }
+    
+  /** Sets the value of "empty-cells" */
+  void set emptyCells(String value) {
+    _setAll('emptyCells', value);
+  }
+    
+  /** Sets the value of "font" */
+  void set font(String value) {
+    _setAll('font', value);
+  }
+    
+  /** Sets the value of "font-family" */
+  void set fontFamily(String value) {
+    _setAll('fontFamily', value);
+  }
+    
+  /** Sets the value of "font-size" */
+  void set fontSize(String value) {
+    _setAll('fontSize', value);
+  }
+    
+  /** Sets the value of "font-style" */
+  void set fontStyle(String value) {
+    _setAll('fontStyle', value);
+  }
+    
+  /** Sets the value of "font-variant" */
+  void set fontVariant(String value) {
+    _setAll('fontVariant', value);
+  }
+    
+  /** Sets the value of "font-weight" */
+  void set fontWeight(String value) {
+    _setAll('fontWeight', value);
+  }
+    
+  /** Sets the value of "height" */
+  void set height(String value) {
+    _setAll('height', value);
+  }
+    
+  /** Sets the value of "left" */
+  void set left(String value) {
+    _setAll('left', value);
+  }
+    
+  /** Sets the value of "letter-spacing" */
+  void set letterSpacing(String value) {
+    _setAll('letterSpacing', value);
+  }
+    
+  /** Sets the value of "line-height" */
+  void set lineHeight(String value) {
+    _setAll('lineHeight', value);
+  }
+    
+  /** Sets the value of "list-style" */
+  void set listStyle(String value) {
+    _setAll('listStyle', value);
+  }
+    
+  /** Sets the value of "list-style-image" */
+  void set listStyleImage(String value) {
+    _setAll('listStyleImage', value);
+  }
+    
+  /** Sets the value of "list-style-position" */
+  void set listStylePosition(String value) {
+    _setAll('listStylePosition', value);
+  }
+    
+  /** Sets the value of "list-style-type" */
+  void set listStyleType(String value) {
+    _setAll('listStyleType', value);
+  }
+    
+  /** Sets the value of "margin" */
+  void set margin(String value) {
+    _setAll('margin', value);
+  }
+    
+  /** Sets the value of "margin-bottom" */
+  void set marginBottom(String value) {
+    _setAll('marginBottom', value);
+  }
+    
+  /** Sets the value of "margin-left" */
+  void set marginLeft(String value) {
+    _setAll('marginLeft', value);
+  }
+    
+  /** Sets the value of "margin-right" */
+  void set marginRight(String value) {
+    _setAll('marginRight', value);
+  }
+    
+  /** Sets the value of "margin-top" */
+  void set marginTop(String value) {
+    _setAll('marginTop', value);
+  }
+    
+  /** Sets the value of "max-height" */
+  void set maxHeight(String value) {
+    _setAll('maxHeight', value);
+  }
+    
+  /** Sets the value of "max-width" */
+  void set maxWidth(String value) {
+    _setAll('maxWidth', value);
+  }
+    
+  /** Sets the value of "min-height" */
+  void set minHeight(String value) {
+    _setAll('minHeight', value);
+  }
+    
+  /** Sets the value of "min-width" */
+  void set minWidth(String value) {
+    _setAll('minWidth', value);
+  }
+    
+  /** Sets the value of "outline" */
+  void set outline(String value) {
+    _setAll('outline', value);
+  }
+    
+  /** Sets the value of "outline-color" */
+  void set outlineColor(String value) {
+    _setAll('outlineColor', value);
+  }
+    
+  /** Sets the value of "outline-style" */
+  void set outlineStyle(String value) {
+    _setAll('outlineStyle', value);
+  }
+    
+  /** Sets the value of "outline-width" */
+  void set outlineWidth(String value) {
+    _setAll('outlineWidth', value);
+  }
+    
+  /** Sets the value of "overflow" */
+  void set overflow(String value) {
+    _setAll('overflow', value);
+  }
+    
+  /** Sets the value of "padding" */
+  void set padding(String value) {
+    _setAll('padding', value);
+  }
+    
+  /** Sets the value of "padding-bottom" */
+  void set paddingBottom(String value) {
+    _setAll('paddingBottom', value);
+  }
+    
+  /** Sets the value of "padding-left" */
+  void set paddingLeft(String value) {
+    _setAll('paddingLeft', value);
+  }
+    
+  /** Sets the value of "padding-right" */
+  void set paddingRight(String value) {
+    _setAll('paddingRight', value);
+  }
+    
+  /** Sets the value of "padding-top" */
+  void set paddingTop(String value) {
+    _setAll('paddingTop', value);
+  }
+    
+  /** Sets the value of "page-break-after" */
+  void set pageBreakAfter(String value) {
+    _setAll('pageBreakAfter', value);
+  }
+    
+  /** Sets the value of "page-break-before" */
+  void set pageBreakBefore(String value) {
+    _setAll('pageBreakBefore', value);
+  }
+    
+  /** Sets the value of "page-break-inside" */
+  void set pageBreakInside(String value) {
+    _setAll('pageBreakInside', value);
+  }
+    
+  /** Sets the value of "position" */
+  void set position(String value) {
+    _setAll('position', value);
+  }
+    
+  /** Sets the value of "quotes" */
+  void set quotes(String value) {
+    _setAll('quotes', value);
+  }
+    
+  /** Sets the value of "right" */
+  void set right(String value) {
+    _setAll('right', value);
+  }
+    
+  /** Sets the value of "table-layout" */
+  void set tableLayout(String value) {
+    _setAll('tableLayout', value);
+  }
+    
+  /** Sets the value of "text-align" */
+  void set textAlign(String value) {
+    _setAll('textAlign', value);
+  }
+    
+  /** Sets the value of "text-decoration" */
+  void set textDecoration(String value) {
+    _setAll('textDecoration', value);
+  }
+    
+  /** Sets the value of "text-indent" */
+  void set textIndent(String value) {
+    _setAll('textIndent', value);
+  }
+    
+  /** Sets the value of "text-transform" */
+  void set textTransform(String value) {
+    _setAll('textTransform', value);
+  }
+    
+  /** Sets the value of "top" */
+  void set top(String value) {
+    _setAll('top', value);
+  }
+    
+  /** Sets the value of "unicode-bidi" */
+  void set unicodeBidi(String value) {
+    _setAll('unicodeBidi', value);
+  }
+    
+  /** Sets the value of "vertical-align" */
+  void set verticalAlign(String value) {
+    _setAll('verticalAlign', value);
+  }
+    
+  /** Sets the value of "visibility" */
+  void set visibility(String value) {
+    _setAll('visibility', value);
+  }
+    
+  /** Sets the value of "white-space" */
+  void set whiteSpace(String value) {
+    _setAll('whiteSpace', value);
+  }
+    
+  /** Sets the value of "width" */
+  void set width(String value) {
+    _setAll('width', value);
+  }
+    
+  /** Sets the value of "word-spacing" */
+  void set wordSpacing(String value) {
+    _setAll('wordSpacing', value);
+  }
+    
+  /** Sets the value of "z-index" */
+  void set zIndex(String value) {
+    _setAll('zIndex', value);
+  }
+    
+
   // Important note: CssStyleDeclarationSet does NOT implement every method
   // available in CssStyleDeclaration. Some of the methods don't make so much
   // sense in terms of having a resonable value to return when you're
@@ -11796,6 +13255,33 @@
    * used when an explicit accessor is not available.
    */
   ElementEvents get on => new ElementEvents(this);
+  
+  /**
+   * Verify if any of the attributes that we use in the sanitizer look unexpected,
+   * possibly indicating DOM clobbering attacks.
+   *
+   * Those attributes are: attributes, lastChild, children, previousNode and tagName.
+   */
+  bool get _hasCorruptedAttributes {
+     return JS('bool', r'''
+       (function(element) {
+         if (!(element.attributes instanceof NamedNodeMap)) {
+	   return true;
+	 }
+	 var childNodes = element.childNodes;
+	 if (element.lastChild &&
+	     element.lastChild !== childNodes[childNodes.length -1]) {
+	   return true;
+	 }
+	 if (element.children) { // On Safari, children can apparently be null.
+  	   if (!((element.children instanceof HTMLCollection) ||
+               (element.children instanceof NodeList))) {
+	     return true;
+	   }
+	 }
+	 return false;
+          })(#)''', this);
+  }
 
   @DomName('Element.offsetHeight')
   @DocsEditable()
@@ -24843,7 +26329,7 @@
 @DomName('RTCIceCandidateEvent')
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcicecandidate-type
 @Experimental()
-@Native("RTCIceCandidateEvent")
+@Native("RTCIceCandidateEvent,RTCPeerConnectionIceEvent")
 class RtcIceCandidateEvent extends Event {
   // To suppress missing implicit constructor warnings.
   factory RtcIceCandidateEvent._() { throw new UnsupportedError("Not supported"); }
@@ -34891,6 +36377,12 @@
    *
    * If [shouldAdd] is true, then we always add that [value] to the element. If
    * [shouldAdd] is false then we always remove [value] from the element.
+   *
+   * If this corresponds to one element, returns `true` if [value] is present
+   * after the operation, and returns `false` if [value] is absent after the
+   * operation.
+   *
+   * If this corresponds to many elements, `null` is always returned.
    */
   bool toggle(String value, [bool shouldAdd]);
 
@@ -34917,7 +36409,7 @@
    * If this corresponds to one element. Returns true if [value] was added to
    * the set, otherwise false.
    *
-   * If this corresponds to many elements, null is always returned.
+   * If this corresponds to many elements, `null` is always returned.
    */
   bool add(String value);
 
@@ -34958,90 +36450,6 @@
    */
   void toggleAll(Iterable<String> iterable, [bool shouldAdd]);
 }
-
-/**
- * A set (union) of the CSS classes that are present in a set of elements.
- * Implemented separately from _ElementCssClassSet for performance.
- */
-class _MultiElementCssClassSet extends CssClassSetImpl {
-  final Iterable<Element> _elementIterable;
-  Iterable<_ElementCssClassSet> _elementCssClassSetIterable;
-
-  _MultiElementCssClassSet(this._elementIterable) {
-    _elementCssClassSetIterable = new List.from(_elementIterable).map(
-        (e) => new _ElementCssClassSet(e));
-  }
-
-  Set<String> readClasses() {
-    var s = new LinkedHashSet<String>();
-    _elementCssClassSetIterable.forEach(
-        (_ElementCssClassSet e) => s.addAll(e.readClasses()));
-    return s;
-  }
-
-  void writeClasses(Set<String> s) {
-    var classes = s.join(' ');
-    for (Element e in _elementIterable) {
-      e.className = classes;
-    }
-  }
-
-  /**
-   * Helper method used to modify the set of css classes on this element.
-   *
-   *   f - callback with:
-   *   s - a Set of all the css class name currently on this element.
-   *
-   *   After f returns, the modified set is written to the
-   *       className property of this element.
-   */
-  modify( f(Set<String> s)) {
-    _elementCssClassSetIterable.forEach((_ElementCssClassSet e) => e.modify(f));
-  }
-
-  /**
-   * Adds the class [value] to the element if it is not on it, removes it if it
-   * is.
-   */
-  bool toggle(String value, [bool shouldAdd]) =>
-      _elementCssClassSetIterable.fold(false,
-          (bool changed, _ElementCssClassSet e) =>
-              e.toggle(value, shouldAdd) || changed);
-
-  /**
-   * Remove the class [value] from element, and return true on successful
-   * removal.
-   *
-   * This is the Dart equivalent of jQuery's
-   * [removeClass](http://api.jquery.com/removeClass/).
-   */
-  bool remove(Object value) => _elementCssClassSetIterable.fold(false,
-      (bool changed, _ElementCssClassSet e) => e.remove(value) || changed);
-}
-
-class _ElementCssClassSet extends CssClassSetImpl {
-
-  final Element _element;
-
-  _ElementCssClassSet(this._element);
-
-  Set<String> readClasses() {
-    var s = new LinkedHashSet<String>();
-    var classname = _element.className;
-
-    for (String name in classname.split(' ')) {
-      String trimmed = name.trim();
-      if (!trimmed.isEmpty) {
-        s.add(trimmed);
-      }
-    }
-    return s;
-  }
-
-  void writeClasses(Set<String> s) {
-    _element.className = s.join(' ');
-  }
-}
 // 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.
@@ -35303,6 +36711,254 @@
 final _CONTENT = 'content';
 final _PADDING = 'padding';
 final _MARGIN = 'margin';
+// 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.
+
+
+/**
+ * A set (union) of the CSS classes that are present in a set of elements.
+ * Implemented separately from _ElementCssClassSet for performance.
+ */
+class _MultiElementCssClassSet extends CssClassSetImpl {
+  final Iterable<Element> _elementIterable;
+
+  // TODO(sra): Perhaps we should store the DomTokenList instead.
+  final List<CssClassSetImpl> _sets;
+
+  factory _MultiElementCssClassSet(Iterable<Element> elements) {
+    return new _MultiElementCssClassSet._(elements,
+        elements.map((Element e) => e.classes).toList());
+  }
+
+  _MultiElementCssClassSet._(this._elementIterable, this._sets);
+
+  Set<String> readClasses() {
+    var s = new LinkedHashSet<String>();
+    _sets.forEach((CssClassSetImpl e) => s.addAll(e.readClasses()));
+    return s;
+  }
+
+  void writeClasses(Set<String> s) {
+    var classes = s.join(' ');
+    for (Element e in _elementIterable) {
+      e.className = classes;
+    }
+  }
+
+  /**
+   * Helper method used to modify the set of css classes on this element.
+   *
+   *   f - callback with:
+   *   s - a Set of all the css class name currently on this element.
+   *
+   *   After f returns, the modified set is written to the
+   *       className property of this element.
+   */
+  modify( f(Set<String> s)) {
+    _sets.forEach((CssClassSetImpl e) => e.modify(f));
+  }
+
+  /**
+   * Adds the class [value] to the element if it is not on it, removes it if it
+   * is.
+   *
+   * TODO(sra): It seems wrong to collect a 'changed' flag like this when the
+   * underlying toggle returns an 'is set' flag.
+   */
+  bool toggle(String value, [bool shouldAdd]) =>
+      _sets.fold(false,
+          (bool changed, CssClassSetImpl e) =>
+              e.toggle(value, shouldAdd) || changed);
+
+  /**
+   * Remove the class [value] from element, and return true on successful
+   * removal.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
+  bool remove(Object value) => _sets.fold(false,
+      (bool changed, CssClassSetImpl e) => e.remove(value) || changed);
+}
+
+class _ElementCssClassSet extends CssClassSetImpl {
+  final Element _element;
+
+  _ElementCssClassSet(this._element);
+
+  Set<String> readClasses() {
+    var s = new LinkedHashSet<String>();
+    var classname = _element.className;
+
+    for (String name in classname.split(' ')) {
+      String trimmed = name.trim();
+      if (!trimmed.isEmpty) {
+        s.add(trimmed);
+      }
+    }
+    return s;
+  }
+
+  void writeClasses(Set<String> s) {
+    _element.className = s.join(' ');
+  }
+
+  int get length => _classListLength(_classListOf(_element));
+  bool get isEmpty => length == 0;
+  bool get isNotEmpty => length != 0;
+
+  void clear() {
+    _element.className = '';
+  }
+
+  bool contains(String value) {
+    return _contains(_element, value);
+  }
+
+  bool add(String value) {
+    return _add(_element, value);
+  }
+
+  bool remove(Object value) {
+    return value is String && _remove(_element, value);
+  }
+
+  bool toggle(String value, [bool shouldAdd]) {
+    return _toggle(_element, value, shouldAdd);
+  }
+
+  void addAll(Iterable<String> iterable) {
+    _addAll(_element, iterable);
+  }
+
+  void removeAll(Iterable<String> iterable) {
+    _removeAll(_element, iterable);
+  }
+
+  void retainAll(Iterable<String> iterable) {
+    _removeWhere(_element, iterable.toSet().contains, false);
+  }
+
+  void removeWhere(bool test(String name)) {
+    _removeWhere(_element, test, true);
+  }
+
+  void retainWhere(bool test(String name)) {
+    _removeWhere(_element, test, false);
+  }
+
+  static bool _contains(Element _element, String value) {
+    return _classListContains(_classListOf(_element), value);
+  }
+
+  static bool _add(Element _element, String value) {
+    DomTokenList list = _classListOf(_element);
+    // Compute returned result independently of action upon the set. One day we
+    // will be able to optimize it way if unused.
+    bool added = !_classListContains(list, value);
+    _classListAdd(list, value);
+    return added;
+  }
+
+  static bool _remove(Element _element, String value) {
+    DomTokenList list = _classListOf(_element);
+    bool removed = _classListContains(list, value);
+    _classListRemove(list, value);
+    return removed;
+  }
+
+  static bool _toggle(Element _element, String value, bool shouldAdd) {
+    // There is no value that can be passed as the second argument of
+    // DomTokenList.toggle that behaves the same as passing one argument.
+    // `null` is seen as false, meaning 'remove'.
+    return shouldAdd == null
+        ? _toggleDefault(_element, value)
+        : _toggleOnOff(_element, value, shouldAdd);
+  }
+
+  static bool _toggleDefault(Element _element, String value) {
+    DomTokenList list = _classListOf(_element);
+    return _classListToggle1(list, value);
+  }
+
+  static bool _toggleOnOff(Element _element, String value, bool shouldAdd) {
+    DomTokenList list = _classListOf(_element);
+    // IE's toggle does not take a second parameter. We would prefer:
+    //
+    //    return _classListToggle2(list, value, shouldAdd);
+    //
+    if (shouldAdd) {
+      _classListAdd(list, value);
+      return true;
+    } else {
+      _classListRemove(list, value);
+      return false;
+    }
+  }
+
+  static void _addAll(Element _element, Iterable<String> iterable) {
+    DomTokenList list = _classListOf(_element);
+    for (String value in iterable) {
+      _classListAdd(list, value);
+    }
+  }
+
+  static void _removeAll(Element _element, Iterable<String> iterable) {
+    DomTokenList list = _classListOf(_element);
+    for (var value in iterable) {
+      _classListRemove(list, value);
+    }
+  }
+
+  static void _removeWhere(
+      Element _element, bool test(String name), bool doRemove) {
+    DomTokenList list = _classListOf(_element);
+    int i = 0;
+    while (i < _classListLength(list)) {
+      String item = list.item(i);
+      if (doRemove == test(item)) {
+        _classListRemove(list, item);
+      } else {
+        ++i;
+      }
+    }
+  }
+
+  // A collection of static methods for DomTokenList. These methods are a
+  // work-around for the lack of annotations to express the full behaviour of
+  // the DomTokenList methods.
+
+  static DomTokenList _classListOf(Element e) =>
+      JS('returns:DomTokenList;creates:DomTokenList;effects:none;depends:all;',
+         '#.classList', e);
+
+  static int _classListLength(DomTokenList list) =>
+      JS('returns:JSUInt31;effects:none;depends:all;', '#.length', list);
+
+  static bool _classListContains(DomTokenList list, String value) =>
+      JS('returns:bool;effects:none;depends:all;',
+          '#.contains(#)', list, value);
+
+  static void _classListAdd(DomTokenList list, String value) {
+    // list.add(value);
+    JS('', '#.add(#)', list, value);
+  }
+
+  static void _classListRemove(DomTokenList list, String value) {
+    // list.remove(value);
+    JS('', '#.remove(#)', list, value);
+  }
+
+  static bool _classListToggle1(DomTokenList list, String value) {
+    return JS('bool', '#.toggle(#)', list, value);
+  }
+
+  static bool _classListToggle2(
+      DomTokenList list, String value, bool shouldAdd) {
+    return JS('bool', '#.toggle(#, #)', list, value, shouldAdd);
+  }
+}
 
 /**
  * Class representing a
@@ -38009,6 +39665,13 @@
     if (element is svg.ScriptElement) {
       return false;
     }
+    // Firefox 37 has issues with creating foreign elements inside a
+    // foreignobject tag as SvgElement. We don't want foreignobject contents
+    // anyway, so just remove the whole tree outright. And we can't rely
+    // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144
+    if (element is svg.SvgElement && element.tagName == 'foreignObject') {
+      return false;
+    }
     if (element is svg.SvgElement) {
       return true;
     }
@@ -39103,7 +40766,7 @@
         _hiddenAnchor.protocol == _loc.protocol) ||
         (_hiddenAnchor.hostname == '' &&
         _hiddenAnchor.port == '' &&
-        _hiddenAnchor.protocol == ':');
+        (_hiddenAnchor.protocol == ':' || _hiddenAnchor.protocol == ''));
   }
 }
 
@@ -39137,29 +40800,46 @@
   _ValidatingTreeSanitizer(this.validator) {}
 
   void sanitizeTree(Node node) {
-    void walk(Node node) {
-      sanitizeNode(node);
+    void walk(Node node, Node parent) {
+      sanitizeNode(node, parent);
 
       var child = node.lastChild;
       while (child != null) {
         // Child may be removed during the walk.
         var nextChild = child.previousNode;
-        walk(child);
+        walk(child, node);
         child = nextChild;
       }
     }
-    walk(node);
+    walk(node, null);
   }
 
-  void sanitizeNode(Node node) {
+  /// Aggressively try to remove node.
+  void _removeNode(Node node, Node parent) {
+    // If we have the parent, it's presumably already passed more sanitization or
+    // is the fragment, so ask it to remove the child. And if that fails try to
+    // set the outer html.
+    if (parent == null) {
+      node.remove();
+    } else {
+      parent._removeChild(node);
+    }
+  }
+  
+  void sanitizeNode(Node node, Node parent) {
     switch (node.nodeType) {
       case Node.ELEMENT_NODE:
         Element element = node;
+        if (element._hasCorruptedAttributes) {
+          window.console.warn('Removing element due to corrupted attributes on <${element}>');
+          _removeNode(node, parent);
+          break;
+        }
         var attrs = element.attributes;
         if (!validator.allowsElement(element)) {
           window.console.warn(
               'Removing disallowed element <${element.tagName}>');
-          element.remove();
+          _removeNode(node, parent);
           break;
         }
 
@@ -39168,7 +40848,7 @@
           if (!validator.allowsAttribute(element, 'is', isAttr)) {
             window.console.warn('Removing disallowed type extension '
                 '<${element.tagName} is="$isAttr">');
-            element.remove();
+            _removeNode(node, parent);
             break;
           }
         }
@@ -39197,7 +40877,7 @@
       case Node.CDATA_SECTION_NODE:
         break;
       default:
-        node.remove();
+        _removeNode(node, parent);
     }
   }
 }
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 4b331b7..63e26ae 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -4234,7 +4234,7 @@
 
 
 @DomName('CSSStyleDeclaration')
- class CssStyleDeclaration  extends NativeFieldWrapperClass2 with
+class CssStyleDeclaration  extends NativeFieldWrapperClass2 with
     CssStyleDeclarationBase  {
   factory CssStyleDeclaration() => new CssStyleDeclaration.css('');
 
@@ -4284,14 +4284,25 @@
 
   @DomName('CSSStyleDeclaration.setProperty')
   void setProperty(String propertyName, String value, [String priority]) {
-    if (_supportsProperty(_camelCase(propertyName))) {
-      return _setPropertyHelper(propertyName, value, priority);
-    } else {
-      return _setPropertyHelper(Device.cssPrefix + propertyName, value,
-          priority);
-    }
+    return _setPropertyHelper(_browserPropertyName(propertyName),
+      value, priority);
   }
 
+  String _browserPropertyName(String propertyName) {
+    String name = _readCache(propertyName);
+    if (name is String) return name;
+    if (_supportsProperty(_camelCase(propertyName))) {
+      name = propertyName;
+    } else {
+      name = Device.cssPrefix + propertyName;
+    }
+    _writeCache(propertyName, name);
+    return name;
+  }
+
+  static String _readCache(String key) => null;
+  static void _writeCache(String key, value) {}
+
   static String _camelCase(String hyphenated) {
     // The "ms" prefix is always lowercased.
     return hyphenated.replaceFirst(new RegExp('^-ms-'), 'ms-').replaceAllMapped(
@@ -4382,6 +4393,9 @@
     _elementCssStyleDeclarationSetIterable.forEach((e) =>
         e.setProperty(propertyName, value, priority));
   }
+
+
+
   // Important note: CssStyleDeclarationSet does NOT implement every method
   // available in CssStyleDeclaration. Some of the methods don't make so much
   // sense in terms of having a resonable value to return when you're
@@ -12634,6 +12648,15 @@
    * used when an explicit accessor is not available.
    */
   ElementEvents get on => new ElementEvents(this);
+  
+  /**
+   * Verify if any of the attributes that we use in the sanitizer look unexpected,
+   * possibly indicating DOM clobbering attacks.
+   *
+   * Those attributes are: attributes, lastChild, children, previousNode and tagName.
+   */
+  // Dartium isn't affected by these attacks, because it goes directly to the C++ API.
+  bool get _hasCorruptedAttributes => false;
 
   @DomName('Element.offsetHeight')
   @DocsEditable()
@@ -37276,6 +37299,12 @@
    *
    * If [shouldAdd] is true, then we always add that [value] to the element. If
    * [shouldAdd] is false then we always remove [value] from the element.
+   *
+   * If this corresponds to one element, returns `true` if [value] is present
+   * after the operation, and returns `false` if [value] is absent after the
+   * operation.
+   *
+   * If this corresponds to many elements, `null` is always returned.
    */
   bool toggle(String value, [bool shouldAdd]);
 
@@ -37302,7 +37331,7 @@
    * If this corresponds to one element. Returns true if [value] was added to
    * the set, otherwise false.
    *
-   * If this corresponds to many elements, null is always returned.
+   * If this corresponds to many elements, `null` is always returned.
    */
   bool add(String value);
 
@@ -37343,6 +37372,10 @@
    */
   void toggleAll(Iterable<String> iterable, [bool shouldAdd]);
 }
+// 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.
+
 
 /**
  * A set (union) of the CSS classes that are present in a set of elements.
@@ -40394,6 +40427,13 @@
     if (element is svg.ScriptElement) {
       return false;
     }
+    // Firefox 37 has issues with creating foreign elements inside a
+    // foreignobject tag as SvgElement. We don't want foreignobject contents
+    // anyway, so just remove the whole tree outright. And we can't rely
+    // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144
+    if (element is svg.SvgElement && element.tagName == 'foreignObject') {
+      return false;
+    }
     if (element is svg.SvgElement) {
       return true;
     }
@@ -40544,7 +40584,7 @@
         _hiddenAnchor.protocol == _loc.protocol) ||
         (_hiddenAnchor.hostname == '' &&
         _hiddenAnchor.port == '' &&
-        _hiddenAnchor.protocol == ':');
+        (_hiddenAnchor.protocol == ':' || _hiddenAnchor.protocol == ''));
   }
 }
 
@@ -40578,29 +40618,46 @@
   _ValidatingTreeSanitizer(this.validator) {}
 
   void sanitizeTree(Node node) {
-    void walk(Node node) {
-      sanitizeNode(node);
+    void walk(Node node, Node parent) {
+      sanitizeNode(node, parent);
 
       var child = node.lastChild;
       while (child != null) {
         // Child may be removed during the walk.
         var nextChild = child.previousNode;
-        walk(child);
+        walk(child, node);
         child = nextChild;
       }
     }
-    walk(node);
+    walk(node, null);
   }
 
-  void sanitizeNode(Node node) {
+  /// Aggressively try to remove node.
+  void _removeNode(Node node, Node parent) {
+    // If we have the parent, it's presumably already passed more sanitization or
+    // is the fragment, so ask it to remove the child. And if that fails try to
+    // set the outer html.
+    if (parent == null) {
+      node.remove();
+    } else {
+      parent._removeChild(node);
+    }
+  }
+  
+  void sanitizeNode(Node node, Node parent) {
     switch (node.nodeType) {
       case Node.ELEMENT_NODE:
         Element element = node;
+        if (element._hasCorruptedAttributes) {
+          window.console.warn('Removing element due to corrupted attributes on <${element}>');
+          _removeNode(node, parent);
+          break;
+        }
         var attrs = element.attributes;
         if (!validator.allowsElement(element)) {
           window.console.warn(
               'Removing disallowed element <${element.tagName}>');
-          element.remove();
+          _removeNode(node, parent);
           break;
         }
 
@@ -40609,7 +40666,7 @@
           if (!validator.allowsAttribute(element, 'is', isAttr)) {
             window.console.warn('Removing disallowed type extension '
                 '<${element.tagName} is="$isAttr">');
-            element.remove();
+            _removeNode(node, parent);
             break;
           }
         }
@@ -40638,7 +40695,7 @@
       case Node.CDATA_SECTION_NODE:
         break;
       default:
-        node.remove();
+        _removeNode(node, parent);
     }
   }
 }
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index 09f06ea..97d4fd7 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -334,6 +334,74 @@
     }
   }
 
+  // Process end of headers. Returns true if the parser should stop
+  // parsing and return. This will be in case of either an upgrade
+  // request or a request or response with an empty body.
+  bool _headersEnd() {
+    _headers._mutable = false;
+
+    _transferLength = _headers.contentLength;
+    // Ignore the Content-Length header if Transfer-Encoding
+    // is chunked (RFC 2616 section 4.4)
+    if (_chunked) _transferLength = -1;
+
+    // If a request message has neither Content-Length nor
+    // Transfer-Encoding the message must not have a body (RFC
+    // 2616 section 4.3).
+    if (_messageType == _MessageType.REQUEST &&
+        _transferLength < 0 &&
+       _chunked == false) {
+       _transferLength = 0;
+    }
+    if (_connectionUpgrade) {
+      _state = _State.UPGRADED;
+      _transferLength = 0;
+    }
+    _createIncoming(_transferLength);
+    if (_requestParser) {
+      _incoming.method =
+          new String.fromCharCodes(_method);
+      _incoming.uri =
+          Uri.parse(
+              new String.fromCharCodes(_uri_or_reason_phrase));
+    } else {
+      _incoming.statusCode = _statusCode;
+      _incoming.reasonPhrase =
+          new String.fromCharCodes(_uri_or_reason_phrase);
+    }
+    _method.clear();
+    _uri_or_reason_phrase.clear();
+    if (_connectionUpgrade) {
+      _incoming.upgraded = true;
+      _parserCalled = false;
+      var tmp = _incoming;
+      _closeIncoming();
+      _controller.add(tmp);
+      return true;
+    }
+    if (_transferLength == 0 ||
+        (_messageType == _MessageType.RESPONSE && _noMessageBody)) {
+      _reset();
+      var tmp = _incoming;
+      _closeIncoming();
+      _controller.add(tmp);
+      return false;
+    } else if (_chunked) {
+      _state = _State.CHUNK_SIZE;
+      _remainingContent = 0;
+    } else if (_transferLength > 0) {
+      _remainingContent = _transferLength;
+      _state = _State.BODY;
+    } else {
+      // Neither chunked nor content length. End of body
+      // indicated by close.
+      _state = _State.BODY;
+    }
+    _parserCalled = false;
+    _controller.add(_incoming);
+    return true;
+  }
+
   // From RFC 2616.
   // generic-message = start-line
   //                   *(message-header CRLF)
@@ -487,8 +555,13 @@
               throw new HttpException("Invalid response line");
             }
           } else {
-            _expect(byte, _CharCode.CR);
-            _state = _State.REQUEST_LINE_ENDING;
+            if (byte == _CharCode.CR) {
+              _state = _State.REQUEST_LINE_ENDING;
+            } else {
+              _expect(byte, _CharCode.LF);
+              _messageType = _MessageType.REQUEST;
+              _state = _State.HEADER_START;
+            }
           }
           break;
 
@@ -545,6 +618,9 @@
           _headers = new _HttpHeaders(version);
           if (byte == _CharCode.CR) {
             _state = _State.HEADER_ENDING;
+          } else if (byte == _CharCode.LF) {
+            _state = _State.HEADER_ENDING;
+            _index--;  // Make the new state see the LF again.
           } else {
             // Start of new header field.
             _headerField.add(_toLowerCaseByte(byte));
@@ -566,6 +642,8 @@
         case _State.HEADER_VALUE_START:
           if (byte == _CharCode.CR) {
             _state = _State.HEADER_VALUE_FOLDING_OR_ENDING;
+          } else if (byte == _CharCode.LF) {
+            _state = _State.HEADER_VALUE_FOLD_OR_END;
           } else if (byte != _CharCode.SP && byte != _CharCode.HT) {
             // Start of new header value.
             _headerValue.add(byte);
@@ -576,6 +654,8 @@
         case _State.HEADER_VALUE:
           if (byte == _CharCode.CR) {
             _state = _State.HEADER_VALUE_FOLDING_OR_ENDING;
+          } else if (byte == _CharCode.LF) {
+            _state = _State.HEADER_VALUE_FOLD_OR_END;
           } else {
             _headerValue.add(byte);
           }
@@ -613,6 +693,9 @@
 
             if (byte == _CharCode.CR) {
               _state = _State.HEADER_ENDING;
+            } else if (byte == _CharCode.LF) {
+              _state = _State.HEADER_ENDING;
+              _index--;  // Make the new state see the LF again.
             } else {
               // Start of new header field.
               _headerField.add(_toLowerCaseByte(byte));
@@ -623,67 +706,11 @@
 
         case _State.HEADER_ENDING:
           _expect(byte, _CharCode.LF);
-          _headers._mutable = false;
-
-          _transferLength = _headers.contentLength;
-          // Ignore the Content-Length header if Transfer-Encoding
-          // is chunked (RFC 2616 section 4.4)
-          if (_chunked) _transferLength = -1;
-
-          // If a request message has neither Content-Length nor
-          // Transfer-Encoding the message must not have a body (RFC
-          // 2616 section 4.3).
-          if (_messageType == _MessageType.REQUEST &&
-              _transferLength < 0 &&
-              _chunked == false) {
-            _transferLength = 0;
-          }
-          if (_connectionUpgrade) {
-            _state = _State.UPGRADED;
-            _transferLength = 0;
-          }
-          _createIncoming(_transferLength);
-          if (_requestParser) {
-            _incoming.method =
-                new String.fromCharCodes(_method);
-            _incoming.uri =
-                Uri.parse(
-                    new String.fromCharCodes(_uri_or_reason_phrase));
-          } else {
-            _incoming.statusCode = _statusCode;
-            _incoming.reasonPhrase =
-                new String.fromCharCodes(_uri_or_reason_phrase);
-          }
-          _method.clear();
-          _uri_or_reason_phrase.clear();
-          if (_connectionUpgrade) {
-            _incoming.upgraded = true;
-            _parserCalled = false;
-            var tmp = _incoming;
-            _closeIncoming();
-            _controller.add(tmp);
+          if (_headersEnd()) {
             return;
-          }
-          if (_transferLength == 0 ||
-              (_messageType == _MessageType.RESPONSE && _noMessageBody)) {
-            _reset();
-            var tmp = _incoming;
-            _closeIncoming();
-            _controller.add(tmp);
-            break;
-          } else if (_chunked) {
-            _state = _State.CHUNK_SIZE;
-            _remainingContent = 0;
-          } else if (_transferLength > 0) {
-            _remainingContent = _transferLength;
-            _state = _State.BODY;
           } else {
-            // Neither chunked nor content length. End of body
-            // indicated by close.
-            _state = _State.BODY;
+            break;
           }
-          _parserCalled = false;
-          _controller.add(_incoming);
           return;
 
         case _State.CHUNK_SIZE_STARTING_CR:
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 2d8ecab..ea1bd76 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -431,16 +431,16 @@
 
 /**
  * [ProcessResult] represents the result of running a non-interactive
- * process started with [:Process.run:].
+ * process started with [Process.run] or [Process.runSync].
  */
-abstract class ProcessResult {
+class ProcessResult {
   /**
    * Exit code for the process.
    *
    * See [Process.exitCode] for more information in the exit code
    * value.
    */
-  int get exitCode;
+  final int exitCode;
 
   /**
    * Standard output from the process. The value used for the
@@ -448,7 +448,7 @@
    * `null` was used this value is of type `List<int> otherwise it is
    * of type `String`.
    */
-  get stdout;
+  final stdout;
 
   /**
    * Standard error from the process. The value used for the
@@ -456,12 +456,14 @@
    * `null` was used this value is of type `List<int>
    * otherwise it is of type `String`.
    */
-  get stderr;
+  final stderr;
 
   /**
-   * Process id from the process.
+   * Process id of the process.
    */
-  int get pid;
+  final int pid;
+
+  ProcessResult(this.pid, this.exitCode, this.stdout, this.stderr);
 }
 
 
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index bcd5d07..ba0ac01 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -4797,13 +4797,7 @@
     return fragment.nodes.where((e) => e is SvgElement).single;
   }
 
-  _AttributeClassSet _cssClassSet;
-  CssClassSet get classes {
-    if (_cssClassSet == null) {
-      _cssClassSet = new _AttributeClassSet(this);
-    }
-    return _cssClassSet;
-  }
+  CssClassSet get classes => new _AttributeClassSet(this);
 
   List<Element> get children => new FilteredElementList<Element>(this);
 
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index deacd52..d480db3 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -5437,13 +5437,7 @@
     return fragment.nodes.where((e) => e is SvgElement).single;
   }
 
-  _AttributeClassSet _cssClassSet;
-  CssClassSet get classes {
-    if (_cssClassSet == null) {
-      _cssClassSet = new _AttributeClassSet(this);
-    }
-    return _cssClassSet;
-  }
+  CssClassSet get classes => new _AttributeClassSet(this);
 
   List<Element> get children => new FilteredElementList<Element>(this);
 
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status
index 8807107..b0072cf 100644
--- a/tests/co19/co19-analyzer2.status
+++ b/tests/co19/co19-analyzer2.status
@@ -6,6 +6,7 @@
 
 WebPlatformTest/html/semantics/forms/the-textarea-element/textarea-type_t01: fail
 LayoutTests/fast/forms/checkValidity-001_t01: fail
+Language/12_Expressions/29_Assignable_Expressions_A01_t08: StaticWarning
 
 # TBF: infinite look: class A {const A();final m = const A();}
 Language/12_Expressions/01_Constants_A17_t03: fail
@@ -67,7 +68,6 @@
 
 
 Language/12_Expressions/15_Method_Invocation/2_Cascaded_Invocation_A01_t19: MissingStaticWarning
-Language/12_Expressions/29_Assignable_Expressions_A01_t09: MissingStaticWarning
 Language/13_Statements/06_For/1_For_Loop_A01_t07: MissingStaticWarning
 Language/13_Statements/06_For/1_For_Loop_A01_t08: MissingStaticWarning
 Language/13_Statements/09_Switch_A10_t03: MissingStaticWarning
@@ -287,3 +287,6 @@
 WebPlatformTest/html/semantics/forms/the-input-element/email_t02: StaticWarning # co19 issue 701
 Language/12_Expressions/12_Instance_Creation/2_Const_A11_t01: MissingCompileTimeError # Issue 22010
 Language/12_Expressions/12_Instance_Creation/2_Const_A11_t03: MissingCompileTimeError # Issue 22010
+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
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 8a25345..0e54aec 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2dart && $builder_tag == new_backend ]
+Language/12_Expressions/18_Assignment_A04_t09: RuntimeError # Issue 23015
 LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # issue 19953
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # issue 19953
 LibTest/core/List/List_class_A01_t02: Crash # issue 19953
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index a88dee0..e68755a 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -2,6 +2,8 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+LayoutTests/fast/innerHTML/innerHTML-svg-write_t01: Skip # Temporary suppression, WIP alanknight
+
 [ $compiler == dart2js ]
 Language/03_Overview/1_Scoping_A02_t05: CompileTimeError # Issue 21072
 Language/03_Overview/1_Scoping_A02_t06: CompileTimeError # Issue 21072
@@ -503,6 +505,7 @@
 LayoutTests/fast/canvas/webgl/uniform-location_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/uninitialized-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-depth-texture_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/hit-test-generated-content_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/malformed-url_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-animation-before-onload_t01: Pass, RuntimeError # Please triage this failure
@@ -700,7 +703,6 @@
 LayoutTests/fast/dom/blur-contenteditable_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/characterdata-api-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/computed-style-set-property_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/document-register-svg-extends_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/element-names_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/dataset-xhtml_t01: RuntimeError # Please triage this failure
@@ -1990,7 +1992,6 @@
 LayoutTests/fast/dom/characterdata-api-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/click-method-on-html-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/computed-style-set-property_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/containerNode_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/css-delete-doc_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/css-innerHTML_t01: RuntimeError # Please triage this failure
@@ -2925,6 +2926,28 @@
 [ $compiler == dart2js && $runtime == ff && $system == windows ]
 LayoutTests/fast/dom/Window/window-scroll-arguments_t01: RuntimeError # Issue 22564
 WebPlatformTest/html/syntax/parsing/math-parse_t03: RuntimeError # Issue 22564
+LayoutTests/fast/dom/Attr/access-after-element-destruction_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/HTMLOutputElement/htmloutputelement-value_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/Range/surroundContents-check-boundary-points_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/Range/surroundContents-for-detached-node_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/insertAdjacentElement_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/insertAllBefore_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/insertAllBefore_A02_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/insertBefore_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/insertBefore_A02_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/nodes_A01_t02: RuntimeError # Please triage this failure
+LibTest/html/Element/replaceWith_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/children_A01_t02: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/insertAdjacentElement_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/insertAllBefore_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/insertAllBefore_A02_t01: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/insertBefore_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/insertBefore_A02_t01: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/nodes_A01_t02: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/nodes_setter_A01_t01: RuntimeError # Please triage this failure
+LibTest/html/IFrameElement/replaceWith_A01_t01: RuntimeError # Please triage this failure
+WebPlatformTest/dom/nodes/attributes/setAttributeNS_A03_t01: RuntimeError # Please triage this failure
+WebPlatformTest/html-templates/serializing-html-templates/outerhtml_t01: RuntimeError # Please triage this failure
 
 [ $compiler == dart2js && $runtime == ff && $system != windows ]
 LayoutTests/fast/canvas/canvas-resetTransform_t01: RuntimeError # Please triage this failure
@@ -3369,7 +3392,6 @@
 LayoutTests/fast/dom/attribute-namespaces-get-set_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/characterdata-api-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/computed-style-set-property_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/attribute-changed-callback_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/constructor-calls-created-synchronously_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/created-callback_t01: RuntimeError # Please triage this failure
@@ -4657,7 +4679,6 @@
 LayoutTests/fast/dom/characterdata-api-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/comment-not-documentElement_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/computed-style-set-property_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/createDocumentType-ownerDocument_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/createElementNS-namespace-errors_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/attribute-changed-callback_t01: RuntimeError # Please triage this failure
@@ -5893,7 +5914,6 @@
 LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/insertRule-font-face_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/insertRule-media_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/invalid-hex-color_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-import-rule-insertion_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-predefined-color_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-rule-value_t01: RuntimeError # Please triage this failure
@@ -5971,7 +5991,6 @@
 LayoutTests/fast/css/shadow-current-color_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/sheet-collection-link_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/shorthand-priority_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/shorthand-setProperty-important_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/sibling-selectors_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/space-before-charset-external_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/sticky/parsing-position-sticky_t01: RuntimeError # Please triage this failure
@@ -6258,7 +6277,7 @@
 LayoutTests/fast/dom/click-method-on-html-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/clone-node-form-elements_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/computed-style-set-property_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/clone-node-z-index_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/containerNode_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/createDocumentType-ownerDocument_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/createElementNS-namespace-errors_t01: RuntimeError # Please triage this failure
@@ -7913,7 +7932,6 @@
 LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/insertRule-font-face_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/insertRule-media_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/invalid-hex-color_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-import-rule-insertion_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-predefined-color_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/invalid-rule-value_t01: RuntimeError # Please triage this failure
@@ -7991,7 +8009,6 @@
 LayoutTests/fast/css/shadow-current-color_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css/sheet-collection-link_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/shorthand-priority_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/shorthand-setProperty-important_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/sibling-selectors_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/space-before-charset-external_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/sticky/parsing-position-sticky_t01: RuntimeError # Please triage this failure
@@ -8258,7 +8275,7 @@
 LayoutTests/fast/dom/characterdata-api-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/click-method-on-html-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/computed-style-set-property_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/clone-node-z-index_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/containerNode_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/createDocumentType-ownerDocument_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/createElementNS-namespace-errors_t01: RuntimeError # Please triage this failure
diff --git a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
index a7bb1ba..b0bdf8d 100644
--- a/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
+++ b/tests/compiler/dart2js/analyze_unused_dart2js_test.dart
@@ -28,8 +28,11 @@
   "lib/src/resolution/semantic_visitor.dart": const [
       "The method 'error"],
   "lib/src/resolution/semantic_visitor_mixins.dart": const [
-      "The method 'error",
-      "Mixin' is never used."]
+      "The method 'error"],
+
+  // Uncalled type predicate.  Keep while related predicates are used.
+  "lib/src/ssa/nodes.dart": const [
+      "The method 'isArray' is never called"],
 };
 
 void main() {
diff --git a/tests/compiler/dart2js/backend_dart/sexpr2_test.dart b/tests/compiler/dart2js/backend_dart/sexpr2_test.dart
index 3cff4de..fb55ec0 100644
--- a/tests/compiler/dart2js/backend_dart/sexpr2_test.dart
+++ b/tests/compiler/dart2js/backend_dart/sexpr2_test.dart
@@ -25,7 +25,7 @@
     void checkOutput(String elementName,

                      Element element,

                      String expectedOutput) {

-      ExecutableDefinition ir = compiler.irBuilder.getIr(element);

+      RootNode ir = compiler.irBuilder.getIr(element);

       if (expectedOutput == null) {

         Expect.isNull(ir, "\nInput:\n${result.input}\n"

                           "No CPS IR expected for $element");

diff --git a/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart b/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
index 1f06307..aa2c1ac 100644
--- a/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
+++ b/tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart
@@ -16,12 +16,12 @@
     show DartType;
 import 'package:compiler/src/elements/elements.dart'
    show Entity, Element, Elements, Local, TypeVariableElement, ErroneousElement,
-         TypeDeclarationElement, ExecutableElement;
+         TypeDeclarationElement, ExecutableElement, PublicName;
 import 'package:compiler/src/elements/modelx.dart'
     show ErroneousElementX, TypeVariableElementX;
 import 'package:compiler/src/tree/tree.dart' show LiteralDartString;
 import 'package:compiler/src/universe/universe.dart'
-    show Selector, SelectorKind;
+    show Selector, SelectorKind, CallStructure;
 import 'package:compiler/src/cps_ir/cps_ir_nodes.dart';
 
 /// Used whenever a node constructed by [SExpressionUnstringifier] needs a
@@ -190,7 +190,8 @@
     } else {
       kind = SelectorKind.CALL;
     }
-    return new Selector(kind, name, null, argumentCount);
+    return new Selector(kind, new PublicName(name), 
+        new CallStructure.unnamed(argumentCount));
   }
 
   /// Returns the tokens in s. Note that string literals are not necessarily
@@ -317,7 +318,7 @@
 
     tokens.consumeEnd();
     return new FunctionDefinition(element, thisParameter, parameters,
-        new RunnableBody(body, cont), null, null);
+        new Body(body, cont), null, null);
   }
 
   /// (IsTrue arg)
@@ -411,7 +412,7 @@
     List<Primitive> args = parsePrimitiveList();
 
     tokens.consumeEnd();
-    return new InvokeContinuation(cont, args, recursive: isRecursive);
+    return new InvokeContinuation(cont, args, isRecursive: isRecursive);
   }
 
   /// (InvokeMethod receiver method (args) cont)
diff --git a/tests/compiler/dart2js/interceptor_almost_constant_test.dart b/tests/compiler/dart2js/interceptor_almost_constant_test.dart
new file mode 100644
index 0000000..f32c3f4
--- /dev/null
+++ b/tests/compiler/dart2js/interceptor_almost_constant_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.
+
+import 'dart:async';
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'compiler_helper.dart';
+
+const String TEST_ONE = r"""
+  foo(b) {
+    var a = b ? [1,2,3] : null;
+    print(a.first);
+  }
+""";
+
+main() {
+  asyncTest(() => Future.wait([
+    // Check that almost-constant interceptor is used.
+    compile(TEST_ONE, entry: 'foo', check: (String generated) {
+      String re = r'a && [\w\.]*_methods';
+      Expect.isTrue(generated.contains(new RegExp(re)), 'contains /$re/');
+    })
+  ]));
+}
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 902ea6b..5b0b557 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart
@@ -111,8 +111,8 @@
   print(new Set.from([1, 2, 3]));
 }""", r"""
 function() {
-  P.print(P.Set_Set());
-  P.print(P.Set_Set$from([1, 2, 3]));
+  P.print(P.Set_Set(null));
+  P.print(P.Set_Set$from([1, 2, 3], null));
   return null;
 }"""),
   // Call synthetic constructor.
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 13547488..e77d5cd 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_constructor_test.dart
@@ -164,6 +164,56 @@
   v0.Bar$5$q$w$y$z("x", null, "w", "y", "z");
   return v0;
 }"""),
+  const TestEntry(r"""
+class C<T> {
+  foo() => T;
+}
+main() {
+  print(new C<int>().foo());
+}""", r"""
+function() {
+  P.print(V.C$(P.$int).foo$0());
+  return null;
+}"""),
+  const TestEntry(r"""
+class C<T> {
+  foo() => C;
+}
+main() {
+  print(new C<int>().foo());
+}""", r"""
+function() {
+  P.print(V.C$().foo$0());
+  return null;
+}"""),
+  const TestEntry.forMethod('generative_constructor(C#)', r"""
+class C<T> {
+  C() { print(T); }
+  foo() => print(T);
+}
+main() {
+  new C<int>();
+}""", r"""
+function($T) {
+  var v0;
+  v0 = H.setRuntimeTypeInfo(new V.C(), [$T]);
+  v0.C$0();
+  return v0;
+}"""),
+  const TestEntry.forMethod('generative_constructor(C#)', r"""
+class C<T> {
+  var x;
+  C() : x = new D<T>();
+}
+class D<T> {
+  foo() => T;
+}
+main() {
+  print(new C<int>().x.foo());
+}""", r"""
+function($T) {
+  return H.setRuntimeTypeInfo(new V.C(V.D$($T)), [$T]);
+}"""),
 ];
 
 void main() {
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 e15bf3e..64515ce 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_interceptors_test.dart
@@ -37,7 +37,7 @@
 }""",
 r"""
 function() {
-  var l, i, v0, x, j, v1;
+  var l, i, v0, x, j;
   l = ["hest", ["h", "e", "s", "t"]];
   P.print(J.getInterceptor$as(l).get$length(l));
   i = 0;
@@ -48,8 +48,8 @@
         x = J.getInterceptor$as(l).$index(l, i);
         j = 0;
         while (true) {
-          v1 = J.getInterceptor$as(x).get$length(x);
-          if (P.identical(J.getInterceptor$n(j).$lt(j, v1), true)) {
+          v0 = J.getInterceptor$as(x).get$length(x);
+          if (P.identical(J.getInterceptor$n(j).$lt(j, v0), true)) {
             P.print(J.getInterceptor$as(x).$index(x, j));
             j = J.getInterceptor$ns(j).$add(j, 1);
           } else {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
index 86f8260..debe5b0 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_runtime_types_test.dart
@@ -43,6 +43,29 @@
 function() {
   return P.print($createType($typeToString($getSubstitutedTypeArgument(this, "\$asC", 1))));
 }"""),
+  const TestEntry.forMethod('function(C#foo)', r"""
+class C<T> {
+  foo() => new D<C<T>>();
+}
+class D<T> {
+  bar() => T;
+}
+main() {
+  print(new C<int>().foo().bar());
+}""", """
+function() {
+  return V.D\$([V.C, $getTypeArgument(this, 0)]);
+}"""),
+    const TestEntry.forMethod('generative_constructor(C#)', r"""
+class C<X, Y, Z> {
+  foo() => 'C<$X $Y, $Z>';
+}
+main() {
+  new C<C, int, String>().foo();
+}""", r"""
+function($X, $Y, $Z) {
+  return H.setRuntimeTypeInfo(new V.C(), [$X, $Y, $Z]);
+}"""),
 ];
 
 void main() {
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
index 29a42ad..9ea9201 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
@@ -40,18 +40,15 @@
   return compiler.enqueuer.codegen.generatedCode[mainFunction];
 }
 
-js.Node getJsNodeForElement(Compiler compiler,
-                                Element element) {
+js.Node getJsNodeForElement(Compiler compiler, Element element) {
   return compiler.enqueuer.codegen.generatedCode[element];
 }
 
-ir.ExecutableDefinition getIrNodeForElement(Compiler compiler,
-                                            Element element) {
+ir.RootNode getIrNodeForElement(Compiler compiler, Element element) {
   return compiler.irBuilder.getIr(element);
 }
 
-String getCodeForMethod(Compiler compiler,
-                        String name) {
+String getCodeForMethod(Compiler compiler, String name) {
   Element foundElement;
   for (Element element in compiler.enqueuer.codegen.generatedCode.keys) {
     if (element.toString() == name) {
diff --git a/tests/compiler/dart2js/js_spec_string_test.dart b/tests/compiler/dart2js/js_spec_string_test.dart
index 8ebbfd7..876c87c 100644
--- a/tests/compiler/dart2js/js_spec_string_test.dart
+++ b/tests/compiler/dart2js/js_spec_string_test.dart
@@ -20,6 +20,10 @@
     errorMessage = message;
     throw "error";
   }
+  reportError(spannable, kind, arguments) {
+    errorMessage = '$arguments';  // E.g.  "{text: Duplicate tag 'new'.}"
+    throw "error";
+  }
 
   noSuchMethod(_) => null;
 }
@@ -28,10 +32,16 @@
           {List returns,
            List creates,
            SideEffects expectedSideEffects,
+           NativeThrowBehavior expectedThrows,
+           bool expectedNew,
+           bool expectedGvn,
            bool expectError: false}) {
   List actualReturns = [];
   List actualCreates = [];
   SideEffects actualSideEffects;
+  NativeThrowBehavior actualThrows;
+  bool actualNew;
+  bool actualGvn;
   Listener listener = new Listener();
   try {
     NativeBehavior.processSpecString(
@@ -39,18 +49,28 @@
         null,
         specString,
         setSideEffects: (effects) { actualSideEffects = effects; },
+        setThrows: (b) { actualThrows = b; },
+        setIsAllocation: (b) { actualNew = b; },
+        setUseGvn: (b) { actualGvn = b; },
         resolveType: (t) => t,
         typesReturned: actualReturns, typesInstantiated: actualCreates,
         objectType: OBJECT, nullType: NULL);
   } catch (e) {
     Expect.isTrue(expectError);
-    Expect.isNotNull(listener.errorMessage, 'Internal error expected.');
+    Expect.isNotNull(listener.errorMessage, 'Error expected.');
     return;
   }
-  Expect.isNull(listener.errorMessage, 'Unexpected internal error.');
-  Expect.listEquals(returns, actualReturns, 'Unexpected returns.');
-  Expect.listEquals(creates, actualCreates, 'Unexpected creates.');
+  Expect.isNull(listener.errorMessage, 'Unexpected error.');
+  if (returns != null) {
+    Expect.listEquals(returns, actualReturns, 'Unexpected returns.');
+  }
+  if (creates != null) {
+    Expect.listEquals(creates, actualCreates, 'Unexpected creates.');
+  }
   Expect.equals(expectedSideEffects, actualSideEffects);
+  Expect.equals(expectedThrows, actualThrows);
+  Expect.equals(expectedNew, actualNew);
+  Expect.equals(expectedGvn, actualGvn);
 }
 
 void testWithSideEffects(String specString,
@@ -217,6 +237,8 @@
   testWithSideEffects('returns:A;', returns: ['A'], creates: []);
   testWithSideEffects('returns:A|B;', returns: ['A', 'B'], creates: []);
   testWithSideEffects('returns:A|B|C;', returns: ['A', 'B', 'C'], creates: []);
+  testWithSideEffects('returns: A| B |C ;',
+      returns: ['A', 'B', 'C'], creates: []);
 
   testWithSideEffects('creates:void;', expectError: true);
   testWithSideEffects('creates:;', expectError: true);
@@ -236,4 +258,28 @@
       returns: ['A', 'B'], creates: ['A', 'C']);
   testWithSideEffects(' returns:A|B|C;   creates:A;  ',
       returns: ['A', 'B', 'C'], creates: ['A']);
+
+  test('throws:must', expectedThrows: NativeThrowBehavior.MUST);
+  test('throws:may', expectedThrows: NativeThrowBehavior.MAY);
+  test('throws:never', expectedThrows: NativeThrowBehavior.NEVER);
+  test('throws:null(1)',
+      expectedThrows:
+          NativeThrowBehavior.MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS);
+
+  test('new:true', expectedNew: true);
+  test('new:false', expectedNew: false);
+  test('returns:A;new:true', returns: ['A'], expectedNew: true);
+  test(' new : true ;  returns:A;', returns: ['A'], expectedNew: true);
+  test('new:true;returns:A;new:true', expectError: true);
+
+  test('gvn:true', expectedGvn: true);
+  test('gvn:false', expectedGvn: false);
+  test('returns:A;gvn:true', returns: ['A'], expectedGvn: true);
+  test(' gvn : true ;  returns:A;', returns: ['A'], expectedGvn: true);
+  test('gvn:true;returns:A;gvn:true', expectError: true);
+
+  test('gvn: true; new: true', expectError: true);
+  test('gvn: true; new: false', expectedGvn: true, expectedNew: false);
+  test('gvn: false; new: true', expectedGvn: false, expectedNew: true);
+  test('gvn: false; new: false', expectedGvn: false, expectedNew: false);
 }
diff --git a/tests/compiler/dart2js/minify_many_locals_test.dart b/tests/compiler/dart2js/minify_many_locals_test.dart
index b1379ae..75345a4 100644
--- a/tests/compiler/dart2js/minify_many_locals_test.dart
+++ b/tests/compiler/dart2js/minify_many_locals_test.dart
@@ -7,17 +7,23 @@
 import 'package:expect/expect.dart';
 import 'compiler_helper.dart';
 
+// TODO(johnniwinther): This value is some what arbitrary. With the old
+// [ResolvedVisitor] we could handle 2000, with the new [ResolvedVisitor] build
+// upon the [SemanticVisitor] we can handle <1300. Update (increase) the value
+// when the [SssBuilder] is no longer build upon the [ResolvedVisitor] .
+const int NUMBER_OF_PARAMETERS = 1250;
+
 main() {
   var buffer = new StringBuffer();
   buffer.write("foo(");
-  for (int i = 0; i < 2000; i++) {
+  for (int i = 0; i < NUMBER_OF_PARAMETERS; i++) {
     buffer.write("x$i, ");
   }
   buffer.write("x) { int i = ");
-  for (int i = 0; i < 2000; i++) {
+  for (int i = 0; i < NUMBER_OF_PARAMETERS; i++) {
     buffer.write("x$i+");
   }
-  buffer.write("2000; return i; }");
+  buffer.write("$NUMBER_OF_PARAMETERS; return i; }");
   String code = buffer.toString();
 
   asyncTest(() => compile(code, entry: 'foo', minify: true)
diff --git a/tests/compiler/dart2js/no_such_method_enabled_test.dart b/tests/compiler/dart2js/no_such_method_enabled_test.dart
index c9da1a0..cb994a9 100644
--- a/tests/compiler/dart2js/no_such_method_enabled_test.dart
+++ b/tests/compiler/dart2js/no_such_method_enabled_test.dart
@@ -231,6 +231,57 @@
   }));
 }
 
+dummyImplTest11() {
+  String source = """
+class A {
+  noSuchMethod(Invocation x) {
+    print('foo');
+    throw 'foo';
+  }
+}
+main() {
+  print(new A().foo());
+}
+""";
+  Uri uri = new Uri(scheme: 'source');
+  var compiler = compilerFor(source, uri);
+  asyncTest(() => compiler.runCompiler(uri).then((_) {
+    Expect.isTrue(compiler.backend.enabledNoSuchMethod);
+    ClassElement clsA = findElement(compiler, 'A');
+    Expect.isTrue(
+        compiler.backend.noSuchMethodRegistry.otherImpls.contains(
+            clsA.lookupMember('noSuchMethod')));
+    Expect.isTrue(
+        compiler.backend.noSuchMethodRegistry.complexNoReturnImpls.contains(
+            clsA.lookupMember('noSuchMethod')));
+  }));
+}
+
+dummyImplTest12() {
+  String source = """
+class A {
+  noSuchMethod(Invocation x) {
+    return toString();
+  }
+}
+main() {
+  print(new A().foo());
+}
+""";
+  Uri uri = new Uri(scheme: 'source');
+  var compiler = compilerFor(source, uri);
+  asyncTest(() => compiler.runCompiler(uri).then((_) {
+    Expect.isTrue(compiler.backend.enabledNoSuchMethod);
+    ClassElement clsA = findElement(compiler, 'A');
+    Expect.isTrue(
+        compiler.backend.noSuchMethodRegistry.otherImpls.contains(
+            clsA.lookupMember('noSuchMethod')));
+    Expect.isTrue(
+        compiler.backend.noSuchMethodRegistry.complexReturningImpls.contains(
+            clsA.lookupMember('noSuchMethod')));
+  }));
+}
+
 main() {
   dummyImplTest();
   dummyImplTest2();
@@ -242,4 +293,6 @@
   dummyImplTest8();
   dummyImplTest9();
   dummyImplTest10();
+  dummyImplTest11();
+  dummyImplTest12();
 }
diff --git a/tests/compiler/dart2js/private_test.dart b/tests/compiler/dart2js/private_test.dart
index df4c40a..5121422 100644
--- a/tests/compiler/dart2js/private_test.dart
+++ b/tests/compiler/dart2js/private_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
 import "package:expect/expect.dart";
 import "package:async_helper/async_helper.dart";
 import 'mock_compiler.dart';
@@ -41,127 +42,132 @@
 ''';
 
 
-void analyze(String text, [expectedWarnings]) {
-  if (expectedWarnings == null) expectedWarnings = [];
-  if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
+analyze(String text, [expectedWarnings]) {
+  return () {
+    if (expectedWarnings == null) expectedWarnings = [];
+    if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
 
-  MockCompiler compiler = new MockCompiler.internal(analyzeOnly: true);
-  compiler.registerSource(Uri.parse(PRIVATE_SOURCE_URI), PRIVATE_SOURCE);
-  compiler.diagnosticHandler = (uri, int begin, int end, String message, kind) {
-    SourceFile sourceFile = compiler.sourceFiles[uri.toString()];
-    if (sourceFile != null) {
-      print(sourceFile.getLocationMessage(message, begin, end));
-    } else {
-      print(message);
-    }
+    MockCompiler compiler = new MockCompiler.internal(analyzeOnly: true);
+    compiler.registerSource(Uri.parse(PRIVATE_SOURCE_URI), PRIVATE_SOURCE);
+    compiler.diagnosticHandler =
+        (uri, int begin, int end, String message, kind) {
+      SourceFile sourceFile = compiler.sourceFiles[uri.toString()];
+      if (sourceFile != null) {
+        print(sourceFile.getLocationMessage(message, begin, end));
+      } else {
+        print(message);
+      }
+    };
+
+    String source = '''
+                    library public;
+  
+                    import '$PRIVATE_SOURCE_URI';
+  
+                    void main() {
+                      PublicClass publicClass;
+                      $text
+                    }
+                    ''';
+    Uri uri = Uri.parse('src:public');
+    compiler.registerSource(uri, source);
+    return compiler.runCompiler(uri).then((_) {
+      compareWarningKinds(text, expectedWarnings, compiler.warnings);
+    });
   };
-
-  String source = '''
-                  library public;
-
-                  import '$PRIVATE_SOURCE_URI';
-
-                  void main() {
-                    PublicClass publicClass;
-                    $text
-                  }
-                  ''';
-  Uri uri = Uri.parse('src:public');
-  compiler.registerSource(uri, source);
-  asyncTest(() => compiler.runCompiler(uri).then((_) {
-    compareWarningKinds(text, expectedWarnings, compiler.warnings);
-  }));
 }
 
 void main() {
-  // Read from private variable.
-  analyze('var value = _privateVariable;', MessageKind.CANNOT_RESOLVE);
-  // Write to private variable.
-  analyze('_privateVariable = 0;', MessageKind.CANNOT_RESOLVE);
-  // Access private function.
-  analyze('var value = _privateFunction;', MessageKind.CANNOT_RESOLVE);
-  // Call private function.
-  analyze('_privateFunction();', MessageKind.CANNOT_RESOLVE);
+  asyncTest(() => Future.forEach([
+    // Read from private variable.
+    analyze('var value = _privateVariable;', MessageKind.CANNOT_RESOLVE),
+    // Write to private variable.
+    analyze('_privateVariable = 0;', MessageKind.CANNOT_RESOLVE),
+    // Access private function.
+    analyze('var value = _privateFunction;', MessageKind.CANNOT_RESOLVE),
+    // Call private function.
+    analyze('_privateFunction();', MessageKind.CANNOT_RESOLVE),
 
-  // Call unnamed (public) constructor on private class.
-  analyze('new _PrivateClass();', MessageKind.CANNOT_RESOLVE);
-  // Call public constructor on private class.
-  analyze('new _PrivateClass.publicConstructor();',
-          MessageKind.CANNOT_RESOLVE);
-  // Call private constructor on private class.
-  analyze('new _PrivateClass._privateConstructor();',
-      MessageKind.CANNOT_RESOLVE);
-  // Call public getter of private type.
-  analyze('var value = publicClass.private;');
-  // Read from private field on private class.
-  analyze('var value = publicClass.private._privateField;',
-      MessageKind.PRIVATE_ACCESS);
-  // Write to private field on private class.
-  analyze('publicClass.private._privateField = 0;',
-      MessageKind.PRIVATE_ACCESS);
-  // Call private getter on private class.
-  analyze('var value = publicClass.private._privateGetter;',
-      MessageKind.PRIVATE_ACCESS);
-  // Call private setter on private class.
-  analyze('publicClass.private._privateSetter = 0;',
-      MessageKind.PRIVATE_ACCESS);
-  // Access private method on private class.
-  analyze('var value = publicClass.private._privateMethod;',
-      MessageKind.PRIVATE_ACCESS);
-  // Call private method on private class.
-  analyze('publicClass.private._privateMethod();',
-      MessageKind.PRIVATE_ACCESS);
+    // Call unnamed (public) constructor on private class.
+    analyze('new _PrivateClass();', MessageKind.CANNOT_RESOLVE),
+    // Call public constructor on private class.
+    analyze('new _PrivateClass.publicConstructor();',
+            MessageKind.CANNOT_RESOLVE),
+    // Call private constructor on private class.
+    analyze('new _PrivateClass._privateConstructor();',
+        MessageKind.CANNOT_RESOLVE),
+    // Call public getter of private type.
+    analyze('var value = publicClass.private;'),
+    // Read from private field on private class.
+    analyze('var value = publicClass.private._privateField;',
+        MessageKind.PRIVATE_ACCESS),
+    // Write to private field on private class.
+    analyze('publicClass.private._privateField = 0;',
+        MessageKind.PRIVATE_ACCESS),
+    // Call private getter on private class.
+    analyze('var value = publicClass.private._privateGetter;',
+        MessageKind.PRIVATE_ACCESS),
+    // Call private setter on private class.
+    analyze('publicClass.private._privateSetter = 0;',
+        MessageKind.PRIVATE_ACCESS),
+    // Access private method on private class.
+    analyze('var value = publicClass.private._privateMethod;',
+        MessageKind.PRIVATE_ACCESS),
+    // Call private method on private class.
+    analyze('publicClass.private._privateMethod();',
+        MessageKind.PRIVATE_ACCESS),
 
-  // Read from public field on private class.
-  analyze('var value = publicClass.private.publicField;');
-  // Write to public field on private class.
-  analyze('publicClass.private.publicField = 0;');
-  // Call public getter on private class.
-  analyze('var value = publicClass.private.publicGetter;');
-  // Call public setter on private class.
-  analyze('publicClass.private.publicSetter = 0;');
-  // Access public method on private class.
-  analyze('var value = publicClass.private.publicMethod;');
-  // Call public method on private class.
-  analyze('publicClass.private.publicMethod();');
+    // Read from public field on private class.
+    analyze('var value = publicClass.private.publicField;'),
+    // Write to public field on private class.
+    analyze('publicClass.private.publicField = 0;'),
+    // Call public getter on private class.
+    analyze('var value = publicClass.private.publicGetter;'),
+    // Call public setter on private class.
+    analyze('publicClass.private.publicSetter = 0;'),
+    // Access public method on private class.
+    analyze('var value = publicClass.private.publicMethod;'),
+    // Call public method on private class.
+    analyze('publicClass.private.publicMethod();'),
 
-  // Call unnamed (public) constructor on public class.
-  analyze('publicClass = new PublicClass();');
-  // Call public constructor on public class.
-  analyze('publicClass = new PublicClass.publicConstructor();');
-  // Call private constructor on public class.
-  analyze('publicClass = new PublicClass._privateConstructor();',
-      MessageKind.PRIVATE_ACCESS);
-  // Read from private field on public class.
-  analyze('var value = publicClass._privateField;',
-      MessageKind.PRIVATE_ACCESS);
-  // Write to private field on public class.
-  analyze('publicClass._privateField = 0;',
-      MessageKind.PRIVATE_ACCESS);
-  // Call private getter on public class.
-  analyze('var value = publicClass._privateGetter;',
-      MessageKind.PRIVATE_ACCESS);
-  // Call private setter on public class.
-  analyze('publicClass._privateSetter = 0;',
-      MessageKind.PRIVATE_ACCESS);
-  // Access private method on public class.
-  analyze('var value = publicClass._privateMethod;',
-      MessageKind.PRIVATE_ACCESS);
-  // Call private method on public class.
-  analyze('publicClass._privateMethod();',
-      MessageKind.PRIVATE_ACCESS);
+    // Call unnamed (public) constructor on public class.
+    analyze('publicClass = new PublicClass();'),
+    // Call public constructor on public class.
+    analyze('publicClass = new PublicClass.publicConstructor();'),
+    // Call private constructor on public class.
+    analyze('publicClass = new PublicClass._privateConstructor();',
+        MessageKind.CANNOT_FIND_CONSTRUCTOR),
+    // Read from private field on public class.
+    analyze('var value = publicClass._privateField;',
+        MessageKind.PRIVATE_ACCESS),
+    // Write to private field on public class.
+    analyze('publicClass._privateField = 0;',
+        MessageKind.PRIVATE_ACCESS),
+    // Call private getter on public class.
+    analyze('var value = publicClass._privateGetter;',
+        MessageKind.PRIVATE_ACCESS),
+    // Call private setter on public class.
+    analyze('publicClass._privateSetter = 0;',
+        MessageKind.PRIVATE_ACCESS),
+    // Access private method on public class.
+    analyze('var value = publicClass._privateMethod;',
+        MessageKind.PRIVATE_ACCESS),
+    // Call private method on public class.
+    analyze('publicClass._privateMethod();',
+        MessageKind.PRIVATE_ACCESS),
 
-  // Read from public field on public class.
-  analyze('var value = publicClass.publicField;');
-  // Write to public field on public class.
-  analyze('publicClass.publicField = 0;');
-  // Call public getter on public class.
-  analyze('var value = publicClass.publicGetter;');
-  // Call public setter on public class.
-  analyze('publicClass.publicSetter = 0;');
-  // Access public method on public class.
-  analyze('var value = publicClass.publicMethod;');
-  // Call public method on public class.
-  analyze('publicClass.publicMethod();');
+    // Read from public field on public class.
+    analyze('var value = publicClass.publicField;'),
+    // Write to public field on public class.
+    analyze('publicClass.publicField = 0;'),
+    // Call public getter on public class.
+    analyze('var value = publicClass.publicGetter;'),
+    // Call public setter on public class.
+    analyze('publicClass.publicSetter = 0;'),
+    // Access public method on public class.
+    analyze('var value = publicClass.publicMethod;'),
+    // Call public method on public class.
+    analyze('publicClass.publicMethod();'),
+  ], (f) => f()));
 }
 
diff --git a/tests/compiler/dart2js/semantic_visitor_test.dart b/tests/compiler/dart2js/semantic_visitor_test.dart
index fea44dc..cdacd2c 100644
--- a/tests/compiler/dart2js/semantic_visitor_test.dart
+++ b/tests/compiler/dart2js/semantic_visitor_test.dart
@@ -4,6 +4,7 @@
 

 library dart2js.semantics_visitor_test;

 

+import 'dart:async';

 import 'package:async_helper/async_helper.dart';

 import 'package:expect/expect.dart';

 import 'package:compiler/src/constants/expressions.dart';

@@ -34,6 +35,11 @@
   final setter;

   final constant;

   final selector;

+  final parameters;

+  final body;

+  final target;

+  final targetType;

+  final initializers;

 

   const Visit(this.method,

               {this.element,

@@ -50,7 +56,12 @@
                this.getter,

                this.setter,

                this.constant,

-               this.selector});

+               this.selector,

+               this.parameters,

+               this.body,

+               this.target,

+               this.targetType,

+               this.initializers});

 

   int get hashCode => toString().hashCode;

 

@@ -104,6 +115,21 @@
     if (selector != null) {

       sb.write(',selector=$selector');

     }

+    if (parameters != null) {

+      sb.write(',parameters=$parameters');

+    }

+    if (body != null) {

+      sb.write(',body=$body');

+    }

+    if (target != null) {

+      sb.write(',target=$target');

+    }

+    if (targetType != null) {

+      sb.write(',targetType=$targetType');

+    }

+    if (initializers != null) {

+      sb.write(',initializers=$initializers');

+    }

     return sb.toString();

   }

 }

@@ -113,15 +139,15 @@
   final String code;

   final /*Visit | List<Visit>*/ expectedVisits;

   final String cls;

+  final String method;

 

   const Test(this.code, this.expectedVisits)

-      : cls = null, codeByPrefix = null;

-  const Test.clazz(this.code, this.expectedVisits)

-      : cls = 'C', codeByPrefix = null;

+      : cls = null, method = 'm', codeByPrefix = null;

+  const Test.clazz(this.code, this.expectedVisits,

+                   {this.cls: 'C', this.method: 'm'})

+      : codeByPrefix = null;

   const Test.prefix(this.codeByPrefix, this.code, this.expectedVisits)

-      : cls = null;

-

-  String get method => 'm';

+      : cls = null, method = 'm';

 

   String toString() {

     StringBuffer sb = new StringBuffer();

@@ -135,7 +161,8 @@
   }

 }

 

-const List<Test> TESTS = const [

+const Map<String, List<Test>> SEND_TESTS = const {

+  'Parameters': const [

     // Parameters

     const Test('m(o) => o;',

         const Visit(VisitKind.VISIT_PARAMETER_GET,

@@ -149,7 +176,8 @@
                     element: 'parameter(m#o)',

                     arguments: '(null,42)',

                     selector: 'Selector(call, call, arity=2)')),

-

+  ],

+  'Local variables': const [

     // Local variables

     const Test('m() { var o; return o; }',

         const Visit(VisitKind.VISIT_LOCAL_VARIABLE_GET,

@@ -163,7 +191,8 @@
                     element: 'variable(m#o)',

                     arguments: '(null,42)',

                     selector: 'Selector(call, call, arity=2)')),

-

+  ],

+  'Local functions': const [

     // Local functions

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

         const Visit(VisitKind.VISIT_LOCAL_FUNCTION_GET,

@@ -173,7 +202,8 @@
                     element: 'function(m#o)',

                     arguments: '(null,42)',

                     selector: 'Selector(call, call, arity=2)')),

-

+  ],

+  'Static fields': const [

     // Static fields

     const Test(

         '''

@@ -285,7 +315,8 @@
         const Visit(VisitKind.VISIT_STATIC_FIELD_INVOKE,

                     element: 'field(C#o)',

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

-

+  ],

+  'Static properties': const [

     // Static properties

     const Test(

         '''

@@ -399,7 +430,8 @@
         const Visit(VisitKind.VISIT_STATIC_GETTER_INVOKE,

                     element: 'getter(C#o)',

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

-

+  ],

+  'Static functions': const [

     // Static functions

     const Test(

         '''

@@ -473,7 +505,8 @@
         const Visit(VisitKind.VISIT_STATIC_FUNCTION_INVOKE,

                     element: 'function(C#o)',

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

-

+  ],

+  'Top level fields': const [

     // Top level fields

     const Test(

         '''

@@ -521,7 +554,8 @@
         const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_INVOKE,

                     element: 'field(o)',

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

-

+  ],

+  'Top level properties': const [

     // Top level properties

     const Test(

         '''

@@ -571,7 +605,8 @@
         const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_INVOKE,

                     element: 'getter(o)',

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

-

+  ],

+  'Top level functions': const [

     // Top level functions

     const Test(

         '''

@@ -596,23 +631,37 @@
         const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_INVOKE,

                     element: 'function(o)',

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

-

+  ],

+  'Dynamic properties': const [

     // Dynamic properties

     const Test('m(o) => o.foo;',

-        const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_GET,

-                    receiver: 'o',

-                    name: 'foo')),

+        const [

+          const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_GET,

+                      receiver: 'o',

+                      name: 'foo'),

+          const Visit(VisitKind.VISIT_PARAMETER_GET,

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

+        ]),

     const Test('m(o) { o.foo = 42; }',

-        const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_SET,

-                    receiver: 'o',

-                    name: 'foo',

-                    rhs: '42')),

+        const [

+          const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_SET,

+                      receiver: 'o',

+                      name: 'foo',

+                      rhs: '42'),

+          const Visit(VisitKind.VISIT_PARAMETER_GET,

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

+        ]),

     const Test('m(o) { o.foo(null, 42); }',

-        const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_INVOKE,

-                    receiver: 'o',

-                    name: 'foo',

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

-

+        const [

+          const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_INVOKE,

+                      receiver: 'o',

+                      name: 'foo',

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

+          const Visit(VisitKind.VISIT_PARAMETER_GET,

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

+        ]),

+  ],

+  'This access': const [

     // This access

     const Test.clazz(

         '''

@@ -630,7 +679,8 @@
         ''',

         const Visit(VisitKind.VISIT_THIS_INVOKE,

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

-

+  ],

+  'This properties': const [

     // This properties

     const Test.clazz(

         '''

@@ -728,7 +778,8 @@
         const Visit(VisitKind.VISIT_THIS_PROPERTY_INVOKE,

                     name: 'foo',

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

-

+  ],

+  'Super fields': const [

     // Super fields

     const Test.clazz(

         '''

@@ -765,7 +816,8 @@
         const Visit(VisitKind.VISIT_SUPER_FIELD_INVOKE,

                     element: 'field(B#o)',

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

-

+  ],

+  'Super properties': const [

     // Super properties

     const Test.clazz(

         '''

@@ -802,7 +854,8 @@
         const Visit(VisitKind.VISIT_SUPER_GETTER_INVOKE,

                     element: 'getter(B#o)',

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

-

+  ],

+  'Super methods': const [

     // Super methods

     const Test.clazz(

         '''

@@ -827,13 +880,15 @@
         const Visit(VisitKind.VISIT_SUPER_METHOD_INVOKE,

                     element: 'function(B#o)',

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

-

+  ],

+  'Expression invoke': const [

     // Expression invoke

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

         const Visit(VisitKind.VISIT_EXPRESSION_INVOKE,

                     receiver: '(a,b){}',

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

-

+  ],

+  'Class type literals': const [

     // Class type literals

     const Test(

         '''

@@ -850,7 +905,8 @@
         const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_INVOKE,

                     constant: 'C',

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

-

+  ],

+  'Typedef type literals': const [

     // Typedef type literals

     const Test(

         '''

@@ -867,7 +923,8 @@
         const Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_INVOKE,

                     constant: 'F',

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

-

+  ],

+  'Type variable type literals': const [

     // Type variable type literals

     const Test.clazz(

         '''

@@ -887,6 +944,8 @@
                     element: 'type_variable(C#T)',

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

 

+  ],

+  'Dynamic type literals': const [

     // Dynamic type literals

     const Test(

         '''

@@ -903,28 +962,32 @@
         const Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_INVOKE,

                     constant: 'dynamic',

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

-

+  ],

+  'Assert': const [

     // Assert

     const Test(

         '''

         m() { assert(false); }

         ''',

         const Visit(VisitKind.VISIT_ASSERT, expression: 'false')),

-

+  ],

+  'Logical and': const [

     // Logical and

     const Test(

         '''

         m() => true && false;

         ''',

         const Visit(VisitKind.VISIT_LOGICAL_AND, left: 'true', right: 'false')),

-

+  ],

+  'Logical or': const [

     // Logical or

     const Test(

         '''

         m() => true || false;

         ''',

         const Visit(VisitKind.VISIT_LOGICAL_OR, left: 'true', right: 'false')),

-

+  ],

+  'Is test': const [

     // Is test

     const Test(

         '''

@@ -932,7 +995,8 @@
         m() => 0 is C;

         ''',

         const Visit(VisitKind.VISIT_IS, expression: '0', type: 'C')),

-

+  ],

+  'Is not test': const [

     // Is not test

     const Test(

         '''

@@ -940,15 +1004,17 @@
         m() => 0 is! C;

         ''',

         const Visit(VisitKind.VISIT_IS_NOT, expression: '0', type: 'C')),

-

-    // Is test

+  ],

+  'As test': const [

+    // As test

     const Test(

         '''

         class C {}

         m() => 0 as C;

         ''',

         const Visit(VisitKind.VISIT_AS, expression: '0', type: 'C')),

-

+  ],

+  'Binary operators': const [

     // Binary operators

     const Test(

         '''

@@ -1053,6 +1119,8 @@
                     element: 'function(B#+)',

                     operator: '+',

                     right: '42')),

+  ],

+  'Index': const [

     // Index

     const Test(

         '''

@@ -1114,7 +1182,8 @@
                     setter: 'function(B#[]=)',

                     index: '42',

                     operator: '--')),

-

+  ],

+  'Equals': const [

     // Equals

     const Test(

         '''

@@ -1134,7 +1203,8 @@
         const Visit(VisitKind.VISIT_SUPER_EQUALS,

                     element: 'function(B#==)',

                     right: '42')),

-

+  ],

+  'Not equals': const [

     // Not equals

     const Test(

         '''

@@ -1155,7 +1225,8 @@
         const Visit(VisitKind.VISIT_SUPER_NOT_EQUALS,

                     element: 'function(B#==)',

                     right: '42')),*/

-

+  ],

+  'Unary expression': const [

     // Unary expression

     const Test(

         '''

@@ -1196,7 +1267,8 @@
         m() => !0;

         ''',

         const Visit(VisitKind.VISIT_NOT, expression: '0')),

-

+  ],

+  'Index set': const [

     // Index set

     const Test(

         '''

@@ -1215,7 +1287,8 @@
         ''',

         const Visit(VisitKind.VISIT_SUPER_INDEX_SET,

             element: 'function(B#[]=)', index: '1', rhs: '2')),

-

+  ],

+  'Compound assignment': const [

     // Compound assignment

     const Test(

         '''

@@ -1533,7 +1606,8 @@
         const Visit(VisitKind.VISIT_SUPER_FIELD_FIELD_COMPOUND,

             getter: 'field(B#a)', setter: 'field(A#a)',

             operator: '+=', rhs: '42')),*/

-

+  ],

+  'Compound index assignment': const [

     // Compound index assignment

     const Test(

         '''

@@ -1555,7 +1629,8 @@
         const Visit(VisitKind.VISIT_SUPER_COMPOUND_INDEX_SET,

             getter: 'function(B#[])', setter: 'function(B#[]=)',

             index: '1', operator: '+=', rhs: '42')),*/

-

+  ],

+  'Prefix expression': const [

     // Prefix expression

     const Test(

         '''

@@ -1777,8 +1852,9 @@
         const Visit(VisitKind.VISIT_SUPER_FIELD_SETTER_PREFIX,

             getter: 'field(A#a)', setter: 'setter(B#a)',

             operator: '++')),

-

-    // Prefix expression

+  ],

+  'Postfix expression': const [

+    // Postfix expression

     const Test(

         '''

         m(a) => a.b--;

@@ -1999,79 +2075,266 @@
         const Visit(VisitKind.VISIT_SUPER_FIELD_SETTER_POSTFIX,

             getter: 'field(A#a)', setter: 'setter(B#a)',

             operator: '++')),

+  ],

+  'Constructor invocations': const [

+    const Test(

+        '''

+        class Class {

+          const Class(a, b);

+        }

+        m() => const Class(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_CONST_CONSTRUCTOR_INVOKE,

+            constant: 'const Class(true, 42)')),

+    const Test(

+        '''

+        class Class {}

+        m() => new Class();

+        ''',

+        const Visit(VisitKind.VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,

+            element: 'generative_constructor(Class#)',

+            arguments: '()',

+            type: 'Class',

+            selector: 'Selector(call, , arity=0)')),

+    const Test(

+        '''

+        class Class {

+          Class(a, b);

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,

+            element: 'generative_constructor(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'Selector(call, , arity=2)')),

+    const Test(

+        '''

+        class Class {

+          Class.named(a, b);

+        }

+        m() => new Class.named(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,

+            element: 'generative_constructor(Class#named)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'Selector(call, named, arity=2)')),

+    const Test(

+        '''

+        class Class {

+          Class(a, b) : this._(a, b);

+          Class._(a, b);

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_REDIRECTING_GENERATIVE_CONSTRUCTOR_INVOKE,

+            element: 'generative_constructor(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'Selector(call, , arity=2)')),

+    const Test(

+        '''

+        class Class {

+          factory Class(a, b) => new Class._(a, b);

+          Class._(a, b);

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'Selector(call, , arity=2)')),

+    const Test(

+        '''

+        class Class<T> {

+          factory Class(a, b) = Class<int>.a;

+          factory Class.a(a, b) = Class<Class<T>>.b;

+          Class.b(a, b);

+        }

+        m() => new Class<double>(true, 42);

+        ''',

+        const Visit(VisitKind.VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class<double>',

+            target: 'generative_constructor(Class#b)',

+            targetType: 'Class<Class<int>>',

+            selector: 'Selector(call, , arity=2)')),

+    const Test(

+        '''

+        class Class {

+          Class(a, b);

+        }

+        m() => new Class.unresolved(true, 42);

+        ''',

+        const Visit(

+            VisitKind.ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,

+            arguments: '(true,42)')),

+    const Test(

+        '''

+        m() => new Unresolved(true, 42);

+        ''',

+        const Visit(

+            // TODO(johnniwinther): Update this to

+            // `VisitKind.ERROR_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE`.

+            VisitKind.ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,

+            arguments: '(true,42)')),

+    const Test(

+        '''

+        abstract class AbstractClass {}

+        m() => new AbstractClass();

+        ''',

+        const Visit(

+            VisitKind.ERROR_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,

+            element: 'generative_constructor(AbstractClass#)',

+            type: 'AbstractClass',

+            arguments: '()',

+            selector: 'Selector(call, , arity=0)')),

+    const Test(

+        '''

+        class Class {

+          factory Class(a, b) = Unresolved;

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(

+            VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'Selector(call, , arity=2)')),

+    const Test(

+        '''

+        class Class {

+          factory Class(a, b) = Class.named;

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(

+            VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'Selector(call, , arity=2)')),

+    const Test(

+        '''

+        class Class {

+          factory Class(a, b) = Class.named;

+          factory Class.named(a, b) = Class.unresolved;

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(

+            VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'Selector(call, , arity=2)')),

+    const Test(

+        '''

+        abstract class AbstractClass {

+          AbstractClass(a, b);

+        }

+        class Class {

+          factory Class(a, b) = AbstractClass;

+        }

+        m() => new Class(true, 42);

+        ''',

+        const Visit(

+            VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+            element: 'function(Class#)',

+            arguments: '(true,42)',

+            type: 'Class',

+            selector: 'Selector(call, , arity=2)')),

+  ],

+};

 

-];

+main(List<String> arguments) {

+  asyncTest(() => Future.forEach([

+    () {

+      return test(

+          arguments,

+          SEND_TESTS,

+          (elements) => new SemanticSendTestVisitor(elements));

+    },

+  ], (f) => f()));

+}

 

-main() {

+Future test(List<String> arguments,

+            Map<String, List<Test>> TESTS,

+            SemanticTestVisitor createVisitor(TreeElements elements)) {

   Map<String, String> sourceFiles = {};

   Map<String, Test> testMap = {};

   StringBuffer mainSource = new StringBuffer();

   int index = 0;

-  TESTS.forEach((Test test) {

-    StringBuffer testSource = new StringBuffer();

-    if (test.codeByPrefix != null) {

-      String prefixFilename = 'pre$index.dart';

-      sourceFiles[prefixFilename] = test.codeByPrefix;

-      testSource.writeln("import '$prefixFilename' as p;");

-    }

+  TESTS.forEach((String group, List<Test> tests) {

+    if (arguments.isNotEmpty && !arguments.contains(group)) return;

 

-    String filename = 'lib$index.dart';

-    testSource.writeln(test.code);

-    sourceFiles[filename] = testSource.toString();

-    mainSource.writeln("import '$filename';");

-    testMap[filename] = test;

-    index++;

+    tests.forEach((Test test) {

+      StringBuffer testSource = new StringBuffer();

+      if (test.codeByPrefix != null) {

+        String prefixFilename = 'pre$index.dart';

+        sourceFiles[prefixFilename] = test.codeByPrefix;

+        testSource.writeln("import '$prefixFilename' as p;");

+      }

+

+      String filename = 'lib$index.dart';

+      testSource.writeln(test.code);

+      sourceFiles[filename] = testSource.toString();

+      mainSource.writeln("import '$filename';");

+      testMap[filename] = test;

+      index++;

+    });

   });

   mainSource.writeln("main() {}");

   sourceFiles['main.dart'] = mainSource.toString();

 

-  asyncTest(() {

-    Compiler compiler = compilerFor(sourceFiles,

-        options: ['--analyze-all', '--analyze-only']);

-    return compiler.run(Uri.parse('memory:main.dart')).then((_) {

-      testMap.forEach((String filename, Test test) {

-        LibraryElement library = compiler.libraryLoader.lookupLibrary(

-            Uri.parse('memory:$filename'));

-        var expectedVisits = test.expectedVisits;

-        if (expectedVisits is! List) {

-          expectedVisits = [expectedVisits];

-        }

-        AstElement element;

-        String cls = test.cls;

-        String method = test.method;

-        if (cls == null) {

-          element = library.find(method);

-        } else {

-          ClassElement classElement = library.find(cls);

-          Expect.isNotNull(classElement,

-                           "Class '$cls' not found in:\n"

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

-          element = classElement.localLookup(method);

-        }

-        Expect.isNotNull(element, "Element '$method' not found in:\n"

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

-        ResolvedAst resolvedAst = element.resolvedAst;

-        SemanticTestVisitor visitor =

-            new SemanticTestVisitor(resolvedAst.elements);

-        try {

-          compiler.withCurrentElement(resolvedAst.element, () {

-            //print(resolvedAst.node.toDebugString());

-            resolvedAst.node.accept(visitor);

-          });

-        } catch (e, s) {

-          Expect.fail("$e:\n$s\nIn test:\n"

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

-        }

-        Expect.listEquals(expectedVisits, visitor.visits,

-            "In test:\n"

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

-      });

+  Compiler compiler = compilerFor(sourceFiles,

+      options: ['--analyze-all', '--analyze-only']);

+  return compiler.run(Uri.parse('memory:main.dart')).then((_) {

+    testMap.forEach((String filename, Test test) {

+      LibraryElement library = compiler.libraryLoader.lookupLibrary(

+          Uri.parse('memory:$filename'));

+      var expectedVisits = test.expectedVisits;

+      if (expectedVisits is! List) {

+        expectedVisits = [expectedVisits];

+      }

+      AstElement element;

+      String cls = test.cls;

+      String method = test.method;

+      if (cls == null) {

+        element = library.find(method);

+      } else {

+        ClassElement classElement = library.find(cls);

+        Expect.isNotNull(classElement,

+                         "Class '$cls' not found in:\n"

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

+        element = classElement.localLookup(method);

+      }

+      Expect.isNotNull(element, "Element '$method' not found in:\n"

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

+      ResolvedAst resolvedAst = element.resolvedAst;

+      SemanticTestVisitor visitor = createVisitor(resolvedAst.elements);

+      try {

+        compiler.withCurrentElement(resolvedAst.element, () {

+          //print(resolvedAst.node.toDebugString());

+          resolvedAst.node.accept(visitor);

+        });

+      } catch (e, s) {

+        Expect.fail("$e:\n$s\nIn test:\n"

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

+      }

+      Expect.listEquals(expectedVisits, visitor.visits,

+          "In test:\n"

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

     });

   });

 }

 

 

-class SemanticTestVisitor extends SemanticVisitor with SemanticSendVisitor {

+abstract class SemanticTestVisitor extends TraversalVisitor {

   List<Visit> visits = <Visit>[];

 

   SemanticTestVisitor(TreeElements elements) : super(elements);

@@ -2081,13 +2344,11 @@
   internalError(Spannable spannable, String message) {

     throw new SpannableAssertionFailure(spannable, message);

   }

+}

 

-  SemanticSendVisitor get sendVisitor => this;

+class SemanticSendTestVisitor extends SemanticTestVisitor {

 

-  @override

-  visitNode(Node node) {

-    node.visitChildren(this);

-  }

+  SemanticSendTestVisitor(TreeElements elements) : super(elements);

 

   @override

   visitAs(

@@ -2145,7 +2406,7 @@
   @override

   visitClassTypeLiteralGet(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       arg) {

     visits.add(new Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_GET,

         constant: constant.getText()));

@@ -2154,7 +2415,7 @@
   @override

   visitClassTypeLiteralInvoke(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       NodeList arguments,

       Selector selector,

       arg) {

@@ -2166,7 +2427,7 @@
   @override

   errorClassTypeLiteralSet(

       SendSet node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       Node rhs,

       arg) {

     visits.add(new Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_INVOKE,

@@ -2222,6 +2483,7 @@
       arg) {

     visits.add(new Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_GET,

         receiver: receiver, name: selector.name));

+    apply(receiver, arg);

   }

 

   @override

@@ -2233,6 +2495,7 @@
       arg) {

     visits.add(new Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_INVOKE,

         receiver: receiver, name: selector.name, arguments: arguments));

+    apply(receiver, arg);

     apply(arguments, arg);

   }

 

@@ -2245,12 +2508,13 @@
       arg) {

     visits.add(new Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_SET,

         receiver: receiver, name: selector.name, rhs: rhs));

+    apply(receiver, arg);

   }

 

   @override

   visitDynamicTypeLiteralGet(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       arg) {

     visits.add(new Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_GET,

         constant: constant.getText()));

@@ -2259,7 +2523,7 @@
   @override

   visitDynamicTypeLiteralInvoke(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       NodeList arguments,

       Selector selector,

       arg) {

@@ -2270,7 +2534,7 @@
   @override

   errorDynamicTypeLiteralSet(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       Node rhs,

       arg) {

     visits.add(new Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_SET,

@@ -2702,7 +2966,7 @@
   @override

   visitTypedefTypeLiteralGet(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       arg) {

     visits.add(new Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_GET,

         constant: constant.getText()));

@@ -2711,7 +2975,7 @@
   @override

   visitTypedefTypeLiteralInvoke(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       NodeList arguments,

       Selector selector,

       arg) {

@@ -2723,7 +2987,7 @@
   @override

   errorTypedefTypeLiteralSet(

       SendSet node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       Node rhs,

       arg) {

     visits.add(new Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_SET,

@@ -3344,7 +3608,7 @@
   @override

   errorClassTypeLiteralCompound(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       AssignmentOperator operator,

       Node rhs,

       arg) {

@@ -3356,7 +3620,7 @@
   @override

   errorDynamicTypeLiteralCompound(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       AssignmentOperator operator,

       Node rhs,

       arg) {

@@ -3380,7 +3644,7 @@
   @override

   errorTypedefTypeLiteralCompound(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       AssignmentOperator operator,

       Node rhs,

       arg) {

@@ -3401,7 +3665,7 @@
   @override

   errorClassTypeLiteralPrefix(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       IncDecOperator operator,

       arg) {

     visits.add(new Visit(VisitKind.ERROR_CLASS_TYPE_LITERAL_PREFIX,

@@ -3411,7 +3675,7 @@
   @override

   errorDynamicTypeLiteralPrefix(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       IncDecOperator operator,

       arg) {

     visits.add(new Visit(VisitKind.ERROR_DYNAMIC_TYPE_LITERAL_PREFIX,

@@ -3588,7 +3852,7 @@
   @override

   errorTypedefTypeLiteralPrefix(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       IncDecOperator operator,

       arg) {

     visits.add(new Visit(VisitKind.ERROR_TYPEDEF_TYPE_LITERAL_PREFIX,

@@ -3607,7 +3871,7 @@
   @override

   errorClassTypeLiteralPostfix(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       IncDecOperator operator,

       arg) {

     visits.add(new Visit(VisitKind.ERROR_CLASS_TYPE_LITERAL_POSTFIX,

@@ -3617,7 +3881,7 @@
   @override

   errorDynamicTypeLiteralPostfix(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       IncDecOperator operator,

       arg) {

     visits.add(new Visit(VisitKind.ERROR_DYNAMIC_TYPE_LITERAL_POSTFIX,

@@ -3794,7 +4058,7 @@
   @override

   errorTypedefTypeLiteralPostfix(

       Send node,

-      TypeConstantExpression constant,

+      ConstantExpression constant,

       IncDecOperator operator,

       arg) {

     visits.add(new Visit(VisitKind.ERROR_TYPEDEF_TYPE_LITERAL_POSTFIX,

@@ -4015,6 +4279,151 @@
         index: index, operator: operator));

     apply(index, arg);

   }

+

+  @override

+  errorUnresolvedClassConstructorInvoke(

+      NewExpression node,

+      Element constructor,

+      MalformedType type,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    // TODO(johnniwinther): Test [type] and [selector].

+    visits.add(new Visit(

+        VisitKind.ERROR_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,

+        arguments: arguments));

+    apply(arguments, arg);

+  }

+

+  @override

+  errorUnresolvedConstructorInvoke(

+      NewExpression node,

+      Element constructor,

+      DartType type,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    // TODO(johnniwinther): Test [type] and [selector].

+    visits.add(new Visit(

+        VisitKind.ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,

+        arguments: arguments));

+    apply(arguments, arg);

+  }

+

+  @override

+  visitConstConstructorInvoke(

+      NewExpression node,

+      ConstructedConstantExpression constant,

+      arg) {

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

+                         constant: constant.getText()));

+  }

+

+  @override

+  visitFactoryConstructorInvoke(

+      NewExpression node,

+      ConstructorElement constructor,

+      InterfaceType type,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.VISIT_FACTORY_CONSTRUCTOR_INVOKE,

+        element: constructor,

+        type: type,

+        arguments: arguments,

+        selector: selector));

+    apply(arguments, arg);

+  }

+

+  @override

+  visitGenerativeConstructorInvoke(

+      NewExpression node,

+      ConstructorElement constructor,

+      InterfaceType type,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,

+        element: constructor,

+        type: type,

+        arguments: arguments,

+        selector: selector));

+    apply(arguments, arg);

+  }

+

+  @override

+  visitRedirectingFactoryConstructorInvoke(

+      NewExpression node,

+      ConstructorElement constructor,

+      InterfaceType type,

+      ConstructorElement effectiveTarget,

+      InterfaceType effectiveTargetType,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+        element: constructor,

+        type: type,

+        target: effectiveTarget,

+        targetType: effectiveTargetType,

+        arguments: arguments,

+        selector: selector));

+    apply(arguments, arg);

+  }

+

+  @override

+  visitRedirectingGenerativeConstructorInvoke(

+      NewExpression node,

+      ConstructorElement constructor,

+      InterfaceType type,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.VISIT_REDIRECTING_GENERATIVE_CONSTRUCTOR_INVOKE,

+        element: constructor,

+        type: type,

+        arguments: arguments,

+        selector: selector));

+    apply(arguments, arg);

+  }

+

+  @override

+  errorAbstractClassConstructorInvoke(

+      NewExpression node,

+      ConstructorElement constructor,

+      InterfaceType type,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.ERROR_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,

+        element: constructor,

+        type: type,

+        arguments: arguments,

+        selector: selector));

+    apply(arguments, arg);

+  }

+

+  @override

+  errorUnresolvedRedirectingFactoryConstructorInvoke(

+      NewExpression node,

+      ConstructorElement constructor,

+      InterfaceType type,

+      NodeList arguments,

+      Selector selector,

+      arg) {

+    visits.add(new Visit(

+        VisitKind.ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+        element: constructor,

+        type: type,

+        arguments: arguments,

+        selector: selector));

+    apply(arguments, arg);

+  }

 }

 

 enum VisitKind {

@@ -4174,5 +4583,16 @@
   VISIT_IS_NOT,

   VISIT_AS,

 

+  VISIT_CONST_CONSTRUCTOR_INVOKE,

+  VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,

+  VISIT_REDIRECTING_GENERATIVE_CONSTRUCTOR_INVOKE,

+  VISIT_FACTORY_CONSTRUCTOR_INVOKE,

+  VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+

+  ERROR_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,

+  ERROR_UNRESOLVED_CONSTRUCTOR_INVOKE,

+  ERROR_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,

+  ERROR_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,

+

   // TODO(johnniwinther): Add tests for error cases.

 }

diff --git a/tests/compiler/dart2js_extra/23056_test.dart b/tests/compiler/dart2js_extra/23056_test.dart
new file mode 100644
index 0000000..c8953f2
--- /dev/null
+++ b/tests/compiler/dart2js_extra/23056_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.
+
+// Regression test for http://dartbug.com/23056/
+// Ensure that Mixin prototypes are initialized before first use.
+
+// Mirrors is the only way to have a getter be equipped with metadata.
+@MirrorsUsed(targets: 'M', override: '*')
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+class M {
+  @NoInline()
+  bool get foo => true;
+}
+
+class A extends Object with M {
+  @NoInline()
+  bool get foo => super.foo;
+}
+
+@AssumeDynamic() @NoInline()
+bool hide(bool x) => x;
+
+main() {
+  Expect.isTrue((hide(true) ? new A() : new M()).foo);
+}
diff --git a/tests/compiler/dart2js_native/native_field_optimization_test.dart b/tests/compiler/dart2js_native/native_field_optimization_test.dart
new file mode 100644
index 0000000..405dccc
--- /dev/null
+++ b/tests/compiler/dart2js_native/native_field_optimization_test.dart
@@ -0,0 +1,93 @@
+// 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:_js_helper";
+import "package:expect/expect.dart";
+
+// Test that compiler is cautious with optimizations on native fields.  The
+// motivation is that DOM properties are getters and setters with arbitrary
+// effects.  Setting CSSStyleDeclaration.borderLeft can canonicalize the value
+// and changes the value of CSSStyleDeclaration.border.
+
+@Native("Foo")
+class Foo {
+  var a;
+  var b;
+  var ab;
+}
+
+Foo makeFoo() native;
+
+void setup() native """
+function Foo() { this.i = 0; }
+
+Object.defineProperty(Foo.prototype, 'a', {
+  get: function () { return (this._a || '') + ++this.i; },
+  set: function (v) { this._a = v.toLowerCase(); }
+});
+
+Object.defineProperty(Foo.prototype, 'b', {
+  get: function () { return this._b || ''; },
+  set: function (v) { this._b = v.toLowerCase(); }
+});
+
+Object.defineProperty(Foo.prototype, 'ab', {
+  get: function () { return this.a + ' ' + this.b; },
+  set: function (v) {
+    var s = v.split(' ');
+    this.a = s[0];
+    this.b = s[1];
+  }
+});
+
+makeFoo = function() { return new Foo() }
+""";
+
+
+test1() {
+  var f = makeFoo();
+  f.a = 'Hi';
+  f.b = 'There';
+  Expect.equals('hi1 there', f.ab);
+}
+
+test2() {
+  // Test for CSE. dart2js currently does CSE loads. Is this the right choice?
+  var f = makeFoo();
+  var a1 = f.a;
+  var b1 = f.b;
+  var a2 = f.a;
+  Expect.equals('1', a1);
+  if (a2 == a1) {
+    // We did CSE.
+  } else {
+    Expect.equals('2', a2);
+  }
+}
+
+test3() {
+  // Must not CSE over a native field store.
+  var f = makeFoo();
+  var a1 = f.a;
+  f.ab = 'X Y';
+  var a2 = f.a;
+  Expect.equals('1', a1);
+  Expect.equals('x2', a2);
+}
+
+test4() {
+  // Must not store-forward.
+  var f = makeFoo();
+  f.a = 'A';
+  var a2 = f.a;
+  Expect.equals('a1', a2);
+}
+
+main() {
+  setup();
+  (test1)();
+  (test2)();
+  (test3)();
+  (test4)();
+}
diff --git a/tests/corelib/uri_parse_test.dart b/tests/corelib/uri_parse_test.dart
index 2a0c980..1e9ceb7 100644
--- a/tests/corelib/uri_parse_test.dart
+++ b/tests/corelib/uri_parse_test.dart
@@ -9,37 +9,48 @@
   var schemes = ["", "file", "ws", "ftp"];
   var fragments = ["", "#", "#f", "#fragment", "#l:?/"];
   var queries = ["", "?", "?q", "?query", "?q:/"];
-  var paths = ["/", "/x", "/x/y", "/x/y/", "/x:y"];
+  var paths = ["/", "/x", "/x/y", "/x/y/", "/x:y", "x", "x/y", "x/y/"];
   var userInfos = ["", "x", "xxx", "x:4", "xxx:444", "x:4:x"];
   var hosts = ["", "h", "hhh", "h:4", "hhh:444", "[::1.2.3.4]"];
 
   void check(uriString, scheme, fragment, query, path, user, host) {
-    var uri = Uri.parse(uriString);
-    Expect.equals(scheme, uri.scheme);
-    var uriFragment = uri.fragment;
-    if (fragment.startsWith('#')) uriFragment = "#$uriFragment";
-    Expect.equals(fragment, uriFragment);
-    var uriQuery = uri.query;
-    if (query.startsWith('?')) uriQuery = "?$uriQuery";
-    Expect.equals(query, uriQuery);
-    Expect.equals(path, uri.path);
-    Expect.equals(user, uri.userInfo);
-    var uriHost = uri.host;
-    if (host.startsWith("[")) uriHost = "[$uriHost]";
-    if (uri.port != 0) uriHost += ":${uri.port}";
-    Expect.equals(host, uriHost);
+    for (var uri in [Uri.parse(uriString),
+                     Uri.parse(">\u{10000}>$uriString<\u{10000}<",
+                               4, uriString.length + 4),
+                     Uri.parse("http://example.com/$uriString#?:/[]\"",
+                               19, uriString.length + 19),
+                     Uri.parse(uriString * 3,
+                               uriString.length, uriString.length * 2)]) {
+      String name = "$uriString -> $uri";
+      Expect.equals(scheme, uri.scheme, name);
+      var uriFragment = uri.fragment;
+      if (fragment.startsWith('#')) uriFragment = "#$uriFragment";
+      Expect.equals(fragment, uriFragment, name);
+      var uriQuery = uri.query;
+      if (query.startsWith('?')) uriQuery = "?$uriQuery";
+      Expect.equals(query, uriQuery, name);
+      Expect.equals(path, uri.path, name);
+      Expect.equals(user, uri.userInfo, name);
+      var uriHost = uri.host;
+      if (host.startsWith("[")) uriHost = "[$uriHost]";
+      if (uri.port != 0) uriHost += ":${uri.port}";
+      Expect.equals(host, uriHost, name);
+    }
   }
 
   for (var scheme in schemes) {
     for (var fragment in fragments) {
       for (var query in queries) {
         for (var path in paths) {
+          // File scheme URIs always get a leading slash.
+          if (scheme == "file" && !path.startsWith('/')) continue;
           for (var user in userInfos) {
             for (var host in hosts) {
               var auth = host;
               var s = scheme;
               if (user.isNotEmpty) auth = "$user@$auth";
               if (auth.isNotEmpty) auth = "//$auth";
+              if (auth.isNotEmpty && !path.startsWith('/')) continue;
               check("$scheme${scheme.isEmpty ? "" : ":"}"
                         "$auth$path$query$fragment",
                     scheme,
diff --git a/tests/html/custom/attribute_changed_callback_test.dart b/tests/html/custom/attribute_changed_callback_test.dart
index 3eaa446..d0c0e32 100644
--- a/tests/html/custom/attribute_changed_callback_test.dart
+++ b/tests/html/custom/attribute_changed_callback_test.dart
@@ -4,6 +4,7 @@
 
 library attribute_changed_callback_test;
 
+import 'dart:async';
 import 'dart:html';
 import 'dart:js' as js;
 import 'package:unittest/html_individual_config.dart';
@@ -31,8 +32,14 @@
 
   static var invocations = [];
 
+  Completer completer;
+  
   void attributeChanged(name, oldValue, newValue) {
     invocations.add('$name: $oldValue => $newValue');
+    if (completer != null) {
+      completer.complete('value changed to $newValue');
+      completer = null;
+    }
   }
 }
 
@@ -84,20 +91,31 @@
       b.attributes.remove('data-v');
       expect(B.invocations, ['data-v: x => null']);
     });
-  });
 
-  group('unsupported_on_polyfill', () {
     test('add, change ID', () {
       B.invocations = [];
 
       var b = new B();
+      var completer = new Completer();
+      b.completer = completer;
       b.id = 'x';
-      expect(B.invocations, ['created', 'id: null => x']);
-
-      B.invocations = [];
-      b.attributes.remove('id');
-      expect(B.invocations, ['id: x => null']);
+      return completer.future
+        .then((_) => expect(B.invocations, ['created', 'id: null => x']))
+        .then((_) {
+          B.invocations = [];
+          var secondCompleter = new Completer();
+          b.completer = secondCompleter;
+          b.attributes.remove('id');
+          return secondCompleter.future;
+        })
+       .then((_) => expect(B.invocations, ['id: x => null'])); 
     });
+  });
+
+  group('unsupported_on_polyfill', () {
+
+    // If these tests start passing, don't remove the status suppression. Move
+    // the tests to the fullYy_supported group.
 
     test('add, change classes', () {
       var b = new B();
diff --git a/tests/html/custom_elements_23127_test.dart b/tests/html/custom_elements_23127_test.dart
new file mode 100644
index 0000000..6386690
--- /dev/null
+++ b/tests/html/custom_elements_23127_test.dart
@@ -0,0 +1,126 @@
+// 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.
+
+
+// Regression test for http://dartbug.com/23127
+// Tests super calls to a custom element upgrade constructor with various
+// combinations of parameters and type arguments.
+
+library custom_elements_23127_test;
+import 'dart:async';
+import 'dart:html';
+import 'package:unittest/html_individual_config.dart';
+import 'package:unittest/unittest.dart';
+import 'utils.dart';
+
+abstract class B1 extends HtmlElement {
+  void action();
+
+  B1.created() : super.created() {
+    action();
+  }
+}
+
+abstract class B1T<T> extends HtmlElement {
+  void action();
+  var qq = false;
+  B1T.created() : super.created() {
+    action();
+    qq = this is T;
+  }
+}
+
+abstract class B2 extends HtmlElement {
+  void action();
+  var qq;
+  B2.created([a = 1, b = 2, c = 3])
+      : qq = callTwice(() => ++a * ++b),  // [a] and [b] are boxed.
+        super.created() {
+    action();
+    qq = [qq, a, b, c];
+  }
+}
+
+abstract class B2T<T> extends HtmlElement {
+  void action();
+  var qq;
+  B2T.created([a = 1, b = 2, c = 3])
+      : qq = callTwice(() => ++a * ++b),
+        super.created() {
+    action();
+    qq = [this is T, qq, a, b, c];
+  }
+}
+
+class C1 extends B1 {
+  int z;
+  C1.created() : super.created();
+  action() => z = 3;
+}
+
+class C1T extends B1T {
+  int z;
+  C1T.created() : super.created();
+  action() => z = 3;
+}
+
+class C2 extends B2 {
+  int z;
+  C2.created() : super.created(20);
+  action() => z = 3;
+}
+
+class C2T extends B2T {
+  int z;
+  C2T.created() : super.created(20);
+  action() => z = 3;
+}
+
+
+
+var callTwice;
+
+main() {
+  useHtmlIndividualConfiguration();
+
+  setUp(() => customElementsReady);
+
+  callTwice = (f) { f(); return f(); };
+
+  group('baseline', () {
+    test('C1', () {
+      document.register('x-c1', C1);
+      C1 e = document.createElement('x-c1');
+      expect(e.z, 3);
+    });
+  });
+
+  group('c1t', () {
+    test('C1T', () {
+      document.register('x-c1t', C1T);
+      C1T e = document.createElement('x-c1t');
+      expect(e.z, 3);
+      expect(e.qq, true);
+    });
+  });
+
+  group('c2', () {
+    test('C2', () {
+      document.register('x-c2', C2);
+      C2 e = document.createElement('x-c2');
+      expect(e.z, 3);
+      expect(e.qq, [88, 22, 4, 3]);
+    });
+  });
+
+  group('c2t', () {
+    test('C2T', () {
+      document.register('x-c2t', C2T);
+      C2T e = document.createElement('x-c2t');
+      expect(e.z, 3);
+      expect(e.qq, [true, 88, 22, 4, 3]);
+    });
+  });
+
+}
diff --git a/tests/html/custom_elements_23127_test.html b/tests/html/custom_elements_23127_test.html
new file mode 100644
index 0000000..b0b68b5
--- /dev/null
+++ b/tests/html/custom_elements_23127_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <title> custom_elements_23127_test </title>
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <h1> Running custom_elements_23127_test </h1>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/tests/html/element_classes_svg_test.dart b/tests/html/element_classes_svg_test.dart
new file mode 100644
index 0000000..0acd2a7
--- /dev/null
+++ b/tests/html/element_classes_svg_test.dart
@@ -0,0 +1,200 @@
+// 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 ElementTest;
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'dart:collection';
+import 'dart:html';
+import 'dart:svg' as svg;
+
+// Test for `querySelectorAll(xxx).classes.op()` where the query returns mixed
+// Html and Svg elements.
+
+Element makeElementsContainer() {
+  var e = new Element.html(
+      '<ul class="yes foo">'
+      '<li class="yes quux qux">'
+      '</ul>');
+  final svgContent = r"""
+<svg version="1.1">
+  <circle class="yes qux"></circle>
+  <path class="yes classy"></path>
+</svg>""";
+  final svgElement = new svg.SvgElement.svg(svgContent);
+  e.append(svgElement);
+  return e;
+}
+
+Element elementsContainer;
+
+ElementList<Element> elementsSetup() {
+  elementsContainer = makeElementsContainer();
+  document.documentElement.children.add(elementsContainer);
+  var elements = document.querySelectorAll('.yes');
+  expect(elements.length, 4);
+  return elements;
+}
+
+void elementsTearDown() {
+  if (elementsContainer != null) {
+    document.documentElement.children.remove(elementsContainer);
+    elementsContainer = null;
+  }
+}
+
+/// Returns a canonical string for Set<String> and lists of Element's classes.
+String view(var e) {
+  if (e is Set) return '${e.toList()..sort()}';
+  if (e is Element) return view(e.classes);
+  if (e is Iterable) return '${e.map(view).toList()}';
+  throw new ArgumentError('Cannot make canonical view string for: $e}');
+}
+
+main() {
+  useHtmlConfiguration();
+
+  Set<String> extractClasses(Element el) {
+    final match = new RegExp('class="([^"]+)"').firstMatch(el.outerHtml);
+    return new LinkedHashSet.from(match[1].split(' '));
+  }
+
+  tearDown(elementsTearDown);
+
+  test('list_view', () {
+    // Test that the 'view' helper function is behaving.
+    var elements = elementsSetup();
+    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
+    expect(view(elements),
+        '[[foo, yes], [quux, qux, yes], [qux, yes], [classy, yes]]');
+  });
+
+  test('listClasses=', () {
+    var elements =  elementsSetup();
+
+    elements.classes = ['foo', 'qux'];
+    expect(view(elements.classes), '[foo, qux]');
+    expect(view(elements), '[[foo, qux], [foo, qux], [foo, qux], [foo, qux]]');
+
+    var elements2 = document.querySelectorAll('.qux');
+    expect(view(elements2.classes), '[foo, qux]');
+    expect(view(elements2), '[[foo, qux], [foo, qux], [foo, qux], [foo, qux]]');
+
+    for (Element e in elements2) {
+      expect(e.classes, orderedEquals(['foo', 'qux']));
+      expect(extractClasses(e), orderedEquals(['foo', 'qux']));
+    }
+
+    elements.classes = [];
+    expect(view(elements2.classes), '[]');
+    expect(view(elements2), '[[], [], [], []]');
+  });
+
+  test('listMap', () {
+    var elements = elementsSetup();
+    expect(elements.classes.map((c) => c.toUpperCase()).toList(),
+        unorderedEquals(['YES', 'FOO', 'QUX', 'QUUX', 'CLASSY']));
+  });
+
+  test('listContains', () {
+    var elements = elementsSetup();
+    expect(elements.classes.contains('classy'), isTrue);
+    expect(elements.classes.contains('troll'), isFalse);
+  });
+
+
+  test('listAdd', () {
+    var elements =  elementsSetup();
+    var added = elements.classes.add('lassie');
+    expect(added, isNull);
+
+    expect(view(elements.classes), '[classy, foo, lassie, quux, qux, yes]');
+    expect(view(elements),
+        '[[foo, lassie, yes], [lassie, quux, qux, yes], '
+        '[lassie, qux, yes], [classy, lassie, yes]]');
+  });
+
+  test('listRemove', () {
+    var elements = elementsSetup();
+    expect(elements.classes.remove('lassi'), isFalse);
+    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
+    expect(view(elements),
+        '[[foo, yes], [quux, qux, yes], [qux, yes], [classy, yes]]');
+
+    expect(elements.classes.remove('qux'), isTrue);
+    expect(view(elements.classes), '[classy, foo, quux, yes]');
+    expect(view(elements),
+        '[[foo, yes], [quux, yes], [yes], [classy, yes]]');
+  });
+
+  test('listToggle', () {
+    var elements = elementsSetup();
+    elements.classes.toggle('qux');
+    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
+    expect(view(elements),
+        '[[foo, qux, yes], [quux, yes], [yes], [classy, qux, yes]]');
+  });
+
+  test('listAddAll', () {
+    var elements = elementsSetup();
+    elements.classes.addAll(['qux', 'lassi', 'sassy']);
+    expect(view(elements.classes),
+        '[classy, foo, lassi, quux, qux, sassy, yes]');
+    expect(view(elements),
+        '[[foo, lassi, qux, sassy, yes], [lassi, quux, qux, sassy, yes], '
+        '[lassi, qux, sassy, yes], [classy, lassi, qux, sassy, yes]]');
+  });
+
+  test('listRemoveAll', () {
+    var elements = elementsSetup();
+    elements.classes.removeAll(['qux', 'classy', 'mumble']);
+    expect(view(elements.classes), '[foo, quux, yes]');
+    expect(view(elements),
+        '[[foo, yes], [quux, yes], [yes], [yes]]');
+
+    elements.classes.removeAll(['foo', 'yes']);
+    expect(view(elements.classes), '[quux]');
+    expect(view(elements),
+        '[[], [quux], [], []]');
+  });
+
+  test('listToggleAll', () {
+    var elements = elementsSetup();
+    elements.classes.toggleAll(['qux', 'mornin']);
+    expect(view(elements.classes), '[classy, foo, mornin, quux, qux, yes]');
+    expect(view(elements),
+        '[[foo, mornin, qux, yes], [mornin, quux, yes], '
+        '[mornin, yes], [classy, mornin, qux, yes]]');
+
+  });
+
+  test('listRetainAll', () {
+    var elements = elementsSetup();
+    elements.classes.retainAll(['bar', 'baz', 'classy', 'qux']);
+    expect(view(elements.classes), '[classy, qux]');
+    expect(view(elements), '[[], [qux], [qux], [classy]]');
+  });
+
+  test('listRemoveWhere', () {
+    var elements = elementsSetup();
+    elements.classes.removeWhere((s) => s.startsWith('q'));
+    expect(view(elements.classes), '[classy, foo, yes]');
+    expect(view(elements),
+        '[[foo, yes], [yes], [yes], [classy, yes]]');
+  });
+
+  test('listRetainWhere', () {
+    var elements = elementsSetup();
+    elements.classes.retainWhere((s) => s.startsWith('q'));
+    expect(view(elements.classes), '[quux, qux]');
+    expect(view(elements),
+        '[[], [quux, qux], [qux], []]');
+  });
+
+  test('listContainsAll', () {
+    var elements = elementsSetup();
+    expect(elements.classes.containsAll(['qux', 'mornin']), isFalse);
+    expect(elements.classes.containsAll(['qux', 'classy']), isTrue);
+  });
+}
diff --git a/tests/html/element_classes_test.dart b/tests/html/element_classes_test.dart
index d1d23ee..14af4bd 100644
--- a/tests/html/element_classes_test.dart
+++ b/tests/html/element_classes_test.dart
@@ -8,29 +8,53 @@
 import 'dart:collection';
 import 'dart:html';
 
-main() {
-  useHtmlConfiguration();
+Element makeElement() => new Element.tag('div');
 
-  Element makeElement() => new Element.tag('div');
-
-  Element makeElementWithChildren() =>
-    new Element.html("<div><br/><img/><input/></div>");
-
-  Element makeElementWithClasses() =>
+Element makeElementWithClasses() =>
     new Element.html('<div class="foo bar baz"></div>');
 
-  Element makeListElement() =>
-    new Element.html('<ul class="foo bar baz">'
-        '<li class="quux qux"><li class="meta">'
-        '<li class="classy lassy"><li class="qux lassy"></ul>');
+Set<String> makeClassSet() => makeElementWithClasses().classes;
 
-  Set<String> makeClassSet() => makeElementWithClasses().classes;
+Element makeListElement() =>
+    new Element.html('<ul class="foo bar baz">'
+        '<li class="quux qux">'
+        '<li class="meta">'
+        '<li class="classy lassy">'
+        '<li class="qux lassy">'
+        '</ul>');
+
+Element listElement;
+
+ElementList<Element> listElementSetup() {
+  listElement = makeListElement();
+  document.documentElement.children.add(listElement);
+  return document.querySelectorAll('li');
+}
+
+void listElementTearDown() {
+  if (listElement != null) {
+    document.documentElement.children.remove(listElement);
+    listElement = null;
+  }
+}
+
+/// Returns a canonical string for Set<String> and lists of Element's classes.
+String view(var e) {
+  if (e is Set) return '${e.toList()..sort()}';
+  if (e is Element) return view(e.classes);
+  if (e is Iterable) return '${e.map(view).toList()}';
+  throw new ArgumentError('Cannot make canonical view string for: $e}');
+}
+
+main() {
+  useHtmlConfiguration();
 
   Set<String> extractClasses(Element el) {
     final match = new RegExp('class="([^"]+)"').firstMatch(el.outerHtml);
     return new LinkedHashSet.from(match[1].split(' '));
   }
 
+
   test('affects the "class" attribute', () {
     final el = makeElementWithClasses();
     el.classes.add('qux');
@@ -168,8 +192,28 @@
     expect(classes, orderedEquals(['qux','bar', 'foo']));
   });
 
+  test('retainAll', () {
+    final classes = makeClassSet();
+    classes.retainAll(['bar', 'baz', 'qux']);
+    expect(classes, orderedEquals(['bar', 'baz']));
+  });
+
+  test('removeWhere', () {
+    final classes = makeClassSet();
+    classes.removeWhere((s) => s.startsWith('b'));
+    expect(classes, orderedEquals(['foo']));
+  });
+
+  test('retainWhere', () {
+    final classes = makeClassSet();
+    classes.retainWhere((s) => s.startsWith('b'));
+    expect(classes, orderedEquals(['bar', 'baz']));
+  });
+
   test('containsAll', () {
     final classes = makeClassSet();
+    expect(classes.containsAll(['foo', 'baz']), isTrue);
+    expect(classes.containsAll(['foo', 'qux']), isFalse);
     expect(classes.containsAll(['foo', 'baz'].toSet()), isTrue);
     expect(classes.containsAll(['foo', 'qux'].toSet()), isFalse);
   });
@@ -196,13 +240,15 @@
     expect(classes, orderedEquals(['foo', 'bar', 'aardvark', 'baz']));
   });
 
-  Element listElement;
+  tearDown(listElementTearDown);
 
-  ElementList<Element> listElementSetup() {
-    listElement = makeListElement();
-    document.documentElement.children.add(listElement);
-    return document.queryAll('li');
-  }
+  test('list_view', () {
+    // Test that the 'view' helper function is behaving.
+    var elements = listElementSetup();
+    expect(view(elements.classes), '[classy, lassy, meta, quux, qux]');
+    expect(view(elements),
+        '[[quux, qux], [meta], [classy, lassy], [lassy, qux]]');
+  });
 
   test('listClasses=', () {
     var elements =  listElementSetup();
@@ -214,24 +260,20 @@
     }
 
     elements.classes = [];
-    for (Element e in elements) {
-      expect(e.classes, []);
-    }
-    document.documentElement.children.remove(listElement);
+    expect(view(elements.classes), '[]');
+    expect(view(elements), '[[], [], [], []]');
   });
 
   test('listMap', () {
     var elements = listElementSetup();
     expect(elements.classes.map((c) => c.toUpperCase()).toList(),
         unorderedEquals(['QUX', 'QUUX', 'META', 'CLASSY', 'LASSY']));
-    document.documentElement.children.remove(listElement);
   });
 
   test('listContains', () {
     var elements = listElementSetup();
     expect(elements.classes.contains('lassy'), isTrue);
     expect(elements.classes.contains('foo'), isFalse);
-    document.documentElement.children.remove(listElement);
   });
 
 
@@ -240,98 +282,85 @@
     var added = elements.classes.add('lassie');
     expect(added, isNull);
 
-    expect(elements.classes,
-        unorderedEquals(['lassie', 'qux', 'quux', 'meta', 'classy', 'lassy']));
-    for (Element e in elements) {
-      expect(e.classes, anyOf(unorderedEquals(['quux', 'qux', 'lassie']),
-          unorderedEquals(['meta', 'lassie']),
-          unorderedEquals(['classy', 'lassy', 'lassie']),
-          unorderedEquals(['qux', 'lassy', 'lassie'])));
-    }
-    document.documentElement.children.remove(listElement);
+    expect(view(elements.classes), '[classy, lassie, lassy, meta, quux, qux]');
+    expect(view(elements),
+        '[[lassie, quux, qux], [lassie, meta], [classy, lassie, lassy], '
+        '[lassie, lassy, qux]]');
   });
 
   test('listRemove', () {
     var elements = listElementSetup();
     expect(elements.classes.remove('lassi'), isFalse);
-    expect(elements.classes,
-        unorderedEquals(['qux', 'quux', 'meta', 'classy', 'lassy']));
-    for (Element e in elements) {
-      expect(e.classes, anyOf(unorderedEquals(['quux', 'qux']),
-          unorderedEquals(['meta']), unorderedEquals(['classy', 'lassy']),
-          unorderedEquals(['qux', 'lassy'])));
-    }
+    expect(view(elements.classes), '[classy, lassy, meta, quux, qux]');
+    expect(view(elements),
+        '[[quux, qux], [meta], [classy, lassy], [lassy, qux]]');
 
     expect(elements.classes.remove('qux'), isTrue);
-    expect(elements.classes,
-        unorderedEquals(['quux', 'meta', 'classy', 'lassy']));
-    for (Element e in elements) {
-      expect(e.classes, anyOf(unorderedEquals(['quux']),
-          unorderedEquals(['meta']), unorderedEquals(['classy', 'lassy']),
-          unorderedEquals(['lassy'])));
-    }
-    document.documentElement.children.remove(listElement);
+    expect(view(elements.classes), '[classy, lassy, meta, quux]');
+    expect(view(elements), '[[quux], [meta], [classy, lassy], [lassy]]');
   });
 
   test('listToggle', () {
     var elements = listElementSetup();
     elements.classes.toggle('qux');
-    expect(elements.classes,
-        unorderedEquals(['qux', 'quux', 'meta', 'classy', 'lassy']));
-    for (Element e in elements) {
-      expect(e.classes, anyOf(unorderedEquals(['quux']),
-          unorderedEquals(['meta', 'qux']), unorderedEquals(['classy', 'lassy',
-          'qux']), unorderedEquals(['lassy'])));
-    }
-    document.documentElement.children.remove(listElement);
+    expect(view(elements.classes), '[classy, lassy, meta, quux, qux]');
+    expect(view(elements),
+        '[[quux], [meta, qux], [classy, lassy, qux], [lassy]]');
   });
 
   test('listAddAll', () {
     var elements = listElementSetup();
     elements.classes.addAll(['qux', 'lassi', 'sassy']);
-    expect(elements.classes,
-        unorderedEquals(['qux', 'quux', 'meta', 'classy', 'lassy', 'sassy',
-        'lassi']));
-    for (Element e in elements) {
-      expect(e.classes, anyOf(
-          unorderedEquals(['quux', 'qux', 'lassi', 'sassy']),
-          unorderedEquals(['meta', 'qux', 'lassi', 'sassy']),
-          unorderedEquals(['classy', 'lassy', 'qux', 'lassi','sassy']),
-          unorderedEquals(['lassy', 'qux', 'lassi', 'sassy'])));
-    }
-    document.documentElement.children.remove(listElement);
+    expect(view(elements.classes),
+        '[classy, lassi, lassy, meta, quux, qux, sassy]');
+    expect(view(elements),
+        '[[lassi, quux, qux, sassy], [lassi, meta, qux, sassy], '
+        '[classy, lassi, lassy, qux, sassy], [lassi, lassy, qux, sassy]]');
   });
 
   test('listRemoveAll', () {
     var elements = listElementSetup();
     elements.classes.removeAll(['qux', 'lassy', 'meta']);
-    expect(elements.classes,
-        unorderedEquals(['quux','classy']));
-    for (Element e in elements) {
-      expect(e.classes, anyOf(unorderedEquals(['quux']),
-          unorderedEquals([]), unorderedEquals(['classy'])));
-    }
-    document.documentElement.children.remove(listElement);
+    expect(view(elements.classes), '[classy, quux]');
+    expect(view(elements), '[[quux], [], [classy], []]');
+
   });
 
   test('listToggleAll', () {
     var elements = listElementSetup();
     elements.classes.toggleAll(['qux', 'meta', 'mornin']);
-    expect(elements.classes,
-        unorderedEquals(['qux', 'quux', 'meta', 'classy', 'lassy', 'mornin']));
-    for (Element e in elements) {
-      expect(e.classes, anyOf(unorderedEquals(['quux', 'meta', 'mornin']),
-          unorderedEquals(['qux', 'mornin']),
-          unorderedEquals(['classy', 'lassy', 'qux', 'mornin', 'meta']),
-          unorderedEquals(['lassy', 'mornin', 'meta'])));
-    }
-    document.documentElement.children.remove(listElement);
+    expect(view(elements.classes), '[classy, lassy, meta, mornin, quux, qux]');
+    expect(view(elements),
+        '[[meta, mornin, quux], [mornin, qux], '
+        '[classy, lassy, meta, mornin, qux], [lassy, meta, mornin]]');
+
+  });
+
+  test('listRetainAll', () {
+    var elements = listElementSetup();
+    elements.classes.retainAll(['bar', 'baz', 'qux']);
+    expect(view(elements.classes), '[qux]');
+    expect(view(elements), '[[qux], [], [], [qux]]');
+  });
+
+  test('listRemoveWhere', () {
+    var elements = listElementSetup();
+    elements.classes.removeWhere((s) => s.startsWith('q'));
+    expect(view(elements.classes), '[classy, lassy, meta]');
+    expect(view(elements),
+        '[[], [meta], [classy, lassy], [lassy]]');
+  });
+
+  test('listRetainWhere', () {
+    var elements = listElementSetup();
+    elements.classes.retainWhere((s) => s.startsWith('q'));
+    expect(view(elements.classes), '[quux, qux]');
+    expect(view(elements), '[[quux, qux], [], [], [qux]]');
   });
 
   test('listContainsAll', () {
     var elements = listElementSetup();
     expect(elements.classes.containsAll(['qux', 'meta', 'mornin']), isFalse);
     expect(elements.classes.containsAll(['qux', 'lassy', 'classy']), isTrue);
-    document.documentElement.children.remove(listElement);
   });
 }
diff --git a/tests/html/html.status b/tests/html/html.status
index c367d6f..c9d468d 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -6,6 +6,7 @@
 interactive_test: Skip # Must be run manually.
 dromaeo_smoke_test: Skip # Issue 14521, 8257
 cross_frame_test: Skip # Test reloads itself. Issue 18558
+svgelement_test/constructors: Skip # Temporary suppression, WIP alanknight
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 custom/attribute_changed_callback_test/unsupported_on_polyfill: Fail # Issue 18931 (Disabled for Chrome 35 roll)
@@ -37,6 +38,7 @@
 [ $compiler == dart2js && ($runtime == safari || $runtime == safarimobilesim || $runtime == ff  || $ie) ]
 custom/entered_left_view_test/viewless_document: Fail # Polyfill does not handle this
 fontface_test: Fail # Fontface not supported on these.
+custom/attribute_changed_callback_test/unsupported_on_polyfill: Fail # Polyfill does not support
 element_animate_test: Fail # Element.animate not supported on these browsers.
 
 [ $compiler == none && $runtime == dartium && $system == macos]
@@ -52,6 +54,7 @@
 isolates_test: Fail # Issue 13921
 indexeddb_3_test: Skip # Issue 19578.  Timeouts and RuntimeError
 fileapi_test/getFile: Pass, Fail # Issue 20488
+node_validator_test/dom_clobbering: Skip # Dartium is immune to DOM clobbering, so the HTML passes through the sanitizer.
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) && $mode == debug ]
 websocket_test/websocket: Skip # Issue 17666
@@ -189,7 +192,6 @@
 [ $runtime == ie11 ]
 custom/document_register_type_extensions_test/single-parameter: Fail # Issue 13193.
 canvasrenderingcontext2d_test/arc: Pass, Fail # Pixel unexpected value. Please triage this failure.
-node_validator_test: Pass, RuntimeError # Issues 20657, 20659.
 worker_test/functional: Pass, Fail # Issues 20659.
 transferables_test: Pass, Fail # Issues 20659.
 
@@ -378,9 +380,6 @@
 [ $compiler == dart2js && ($runtime == drt || $runtime ==chrome) ]
 wheelevent_test: Fail # Issue 12958
 
-[ $compiler == dart2js && $runtime == ff && $system == windows ]
-node_validator_test: Fail # Issue 22564
-
 [ $compiler == dart2js &&  $runtime == chrome]
 svgelement_test/supported_altGlyph: RuntimeError # Issue 22154
 
diff --git a/tests/html/node_validator_test.dart b/tests/html/node_validator_test.dart
index 3189ec3..46b2beb 100644
--- a/tests/html/node_validator_test.dart
+++ b/tests/html/node_validator_test.dart
@@ -4,11 +4,10 @@
 
 library validator_test;
 
-import 'dart:async';
 import 'dart:html';
 import 'dart:svg' as svg;
 import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
+import 'package:unittest/html_individual_config.dart';
 import 'utils.dart';
 
 
@@ -19,6 +18,11 @@
   var b = document.body.createFragment(reference,
       treeSanitizer: nullSanitizer);
 
+  // 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.
+  if (reference != '') {
+    expect(b.childNodes.length > 0, isTrue);
+  }
   validateNodeTree(a, b);
 }
 
@@ -47,9 +51,9 @@
 }
 
 main() {
-  useHtmlConfiguration();
+  useHtmlIndividualConfiguration();
 
-  group('DOM sanitization', () {
+  group('DOM_sanitization', () {
     var validator = new NodeValidatorBuilder.common();
 
     testHtml('allows simple constructs',
@@ -131,7 +135,7 @@
     });
   });
 
-  group('URI sanitization', () {
+  group('URI_sanitization', () {
     var recorder = new RecordingUriValidator();
     var validator = new NodeValidatorBuilder()..allowHtml5(uriPolicy: recorder);
 
@@ -186,228 +190,237 @@
         ['s']);
   });
 
-  group('NodeValidationPolicy', () {
+  group('allowNavigation', () {
+    var validator = new NodeValidatorBuilder()..allowNavigation();
 
-    group('allowNavigation', () {
-      var validator = new NodeValidatorBuilder()..allowNavigation();
+    testHtml('allows anchor tags',
+        validator,
+        '<a href="#foo">foo</a>');
 
-      testHtml('allows anchor tags',
+    testHtml('allows form elements',
+        validator,
+        '<form method="post" action="/foo"></form>');
+
+    testHtml('disallows script navigation',
+        validator,
+        '<a href="javascript:foo = 1">foo</a>',
+        '<a>foo</a>');
+
+    testHtml('disallows cross-site navigation',
+        validator,
+        '<a href="http://example.com">example.com</a>',
+        '<a>example.com</a>');
+
+    testHtml('blocks other elements',
+        validator,
+        '<a href="#foo"><b>foo</b></a>',
+        '<a href="#foo"></a>');
+
+    testHtml('blocks tag extension',
+        validator,
+        '<a is="x-foo"></a>',
+        '');
+  });
+
+  group('allowImages', () {
+    var validator = new NodeValidatorBuilder()..allowImages();
+
+    testHtml('allows images',
+        validator,
+        '<img src="/foo.jpg" alt="something" width="100" height="100"/>');
+
+    testHtml('blocks onerror',
+        validator,
+        '<img src="/foo.jpg" onerror="something"/>',
+        '<img src="/foo.jpg"/>');
+
+    testHtml('enforces same-origin',
+        validator,
+        '<img src="http://example.com/foo.jpg"/>',
+        '<img/>');
+  });
+
+  group('allowCustomElement', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowCustomElement(
+          'x-foo',
+          attributes: ['bar'],
+          uriAttributes: ['baz'])
+      ..allowHtml5();
+
+    testHtml('allows custom elements',
+        validator,
+        '<x-foo bar="something" baz="/foo.jpg"></x-foo>');
+
+
+    testHtml('validates custom tag URIs',
+        validator,
+        '<x-foo baz="http://example.com/foo.jpg"></x-foo>',
+        '<x-foo></x-foo>');
+
+    testHtml('blocks type extensions',
+        validator,
+        '<div is="x-foo"></div>',
+        '');
+
+    testHtml('blocks tags on non-matching elements',
+        validator,
+        '<div bar="foo"></div>',
+        '<div></div>');
+  });
+
+  group('allowTagExtension', () {
+     var validator = new NodeValidatorBuilder()
+      ..allowTagExtension(
+          'x-foo',
+          'div',
+          attributes: ['bar'],
+          uriAttributes: ['baz'])
+      ..allowHtml5();
+
+    testHtml('allows tag extensions',
+        validator,
+        '<div is="x-foo" bar="something" baz="/foo.jpg"></div>');
+
+    testHtml('blocks custom elements',
           validator,
-          '<a href="#foo">foo</a>');
-
-      testHtml('allows form elements',
-          validator,
-          '<form method="post" action="/foo"></form>');
-
-      testHtml('disallows script navigation',
-          validator,
-          '<a href="javascript:foo = 1">foo</a>',
-          '<a>foo</a>');
-
-      testHtml('disallows cross-site navigation',
-          validator,
-          '<a href="http://example.com">example.com</a>',
-          '<a>example.com</a>');
-
-      testHtml('blocks other elements',
-          validator,
-          '<a href="#foo"><b>foo</b></a>',
-          '<a href="#foo"></a>');
-
-      testHtml('blocks tag extension',
-          validator,
-          '<a is="x-foo"></a>',
-          '');
-    });
-
-    group('allowImages', () {
-      var validator = new NodeValidatorBuilder()..allowImages();
-
-      testHtml('allows images',
-          validator,
-          '<img src="/foo.jpg" alt="something" width="100" height="100"/>');
-
-      testHtml('blocks onerror',
-          validator,
-          '<img src="/foo.jpg" onerror="something"/>',
-          '<img src="/foo.jpg"/>');
-
-      testHtml('enforces same-origin',
-          validator,
-          '<img src="http://example.com/foo.jpg"/>',
-          '<img/>');
-    });
-
-    group('allowCustomElement', () {
-      var validator = new NodeValidatorBuilder()
-        ..allowCustomElement(
-            'x-foo',
-            attributes: ['bar'],
-            uriAttributes: ['baz'])
-        ..allowHtml5();
-
-      testHtml('allows custom elements',
-          validator,
-          '<x-foo bar="something" baz="/foo.jpg"></x-foo>');
-
-
-      testHtml('validates custom tag URIs',
-          validator,
-          '<x-foo baz="http://example.com/foo.jpg"></x-foo>',
-          '<x-foo></x-foo>');
-
-      testHtml('blocks type extensions',
-          validator,
-          '<div is="x-foo"></div>',
+          '<x-foo></x-foo>',
           '');
 
-      testHtml('blocks tags on non-matching elements',
-          validator,
-          '<div bar="foo"></div>',
-          '<div></div>');
-    });
-
-    group('allowTagExtension', () {
-       var validator = new NodeValidatorBuilder()
-        ..allowTagExtension(
-            'x-foo',
-            'div',
-            attributes: ['bar'],
-            uriAttributes: ['baz'])
-        ..allowHtml5();
-
-      testHtml('allows tag extensions',
-          validator,
-          '<div is="x-foo" bar="something" baz="/foo.jpg"></div>');
-
-      testHtml('blocks custom elements',
-            validator,
-            '<x-foo></x-foo>',
-            '');
-
-      testHtml('validates tag extension URIs',
-          validator,
-          '<div is="x-foo" baz="http://example.com/foo.jpg"></div>',
-          '<div is="x-foo"></div>');
-
-      testHtml('blocks tags on non-matching elements',
-          validator,
-          '<div bar="foo"></div>',
-          '<div></div>');
-
-      testHtml('blocks non-matching tags',
-          validator,
-          '<span is="x-foo">something</span>',
-          '');
-
-      validator = new NodeValidatorBuilder()
-        ..allowTagExtension(
-            'x-foo',
-            'div',
-            attributes: ['bar'],
-            uriAttributes: ['baz'])
-        ..allowTagExtension(
-            'x-else',
-            'div');
-
-      testHtml('blocks tags on non-matching custom elements',
-          validator,
-          '<div bar="foo" is="x-else"></div>',
-          '<div is="x-else"></div>');
-    });
-
-    group('allowTemplating', () {
-      var validator = new NodeValidatorBuilder()
-        ..allowTemplating()
-        ..allowHtml5();
-
-      testHtml('allows templates',
-          validator,
-          '<template bind="{{a}}"></template>');
-
-      testHtml('allows template attributes',
-          validator,
-          '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo"></template>');
-
-      testHtml('allows template attribute',
-          validator,
-          '<div template repeat="{{}}"></div>');
-
-      testHtml('blocks illegal template attribute',
-          validator,
-          '<div template="foo" repeat="{{}}"></div>',
-          '<div></div>');
-    });
-
-    group('allowSvg', () {
-      var validator = new NodeValidatorBuilder()..allowSvg();
-
-      testHtml('allows basic SVG',
+    testHtml('validates tag extension URIs',
         validator,
-        '<svg xmlns="http://www.w3.org/2000/svg'
-            'xmlns:xlink="http://www.w3.org/1999/xlink">'
-          '<image xlink:href="foo" data-foo="bar"/>'
-        '</svg>');
+        '<div is="x-foo" baz="http://example.com/foo.jpg"></div>',
+        '<div is="x-foo"></div>');
 
-      testHtml('blocks script elements',
+    testHtml('blocks tags on non-matching elements',
         validator,
-        '<svg xmlns="http://www.w3.org/2000/svg>'
-          '<script></script>'
-        '</svg>',
-        '<svg xmlns="http://www.w3.org/2000/svg></svg>');
+        '<div bar="foo"></div>',
+        '<div></div>');
 
-      testHtml('blocks script handlers',
+    testHtml('blocks non-matching tags',
         validator,
-        '<svg xmlns="http://www.w3.org/2000/svg'
-            'xmlns:xlink="http://www.w3.org/1999/xlink">'
-          '<image xlink:href="foo" onerror="something"/>'
-        '</svg>',
-        '<svg xmlns="http://www.w3.org/2000/svg'
-            'xmlns:xlink="http://www.w3.org/1999/xlink">'
-          '<image xlink:href="foo"/>'
-        '</svg>');
+        '<span is="x-foo">something</span>',
+        '');
 
-      testHtml('blocks foreignObject content',
+    validator = new NodeValidatorBuilder()
+      ..allowTagExtension(
+          'x-foo',
+          'div',
+          attributes: ['bar'],
+          uriAttributes: ['baz'])
+      ..allowTagExtension(
+          'x-else',
+          'div');
+
+    testHtml('blocks tags on non-matching custom elements',
         validator,
-        '<svg xmlns="http://www.w3.org/2000/svg>'
-          '<foreignobject width="100" height="150">'
-            '<body xmlns="http://www.w3.org/1999/xhtml">'
-              '<div>Some content</div>'
-            '</body>'
-          '</foreignobject>'
-        '</svg>',
-        '<svg xmlns="http://www.w3.org/2000/svg>'
-          '<foreignobject width="100" height="150"></foreignobject>'
-        '</svg>');
-    });
+        '<div bar="foo" is="x-else"></div>',
+        '<div is="x-else"></div>');
+  });
 
-    group('allowInlineStyles', () {
-      var validator = new NodeValidatorBuilder()
-          ..allowTextElements()
-          ..allowInlineStyles();
+  group('allowTemplating', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowTemplating()
+      ..allowHtml5();
 
-      testHtml('allows inline styles',
-          validator,
-          '<span style="background-color:red">text</span>');
+    testHtml('allows templates',
+        validator,
+        '<template bind="{{a}}"></template>');
 
-      testHtml('blocks other attributes',
-          validator,
-          '<span class="red-span"></span>',
-          '<span></span>');
+    testHtml('allows template attributes',
+        validator,
+        '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo"></template>');
 
-      validator = new NodeValidatorBuilder()
-          ..allowTextElements()
-          ..allowInlineStyles(tagName: 'span');
+    testHtml('allows template attribute',
+        validator,
+        '<div template repeat="{{}}"></div>');
 
-      testHtml('scoped allows inline styles on spans',
-          validator,
-          '<span style="background-color:red">text</span>');
+    testHtml('blocks illegal template attribute',
+        validator,
+        '<div template="foo" repeat="{{}}"></div>',
+        '<div></div>');
+  });
 
-      testHtml('scoped blocks inline styles on LIs',
-          validator,
-          '<li style="background-color:red">text</li>',
-          '<li>text</li>');
-    });
+  group('allowSvg', () {
+    var validator = new NodeValidatorBuilder()
+      ..allowSvg()
+      ..allowTextElements();
+
+    testHtml('allows basic SVG',
+      validator,
+      '<svg xmlns="http://www.w3.org/2000/svg'
+          'xmlns:xlink="http://www.w3.org/1999/xlink">'
+        '<image xlink:href="foo" data-foo="bar"/>'
+      '</svg>');
+
+    testHtml('blocks script elements',
+      validator,
+      '<svg xmlns="http://www.w3.org/2000/svg>'
+        '<script></script>'
+      '</svg>',
+      '');
+
+    testHtml('blocks script elements but allows other',
+      validator,
+      '<svg xmlns="http://www.w3.org/2000/svg>'
+        '<script></script><ellipse cx="200" cy="80" rx="100" ry="50"></ellipse>'
+      '</svg>',
+      '<svg xmlns="http://www.w3.org/2000/svg>'
+        '<ellipse cx="200" cy="80" rx="100" ry="50"></ellipse>'
+      '</svg>');
+
+    testHtml('blocks script handlers',
+      validator,
+      '<svg xmlns="http://www.w3.org/2000/svg'
+          'xmlns:xlink="http://www.w3.org/1999/xlink">'
+        '<image xlink:href="foo" onerror="something"/>'
+      '</svg>',
+      '<svg xmlns="http://www.w3.org/2000/svg'
+          'xmlns:xlink="http://www.w3.org/1999/xlink">'
+        '<image xlink:href="foo"/>'
+      '</svg>');
+
+    testHtml('blocks foreignObject content',
+      validator,
+      '<svg xmlns="http://www.w3.org/2000/svg">'
+        '<foreignobject width="100" height="150">'
+          '<body xmlns="http://www.w3.org/1999/xhtml">'
+            '<div>Some content</div>'
+          '</body>'
+        '</foreignobject>'
+        '<b>42</b>'
+      '</svg>',
+      '<svg xmlns="http://www.w3.org/2000/svg">'
+        '<b>42</b>'
+      '</svg>');
+  });
+
+  group('allowInlineStyles', () {
+    var validator = new NodeValidatorBuilder()
+        ..allowTextElements()
+        ..allowInlineStyles();
+
+    testHtml('allows inline styles',
+        validator,
+        '<span style="background-color:red">text</span>');
+
+    testHtml('blocks other attributes',
+        validator,
+        '<span class="red-span"></span>',
+        '<span></span>');
+
+    validator = new NodeValidatorBuilder()
+        ..allowTextElements()
+        ..allowInlineStyles(tagName: 'span');
+
+    testHtml('scoped allows inline styles on spans',
+        validator,
+        '<span style="background-color:red">text</span>');
+
+    testHtml('scoped blocks inline styles on LIs',
+        validator,
+        '<li style="background-color:red">text</li>',
+        '<li>text</li>');
   });
 
   group('throws', () {
@@ -456,4 +469,47 @@
       expect(element.children[0] is svg.ImageElement, isTrue);
     });
   });
+
+  group('dom_clobbering', () {
+    var validator = new NodeValidatorBuilder.common();
+
+    testHtml('DOM clobbering of attributes with single node',
+    validator,
+    "<form onmouseover='alert(1)'><input name='attributes'>",
+    "");
+
+    testHtml('DOM clobbering of attributes with multiple nodes',
+    validator,
+    "<form onmouseover='alert(1)'><input name='attributes'>"
+    "<input name='attributes'>",
+    "");
+
+    testHtml('DOM clobbering of lastChild',
+    validator,
+    "<form><input name='lastChild'><input onmouseover='alert(1)'>",
+    "");
+
+    testHtml('DOM clobbering of both children and lastChild',
+    validator,
+    "<form><input name='lastChild'><input name='children'>"
+    "<input id='children'><input onmouseover='alert(1)'>",
+    "");
+
+    testHtml('DOM clobbering of both children and lastChild, different order',
+    validator,
+    "<form><input name='children'><input name='children'>"
+    "<input id='children' name='lastChild'>"
+    "<input id='bad' onmouseover='alert(1)'>",
+    "");
+
+    testHtml('tagName makes containing form invalid',
+    validator,
+    "<form onmouseover='alert(2)'><input name='tagName'>",
+    "");
+
+    testHtml('tagName without mouseover',
+    validator,
+    "<form><input name='tagName'>",
+    "");
+  });
 }
diff --git a/tests/language/assign_to_type_test.dart b/tests/language/assign_to_type_test.dart
new file mode 100644
index 0000000..97da693
--- /dev/null
+++ b/tests/language/assign_to_type_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.
+
+// Verify that an attempt to assign to a class, enum, typedef, or type
+// parameter produces a static warning and runtime error.
+
+import "package:expect/expect.dart";
+
+noMethod(e) => e is NoSuchMethodError;
+
+class C<T> {
+  f() {
+    Expect.throws(() => T = null, noMethod); /// 01: static type warning
+  }
+}
+
+class D {}
+
+enum E { e0 }
+
+typedef void F();
+
+main() {
+  new C<D>().f();
+  Expect.throws(() => D = null, noMethod); /// 02: static type warning
+  Expect.throws(() => E = null, noMethod); /// 03: static type warning
+  Expect.throws(() => F = null, noMethod); /// 04: static type warning
+}
diff --git a/tests/language/async_regression_23058_test.dart b/tests/language/async_regression_23058_test.dart
new file mode 100644
index 0000000..ebec58e
--- /dev/null
+++ b/tests/language/async_regression_23058_test.dart
@@ -0,0 +1,36 @@
+// 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.
+
+// Regression test for issue 23058.
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+class A {
+  var x = new B();
+
+  foo() async {
+    return x.foo == 2 ? 42 : x.foo;
+  }
+}
+
+class B {
+  var x = 0;
+
+  get foo {
+    if (x == -1) {
+      return 0;
+    } else {
+      return x++;
+    }
+  }
+}
+
+main() {
+  asyncStart();
+  new A().foo().then((result) {
+    Expect.equals(1, result);
+    asyncEnd();
+  });
+}
\ No newline at end of file
diff --git a/tests/language/catch_liveness_test.dart b/tests/language/catch_liveness_test.dart
new file mode 100644
index 0000000..27b9488
--- /dev/null
+++ b/tests/language/catch_liveness_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+@AssumeDynamic() @NoInline()
+foo() => 1;
+
+@AssumeDynamic() @NoInline()
+throwException() => throw 'x';
+
+main() {
+	var x = 10;
+	var e2 = null;
+	try {
+		var t = foo();
+		throwException();
+		print(t);
+		x = 3;
+	} catch(e) {
+		Expect.equals(10, x);
+		e2 = e;
+	}
+	Expect.equals(10, x);
+	Expect.equals('x', e2);
+}
diff --git a/tests/language/conditional_access_helper.dart b/tests/language/conditional_access_helper.dart
new file mode 100644
index 0000000..3b31e28
--- /dev/null
+++ b/tests/language/conditional_access_helper.dart
@@ -0,0 +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 used by conditional_property_assignment_test.dart,
+// conditional_property_access_test.dart, and
+// conditional_method_invocation_test.dart, all of which import it using the
+// prefix "h.".
+
+library lib;
+
+var topLevelVar;
+
+class C {
+  static var staticField;
+}
diff --git a/tests/language/conditional_method_invocation_test.dart b/tests/language/conditional_method_invocation_test.dart
new file mode 100644
index 0000000..e194ab9
--- /dev/null
+++ b/tests/language/conditional_method_invocation_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+noMethod(e) => e is NoSuchMethodError;
+
+class B {}
+
+class C extends B {
+  f(callback()) => callback();
+  int g(int callback()) => callback();
+}
+
+C nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+  Expect.equals(null, nullC()?.f(bad())); /// 01: ok
+  Expect.equals(1, new C()?.f(() => 1)); /// 02: ok
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+  { int i = nullC()?.g(bad()); Expect.equals(null, i); } /// 03: ok
+  { int i = new C()?.g(() => 1); Expect.equals(1, i); } /// 04: ok
+  { String s = nullC()?.g(bad()); Expect.equals(null, s); } /// 05: static type warning
+  { String s = new C()?.g(() => null); Expect.equals(null, s); } /// 06: static type warning
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+  { B b = new C(); Expect.equals(1, b?.f(() => 1)); } /// 07: static type warning
+  { int i = 1; Expect.equals(null, nullC()?.f(i)); } /// 08: static type warning
+
+  // Consequently, '?.' cannot be used to invoke static methods of classes.
+  Expect.throws(() => C?.staticMethod(), noMethod); /// 09: static type warning
+  Expect.throws(() => h.C?.staticMethod(), noMethod); /// 10: static type warning
+
+  // Nor can it be used to access toplevel functions in libraries imported via
+  // prefix.
+  Expect.throws(() => h?.topLevelFunction(), noMethod); /// 11: static type warning
+
+  // However, '?.' can be used to access the toString method on the class Type.
+  Expect.equals(C?.toString(), (C).toString()); /// 12: ok
+  Expect.equals(h.C?.toString(), (h.C).toString()); /// 13: ok
+}
diff --git a/tests/language/conditional_property_access_test.dart b/tests/language/conditional_property_access_test.dart
new file mode 100644
index 0000000..e821865
--- /dev/null
+++ b/tests/language/conditional_property_access_test.dart
@@ -0,0 +1,55 @@
+// 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 does not appear on the LHS of an
+// assignment.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+noMethod(e) => e is NoSuchMethodError;
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static var staticField;
+}
+
+C nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+  Expect.equals(null, nullC()?.v); /// 01: ok
+  Expect.equals(1, new C(1)?.v); /// 02: ok
+
+  // The static type of e1?.d is the static type of e1.id.
+  { int i = new C(1)?.v; Expect.equals(1, i); } /// 03: ok
+  { String s = new C(null)?.v; Expect.equals(null, s); } /// 04: static type warning
+
+  // Let T be the static type of e1 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 e1?.id.
+  Expect.equals(null, nullC()?.bad); /// 05: static type warning
+  { B b = new C(1); Expect.equals(1, b?.v); } /// 06: static type warning
+
+  // Consequently, '?.' cannot be used to access static properties of classes.
+  Expect.throws(() => C?.staticField, noMethod); /// 07: static type warning
+  Expect.throws(() => h.C?.staticField, noMethod); /// 08: static type warning
+
+  // Nor can it be used to access toplevel properties in libraries imported via
+  // prefix.
+  Expect.throws(() => h?.topLevelVar, noMethod); /// 09: static type warning
+
+  // However, '?.' can be used to access the hashCode getter on the class Type.
+  Expect.equals(C?.hashCode, (C).hashCode); /// 10: ok
+  Expect.equals(h.C?.hashCode, (h.C).hashCode); /// 11: ok
+}
diff --git a/tests/language/conditional_property_assignment_test.dart b/tests/language/conditional_property_assignment_test.dart
new file mode 100644
index 0000000..bf77842
--- /dev/null
+++ b/tests/language/conditional_property_assignment_test.dart
@@ -0,0 +1,93 @@
+// 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 on the LHS of an
+// assignment.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+noMethod(e) => e is NoSuchMethodError;
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static var staticField;
+}
+
+class D {
+  E v;
+  D(this.v);
+}
+
+class E {
+  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 = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+  Expect.equals(null, nullC()?.v = bad()); /// 01: ok
+  { C c = new C(1); Expect.equals(2, c?.v = 2); Expect.equals(2, c.v); } /// 02: ok
+
+  // The static type of e1?.v = e2 is the static type of e2.
+  { D d = new D(new E()); G g = new G(); F f = (d?.v = g); Expect.identical(f, g); } /// 03: ok
+  { D d = new D(new E()); E e = new G(); F f = (d?.v = e); Expect.identical(f, e); } /// 04: static type warning
+
+  // Exactly the same static warnings that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+  Expect.equals(null, nullC()?.bad = bad()); /// 05: static type warning
+  { B b = new C(1); Expect.equals(2, b?.v = 2); Expect.equals(2, (b as C).v); } /// 06: static type warning
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+  Expect.equals(null, nullC()?.v += bad()); /// 07: ok
+  { C c = new C(1); Expect.equals(3, c?.v += 2); Expect.equals(3, c.v); } /// 08: ok
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+  { D d = new D(new E()); F f = (d?.v += 1); Expect.identical(d.v, f); } /// 09: ok
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+  Expect.equals(null, nullC()?.bad = bad()); /// 10: static type warning
+  { B b = new C(1); Expect.equals(3, b?.v += 2); Expect.equals(3, (b as C).v); } /// 11: static type warning
+  { D d = new D(new E()); F f = (d?.v += nullC()); Expect.identical(d.v, f); } /// 12: static type warning
+  { D d = new D(new E()); H h = (d?.v += 1); Expect.identical(d.v, h); } /// 13: static type warning
+
+  // Consequently, '?.' cannot be used to assign to static properties of
+  // classes.
+  Expect.throws(() => C?.staticField = null, noMethod); /// 14: static type warning
+  Expect.throws(() => C?.staticField += null, noMethod); /// 15: static type warning
+  Expect.throws(() => C?.staticField ??= null, noMethod); /// 16: static type warning
+  Expect.throws(() => h.C?.staticField = null, noMethod); /// 17: static type warning
+  Expect.throws(() => h.C?.staticField += null, noMethod); /// 18: static type warning
+  Expect.throws(() => h.C?.staticField ??= null, noMethod); /// 19: static type warning
+
+  // 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
+}
diff --git a/tests/language/const_dynamic_type_literal_test.dart b/tests/language/const_dynamic_type_literal_test.dart
new file mode 100644
index 0000000..a1be0f3
--- /dev/null
+++ b/tests/language/const_dynamic_type_literal_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that 'dynamic' can be used in const expressions and has the expected
+// behavior.
+
+import "package:expect/expect.dart";
+
+const d = dynamic;
+const i = int;
+
+void main() {
+  Expect.isTrue(identical(d, dynamic)); /// 01: ok
+  Expect.equals(1, const { d: 1, d: 2 }.length); /// 02: static type warning
+  Expect.equals(2, const { d: 1, i: 2 }.length); /// 03: ok
+}
diff --git a/tests/language/if_null_assignment_behavior_test.dart b/tests/language/if_null_assignment_behavior_test.dart
new file mode 100644
index 0000000..548d94a
--- /dev/null
+++ b/tests/language/if_null_assignment_behavior_test.dart
@@ -0,0 +1,204 @@
+// 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, including order of operations, by
+// keeping track of the operations performed.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+import "if_null_assignment_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+var xGetValue = null;
+
+get x {
+  h.operations.add('x');
+  var tmp = xGetValue;
+  xGetValue = null;
+  return tmp;
+}
+
+void set x(value) {
+  h.operations.add('x=$value');
+}
+
+var yGetValue = null;
+
+get y {
+  h.operations.add('y');
+  var tmp = yGetValue;
+  yGetValue = null;
+  return tmp;
+}
+
+void set y(value) {
+  h.operations.add('y=$value');
+}
+
+var zGetValue = null;
+
+get z {
+  h.operations.add('z');
+  var tmp = zGetValue;
+  zGetValue = null;
+  return tmp;
+}
+
+void set z(value) {
+  h.operations.add('z=$value');
+}
+
+var fValue = null;
+
+f() {
+  h.operations.add('f()');
+  var tmp = fValue;
+  fValue = null;
+  return tmp;
+}
+
+void check(expectedValue, f(), expectedOperations) {
+  Expect.equals(expectedValue, f());
+  Expect.listEquals(expectedOperations, h.operations);
+  h.operations = [];
+}
+
+void checkThrows(expectedException, f(), expectedOperations) {
+  Expect.throws(f, expectedException);
+  Expect.listEquals(expectedOperations, h.operations);
+  h.operations = [];
+}
+
+noMethod(e) => e is NoSuchMethodError;
+
+class C {
+  final String s;
+
+  C(this.s);
+
+  @override
+  String toString() => s;
+
+  static var xGetValue = null;
+
+  static get x {
+    h.operations.add('C.x');
+    var tmp = xGetValue;
+    xGetValue = null;
+    return tmp;
+  }
+
+  static void set x(value) {
+    h.operations.add('C.x=$value');
+  }
+
+  var vGetValue = null;
+
+  get v {
+    h.operations.add('$s.v');
+    var tmp = vGetValue;
+    vGetValue = null;
+    return tmp;
+  }
+
+  void set v(value) {
+    h.operations.add('$s.v=$value');
+  }
+
+  var indexGetValue = null;
+
+  operator[](index) {
+    h.operations.add('$s[$index]');
+    var tmp = indexGetValue;
+    indexGetValue = null;
+    return tmp;
+  }
+
+  void operator[]=(index, value) {
+    h.operations.add('$s[$index]=$value');
+  }
+
+  final finalOne = 1;
+  final finalNull = null;
+
+  void instanceTest() {
+    // v ??= e is equivalent to ((x) => x == null ? v = e : x)(v)
+    vGetValue = 1; check(1, () => v ??= bad(), ['$s.v']); /// 01: ok
+    yGetValue = 1; check(1, () => v ??= y, ['$s.v', 'y', '$s.v=1']); /// 02: ok
+    check(1, () => finalOne ??= bad(), []); /// 03: static type warning
+    yGetValue = 1; checkThrows(noMethod, () => finalNull ??= y, ['y']); /// 04: static type warning
+  }
+}
+
+class D extends C {
+  D(String s) : super(s);
+
+  get v => bad();
+
+  void set v(value) {
+    bad();
+  }
+
+  void derivedInstanceTest() {
+    // super.v ??= e is equivalent to
+    // ((x) => x == null ? super.v = e : x)(super.v)
+    vGetValue = 1; check(1, () => super.v ??= bad(), ['$s.v']); /// 05: ok
+    yGetValue = 1; check(1, () => super.v ??= y, ['$s.v', 'y', '$s.v=1']); /// 06: ok
+  }
+}
+
+main() {
+  // Make sure the "none" test fails if "??=" is not implemented.  This makes
+  // status files easier to maintain.
+  var _; _ ??= null;
+
+  new C('c').instanceTest();
+  new D('d').derivedInstanceTest();
+
+  // v ??= e is equivalent to ((x) => x == null ? v = e : x)(v)
+  xGetValue = 1; check(1, () => x ??= bad(), ['x']); /// 07: ok
+  yGetValue = 1; check(1, () => x ??= y, ['x', 'y', 'x=1']); /// 08: ok
+  h.xGetValue = 1; check(1, () => h.x ??= bad(), ['h.x']); /// 09: ok
+  yGetValue = 1; check(1, () => h.x ??= y, ['h.x', 'y', 'h.x=1']); /// 10: ok
+  { var l = 1; check(1, () => l ??= bad(), []); } /// 11: ok
+  { var l; yGetValue = 1; check(1, () => l ??= y, ['y']); Expect.equals(1, l); } /// 12: ok
+  { 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
+
+  // 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
+  yGetValue = 1; check(1, () => C.x ??= y, ['C.x', 'y', 'C.x=1']); /// 17: ok
+  h.C.xGetValue = 1; check(1, () => h.C.x ??= bad(), ['h.C.x']); /// 18: ok
+  yGetValue = 1; check(1, () => h.C.x ??= y, ['h.C.x', 'y', 'h.C.x=1']); /// 19: ok
+
+  // e1.v ??= e2 is equivalent to
+  // ((x) => ((y) => y == null ? x.v = e2 : y)(x.v))(e1)
+  xGetValue = new C('x'); xGetValue.vGetValue = 1; /// 20: ok
+  check(1, () => x.v ??= bad(), ['x', 'x.v']);     /// 20: continued
+  xGetValue = new C('x'); yGetValue = 1;                /// 21: ok
+  check(1, () => x.v ??= y, ['x', 'x.v', 'y', 'x.v=1']); /// 21: continued
+  fValue = new C('f()'); fValue.vGetValue = 1;       /// 22: ok
+  check(1, () => f().v ??= bad(), ['f()', 'f().v']); /// 22: continued
+  fValue = new C('f()'); yGetValue = 1;                          /// 23: ok
+  check(1, () => f().v ??= y, ['f()', 'f().v', 'y', 'f().v=1']); /// 23: continued
+
+  // e1[e2] ??= e3 is equivalent to
+  // ((a, i) => ((x) => x == null ? a[i] = e3 : x)(a[i]))(e1, e2)
+  xGetValue = new C('x'); yGetValue = 1; xGetValue.indexGetValue = 2; /// 24: ok
+  check(2, () => x[y] ??= bad(), ['x', 'y', 'x[1]']);                 /// 24: continued
+  xGetValue = new C('x'); yGetValue = 1; zGetValue = 2;          /// 25: ok
+  check(2, () => x[y] ??= z, ['x', 'y', 'x[1]', 'z', 'x[1]=2']); /// 25: continued
+
+  // e1?.v ??= e2 is equivalent to ((x) => x == null ? null : x.v ??= e2)(e1).
+  check(null, () => x?.v ??= bad(), ['x']); /// 26: ok
+  xGetValue = new C('x'); xGetValue.vGetValue = 1; /// 27: ok
+  check(1, () => x?.v ??= bad(), ['x', 'x.v']);     /// 27: continued
+  xGetValue = new C('x'); yGetValue = 1;                 /// 28: ok
+  check(1, () => x?.v ??= y, ['x', 'x.v', 'y', 'x.v=1']); /// 28: continued
+}
diff --git a/tests/language/if_null_assignment_helper.dart b/tests/language/if_null_assignment_helper.dart
new file mode 100644
index 0000000..9d6819b
--- /dev/null
+++ b/tests/language/if_null_assignment_helper.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Library used by if_null_assignment_behavior_test.dart, which
+// imports it using the prefix "h.".
+
+library lib;
+
+import "package:expect/expect.dart";
+
+List<String> operations = [];
+
+var xGetValue = null;
+
+get x {
+  operations.add('h.x');
+  var tmp = xGetValue;
+  xGetValue = null;
+  return tmp;
+}
+
+void set x(value) {
+  operations.add('h.x=$value');
+}
+
+class C {
+  static var xGetValue = null;
+
+  static get x {
+    operations.add('h.C.x');
+    var tmp = xGetValue;
+    xGetValue = null;
+    return tmp;
+  }
+
+  static void set x(value) {
+    operations.add('h.C.x=$value');
+  }
+}
diff --git a/tests/language/if_null_assignment_static_test.dart b/tests/language/if_null_assignment_static_test.dart
new file mode 100644
index 0000000..03739c4
--- /dev/null
+++ b/tests/language/if_null_assignment_static_test.dart
@@ -0,0 +1,176 @@
+// 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 that the static type of a ??= b is the least upper bound of the
+// static types of a and b.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+
+// Determine whether the VM is running in checked mode.
+bool get checkedMode {
+  try {
+    var x = 'foo';
+    int y = x;
+    return false;
+  } catch (_) {
+    return true;
+  }
+}
+
+noMethod(e) => e is NoSuchMethodError;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class A {
+  String a;
+}
+
+class B extends A {
+  String b;
+}
+
+class C extends A {
+  String c;
+}
+
+A get a => null;
+
+void set a(A value) {}
+
+B get b => null;
+
+void set b(B value) {}
+
+class ClassWithStaticGetters {
+  static A get a => null;
+
+  static void set a(A value) {}
+
+  static B get b => null;
+
+  static void set b(B value) {}
+}
+
+class ClassWithInstanceGetters {
+  A get a => null;
+
+  void set a(A value) {}
+
+  B get b => null;
+
+  void set b(B value) {}
+}
+
+class DerivedClass extends ClassWithInstanceGetters {
+  dynamic get a => bad();
+
+  void set a(dynamic value) { bad(); }
+
+  dynamic get b => bad();
+
+  void set b(dynamic value) { bad(); }
+
+  void derivedTest() {
+    // The static type of super.v ??= e is the LUB of the static types of
+    // super.v and e.
+    (super.a ??= new A()).a; /// 01: ok
+    Expect.throws(() => (super.a ??= new A()).b, noMethod); /// 02: static type warning
+    (super.a ??= new B()).a; /// 03: ok
+    (super.a ??= new B()).b; /// 04: static type warning
+    if (!checkedMode) {
+      (super.b ??= new A()).a; /// 05: ok
+      Expect.throws(() => (super.b ??= new A()).b, noMethod); /// 06: static type warning
+
+      // Exactly the same static warnings that would be caused by super.v = e
+      // are also generated in the case of super.v ??= e.
+      super.b ??= new C(); /// 07: static type warning
+    }
+  }
+}
+
+main() {
+  // Make sure the "none" test fails if "??=" is not implemented.  This makes
+  // status files easier to maintain.
+  var _; _ ??= null;
+
+  new DerivedClass().derivedTest();
+
+  // The static type of v ??= e is the LUB of the static types of v and e.
+  (a ??= new A()).a; /// 08: ok
+  Expect.throws(() => (a ??= new A()).b, noMethod); /// 09: static type warning
+  (a ??= new B()).a; /// 10: ok
+  (a ??= new B()).b; /// 11: static type warning
+  if (!checkedMode) {
+    (b ??= new A()).a; /// 12: ok
+    Expect.throws(() => (b ??= new A()).b, noMethod); /// 13: static type warning
+
+    // Exactly the same static warnings that would be caused by v = e are also
+    // generated in the case of v ??= e.
+    b ??= new C(); /// 14: static type warning
+  }
+
+  // The static type of C.v ??= e is the LUB of the static types of C.v and e.
+  (ClassWithStaticGetters.a ??= new A()).a; /// 15: ok
+  Expect.throws(() => (ClassWithStaticGetters.a ??= new A()).b, noMethod); /// 16: static type warning
+  (ClassWithStaticGetters.a ??= new B()).a; /// 17: ok
+  (ClassWithStaticGetters.a ??= new B()).b; /// 18: static type warning
+  if (!checkedMode) {
+    (ClassWithStaticGetters.b ??= new A()).a; /// 19: ok
+    Expect.throws(() => (ClassWithStaticGetters.b ??= new A()).b, noMethod); /// 20: static type warning
+
+    // Exactly the same static warnings that would be caused by C.v = e are
+    // also generated in the case of C.v ??= e.
+    ClassWithStaticGetters.b ??= new C(); /// 21: static type warning
+  }
+
+  // The static type of e1.v ??= e2 is the LUB of the static types of e1.v and
+  // e2.
+  (new ClassWithInstanceGetters().a ??= new A()).a; /// 22: ok
+  Expect.throws(() => (new ClassWithInstanceGetters().a ??= new A()).b, noMethod); /// 23: static type warning
+  (new ClassWithInstanceGetters().a ??= new B()).a; /// 24: ok
+  (new ClassWithInstanceGetters().a ??= new B()).b; /// 25: static type warning
+  if (!checkedMode) {
+    (new ClassWithInstanceGetters().b ??= new A()).a; /// 26: ok
+    Expect.throws(() => (new ClassWithInstanceGetters().b ??= new A()).b, noMethod); /// 27: static type warning
+
+    // Exactly the same static warnings that would be caused by e1.v = e2 are
+    // also generated in the case of e1.v ??= e2.
+    new ClassWithInstanceGetters().b ??= new C(); /// 28: static type warning
+  }
+
+  // The static type of e1[e2] ??= e3 is the LUB of the static types of e1[e2]
+  // and e3.
+  ((<A>[null])[0] ??= new A()).a; /// 29: ok
+  Expect.throws(() => ((<A>[null])[0] ??= new A()).b, noMethod); /// 30: static type warning
+  ((<A>[null])[0] ??= new B()).a; /// 31: ok
+  ((<A>[null])[0] ??= new B()).b; /// 32: static type warning
+  if (!checkedMode) {
+    ((<B>[null])[0] ??= new A()).a; /// 33: ok
+    Expect.throws(() => ((<B>[null])[0] ??= new A()).b, noMethod); /// 34: static type warning
+
+    // Exactly the same static warnings that would be caused by e1[e2] = e3 are
+    // also generated in the case of e1[e2] ??= e3.
+    (<B>[null])[0] ??= new C(); /// 35: static type warning
+  }
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2,
+  // therefore the static type of e1?.v ??= e2 is the static type of
+  // e1.v ?? e2, which is the LUB of the static types of e1?.v and e2.
+  (new ClassWithInstanceGetters()?.a ??= new A()).a; /// 36: ok
+  Expect.throws(() => (new ClassWithInstanceGetters()?.a ??= new A()).b, noMethod); /// 37: static type warning
+  (new ClassWithInstanceGetters()?.a ??= new B()).a; /// 38: ok
+  (new ClassWithInstanceGetters()?.a ??= new B()).b; /// 39: static type warning
+  if (!checkedMode) {
+    (new ClassWithInstanceGetters()?.b ??= new A()).a; /// 40: ok
+    Expect.throws(() => (new ClassWithInstanceGetters()?.b ??= new A()).b, noMethod); /// 41: static type warning
+
+    // Exactly the same static warnings that would be caused by e1.v ??= e2 are
+    // also generated in the case of e1?.v ??= e2.
+    new ClassWithInstanceGetters()?.b ??= new C(); /// 42: static type warning
+  }
+}
diff --git a/tests/language/if_null_behavior_test.dart b/tests/language/if_null_behavior_test.dart
new file mode 100644
index 0000000..4fcbfa7
--- /dev/null
+++ b/tests/language/if_null_behavior_test.dart
@@ -0,0 +1,55 @@
+// 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.
+
+// Evaluation of an if-null expresion e of the form e1 ?? e2 is equivalent to
+// the evaluation of the expression ((x) => x == null ? e2 : x)(e1).  The
+// static type of e is the least upper bound of the static type of e1 and the
+// static type of e2.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+
+class A {
+  final String a;
+  A(this.a);
+}
+
+class B extends A {
+  B(String v) : b = v, super(v);
+  final String b;
+}
+
+class C extends A {
+  C(String v) : c = v, super(v);
+  final String c;
+}
+
+B nullB() => null;
+C nullC() => null;
+
+noMethod(e) => e is NoSuchMethodError;
+
+main() {
+  // Make sure the "none" test fails if "??" is not implemented.  This makes
+  // status files easier to maintain.
+  var _ = null ?? null;
+
+  Expect.equals(1, 1 ?? 2); /// 01: ok
+  Expect.equals(1, 1 ?? null); /// 02: ok
+  Expect.equals(2, null ?? 2); /// 03: ok
+  Expect.equals(null, null ?? null); /// 04: ok
+  Expect.equals('B', (new B('B') ?? new C('C')).a); /// 05: ok
+  Expect.equals('B', (new B('B') ?? new C('C')).b); /// 06: static type warning
+  Expect.throws(() => (new B('B') ?? new C('C')).c, noMethod); /// 07: static type warning
+  Expect.equals('B', (new B('B') ?? nullC()).a); /// 08: ok
+  Expect.equals('B', (new B('B') ?? nullC()).b); /// 09: static type warning
+  Expect.throws(() => (new B('B') ?? nullC()).c, noMethod); /// 10: static type warning
+  Expect.equals('C', (nullB() ?? new C('C')).a); /// 11: ok
+  Expect.throws(() => (nullB() ?? new C('C')).b, noMethod); /// 12: static type warning
+  Expect.equals('C', (nullB() ?? new C('C')).c); /// 13: static type warning
+  Expect.throws(() => (nullB() ?? nullC()).a, noMethod); /// 14: ok
+  Expect.throws(() => (nullB() ?? nullC()).b, noMethod); /// 15: static type warning
+  Expect.throws(() => (nullB() ?? nullC()).c, noMethod); /// 16: static type warning
+}
diff --git a/tests/language/if_null_evaluation_order_test.dart b/tests/language/if_null_evaluation_order_test.dart
new file mode 100644
index 0000000..bc067e1
--- /dev/null
+++ b/tests/language/if_null_evaluation_order_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Evaluation of an if-null expresion e of the form e1 ?? e2 is equivalent to
+// the evaluation of the expression ((x) => x == null ? e2 : x)(e1).
+//
+// Therefore, e1 should be evaluated first; if it is non-null, e2 should not
+// be evaluated.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+
+void bad() {
+  throw new Exception();
+}
+
+bool firstExecuted = false;
+
+first() {
+  firstExecuted = true;
+  return null;
+}
+
+second() {
+  Expect.isTrue(firstExecuted);
+  return 2;
+}
+
+main() {
+  // Make sure the "none" test fails if "??" is not implemented.  This makes
+  // status files easier to maintain.
+  var _ = null ?? null;
+
+  Expect.equals(1, 1 ?? bad()); /// 01: ok
+  Expect.equals(2, first() ?? second()); /// 02: ok
+}
diff --git a/tests/language/if_null_precedence_test.dart b/tests/language/if_null_precedence_test.dart
new file mode 100644
index 0000000..32d49ce
--- /dev/null
+++ b/tests/language/if_null_precedence_test.dart
@@ -0,0 +1,66 @@
+// 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 that '??' binds tighter than '?:' and less tightly than '||'.
+
+// SharedOptions=--enable-null-aware-operators
+
+import "package:expect/expect.dart";
+
+assertionError(e) => e is AssertionError;
+
+// Determine whether the VM is running in checked mode.
+bool get checkedMode {
+  try {
+    var x = 'foo';
+    int y = x;
+    return false;
+  } catch (_) {
+    return true;
+  }
+}
+
+main() {
+  // Make sure the "none" test fails if "??" is not implemented.  This makes
+  // status files easier to maintain.
+  var _ = null ?? null;
+
+  // "a ?? b ?? c" should be legal, and should evaluate to the first non-null
+  // value (or null if there are no non-null values).
+  Expect.equals(1, 1 ?? 2 ?? 3); /// 01: ok
+  Expect.equals(2, null ?? 2 ?? 3); /// 02: ok
+  Expect.equals(3, null ?? null ?? 3); /// 03: ok
+  Expect.equals(null, null ?? null ?? null); /// 04: ok
+
+  // "a ?? b ? c : d" should parse as "(a ?? b) ? c : d", therefore provided
+  // that a is true, b need not be a bool.  An incorrect parse of
+  // "a ?? (b ? c : d)" would require b to be a bool to avoid a static type
+  // warning.
+  Expect.equals(2, true ?? 1 ? 2 : 3); /// 05: ok
+
+  // "a ?? b || c" should parse as "a ?? (b || c)", therefore it's a static
+  // type warning if b doesn't have type bool.  An incorrect parse of
+  // "(a ?? b) || c" would allow b to have any type provided that a is bool.
+  Expect.equals(false, false ?? 1 || true); /// 06: static type warning
+
+  // "a || b ?? c" should parse as "(a || b) ?? c", therefore it is a static
+  // type warning if b doesn't have type bool.  An incorrect parse of
+  // "a || (b ?? c)" would allow b to have any type provided that c is bool.
+  if (checkedMode) {
+    Expect.throws(() => false || 1 ?? true, assertionError); /// 07: static type warning
+  } else {
+    Expect.equals(false, false || 1 ?? true);                /// 07: continued
+  }
+
+  if (checkedMode) {
+    // An incorrect parse of "a || (b ?? c)" would result in no checked-mode
+    // error.
+    Expect.throws(() => false || null ?? true, assertionError); /// 08: ok
+  } else {
+    // An incorrect parse of "a || (b ?? c)" would result in c being evaluated.
+    int i = 0;                                                  /// 08: continued
+    Expect.equals(false, false || null ?? i++ == 0);            /// 08: continued
+    Expect.equals(0, i);                                        /// 08: continued
+  }
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 0d182a6..f49e43c9 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -17,6 +17,17 @@
 # Regular bugs which should be fixed.
 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
+
 [ $compiler == dart2dart ]
 deferred_load_library_wrong_args_test/none: Fail # Issue 17523
 deferred_load_inval_code_test: Fail # Issue 17523
@@ -27,6 +38,8 @@
 deferred_closurize_load_library_test: Fail  # Issue 17523
 deferred_inlined_test: Fail  # Issue 17523
 deferred_optimized_test: Fail  # Issue 17523
+multiline_strings_test: Fail # Issue (pending)
+regress_22443_test: Fail # Issue 17523
 enum_mirror_test: Skip # Issue 11511.
 
 override_inheritance_mixed_test/08: Fail # Issue 18124
@@ -43,8 +56,6 @@
 async_star_test/02: RuntimeError
 async_star_test/05: Timeout, RuntimeError
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium|| $runtime == ContentShellOnAndroid) ]
-
 [ $compiler == none && $runtime == vm ]
 class_keyword_test/02: MissingCompileTimeError # Issue 13627
 unicode_bom_test: Fail # Issue 16067
@@ -54,6 +65,7 @@
 
 [ $compiler == none ]
 dynamic_prefix_core_test/01: RuntimeError # Issue 12478
+multiline_strings_test: Fail # Issue 23020
 
 [ $compiler == none && ($runtime == vm || $runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 dynamic_prefix_core_test/none: Fail # Issue 12478
@@ -104,6 +116,6 @@
 [ $compiler == none && $runtime == ContentShellOnAndroid ]
 gc_test: SkipSlow # Times out flakily. Issue 20956
 
-[ $compiler == none && $runtime == vm && ( $arch == simarm || $arch == arm || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
+[ $compiler == none && $runtime == vm && ( $arch == simarm || $arch == arm || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
 vm/load_to_load_unaligned_forwarding_vm_test: Pass, Crash # Unaligned offset. Issue 22151
 
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index b381c07..6b777de 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -11,6 +11,8 @@
 await_backwards_compatibility_test/none: CompileTimeError # Issue 22052
 await_test: CompileTimeError # Issue 22052
 async_await_test/02: CompileTimeError # Issue 22052
+regress_17382_test: Skip # don't care about the static warning.
+regress_23038_test/01: Skip # Issue 23038
 
 issue13179_test: CompileTimeError # Issue 13179
 
@@ -35,6 +37,11 @@
 async_await_syntax_test/c10a: MissingStaticWarning
 async_await_syntax_test/d10a: MissingStaticWarning
 
+assign_to_type_test/01: MissingStaticWarning
+assign_to_type_test/02: MissingStaticWarning
+assign_to_type_test/03: MissingStaticWarning
+assign_to_type_test/04: MissingStaticWarning
+
 # Runtime negative test. No static errors or warnings.
 closure_call_wrong_argument_count_negative_test: skip
 
@@ -509,6 +516,21 @@
 
 compile_time_constant10_test/none: CompileTimeError # Issue 21177
 
+const_dynamic_type_literal_test: CompileTimeError # Issue 22989
+
+regress_21912_test/02: StaticWarning # Issue 21912
+regress_22976_test/02: StaticWarning # Issue 22976
+
+# Null-aware operators aren't implemented in the Java-based analyzer.
+if_null_evaluation_order_test: CompileTimeError
+if_null_precedence_test: CompileTimeError
+if_null_behavior_test: CompileTimeError
+if_null_assignment_behavior_test: CompileTimeError
+if_null_assignment_static_test: CompileTimeError
+conditional_property_assignment_test: CompileTimeError
+conditional_property_access_test: CompileTimeError
+conditional_method_invocation_test: CompileTimeError
+
 # Issue 16391. These tests are supposed to produce a compile time
 # error in checked mode, but they don't:
 [ $compiler == dartanalyzer && $checked ]
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index eb9d175..8baf949 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -13,6 +13,8 @@
 enum_syntax_test/05: Fail # 21649
 enum_syntax_test/06: Fail # 21649
 
+regress_17382_test: Skip # don't care about the static warning.
+
 # Test issue 12694 (was analyzer issue), (1) when "abstract" is import prefix using it as type is warning; (2) currently analyzer resolves prefix as field (don't ask)
 built_in_identifier_prefix_test: CompileTimeError # Issue 12694
 
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 272ba36..1be445a 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -59,6 +59,20 @@
 ref_before_declaration_test/05: MissingCompileTimeError
 ref_before_declaration_test/06: MissingCompileTimeError
 
+regress_22976_test/01: CompileTimeError # Issue 23132
+regress_22976_test/02: CompileTimeError # Issue 23132
+
+# Null-aware operators aren't implemented in dart2js yet.
+if_null_evaluation_order_test: CompileTimeError
+if_null_precedence_test: CompileTimeError
+if_null_behavior_test: CompileTimeError
+if_null_assignment_behavior_test: CompileTimeError
+if_null_assignment_static_test: CompileTimeError
+conditional_property_assignment_test: CompileTimeError
+conditional_property_access_test: CompileTimeError
+conditional_method_invocation_test: CompileTimeError
+super_conditional_operator_test/none: CompileTimeError
+
 
 # VM specific tests that should not be run by dart2js.
 vm/*: Skip # Issue 12699
@@ -148,6 +162,9 @@
 
 enum_const_test/02: RuntimeError # Issue 21817
 
+const_dynamic_type_literal_test/02: CompileTimeError # Issue 23009
+const_dynamic_type_literal_test/03: CompileTimeError # Issue 23009
+
 # Compilation errors.
 method_override5_test: RuntimeError # Issue 12809
 external_test/10: CompileTimeError # Issue 12887
@@ -187,6 +204,9 @@
 
 [ $compiler == dart2dart && $builder_tag == new_backend ]
 regress_13494_test: Pass # Issue 22370, passes for the wrong reason
+await_for_cancel_test: RuntimeError # Issue 23015
+regress_22936_test/01: RuntimeError # Issue 23015
+async_star_cancel_and_throw_in_finally_test: RuntimeError # Issue 23015
 
 [ $compiler == dart2dart && $builder_tag == new_backend && $host_checked ]
 large_implicit_getter_test: Crash # Stack overflow
@@ -212,6 +232,8 @@
 # Calling unresolved class constructor:
 call_nonexistent_constructor_test/01: Fail # Issue 13082
 call_nonexistent_constructor_test/02: Fail # Issue 13082
+private_access_test/05: Fail # Issue 13082
+private_access_test/06: Fail # Issue 13082
 
 bad_override_test/01: Fail # Issue 11496
 bad_override_test/02: Fail # Issue 11496
@@ -267,5 +289,9 @@
 regress_21795_test: RuntimeError # Issue 12605
 
 [ $compiler == dart2js && $runtime == d8 && $system == windows ]
-*deferred*: Skip # Issue 17458
-cha_deopt*: Skip # Issue 17458
+# Detection of d8 runtime does not work on Windows so the runtime result is
+# unreliable; at the time of writing, 32 passed, 31 failed with runtime error.
+# Marked with Pass,RuntimeError to avoid undetected compile-time failures.
+*deferred*: Pass,RuntimeError # Issue 17458
+cha_deopt*: Pass,RuntimeError # Issue 17458
+regress_22443_test: Pass,RuntimeError # Issue 17458
diff --git a/tests/language/metadata_test.dart b/tests/language/metadata_test.dart
index dc901c2..29f11dc 100644
--- a/tests/language/metadata_test.dart
+++ b/tests/language/metadata_test.dart
@@ -29,7 +29,8 @@
   static String staticField;
 
   @Meta.Alien("ET") int foo(@meta1 bool fool, {@meta1 @Tag("opt") x: 100}) {
-    return x;
+    @meta2 @meta1 g() => 10;
+    return x * g();
   }
 
   @Tag(r"timewarp")
diff --git a/tests/language/mul_recipr_test.dart b/tests/language/mul_recipr_test.dart
new file mode 100644
index 0000000..da4d7a1
--- /dev/null
+++ b/tests/language/mul_recipr_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program checking that optimizations are not too aggresive and
+// incorrect:
+// - (a * (1.0 / b))
+//
+// VMOptions=--optimization-counter-threshold=8 --no-use-osr
+
+import "package:expect/expect.dart";
+
+var xx = 23.0;
+
+main() {
+  xx = 1e-6;
+  scaleIt(1e-310);
+  Expect.isTrue(xx.isInfinite);
+  for (int i = 0; i < 10; i++) {
+    xx = 24.0;
+    scaleIt(6.0);
+    Expect.equals(4.0, xx);
+  }
+  xx = 1e-6;
+  scaleIt(1e-310);
+  Expect.isTrue(xx.isInfinite);
+}
+
+scaleIt(double b) {
+  scale(1.0 / b);
+}
+
+scale(a) {
+  xx *= a;
+}
\ No newline at end of file
diff --git a/tests/language/multiline_strings_test.dart b/tests/language/multiline_strings_test.dart
new file mode 100644
index 0000000..d7f8f3e
--- /dev/null
+++ b/tests/language/multiline_strings_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  Expect.equals('foo', '''  
+foo''');
+
+  Expect.equals('\\\nfoo', '''\\
+foo''');
+
+  Expect.equals('\t\nfoo', '''\t
+foo''');
+
+  Expect.equals('foo', '''\
+foo''');
+
+  Expect.equals('foo', '''\ \
+foo''');
+
+  Expect.equals(' \nfoo', '''\x20
+foo''');
+
+  String x = ' ';
+  Expect.equals(' \nfoo', '''$x
+foo''');
+
+  Expect.equals('foo', r'''  
+foo''');
+
+  Expect.equals('\\\\\nfoo', r'''\\
+foo''');
+
+  Expect.equals('\\t\nfoo', r'''\t
+foo''');
+
+  Expect.equals('foo', r'''\
+foo''');
+
+  Expect.equals('foo', r'''\ \
+foo''');
+}
diff --git a/tests/language/private_access_lib.dart b/tests/language/private_access_lib.dart
new file mode 100644
index 0000000..e9af620
--- /dev/null
+++ b/tests/language/private_access_lib.dart
@@ -0,0 +1,13 @@
+// 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 private;
+
+_function() {}
+
+class _Class {}
+
+class Class {
+  Class._constructor();
+}
\ No newline at end of file
diff --git a/tests/language/private_access_test.dart b/tests/language/private_access_test.dart
new file mode 100644
index 0000000..f9c4ad4
--- /dev/null
+++ b/tests/language/private_access_test.dart
@@ -0,0 +1,21 @@
+// 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 'private_access_lib.dart';
+import 'private_access_lib.dart' as private;
+
+main() {
+  Expect.throws(() => _function(),                      /// 01: static type warning
+                (e) => e is NoSuchMethodError);         /// 01: continued
+  Expect.throws(() => private._function(),              /// 02: static type warning
+                (e) => e is NoSuchMethodError);         /// 02: continued
+  Expect.throws(() => new _Class());                    /// 03: static type warning
+  Expect.throws(() => new private._Class());            /// 04: static type warning
+  Expect.throws(() => new Class._constructor(),         /// 05: static type warning
+                (e) => e is NoSuchMethodError);         /// 05: continued
+  Expect.throws(() => new private.Class._constructor(), /// 06: static type warning
+                (e) => e is NoSuchMethodError);         /// 06: continued
+}
\ No newline at end of file
diff --git a/tests/language/regress_17382_test.dart b/tests/language/regress_17382_test.dart
new file mode 100644
index 0000000..749bcf0
--- /dev/null
+++ b/tests/language/regress_17382_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.
+
+// Regression test for issue 17382.
+
+import 'package:expect/expect.dart';
+
+var mCalled = false;
+
+m(x) { mCalled = true; return x; }
+
+main() {
+  try {
+    tl(m(0));
+  } catch (e) {
+  }
+  Expect.isTrue(mCalled);
+}
+
diff --git a/tests/language/regress_21912_test.dart b/tests/language/regress_21912_test.dart
new file mode 100644
index 0000000..a978882
--- /dev/null
+++ b/tests/language/regress_21912_test.dart
@@ -0,0 +1,22 @@
+// 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.
+
+// Regression test for issue 21912.
+
+class A {}
+class B extends A {}
+
+typedef T Function2<S, T>(S z);
+typedef B AToB(A x);
+typedef A BToA(B x);
+
+void main() {
+  {
+    Function2<Function2<A, B>, Function2<B, A>> t1;
+    Function2<AToB, BToA> t2;
+    Function2<Function2<int, double>, Function2<int, double>> left;
+    left = t1; /// 01: ok
+    left = t2; /// 02: ok
+  }
+}
diff --git a/tests/language/regress_22443_lib.dart b/tests/language/regress_22443_lib.dart
new file mode 100644
index 0000000..4499cf9
--- /dev/null
+++ b/tests/language/regress_22443_lib.dart
@@ -0,0 +1,8 @@
+// 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 regress_22443;
+
+class LazyClass {
+}
diff --git a/tests/language/regress_22443_test.dart b/tests/language/regress_22443_test.dart
new file mode 100644
index 0000000..d0a6908
--- /dev/null
+++ b/tests/language/regress_22443_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.
+
+import 'regress_22443_lib.dart' deferred as D;
+import 'package:expect/expect.dart';
+
+int fooCount = 0;
+
+foo() {
+  fooCount++;
+  return new D.LazyClass();
+}
+
+main() {
+  var caughtIt = false;
+  try { foo(); } catch (e) { caughtIt = true; };
+  D.loadLibrary().then((_) {
+    foo();
+    Expect.isTrue(caughtIt);
+    Expect.equals(2, fooCount);
+  });
+}
diff --git a/tests/language/regress_22976_test.dart b/tests/language/regress_22976_test.dart
new file mode 100644
index 0000000..67d6957
--- /dev/null
+++ b/tests/language/regress_22976_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for issue 22976.
+
+class A<T> {}
+class B<T> implements A<T> {}
+class C<S, T> implements B<S>, A<T> {}
+
+main() {
+  A<int> a0 = new C<int, String>(); /// 01: ok
+  A<int> a1 = new C<String, int>(); /// 02: ok
+}
diff --git a/tests/language/regress_23038_test.dart b/tests/language/regress_23038_test.dart
new file mode 100644
index 0000000..643ca78
--- /dev/null
+++ b/tests/language/regress_23038_test.dart
@@ -0,0 +1,15 @@
+// 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.
+
+class C<T> {
+  const
+    factory /// 01: compile-time error
+    C()
+    = C<C<T>> /// 01: continued
+    ;
+}
+
+main() {
+  const C<int>();
+}
diff --git a/tests/language/regress_23046_test.dart b/tests/language/regress_23046_test.dart
new file mode 100644
index 0000000..cb7b84a
--- /dev/null
+++ b/tests/language/regress_23046_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Make sure the logic for skipping the initial quotes in a string isn't
+// re-triggered after an interpolation expression.
+
+const String x = '$y"';
+const String y = 'foo';
+const Map m = const { x: 0, y: 1 };
+
+main() {
+  Expect.equals(x, 'foo"');
+  Expect.equals(m.length, 2);
+}
diff --git a/tests/language/regress_23051_test.dart b/tests/language/regress_23051_test.dart
new file mode 100644
index 0000000..6d466d3
--- /dev/null
+++ b/tests/language/regress_23051_test.dart
@@ -0,0 +1,15 @@
+// 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.
+
+// Regression test for issue 23051.
+
+main() {
+  new A();                                 /// 01: compile-time error
+}
+
+class A {                                  /// 01: continued
+  // Note the trailing ' in the next line. /// 01: continued
+  get foo => bar();'                       /// 01: continued
+                                           /// 01: continued
+  String bar(                              /// 01: continued
\ No newline at end of file
diff --git a/tests/language/regress_23089_test.dart b/tests/language/regress_23089_test.dart
new file mode 100644
index 0000000..138749f
--- /dev/null
+++ b/tests/language/regress_23089_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.
+
+abstract class IPeer<C extends IP2PClient> {
+}
+
+abstract class IPeerRoom<P extends IPeer, C extends IP2PClient> {
+}
+
+abstract class IP2PClient<R extends IPeerRoom> {
+
+}
+
+class _Peer<C extends _P2PClient> implements IPeer<C> {
+
+}
+
+class _PeerRoom<P extends _Peer, C extends _P2PClient>
+    implements IPeerRoom<P, C> {
+
+}
+
+abstract class _P2PClient<R extends _PeerRoom, P extends _Peer>
+    implements IP2PClient<R> {
+
+}
+
+void main() {
+}
diff --git a/tests/language/super_conditional_operator_test.dart b/tests/language/super_conditional_operator_test.dart
new file mode 100644
index 0000000..83914ee
--- /dev/null
+++ b/tests/language/super_conditional_operator_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify that the ?. operator cannot be used with "super".
+
+// SharedOptions=--enable-null-aware-operators
+
+class B {
+  B();
+  B.namedConstructor();
+  var field = 1;
+  method() => 1;
+}
+
+class C extends B {
+  C()
+    : super?.namedConstructor() /// 01: compile-time error
+  ;
+
+  test() {
+    super?.field = 1; /// 02: compile-time error
+    super?.field += 1; /// 03: compile-time error
+    super?.field ??= 1; /// 04: compile-time error
+    super?.field; /// 05: compile-time error
+    1 * super?.field; /// 06: compile-time error
+    -super?.field; /// 07: compile-time error
+    ~super?.field; /// 08: compile-time error
+    !super?.field; /// 09: compile-time error
+    --super?.field; /// 10: compile-time error
+    ++super?.field; /// 11: compile-time error
+    super?.method(); /// 12: compile-time error
+    1 * super?.method(); /// 13: compile-time error
+    -super?.method(); /// 14: compile-time error
+    ~super?.method(); /// 15: compile-time error
+    !super?.method(); /// 16: compile-time error
+    --super?.method(); /// 17: compile-time error
+    ++super?.method(); /// 18: compile-time error
+  }
+}
+
+main() {
+  new C().test();
+}
diff --git a/tests/language/vm/regress_23117_vm_test.dart b/tests/language/vm/regress_23117_vm_test.dart
new file mode 100644
index 0000000..550d550
--- /dev/null
+++ b/tests/language/vm/regress_23117_vm_test.dart
@@ -0,0 +1,21 @@
+// 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 location summary for Uint32 multiplication.
+// VMOptions=--optimization-counter-threshold=5
+
+import 'package:expect/expect.dart';
+
+mintLeftShift(x, y) => x << y;
+mintRightShift(x, y) => x >> y;
+
+main() {
+  for (var i = 0; i < 20; i++) {
+    var x = 1 + (1 << (i + 32));
+    Expect.equals(x, mintLeftShift(x, 0));
+    Expect.equals(x, mintRightShift(x, 0));
+    Expect.equals(2*x, mintLeftShift(x, 1));
+    Expect.equals(x~/2, mintRightShift(x, 1));
+    Expect.equals(x, mintRightShift(mintLeftShift(x, i), i));
+  }
+}
diff --git a/tests/lib/convert/html_escape_test.dart b/tests/lib/convert/html_escape_test.dart
index 674c781..787ae34 100644
--- a/tests/lib/convert/html_escape_test.dart
+++ b/tests/lib/convert/html_escape_test.dart
@@ -8,16 +8,19 @@
 
 const _NOOP = 'Nothing_to_escape';
 
-const _TEST_INPUT = '<A </test> of \u00A0 "double" & \'single\' values>';
+const _TEST_INPUT = """<A </test> of \xA0 "double" & 'single' values>""";
 
-const _OUTPUT_UNKNOWN = '&lt;A &lt;&#x2F;test&gt; of &nbsp; &quot;double&quot; &amp; '
-  '&#x27;single&#x27; values&gt;';
+const _OUTPUT_UNKNOWN = '&lt;A &lt;/test&gt; of \xA0 &quot;double&quot; &amp; '
+  '&#39;single&#39; values&gt;';
 
-const _OUTPUT_ATTRIBUTE = "<A </test> of &nbsp; &quot;double&quot; &amp; "
-  "\'single\' values>";
+const _OUTPUT_ATTRIBUTE =
+    "<A </test> of \xA0 &quot;double&quot; &amp; 'single' values>";
 
-const _OUTPUT_ELEMENT = '&lt;A &lt;&#x2F;test&gt; of &nbsp; "double" &amp; '
-  '\'single\' values&gt;';
+const _OUTPUT_SQ_ATTRIBUTE =
+    '<A </test> of \xA0 "double" &amp; &#39;single&#39; values>';
+
+const _OUTPUT_ELEMENT =
+    """&lt;A &lt;/test&gt; of \xA0 "double" &amp; 'single' values&gt;""";
 
 void _testMode(HtmlEscape escape, String input, String expected) {
   _testConvert(escape, input, expected);
@@ -80,6 +83,7 @@
   _testMode(const HtmlEscape(), _TEST_INPUT, _OUTPUT_UNKNOWN);
   _testMode(const HtmlEscape(HtmlEscapeMode.UNKNOWN), _TEST_INPUT, _OUTPUT_UNKNOWN);
   _testMode(const HtmlEscape(HtmlEscapeMode.ATTRIBUTE), _TEST_INPUT, _OUTPUT_ATTRIBUTE);
+  _testMode(const HtmlEscape(HtmlEscapeMode.SQ_ATTRIBUTE), _TEST_INPUT, _OUTPUT_SQ_ATTRIBUTE);
   _testMode(const HtmlEscape(HtmlEscapeMode.ELEMENT), _TEST_INPUT, _OUTPUT_ELEMENT);
   _testMode(HTML_ESCAPE, _NOOP, _NOOP);
 }
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 6e59d60..a965810 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -247,7 +247,6 @@
 [ $compiler == none ]
 async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
 
-mirrors/generic_local_function_test: RuntimeError # Issue 14913
 mirrors/symbol_validation_test: RuntimeError # Issue 13596
 
 mirrors/mirrors_used*: SkipByDesign # Invalid tests. MirrorsUsed does not have a specification, and dart:mirrors is not required to hide declarations that are not covered by any MirrorsUsed annotation.
@@ -288,6 +287,9 @@
 # Deferred loading is not supported by dart2dart.
 async/deferred/deferred_in_isolate_test: Skip # Issue 17523
 
+[ $compiler == dart2dart && $builder_tag == new_backend ]
+async/future_test: RuntimeError # Issue 23015
+
 [ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
 # Dart vm does not support spawn from a dom-enabled isolate.
 async/deferred/deferred_in_isolate_test: RuntimeError # Issue 16209
diff --git a/tests/lib/mirrors/method_mirror_source_other.dart b/tests/lib/mirrors/method_mirror_source_other.dart
new file mode 100644
index 0000000..29adf5b
--- /dev/null
+++ b/tests/lib/mirrors/method_mirror_source_other.dart
@@ -0,0 +1,6 @@
+main() {
+  print("Blah");
+}
+// This function must be on the first line.
+
+class SomethingInOther {}
\ No newline at end of file
diff --git a/tests/lib/mirrors/method_mirror_source_test.dart b/tests/lib/mirrors/method_mirror_source_test.dart
index d0aad92..9b09452 100644
--- a/tests/lib/mirrors/method_mirror_source_test.dart
+++ b/tests/lib/mirrors/method_mirror_source_test.dart
@@ -3,8 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "dart:mirrors";
-
 import "package:expect/expect.dart";
+import "method_mirror_source_other.dart";
 
 expectSource(Mirror mirror, String source) {
   MethodMirror methodMirror;
@@ -14,7 +14,7 @@
     methodMirror = mirror as MethodMirror;
   }
   Expect.isTrue(methodMirror is MethodMirror);
-  Expect.equals(methodMirror.source, source);
+  Expect.equals(source, methodMirror.source);
 }
 
 foo1() {}
@@ -98,4 +98,11 @@
   var a = () {};
   expectSource(reflect(namedClosure), "namedClosure(x,y,z) => 1;");
   expectSource(reflect(a), "() {}");
+
+  // Function at first line.
+  LibraryMirror otherLib = reflectClass(SomethingInOther).owner;
+  expectSource(otherLib.declarations[#main],
+"""main() {
+  print("Blah");
+}""");
 }
diff --git a/tests/lib/mirrors/optional_parameters_test.dart b/tests/lib/mirrors/optional_parameters_test.dart
new file mode 100644
index 0000000..edb3f56
--- /dev/null
+++ b/tests/lib/mirrors/optional_parameters_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.
+
+// Regression test for http://dartbug.com/22987.
+// Ensure that functions whose signature only differs in optionality of
+// parameters are reflected correctly.
+
+library optional_parameter_test;
+
+@MirrorsUsed(targets: 'optional_parameter_test')
+import "dart:mirrors";
+import 'package:expect/expect.dart';
+
+class A {
+  foo(int x) => x;
+}
+
+class B {
+  foo([int x]) => x+1;
+}
+
+main () {
+  var x = {};
+  x["A"] = reflect(new A());
+  x["B"] = reflect(new B());
+
+  Expect.equals(1, x["A"].invoke(#foo, [1]).reflectee);
+  Expect.equals(2, x["B"].invoke(#foo, [1]).reflectee);
+}
diff --git a/tests/lib/mirrors/reflect_two_classes_test.dart b/tests/lib/mirrors/reflect_two_classes_test.dart
new file mode 100644
index 0000000..83c71de
--- /dev/null
+++ b/tests/lib/mirrors/reflect_two_classes_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This is a regression test for http://dartbug.com/23054
+
+library index;
+
+@MirrorsUsed(targets: const [Bar, Foo], symbols: const ['bar', 'getBar', 'foo', 'getFoo'], override: '*')
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+main() {
+  var bar = new Bar();
+  var barMirror = reflect(bar);
+  Expect.equals(42, barMirror.getField(#bar).reflectee, "bar field");
+  Expect.equals(42, barMirror.invoke(#getBar, []).reflectee, "getBar Method");
+
+  var foo = new Foo();
+  var fooMirror = reflect(foo);
+  Expect.equals(9, fooMirror.getField(#foo).reflectee, "foo field");
+  Expect.equals(9, fooMirror.invoke(#getFoo, []).reflectee, "getFoo Method");
+}
+
+class Bar {
+  int bar = 42;
+
+  int getBar() => bar;
+}
+
+class Foo {
+  int foo = 9;
+
+  int getFoo() => foo;
+}
+
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index c5da991..6302dc6 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -150,6 +150,42 @@
     testWrite(requestData, 1);
   }
 
+  static void _testParseRequestLean(String request,
+                                    String expectedMethod,
+                                    String expectedUri,
+                                    {int expectedTransferLength: 0,
+                                     int expectedBytesReceived: 0,
+                                     Map expectedHeaders: null,
+                                     bool chunked: false,
+                                     bool upgrade: false,
+                                     int unparsedLength: 0,
+                                     bool connectionClose: false,
+                                     String expectedVersion: "1.1"}) {
+    _testParseRequest(request,
+                      expectedMethod,
+                      expectedUri,
+                      expectedTransferLength: expectedTransferLength,
+                      expectedBytesReceived: expectedBytesReceived,
+                      expectedHeaders: expectedHeaders,
+                      chunked: chunked,
+                      upgrade: upgrade,
+                      unparsedLength: unparsedLength,
+                      connectionClose: connectionClose,
+                      expectedVersion: expectedVersion);
+    // Same test but with only \n instead of \r\n terminating each header line.
+    _testParseRequest(request.replaceAll('\r', ''),
+                      expectedMethod,
+                      expectedUri,
+                      expectedTransferLength: expectedTransferLength,
+                      expectedBytesReceived: expectedBytesReceived,
+                      expectedHeaders: expectedHeaders,
+                      chunked: chunked,
+                      upgrade: upgrade,
+                      unparsedLength: unparsedLength,
+                      connectionClose: connectionClose,
+                      expectedVersion: expectedVersion);
+  }
+
   static void _testParseInvalidRequest(String request) {
     _HttpParser httpParser;
     bool errorCalled;
@@ -356,33 +392,33 @@
         "SEARCH",
         // Methods with HTTP prefix.
         "H", "HT", "HTT", "HTTP", "HX", "HTX", "HTTX", "HTTPX"];
+    methods = ['GET'];
     methods.forEach((method) {
        request = "$method / HTTP/1.1\r\n\r\n";
-      _testParseRequest(request, method, "/");
+      _testParseRequestLean(request, method, "/");
        request = "$method /index.html HTTP/1.1\r\n\r\n";
-      _testParseRequest(request, method, "/index.html");
+      _testParseRequestLean(request, method, "/index.html");
     });
-
     request = "GET / HTTP/1.0\r\n\r\n";
-    _testParseRequest(request, "GET", "/",
-                      expectedVersion: "1.0",
-                      connectionClose: true);
+    _testParseRequestLean(request, "GET", "/",
+                          expectedVersion: "1.0",
+                          connectionClose: true);
 
     request = "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n";
-    _testParseRequest(request, "GET", "/", expectedVersion: "1.0");
+    _testParseRequestLean(request, "GET", "/", expectedVersion: "1.0");
 
     request = """
 POST /test HTTP/1.1\r
 AAA: AAA\r
 \r
 """;
-    _testParseRequest(request, "POST", "/test");
+    _testParseRequestLean(request, "POST", "/test");
 
     request = """
 POST /test HTTP/1.1\r
 \r
 """;
-    _testParseRequest(request, "POST", "/test");
+    _testParseRequestLean(request, "POST", "/test");
 
     request = """
 POST /test HTTP/1.1\r
@@ -393,7 +429,7 @@
     headers = new Map();
     headers["header-a"] = "AAA";
     headers["x-header-b"] = "bbb";
-    _testParseRequest(request, "POST", "/test", expectedHeaders: headers);
+    _testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
 
     request = """
 POST /test HTTP/1.1\r
@@ -405,7 +441,7 @@
     headers = new Map();
     headers["empty-header-1"] = "";
     headers["empty-header-2"] = "";
-    _testParseRequest(request, "POST", "/test", expectedHeaders: headers);
+    _testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
 
     request = """
 POST /test HTTP/1.1\r
@@ -416,7 +452,7 @@
     headers = new Map();
     headers["header-a"] = "AAA";
     headers["x-header-b"] = "bbb";
-    _testParseRequest(request, "POST", "/test", expectedHeaders: headers);
+    _testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
 
     request = """
 POST /test HTTP/1.1\r
@@ -431,18 +467,18 @@
     headers = new Map();
     headers["header-a"] = "AAA";
     headers["x-header-b"] = "bbb";
-    _testParseRequest(request, "POST", "/test", expectedHeaders: headers);
+    _testParseRequestLean(request, "POST", "/test", expectedHeaders: headers);
 
     request = """
 POST /test HTTP/1.1\r
 Content-Length: 10\r
 \r
 0123456789""";
-    _testParseRequest(request,
-                      "POST",
-                      "/test",
-                      expectedTransferLength: 10,
-                      expectedBytesReceived: 10);
+    _testParseRequestLean(request,
+                          "POST",
+                          "/test",
+                          expectedTransferLength: 10,
+                          expectedBytesReceived: 10);
 
     // Test connection close header.
     request = "GET /test HTTP/1.1\r\nConnection: close\r\n\r\n";
diff --git a/tools/VERSION b/tools/VERSION
index 80747fa..0476332 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 10
 PATCH 0
-PRERELEASE 0
-PRERELEASE_PATCH 2
+PRERELEASE 1
+PRERELEASE_PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index f166bc1..9e47f59 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -80,6 +80,8 @@
     test_set = web_pattern.group(4)
     if web_pattern.group(6) == 'csp':
       csp = True
+      # Always run csp mode minified
+      minified = True
     shard_index = web_pattern.group(8)
     total_shards = web_pattern.group(9)
   elif dart2js_full_pattern:
diff --git a/tools/build.py b/tools/build.py
index ec0646b..4282589 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -55,7 +55,7 @@
       default=False, action="store_true")
   result.add_option("-a", "--arch",
       help='Target architectures (comma-separated).',
-      metavar='[all,ia32,x64,simarm,arm,simmips,mips,simarm64,arm64,]',
+      metavar='[all,ia32,x64,simarm,arm,armv5te,simmips,mips,simarm64,arm64,]',
       default=utils.GuessArchitecture())
   result.add_option("--os",
     help='Target OSs (comma-separated).',
@@ -105,7 +105,7 @@
       print "Unknown mode %s" % mode
       return False
   for arch in options.arch:
-    archs = ['ia32', 'x64', 'simarm', 'arm', 'simmips', 'mips',
+    archs = ['ia32', 'x64', 'simarm', 'arm', 'armv5te', 'simmips', 'mips',
              'simarm64', 'arm64',]
     if not arch in archs:
       print "Unknown arch %s" % arch
@@ -123,7 +123,7 @@
         print ("Cross-compilation to %s is not supported on host os %s."
                % (os_name, HOST_OS))
         return False
-      if not arch in ['ia32', 'arm', 'arm64', 'mips']:
+      if not arch in ['ia32', 'arm', 'armv5te', 'arm64', 'mips']:
         print ("Cross-compilation to %s is not supported for architecture %s."
                % (os_name, arch))
         return False
@@ -162,6 +162,7 @@
 
   return None
 
+
 def SetTools(arch, target_os, options):
   toolsOverride = None
 
diff --git a/tools/dom/scripts/cssProperties.CSS21.txt b/tools/dom/scripts/cssProperties.CSS21.txt
new file mode 100644
index 0000000..8c715c5
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.CSS21.txt
@@ -0,0 +1,102 @@
+// Universally supported properties.
+//
+// This list was constructed by filtering CSS2.1 properties against
+// CSSPropertyNames.in
+//
+// TODO(sra): Remove this file once we have samples from all supported browsers.
+
+backgroundAttachment
+backgroundColor
+backgroundImage
+backgroundPosition
+backgroundRepeat
+background
+borderCollapse
+borderColor
+borderSpacing
+borderStyle
+borderTop
+borderRight
+borderBottom
+borderLeft
+borderTopColor
+borderRightColor
+borderBottomColor
+borderLeftColor
+borderTopStyle
+borderRightStyle
+borderBottomStyle
+borderLeftStyle
+borderTopWidth
+borderRightWidth
+borderBottomWidth
+borderLeftWidth
+borderWidth
+border
+bottom
+captionSide
+clear
+clip
+color
+content
+counterIncrement
+counterReset
+cursor
+direction
+display
+emptyCells
+float
+fontFamily
+fontSize
+fontStyle
+fontVariant
+fontWeight
+font
+height
+left
+letterSpacing
+lineHeight
+listStyleImage
+listStylePosition
+listStyleType
+listStyle
+marginRight
+marginLeft
+marginTop
+marginBottom
+margin
+maxHeight
+maxWidth
+minHeight
+minWidth
+orphans
+outlineColor
+outlineStyle
+outlineWidth
+outline
+overflow
+paddingTop
+paddingRight
+paddingBottom
+paddingLeft
+padding
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+position
+quotes
+right
+tableLayout
+textAlign
+textDecoration
+textIndent
+textTransform
+top
+unicodeBidi
+verticalAlign
+visibility
+whiteSpace
+widows
+width
+wordSpacing
+zIndex
diff --git a/tools/dom/scripts/cssProperties.chrome40.txt b/tools/dom/scripts/cssProperties.chrome40.txt
new file mode 100644
index 0000000..5bb010d
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.chrome40.txt
@@ -0,0 +1,358 @@
+# Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36
+cssText
+alignContent
+alignItems
+alignSelf
+alignmentBaseline
+all
+backfaceVisibility
+background
+backgroundAttachment
+backgroundBlendMode
+backgroundClip
+backgroundColor
+backgroundImage
+backgroundOrigin
+backgroundPosition
+backgroundPositionX
+backgroundPositionY
+backgroundRepeat
+backgroundRepeatX
+backgroundRepeatY
+backgroundSize
+baselineShift
+border
+borderBottom
+borderBottomColor
+borderBottomLeftRadius
+borderBottomRightRadius
+borderBottomStyle
+borderBottomWidth
+borderCollapse
+borderColor
+borderImage
+borderImageOutset
+borderImageRepeat
+borderImageSlice
+borderImageSource
+borderImageWidth
+borderLeft
+borderLeftColor
+borderLeftStyle
+borderLeftWidth
+borderRadius
+borderRight
+borderRightColor
+borderRightStyle
+borderRightWidth
+borderSpacing
+borderStyle
+borderTop
+borderTopColor
+borderTopLeftRadius
+borderTopRightRadius
+borderTopStyle
+borderTopWidth
+borderWidth
+bottom
+boxShadow
+boxSizing
+bufferedRendering
+captionSide
+clear
+clip
+clipPath
+clipRule
+color
+colorInterpolation
+colorInterpolationFilters
+colorRendering
+content
+counterIncrement
+counterReset
+cursor
+direction
+display
+dominantBaseline
+emptyCells
+enableBackground
+fill
+fillOpacity
+fillRule
+filter
+flex
+flexBasis
+flexDirection
+flexFlow
+flexGrow
+flexShrink
+flexWrap
+float
+floodColor
+floodOpacity
+font
+fontFamily
+fontKerning
+fontSize
+fontStretch
+fontStyle
+fontVariant
+fontVariantLigatures
+fontWeight
+glyphOrientationHorizontal
+glyphOrientationVertical
+height
+imageRendering
+justifyContent
+left
+letterSpacing
+lightingColor
+lineHeight
+listStyle
+listStyleImage
+listStylePosition
+listStyleType
+margin
+marginBottom
+marginLeft
+marginRight
+marginTop
+marker
+markerEnd
+markerMid
+markerStart
+mask
+maskType
+maxHeight
+maxWidth
+maxZoom
+minHeight
+minWidth
+minZoom
+objectFit
+objectPosition
+opacity
+order
+orientation
+orphans
+outline
+outlineColor
+outlineOffset
+outlineStyle
+outlineWidth
+overflow
+overflowWrap
+overflowX
+overflowY
+padding
+paddingBottom
+paddingLeft
+paddingRight
+paddingTop
+page
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+paintOrder
+perspective
+perspectiveOrigin
+pointerEvents
+position
+quotes
+resize
+right
+shapeImageThreshold
+shapeMargin
+shapeOutside
+shapeRendering
+size
+speak
+src
+stopColor
+stopOpacity
+stroke
+strokeDasharray
+strokeDashoffset
+strokeLinecap
+strokeLinejoin
+strokeMiterlimit
+strokeOpacity
+strokeWidth
+tabSize
+tableLayout
+textAlign
+textAnchor
+textDecoration
+textIndent
+textOverflow
+textRendering
+textShadow
+textTransform
+top
+touchAction
+transform
+transformOrigin
+transformStyle
+transition
+transitionDelay
+transitionDuration
+transitionProperty
+transitionTimingFunction
+unicodeBidi
+unicodeRange
+userZoom
+vectorEffect
+verticalAlign
+visibility
+webkitAnimation
+webkitAnimationDelay
+webkitAnimationDirection
+webkitAnimationDuration
+webkitAnimationFillMode
+webkitAnimationIterationCount
+webkitAnimationName
+webkitAnimationPlayState
+webkitAnimationTimingFunction
+webkitAppRegion
+webkitAppearance
+webkitBackfaceVisibility
+webkitBackgroundClip
+webkitBackgroundComposite
+webkitBackgroundOrigin
+webkitBackgroundSize
+webkitBorderAfter
+webkitBorderAfterColor
+webkitBorderAfterStyle
+webkitBorderAfterWidth
+webkitBorderBefore
+webkitBorderBeforeColor
+webkitBorderBeforeStyle
+webkitBorderBeforeWidth
+webkitBorderEnd
+webkitBorderEndColor
+webkitBorderEndStyle
+webkitBorderEndWidth
+webkitBorderHorizontalSpacing
+webkitBorderImage
+webkitBorderRadius
+webkitBorderStart
+webkitBorderStartColor
+webkitBorderStartStyle
+webkitBorderStartWidth
+webkitBorderVerticalSpacing
+webkitBoxAlign
+webkitBoxDecorationBreak
+webkitBoxDirection
+webkitBoxFlex
+webkitBoxFlexGroup
+webkitBoxLines
+webkitBoxOrdinalGroup
+webkitBoxOrient
+webkitBoxPack
+webkitBoxReflect
+webkitBoxShadow
+webkitClipPath
+webkitColumnBreakAfter
+webkitColumnBreakBefore
+webkitColumnBreakInside
+webkitColumnCount
+webkitColumnGap
+webkitColumnRule
+webkitColumnRuleColor
+webkitColumnRuleStyle
+webkitColumnRuleWidth
+webkitColumnSpan
+webkitColumnWidth
+webkitColumns
+webkitFilter
+webkitFontFeatureSettings
+webkitFontSizeDelta
+webkitFontSmoothing
+webkitHighlight
+webkitHyphenateCharacter
+webkitLineBoxContain
+webkitLineBreak
+webkitLineClamp
+webkitLocale
+webkitLogicalHeight
+webkitLogicalWidth
+webkitMarginAfter
+webkitMarginAfterCollapse
+webkitMarginBefore
+webkitMarginBeforeCollapse
+webkitMarginBottomCollapse
+webkitMarginCollapse
+webkitMarginEnd
+webkitMarginStart
+webkitMarginTopCollapse
+webkitMask
+webkitMaskBoxImage
+webkitMaskBoxImageOutset
+webkitMaskBoxImageRepeat
+webkitMaskBoxImageSlice
+webkitMaskBoxImageSource
+webkitMaskBoxImageWidth
+webkitMaskClip
+webkitMaskComposite
+webkitMaskImage
+webkitMaskOrigin
+webkitMaskPosition
+webkitMaskPositionX
+webkitMaskPositionY
+webkitMaskRepeat
+webkitMaskRepeatX
+webkitMaskRepeatY
+webkitMaskSize
+webkitMaxLogicalHeight
+webkitMaxLogicalWidth
+webkitMinLogicalHeight
+webkitMinLogicalWidth
+webkitPaddingAfter
+webkitPaddingBefore
+webkitPaddingEnd
+webkitPaddingStart
+webkitPerspective
+webkitPerspectiveOrigin
+webkitPerspectiveOriginX
+webkitPerspectiveOriginY
+webkitPrintColorAdjust
+webkitRtlOrdering
+webkitRubyPosition
+webkitTapHighlightColor
+webkitTextCombine
+webkitTextDecorationsInEffect
+webkitTextEmphasis
+webkitTextEmphasisColor
+webkitTextEmphasisPosition
+webkitTextEmphasisStyle
+webkitTextFillColor
+webkitTextOrientation
+webkitTextSecurity
+webkitTextStroke
+webkitTextStrokeColor
+webkitTextStrokeWidth
+webkitTransform
+webkitTransformOrigin
+webkitTransformOriginX
+webkitTransformOriginY
+webkitTransformOriginZ
+webkitTransformStyle
+webkitTransition
+webkitTransitionDelay
+webkitTransitionDuration
+webkitTransitionProperty
+webkitTransitionTimingFunction
+webkitUserDrag
+webkitUserModify
+webkitUserSelect
+webkitWritingMode
+whiteSpace
+widows
+width
+willChange
+wordBreak
+wordSpacing
+wordWrap
+writingMode
+zIndex
+zoom
diff --git a/tools/dom/scripts/cssProperties.ff36.txt b/tools/dom/scripts/cssProperties.ff36.txt
new file mode 100644
index 0000000..5b649d6
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.ff36.txt
@@ -0,0 +1,474 @@
+# Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0
+# 472 properties
+MozAnimation
+MozAnimationDelay
+MozAnimationDirection
+MozAnimationDuration
+MozAnimationFillMode
+MozAnimationIterationCount
+MozAnimationName
+MozAnimationPlayState
+MozAnimationTimingFunction
+MozAppearance
+MozBackfaceVisibility
+MozBinding
+MozBorderBottomColors
+MozBorderEnd
+MozBorderEndColor
+MozBorderEndStyle
+MozBorderEndWidth
+MozBorderImage
+MozBorderLeftColors
+MozBorderRightColors
+MozBorderStart
+MozBorderStartColor
+MozBorderStartStyle
+MozBorderStartWidth
+MozBorderTopColors
+MozBoxAlign
+MozBoxDirection
+MozBoxFlex
+MozBoxOrdinalGroup
+MozBoxOrient
+MozBoxPack
+MozBoxSizing
+MozColumnCount
+MozColumnFill
+MozColumnGap
+MozColumnRule
+MozColumnRuleColor
+MozColumnRuleStyle
+MozColumnRuleWidth
+MozColumnWidth
+MozColumns
+MozFloatEdge
+MozFontFeatureSettings
+MozFontLanguageOverride
+MozForceBrokenImageIcon
+MozHyphens
+MozImageRegion
+MozMarginEnd
+MozMarginStart
+MozOrient
+MozOutlineRadius
+MozOutlineRadiusBottomleft
+MozOutlineRadiusBottomright
+MozOutlineRadiusTopleft
+MozOutlineRadiusTopright
+MozPaddingEnd
+MozPaddingStart
+MozPerspective
+MozPerspectiveOrigin
+MozStackSizing
+MozTabSize
+MozTextAlignLast
+MozTextDecorationColor
+MozTextDecorationLine
+MozTextDecorationStyle
+MozTextSizeAdjust
+MozTransform
+MozTransformOrigin
+MozTransformStyle
+MozTransition
+MozTransitionDelay
+MozTransitionDuration
+MozTransitionProperty
+MozTransitionTimingFunction
+MozUserFocus
+MozUserInput
+MozUserModify
+MozUserSelect
+MozWindowDragging
+MozWindowShadow
+align-content
+align-items
+align-self
+alignContent
+alignItems
+alignSelf
+all
+animation
+animation-delay
+animation-direction
+animation-duration
+animation-fill-mode
+animation-iteration-count
+animation-name
+animation-play-state
+animation-timing-function
+animationDelay
+animationDirection
+animationDuration
+animationFillMode
+animationIterationCount
+animationName
+animationPlayState
+animationTimingFunction
+backface-visibility
+backfaceVisibility
+background
+background-attachment
+background-blend-mode
+background-clip
+background-color
+background-image
+background-origin
+background-position
+background-repeat
+background-size
+backgroundAttachment
+backgroundBlendMode
+backgroundClip
+backgroundColor
+backgroundImage
+backgroundOrigin
+backgroundPosition
+backgroundRepeat
+backgroundSize
+border
+border-bottom
+border-bottom-color
+border-bottom-left-radius
+border-bottom-right-radius
+border-bottom-style
+border-bottom-width
+border-collapse
+border-color
+border-image
+border-image-outset
+border-image-repeat
+border-image-slice
+border-image-source
+border-image-width
+border-left
+border-left-color
+border-left-style
+border-left-width
+border-radius
+border-right
+border-right-color
+border-right-style
+border-right-width
+border-spacing
+border-style
+border-top
+border-top-color
+border-top-left-radius
+border-top-right-radius
+border-top-style
+border-top-width
+border-width
+borderBottom
+borderBottomColor
+borderBottomLeftRadius
+borderBottomRightRadius
+borderBottomStyle
+borderBottomWidth
+borderCollapse
+borderColor
+borderImage
+borderImageOutset
+borderImageRepeat
+borderImageSlice
+borderImageSource
+borderImageWidth
+borderLeft
+borderLeftColor
+borderLeftStyle
+borderLeftWidth
+borderRadius
+borderRight
+borderRightColor
+borderRightStyle
+borderRightWidth
+borderSpacing
+borderStyle
+borderTop
+borderTopColor
+borderTopLeftRadius
+borderTopRightRadius
+borderTopStyle
+borderTopWidth
+borderWidth
+bottom
+box-decoration-break
+box-shadow
+box-sizing
+boxDecorationBreak
+boxShadow
+boxSizing
+caption-side
+captionSide
+clear
+clip
+clip-path
+clip-rule
+clipPath
+clipRule
+color
+color-interpolation
+color-interpolation-filters
+colorInterpolation
+colorInterpolationFilters
+content
+counter-increment
+counter-reset
+counterIncrement
+counterReset
+cssFloat
+cssText
+cursor
+direction
+display
+dominant-baseline
+dominantBaseline
+empty-cells
+emptyCells
+fill
+fill-opacity
+fill-rule
+fillOpacity
+fillRule
+filter
+flex
+flex-basis
+flex-direction
+flex-flow
+flex-grow
+flex-shrink
+flex-wrap
+flexBasis
+flexDirection
+flexFlow
+flexGrow
+flexShrink
+flexWrap
+float
+flood-color
+flood-opacity
+floodColor
+floodOpacity
+font
+font-family
+font-feature-settings
+font-kerning
+font-language-override
+font-size
+font-size-adjust
+font-stretch
+font-style
+font-synthesis
+font-variant
+font-variant-alternates
+font-variant-caps
+font-variant-east-asian
+font-variant-ligatures
+font-variant-numeric
+font-variant-position
+font-weight
+fontFamily
+fontFeatureSettings
+fontKerning
+fontLanguageOverride
+fontSize
+fontSizeAdjust
+fontStretch
+fontStyle
+fontSynthesis
+fontVariant
+fontVariantAlternates
+fontVariantCaps
+fontVariantEastAsian
+fontVariantLigatures
+fontVariantNumeric
+fontVariantPosition
+fontWeight
+height
+image-orientation
+image-rendering
+imageOrientation
+imageRendering
+ime-mode
+imeMode
+isolation
+justify-content
+justifyContent
+left
+letter-spacing
+letterSpacing
+lighting-color
+lightingColor
+line-height
+lineHeight
+list-style
+list-style-image
+list-style-position
+list-style-type
+listStyle
+listStyleImage
+listStylePosition
+listStyleType
+margin
+margin-bottom
+margin-left
+margin-right
+margin-top
+marginBottom
+marginLeft
+marginRight
+marginTop
+marker
+marker-end
+marker-mid
+marker-offset
+marker-start
+markerEnd
+markerMid
+markerOffset
+markerStart
+marks
+mask
+mask-type
+maskType
+max-height
+max-width
+maxHeight
+maxWidth
+min-height
+min-width
+minHeight
+minWidth
+mix-blend-mode
+mixBlendMode
+object-fit
+object-position
+objectFit
+objectPosition
+opacity
+order
+orphans
+outline
+outline-color
+outline-offset
+outline-style
+outline-width
+outlineColor
+outlineOffset
+outlineStyle
+outlineWidth
+overflow
+overflow-x
+overflow-y
+overflowX
+overflowY
+padding
+padding-bottom
+padding-left
+padding-right
+padding-top
+paddingBottom
+paddingLeft
+paddingRight
+paddingTop
+page
+page-break-after
+page-break-before
+page-break-inside
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+paint-order
+paintOrder
+perspective
+perspective-origin
+perspectiveOrigin
+pointer-events
+pointerEvents
+position
+quotes
+resize
+right
+scroll-behavior
+scrollBehavior
+shape-rendering
+shapeRendering
+size
+stop-color
+stop-opacity
+stopColor
+stopOpacity
+stroke
+stroke-dasharray
+stroke-dashoffset
+stroke-linecap
+stroke-linejoin
+stroke-miterlimit
+stroke-opacity
+stroke-width
+strokeDasharray
+strokeDashoffset
+strokeLinecap
+strokeLinejoin
+strokeMiterlimit
+strokeOpacity
+strokeWidth
+table-layout
+tableLayout
+text-align
+text-anchor
+text-decoration
+text-decoration-color
+text-decoration-line
+text-decoration-style
+text-indent
+text-overflow
+text-rendering
+text-shadow
+text-transform
+textAlign
+textAnchor
+textDecoration
+textDecorationColor
+textDecorationLine
+textDecorationStyle
+textIndent
+textOverflow
+textRendering
+textShadow
+textTransform
+top
+transform
+transform-origin
+transform-style
+transformOrigin
+transformStyle
+transition
+transition-delay
+transition-duration
+transition-property
+transition-timing-function
+transitionDelay
+transitionDuration
+transitionProperty
+transitionTimingFunction
+unicode-bidi
+unicodeBidi
+vector-effect
+vectorEffect
+vertical-align
+verticalAlign
+visibility
+white-space
+whiteSpace
+widows
+width
+will-change
+willChange
+word-break
+word-spacing
+word-wrap
+wordBreak
+wordSpacing
+wordWrap
+z-index
+zIndex
diff --git a/tools/dom/scripts/cssProperties.html b/tools/dom/scripts/cssProperties.html
new file mode 100644
index 0000000..a2d8bc4
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.html
@@ -0,0 +1,25 @@
+<!--
+Run this file in a browser to get the CSSStyleDeclaration properties
+available in that browser
+-->
+<body>
+<script>
+function emit(text) {
+  var e = document.createElement('div');
+  e.innerHTML = text;
+  document.body.appendChild(e);
+}
+emit('# ' + navigator.userAgent);
+var s = document.body.style;
+var a = [];
+for (var p in s) {
+  if (typeof s[p] != 'string') continue;
+  a.push(p);
+}
+a.sort();
+emit('# ' + a.length + ' properties')
+for (var i = 0; i < a.length; i++) {
+  emit(a[i]);
+}
+</script>
+</body>
diff --git a/tools/dom/scripts/cssProperties.iPad4Air.onGoogleSites.txt b/tools/dom/scripts/cssProperties.iPad4Air.onGoogleSites.txt
new file mode 100644
index 0000000..5186ff4
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.iPad4Air.onGoogleSites.txt
@@ -0,0 +1,159 @@
+# Mozilla/5.0 (iPad; CPU OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12D508 Safari/600.1.4
+# 157 properties
+animation
+animationDelay
+animationDirection
+animationDuration
+animationFillMode
+animationIterationCount
+animationName
+animationPlayState
+animationTimingFunction
+appearance
+azimuth
+backfaceVisibility
+background
+backgroundAttachment
+backgroundColor
+backgroundImage
+backgroundPosition
+backgroundRepeat
+backgroundSize
+border
+borderBottom
+borderBottomColor
+borderBottomLeftRadius
+borderBottomRightRadius
+borderBottomStyle
+borderBottomWidth
+borderCollapse
+borderColor
+borderLeft
+borderLeftColor
+borderLeftStyle
+borderLeftWidth
+borderRadius
+borderRight
+borderRightColor
+borderRightStyle
+borderRightWidth
+borderSpacing
+borderStyle
+borderTop
+borderTopColor
+borderTopLeftRadius
+borderTopRightRadius
+borderTopStyle
+borderTopWidth
+borderWidth
+bottom
+box
+boxShadow
+boxSizing
+captionSide
+clear
+clip
+color
+content
+cssFloat
+cue
+cueAfter
+cueBefore
+cursor
+direction
+display
+displayExtras
+displayInside
+displayOutside
+elevation
+emptyCells
+filter
+font
+fontFamily
+fontSize
+fontStretch
+fontStyle
+fontVariant
+fontWeight
+height
+left
+letterSpacing
+lineHeight
+listStyle
+listStyleImage
+listStylePosition
+listStyleType
+margin
+marginBottom
+marginLeft
+marginRight
+marginTop
+maxHeight
+maxWidth
+minHeight
+minWidth
+opacity
+outline
+outlineColor
+outlineStyle
+outlineWidth
+overflow
+overflowWrap
+overflowX
+overflowY
+padding
+paddingBottom
+paddingLeft
+paddingRight
+paddingTop
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+pause
+pauseAfter
+pauseBefore
+perspective
+perspectiveOrigin
+pitch
+pitchRange
+playDuring
+position
+quotes
+resize
+richness
+right
+speak
+speakHeader
+speakNumeral
+speakPunctuation
+speechRate
+stress
+tableLayout
+textAlign
+textDecoration
+textIndent
+textOverflow
+textShadow
+textTransform
+textWrap
+top
+transform
+transformOrigin
+transformStyle
+transition
+transitionDelay
+transitionDuration
+transitionProperty
+transitionTimingFunction
+unicodeBidi
+verticalAlign
+visibility
+voiceFamily
+volume
+whiteSpace
+width
+wordBreak
+wordSpacing
+wordWrap
+zIndex
+zoom
diff --git a/tools/dom/scripts/cssProperties.ie10.txt b/tools/dom/scripts/cssProperties.ie10.txt
new file mode 100644
index 0000000..57ed3ec
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.ie10.txt
@@ -0,0 +1,296 @@
+# Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Win64; x64; Trident/7.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
+# 294 properties
+accelerator
+alignmentBaseline
+animation
+animationDelay
+animationDirection
+animationDuration
+animationFillMode
+animationIterationCount
+animationName
+animationPlayState
+animationTimingFunction
+backfaceVisibility
+background
+backgroundAttachment
+backgroundClip
+backgroundColor
+backgroundImage
+backgroundOrigin
+backgroundPosition
+backgroundPositionX
+backgroundPositionY
+backgroundRepeat
+backgroundSize
+baselineShift
+behavior
+border
+borderBottom
+borderBottomColor
+borderBottomLeftRadius
+borderBottomRightRadius
+borderBottomStyle
+borderBottomWidth
+borderCollapse
+borderColor
+borderLeft
+borderLeftColor
+borderLeftStyle
+borderLeftWidth
+borderRadius
+borderRight
+borderRightColor
+borderRightStyle
+borderRightWidth
+borderSpacing
+borderStyle
+borderTop
+borderTopColor
+borderTopLeftRadius
+borderTopRightRadius
+borderTopStyle
+borderTopWidth
+borderWidth
+bottom
+boxShadow
+boxSizing
+breakAfter
+breakBefore
+breakInside
+captionSide
+clear
+clip
+clipPath
+clipRule
+color
+colorInterpolationFilters
+columnCount
+columnFill
+columnGap
+columnRule
+columnRuleColor
+columnRuleStyle
+columnRuleWidth
+columnSpan
+columnWidth
+columns
+content
+counterIncrement
+counterReset
+cssFloat
+cssText
+cursor
+direction
+display
+dominantBaseline
+emptyCells
+enableBackground
+fill
+fillOpacity
+fillRule
+filter
+floodColor
+floodOpacity
+font
+fontFamily
+fontFeatureSettings
+fontSize
+fontSizeAdjust
+fontStretch
+fontStyle
+fontVariant
+fontWeight
+glyphOrientationHorizontal
+glyphOrientationVertical
+height
+imeMode
+kerning
+layoutFlow
+layoutGrid
+layoutGridChar
+layoutGridLine
+layoutGridMode
+layoutGridType
+left
+letterSpacing
+lightingColor
+lineBreak
+lineHeight
+listStyle
+listStyleImage
+listStylePosition
+listStyleType
+margin
+marginBottom
+marginLeft
+marginRight
+marginTop
+marker
+markerEnd
+markerMid
+markerStart
+mask
+maxHeight
+maxWidth
+minHeight
+minWidth
+msAnimation
+msAnimationDelay
+msAnimationDirection
+msAnimationDuration
+msAnimationFillMode
+msAnimationIterationCount
+msAnimationName
+msAnimationPlayState
+msAnimationTimingFunction
+msBackfaceVisibility
+msBlockProgression
+msContentZoomChaining
+msContentZoomLimit
+msContentZoomLimitMax
+msContentZoomLimitMin
+msContentZoomSnap
+msContentZoomSnapPoints
+msContentZoomSnapType
+msContentZooming
+msFlex
+msFlexAlign
+msFlexDirection
+msFlexFlow
+msFlexItemAlign
+msFlexLinePack
+msFlexNegative
+msFlexOrder
+msFlexPack
+msFlexPositive
+msFlexPreferredSize
+msFlexWrap
+msFlowFrom
+msFlowInto
+msFontFeatureSettings
+msGridColumn
+msGridColumnAlign
+msGridColumnSpan
+msGridColumns
+msGridRow
+msGridRowAlign
+msGridRowSpan
+msGridRows
+msHighContrastAdjust
+msHyphenateLimitChars
+msHyphenateLimitLines
+msHyphenateLimitZone
+msHyphens
+msInterpolationMode
+msOverflowStyle
+msPerspective
+msPerspectiveOrigin
+msScrollChaining
+msScrollLimit
+msScrollLimitXMax
+msScrollLimitXMin
+msScrollLimitYMax
+msScrollLimitYMin
+msScrollRails
+msScrollSnapPointsX
+msScrollSnapPointsY
+msScrollSnapType
+msScrollSnapX
+msScrollSnapY
+msScrollTranslation
+msTouchAction
+msTouchSelect
+msTransform
+msTransformOrigin
+msTransformStyle
+msTransition
+msTransitionDelay
+msTransitionDuration
+msTransitionProperty
+msTransitionTimingFunction
+msUserSelect
+msWrapFlow
+msWrapMargin
+msWrapThrough
+opacity
+orphans
+outline
+outlineColor
+outlineStyle
+outlineWidth
+overflow
+overflowX
+overflowY
+padding
+paddingBottom
+paddingLeft
+paddingRight
+paddingTop
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+perspective
+perspectiveOrigin
+pointerEvents
+position
+quotes
+right
+rubyAlign
+rubyOverhang
+rubyPosition
+scrollbar3dLightColor
+scrollbarArrowColor
+scrollbarBaseColor
+scrollbarDarkShadowColor
+scrollbarFaceColor
+scrollbarHighlightColor
+scrollbarShadowColor
+scrollbarTrackColor
+stopColor
+stopOpacity
+stroke
+strokeDasharray
+strokeDashoffset
+strokeLinecap
+strokeLinejoin
+strokeMiterlimit
+strokeOpacity
+strokeWidth
+styleFloat
+tableLayout
+textAlign
+textAlignLast
+textAnchor
+textAutospace
+textDecoration
+textIndent
+textJustify
+textJustifyTrim
+textKashida
+textKashidaSpace
+textOverflow
+textShadow
+textTransform
+textUnderlinePosition
+top
+transform
+transformOrigin
+transformStyle
+transition
+transitionDelay
+transitionDuration
+transitionProperty
+transitionTimingFunction
+unicodeBidi
+verticalAlign
+visibility
+whiteSpace
+widows
+width
+wordBreak
+wordSpacing
+wordWrap
+writingMode
+zIndex
+zoom
diff --git a/tools/dom/scripts/cssProperties.ie11.txt b/tools/dom/scripts/cssProperties.ie11.txt
new file mode 100644
index 0000000..2240ab3
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.ie11.txt
@@ -0,0 +1,316 @@
+# Mozilla/5.0 (Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; Tablet PC 2.0; rv:11.0) like Gecko
+# 314 properties
+accelerator
+alignContent
+alignItems
+alignSelf
+alignmentBaseline
+animation
+animationDelay
+animationDirection
+animationDuration
+animationFillMode
+animationIterationCount
+animationName
+animationPlayState
+animationTimingFunction
+backfaceVisibility
+background
+backgroundAttachment
+backgroundClip
+backgroundColor
+backgroundImage
+backgroundOrigin
+backgroundPosition
+backgroundPositionX
+backgroundPositionY
+backgroundRepeat
+backgroundSize
+baselineShift
+border
+borderBottom
+borderBottomColor
+borderBottomLeftRadius
+borderBottomRightRadius
+borderBottomStyle
+borderBottomWidth
+borderCollapse
+borderColor
+borderImage
+borderImageOutset
+borderImageRepeat
+borderImageSlice
+borderImageSource
+borderImageWidth
+borderLeft
+borderLeftColor
+borderLeftStyle
+borderLeftWidth
+borderRadius
+borderRight
+borderRightColor
+borderRightStyle
+borderRightWidth
+borderSpacing
+borderStyle
+borderTop
+borderTopColor
+borderTopLeftRadius
+borderTopRightRadius
+borderTopStyle
+borderTopWidth
+borderWidth
+bottom
+boxShadow
+boxSizing
+breakAfter
+breakBefore
+breakInside
+captionSide
+clear
+clip
+clipPath
+clipRule
+color
+colorInterpolationFilters
+columnCount
+columnFill
+columnGap
+columnRule
+columnRuleColor
+columnRuleStyle
+columnRuleWidth
+columnSpan
+columnWidth
+columns
+content
+counterIncrement
+counterReset
+cssFloat
+cssText
+cursor
+direction
+display
+dominantBaseline
+emptyCells
+enableBackground
+fill
+fillOpacity
+fillRule
+filter
+flex
+flexBasis
+flexDirection
+flexFlow
+flexGrow
+flexShrink
+flexWrap
+floodColor
+floodOpacity
+font
+fontFamily
+fontFeatureSettings
+fontSize
+fontSizeAdjust
+fontStretch
+fontStyle
+fontVariant
+fontWeight
+glyphOrientationHorizontal
+glyphOrientationVertical
+height
+imeMode
+justifyContent
+kerning
+layoutFlow
+layoutGrid
+layoutGridChar
+layoutGridLine
+layoutGridMode
+layoutGridType
+left
+letterSpacing
+lightingColor
+lineBreak
+lineHeight
+listStyle
+listStyleImage
+listStylePosition
+listStyleType
+margin
+marginBottom
+marginLeft
+marginRight
+marginTop
+marker
+markerEnd
+markerMid
+markerStart
+mask
+maxHeight
+maxWidth
+minHeight
+minWidth
+msAnimation
+msAnimationDelay
+msAnimationDirection
+msAnimationDuration
+msAnimationFillMode
+msAnimationIterationCount
+msAnimationName
+msAnimationPlayState
+msAnimationTimingFunction
+msBackfaceVisibility
+msBlockProgression
+msContentZoomChaining
+msContentZoomLimit
+msContentZoomLimitMax
+msContentZoomLimitMin
+msContentZoomSnap
+msContentZoomSnapPoints
+msContentZoomSnapType
+msContentZooming
+msFlex
+msFlexAlign
+msFlexDirection
+msFlexFlow
+msFlexItemAlign
+msFlexLinePack
+msFlexNegative
+msFlexOrder
+msFlexPack
+msFlexPositive
+msFlexPreferredSize
+msFlexWrap
+msFlowFrom
+msFlowInto
+msFontFeatureSettings
+msGridColumn
+msGridColumnAlign
+msGridColumnSpan
+msGridColumns
+msGridRow
+msGridRowAlign
+msGridRowSpan
+msGridRows
+msHighContrastAdjust
+msHyphenateLimitChars
+msHyphenateLimitLines
+msHyphenateLimitZone
+msHyphens
+msImeAlign
+msInterpolationMode
+msOverflowStyle
+msPerspective
+msPerspectiveOrigin
+msScrollChaining
+msScrollLimit
+msScrollLimitXMax
+msScrollLimitXMin
+msScrollLimitYMax
+msScrollLimitYMin
+msScrollRails
+msScrollSnapPointsX
+msScrollSnapPointsY
+msScrollSnapType
+msScrollSnapX
+msScrollSnapY
+msScrollTranslation
+msTextCombineHorizontal
+msTouchAction
+msTouchSelect
+msTransform
+msTransformOrigin
+msTransformStyle
+msTransition
+msTransitionDelay
+msTransitionDuration
+msTransitionProperty
+msTransitionTimingFunction
+msUserSelect
+msWrapFlow
+msWrapMargin
+msWrapThrough
+opacity
+order
+orphans
+outline
+outlineColor
+outlineStyle
+outlineWidth
+overflow
+overflowX
+overflowY
+padding
+paddingBottom
+paddingLeft
+paddingRight
+paddingTop
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+perspective
+perspectiveOrigin
+pointerEvents
+position
+quotes
+right
+rubyAlign
+rubyOverhang
+rubyPosition
+scrollbar3dLightColor
+scrollbarArrowColor
+scrollbarBaseColor
+scrollbarDarkShadowColor
+scrollbarFaceColor
+scrollbarHighlightColor
+scrollbarShadowColor
+scrollbarTrackColor
+stopColor
+stopOpacity
+stroke
+strokeDasharray
+strokeDashoffset
+strokeLinecap
+strokeLinejoin
+strokeMiterlimit
+strokeOpacity
+strokeWidth
+styleFloat
+tableLayout
+textAlign
+textAlignLast
+textAnchor
+textAutospace
+textDecoration
+textIndent
+textJustify
+textJustifyTrim
+textKashida
+textKashidaSpace
+textOverflow
+textShadow
+textTransform
+textUnderlinePosition
+top
+touchAction
+transform
+transformOrigin
+transformStyle
+transition
+transitionDelay
+transitionDuration
+transitionProperty
+transitionTimingFunction
+unicodeBidi
+verticalAlign
+visibility
+whiteSpace
+widows
+width
+wordBreak
+wordSpacing
+wordWrap
+writingMode
+zIndex
+zoom
diff --git a/tools/dom/scripts/cssProperties.ie9.txt b/tools/dom/scripts/cssProperties.ie9.txt
new file mode 100644
index 0000000..035ba26
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.ie9.txt
@@ -0,0 +1,182 @@
+# Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/7.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
+# 180 properties
+accelerator
+alignmentBaseline
+background
+backgroundAttachment
+backgroundClip
+backgroundColor
+backgroundImage
+backgroundOrigin
+backgroundPosition
+backgroundPositionX
+backgroundPositionY
+backgroundRepeat
+backgroundSize
+baselineShift
+behavior
+border
+borderBottom
+borderBottomColor
+borderBottomLeftRadius
+borderBottomRightRadius
+borderBottomStyle
+borderBottomWidth
+borderCollapse
+borderColor
+borderLeft
+borderLeftColor
+borderLeftStyle
+borderLeftWidth
+borderRadius
+borderRight
+borderRightColor
+borderRightStyle
+borderRightWidth
+borderSpacing
+borderStyle
+borderTop
+borderTopColor
+borderTopLeftRadius
+borderTopRightRadius
+borderTopStyle
+borderTopWidth
+borderWidth
+bottom
+boxShadow
+boxSizing
+captionSide
+clear
+clip
+clipPath
+clipRule
+color
+content
+counterIncrement
+counterReset
+cssFloat
+cssText
+cursor
+direction
+display
+dominantBaseline
+emptyCells
+fill
+fillOpacity
+fillRule
+filter
+font
+fontFamily
+fontSize
+fontSizeAdjust
+fontStretch
+fontStyle
+fontVariant
+fontWeight
+glyphOrientationHorizontal
+glyphOrientationVertical
+height
+imeMode
+kerning
+layoutFlow
+layoutGrid
+layoutGridChar
+layoutGridLine
+layoutGridMode
+layoutGridType
+left
+letterSpacing
+lineBreak
+lineHeight
+listStyle
+listStyleImage
+listStylePosition
+listStyleType
+margin
+marginBottom
+marginLeft
+marginRight
+marginTop
+marker
+markerEnd
+markerMid
+markerStart
+mask
+maxHeight
+maxWidth
+minHeight
+minWidth
+msBlockProgression
+msInterpolationMode
+msTransform
+msTransformOrigin
+opacity
+orphans
+outline
+outlineColor
+outlineStyle
+outlineWidth
+overflow
+overflowX
+overflowY
+padding
+paddingBottom
+paddingLeft
+paddingRight
+paddingTop
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+pointerEvents
+position
+quotes
+right
+rubyAlign
+rubyOverhang
+rubyPosition
+scrollbar3dLightColor
+scrollbarArrowColor
+scrollbarBaseColor
+scrollbarDarkShadowColor
+scrollbarFaceColor
+scrollbarHighlightColor
+scrollbarShadowColor
+scrollbarTrackColor
+stopColor
+stopOpacity
+stroke
+strokeDasharray
+strokeDashoffset
+strokeLinecap
+strokeLinejoin
+strokeMiterlimit
+strokeOpacity
+strokeWidth
+styleFloat
+tableLayout
+textAlign
+textAlignLast
+textAnchor
+textAutospace
+textDecoration
+textIndent
+textJustify
+textJustifyTrim
+textKashida
+textKashidaSpace
+textOverflow
+textTransform
+textUnderlinePosition
+top
+unicodeBidi
+verticalAlign
+visibility
+whiteSpace
+widows
+width
+wordBreak
+wordSpacing
+wordWrap
+writingMode
+zIndex
+zoom
diff --git a/tools/dom/scripts/cssProperties.mobileSafari-8.2.txt b/tools/dom/scripts/cssProperties.mobileSafari-8.2.txt
new file mode 100644
index 0000000..5186ff4
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.mobileSafari-8.2.txt
@@ -0,0 +1,159 @@
+# Mozilla/5.0 (iPad; CPU OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12D508 Safari/600.1.4
+# 157 properties
+animation
+animationDelay
+animationDirection
+animationDuration
+animationFillMode
+animationIterationCount
+animationName
+animationPlayState
+animationTimingFunction
+appearance
+azimuth
+backfaceVisibility
+background
+backgroundAttachment
+backgroundColor
+backgroundImage
+backgroundPosition
+backgroundRepeat
+backgroundSize
+border
+borderBottom
+borderBottomColor
+borderBottomLeftRadius
+borderBottomRightRadius
+borderBottomStyle
+borderBottomWidth
+borderCollapse
+borderColor
+borderLeft
+borderLeftColor
+borderLeftStyle
+borderLeftWidth
+borderRadius
+borderRight
+borderRightColor
+borderRightStyle
+borderRightWidth
+borderSpacing
+borderStyle
+borderTop
+borderTopColor
+borderTopLeftRadius
+borderTopRightRadius
+borderTopStyle
+borderTopWidth
+borderWidth
+bottom
+box
+boxShadow
+boxSizing
+captionSide
+clear
+clip
+color
+content
+cssFloat
+cue
+cueAfter
+cueBefore
+cursor
+direction
+display
+displayExtras
+displayInside
+displayOutside
+elevation
+emptyCells
+filter
+font
+fontFamily
+fontSize
+fontStretch
+fontStyle
+fontVariant
+fontWeight
+height
+left
+letterSpacing
+lineHeight
+listStyle
+listStyleImage
+listStylePosition
+listStyleType
+margin
+marginBottom
+marginLeft
+marginRight
+marginTop
+maxHeight
+maxWidth
+minHeight
+minWidth
+opacity
+outline
+outlineColor
+outlineStyle
+outlineWidth
+overflow
+overflowWrap
+overflowX
+overflowY
+padding
+paddingBottom
+paddingLeft
+paddingRight
+paddingTop
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+pause
+pauseAfter
+pauseBefore
+perspective
+perspectiveOrigin
+pitch
+pitchRange
+playDuring
+position
+quotes
+resize
+richness
+right
+speak
+speakHeader
+speakNumeral
+speakPunctuation
+speechRate
+stress
+tableLayout
+textAlign
+textDecoration
+textIndent
+textOverflow
+textShadow
+textTransform
+textWrap
+top
+transform
+transformOrigin
+transformStyle
+transition
+transitionDelay
+transitionDuration
+transitionProperty
+transitionTimingFunction
+unicodeBidi
+verticalAlign
+visibility
+voiceFamily
+volume
+whiteSpace
+width
+wordBreak
+wordSpacing
+wordWrap
+zIndex
+zoom
diff --git a/tools/dom/scripts/cssProperties.safari-7.1.3.txt b/tools/dom/scripts/cssProperties.safari-7.1.3.txt
new file mode 100644
index 0000000..15e1a61
--- /dev/null
+++ b/tools/dom/scripts/cssProperties.safari-7.1.3.txt
@@ -0,0 +1,399 @@
+# Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.3.18 (KHTML, like Gecko) Version/7.1.3 Safari/537.85.12
+# 397 properties
+alignmentBaseline
+background
+backgroundAttachment
+backgroundBlendMode
+backgroundClip
+backgroundColor
+backgroundImage
+backgroundOrigin
+backgroundPosition
+backgroundPositionX
+backgroundPositionY
+backgroundRepeat
+backgroundRepeatX
+backgroundRepeatY
+backgroundSize
+baselineShift
+border
+borderBottom
+borderBottomColor
+borderBottomLeftRadius
+borderBottomRightRadius
+borderBottomStyle
+borderBottomWidth
+borderCollapse
+borderColor
+borderImage
+borderImageOutset
+borderImageRepeat
+borderImageSlice
+borderImageSource
+borderImageWidth
+borderLeft
+borderLeftColor
+borderLeftStyle
+borderLeftWidth
+borderRadius
+borderRight
+borderRightColor
+borderRightStyle
+borderRightWidth
+borderSpacing
+borderStyle
+borderTop
+borderTopColor
+borderTopLeftRadius
+borderTopRightRadius
+borderTopStyle
+borderTopWidth
+borderWidth
+bottom
+boxShadow
+boxSizing
+bufferedRendering
+captionSide
+clear
+clip
+clipPath
+clipRule
+color
+colorInterpolation
+colorInterpolationFilters
+colorProfile
+colorRendering
+content
+counterIncrement
+counterReset
+cssText
+cursor
+direction
+display
+dominantBaseline
+emptyCells
+enableBackground
+fill
+fillOpacity
+fillRule
+filter
+float
+floodColor
+floodOpacity
+font
+fontFamily
+fontSize
+fontStretch
+fontStyle
+fontVariant
+fontWeight
+glyphOrientationHorizontal
+glyphOrientationVertical
+height
+imageRendering
+isolation
+kerning
+left
+letterSpacing
+lightingColor
+lineHeight
+listStyle
+listStyleImage
+listStylePosition
+listStyleType
+margin
+marginBottom
+marginLeft
+marginRight
+marginTop
+marker
+markerEnd
+markerMid
+markerStart
+mask
+maskType
+maxHeight
+maxWidth
+minHeight
+minWidth
+mixBlendMode
+objectFit
+opacity
+orphans
+outline
+outlineColor
+outlineOffset
+outlineStyle
+outlineWidth
+overflow
+overflowWrap
+overflowX
+overflowY
+padding
+paddingBottom
+paddingLeft
+paddingRight
+paddingTop
+page
+pageBreakAfter
+pageBreakBefore
+pageBreakInside
+paintOrder
+pointerEvents
+position
+quotes
+resize
+right
+shapeRendering
+size
+speak
+src
+stopColor
+stopOpacity
+stroke
+strokeDasharray
+strokeDashoffset
+strokeLinecap
+strokeLinejoin
+strokeMiterlimit
+strokeOpacity
+strokeWidth
+tabSize
+tableLayout
+textAlign
+textAnchor
+textDecoration
+textIndent
+textLineThrough
+textLineThroughColor
+textLineThroughMode
+textLineThroughStyle
+textLineThroughWidth
+textOverflow
+textOverline
+textOverlineColor
+textOverlineMode
+textOverlineStyle
+textOverlineWidth
+textRendering
+textShadow
+textTransform
+textUnderline
+textUnderlineColor
+textUnderlineMode
+textUnderlineStyle
+textUnderlineWidth
+top
+transition
+transitionDelay
+transitionDuration
+transitionProperty
+transitionTimingFunction
+unicodeBidi
+unicodeRange
+vectorEffect
+verticalAlign
+visibility
+webkitAlignContent
+webkitAlignItems
+webkitAlignSelf
+webkitAlt
+webkitAnimation
+webkitAnimationDelay
+webkitAnimationDirection
+webkitAnimationDuration
+webkitAnimationFillMode
+webkitAnimationIterationCount
+webkitAnimationName
+webkitAnimationPlayState
+webkitAnimationTimingFunction
+webkitAppearance
+webkitAspectRatio
+webkitBackfaceVisibility
+webkitBackgroundClip
+webkitBackgroundComposite
+webkitBackgroundOrigin
+webkitBackgroundSize
+webkitBorderAfter
+webkitBorderAfterColor
+webkitBorderAfterStyle
+webkitBorderAfterWidth
+webkitBorderBefore
+webkitBorderBeforeColor
+webkitBorderBeforeStyle
+webkitBorderBeforeWidth
+webkitBorderEnd
+webkitBorderEndColor
+webkitBorderEndStyle
+webkitBorderEndWidth
+webkitBorderFit
+webkitBorderHorizontalSpacing
+webkitBorderImage
+webkitBorderRadius
+webkitBorderStart
+webkitBorderStartColor
+webkitBorderStartStyle
+webkitBorderStartWidth
+webkitBorderVerticalSpacing
+webkitBoxAlign
+webkitBoxDecorationBreak
+webkitBoxDirection
+webkitBoxFlex
+webkitBoxFlexGroup
+webkitBoxLines
+webkitBoxOrdinalGroup
+webkitBoxOrient
+webkitBoxPack
+webkitBoxReflect
+webkitBoxShadow
+webkitClipPath
+webkitColorCorrection
+webkitColumnAxis
+webkitColumnBreakAfter
+webkitColumnBreakBefore
+webkitColumnBreakInside
+webkitColumnCount
+webkitColumnFill
+webkitColumnGap
+webkitColumnProgression
+webkitColumnRule
+webkitColumnRuleColor
+webkitColumnRuleStyle
+webkitColumnRuleWidth
+webkitColumnSpan
+webkitColumnWidth
+webkitColumns
+webkitCursorVisibility
+webkitDashboardRegion
+webkitFilter
+webkitFlex
+webkitFlexBasis
+webkitFlexDirection
+webkitFlexFlow
+webkitFlexGrow
+webkitFlexShrink
+webkitFlexWrap
+webkitFlowFrom
+webkitFlowInto
+webkitFontFeatureSettings
+webkitFontKerning
+webkitFontSizeDelta
+webkitFontSmoothing
+webkitFontVariantLigatures
+webkitHyphenateCharacter
+webkitHyphenateLimitAfter
+webkitHyphenateLimitBefore
+webkitHyphenateLimitLines
+webkitHyphens
+webkitJustifyContent
+webkitJustifySelf
+webkitLineAlign
+webkitLineBoxContain
+webkitLineBreak
+webkitLineClamp
+webkitLineGrid
+webkitLineSnap
+webkitLocale
+webkitLogicalHeight
+webkitLogicalWidth
+webkitMarginAfter
+webkitMarginAfterCollapse
+webkitMarginBefore
+webkitMarginBeforeCollapse
+webkitMarginBottomCollapse
+webkitMarginCollapse
+webkitMarginEnd
+webkitMarginStart
+webkitMarginTopCollapse
+webkitMarquee
+webkitMarqueeDirection
+webkitMarqueeIncrement
+webkitMarqueeRepetition
+webkitMarqueeSpeed
+webkitMarqueeStyle
+webkitMask
+webkitMaskBoxImage
+webkitMaskBoxImageOutset
+webkitMaskBoxImageRepeat
+webkitMaskBoxImageSlice
+webkitMaskBoxImageSource
+webkitMaskBoxImageWidth
+webkitMaskClip
+webkitMaskComposite
+webkitMaskImage
+webkitMaskOrigin
+webkitMaskPosition
+webkitMaskPositionX
+webkitMaskPositionY
+webkitMaskRepeat
+webkitMaskRepeatX
+webkitMaskRepeatY
+webkitMaskSize
+webkitMaskSourceType
+webkitMaxLogicalHeight
+webkitMaxLogicalWidth
+webkitMinLogicalHeight
+webkitMinLogicalWidth
+webkitNbspMode
+webkitOrder
+webkitPaddingAfter
+webkitPaddingBefore
+webkitPaddingEnd
+webkitPaddingStart
+webkitPerspective
+webkitPerspectiveOrigin
+webkitPerspectiveOriginX
+webkitPerspectiveOriginY
+webkitPrintColorAdjust
+webkitRegionBreakAfter
+webkitRegionBreakBefore
+webkitRegionBreakInside
+webkitRegionFragment
+webkitRtlOrdering
+webkitRubyPosition
+webkitShapeImageThreshold
+webkitShapeMargin
+webkitShapeOutside
+webkitSvgShadow
+webkitTextCombine
+webkitTextDecoration
+webkitTextDecorationColor
+webkitTextDecorationLine
+webkitTextDecorationSkip
+webkitTextDecorationStyle
+webkitTextDecorationsInEffect
+webkitTextEmphasis
+webkitTextEmphasisColor
+webkitTextEmphasisPosition
+webkitTextEmphasisStyle
+webkitTextFillColor
+webkitTextOrientation
+webkitTextSecurity
+webkitTextStroke
+webkitTextStrokeColor
+webkitTextStrokeWidth
+webkitTextUnderlinePosition
+webkitTransform
+webkitTransformOrigin
+webkitTransformOriginX
+webkitTransformOriginY
+webkitTransformOriginZ
+webkitTransformStyle
+webkitTransition
+webkitTransitionDelay
+webkitTransitionDuration
+webkitTransitionProperty
+webkitTransitionTimingFunction
+webkitUserDrag
+webkitUserModify
+webkitUserSelect
+webkitWritingMode
+whiteSpace
+widows
+width
+wordBreak
+wordSpacing
+wordWrap
+writingMode
+zIndex
+zoom
diff --git a/tools/dom/scripts/css_code_generator.py b/tools/dom/scripts/css_code_generator.py
index a290c5f..fc437dd 100644
--- a/tools/dom/scripts/css_code_generator.py
+++ b/tools/dom/scripts/css_code_generator.py
@@ -7,7 +7,7 @@
 """Generates CSSStyleDeclaration template file from css property definitions
 defined in WebKit."""
 
-import tempfile, os
+import tempfile, os, re
 
 COMMENT_LINE_PREFIX = '   * '
 # TODO(efortuna): Pull from DEPS so that we have latest css *in sync* with our
@@ -16,6 +16,20 @@
 #SOURCE_PATH = 'Source/WebCore/css/CSSPropertyNames.in'
 TEMPLATE_FILE = '../templates/html/impl/impl_CSSStyleDeclaration.darttemplate'
 
+# These are the properties that are supported on all Dart project supported
+# browsers as camelCased names on the CssStyleDeclaration.
+BROWSER_PATHS = [
+    'cssProperties.CSS21.txt',  # Remove when we have samples from all browsers.
+    'cssProperties.ie9.txt',
+    'cssProperties.ie10.txt',
+    'cssProperties.ie11.txt',
+    'cssProperties.ff36.txt',
+    'cssProperties.chrome40.txt',
+    'cssProperties.safari-7.1.3.txt',
+    'cssProperties.mobileSafari-8.2.txt',
+    'cssProperties.iPad4Air.onGoogleSites.txt',
+    ]
+
 # Supported annotations for any specific CSS properties.
 annotated = {
   'transition': '''@SupportedBrowser(SupportedBrowser.CHROME)
@@ -24,6 +38,12 @@
   @SupportedBrowser(SupportedBrowser.SAFARI)'''
 }
 
+class Error:
+  def __init__(self, message):
+    self.message = message
+  def __repr__(self):
+    return self.message
+
 def camelCaseName(name):
   """Convert a CSS property name to a lowerCamelCase name."""
   name = name.replace('-webkit-', '')
@@ -35,17 +55,35 @@
       words.append(word)
   return ''.join(words)
 
+def dashifyName(camelName):
+  def fix(match):
+    return '-' + match.group(0).lower()
+  return re.sub(r'[A-Z]', fix, camelName)
+
+def isCommentLine(line):
+  return line.strip() == '' or line.startswith('#') or line.startswith('//')
+
+def readCssProperties(filename):
+  data = open(filename).readlines()
+  data = sorted([d.strip() for d in set(data) if not isCommentLine(d)])
+  return data
+
 def GenerateCssTemplateFile():
   data = open(SOURCE_PATH).readlines()
 
   # filter CSSPropertyNames.in to only the properties
   # TODO(efortuna): do we also want CSSPropertyNames.in?
-  data = [d[:-1] for d in data
-          if len(d) > 1
-          and not d.startswith('#')
-          and not d.startswith('//')
+  data = [d.strip() for d in data
+          if not isCommentLine(d)
           and not '=' in d]
 
+  browser_props = [readCssProperties(file) for file in BROWSER_PATHS]
+  universal_properties = reduce(
+        lambda a, b: set(a).intersection(b), browser_props)
+  universal_properties = universal_properties.difference(['cssText'])
+  universal_properties = universal_properties.intersection(
+        map(camelCaseName, data))
+
   class_file = open(TEMPLATE_FILE, 'w')
 
   class_file.write("""
@@ -60,8 +98,11 @@
 //   %s
 
 part of $LIBRARYNAME;
+""" % SOURCE_PATH)
 
-$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS) class $CLASSNAME $EXTENDS with
+
+  class_file.write("""
+$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME $EXTENDS with
     $(CLASSNAME)Base $IMPLEMENTS {
   factory $CLASSNAME() => new CssStyleDeclaration.css('');
 
@@ -117,14 +158,34 @@
 
   @DomName('CSSStyleDeclaration.setProperty')
   void setProperty(String propertyName, String value, [String priority]) {
-    if (_supportsProperty(_camelCase(propertyName))) {
-      return _setPropertyHelper(propertyName, value, priority);
-    } else {
-      return _setPropertyHelper(Device.cssPrefix + propertyName, value,
-          priority);
-    }
+    return _setPropertyHelper(_browserPropertyName(propertyName),
+      value, priority);
   }
 
+  String _browserPropertyName(String propertyName) {
+    String name = _readCache(propertyName);
+    if (name is String) return name;
+    if (_supportsProperty(_camelCase(propertyName))) {
+      name = propertyName;
+    } else {
+      name = Device.cssPrefix + propertyName;
+    }
+    _writeCache(propertyName, name);
+    return name;
+  }
+
+$if DART2JS
+  static final _propertyCache = JS('', '{}');
+  static String _readCache(String key) =>
+    JS('String|Null', '#[#]', _propertyCache, key);
+  static void _writeCache(String key, String value) {
+    JS('void', '#[#] = #', _propertyCache, key, value);
+  }
+$else
+  static String _readCache(String key) => null;
+  static void _writeCache(String key, value) {}
+$endif
+
   static String _camelCase(String hyphenated) {
 $if DART2JS
     var replacedMs = JS('String', r'#.replace(/^-ms-/, "ms-")', hyphenated);
@@ -142,18 +203,9 @@
 
 $if DART2JS
   void _setPropertyHelper(String propertyName, String value, [String priority]) {
-    // try/catch for IE9 which throws on unsupported values.
-    try {
-      if (value == null) value = '';
-      if (priority == null) {
-        priority = '';
-      }
-      JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
-      // Bug #2772, IE9 requires a poke to actually apply the value.
-      if (JS('bool', '!!#.setAttribute', this)) {
-        JS('void', '#.setAttribute(#, #)', this, propertyName, value);
-      }
-    } catch (e) {}
+    if (value == null) value = '';
+    if (priority == null) priority = '';
+    JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
   }
 
   /**
@@ -176,6 +228,28 @@
   static bool get supportsTransitions => true;
 $endif
 $!MEMBERS
+$if DART2JS
+""")
+
+  for camelName in sorted(universal_properties):
+    property = dashifyName(camelName)
+    class_file.write("""
+  /** Gets the value of "%s" */
+  String get %s => this._%s;
+
+  /** Sets the value of "%s" */
+  void set %s(String value) {
+    _%s = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('%s')
+  String _%s;
+    """ % (property, camelName, camelName,
+           property, camelName, camelName,
+           camelName, camelName))
+
+  class_file.write("""
+$endif
 }
 
 class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
@@ -195,6 +269,32 @@
     _elementCssStyleDeclarationSetIterable.forEach((e) =>
         e.setProperty(propertyName, value, priority));
   }
+
+""")
+
+  class_file.write("""
+$if DART2JS
+  void _setAll(String propertyName, String value) {
+    value = value == null ? '' : value;
+    for (Element element in _elementIterable) {
+      JS('void', '#.style[#] = #', element, propertyName, value);
+    }
+  }
+""")
+
+
+  for camelName in sorted(universal_properties):
+    property = dashifyName(camelName)
+    class_file.write("""
+  /** Sets the value of "%s" */
+  void set %s(String value) {
+    _setAll('%s', value);
+  }
+    """ % (property, camelName, camelName))
+
+  class_file.write("""
+$endif
+
   // Important note: CssStyleDeclarationSet does NOT implement every method
   // available in CssStyleDeclaration. Some of the methods don't make so much
   // sense in terms of having a resonable value to return when you're
@@ -205,12 +305,12 @@
 abstract class CssStyleDeclarationBase {
   String getPropertyValue(String propertyName);
   void setProperty(String propertyName, String value, [String priority]);
-""" % SOURCE_PATH)
+""")
 
   class_lines = [];
 
   seen = set()
-  for prop in sorted(data, key=lambda p: camelCaseName(p)):
+  for prop in sorted(data, key=camelCaseName):
     camel_case_name = camelCaseName(prop)
     upper_camel_case_name = camel_case_name[0].upper() + camel_case_name[1:];
     css_name = prop.replace('-webkit-', '')
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 6b66511..cb3e737 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -167,6 +167,8 @@
 
     'RTCIceCandidate': 'RTCIceCandidate,mozRTCIceCandidate',
 
+    'RTCIceCandidateEvent': 'RTCIceCandidateEvent,RTCPeerConnectionIceEvent', 
+
     'RTCSessionDescription': 'RTCSessionDescription,mozRTCSessionDescription',
 
     'RTCDataChannel': 'RTCDataChannel,DataChannel',
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 0b22ef7..0c405e4 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -13,6 +13,12 @@
    *
    * If [shouldAdd] is true, then we always add that [value] to the element. If
    * [shouldAdd] is false then we always remove [value] from the element.
+   *
+   * If this corresponds to one element, returns `true` if [value] is present
+   * after the operation, and returns `false` if [value] is absent after the
+   * operation.
+   *
+   * If this corresponds to many elements, `null` is always returned.
    */
   bool toggle(String value, [bool shouldAdd]);
 
@@ -39,7 +45,7 @@
    * If this corresponds to one element. Returns true if [value] was added to
    * the set, otherwise false.
    *
-   * If this corresponds to many elements, null is always returned.
+   * If this corresponds to many elements, `null` is always returned.
    */
   bool add(String value);
 
@@ -80,87 +86,3 @@
    */
   void toggleAll(Iterable<String> iterable, [bool shouldAdd]);
 }
-
-/**
- * A set (union) of the CSS classes that are present in a set of elements.
- * Implemented separately from _ElementCssClassSet for performance.
- */
-class _MultiElementCssClassSet extends CssClassSetImpl {
-  final Iterable<Element> _elementIterable;
-  Iterable<_ElementCssClassSet> _elementCssClassSetIterable;
-
-  _MultiElementCssClassSet(this._elementIterable) {
-    _elementCssClassSetIterable = new List.from(_elementIterable).map(
-        (e) => new _ElementCssClassSet(e));
-  }
-
-  Set<String> readClasses() {
-    var s = new LinkedHashSet<String>();
-    _elementCssClassSetIterable.forEach(
-        (_ElementCssClassSet e) => s.addAll(e.readClasses()));
-    return s;
-  }
-
-  void writeClasses(Set<String> s) {
-    var classes = s.join(' ');
-    for (Element e in _elementIterable) {
-      e.className = classes;
-    }
-  }
-
-  /**
-   * Helper method used to modify the set of css classes on this element.
-   *
-   *   f - callback with:
-   *   s - a Set of all the css class name currently on this element.
-   *
-   *   After f returns, the modified set is written to the
-   *       className property of this element.
-   */
-  modify( f(Set<String> s)) {
-    _elementCssClassSetIterable.forEach((_ElementCssClassSet e) => e.modify(f));
-  }
-
-  /**
-   * Adds the class [value] to the element if it is not on it, removes it if it
-   * is.
-   */
-  bool toggle(String value, [bool shouldAdd]) =>
-      _elementCssClassSetIterable.fold(false,
-          (bool changed, _ElementCssClassSet e) =>
-              e.toggle(value, shouldAdd) || changed);
-
-  /**
-   * Remove the class [value] from element, and return true on successful
-   * removal.
-   *
-   * This is the Dart equivalent of jQuery's
-   * [removeClass](http://api.jquery.com/removeClass/).
-   */
-  bool remove(Object value) => _elementCssClassSetIterable.fold(false,
-      (bool changed, _ElementCssClassSet e) => e.remove(value) || changed);
-}
-
-class _ElementCssClassSet extends CssClassSetImpl {
-
-  final Element _element;
-
-  _ElementCssClassSet(this._element);
-
-  Set<String> readClasses() {
-    var s = new LinkedHashSet<String>();
-    var classname = _element.className;
-
-    for (String name in classname.split(' ')) {
-      String trimmed = name.trim();
-      if (!trimmed.isEmpty) {
-        s.add(trimmed);
-      }
-    }
-    return s;
-  }
-
-  void writeClasses(Set<String> s) {
-    _element.className = s.join(' ');
-  }
-}
diff --git a/tools/dom/src/NodeValidatorBuilder.dart b/tools/dom/src/NodeValidatorBuilder.dart
index 41cab67..7ebeb36 100644
--- a/tools/dom/src/NodeValidatorBuilder.dart
+++ b/tools/dom/src/NodeValidatorBuilder.dart
@@ -453,6 +453,13 @@
     if (element is svg.ScriptElement) {
       return false;
     }
+    // Firefox 37 has issues with creating foreign elements inside a
+    // foreignobject tag as SvgElement. We don't want foreignobject contents
+    // anyway, so just remove the whole tree outright. And we can't rely
+    // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144
+    if (element is svg.SvgElement && element.tagName == 'foreignObject') {
+      return false;
+    }
     if (element is svg.SvgElement) {
       return true;
     }
diff --git a/tools/dom/src/Validators.dart b/tools/dom/src/Validators.dart
index 5154a9d..ac51da1 100644
--- a/tools/dom/src/Validators.dart
+++ b/tools/dom/src/Validators.dart
@@ -111,7 +111,7 @@
         _hiddenAnchor.protocol == _loc.protocol) ||
         (_hiddenAnchor.hostname == '' &&
         _hiddenAnchor.port == '' &&
-        _hiddenAnchor.protocol == ':');
+        (_hiddenAnchor.protocol == ':' || _hiddenAnchor.protocol == ''));
   }
 }
 
@@ -145,29 +145,46 @@
   _ValidatingTreeSanitizer(this.validator) {}
 
   void sanitizeTree(Node node) {
-    void walk(Node node) {
-      sanitizeNode(node);
+    void walk(Node node, Node parent) {
+      sanitizeNode(node, parent);
 
       var child = node.lastChild;
       while (child != null) {
         // Child may be removed during the walk.
         var nextChild = child.previousNode;
-        walk(child);
+        walk(child, node);
         child = nextChild;
       }
     }
-    walk(node);
+    walk(node, null);
   }
 
-  void sanitizeNode(Node node) {
+  /// Aggressively try to remove node.
+  void _removeNode(Node node, Node parent) {
+    // If we have the parent, it's presumably already passed more sanitization or
+    // is the fragment, so ask it to remove the child. And if that fails try to
+    // set the outer html.
+    if (parent == null) {
+      node.remove();
+    } else {
+      parent._removeChild(node);
+    }
+  }
+  
+  void sanitizeNode(Node node, Node parent) {
     switch (node.nodeType) {
       case Node.ELEMENT_NODE:
         Element element = node;
+        if (element._hasCorruptedAttributes) {
+          window.console.warn('Removing element due to corrupted attributes on <${element}>');
+          _removeNode(node, parent);
+          break;
+        }
         var attrs = element.attributes;
         if (!validator.allowsElement(element)) {
           window.console.warn(
               'Removing disallowed element <${element.tagName}>');
-          element.remove();
+          _removeNode(node, parent);
           break;
         }
 
@@ -176,7 +193,7 @@
           if (!validator.allowsAttribute(element, 'is', isAttr)) {
             window.console.warn('Removing disallowed type extension '
                 '<${element.tagName} is="$isAttr">');
-            element.remove();
+            _removeNode(node, parent);
             break;
           }
         }
@@ -205,7 +222,7 @@
       case Node.CDATA_SECTION_NODE:
         break;
       default:
-        node.remove();
+        _removeNode(node, parent);
     }
   }
 }
diff --git a/tools/dom/src/dart2js_CssClassSet.dart b/tools/dom/src/dart2js_CssClassSet.dart
new file mode 100644
index 0000000..783828b
--- /dev/null
+++ b/tools/dom/src/dart2js_CssClassSet.dart
@@ -0,0 +1,249 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of html;
+
+/**
+ * A set (union) of the CSS classes that are present in a set of elements.
+ * Implemented separately from _ElementCssClassSet for performance.
+ */
+class _MultiElementCssClassSet extends CssClassSetImpl {
+  final Iterable<Element> _elementIterable;
+
+  // TODO(sra): Perhaps we should store the DomTokenList instead.
+  final List<CssClassSetImpl> _sets;
+
+  factory _MultiElementCssClassSet(Iterable<Element> elements) {
+    return new _MultiElementCssClassSet._(elements,
+        elements.map((Element e) => e.classes).toList());
+  }
+
+  _MultiElementCssClassSet._(this._elementIterable, this._sets);
+
+  Set<String> readClasses() {
+    var s = new LinkedHashSet<String>();
+    _sets.forEach((CssClassSetImpl e) => s.addAll(e.readClasses()));
+    return s;
+  }
+
+  void writeClasses(Set<String> s) {
+    var classes = s.join(' ');
+    for (Element e in _elementIterable) {
+      e.className = classes;
+    }
+  }
+
+  /**
+   * Helper method used to modify the set of css classes on this element.
+   *
+   *   f - callback with:
+   *   s - a Set of all the css class name currently on this element.
+   *
+   *   After f returns, the modified set is written to the
+   *       className property of this element.
+   */
+  modify( f(Set<String> s)) {
+    _sets.forEach((CssClassSetImpl e) => e.modify(f));
+  }
+
+  /**
+   * Adds the class [value] to the element if it is not on it, removes it if it
+   * is.
+   *
+   * TODO(sra): It seems wrong to collect a 'changed' flag like this when the
+   * underlying toggle returns an 'is set' flag.
+   */
+  bool toggle(String value, [bool shouldAdd]) =>
+      _sets.fold(false,
+          (bool changed, CssClassSetImpl e) =>
+              e.toggle(value, shouldAdd) || changed);
+
+  /**
+   * Remove the class [value] from element, and return true on successful
+   * removal.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
+  bool remove(Object value) => _sets.fold(false,
+      (bool changed, CssClassSetImpl e) => e.remove(value) || changed);
+}
+
+class _ElementCssClassSet extends CssClassSetImpl {
+  final Element _element;
+
+  _ElementCssClassSet(this._element);
+
+  Set<String> readClasses() {
+    var s = new LinkedHashSet<String>();
+    var classname = _element.className;
+
+    for (String name in classname.split(' ')) {
+      String trimmed = name.trim();
+      if (!trimmed.isEmpty) {
+        s.add(trimmed);
+      }
+    }
+    return s;
+  }
+
+  void writeClasses(Set<String> s) {
+    _element.className = s.join(' ');
+  }
+
+  int get length => _classListLength(_classListOf(_element));
+  bool get isEmpty => length == 0;
+  bool get isNotEmpty => length != 0;
+
+  void clear() {
+    _element.className = '';
+  }
+
+  bool contains(String value) {
+    return _contains(_element, value);
+  }
+
+  bool add(String value) {
+    return _add(_element, value);
+  }
+
+  bool remove(Object value) {
+    return value is String && _remove(_element, value);
+  }
+
+  bool toggle(String value, [bool shouldAdd]) {
+    return _toggle(_element, value, shouldAdd);
+  }
+
+  void addAll(Iterable<String> iterable) {
+    _addAll(_element, iterable);
+  }
+
+  void removeAll(Iterable<String> iterable) {
+    _removeAll(_element, iterable);
+  }
+
+  void retainAll(Iterable<String> iterable) {
+    _removeWhere(_element, iterable.toSet().contains, false);
+  }
+
+  void removeWhere(bool test(String name)) {
+    _removeWhere(_element, test, true);
+  }
+
+  void retainWhere(bool test(String name)) {
+    _removeWhere(_element, test, false);
+  }
+
+  static bool _contains(Element _element, String value) {
+    return _classListContains(_classListOf(_element), value);
+  }
+
+  static bool _add(Element _element, String value) {
+    DomTokenList list = _classListOf(_element);
+    // Compute returned result independently of action upon the set. One day we
+    // will be able to optimize it way if unused.
+    bool added = !_classListContains(list, value);
+    _classListAdd(list, value);
+    return added;
+  }
+
+  static bool _remove(Element _element, String value) {
+    DomTokenList list = _classListOf(_element);
+    bool removed = _classListContains(list, value);
+    _classListRemove(list, value);
+    return removed;
+  }
+
+  static bool _toggle(Element _element, String value, bool shouldAdd) {
+    // There is no value that can be passed as the second argument of
+    // DomTokenList.toggle that behaves the same as passing one argument.
+    // `null` is seen as false, meaning 'remove'.
+    return shouldAdd == null
+        ? _toggleDefault(_element, value)
+        : _toggleOnOff(_element, value, shouldAdd);
+  }
+
+  static bool _toggleDefault(Element _element, String value) {
+    DomTokenList list = _classListOf(_element);
+    return _classListToggle1(list, value);
+  }
+
+  static bool _toggleOnOff(Element _element, String value, bool shouldAdd) {
+    DomTokenList list = _classListOf(_element);
+    // IE's toggle does not take a second parameter. We would prefer:
+    //
+    //    return _classListToggle2(list, value, shouldAdd);
+    //
+    if (shouldAdd) {
+      _classListAdd(list, value);
+      return true;
+    } else {
+      _classListRemove(list, value);
+      return false;
+    }
+  }
+
+  static void _addAll(Element _element, Iterable<String> iterable) {
+    DomTokenList list = _classListOf(_element);
+    for (String value in iterable) {
+      _classListAdd(list, value);
+    }
+  }
+
+  static void _removeAll(Element _element, Iterable<String> iterable) {
+    DomTokenList list = _classListOf(_element);
+    for (var value in iterable) {
+      _classListRemove(list, value);
+    }
+  }
+
+  static void _removeWhere(
+      Element _element, bool test(String name), bool doRemove) {
+    DomTokenList list = _classListOf(_element);
+    int i = 0;
+    while (i < _classListLength(list)) {
+      String item = list.item(i);
+      if (doRemove == test(item)) {
+        _classListRemove(list, item);
+      } else {
+        ++i;
+      }
+    }
+  }
+
+  // A collection of static methods for DomTokenList. These methods are a
+  // work-around for the lack of annotations to express the full behaviour of
+  // the DomTokenList methods.
+
+  static DomTokenList _classListOf(Element e) =>
+      JS('returns:DomTokenList;creates:DomTokenList;effects:none;depends:all;',
+         '#.classList', e);
+
+  static int _classListLength(DomTokenList list) =>
+      JS('returns:JSUInt31;effects:none;depends:all;', '#.length', list);
+
+  static bool _classListContains(DomTokenList list, String value) =>
+      JS('returns:bool;effects:none;depends:all;',
+          '#.contains(#)', list, value);
+
+  static void _classListAdd(DomTokenList list, String value) {
+    // list.add(value);
+    JS('', '#.add(#)', list, value);
+  }
+
+  static void _classListRemove(DomTokenList list, String value) {
+    // list.remove(value);
+    JS('', '#.remove(#)', list, value);
+  }
+
+  static bool _classListToggle1(DomTokenList list, String value) {
+    return JS('bool', '#.toggle(#)', list, value);
+  }
+
+  static bool _classListToggle2(
+      DomTokenList list, String value, bool shouldAdd) {
+    return JS('bool', '#.toggle(#, #)', list, value, shouldAdd);
+  }
+}
diff --git a/tools/dom/src/dartium_CssClassSet.dart b/tools/dom/src/dartium_CssClassSet.dart
new file mode 100644
index 0000000..cba9025
--- /dev/null
+++ b/tools/dom/src/dartium_CssClassSet.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of html;
+
+/**
+ * A set (union) of the CSS classes that are present in a set of elements.
+ * Implemented separately from _ElementCssClassSet for performance.
+ */
+class _MultiElementCssClassSet extends CssClassSetImpl {
+  final Iterable<Element> _elementIterable;
+  Iterable<_ElementCssClassSet> _elementCssClassSetIterable;
+
+  _MultiElementCssClassSet(this._elementIterable) {
+    _elementCssClassSetIterable = new List.from(_elementIterable).map(
+        (e) => new _ElementCssClassSet(e));
+  }
+
+  Set<String> readClasses() {
+    var s = new LinkedHashSet<String>();
+    _elementCssClassSetIterable.forEach(
+        (_ElementCssClassSet e) => s.addAll(e.readClasses()));
+    return s;
+  }
+
+  void writeClasses(Set<String> s) {
+    var classes = s.join(' ');
+    for (Element e in _elementIterable) {
+      e.className = classes;
+    }
+  }
+
+  /**
+   * Helper method used to modify the set of css classes on this element.
+   *
+   *   f - callback with:
+   *   s - a Set of all the css class name currently on this element.
+   *
+   *   After f returns, the modified set is written to the
+   *       className property of this element.
+   */
+  modify( f(Set<String> s)) {
+    _elementCssClassSetIterable.forEach((_ElementCssClassSet e) => e.modify(f));
+  }
+
+  /**
+   * Adds the class [value] to the element if it is not on it, removes it if it
+   * is.
+   */
+  bool toggle(String value, [bool shouldAdd]) =>
+      _elementCssClassSetIterable.fold(false,
+          (bool changed, _ElementCssClassSet e) =>
+              e.toggle(value, shouldAdd) || changed);
+
+  /**
+   * Remove the class [value] from element, and return true on successful
+   * removal.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
+  bool remove(Object value) => _elementCssClassSetIterable.fold(false,
+      (bool changed, _ElementCssClassSet e) => e.remove(value) || changed);
+}
+
+class _ElementCssClassSet extends CssClassSetImpl {
+
+  final Element _element;
+
+  _ElementCssClassSet(this._element);
+
+  Set<String> readClasses() {
+    var s = new LinkedHashSet<String>();
+    var classname = _element.className;
+
+    for (String name in classname.split(' ')) {
+      String trimmed = name.trim();
+      if (!trimmed.isEmpty) {
+        s.add(trimmed);
+      }
+    }
+    return s;
+  }
+
+  void writeClasses(Set<String> s) {
+    _element.className = s.join(' ');
+  }
+}
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 04acea0..e12a06c 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -52,12 +52,14 @@
 import 'dart:web_sql';
 import 'dart:_js_helper' show
     convertDartClosureToJS, Creates, JavaScriptIndexingBehavior,
-    JSName, Native, Null, Returns,
+    JSName, Native, Null, Returns, Inline, ForceInline,
     findDispatchTagForInterceptorClass, setNativeSubclassDispatchRecord,
     makeLeafDispatchRecord;
 import 'dart:_interceptors' show
-    Interceptor, JSExtendableArray, findInterceptorConstructorForType,
-    findConstructorForNativeSubclassType, getNativeInterceptor,
+    Interceptor, JSExtendableArray, JSUInt31,
+    findInterceptorConstructorForType,
+    findConstructorForNativeSubclassType,
+    getNativeInterceptor,
     setDispatchProperty;
 import 'dart:_isolate_helper' show IsolateNatives;
 import 'dart:_foreign_helper' show JS, JS_INTERCEPTOR_CONSTANT, JS_CONST;
@@ -71,6 +73,7 @@
 part '$AUXILIARY_DIR/CrossFrameTypes.dart';
 part '$AUXILIARY_DIR/CssClassSet.dart';
 part '$AUXILIARY_DIR/CssRectangle.dart';
+part '$AUXILIARY_DIR/dart2js_CssClassSet.dart';
 part '$AUXILIARY_DIR/Dimension.dart';
 part '$AUXILIARY_DIR/EventListener.dart';
 part '$AUXILIARY_DIR/EventStreamProvider.dart';
diff --git a/tools/dom/templates/html/dartium/html_dartium.darttemplate b/tools/dom/templates/html/dartium/html_dartium.darttemplate
index 348057d..0934721 100644
--- a/tools/dom/templates/html/dartium/html_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/html_dartium.darttemplate
@@ -67,6 +67,7 @@
 part '$AUXILIARY_DIR/CanvasImageSource.dart';
 part '$AUXILIARY_DIR/CrossFrameTypes.dart';
 part '$AUXILIARY_DIR/CssClassSet.dart';
+part '$AUXILIARY_DIR/dartium_CssClassSet.dart';
 part '$AUXILIARY_DIR/CssRectangle.dart';
 part '$AUXILIARY_DIR/Dimension.dart';
 part '$AUXILIARY_DIR/EventListener.dart';
diff --git a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
index 1b47c7d..186848e 100644
--- a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
@@ -11,7 +11,7 @@
 
 part of $LIBRARYNAME;
 
-$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS) class $CLASSNAME $EXTENDS with
+$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME $EXTENDS with
     $(CLASSNAME)Base $IMPLEMENTS {
   factory $CLASSNAME() => new CssStyleDeclaration.css('');
 
@@ -67,14 +67,34 @@
 
   @DomName('CSSStyleDeclaration.setProperty')
   void setProperty(String propertyName, String value, [String priority]) {
-    if (_supportsProperty(_camelCase(propertyName))) {
-      return _setPropertyHelper(propertyName, value, priority);
-    } else {
-      return _setPropertyHelper(Device.cssPrefix + propertyName, value,
-          priority);
-    }
+    return _setPropertyHelper(_browserPropertyName(propertyName),
+      value, priority);
   }
 
+  String _browserPropertyName(String propertyName) {
+    String name = _readCache(propertyName);
+    if (name is String) return name;
+    if (_supportsProperty(_camelCase(propertyName))) {
+      name = propertyName;
+    } else {
+      name = Device.cssPrefix + propertyName;
+    }
+    _writeCache(propertyName, name);
+    return name;
+  }
+
+$if DART2JS
+  static final _propertyCache = JS('', '{}');
+  static String _readCache(String key) =>
+    JS('String|Null', '#[#]', _propertyCache, key);
+  static void _writeCache(String key, String value) {
+    JS('void', '#[#] = #', _propertyCache, key, value);
+  }
+$else
+  static String _readCache(String key) => null;
+  static void _writeCache(String key, value) {}
+$endif
+
   static String _camelCase(String hyphenated) {
 $if DART2JS
     var replacedMs = JS('String', r'#.replace(/^-ms-/, "ms-")', hyphenated);
@@ -92,18 +112,9 @@
 
 $if DART2JS
   void _setPropertyHelper(String propertyName, String value, [String priority]) {
-    // try/catch for IE9 which throws on unsupported values.
-    try {
-      if (value == null) value = '';
-      if (priority == null) {
-        priority = '';
-      }
-      JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
-      // Bug #2772, IE9 requires a poke to actually apply the value.
-      if (JS('bool', '!!#.setAttribute', this)) {
-        JS('void', '#.setAttribute(#, #)', this, propertyName, value);
-      }
-    } catch (e) {}
+    if (value == null) value = '';
+    if (priority == null) priority = '';
+    JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
   }
 
   /**
@@ -126,6 +137,999 @@
   static bool get supportsTransitions => true;
 $endif
 $!MEMBERS
+$if DART2JS
+
+  /** Gets the value of "background" */
+  String get background => this._background;
+
+  /** Sets the value of "background" */
+  void set background(String value) {
+    _background = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('background')
+  String _background;
+    
+  /** Gets the value of "background-attachment" */
+  String get backgroundAttachment => this._backgroundAttachment;
+
+  /** Sets the value of "background-attachment" */
+  void set backgroundAttachment(String value) {
+    _backgroundAttachment = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundAttachment')
+  String _backgroundAttachment;
+    
+  /** Gets the value of "background-color" */
+  String get backgroundColor => this._backgroundColor;
+
+  /** Sets the value of "background-color" */
+  void set backgroundColor(String value) {
+    _backgroundColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundColor')
+  String _backgroundColor;
+    
+  /** Gets the value of "background-image" */
+  String get backgroundImage => this._backgroundImage;
+
+  /** Sets the value of "background-image" */
+  void set backgroundImage(String value) {
+    _backgroundImage = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundImage')
+  String _backgroundImage;
+    
+  /** Gets the value of "background-position" */
+  String get backgroundPosition => this._backgroundPosition;
+
+  /** Sets the value of "background-position" */
+  void set backgroundPosition(String value) {
+    _backgroundPosition = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundPosition')
+  String _backgroundPosition;
+    
+  /** Gets the value of "background-repeat" */
+  String get backgroundRepeat => this._backgroundRepeat;
+
+  /** Sets the value of "background-repeat" */
+  void set backgroundRepeat(String value) {
+    _backgroundRepeat = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('backgroundRepeat')
+  String _backgroundRepeat;
+    
+  /** Gets the value of "border" */
+  String get border => this._border;
+
+  /** Sets the value of "border" */
+  void set border(String value) {
+    _border = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('border')
+  String _border;
+    
+  /** Gets the value of "border-bottom" */
+  String get borderBottom => this._borderBottom;
+
+  /** Sets the value of "border-bottom" */
+  void set borderBottom(String value) {
+    _borderBottom = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderBottom')
+  String _borderBottom;
+    
+  /** Gets the value of "border-bottom-color" */
+  String get borderBottomColor => this._borderBottomColor;
+
+  /** Sets the value of "border-bottom-color" */
+  void set borderBottomColor(String value) {
+    _borderBottomColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderBottomColor')
+  String _borderBottomColor;
+    
+  /** Gets the value of "border-bottom-style" */
+  String get borderBottomStyle => this._borderBottomStyle;
+
+  /** Sets the value of "border-bottom-style" */
+  void set borderBottomStyle(String value) {
+    _borderBottomStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderBottomStyle')
+  String _borderBottomStyle;
+    
+  /** Gets the value of "border-bottom-width" */
+  String get borderBottomWidth => this._borderBottomWidth;
+
+  /** Sets the value of "border-bottom-width" */
+  void set borderBottomWidth(String value) {
+    _borderBottomWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderBottomWidth')
+  String _borderBottomWidth;
+    
+  /** Gets the value of "border-collapse" */
+  String get borderCollapse => this._borderCollapse;
+
+  /** Sets the value of "border-collapse" */
+  void set borderCollapse(String value) {
+    _borderCollapse = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderCollapse')
+  String _borderCollapse;
+    
+  /** Gets the value of "border-color" */
+  String get borderColor => this._borderColor;
+
+  /** Sets the value of "border-color" */
+  void set borderColor(String value) {
+    _borderColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderColor')
+  String _borderColor;
+    
+  /** Gets the value of "border-left" */
+  String get borderLeft => this._borderLeft;
+
+  /** Sets the value of "border-left" */
+  void set borderLeft(String value) {
+    _borderLeft = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderLeft')
+  String _borderLeft;
+    
+  /** Gets the value of "border-left-color" */
+  String get borderLeftColor => this._borderLeftColor;
+
+  /** Sets the value of "border-left-color" */
+  void set borderLeftColor(String value) {
+    _borderLeftColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderLeftColor')
+  String _borderLeftColor;
+    
+  /** Gets the value of "border-left-style" */
+  String get borderLeftStyle => this._borderLeftStyle;
+
+  /** Sets the value of "border-left-style" */
+  void set borderLeftStyle(String value) {
+    _borderLeftStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderLeftStyle')
+  String _borderLeftStyle;
+    
+  /** Gets the value of "border-left-width" */
+  String get borderLeftWidth => this._borderLeftWidth;
+
+  /** Sets the value of "border-left-width" */
+  void set borderLeftWidth(String value) {
+    _borderLeftWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderLeftWidth')
+  String _borderLeftWidth;
+    
+  /** Gets the value of "border-right" */
+  String get borderRight => this._borderRight;
+
+  /** Sets the value of "border-right" */
+  void set borderRight(String value) {
+    _borderRight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderRight')
+  String _borderRight;
+    
+  /** Gets the value of "border-right-color" */
+  String get borderRightColor => this._borderRightColor;
+
+  /** Sets the value of "border-right-color" */
+  void set borderRightColor(String value) {
+    _borderRightColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderRightColor')
+  String _borderRightColor;
+    
+  /** Gets the value of "border-right-style" */
+  String get borderRightStyle => this._borderRightStyle;
+
+  /** Sets the value of "border-right-style" */
+  void set borderRightStyle(String value) {
+    _borderRightStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderRightStyle')
+  String _borderRightStyle;
+    
+  /** Gets the value of "border-right-width" */
+  String get borderRightWidth => this._borderRightWidth;
+
+  /** Sets the value of "border-right-width" */
+  void set borderRightWidth(String value) {
+    _borderRightWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderRightWidth')
+  String _borderRightWidth;
+    
+  /** Gets the value of "border-spacing" */
+  String get borderSpacing => this._borderSpacing;
+
+  /** Sets the value of "border-spacing" */
+  void set borderSpacing(String value) {
+    _borderSpacing = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderSpacing')
+  String _borderSpacing;
+    
+  /** Gets the value of "border-style" */
+  String get borderStyle => this._borderStyle;
+
+  /** Sets the value of "border-style" */
+  void set borderStyle(String value) {
+    _borderStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderStyle')
+  String _borderStyle;
+    
+  /** Gets the value of "border-top" */
+  String get borderTop => this._borderTop;
+
+  /** Sets the value of "border-top" */
+  void set borderTop(String value) {
+    _borderTop = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderTop')
+  String _borderTop;
+    
+  /** Gets the value of "border-top-color" */
+  String get borderTopColor => this._borderTopColor;
+
+  /** Sets the value of "border-top-color" */
+  void set borderTopColor(String value) {
+    _borderTopColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderTopColor')
+  String _borderTopColor;
+    
+  /** Gets the value of "border-top-style" */
+  String get borderTopStyle => this._borderTopStyle;
+
+  /** Sets the value of "border-top-style" */
+  void set borderTopStyle(String value) {
+    _borderTopStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderTopStyle')
+  String _borderTopStyle;
+    
+  /** Gets the value of "border-top-width" */
+  String get borderTopWidth => this._borderTopWidth;
+
+  /** Sets the value of "border-top-width" */
+  void set borderTopWidth(String value) {
+    _borderTopWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderTopWidth')
+  String _borderTopWidth;
+    
+  /** Gets the value of "border-width" */
+  String get borderWidth => this._borderWidth;
+
+  /** Sets the value of "border-width" */
+  void set borderWidth(String value) {
+    _borderWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('borderWidth')
+  String _borderWidth;
+    
+  /** Gets the value of "bottom" */
+  String get bottom => this._bottom;
+
+  /** Sets the value of "bottom" */
+  void set bottom(String value) {
+    _bottom = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('bottom')
+  String _bottom;
+    
+  /** Gets the value of "caption-side" */
+  String get captionSide => this._captionSide;
+
+  /** Sets the value of "caption-side" */
+  void set captionSide(String value) {
+    _captionSide = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('captionSide')
+  String _captionSide;
+    
+  /** Gets the value of "clear" */
+  String get clear => this._clear;
+
+  /** Sets the value of "clear" */
+  void set clear(String value) {
+    _clear = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('clear')
+  String _clear;
+    
+  /** Gets the value of "clip" */
+  String get clip => this._clip;
+
+  /** Sets the value of "clip" */
+  void set clip(String value) {
+    _clip = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('clip')
+  String _clip;
+    
+  /** Gets the value of "color" */
+  String get color => this._color;
+
+  /** Sets the value of "color" */
+  void set color(String value) {
+    _color = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('color')
+  String _color;
+    
+  /** Gets the value of "content" */
+  String get content => this._content;
+
+  /** Sets the value of "content" */
+  void set content(String value) {
+    _content = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('content')
+  String _content;
+    
+  /** Gets the value of "cursor" */
+  String get cursor => this._cursor;
+
+  /** Sets the value of "cursor" */
+  void set cursor(String value) {
+    _cursor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('cursor')
+  String _cursor;
+    
+  /** Gets the value of "direction" */
+  String get direction => this._direction;
+
+  /** Sets the value of "direction" */
+  void set direction(String value) {
+    _direction = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('direction')
+  String _direction;
+    
+  /** Gets the value of "display" */
+  String get display => this._display;
+
+  /** Sets the value of "display" */
+  void set display(String value) {
+    _display = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('display')
+  String _display;
+    
+  /** Gets the value of "empty-cells" */
+  String get emptyCells => this._emptyCells;
+
+  /** Sets the value of "empty-cells" */
+  void set emptyCells(String value) {
+    _emptyCells = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('emptyCells')
+  String _emptyCells;
+    
+  /** Gets the value of "font" */
+  String get font => this._font;
+
+  /** Sets the value of "font" */
+  void set font(String value) {
+    _font = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('font')
+  String _font;
+    
+  /** Gets the value of "font-family" */
+  String get fontFamily => this._fontFamily;
+
+  /** Sets the value of "font-family" */
+  void set fontFamily(String value) {
+    _fontFamily = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontFamily')
+  String _fontFamily;
+    
+  /** Gets the value of "font-size" */
+  String get fontSize => this._fontSize;
+
+  /** Sets the value of "font-size" */
+  void set fontSize(String value) {
+    _fontSize = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontSize')
+  String _fontSize;
+    
+  /** Gets the value of "font-style" */
+  String get fontStyle => this._fontStyle;
+
+  /** Sets the value of "font-style" */
+  void set fontStyle(String value) {
+    _fontStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontStyle')
+  String _fontStyle;
+    
+  /** Gets the value of "font-variant" */
+  String get fontVariant => this._fontVariant;
+
+  /** Sets the value of "font-variant" */
+  void set fontVariant(String value) {
+    _fontVariant = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontVariant')
+  String _fontVariant;
+    
+  /** Gets the value of "font-weight" */
+  String get fontWeight => this._fontWeight;
+
+  /** Sets the value of "font-weight" */
+  void set fontWeight(String value) {
+    _fontWeight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('fontWeight')
+  String _fontWeight;
+    
+  /** Gets the value of "height" */
+  String get height => this._height;
+
+  /** Sets the value of "height" */
+  void set height(String value) {
+    _height = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('height')
+  String _height;
+    
+  /** Gets the value of "left" */
+  String get left => this._left;
+
+  /** Sets the value of "left" */
+  void set left(String value) {
+    _left = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('left')
+  String _left;
+    
+  /** Gets the value of "letter-spacing" */
+  String get letterSpacing => this._letterSpacing;
+
+  /** Sets the value of "letter-spacing" */
+  void set letterSpacing(String value) {
+    _letterSpacing = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('letterSpacing')
+  String _letterSpacing;
+    
+  /** Gets the value of "line-height" */
+  String get lineHeight => this._lineHeight;
+
+  /** Sets the value of "line-height" */
+  void set lineHeight(String value) {
+    _lineHeight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('lineHeight')
+  String _lineHeight;
+    
+  /** Gets the value of "list-style" */
+  String get listStyle => this._listStyle;
+
+  /** Sets the value of "list-style" */
+  void set listStyle(String value) {
+    _listStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('listStyle')
+  String _listStyle;
+    
+  /** Gets the value of "list-style-image" */
+  String get listStyleImage => this._listStyleImage;
+
+  /** Sets the value of "list-style-image" */
+  void set listStyleImage(String value) {
+    _listStyleImage = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('listStyleImage')
+  String _listStyleImage;
+    
+  /** Gets the value of "list-style-position" */
+  String get listStylePosition => this._listStylePosition;
+
+  /** Sets the value of "list-style-position" */
+  void set listStylePosition(String value) {
+    _listStylePosition = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('listStylePosition')
+  String _listStylePosition;
+    
+  /** Gets the value of "list-style-type" */
+  String get listStyleType => this._listStyleType;
+
+  /** Sets the value of "list-style-type" */
+  void set listStyleType(String value) {
+    _listStyleType = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('listStyleType')
+  String _listStyleType;
+    
+  /** Gets the value of "margin" */
+  String get margin => this._margin;
+
+  /** Sets the value of "margin" */
+  void set margin(String value) {
+    _margin = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('margin')
+  String _margin;
+    
+  /** Gets the value of "margin-bottom" */
+  String get marginBottom => this._marginBottom;
+
+  /** Sets the value of "margin-bottom" */
+  void set marginBottom(String value) {
+    _marginBottom = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('marginBottom')
+  String _marginBottom;
+    
+  /** Gets the value of "margin-left" */
+  String get marginLeft => this._marginLeft;
+
+  /** Sets the value of "margin-left" */
+  void set marginLeft(String value) {
+    _marginLeft = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('marginLeft')
+  String _marginLeft;
+    
+  /** Gets the value of "margin-right" */
+  String get marginRight => this._marginRight;
+
+  /** Sets the value of "margin-right" */
+  void set marginRight(String value) {
+    _marginRight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('marginRight')
+  String _marginRight;
+    
+  /** Gets the value of "margin-top" */
+  String get marginTop => this._marginTop;
+
+  /** Sets the value of "margin-top" */
+  void set marginTop(String value) {
+    _marginTop = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('marginTop')
+  String _marginTop;
+    
+  /** Gets the value of "max-height" */
+  String get maxHeight => this._maxHeight;
+
+  /** Sets the value of "max-height" */
+  void set maxHeight(String value) {
+    _maxHeight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('maxHeight')
+  String _maxHeight;
+    
+  /** Gets the value of "max-width" */
+  String get maxWidth => this._maxWidth;
+
+  /** Sets the value of "max-width" */
+  void set maxWidth(String value) {
+    _maxWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('maxWidth')
+  String _maxWidth;
+    
+  /** Gets the value of "min-height" */
+  String get minHeight => this._minHeight;
+
+  /** Sets the value of "min-height" */
+  void set minHeight(String value) {
+    _minHeight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('minHeight')
+  String _minHeight;
+    
+  /** Gets the value of "min-width" */
+  String get minWidth => this._minWidth;
+
+  /** Sets the value of "min-width" */
+  void set minWidth(String value) {
+    _minWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('minWidth')
+  String _minWidth;
+    
+  /** Gets the value of "outline" */
+  String get outline => this._outline;
+
+  /** Sets the value of "outline" */
+  void set outline(String value) {
+    _outline = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('outline')
+  String _outline;
+    
+  /** Gets the value of "outline-color" */
+  String get outlineColor => this._outlineColor;
+
+  /** Sets the value of "outline-color" */
+  void set outlineColor(String value) {
+    _outlineColor = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('outlineColor')
+  String _outlineColor;
+    
+  /** Gets the value of "outline-style" */
+  String get outlineStyle => this._outlineStyle;
+
+  /** Sets the value of "outline-style" */
+  void set outlineStyle(String value) {
+    _outlineStyle = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('outlineStyle')
+  String _outlineStyle;
+    
+  /** Gets the value of "outline-width" */
+  String get outlineWidth => this._outlineWidth;
+
+  /** Sets the value of "outline-width" */
+  void set outlineWidth(String value) {
+    _outlineWidth = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('outlineWidth')
+  String _outlineWidth;
+    
+  /** Gets the value of "overflow" */
+  String get overflow => this._overflow;
+
+  /** Sets the value of "overflow" */
+  void set overflow(String value) {
+    _overflow = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('overflow')
+  String _overflow;
+    
+  /** Gets the value of "padding" */
+  String get padding => this._padding;
+
+  /** Sets the value of "padding" */
+  void set padding(String value) {
+    _padding = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('padding')
+  String _padding;
+    
+  /** Gets the value of "padding-bottom" */
+  String get paddingBottom => this._paddingBottom;
+
+  /** Sets the value of "padding-bottom" */
+  void set paddingBottom(String value) {
+    _paddingBottom = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('paddingBottom')
+  String _paddingBottom;
+    
+  /** Gets the value of "padding-left" */
+  String get paddingLeft => this._paddingLeft;
+
+  /** Sets the value of "padding-left" */
+  void set paddingLeft(String value) {
+    _paddingLeft = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('paddingLeft')
+  String _paddingLeft;
+    
+  /** Gets the value of "padding-right" */
+  String get paddingRight => this._paddingRight;
+
+  /** Sets the value of "padding-right" */
+  void set paddingRight(String value) {
+    _paddingRight = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('paddingRight')
+  String _paddingRight;
+    
+  /** Gets the value of "padding-top" */
+  String get paddingTop => this._paddingTop;
+
+  /** Sets the value of "padding-top" */
+  void set paddingTop(String value) {
+    _paddingTop = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('paddingTop')
+  String _paddingTop;
+    
+  /** Gets the value of "page-break-after" */
+  String get pageBreakAfter => this._pageBreakAfter;
+
+  /** Sets the value of "page-break-after" */
+  void set pageBreakAfter(String value) {
+    _pageBreakAfter = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('pageBreakAfter')
+  String _pageBreakAfter;
+    
+  /** Gets the value of "page-break-before" */
+  String get pageBreakBefore => this._pageBreakBefore;
+
+  /** Sets the value of "page-break-before" */
+  void set pageBreakBefore(String value) {
+    _pageBreakBefore = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('pageBreakBefore')
+  String _pageBreakBefore;
+    
+  /** Gets the value of "page-break-inside" */
+  String get pageBreakInside => this._pageBreakInside;
+
+  /** Sets the value of "page-break-inside" */
+  void set pageBreakInside(String value) {
+    _pageBreakInside = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('pageBreakInside')
+  String _pageBreakInside;
+    
+  /** Gets the value of "position" */
+  String get position => this._position;
+
+  /** Sets the value of "position" */
+  void set position(String value) {
+    _position = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('position')
+  String _position;
+    
+  /** Gets the value of "quotes" */
+  String get quotes => this._quotes;
+
+  /** Sets the value of "quotes" */
+  void set quotes(String value) {
+    _quotes = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('quotes')
+  String _quotes;
+    
+  /** Gets the value of "right" */
+  String get right => this._right;
+
+  /** Sets the value of "right" */
+  void set right(String value) {
+    _right = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('right')
+  String _right;
+    
+  /** Gets the value of "table-layout" */
+  String get tableLayout => this._tableLayout;
+
+  /** Sets the value of "table-layout" */
+  void set tableLayout(String value) {
+    _tableLayout = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('tableLayout')
+  String _tableLayout;
+    
+  /** Gets the value of "text-align" */
+  String get textAlign => this._textAlign;
+
+  /** Sets the value of "text-align" */
+  void set textAlign(String value) {
+    _textAlign = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('textAlign')
+  String _textAlign;
+    
+  /** Gets the value of "text-decoration" */
+  String get textDecoration => this._textDecoration;
+
+  /** Sets the value of "text-decoration" */
+  void set textDecoration(String value) {
+    _textDecoration = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('textDecoration')
+  String _textDecoration;
+    
+  /** Gets the value of "text-indent" */
+  String get textIndent => this._textIndent;
+
+  /** Sets the value of "text-indent" */
+  void set textIndent(String value) {
+    _textIndent = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('textIndent')
+  String _textIndent;
+    
+  /** Gets the value of "text-transform" */
+  String get textTransform => this._textTransform;
+
+  /** Sets the value of "text-transform" */
+  void set textTransform(String value) {
+    _textTransform = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('textTransform')
+  String _textTransform;
+    
+  /** Gets the value of "top" */
+  String get top => this._top;
+
+  /** Sets the value of "top" */
+  void set top(String value) {
+    _top = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('top')
+  String _top;
+    
+  /** Gets the value of "unicode-bidi" */
+  String get unicodeBidi => this._unicodeBidi;
+
+  /** Sets the value of "unicode-bidi" */
+  void set unicodeBidi(String value) {
+    _unicodeBidi = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('unicodeBidi')
+  String _unicodeBidi;
+    
+  /** Gets the value of "vertical-align" */
+  String get verticalAlign => this._verticalAlign;
+
+  /** Sets the value of "vertical-align" */
+  void set verticalAlign(String value) {
+    _verticalAlign = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('verticalAlign')
+  String _verticalAlign;
+    
+  /** Gets the value of "visibility" */
+  String get visibility => this._visibility;
+
+  /** Sets the value of "visibility" */
+  void set visibility(String value) {
+    _visibility = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('visibility')
+  String _visibility;
+    
+  /** Gets the value of "white-space" */
+  String get whiteSpace => this._whiteSpace;
+
+  /** Sets the value of "white-space" */
+  void set whiteSpace(String value) {
+    _whiteSpace = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('whiteSpace')
+  String _whiteSpace;
+    
+  /** Gets the value of "width" */
+  String get width => this._width;
+
+  /** Sets the value of "width" */
+  void set width(String value) {
+    _width = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('width')
+  String _width;
+    
+  /** Gets the value of "word-spacing" */
+  String get wordSpacing => this._wordSpacing;
+
+  /** Sets the value of "word-spacing" */
+  void set wordSpacing(String value) {
+    _wordSpacing = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('wordSpacing')
+  String _wordSpacing;
+    
+  /** Gets the value of "z-index" */
+  String get zIndex => this._zIndex;
+
+  /** Sets the value of "z-index" */
+  void set zIndex(String value) {
+    _zIndex = value == null ? '' : value;
+  }
+  @Returns('String')
+  @JSName('zIndex')
+  String _zIndex;
+    
+$endif
 }
 
 class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
@@ -145,6 +1149,468 @@
     _elementCssStyleDeclarationSetIterable.forEach((e) =>
         e.setProperty(propertyName, value, priority));
   }
+
+
+$if DART2JS
+  void _setAll(String propertyName, String value) {
+    value = value == null ? '' : value;
+    for (Element element in _elementIterable) {
+      JS('void', '#.style[#] = #', element, propertyName, value);
+    }
+  }
+
+  /** Sets the value of "background" */
+  void set background(String value) {
+    _setAll('background', value);
+  }
+    
+  /** Sets the value of "background-attachment" */
+  void set backgroundAttachment(String value) {
+    _setAll('backgroundAttachment', value);
+  }
+    
+  /** Sets the value of "background-color" */
+  void set backgroundColor(String value) {
+    _setAll('backgroundColor', value);
+  }
+    
+  /** Sets the value of "background-image" */
+  void set backgroundImage(String value) {
+    _setAll('backgroundImage', value);
+  }
+    
+  /** Sets the value of "background-position" */
+  void set backgroundPosition(String value) {
+    _setAll('backgroundPosition', value);
+  }
+    
+  /** Sets the value of "background-repeat" */
+  void set backgroundRepeat(String value) {
+    _setAll('backgroundRepeat', value);
+  }
+    
+  /** Sets the value of "border" */
+  void set border(String value) {
+    _setAll('border', value);
+  }
+    
+  /** Sets the value of "border-bottom" */
+  void set borderBottom(String value) {
+    _setAll('borderBottom', value);
+  }
+    
+  /** Sets the value of "border-bottom-color" */
+  void set borderBottomColor(String value) {
+    _setAll('borderBottomColor', value);
+  }
+    
+  /** Sets the value of "border-bottom-style" */
+  void set borderBottomStyle(String value) {
+    _setAll('borderBottomStyle', value);
+  }
+    
+  /** Sets the value of "border-bottom-width" */
+  void set borderBottomWidth(String value) {
+    _setAll('borderBottomWidth', value);
+  }
+    
+  /** Sets the value of "border-collapse" */
+  void set borderCollapse(String value) {
+    _setAll('borderCollapse', value);
+  }
+    
+  /** Sets the value of "border-color" */
+  void set borderColor(String value) {
+    _setAll('borderColor', value);
+  }
+    
+  /** Sets the value of "border-left" */
+  void set borderLeft(String value) {
+    _setAll('borderLeft', value);
+  }
+    
+  /** Sets the value of "border-left-color" */
+  void set borderLeftColor(String value) {
+    _setAll('borderLeftColor', value);
+  }
+    
+  /** Sets the value of "border-left-style" */
+  void set borderLeftStyle(String value) {
+    _setAll('borderLeftStyle', value);
+  }
+    
+  /** Sets the value of "border-left-width" */
+  void set borderLeftWidth(String value) {
+    _setAll('borderLeftWidth', value);
+  }
+    
+  /** Sets the value of "border-right" */
+  void set borderRight(String value) {
+    _setAll('borderRight', value);
+  }
+    
+  /** Sets the value of "border-right-color" */
+  void set borderRightColor(String value) {
+    _setAll('borderRightColor', value);
+  }
+    
+  /** Sets the value of "border-right-style" */
+  void set borderRightStyle(String value) {
+    _setAll('borderRightStyle', value);
+  }
+    
+  /** Sets the value of "border-right-width" */
+  void set borderRightWidth(String value) {
+    _setAll('borderRightWidth', value);
+  }
+    
+  /** Sets the value of "border-spacing" */
+  void set borderSpacing(String value) {
+    _setAll('borderSpacing', value);
+  }
+    
+  /** Sets the value of "border-style" */
+  void set borderStyle(String value) {
+    _setAll('borderStyle', value);
+  }
+    
+  /** Sets the value of "border-top" */
+  void set borderTop(String value) {
+    _setAll('borderTop', value);
+  }
+    
+  /** Sets the value of "border-top-color" */
+  void set borderTopColor(String value) {
+    _setAll('borderTopColor', value);
+  }
+    
+  /** Sets the value of "border-top-style" */
+  void set borderTopStyle(String value) {
+    _setAll('borderTopStyle', value);
+  }
+    
+  /** Sets the value of "border-top-width" */
+  void set borderTopWidth(String value) {
+    _setAll('borderTopWidth', value);
+  }
+    
+  /** Sets the value of "border-width" */
+  void set borderWidth(String value) {
+    _setAll('borderWidth', value);
+  }
+    
+  /** Sets the value of "bottom" */
+  void set bottom(String value) {
+    _setAll('bottom', value);
+  }
+    
+  /** Sets the value of "caption-side" */
+  void set captionSide(String value) {
+    _setAll('captionSide', value);
+  }
+    
+  /** Sets the value of "clear" */
+  void set clear(String value) {
+    _setAll('clear', value);
+  }
+    
+  /** Sets the value of "clip" */
+  void set clip(String value) {
+    _setAll('clip', value);
+  }
+    
+  /** Sets the value of "color" */
+  void set color(String value) {
+    _setAll('color', value);
+  }
+    
+  /** Sets the value of "content" */
+  void set content(String value) {
+    _setAll('content', value);
+  }
+    
+  /** Sets the value of "cursor" */
+  void set cursor(String value) {
+    _setAll('cursor', value);
+  }
+    
+  /** Sets the value of "direction" */
+  void set direction(String value) {
+    _setAll('direction', value);
+  }
+    
+  /** Sets the value of "display" */
+  void set display(String value) {
+    _setAll('display', value);
+  }
+    
+  /** Sets the value of "empty-cells" */
+  void set emptyCells(String value) {
+    _setAll('emptyCells', value);
+  }
+    
+  /** Sets the value of "font" */
+  void set font(String value) {
+    _setAll('font', value);
+  }
+    
+  /** Sets the value of "font-family" */
+  void set fontFamily(String value) {
+    _setAll('fontFamily', value);
+  }
+    
+  /** Sets the value of "font-size" */
+  void set fontSize(String value) {
+    _setAll('fontSize', value);
+  }
+    
+  /** Sets the value of "font-style" */
+  void set fontStyle(String value) {
+    _setAll('fontStyle', value);
+  }
+    
+  /** Sets the value of "font-variant" */
+  void set fontVariant(String value) {
+    _setAll('fontVariant', value);
+  }
+    
+  /** Sets the value of "font-weight" */
+  void set fontWeight(String value) {
+    _setAll('fontWeight', value);
+  }
+    
+  /** Sets the value of "height" */
+  void set height(String value) {
+    _setAll('height', value);
+  }
+    
+  /** Sets the value of "left" */
+  void set left(String value) {
+    _setAll('left', value);
+  }
+    
+  /** Sets the value of "letter-spacing" */
+  void set letterSpacing(String value) {
+    _setAll('letterSpacing', value);
+  }
+    
+  /** Sets the value of "line-height" */
+  void set lineHeight(String value) {
+    _setAll('lineHeight', value);
+  }
+    
+  /** Sets the value of "list-style" */
+  void set listStyle(String value) {
+    _setAll('listStyle', value);
+  }
+    
+  /** Sets the value of "list-style-image" */
+  void set listStyleImage(String value) {
+    _setAll('listStyleImage', value);
+  }
+    
+  /** Sets the value of "list-style-position" */
+  void set listStylePosition(String value) {
+    _setAll('listStylePosition', value);
+  }
+    
+  /** Sets the value of "list-style-type" */
+  void set listStyleType(String value) {
+    _setAll('listStyleType', value);
+  }
+    
+  /** Sets the value of "margin" */
+  void set margin(String value) {
+    _setAll('margin', value);
+  }
+    
+  /** Sets the value of "margin-bottom" */
+  void set marginBottom(String value) {
+    _setAll('marginBottom', value);
+  }
+    
+  /** Sets the value of "margin-left" */
+  void set marginLeft(String value) {
+    _setAll('marginLeft', value);
+  }
+    
+  /** Sets the value of "margin-right" */
+  void set marginRight(String value) {
+    _setAll('marginRight', value);
+  }
+    
+  /** Sets the value of "margin-top" */
+  void set marginTop(String value) {
+    _setAll('marginTop', value);
+  }
+    
+  /** Sets the value of "max-height" */
+  void set maxHeight(String value) {
+    _setAll('maxHeight', value);
+  }
+    
+  /** Sets the value of "max-width" */
+  void set maxWidth(String value) {
+    _setAll('maxWidth', value);
+  }
+    
+  /** Sets the value of "min-height" */
+  void set minHeight(String value) {
+    _setAll('minHeight', value);
+  }
+    
+  /** Sets the value of "min-width" */
+  void set minWidth(String value) {
+    _setAll('minWidth', value);
+  }
+    
+  /** Sets the value of "outline" */
+  void set outline(String value) {
+    _setAll('outline', value);
+  }
+    
+  /** Sets the value of "outline-color" */
+  void set outlineColor(String value) {
+    _setAll('outlineColor', value);
+  }
+    
+  /** Sets the value of "outline-style" */
+  void set outlineStyle(String value) {
+    _setAll('outlineStyle', value);
+  }
+    
+  /** Sets the value of "outline-width" */
+  void set outlineWidth(String value) {
+    _setAll('outlineWidth', value);
+  }
+    
+  /** Sets the value of "overflow" */
+  void set overflow(String value) {
+    _setAll('overflow', value);
+  }
+    
+  /** Sets the value of "padding" */
+  void set padding(String value) {
+    _setAll('padding', value);
+  }
+    
+  /** Sets the value of "padding-bottom" */
+  void set paddingBottom(String value) {
+    _setAll('paddingBottom', value);
+  }
+    
+  /** Sets the value of "padding-left" */
+  void set paddingLeft(String value) {
+    _setAll('paddingLeft', value);
+  }
+    
+  /** Sets the value of "padding-right" */
+  void set paddingRight(String value) {
+    _setAll('paddingRight', value);
+  }
+    
+  /** Sets the value of "padding-top" */
+  void set paddingTop(String value) {
+    _setAll('paddingTop', value);
+  }
+    
+  /** Sets the value of "page-break-after" */
+  void set pageBreakAfter(String value) {
+    _setAll('pageBreakAfter', value);
+  }
+    
+  /** Sets the value of "page-break-before" */
+  void set pageBreakBefore(String value) {
+    _setAll('pageBreakBefore', value);
+  }
+    
+  /** Sets the value of "page-break-inside" */
+  void set pageBreakInside(String value) {
+    _setAll('pageBreakInside', value);
+  }
+    
+  /** Sets the value of "position" */
+  void set position(String value) {
+    _setAll('position', value);
+  }
+    
+  /** Sets the value of "quotes" */
+  void set quotes(String value) {
+    _setAll('quotes', value);
+  }
+    
+  /** Sets the value of "right" */
+  void set right(String value) {
+    _setAll('right', value);
+  }
+    
+  /** Sets the value of "table-layout" */
+  void set tableLayout(String value) {
+    _setAll('tableLayout', value);
+  }
+    
+  /** Sets the value of "text-align" */
+  void set textAlign(String value) {
+    _setAll('textAlign', value);
+  }
+    
+  /** Sets the value of "text-decoration" */
+  void set textDecoration(String value) {
+    _setAll('textDecoration', value);
+  }
+    
+  /** Sets the value of "text-indent" */
+  void set textIndent(String value) {
+    _setAll('textIndent', value);
+  }
+    
+  /** Sets the value of "text-transform" */
+  void set textTransform(String value) {
+    _setAll('textTransform', value);
+  }
+    
+  /** Sets the value of "top" */
+  void set top(String value) {
+    _setAll('top', value);
+  }
+    
+  /** Sets the value of "unicode-bidi" */
+  void set unicodeBidi(String value) {
+    _setAll('unicodeBidi', value);
+  }
+    
+  /** Sets the value of "vertical-align" */
+  void set verticalAlign(String value) {
+    _setAll('verticalAlign', value);
+  }
+    
+  /** Sets the value of "visibility" */
+  void set visibility(String value) {
+    _setAll('visibility', value);
+  }
+    
+  /** Sets the value of "white-space" */
+  void set whiteSpace(String value) {
+    _setAll('whiteSpace', value);
+  }
+    
+  /** Sets the value of "width" */
+  void set width(String value) {
+    _setAll('width', value);
+  }
+    
+  /** Sets the value of "word-spacing" */
+  void set wordSpacing(String value) {
+    _setAll('wordSpacing', value);
+  }
+    
+  /** Sets the value of "z-index" */
+  void set zIndex(String value) {
+    _setAll('zIndex', value);
+  }
+    
+$endif
+
   // Important note: CssStyleDeclarationSet does NOT implement every method
   // available in CssStyleDeclaration. Some of the methods don't make so much
   // sense in terms of having a resonable value to return when you're
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index a41c6a6..14d6abf 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -1387,6 +1387,38 @@
    * used when an explicit accessor is not available.
    */
   ElementEvents get on => new ElementEvents(this);
+  
+  /**
+   * Verify if any of the attributes that we use in the sanitizer look unexpected,
+   * possibly indicating DOM clobbering attacks.
+   *
+   * Those attributes are: attributes, lastChild, children, previousNode and tagName.
+   */
+$if DART2JS
+  bool get _hasCorruptedAttributes {
+     return JS('bool', r'''
+       (function(element) {
+         if (!(element.attributes instanceof NamedNodeMap)) {
+	   return true;
+	 }
+	 var childNodes = element.childNodes;
+	 if (element.lastChild &&
+	     element.lastChild !== childNodes[childNodes.length -1]) {
+	   return true;
+	 }
+	 if (element.children) { // On Safari, children can apparently be null.
+  	   if (!((element.children instanceof HTMLCollection) ||
+               (element.children instanceof NodeList))) {
+	     return true;
+	   }
+	 }
+	 return false;
+          })(#)''', this);
+  }
+$else
+  // Dartium isn't affected by these attacks, because it goes directly to the C++ API.
+  bool get _hasCorruptedAttributes => false;
+$endif
 
 $if DART2JS
   @DomName('Element.offsetHeight')
diff --git a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
index 1d9f06e..dd235bc 100644
--- a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
@@ -54,13 +54,7 @@
     return fragment.nodes.where((e) => e is SvgElement).single;
   }
 
-  _AttributeClassSet _cssClassSet;
-  CssClassSet get classes {
-    if (_cssClassSet == null) {
-      _cssClassSet = new _AttributeClassSet(this);
-    }
-    return _cssClassSet;
-  }
+  CssClassSet get classes => new _AttributeClassSet(this);
 
   List<Element> get children => new FilteredElementList<Element>(this);
 
diff --git a/tools/gyp/configurations.gypi b/tools/gyp/configurations.gypi
index 6588db3..e6e19ef 100644
--- a/tools/gyp/configurations.gypi
+++ b/tools/gyp/configurations.gypi
@@ -17,6 +17,7 @@
       ['"<(target_arch)"=="ia32"', { 'dart_target_arch': 'IA32', }],
       ['"<(target_arch)"=="x64"', { 'dart_target_arch': 'X64', }],
       ['"<(target_arch)"=="arm"', { 'dart_target_arch': 'ARM', }],
+      ['"<(target_arch)"=="armv5te"', { 'dart_target_arch': 'ARMV5TE', }],
       ['"<(target_arch)"=="arm64"', { 'dart_target_arch': 'ARM64', }],
       ['"<(target_arch)"=="simarm"', { 'dart_target_arch': 'SIMARM', }],
       ['"<(target_arch)"=="simarm64"', { 'dart_target_arch': 'SIMARM64', }],
@@ -68,6 +69,13 @@
         ],
       },
 
+      'Dart_armv5te_Base': {
+        'abstract': 1,
+        'defines': [
+          'TARGET_ARCH_ARM',
+        ],
+      },
+
       'Dart_simarm64_Base': {
         'abstract': 1,
         'defines': [
@@ -246,6 +254,42 @@
         ],
       },
 
+      'DebugXARMV5TE': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_armv5te_Base', 'Dart_Debug',
+          'Dart_Linux_Base',
+          'Dart_Linux_xarmv5te_Base',
+          'Dart_Linux_Debug',
+        ],
+      },
+
+      'ReleaseXARMV5TE': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_armv5te_Base', 'Dart_Release',
+          'Dart_Linux_Base',
+          'Dart_Linux_xarmv5te_Base',
+          'Dart_Linux_Release',
+        ],
+      },
+
+      'DebugARMV5TE': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_armv5te_Base', 'Dart_Debug',
+          'Dart_Linux_Base',
+          'Dart_Linux_armv5te_Base',
+          'Dart_Linux_Debug',
+        ],
+      },
+
+      'ReleaseARMV5TE': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_armv5te_Base', 'Dart_Release',
+          'Dart_Linux_Base',
+          'Dart_Linux_armv5te_Base',
+          'Dart_Linux_Release',
+        ],
+      },
+
       'DebugXARM64': {
         'inherit_from': [
           'Dart_Base', 'Dart_arm64_Base', 'Dart_Debug',
diff --git a/tools/gyp/configurations_make.gypi b/tools/gyp/configurations_make.gypi
index 38c3f13..2e77656 100644
--- a/tools/gyp/configurations_make.gypi
+++ b/tools/gyp/configurations_make.gypi
@@ -81,6 +81,39 @@
         ],
       },
 
+      # ARMv5 cross-build
+      'Dart_Linux_xarmv5te_Base': {
+        'abstract': 1,
+        'target_conditions': [
+        ['_toolset=="target"', {
+          'cflags': [
+            '-mthumb',
+            '-mlong-calls',
+            '-march=armv5te',
+            '-mfloat-abi=soft',
+            '-Wno-psabi', # suppresses va_list warning
+            '-fno-strict-overflow',
+          ],
+        }],
+        ['_toolset=="host"', {
+          'cflags': ['-m32', '-msse2'],
+          'ldflags': ['-m32'],
+        }]]
+      },
+
+      # ARMv5 native build
+      'Dart_Linux_armv5te_Base': {
+        'abstract': 1,
+        'cflags': [
+          '-mthumb',
+          '-mlong-calls',
+          '-march=armv5te',
+          '-mfloat-abi=soft',
+          '-Wno-psabi', # suppresses va_list warning
+          '-fno-strict-overflow',
+        ],
+      },
+
       # ARM64 cross-build
       'Dart_Linux_xarm64_Base': {
         'abstract': 1,
diff --git a/tools/observatory_tool.py b/tools/observatory_tool.py
index 45fc36a..fab2183 100755
--- a/tools/observatory_tool.py
+++ b/tools/observatory_tool.py
@@ -30,54 +30,98 @@
   result = argparse.ArgumentParser(usage=usage)
   result.add_argument("--package-root", help="package root", default=None)
   result.add_argument("--dart-executable", help="dart executable", default=None)
+  result.add_argument("--pub-executable", help="pub executable", default=None)
   result.add_argument("--directory", help="observatory root", default=None)
   result.add_argument("--command", help="[get, build, deploy]", default=None)
+  result.add_argument("--silent", help="silence all output", default=False)
   return result
 
 def ProcessOptions(options, args):
+  # Required options.
+  if (options.command == None) or (options.directory == None):
+    return False
+  # If we have a pub executable, we are running from the dart-sdk.
+  if (options.pub_executable != None):
+    return True
+  # Otherwise, we need a dart executable and a package root.
   return ((options.package_root != None) and
-          (options.directory != None) and
-          (options.command != None) and
           (options.dart_executable != None))
 
 def ChangeDirectory(directory):
   os.chdir(directory);
 
-def PubGet(dart_executable, pkg_root):
+def PubGet(dart_executable, pub_executable, pkg_root, silent):
   # Always remove pubspec.lock before running 'pub get'.
   try:
     os.remove('pubspec.lock');
   except OSError as e:
     pass
-  return subprocess.call(['python',
-                          RUN_PUB,
-                          '--package-root=' + pkg_root,
-                          '--dart-executable=' + dart_executable,
-                          'get',
-                          '--offline'])
+  with open(os.devnull, 'wb') as silent_sink:
+    if (pub_executable != None):
+      return subprocess.call([pub_executable,
+                              'get',
+                              '--offline'],
+                              stdout=silent_sink if silent else None,
+                              stderr=silent_sink if silent else None)
+    else:
+      return subprocess.call(['python',
+                              RUN_PUB,
+                              '--package-root=' + pkg_root,
+                              '--dart-executable=' + dart_executable,
+                              'get',
+                              '--offline'],
+                              stdout=silent_sink if silent else None,
+                              stderr=silent_sink if silent else None,)
 
-def PubBuild(dart_executable, pkg_root, output_dir):
-  return subprocess.call(['python',
-                          RUN_PUB,
-                          '--package-root=' + pkg_root,
-                          '--dart-executable=' + dart_executable,
-                          'build',
-                          '--output',
-                          output_dir])
+def PubBuild(dart_executable, pub_executable, pkg_root, silent, output_dir):
+  with open(os.devnull, 'wb') as silent_sink:
+    if (pub_executable != None):
+      return subprocess.call([pub_executable,
+                              'build',
+                              '--output',
+                              output_dir],
+                              stdout=silent_sink if silent else None,
+                              stderr=silent_sink if silent else None,)
+    else:
+      return subprocess.call(['python',
+                              RUN_PUB,
+                              '--package-root=' + pkg_root,
+                              '--dart-executable=' + dart_executable,
+                              'build',
+                              '--output',
+                              output_dir],
+                              stdout=silent_sink if silent else None,
+                              stderr=silent_sink if silent else None,)
 
 def Deploy(input_dir, output_dir):
   shutil.rmtree(output_dir)
   shutil.copytree(input_dir, output_dir, ignore=IGNORE_PATTERNS)
   return 0
 
+def RewritePubSpec(input_path, output_path, search, replace):
+  with open(input_path, 'rb') as input_file:
+    input_data = input_file.read()
+    input_data = input_data.replace(search, replace)
+    with open(output_path, 'wb+') as output_file:
+      output_file.write(input_data)
+
 def ExecuteCommand(options, args):
   cmd = options.command
   if (cmd == 'get'):
-    return PubGet(options.dart_executable, options.package_root)
+    return PubGet(options.dart_executable,
+                  options.pub_executable,
+                  options.package_root,
+                  options.silent)
   elif (cmd == 'build'):
-    return PubBuild(options.dart_executable, options.package_root, args[0])
+    return PubBuild(options.dart_executable,
+                    options.pub_executable,
+                    options.package_root,
+                    options.silent,
+                    args[0])
   elif (cmd == 'deploy'):
     Deploy('build', 'deployed')
+  elif (cmd == 'rewrite'):
+    RewritePubSpec(args[0], args[1], args[2], args[3])
   else:
     print >> sys.stderr, ('ERROR: command "%s" not supported') % (cmd)
     return -1;
@@ -92,8 +136,12 @@
   if os.getenv('DART_USE_BOOTSTRAP_BIN') != None:
     dart_executable = options.dart_executable
   # Calculate absolute paths before changing directory.
-  options.package_root = os.path.abspath(options.package_root)
-  options.dart_executable = os.path.abspath(options.dart_executable)
+  if (options.package_root != None):
+    options.package_root = os.path.abspath(options.package_root)
+  if (options.dart_executable != None):
+    options.dart_executable = os.path.abspath(options.dart_executable)
+  if (options.pub_executable != None):
+    options.pub_executable = os.path.abspath(options.pub_executable)
   if len(args) == 1:
     args[0] = os.path.abspath(args[0])
   # Pub must be run from the project's root directory.
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 1358b01..487c9e5 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -169,6 +169,7 @@
     switch (arch) {
       case 'simarm':
       case 'arm':
+      case 'armv5te':
       case 'simmips':
       case 'mips':
       case 'simarm64':
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index 135226e..d56514e 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -29,7 +29,7 @@
     new Path('pkg'),
     new Path('third_party/pkg_tested'),
     new Path('runtime/tests/vm'),
-    new Path('runtime/observatory'),
+    new Path('runtime/observatory/tests/service'),
     new Path('samples'),
     new Path('samples-dev'),
     new Path('tests/benchmark_smoke'),
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 4dddd24..3ee0c59 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -14,7 +14,7 @@
 const List<String> defaultTestSelectors =
     const ['samples', 'standalone', 'corelib', 'co19', 'language',
            'isolate', 'vm', 'html', 'benchmark_smoke',
-           'utils', 'lib', 'pkg', 'analyze_library', 'vmservice',
+           'utils', 'lib', 'pkg', 'analyze_library', 'service',
            'pkg_tested'];
 
 /**
@@ -109,7 +109,7 @@
               'arch',
               'The architecture to run tests for',
               ['-a', '--arch'],
-              ['all', 'ia32', 'x64', 'arm', 'arm64', 'mips',
+              ['all', 'ia32', 'x64', 'arm', 'armv5te', 'arm64', 'mips',
                'simarm', 'simarm64', 'simmips'],
               'ia32'),
           new _TestOptionSpecification(
diff --git a/tools/utils.py b/tools/utils.py
index 55a54bc..3c1eacb 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -48,7 +48,9 @@
 # Try to guess the host architecture.
 def GuessArchitecture():
   os_id = platform.machine()
-  if os_id.startswith('arm'):
+  if os_id.startswith('armv5te'):
+    return 'armv5te'
+  elif os_id.startswith('arm'):
     return 'arm'
   elif os_id.startswith('aarch64'):
     return 'arm64'
@@ -220,6 +222,7 @@
   'ia32': 'ia32',
   'x64': 'ia32',
   'arm': 'arm',
+  'armv5te': 'arm',
   'arm64': 'arm',
   'mips': 'mips',
   'simarm': 'ia32',
@@ -553,7 +556,11 @@
   else:
     arch = GuessArchitecture()
     system = GuessOS()
-    if arch == 'arm':
+    if arch == 'armv5te':
+      # TODO(zra): This binary does not exist, yet. Check one in once we have
+      # sufficient stability.
+      return os.path.join(dart_binary_prefix, system, 'dart-armv5te')
+    elif arch == 'arm':
       return os.path.join(dart_binary_prefix, system, 'dart-arm')
     elif arch == 'arm64':
       return os.path.join(dart_binary_prefix, system, 'dart-arm64')