Version 0.5.18.0

svn merge -r 23890:24018 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@24022 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/client/tools/buildbot_annotated_steps.py b/client/tools/buildbot_annotated_steps.py
index 5d3392c..c7360e9 100755
--- a/client/tools/buildbot_annotated_steps.py
+++ b/client/tools/buildbot_annotated_steps.py
@@ -104,7 +104,13 @@
   cmds = [sys.executable, toolsBuildScript,
           '--mode=' + mode, '--revision=' + version,
           '--name=' + name, '--out=' + outdir]
-  local_env = os.environ
+  local_env = os.environ.copy()
+  # The buildbot sets AWS_CREDENTIAL_FILE/BOTO_CONFIG to the chromium specific
+  # file, we use the one in home.
+  if 'BOTO_CONFIG' in local_env:
+    del local_env['BOTO_CONFIG']
+  if 'AWS_CREDENTIAL_FILE' in local_env:
+    del local_env['AWS_CREDENTIAL_FILE']
   #if 'linux' in name:
   #  javahome = os.path.join(os.path.expanduser('~'), 'jdk1.6.0_25')
   #  local_env['JAVA_HOME'] = javahome
diff --git a/pkg/docgen/README.md b/pkg/docgen/README.md
new file mode 100644
index 0000000..a26d1e9
--- /dev/null
+++ b/pkg/docgen/README.md
@@ -0,0 +1,11 @@
+A documentation generator for Dart.
+
+The docgen tool takes in a library as input and produces documentation
+for it as well as all libraries it imports and uses.
+
+This outputs information about all classes, variables, functions, and
+methods defined in the library and its imported libraries.
+
+## USAGE
+
+  dart docgen.dart path/to/file.dart
\ No newline at end of file
diff --git a/pkg/docgen/bin/docgen.dart b/pkg/docgen/bin/docgen.dart
new file mode 100644
index 0000000..308df28
--- /dev/null
+++ b/pkg/docgen/bin/docgen.dart
@@ -0,0 +1,393 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * The docgen tool takes in a library as input and produces documentation
+ * for the library as well as all libraries it imports and uses. The tool can
+ * be run by passing in the path to a .dart file like this:
+ *
+ *   ./dart docgen.dart path/to/file.dart
+ *
+ * This outputs information about all classes, variables, functions, and
+ * methods defined in the library and its imported libraries.
+ */
+library docgen;
+
+// TODO(tmandel): Use 'package:' references for imports with relative paths.
+import 'dart:io';
+import 'dart:json';
+import 'dart:async';
+import '../lib/dart2yaml.dart';
+import '../lib/src/dart2js_mirrors.dart';
+import 'package:markdown/markdown.dart' as markdown;
+import '../../args/lib/args.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dart';
+
+/**
+ * Entry function to create YAML documentation from Dart files.
+ */
+void main() {
+  // TODO(tmandel): Use args library once flags are clear.
+  Options opts = new Options();
+  Docgen docgen = new Docgen();
+  
+  if (opts.arguments.length > 0) {
+    List<Path> libraries = [new Path(opts.arguments[0])];
+    Path sdkDirectory = new Path("../../../sdk/");
+    var workingMirrors = analyze(libraries, sdkDirectory, 
+        options: ['--preserve-comments', '--categories=Client,Server']);
+    workingMirrors.then( (MirrorSystem mirrorSystem) {
+      var mirrors = mirrorSystem.libraries.values;
+      if (mirrors.isEmpty) {
+        print("no LibraryMirrors");
+      } else {
+        docgen.libraries = mirrors;
+        docgen.documentLibraries();
+      }
+    });
+  }
+}
+
+/**
+ * This class documents a list of libraries.
+ */
+class Docgen {
+
+  /// Libraries to be documented.
+  List<LibraryMirror> _libraries;
+  
+  /// Saves list of libraries for Docgen object.
+  void set libraries(value) => _libraries = value;
+  
+  /// Current library being documented to be used for comment links.
+  LibraryMirror _currentLibrary;
+  
+  /// Current class being documented to be used for comment links.
+  ClassMirror _currentClass;
+  
+  /// Current member being documented to be used for comment links.
+  MemberMirror _currentMember;
+  
+  /// Should the output file type be JSON?
+  // TODO(tmandel): Add flag to allow for output to JSON.
+  bool outputToJson = false;
+  
+  /// Resolves reference links
+  markdown.Resolver linkResolver;
+  
+  /**
+   * Docgen constructor initializes the link resolver for markdown parsing.
+   */
+  Docgen() {
+    this.linkResolver = (name) => 
+        fixReference(name, _currentLibrary, _currentClass, _currentMember);
+  }
+  
+  /**
+   * Creates documentation for filtered libraries.
+   */
+  void documentLibraries() {
+    //TODO(tmandel): Filter libraries and determine output type using flags.
+    _libraries.forEach((library) {
+      _currentLibrary = library;
+      var result = new Library(library.qualifiedName, _getComment(library),
+          _getVariables(library.variables), _getMethods(library.functions),
+          _getClasses(library.classes));
+      if (outputToJson) {
+        _writeToFile(stringify(result.toMap()), "${result.name}.json");
+      } else {
+        _writeToFile(getYamlString(result.toMap()), "${result.name}.yaml");
+      }
+    });
+   }
+  
+  /**
+   * Returns any documentation comments associated with a mirror with
+   * simple markdown converted to html.
+   */
+  String _getComment(DeclarationMirror mirror) {
+    String commentText;
+    mirror.metadata.forEach((metadata) {
+      if (metadata is CommentInstanceMirror) {
+        CommentInstanceMirror comment = metadata;
+        if (comment.isDocComment) {
+          if (commentText == null) {
+            commentText = comment.trimmedText;
+          } else {
+            commentText = "$commentText ${comment.trimmedText}";
+          }
+        } 
+      }
+    });
+    return commentText == null ? "" : 
+      markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver);
+  }
+
+  /**
+   * Converts all [_] references in comments to <code>_</code>.
+   */
+  // TODO(tmandel): Create proper links for [_] style markdown based
+  // on scope once layout of viewer is finished.
+  markdown.Node fixReference(String name, LibraryMirror currentLibrary, 
+      ClassMirror currentClass, MemberMirror currentMember) {
+    return new markdown.Element.text('code', name);
+  }
+  
+  /**
+   * Returns a map of [Variable] objects constructed from inputted mirrors.
+   */
+  Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap) {
+    var data = {};
+    mirrorMap.forEach((String mirrorName, VariableMirror mirror) {
+      _currentMember = mirror;
+      data[mirrorName] = new Variable(mirrorName, mirror.isFinal,
+          mirror.isStatic, mirror.type.toString(), _getComment(mirror));
+    });
+    return data;
+  }
+  
+  /**
+   * Returns a map of [Method] objects constructed from inputted mirrors.
+   */
+  Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap) {
+    var data = {};
+    mirrorMap.forEach((String mirrorName, MethodMirror mirror) {
+      _currentMember = mirror;
+      data[mirrorName] = new Method(mirrorName, mirror.isSetter,
+          mirror.isGetter, mirror.isConstructor, mirror.isOperator, 
+          mirror.isStatic, mirror.returnType.toString(), _getComment(mirror),
+          _getParameters(mirror.parameters));
+    });
+    return data;
+  } 
+  
+  /**
+   * Returns a map of [Class] objects constructed from inputted mirrors.
+   */
+  Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap) {
+    var data = {};
+    mirrorMap.forEach((String mirrorName, ClassMirror mirror) {
+      _currentClass = mirror;
+      var superclass;
+      if (mirror.superclass != null) {
+        superclass = mirror.superclass.qualifiedName;
+      }
+      var interfaces = 
+          mirror.superinterfaces.map((interface) => interface.qualifiedName);
+      data[mirrorName] = new Class(mirrorName, superclass, mirror.isAbstract,
+          mirror.isTypedef, _getComment(mirror), interfaces,
+          _getVariables(mirror.variables), _getMethods(mirror.methods));
+    });
+    return data;
+  }
+  
+  /**
+   * Returns a map of [Parameter] objects constructed from inputted mirrors.
+   */
+  Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) {
+    var data = {};
+    mirrorList.forEach((ParameterMirror mirror) {
+      _currentMember = mirror;
+      data[mirror.simpleName] = new Parameter(mirror.simpleName, 
+          mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, 
+          mirror.type.toString(), mirror.defaultValue);
+    });
+    return data;
+  }
+}
+
+/**
+ * Transforms the map by calling toMap on each value in it.
+ */
+Map recurseMap(Map inputMap) {
+  var outputMap = {};
+  inputMap.forEach((key, value) {
+    outputMap[key] = value.toMap();
+  });
+  return outputMap;
+}
+
+/**
+ * A class containing contents of a Dart library.
+ */
+class Library {
+  
+  /// Documentation comment with converted markdown.
+  String comment;
+  
+  /// Top-level variables in the library.
+  Map<String, Variable> variables;
+  
+  /// Top-level functions in the library.
+  Map<String, Method> functions;
+  
+  /// Classes defined within the library
+  Map<String, Class> classes;
+  
+  String name;
+  
+  Library(this.name, this.comment, this.variables, 
+      this.functions, this.classes);
+  
+  /// Generates a map describing the [Library] object.
+  Map toMap() {
+    var libraryMap = {};
+    libraryMap["name"] = name;
+    libraryMap["comment"] = comment;
+    libraryMap["variables"] = recurseMap(variables);
+    libraryMap["functions"] = recurseMap(functions);
+    libraryMap["classes"] = recurseMap(classes);
+    return libraryMap;
+  }
+}
+
+/**
+ * A class containing contents of a Dart class.
+ */
+// TODO(tmandel): Figure out how to do typedefs (what is needed)
+class Class {
+  
+  /// Documentation comment with converted markdown.
+  String comment;
+  
+  /// List of the names of interfaces that this class implements.
+  List<String> interfaces;
+  
+  /// Top-level variables in the class.
+  Map<String, Variable> variables;
+  
+  /// Methods in the class.
+  Map<String, Method> methods;
+  
+  String name;
+  String superclass;
+  bool isAbstract;
+  bool isTypedef;
+ 
+  Class(this.name, this.superclass, this.isAbstract, this.isTypedef,
+      this.comment, this.interfaces, this.variables, this.methods); 
+  
+  /// Generates a map describing the [Class] object.
+  Map toMap() {
+    var classMap = {};
+    classMap["name"] = name;
+    classMap["comment"] = comment;
+    classMap["superclass"] = superclass;
+    classMap["abstract"] = isAbstract.toString();
+    classMap["typedef"] = isTypedef.toString();
+    classMap["implements"] = new List.from(interfaces);
+    classMap["variables"] = recurseMap(variables);
+    classMap["methods"] = recurseMap(methods);
+    return classMap;
+  }
+}
+
+/**
+ * A class containing properties of a Dart variable.
+ */
+class Variable {
+  
+  /// Documentation comment with converted markdown.
+  String comment;
+  
+  String name;
+  bool isFinal;
+  bool isStatic;
+  String type;
+  
+  Variable(this.name, this.isFinal, this.isStatic, this.type, this.comment);
+  
+  /// Generates a map describing the [Variable] object.
+  Map toMap() {
+    var variableMap = {};
+    variableMap["name"] = name;
+    variableMap["comment"] = comment;
+    variableMap["final"] = isFinal.toString();
+    variableMap["static"] = isStatic.toString();
+    variableMap["type"] = type;
+    return variableMap;
+  }
+}
+
+/**
+ * A class containing properties of a Dart method.
+ */
+class Method {
+  
+  /// Documentation comment with converted markdown.
+  String comment;
+  
+  /// Parameters for this method.
+  Map<String, Parameter> parameters;
+  
+  String name;
+  bool isSetter;
+  bool isGetter;
+  bool isConstructor;
+  bool isOperator;
+  bool isStatic;
+  String returnType;
+  
+  Method(this.name, this.isSetter, this.isGetter, this.isConstructor,
+      this.isOperator, this.isStatic, this.returnType, this.comment,
+      this.parameters);
+  
+  /// Generates a map describing the [Method] object.
+  Map toMap() {
+    var methodMap = {};
+    methodMap["name"] = name;
+    methodMap["comment"] = comment;
+    methodMap["type"] = isSetter ? "setter" : isGetter ? "getter" :
+      isOperator ? "operator" : isConstructor ? "constructor" : "method";
+    methodMap["static"] = isStatic.toString();
+    methodMap["return"] = returnType;
+    methodMap["parameters"] = recurseMap(parameters);
+    return methodMap;
+  }  
+}
+
+/**
+ * A class containing properties of a Dart method/function parameter.
+ */
+class Parameter {
+  
+  String name;
+  bool isOptional;
+  bool isNamed;
+  bool hasDefaultValue;
+  String type;
+  String defaultValue;
+  
+  Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue,
+      this.type, this.defaultValue);
+  
+  /// Generates a map describing the [Parameter] object.
+  Map toMap() {
+    var parameterMap = {};
+    parameterMap["name"] = name;
+    parameterMap["optional"] = isOptional.toString();
+    parameterMap["named"] = isNamed.toString();
+    parameterMap["default"] = hasDefaultValue.toString();
+    parameterMap["type"] = type;
+    parameterMap["value"] = defaultValue;
+    return parameterMap;
+  } 
+}
+
+/**
+ * Writes text to a file in the 'docs' directory.
+ */
+void _writeToFile(String text, String filename) {
+  Directory dir = new Directory('docs');
+  if (!dir.existsSync()) {
+    dir.createSync();
+  }
+  File file = new File('docs/$filename');
+  if (!file.exists()) {
+    file.createSync();
+  }
+  file.openSync();
+  file.writeAsString(text);
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/docgen/examples/test.dart b/pkg/docgen/example/test.dart
similarity index 73%
rename from sdk/lib/_internal/docgen/examples/test.dart
rename to pkg/docgen/example/test.dart
index 026663e..d93b63f 100755
--- a/sdk/lib/_internal/docgen/examples/test.dart
+++ b/pkg/docgen/example/test.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 /**
  * This library is used solely for testing during development and is not
  * intended to be run by the testing machines.
@@ -6,6 +10,7 @@
 library DummyLibrary;
 
 import 'dart:json';
+import 'dart:math';
 
 /// Doc comment for top-level variable.
 int _variable1 = 0;
@@ -24,6 +29,9 @@
  */
 class A implements B {
 
+  /**
+   * Markdown _test_ for **class** [A] 
+   */
   int _someNumber;
 
   A() {
diff --git a/sdk/lib/_internal/docgen/lib/dart2yaml.dart b/pkg/docgen/lib/dart2yaml.dart
similarity index 81%
rename from sdk/lib/_internal/docgen/lib/dart2yaml.dart
rename to pkg/docgen/lib/dart2yaml.dart
index a8be283..a03c7f1 100644
--- a/sdk/lib/_internal/docgen/lib/dart2yaml.dart
+++ b/pkg/docgen/lib/dart2yaml.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 /**
  * This library is used to convert data from a map to a YAML string.
  */
@@ -45,14 +49,10 @@
 }
 
 /**
- * Writes to a StringBuffer the correct output for the inputted element.
+ * Returns an escaped String form of the inputted element.
  */
 String _processElement(var element) {
-  if (element.toString().contains("\"")) {
-    return "$element\n";
-  } else {
-    return "\"$element\"\n";
-  }
+  return "\"${element.toString().replaceAll("\"", "\\\"")}\"\n";
 }
 
 /**
diff --git a/sdk/lib/_internal/docgen/lib/src/dart2js_mirrors.dart b/pkg/docgen/lib/src/dart2js_mirrors.dart
similarity index 85%
rename from sdk/lib/_internal/docgen/lib/src/dart2js_mirrors.dart
rename to pkg/docgen/lib/src/dart2js_mirrors.dart
index 1885363..cee8fbe 100644
--- a/sdk/lib/_internal/docgen/lib/src/dart2js_mirrors.dart
+++ b/pkg/docgen/lib/src/dart2js_mirrors.dart
@@ -11,14 +11,14 @@
 import 'dart:async' show Future;
 import 'dart:io' show Path;
 
-import '../../../compiler/compiler.dart' as api;
-import '../../../compiler/implementation/mirrors/dart2js_mirror.dart' as dart2js
-    show analyze, Dart2JsMirrorSystem;
-import '../../../compiler/implementation/mirrors/mirrors.dart'
+import '../../../../sdk/lib/_internal/compiler/compiler.dart' as api;
+import '../../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart' 
+    as dart2js show analyze, Dart2JsMirrorSystem;
+import '../../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart'
     show MirrorSystem;
-import '../../../compiler/implementation/source_file_provider.dart'
+import '../../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart'
     show FormattingDiagnosticHandler, SourceFileProvider;
-import '../../../compiler/implementation/filenames.dart'
+import '../../../../sdk/lib/_internal/compiler/implementation/filenames.dart'
     show appendSlash, currentDirectory;
 
 // TODO(johnniwinther): Support client configurable providers.
diff --git a/pkg/docgen/pubspec.yaml b/pkg/docgen/pubspec.yaml
new file mode 100644
index 0000000..697f405
--- /dev/null
+++ b/pkg/docgen/pubspec.yaml
@@ -0,0 +1,4 @@
+name: docgen
+description: A documentation generator for the Dart repository.
+dependencies:
+  markdown: any
\ No newline at end of file
diff --git a/pkg/pathos/README.md b/pkg/pathos/README.md
index 66f40b1..e67fc5e 100644
--- a/pkg/pathos/README.md
+++ b/pkg/pathos/README.md
@@ -4,9 +4,9 @@
 joining, splitting, normalizing, etc.
 
 We've tried very hard to make this library do the "right" thing on whatever
-platform you run it on. When you use the top-level functions, it will assume
-the host OS's path style and work with that. If you want to specifically work
-with paths of a specific style, you can construct a `path.Builder` for that
+platform you run it on. When you use the top-level functions, it will assume the
+current platform's path style and work with that. If you want to specifically
+work with paths of a specific style, you can construct a `path.Builder` for that
 style.
 
 ## Using
@@ -20,16 +20,18 @@
 
 The most common way to use the library is through the top-level functions.
 These manipulate path strings based on your current working directory and the
-path style (POSIX or Windows) of the host operating system.
+path style (POSIX, Windows, or URLs) of the host platform.
 
 ### String get current
 
-Gets the path to the current working directory.
+Gets the path to the current working directory. In the browser, this means the
+current URL. When using dart2js, this currently returns `.` due to technical
+constraints. In the future, it will return the current URL.
 
 ### String get separator
 
-Gets the path separator for the current platform. On Mac and Linux, this
-is `/`. On Windows, it's `\`.
+Gets the path separator for the current platform. On Mac, Linux, and the
+browser, this is `/`. On Windows, it's `\`.
 
 ### String absolute(String path)
 
@@ -100,12 +102,23 @@
     path.rootPrefix(r'path\to\foo'); // -> ''
     path.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
 
+    // URL
+    path.rootPrefix('path/to/foo'); // -> ''
+    path.rootPrefix('http://dartlang.org/path/to/foo');
+      // -> 'http://dartlang.org'
+
 ### bool isAbsolute(String path)
 
-Returns `true` if [path] is an absolute path and `false` if it is a
-relative path. On POSIX systems, absolute paths start with a `/` (forward
-slash). On Windows, an absolute path starts with `\\`, or a drive letter
-followed by `:/` or `:\`.
+Returns `true` if [path] is an absolute path and `false` if it is a relative
+path. On POSIX systems, absolute paths start with a `/` (forward slash). On
+Windows, an absolute path starts with `\\`, or a drive letter followed by `:/`
+or `:\`. For URLs, absolute paths either start with a protocol and optional
+hostname (e.g. `http://dartlang.org`, `file://`) or with a `/`.
+
+URLs that start with `/` are known as "root-relative", since they're relative to
+the root of the current URL. Since root-relative paths are still absolute in
+every other sense, [isAbsolute] will return true for them. They can be detected
+using [isRootRelative].
 
 ### bool isRelative(String path)
 
@@ -114,6 +127,16 @@
 Windows, an absolute path starts with `\\`, or a drive letter followed by
 `:/` or `:\`.
 
+### bool isRootRelative(String path)
+
+Returns `true` if [path] is a root-relative path and `false` if it's not. URLs
+that start with `/` are known as "root-relative", since they're relative to the
+root of the current URL. Since root-relative paths are still absolute in every
+other sense, [isAbsolute] will return true for them. They can be detected using
+[isRootRelative].
+
+No POSIX and Windows paths are root-relative.
+
 ### String join(String part1, [String part2, String part3, ...])
 
 Joins the given path parts into a single path using the current platform's
@@ -149,6 +172,10 @@
     // Windows
     path.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo']
 
+    // Browser
+    path.split('http://dartlang.org/path/to/foo');
+      // -> ['http://dartlang.org', 'path', 'to', 'foo']
+
 ### String normalize(String path)
 
 Normalizes [path], simplifying it by handling `..`, and `.`, and
@@ -176,8 +203,13 @@
 Since there is no relative path from one drive letter to another on Windows,
 this will return an absolute path in that case.
 
+    // Windows
     path.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other'
 
+    // URL
+    path.relative('http://dartlang.org', from: 'http://pub.dartlang.org');
+      // -> 'http://dartlang.org'
+
 ### String withoutExtension(String path)
 
 Removes a trailing extension from the last part of [path].
@@ -234,6 +266,11 @@
     builder.rootPrefix(r'path\to\foo'); // -> ''
     builder.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
 
+    // URL
+    builder.rootPrefix('path/to/foo'); // -> ''
+    builder.rootPrefix('http://dartlang.org/path/to/foo');
+      // -> 'http://dartlang.org'
+
 ### String resolve(String part1, [String part2, String part3, ...])
 
 Creates a new path by appending the given path parts to the [root].
@@ -244,9 +281,9 @@
 
 ## The path.Style class
 
-The path library can work with two different "flavors" of path: POSIX and
-Windows. The differences between these are encapsulated by the `path.Style`
-enum class. There are two instances of it:
+The path library can work with three different "flavors" of path: POSIX,
+Windows, and URLs. The differences between these are encapsulated by the
+`path.Style` enum class. There are three instances of it:
 
 ### path.Style.posix
 
@@ -259,16 +296,22 @@
 a drive letter followed by a colon (example, "C:") or two backslashes
 ("\\") for UNC paths.
 
+### path.Style.url
+
+URLs aren't filesystem paths, but they're supported by Pathos to make it easier
+to manipulate URL paths in the browser.
+
+URLs use "/" (forward slash) as separators. Absolute paths either start with a
+protocol and optional hostname (e.g. `http://dartlang.org`, `file://`) or with
+"/".
+
 ## FAQ
 
 ### Where can I use this?
 
-Currently, Dart has no way of encapsulating configuration-specific code.
-Ideally, this library would be able to import dart:io when that's available or
-dart:html when that is. That would let it seamlessly work on both.
-
-Until then, this only works on the standalone VM. It's API is not coupled to
-dart:io, but it uses it internally to determine the current working directory.
+Pathos runs on the Dart VM and in the browser under both dart2js and Dartium.
+Under dart2js, it currently returns "." as the current working directory, while
+under Dartium it returns the current URL.
 
 ### Why doesn't this make paths first-class objects?
 
diff --git a/pkg/pathos/lib/path.dart b/pkg/pathos/lib/path.dart
index 6e7c8c2..145953f 100644
--- a/pkg/pathos/lib/path.dart
+++ b/pkg/pathos/lib/path.dart
@@ -21,7 +21,7 @@
 /// [pkg]: http://pub.dartlang.org/packages/pathos
 library path;
 
-import 'dart:io' as io;
+import 'dart:mirrors';
 
 /// An internal builder for the current OS so we can provide a straight
 /// functional interface and not require users to create one.
@@ -34,8 +34,47 @@
 void _growListFront(List list, int length, fillValue) =>
   list.insertAll(0, new List.filled(length, fillValue));
 
+/// If we're running in the server-side Dart VM, this will return a
+/// [LibraryMirror] that gives access to the `dart:io` library.
+///
+/// If `dart:io` is not available, this returns null.
+LibraryMirror get _io {
+  try {
+    return currentMirrorSystem().libraries[Uri.parse('dart:io')];
+  } catch (_) {
+    return null;
+  }
+}
+
+// TODO(nweiz): when issue 6490 or 6943 are fixed, make this work under dart2js.
+/// If we're running in Dartium, this will return a [LibraryMirror] that gives
+/// access to the `dart:html` library.
+///
+/// If `dart:html` is not available, this returns null.
+LibraryMirror get _html {
+  try {
+    return currentMirrorSystem().libraries[Uri.parse('dart:html')];
+  } catch (_) {
+    return null;
+  }
+}
+
 /// Gets the path to the current working directory.
-String get current => io.Directory.current.path;
+///
+/// In the browser, this means the current URL. When using dart2js, this
+/// currently returns `.` due to technical constraints. In the future, it will
+/// return the current URL.
+String get current {
+  if (_io != null) {
+    return _io.classes[const Symbol('Directory')]
+        .getField(const Symbol('current')).reflectee.path;
+  } else if (_html != null) {
+    return _html.getField(const Symbol('window'))
+        .reflectee.location.href;
+  } else {
+    return '.';
+  }
+}
 
 /// Gets the path separator for the current platform. On Mac and Linux, this
 /// is `/`. On Windows, it's `\`.
@@ -104,6 +143,11 @@
 ///     // Windows
 ///     path.rootPrefix(r'path\to\foo'); // -> ''
 ///     path.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
+///
+///     // URL
+///     path.rootPrefix('path/to/foo'); // -> ''
+///     path.rootPrefix('http://dartlang.org/path/to/foo');
+///       // -> 'http://dartlang.org'
 String rootPrefix(String path) => _builder.rootPrefix(path);
 
 /// Returns `true` if [path] is an absolute path and `false` if it is a
@@ -187,6 +231,10 @@
 ///
 ///     // Windows
 ///     path.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo']
+///
+///     // Browser
+///     path.split('http://dartlang.org/path/to/foo');
+///       // -> ['http://dartlang.org', 'path', 'to', 'foo']
 List<String> split(String path) => _builder.split(path);
 
 /// Normalizes [path], simplifying it by handling `..`, and `.`, and
@@ -210,9 +258,15 @@
 ///         from: '/root/path'); // -> '../other.dart'
 ///
 /// Since there is no relative path from one drive letter to another on Windows,
-/// this will return an absolute path in that case.
+/// or from one hostname to another for URLs, this will return an absolute path
+/// in those cases.
 ///
+///     // Windows
 ///     path.relative(r'D:\other', from: r'C:\home'); // -> 'D:\other'
+///
+///     // URL
+///     path.relative('http://dartlang.org', from: 'http://pub.dartlang.org');
+///       // -> 'http://dartlang.org'
 String relative(String path, {String from}) =>
     _builder.relative(path, from: from);
 
@@ -252,9 +306,16 @@
   /// If [style] is omitted, it uses the host operating system's path style. If
   /// [root] is omitted, it defaults to the current working directory. If [root]
   /// is relative, it is considered relative to the current working directory.
+  ///
+  /// On the browser, the path style is [Style.url]. In Dartium, [root] defaults
+  /// to the current URL. When using dart2js, it currently defaults to `.` due
+  /// to technical constraints.
   factory Builder({Style style, String root}) {
     if (style == null) {
-      if (io.Platform.operatingSystem == 'windows') {
+      if (_io == null) {
+        style = Style.url;
+      } else if (_io.classes[const Symbol('Platform')]
+          .getField(const Symbol('operatingSystem')).reflectee == 'windows') {
         style = Style.windows;
       } else {
         style = Style.posix;
@@ -347,6 +408,11 @@
   ///     // Windows
   ///     builder.rootPrefix(r'path\to\foo'); // -> ''
   ///     builder.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
+  ///
+  ///     // URL
+  ///     builder.rootPrefix('path/to/foo'); // -> ''
+  ///     builder.rootPrefix('http://dartlang.org/path/to/foo');
+  ///       // -> 'http://dartlang.org'
   String rootPrefix(String path) {
     var root = _parse(path).root;
     return root == null ? '' : root;
@@ -550,6 +616,10 @@
     var fromParsed = _parse(from)..normalize();
     var pathParsed = _parse(path)..normalize();
 
+    if (fromParsed.parts.length > 0 && fromParsed.parts[0] == '.') {
+      return pathParsed.toString();
+    }
+
     // If the root prefixes don't match (for example, different drive letters
     // on Windows), then there is no relative path, so just return the absolute
     // one. In Windows, drive letters are case-insenstive and we allow
diff --git a/pkg/pathos/test/pathos_dart2js_test.dart b/pkg/pathos/test/pathos_dart2js_test.dart
new file mode 100644
index 0000000..e49659d
--- /dev/null
+++ b/pkg/pathos/test/pathos_dart2js_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:unittest/unittest.dart';
+import 'package:pathos/path.dart' as path;
+
+// In the future, the default root will be window.location.href, but right now
+// that's not possible.
+
+main() {
+  group('new Builder()', () {
+    test('uses the current working directory if root is omitted', () {
+      var builder = new path.Builder();
+      expect(builder.root, '.');
+    });
+
+    test('uses URL if style is omitted', () {
+      var builder = new path.Builder();
+      expect(builder.style, path.Style.url);
+    });
+  });
+
+  test('current', () {
+    expect(path.current, '.');
+  });
+}
diff --git a/pkg/pathos/test/pathos_dartium_test.dart b/pkg/pathos/test/pathos_dartium_test.dart
new file mode 100644
index 0000000..f03abc6
--- /dev/null
+++ b/pkg/pathos/test/pathos_dartium_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+import 'package:pathos/path.dart' as path;
+
+main() {
+  useHtmlConfiguration();
+
+  group('new Builder()', () {
+    test('uses the current working directory if root is omitted', () {
+      var builder = new path.Builder();
+      expect(builder.root, window.location.href);
+    });
+
+    test('uses URL if style is omitted', () {
+      var builder = new path.Builder();
+      expect(builder.style, path.Style.url);
+    });
+  });
+
+  test('current', () {
+    expect(path.current, window.location.href);
+  });
+}
diff --git a/pkg/pathos/test/pathos_io_test.dart b/pkg/pathos/test/pathos_io_test.dart
new file mode 100644
index 0000000..bb14bd7
--- /dev/null
+++ b/pkg/pathos/test/pathos_io_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io' as io;
+
+import 'package:unittest/unittest.dart';
+import 'package:pathos/path.dart' as path;
+
+main() {
+  group('new Builder()', () {
+    test('uses the current working directory if root is omitted', () {
+      var builder = new path.Builder();
+      expect(builder.root, io.Directory.current.path);
+    });
+
+    test('uses the host OS if style is omitted', () {
+      var builder = new path.Builder();
+      if (io.Platform.operatingSystem == 'windows') {
+        expect(builder.style, path.Style.windows);
+      } else {
+        expect(builder.style, path.Style.posix);
+      }
+    });
+  });
+
+  test('current', () {
+    expect(path.current, io.Directory.current.path);
+  });
+}
diff --git a/pkg/pathos/test/pathos_posix_test.dart b/pkg/pathos/test/pathos_posix_test.dart
index d6bfb91..ecdd133 100644
--- a/pkg/pathos/test/pathos_posix_test.dart
+++ b/pkg/pathos/test/pathos_posix_test.dart
@@ -4,8 +4,6 @@
 
 library pathos_posix_test;
 
-import 'dart:io' as io;
-
 import 'package:unittest/unittest.dart';
 import 'package:pathos/path.dart' as path;
 
@@ -300,6 +298,12 @@
         expect(builder.relative('../a/b.txt'), '../a/b.txt');
         expect(builder.relative('a/./b/../c.txt'), 'a/c.txt');
       });
+
+      // Regression
+      test('from root-only path', () {
+        expect(builder.relative('/', from: '/'), '.');
+        expect(builder.relative('/root/path', from: '/'), 'root/path');
+      });
     });
 
     group('from relative root', () {
@@ -344,6 +348,12 @@
           equals('/foo/bar/baz'));
       expect(r.relative('..', from: 'foo/bar'), equals('../../..'));
     });
+
+    test('from a . root', () {
+      var r = new path.Builder(style: path.Style.posix, root: '.');
+      expect(r.relative('/foo/bar/baz'), equals('/foo/bar/baz'));
+      expect(r.relative('foo/bar/baz'), equals('foo/bar/baz'));
+    });
   });
 
   group('resolve', () {
diff --git a/pkg/pathos/test/pathos_test.dart b/pkg/pathos/test/pathos_test.dart
index 2d56ee2..b002999 100644
--- a/pkg/pathos/test/pathos_test.dart
+++ b/pkg/pathos/test/pathos_test.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library pathos_test;
-
-import 'dart:io' as io;
-
 import 'package:unittest/unittest.dart';
 import 'package:pathos/path.dart' as path;
 
@@ -37,23 +33,5 @@
       var builder = new path.Builder(style: path.Style.windows);
       expect(builder.style, path.Style.windows);
     });
-
-    test('uses the current working directory if root is omitted', () {
-      var builder = new path.Builder();
-      expect(builder.root, io.Directory.current.path);
-    });
-
-    test('uses the host OS if style is omitted', () {
-      var builder = new path.Builder();
-      if (io.Platform.operatingSystem == 'windows') {
-        expect(builder.style, path.Style.windows);
-      } else {
-        expect(builder.style, path.Style.posix);
-      }
-    });
-  });
-
-  test('current', () {
-    expect(path.current, io.Directory.current.path);
   });
 }
diff --git a/pkg/pathos/test/pathos_url_test.dart b/pkg/pathos/test/pathos_url_test.dart
index f419af4..b8c100f 100644
--- a/pkg/pathos/test/pathos_url_test.dart
+++ b/pkg/pathos/test/pathos_url_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:unittest/unittest.dart';
 import 'package:pathos/path.dart' as path;
 
@@ -436,6 +434,16 @@
         expect(builder.relative('../a/b.txt'), '../a/b.txt');
         expect(builder.relative('a/./b/../c.txt'), 'a/c.txt');
       });
+
+      // Regression
+      test('from root-only path', () {
+        expect(builder.relative('http://dartlang.org',
+                from: 'http://dartlang.org'),
+            '.');
+        expect(builder.relative('http://dartlang.org/root/path',
+                from: 'http://dartlang.org'),
+            'root/path');
+      });
     });
 
     group('from relative root', () {
@@ -555,6 +563,15 @@
 
       expect(r.relative('..', from: 'foo/bar'), equals('../../..'));
     });
+
+    test('from a . root', () {
+      var r = new path.Builder(style: path.Style.url, root: '.');
+      expect(r.relative('http://dartlang.org/foo/bar/baz'),
+          equals('http://dartlang.org/foo/bar/baz'));
+      expect(r.relative('file:///foo/bar/baz'), equals('file:///foo/bar/baz'));
+      expect(r.relative('/foo/bar/baz'), equals('/foo/bar/baz'));
+      expect(r.relative('foo/bar/baz'), equals('foo/bar/baz'));
+    });
   });
 
   group('resolve', () {
diff --git a/pkg/pathos/test/pathos_windows_test.dart b/pkg/pathos/test/pathos_windows_test.dart
index 8419b53..6d22742 100644
--- a/pkg/pathos/test/pathos_windows_test.dart
+++ b/pkg/pathos/test/pathos_windows_test.dart
@@ -4,8 +4,6 @@
 
 library pathos_windows_test;
 
-import 'dart:io' as io;
-
 import 'package:unittest/unittest.dart';
 import 'package:pathos/path.dart' as path;
 
@@ -333,6 +331,12 @@
         expect(builder.relative(r'..\a\b.txt'), r'..\a\b.txt');
         expect(builder.relative(r'a\.\b\..\c.txt'), r'a\c.txt');
       });
+
+      // Regression
+      test('from root-only path', () {
+        expect(builder.relative(r'C:\', from: r'C:\'), '.');
+        expect(builder.relative(r'C:\root\path', from: r'C:\'), r'root\path');
+      });
     });
 
     group('from relative root', () {
@@ -385,6 +389,12 @@
       expect(builder.relative(r'D:\a\b'), r'D:\a\b');
       expect(builder.relative(r'\\a\b'), r'\\a\b');
     });
+
+    test('from a . root', () {
+      var r = new path.Builder(style: path.Style.windows, root: '.');
+      expect(r.relative(r'C:\foo\bar\baz'), equals(r'C:\foo\bar\baz'));
+      expect(r.relative(r'foo\bar\baz'), equals(r'foo\bar\baz'));
+    });
   });
 
   group('resolve', () {
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 5b5c18f..ae61138 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -49,8 +49,10 @@
 [ $runtime == safari ]
 fixnum/test/int_64_test: Pass, Fail # Bug in JSC.
 
-# Skip browser-specific Intl tests on VM
+# Skip browser-specific tests on VM
 [ $runtime == vm ]
+pathos/test/pathos_dartium_test: Fail, OK # Uses dart:html
+pathos/test/pathos_dart2js_test: Fail, OK # Uses dart:html
 intl/test/find_default_locale_browser_test: Skip
 intl/test/date_time_format_http_request_test: Skip
 
@@ -59,11 +61,24 @@
 intl/test/message_extraction/message_extraction_test: Fail # Issue 9167
 
 [ $compiler == dart2js ]
-serialization/test/serialization_test: Fail # Issue 6490
-serialization/test/no_library_test: Fail # Issue 6490
-analyzer_experimental/test/generated/ast_test: Fail
+analyzer_experimental/test/generated/ast_test: Fail, Slow # Issue 11230
 unittest/test/instance_test: Fail # http://dartbug.com/11191
 
+[ $compiler == dart2js && $runtime == d8 && $checked ]
+pathos/test/pathos_io_test: Fail # Issue 11258
+oauth2/*: Fail # Issue 11258
+oauth2/test/utils_test: Pass
+http/*: Fail # Issue 11258
+stack_trace/*: Fail # Issue 11258
+intl/test/date_time_format_file_odd_test: Fail # Issue 11258
+intl/test/date_time_format_file_even_test: Fail # Issue 11258
+intl/test/message_extraction/message_extraction_test: Fail # Issue 11258
+scheduled_test/*: Fail # Issue 11258
+scheduled_test/test/substitute_future_test: Pass
+scheduled_test/test/value_future_test: Pass
+analyzer_experimental/test/error_test: Fail # Issue 11258
+analyzer_experimental/test/services/formatter_test: Fail # Issue 11258
+
 [ $compiler == dartc ]
 unittest/test/mock_regexp_negative_test: Fail
 unittest/test/mock_stepwise_negative_test: Fail
@@ -79,6 +94,9 @@
 [ $compiler == dart2js && $csp ]
 unittest/test/unittest_test: Pass, Crash # Issue 10935
 
+serialization/test/serialization_test: Fail # Issue 6490
+serialization/test/no_library_test: Fail # Issue 6490
+
 [ $compiler == dart2js && $minified ]
 # The unittest package relies on getting the original (non-minified) method
 # names in Invocation.  You can't get that when minifying.
@@ -86,6 +104,9 @@
 unittest/test/mock_test: Fail
 unittest/test/mock_regexp_negative_test: Fail
 
+serialization/test/serialization_test: Fail # Issue 6490
+serialization/test/no_library_test: Fail # Issue 6490
+
 # The unminified unittest tests test that the real names of Dart types are
 # printed. Minified versions of these tests exist that test the behavior when
 # minified.
@@ -95,6 +116,7 @@
 crypto/test/sha1_test: Fail # V8 bug: https://code.google.com/p/v8/issues/detail?id=2692
 
 [ $compiler == dart2js && $browser ]
+pathos/test/pathos_dartium_test: Fail, OK # Issue 6490
 crypto/test/sha256_test: Slow, Pass
 crypto/test/sha1_test: Slow, Pass
 
@@ -119,10 +141,7 @@
 oauth2/test/client_test: Fail, OK # Uses dart:io.
 oauth2/test/credentials_test: Fail, OK # Uses dart:io.
 oauth2/test/handle_access_token_response_test: Fail, OK # Uses dart:io.
-pathos/test/pathos_posix_test: Fail, OK # Uses dart:io.
-pathos/test/pathos_test: Fail, OK # Uses dart:io.
-pathos/test/pathos_url_test: Fail, OK # Uses dart:io.
-pathos/test/pathos_windows_test: Fail, OK # Uses dart:io.
+pathos/test/pathos_io_test: Fail, OK # Uses dart:io.
 
 scheduled_test/test/descriptor/async_test: Fail # http://dartbug.com/8440
 scheduled_test/test/descriptor/directory_test: Fail # http://dartbug.com/8440
@@ -181,6 +200,9 @@
 [ $runtime == dartium || $runtime == drt ]
 serialization/test/no_library_test: Skip # Expected Failure
 
+[ ($runtime == dartium || $runtime == drt) && $compiler == none ]
+pathos/test/pathos_dart2js_test: Fail, OK # Issue 6490
+
 # Skip mdv_observe tests on command line VM, they only run in the browser.
 [ $runtime == vm ]
 mdv_observe: Skip
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 0acd6c0..ba50c9f 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -336,10 +336,6 @@
                                                 bool runInShell,
                                                 Encoding stdoutEncoding,
                                                 Encoding stderrEncoding) {
-  // Extract output encoding options and verify arguments.
-  if (stdoutEncoding == null) stdoutEncoding = Encoding.SYSTEM;
-  if (stderrEncoding == null) stderrEncoding = Encoding.SYSTEM;
-
   // Start the underlying process.
   return Process.start(path,
                        arguments,
@@ -351,30 +347,35 @@
     // Make sure the process stdin is closed.
     p.stdin.close();
 
-    // Setup stdout handling.
-    Future<StringBuffer> stdout = p.stdout
-        .transform(new StringDecoder(stdoutEncoding))
-        .fold(
-            new StringBuffer(),
-            (buf, data) {
-              buf.write(data);
-              return buf;
-            });
+    // Setup stdout and stderr handling.
+    Future foldStream(Stream<List<int>> stream, Encoding encoding) {
+      if (encoding == null) {
+        return stream
+            .fold(
+                new _BufferList(),
+                (buf, data) {
+                  buf.add(data);
+                  return buf;
+                })
+            .then((buf) => buf.readBytes());
+      } else {
+        return stream
+            .transform(new StringDecoder(encoding))
+            .fold(
+                new StringBuffer(),
+                (buf, data) {
+                  buf.write(data);
+                  return buf;
+                })
+            .then((sb) => sb.toString());
+      }
+    }
 
-    Future<StringBuffer> stderr = p.stderr
-        .transform(new StringDecoder(stderrEncoding))
-        .fold(
-            new StringBuffer(),
-            (buf, data) {
-              buf.write(data);
-              return buf;
-            });
+    Future stdout = foldStream(p.stdout, stdoutEncoding);
+    Future stderr = foldStream(p.stderr, stderrEncoding);
 
     return Future.wait([p.exitCode, stdout, stderr]).then((result) {
-      return new _ProcessResult(pid,
-                                result[0],
-                                result[1].toString(),
-                                result[2].toString());
+      return new _ProcessResult(pid, result[0], result[1], result[2]);
     });
   });
 }
@@ -383,11 +384,11 @@
 class _ProcessResult implements ProcessResult {
   const _ProcessResult(int this.pid,
                        int this.exitCode,
-                       String this.stdout,
-                       String this.stderr);
+                       this.stdout,
+                       this.stderr);
 
   final int pid;
   final int exitCode;
-  final String stdout;
-  final String stderr;
+  final stdout;
+  final stderr;
 }
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 7d0f5da..e69dfed 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -299,7 +299,7 @@
     if (isClosed) return 0;
     if (bytes == 0) return 0;
     _BufferAndStart bufferAndStart =
-        _ensureFastAndSerializableBuffer(buffer, offset, offset + bytes);
+        _ensureFastAndSerializableByteData(buffer, offset, offset + bytes);
     var result =
         nativeWrite(bufferAndStart.buffer, bufferAndStart.start, bytes);
     if (result is OSError) {
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index afbceaa..075ce12 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -2274,6 +2274,22 @@
 /* TODO(turnidge): Consider renaming to NativeFunctionResolver or
  * NativeResolver. */
 
+
+/* --- Metadata support --- */
+
+/**
+ * Get metadata associated with an object.
+ *
+ * \param obj Object for which the metadata is retrieved.
+ *
+ * \return If no error occurs, returns an array of metadata values.
+ *   Returns an empty array if there is no metadata for the object.
+ *   Returns an error if the evaluation of the metadata expressions fails.
+ *
+ */
+DART_EXPORT Dart_Handle Dart_GetMetadata(Dart_Handle obj);
+
+
 /* --- Scripts and Libraries ---
  * TODO(turnidge): Finish documenting this section. */
 
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index fc7797f..72b6f4b 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -81,6 +81,18 @@
     return new _AllMatchesIterable(this, str);
   }
 
+  Match matchAsPrefix(String string, [int start = 0]) {
+    if (start < 0 || start > string.length) {
+      throw new RangeError.range(start, 0, string.length);
+    }
+    // Inefficient check that searches for a later match too.
+    // Change this when possible.
+    List<int> list = _ExecuteMatch(string, start);
+    if (list == null) return null;
+    if (list[0] != start) return null;
+    return new _JSRegExpMatch(this, string, list);
+  }
+
   bool hasMatch(String str) {
     List match = _ExecuteMatch(str, 0);
     return (match == null) ? false : true;
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index 16c3232..80b369c 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -113,11 +113,8 @@
 
   bool _substringMatches(int start, String other) {
     if (other.isEmpty) return true;
-    if ((start < 0) || (start >= this.length)) {
-      return false;
-    }
     final int len = other.length;
-    if ((start + len) > this.length) {
+    if ((start < 0) || (start + len > this.length)) {
       return false;
     }
     for (int i = 0; i < len; i++) {
@@ -132,38 +129,57 @@
     return _substringMatches(this.length - other.length, other);
   }
 
-  bool startsWith(String other) {
-    return _substringMatches(0, other);
+  bool startsWith(Pattern pattern) {
+    if (pattern is String) {
+      return _substringMatches(0, pattern);
+    }
+    return pattern.matchAsPrefix(this, 0) != null;
   }
 
-  int indexOf(String other, [int start = 0]) {
-    if (other.isEmpty) {
-      return start < this.length ? start : this.length;
+  int indexOf(Pattern pattern, [int start = 0]) {
+    if (start < 0 || start > this.length) {
+      throw new RangeError.range(start, 0, this.length);
     }
-    if ((start < 0) || (start >= this.length)) {
+    if (pattern is String) {
+      String other = pattern;
+      int maxIndex = this.length - other.length;
+      // TODO: Use an efficient string search (e.g. BMH).
+      for (int index = start; index <= maxIndex; index++) {
+        if (_substringMatches(index, other)) {
+          return index;
+        }
+      }
       return -1;
     }
-    int len = this.length - other.length + 1;
-    for (int index = start; index < len; index++) {
-      if (_substringMatches(index, other)) {
-        return index;
-      }
+    for (int i = start; i <= this.length; i++) {
+      // TODO(11276); This has quadratic behavior because matchAsPrefix tries
+      // to find a later match too. Optimize matchAsPrefix to avoid this.
+      if (pattern.matchAsPrefix(this, i) != null) return i;
     }
     return -1;
   }
 
-  int lastIndexOf(String other, [int start = null]) {
-    if (start == null) start = length - 1;
-    if (other.isEmpty) {
-      return min(this.length, start);
+  int lastIndexOf(Pattern pattern, [int start = null]) {
+    if (start == null) {
+      start = this.length;
+    } else if (start < 0 || start > this.length) {
+      throw new RangeError.range(start, 0, this.length);
     }
-    if (start >= this.length) {
-      start = this.length - 1;
-    }
-    for (int index = start; index >= 0; index--) {
-      if (_substringMatches(index, other)) {
-        return index;
+    if (pattern is String) {
+      String other = pattern;
+      int maxIndex = this.length - other.length;
+      if (maxIndex < start) start = maxIndex;
+      for (int index = start; index >= 0; index--) {
+        if (_substringMatches(index, other)) {
+          return index;
+        }
       }
+      return -1;
+    }
+    for (int i = start; i >= 0; i--) {
+      // TODO(11276); This has quadratic behavior because matchAsPrefix tries
+      // to find a later match too. Optimize matchAsPrefix to avoid this.
+      if (pattern.matchAsPrefix(this, i) != null) return i;
     }
     return -1;
   }
@@ -421,6 +437,19 @@
     return result;
   }
 
+  Match matchAsPrefix(String string, [int start = 0]) {
+    if (start < 0 || start > string.length) {
+      throw new RangeError.range(start, 0, string.length);
+    }
+    if (start + this.length > string.length) return null;
+    for (int i = 0; i < this.length; i++) {
+      if (string.codeUnitAt(start + i) != this.codeUnitAt(i)) {
+        return null;
+      }
+    }
+    return new _StringMatch(start, string, this);
+  }
+
   List<String> split(Pattern pattern) {
     if ((pattern is String) && pattern.isEmpty) {
       List<String> result = new List<String>(length);
diff --git a/runtime/lib/type_patch.dart b/runtime/lib/type_patch.dart
index 8f6c325..4f2dee7 100644
--- a/runtime/lib/type_patch.dart
+++ b/runtime/lib/type_patch.dart
@@ -16,3 +16,11 @@
 // Equivalent of RawTypeParameter.
 class _TypeParameter extends _AbstractType {
 }
+
+// Equivalent of RawBoundedType.
+class _BoundedType extends _AbstractType {
+}
+
+// Equivalent of RawMixinAppType.
+class _MixinAppType extends _AbstractType {
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index b11812d..2319452 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -55,9 +55,9 @@
 *: Skip
 
 [ $arch == simarm || $arch == arm ]
-# Bug in optimized code generation.
-dart/byte_array_test: Fail
-dart/byte_array_optimized_test: Fail
+# Bug in optimized code generation results in timeout.
+dart/byte_array_test: Skip
+dart/byte_array_optimized_test: Skip
 
 [ $arch == arm ]
 cc/DoubleToFloatConversion: Fail # Issue: 11207
@@ -74,6 +74,10 @@
 # Tests missing code generation support.
 dart/byte_array_test: Skip
 dart/byte_array_optimized_test: Skip
+dart/isolate_mirror_local_test: Skip
+cc/ParsePatchLibrary: Skip
+cc/CorelibCompileAll: Skip
+cc/Dart2JSCompileAll: Skip
 
 # TODO(ajohnsen): Fix this as part of library changes.
 [ $compiler == none ]
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 5cddcab..7230266 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -66,10 +66,7 @@
 class CPUFeatures : public AllStatic {
  public:
   static void InitOnce();
-  static bool double_truncate_round_supported() {
-    UNIMPLEMENTED();
-    return false;
-  }
+  static bool double_truncate_round_supported() { return false; }
   static bool integer_division_supported();
 #if defined(USING_SIMULATOR)
   static void set_integer_division_supported(bool supported);
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index a2f37fb..a0f5306 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -406,6 +406,13 @@
       flow_graph->RemoveRedefinitions();
 
       if (FLAG_range_analysis) {
+        if (FLAG_propagate_types) {
+          // Propagate types after store-load-forwarding. Some phis may have
+          // become smi phis that can be processed by range analysis.
+          FlowGraphTypePropagator propagator(flow_graph);
+          propagator.Propagate();
+          DEBUG_ASSERT(flow_graph->VerifyUseLists());
+        }
         // We have to perform range analysis after LICM because it
         // optimistically moves CheckSmi through phis into loop preheaders
         // making some phis smi.
@@ -420,7 +427,6 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
       }
 
-      // The final canonicalization pass before the code generation.
       if (FLAG_propagate_types) {
         // Recompute types after code movement was done to ensure correct
         // reaching types for hoisted values.
@@ -447,7 +453,7 @@
 
       // Ensure that all phis inserted by optimization passes have consistent
       // representations.
-      optimizer.UnboxPhis();
+      optimizer.SelectRepresentations();
 
       if (optimizer.Canonicalize()) {
         // To fully remove redundant boxing (e.g. BoxDouble used only in
@@ -509,9 +515,6 @@
                     Code::Handle(function.unoptimized_code()).EntryPoint());
         }
 
-        // If not yet present, allocate deoptimization history array.
-        function.EnsureDeoptHistory();
-
         for (intptr_t i = 0; i < guarded_fields.length(); i++) {
           const Field& field = *guarded_fields[i];
           field.RegisterDependentCode(code);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index bf35ec2..323e4f0 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -34,6 +34,7 @@
 namespace dart {
 
 DECLARE_FLAG(bool, print_class_table);
+DECLARE_FLAG(bool, verify_handles);
 
 ThreadLocalKey Api::api_native_key_ = Thread::kUnsetThreadLocalKey;
 Dart_Handle Api::true_handle_ = NULL;
@@ -97,7 +98,8 @@
   ASSERT(isolate != NULL);
   ApiState* state = isolate->api_state();
   ASSERT(state != NULL);
-  ASSERT(state->IsValidLocalHandle(object) ||
+  ASSERT(!FLAG_verify_handles ||
+         state->IsValidLocalHandle(object) ||
          Dart::vm_isolate()->api_state()->IsValidLocalHandle(object));
   ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
          PersistentHandle::raw_offset() == 0 &&
@@ -4348,6 +4350,28 @@
 }
 
 
+// --- Metadata ----
+
+DART_EXPORT Dart_Handle Dart_GetMetadata(Dart_Handle object) {
+  Isolate* isolate = Isolate::Current();
+  CHECK_ISOLATE(isolate);
+  DARTSCOPE(isolate);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  Class& cls = Class::Handle(isolate);
+  if (obj.IsClass()) {
+    cls ^= obj.raw();
+  } else if (obj.IsFunction()) {
+    cls = Function::Cast(obj).origin();
+  } else if (obj.IsField()) {
+    cls = Field::Cast(obj).origin();
+  } else {
+    return Api::NewHandle(isolate, Object::empty_array().raw());
+  }
+  const Library& lib = Library::Handle(cls.library());
+  return Api::NewHandle(isolate, lib.GetMetadata(obj));
+}
+
+
 // --- Scripts and Libraries ---
 
 
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 89ebb10..3d77b54 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -240,7 +240,8 @@
 
   // Share the immutable descriptor when possible by canonicalizing it.
   descriptor.MakeImmutable();
-  descriptor ^= descriptor.Canonicalize();
+  descriptor ^= descriptor.CheckAndCanonicalize(NULL);
+  ASSERT(!descriptor.IsNull());
   return descriptor.raw();
 }
 
@@ -275,8 +276,9 @@
   // Share the immutable descriptor when possible by canonicalizing it.
   descriptor.MakeImmutable();
   if (canonicalize) {
-    descriptor ^= descriptor.Canonicalize();
+    descriptor ^= descriptor.CheckAndCanonicalize(NULL);
   }
+  ASSERT(!descriptor.IsNull());
   return descriptor.raw();
 }
 
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index e583545..8b82f4c 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1731,7 +1731,7 @@
     return bpt->saved_bytes_.target_address_;
   }
   UNREACHABLE();
-  return NULL;
+  return 0L;
 }
 
 
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 8b37613..d194c3c 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -285,18 +285,6 @@
         ic_data.set_deopt_reason(deopt_context->deopt_reason());
       }
     }
-
-    const Array& deopt_history = Array::Handle(function.deopt_history());
-    ASSERT(!deopt_history.IsNull());
-    intptr_t count = function.deoptimization_counter();
-    ASSERT(count > 0);
-    if (count <= deopt_history.Length()) {
-      deopt_history.SetAt(count - 1, Smi::Handle(Smi::New(deopt_id_)));
-      if (FLAG_trace_deoptimization_verbose) {
-        OS::Print("  adding id %"Pd" to history at %"Pd"\n",
-                  deopt_id_, count - 1);
-      }
-    }
   }
 
   intptr_t object_table_index() const { return object_table_index_; }
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index d56842f..dafa68c 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -255,8 +255,7 @@
 
 intptr_t FlowGraphCompiler::StackSize() const {
   if (is_optimizing_) {
-    GraphEntryInstr* entry = flow_graph_.graph_entry();
-    return entry->fixed_slot_count() + entry->spill_slot_count();
+    return flow_graph_.graph_entry()->spill_slot_count();
   } else {
     return parsed_function_.num_stack_locals() +
         parsed_function_.num_copied_params();
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index c2379c3..911e62c 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -612,10 +612,6 @@
       // Add the function to the cache.
       if (!in_cache) function_cache_.Add(parsed_function);
 
-      // Functions can be inlined before they are optimized.
-      // If not yet present, allocate deoptimization history array.
-      function.EnsureDeoptHistory();
-
       // Build succeeded so we restore the bailout jump.
       inlined_ = true;
       inlined_size_ += size;
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 6087381..5094329 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -450,35 +450,6 @@
 }
 
 
-void FlowGraphOptimizer::UnboxPhis() {
-  GrowableArray<PhiInstr*> worklist(5);
-
-  // Convervatively unbox all phis that were proven to be of Double,
-  // Float32x4, or Uint32x4 type.
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
-    JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
-    if (join_entry != NULL) {
-      for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
-        PhiInstr* phi = it.Current();
-        if (UnboxPhi(phi)) {
-          worklist.Add(phi);
-        }
-      }
-    }
-  }
-
-  while (!worklist.is_empty()) {
-    PhiInstr* phi = worklist.RemoveLast();
-    InsertConversionsFor(phi);
-
-    for (intptr_t i = 0; i < phi->InputCount(); i++) {
-      ConvertUse(phi->InputAt(i),
-                 phi->InputAt(i)->definition()->representation());
-    }
-  }
-}
-
-
 void FlowGraphOptimizer::SelectRepresentations() {
   // Convervatively unbox all phis that were proven to be of Double,
   // Float32x4, or Uint32x4 type.
@@ -3461,6 +3432,8 @@
 void LICM::Hoist(ForwardInstructionIterator* it,
                  BlockEntryInstr* pre_header,
                  Instruction* current) {
+  // TODO(fschneider): Avoid repeated deoptimization when
+  // speculatively hoisting checks.
   if (FLAG_trace_optimization) {
     OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n",
               current->DebugName(),
@@ -3516,7 +3489,7 @@
   }
 
   // Host CheckSmi instruction and make this phi smi one.
-  if (MayHoist(current, pre_header)) Hoist(it, pre_header, current);
+  Hoist(it, pre_header, current);
 
   // Replace value we are checking with phi's input.
   current->value()->BindTo(phi->InputAt(non_smi_input)->definition());
@@ -3535,31 +3508,6 @@
 }
 
 
-bool LICM::MayHoist(Instruction* instr, BlockEntryInstr* pre_header) {
-  // TODO(fschneider): Enable hoisting of Assert-instructions
-  // if it safe to do.
-  if (instr->IsAssertAssignable()) return false;
-  if (instr->IsAssertBoolean()) return false;
-
-  if (instr->CanDeoptimize()) {
-    intptr_t target_deopt_id =
-        pre_header->last_instruction()->AsGoto()->GetDeoptId();
-    const Function& function = flow_graph_->parsed_function().function();
-    const Array& deopt_history = Array::Handle(function.deopt_history());
-    if (deopt_history.IsNull()) return true;
-
-    Smi& deopt_id = Smi::Handle();
-    for (intptr_t i = 0; i < deopt_history.Length(); ++i) {
-      deopt_id ^= deopt_history.At(i);
-      if (!deopt_id.IsNull() && (deopt_id.Value() == target_deopt_id)) {
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-
 void LICM::Optimize() {
   const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
       flow_graph()->loop_headers();
@@ -3594,7 +3542,11 @@
               break;
             }
           }
-          if (inputs_loop_invariant && MayHoist(current, pre_header)) {
+          if (inputs_loop_invariant &&
+              !current->IsAssertAssignable() &&
+              !current->IsAssertBoolean()) {
+            // TODO(fschneider): Enable hoisting of Assert-instructions
+            // if it safe to do.
             Hoist(&it, pre_header, current);
           } else if (current->IsCheckSmi() &&
                      current->InputAt(0)->definition()->IsPhi()) {
@@ -4822,6 +4774,7 @@
 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) {
   GrowableArray<BlockEntryInstr*> ignored;
   ConstantPropagator cp(graph, ignored);
+  cp.Analyze();
   cp.VisitBranches();
   cp.Transform();
 }
@@ -5160,6 +5113,15 @@
   const Object& left = instr->left()->definition()->constant_value();
   const Object& right = instr->right()->definition()->constant_value();
 
+  if (instr->left()->definition() == instr->right()->definition()) {
+    // Fold x === x, and x !== x to true/false.
+    SetValue(instr,
+             (instr->kind() == Token::kEQ_STRICT)
+               ? Bool::True()
+               : Bool::False());
+    return;
+  }
+
   if (IsNonConstant(left) || IsNonConstant(right)) {
     // TODO(vegorov): incorporate nullability information into the lattice.
     if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) ||
@@ -5200,6 +5162,19 @@
 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) {
   const Object& left = instr->left()->definition()->constant_value();
   const Object& right = instr->right()->definition()->constant_value();
+
+  if (instr->left()->definition() == instr->right()->definition()) {
+    // Fold x == x, and x != x to true/false for numbers and checked strict
+    // comparisons.
+    if (instr->is_checked_strict_equal() ||
+        RawObject::IsIntegerClassId(instr->receiver_class_id())) {
+      return SetValue(instr,
+                      (instr->kind() == Token::kEQ)
+                        ? Bool::True()
+                        : Bool::False());
+    }
+  }
+
   if (IsNonConstant(left) || IsNonConstant(right)) {
     SetValue(instr, non_constant_);
   } else if (IsConstant(left) && IsConstant(right)) {
@@ -5436,7 +5411,8 @@
         case Token::kMOD: {
           Instance& result = Integer::ZoneHandle(
               left_int.ArithmeticOp(op_kind, right_int));
-          result = result.Canonicalize();
+          result = result.CheckAndCanonicalize(NULL);
+          ASSERT(!result.IsNull());
           SetValue(instr, result);
           break;
         }
@@ -5445,7 +5421,8 @@
           if (left.IsSmi() && right.IsSmi()) {
             Instance& result = Integer::ZoneHandle(
                 Smi::Cast(left_int).ShiftOp(op_kind, Smi::Cast(right_int)));
-            result = result.Canonicalize();
+            result = result.CheckAndCanonicalize(NULL);
+            ASSERT(!result.IsNull());
             SetValue(instr, result);
           } else {
             SetValue(instr, non_constant_);
@@ -5456,7 +5433,8 @@
         case Token::kBIT_XOR: {
           Instance& result = Integer::ZoneHandle(
               left_int.BitOp(op_kind, right_int));
-          result = result.Canonicalize();
+          result = result.CheckAndCanonicalize(NULL);
+          ASSERT(!result.IsNull());
           SetValue(instr, result);
           break;
         }
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 4b8574a..ce18d6b 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -42,8 +42,6 @@
 
   void SelectRepresentations();
 
-  void UnboxPhis();
-
   void InferSmiRanges();
 
   void AnalyzeTryCatch();
@@ -204,8 +202,6 @@
  private:
   FlowGraph* flow_graph() const { return flow_graph_; }
 
-  bool MayHoist(Instruction* instr, BlockEntryInstr* pre_header);
-
   void Hoist(ForwardInstructionIterator* it,
              BlockEntryInstr* pre_header,
              Instruction* current);
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 82a9233..5b6d6b2 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -742,7 +742,6 @@
         value().GetClassId(),
         AbstractType::ZoneHandle(Instance::Cast(value()).GetType()));
   } else {
-    ASSERT(value().IsAbstractTypeArguments());
     return CompileType::Dynamic();
   }
 }
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 72e8c7b..5dcc4b9 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -7,6 +7,7 @@
 #include "platform/assert.h"
 #include "platform/utils.h"
 #include "vm/flags.h"
+#include "vm/heap_histogram.h"
 #include "vm/heap_profiler.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
@@ -162,6 +163,7 @@
       old_space_->MarkSweep(invoke_api_callbacks);
       RecordAfterGC();
       PrintStats();
+      UpdateObjectHistogram();
       break;
     }
     default:
@@ -170,6 +172,13 @@
 }
 
 
+void Heap::UpdateObjectHistogram() {
+  Isolate* isolate = Isolate::Current();
+  if (isolate->object_histogram() == NULL) return;
+  isolate->object_histogram()->Collect();
+}
+
+
 void Heap::CollectGarbage(Space space) {
   ApiCallbacks api_callbacks;
   if (space == kOld) {
@@ -190,6 +199,7 @@
   old_space_->MarkSweep(kInvokeApiCallbacks);
   RecordAfterGC();
   PrintStats();
+  UpdateObjectHistogram();
 }
 
 
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index b85d262..359efea 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -212,7 +212,7 @@
       intptr_t new_capacity_;
       intptr_t old_used_;
       intptr_t old_capacity_;
-
+    private:
       DISALLOW_COPY_AND_ASSIGN(Data);
     };
 
@@ -225,6 +225,7 @@
     int64_t times_[kDataEntries];
     intptr_t data_[kDataEntries];
 
+   private:
     DISALLOW_COPY_AND_ASSIGN(GCStats);
   };
 
@@ -239,6 +240,7 @@
   void RecordBeforeGC(Space space, GCReason reason);
   void RecordAfterGC();
   void PrintStats();
+  void UpdateObjectHistogram();
 
   // The different spaces used for allocation.
   Scavenger* new_space_;
diff --git a/runtime/vm/heap_histogram.cc b/runtime/vm/heap_histogram.cc
new file mode 100644
index 0000000..09fd5cd
--- /dev/null
+++ b/runtime/vm/heap_histogram.cc
@@ -0,0 +1,133 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/heap_histogram.h"
+
+#include "platform/assert.h"
+#include "vm/flags.h"
+#include "vm/object.h"
+
+namespace dart {
+
+DEFINE_FLAG(bool, print_object_histogram, false,
+            "Print average object histogram at isolate shutdown");
+
+class ObjectHistogramVisitor : public ObjectVisitor {
+ public:
+  explicit ObjectHistogramVisitor(Isolate* isolate) : ObjectVisitor(isolate) { }
+
+  virtual void VisitObject(RawObject* obj) {
+    isolate()->object_histogram()->Add(obj);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ObjectHistogramVisitor);
+};
+
+
+void ObjectHistogram::Collect() {
+  major_gc_count_++;
+  ObjectHistogramVisitor object_visitor(isolate_);
+  isolate_->heap()->IterateObjects(&object_visitor);
+}
+
+
+ObjectHistogram::ObjectHistogram(Isolate* isolate) {
+  isolate_ = isolate;
+  major_gc_count_ = 0;
+  table_length_ = 512;
+  table_ = reinterpret_cast<Element*>(
+    calloc(table_length_, sizeof(Element)));  // NOLINT 
+  for (int index = 0; index < table_length_; index++) {
+    table_[index].class_id_ = index;
+  }
+}
+
+
+ObjectHistogram::~ObjectHistogram() {
+  free(table_);
+}
+
+
+void ObjectHistogram::RegisterClass(const Class& cls) {
+  int class_id = cls.id();
+  if (class_id < table_length_) return;
+  // Resize the table.
+  int new_table_length = table_length_ * 2;
+  Element* new_table = reinterpret_cast<Element*>(
+          realloc(table_, new_table_length * sizeof(Element)));  // NOLINT
+  for (int i = table_length_; i < new_table_length; i++) {
+    new_table[i].class_id_ = i;
+    new_table[i].count_ = 0;
+    new_table[i].size_ = 0;
+  }
+  table_ = new_table;
+  table_length_ = new_table_length;
+  ASSERT(class_id < table_length_);
+}
+
+
+void ObjectHistogram::Add(RawObject* obj) {
+  intptr_t class_id = obj->GetClassId();
+  if (class_id == kFreeListElement) return;
+  ASSERT(class_id < table_length_);
+  table_[class_id].Add(obj->Size());
+}
+
+
+int ObjectHistogram::compare(const Element** a, const Element** b) {
+  return (*b)->size_ - (*a)->size_;
+}
+
+
+void ObjectHistogram::Print() {
+  OS::Print("Printing Object Histogram\n");
+  OS::Print("____bytes___count_description____________\n");
+  // First count the number of non empty entries.
+  int length = 0;
+  for (int index = 0; index < table_length_; index++) {
+    if (table_[index].count_ > 0) length++;
+  }
+  // Then add them to a new array and sort.
+  Element** array = reinterpret_cast<Element**>(
+    calloc(length, sizeof(Element*)));  // NOLINT
+  int pos = 0;
+  for (int index = 0; index < table_length_; index++) {
+    if (table_[index].count_ > 0) array[pos++] = &table_[index];
+  }
+  typedef int (*CmpFunc)(const void*, const void*);
+  qsort(array, length, sizeof(Element*),  // NOLINT
+        reinterpret_cast<CmpFunc>(compare));
+
+  // Finally print the sorted array.
+  Class& cls = Class::Handle();
+  String& str = String::Handle();
+  Library& lib = Library::Handle();
+  for (pos = 0; pos < length; pos++) {
+    Element* e = array[pos];
+    if (e->count_ > 0) {
+      cls = isolate_->class_table()->At(e->class_id_);
+      str = cls.Name();
+      lib = cls.library();
+      OS::Print("%9"Pd" %7"Pd" ",
+                e->size_ / major_gc_count_,
+                e->count_ / major_gc_count_);
+      if (e->class_id_ < kInstanceCid) {
+        OS::Print("`%s`", str.ToCString());  // VM names.
+      } else {
+        OS::Print("%s", str.ToCString());
+      }
+      if (lib.IsNull()) {
+        OS::Print("\n");
+      } else {
+        str = lib.url();
+        OS::Print(", library \'%s\'\n", str.ToCString());
+      }
+    }
+  }
+  // Deallocate the array for sorting.
+  free(array);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/heap_histogram.h b/runtime/vm/heap_histogram.h
new file mode 100644
index 0000000..13e0a38
--- /dev/null
+++ b/runtime/vm/heap_histogram.h
@@ -0,0 +1,68 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef VM_HEAP_HISTOGRAM_H_
+#define VM_HEAP_HISTOGRAM_H_
+
+#include "platform/assert.h"
+#include "vm/flags.h"
+#include "vm/globals.h"
+#include "vm/raw_object.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, print_object_histogram);
+
+// ObjectHistogram is used to compute an average object histogram over
+// the lifetime of an isolate and then print the histogram when the isolate
+// is shut down. Information is gathered at the back-edge of each major GC
+// event. When an object histogram is collected for an isolate, an extra major
+// GC is performed just prior to shutdown.
+class ObjectHistogram {
+ public:
+  explicit ObjectHistogram(Isolate* isolate);
+  ~ObjectHistogram();
+
+  // Called when a new class is registered in the isolate.
+  void RegisterClass(const Class& cls);
+
+  // Collect sample for the histogram. Called at back-edge of major GC.
+  void Collect();
+
+  // Print the histogram on stdout.
+  void Print();
+
+ private:
+  // Add obj to histogram
+  void Add(RawObject* obj);
+
+  // For each class an Element keeps track of the accounting.
+  class Element : public ValueObject {
+   public:
+    void Add(int size) {
+      count_++;
+      size_ += size;
+    }
+    intptr_t class_id_;
+    intptr_t count_;
+    intptr_t size_;
+  };
+
+  // Compare function for sorting result.
+  static int compare(const Element** a, const Element** b);
+
+  intptr_t major_gc_count_;
+  intptr_t table_length_;
+  Element* table_;
+  Isolate* isolate_;
+
+  friend class ObjectHistogramVisitor;
+
+  DISALLOW_COPY_AND_ASSIGN(ObjectHistogram);
+};
+
+}  // namespace dart
+
+#endif  // VM_HEAP_HISTOGRAM_H_
+
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index 43f978b..03f94e9 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -93,9 +93,9 @@
     offset = instr & 0xfff;
     instr = Back(++end);
     if ((instr & 0xffff0000) == 0xe28a0000) {  // add reg, pp, shifter_op
-      const int rot = (instr & 0xf00) * 2;
+      const int rot = (instr & 0xf00) >> 7;
       const int imm8 = instr & 0xff;
-      offset |= (imm8 >> rot) | (imm8 << (32 - rot));
+      offset += (imm8 >> rot) | (imm8 << (32 - rot));
       *reg = static_cast<Register>((instr & 0xf000) >> 12);
     } else {
       ASSERT((instr & 0xffff0000) == 0xe08a0000);  // add reg, pp, reg
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 55746ec..01edb86 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -310,8 +310,6 @@
 
 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
   if (receiver_class_id() == kMintCid) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
@@ -344,7 +342,7 @@
     locs->set_out(Location::RequiresRegister());
     return locs;
   }
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@@ -783,9 +781,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
   }
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
                            deopt_id());
     return;
@@ -826,9 +822,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
     return;
   }
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
                            deopt_id());
     return;
@@ -2097,7 +2091,7 @@
     const intptr_t kCountLimit = 0x1F;
     const intptr_t value = Smi::Cast(constant).Value();
     if (value == 0) {
-      // No code needed.
+      __ MoveRegister(result, left);
     } else if ((value < 0) || (value >= kCountLimit)) {
       // This condition may not be known earlier in some cases because
       // of constant propagation, inlining, etc.
@@ -2278,7 +2272,7 @@
       case Token::kTRUNCDIV: {
         const intptr_t value = Smi::Cast(constant).Value();
         if (value == 1) {
-          // Do nothing.
+          __ MoveRegister(result, left);
           break;
         } else if (value == -1) {
           // Check the corner case of dividing the 'MIN_SMI' with -1, in which
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 500ca71..3f043e3 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -269,8 +269,6 @@
 
 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
   if (receiver_class_id() == kMintCid) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
@@ -304,7 +302,7 @@
     locs->set_out(Location::RequiresRegister());
     return locs;
   }
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@@ -843,9 +841,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
   }
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
                            deopt_id());
     return;
@@ -885,9 +881,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
     return;
   }
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
                            deopt_id());
     return;
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 5c4a45c..0245899 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -304,8 +304,6 @@
 
 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
   if (receiver_class_id() == kMintCid) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
@@ -338,7 +336,7 @@
     locs->set_out(Location::RequiresRegister());
     return locs;
   }
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@@ -757,9 +755,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
   }
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
                            deopt_id());
     return;
@@ -803,9 +799,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
     return;
   }
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
                            deopt_id());
     return;
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index f84bb4c..c93b79a3 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -435,8 +435,6 @@
 
 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
   if (receiver_class_id() == kDoubleCid) {
     const intptr_t kNumTemps =  0;
     LocationSummary* locs =
@@ -460,7 +458,7 @@
     locs->set_out(Location::RequiresRegister());
     return locs;
   }
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@@ -888,9 +886,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
   }
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
                            deopt_id());
     return;
@@ -927,9 +923,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
     return;
   }
-  const bool is_checked_strict_equal =
-      HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  if (is_checked_strict_equal) {
+  if (is_checked_strict_equal()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
                            deopt_id());
     return;
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 6c41997..87a6d81 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -14,6 +14,7 @@
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
 #include "vm/heap.h"
+#include "vm/heap_histogram.h"
 #include "vm/message_handler.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
@@ -34,6 +35,13 @@
             "Trace isolate creation and shut down.");
 DECLARE_FLAG(bool, trace_deoptimization_verbose);
 
+
+void Isolate::RegisterClass(const Class& cls) {
+  class_table()->Register(cls);
+  if (object_histogram() != NULL) object_histogram()->RegisterClass(cls);
+}
+
+
 class IsolateMessageHandler : public MessageHandler {
  public:
   explicit IsolateMessageHandler(Isolate* isolate);
@@ -400,7 +408,11 @@
       deferred_objects_count_(0),
       deferred_objects_(NULL),
       stacktrace_(NULL),
-      stack_frame_index_(-1) {
+      stack_frame_index_(-1),
+      object_histogram_(NULL) {
+  if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) {
+    object_histogram_ = new ObjectHistogram(this);
+  }
 }
 
 
@@ -418,6 +430,7 @@
   mutex_ = NULL;  // Fail fast if interrupts are scheduled on a dead isolate.
   delete message_handler_;
   message_handler_ = NULL;  // Fail fast if we send messages to a dead isolate.
+  delete object_histogram_;
 }
 
 void Isolate::SetCurrent(Isolate* current) {
@@ -729,6 +742,13 @@
   ASSERT(top_resource() == NULL);
   ASSERT((heap_ == NULL) || heap_->Verify());
 
+  if (FLAG_print_object_histogram) {
+    StackZone stack_zone(this);
+    HandleScope handle_scope(this);
+    heap()->CollectAllGarbage();
+    object_histogram()->Print();
+  }
+
   // Clean up debugger resources. Shutting down the debugger
   // requires a handle zone. We must set up a temporary zone because
   // Isolate::Shutdown is called without a zone.
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index e0059cf..a2e37c5 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -46,6 +46,7 @@
 class StubCode;
 class RawFloat32x4;
 class RawUint32x4;
+class ObjectHistogram;
 
 
 // Used by the deoptimization infrastructure to defer allocation of unboxed
@@ -231,6 +232,9 @@
   static Isolate* Init(const char* name_prefix);
   void Shutdown();
 
+  // Register a newly introduced class.
+  void RegisterClass(const Class& cls);
+
   // Visit all object pointers.
   void VisitObjectPointers(ObjectPointerVisitor* visitor,
                            bool visit_prologue_weak_persistent_handles,
@@ -250,6 +254,8 @@
     return OFFSET_OF(Isolate, class_table_);
   }
 
+  ObjectHistogram* object_histogram() { return object_histogram_; }
+
   MegamorphicCacheTable* megamorphic_cache_table() {
     return &megamorphic_cache_table_;
   }
@@ -635,6 +641,7 @@
   // Status support.
   char* stacktrace_;
   intptr_t stack_frame_index_;
+  ObjectHistogram* object_histogram_;
 
   static Dart_IsolateCreateCallback create_callback_;
   static Dart_IsolateInterruptCallback interrupt_callback_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index c29dd4f..e1185d5 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -55,7 +55,6 @@
 DECLARE_FLAG(bool, trace_compiler);
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, enable_type_checks);
-DECLARE_FLAG(int, deoptimization_counter_threshold);
 
 static const char* kGetterPrefix = "get:";
 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
@@ -390,7 +389,7 @@
         Class::kNoTypeArguments;
     cls.raw_ptr()->num_native_fields_ = 0;
     cls.InitEmptyFields();
-    isolate->class_table()->Register(cls);
+    isolate->RegisterClass(cls);
   }
 
   // Allocate and initialize the null class.
@@ -892,6 +891,14 @@
   RegisterPrivateClass(cls, Symbols::TypeParameter(), core_lib);
   pending_classes.Add(cls, Heap::kOld);
 
+  cls = object_store->bounded_type_class();
+  RegisterPrivateClass(cls, Symbols::BoundedType(), core_lib);
+  pending_classes.Add(cls, Heap::kOld);
+
+  cls = object_store->mixin_app_type_class();
+  RegisterPrivateClass(cls, Symbols::MixinAppType(), core_lib);
+  pending_classes.Add(cls, Heap::kOld);
+
   cls = Class::New<Integer>();
   object_store->set_integer_implementation_class(cls);
   RegisterPrivateClass(cls, Symbols::IntegerImplementation(), core_lib);
@@ -1468,7 +1475,7 @@
   result.raw_ptr()->num_native_fields_ = 0;
   result.raw_ptr()->token_pos_ = Scanner::kDummyTokenIndex;
   result.InitEmptyFields();
-  Isolate::Current()->class_table()->Register(result);
+  Isolate::Current()->RegisterClass(result);
   return result.raw();
 }
 
@@ -1619,7 +1626,7 @@
       }
     }
     num_type_args += cls.NumTypeParameters();
-    // Object is its own super class during bootstrap.
+    // Super type of Object class is null.
     if (cls.super_type() == AbstractType::null() ||
         cls.super_type() == isolate->object_store()->object_type()) {
       break;
@@ -1879,7 +1886,7 @@
   result.raw_ptr()->num_native_fields_ = 0;
   result.raw_ptr()->token_pos_ = Scanner::kDummyTokenIndex;
   result.InitEmptyFields();
-  Isolate::Current()->class_table()->Register(result);
+  Isolate::Current()->RegisterClass(result);
   return result.raw();
 }
 
@@ -3446,20 +3453,6 @@
 }
 
 
-void Function::set_deopt_history(const Array& value) const {
-  StorePointer(&raw_ptr()->deopt_history_, value.raw());
-}
-
-
-void Function::EnsureDeoptHistory() const {
-  Array& array = Array::Handle(deopt_history());
-  if (array.IsNull()) {
-    array = Array::New(FLAG_deoptimization_counter_threshold);
-    set_deopt_history(array);
-  }
-}
-
-
 RawContextScope* Function::context_scope() const {
   if (IsClosureFunction()) {
     const Object& obj = Object::Handle(raw_ptr()->data_);
@@ -5992,6 +5985,123 @@
 }
 
 
+static RawString* MakeClassMetaName(const Class& cls) {
+  String& cname = String::Handle(cls.Name());
+  return String::Concat(Symbols::At(), cname);
+}
+
+
+static RawString* MakeFieldMetaName(const Field& field) {
+  const String& cname =
+      String::Handle(MakeClassMetaName(Class::Handle(field.origin())));
+  String& fname = String::Handle(field.name());
+  fname = String::Concat(Symbols::At(), fname);
+  return String::Concat(cname, fname);
+}
+
+
+static RawString* MakeFunctionMetaName(const Function& func) {
+  const String& cname =
+      String::Handle(MakeClassMetaName(Class::Handle(func.origin())));
+  String& fname = String::Handle(func.name());
+  fname = String::Concat(Symbols::At(), fname);
+  return String::Concat(cname, fname);
+}
+
+
+void Library::AddMetadata(const Class& cls,
+                          const String& name,
+                          intptr_t token_pos) const {
+  const String& metaname = String::Handle(Symbols::New(name));
+  Field& field = Field::Handle(Field::New(metaname,
+                                          true,   // is_static
+                                          false,  // is_final
+                                          false,  // is_const
+                                          cls,
+                                          token_pos));
+  field.set_type(Type::Handle(Type::DynamicType()));
+  field.set_value(Array::empty_array());
+  GrowableObjectArray& metadata =
+      GrowableObjectArray::Handle(this->metadata());
+  metadata.Add(field, Heap::kOld);
+}
+
+
+void Library::AddClassMetadata(const Class& cls, intptr_t token_pos) const {
+  AddMetadata(cls, String::Handle(MakeClassMetaName(cls)), token_pos);
+}
+
+
+void Library::AddFieldMetadata(const Field& field,
+                               intptr_t token_pos) const {
+  AddMetadata(Class::Handle(field.origin()),
+              String::Handle(MakeFieldMetaName(field)),
+              token_pos);
+}
+
+
+void Library::AddFunctionMetadata(const Function& func,
+                                  intptr_t token_pos) const {
+  AddMetadata(Class::Handle(func.origin()),
+              String::Handle(MakeFunctionMetaName(func)),
+              token_pos);
+}
+
+
+RawString* Library::MakeMetadataName(const Object& obj) const {
+  if (obj.IsClass()) {
+    return MakeClassMetaName(Class::Cast(obj));
+  } else if (obj.IsField()) {
+    return MakeFieldMetaName(Field::Cast(obj));
+  } else if (obj.IsFunction()) {
+    return MakeFunctionMetaName(Function::Cast(obj));
+  }
+  UNIMPLEMENTED();
+  return String::null();
+}
+
+
+RawField* Library::GetMetadataField(const String& metaname) const {
+  const GrowableObjectArray& metadata =
+      GrowableObjectArray::Handle(this->metadata());
+  Field& entry = Field::Handle();
+  String& entryname = String::Handle();
+  intptr_t num_entries = metadata.Length();
+  for (intptr_t i = 0; i < num_entries; i++) {
+    entry ^= metadata.At(i);
+    entryname = entry.name();
+    if (entryname.Equals(metaname)) {
+      return entry.raw();
+    }
+  }
+  return Field::null();
+}
+
+
+RawObject* Library::GetMetadata(const Object& obj) const {
+  if (!obj.IsClass() && !obj.IsField() && !obj.IsFunction()) {
+    return Object::null();
+  }
+  const String& metaname = String::Handle(MakeMetadataName(obj));
+  Field& field = Field::Handle(GetMetadataField(metaname));
+  if (field.IsNull()) {
+    // There is no metadata for this object.
+    return Object::empty_array().raw();;
+  }
+  Object& metadata = Object::Handle();
+  metadata = field.value();
+  if (field.value() == Object::empty_array().raw()) {
+    metadata = Parser::ParseMetadata(Class::Handle(field.owner()),
+                                     field.token_pos());
+    if (metadata.IsArray()) {
+      ASSERT(Array::Cast(metadata).raw() != Object::empty_array().raw());
+      field.set_value(Array::Cast(metadata));
+    }
+  }
+  return metadata.raw();
+}
+
+
 void Library::GrowDictionary(const Array& dict, intptr_t dict_size) const {
   // TODO(iposva): Avoid exponential growth.
   intptr_t new_dict_size = dict_size * 2;
@@ -6530,6 +6640,8 @@
   result.StorePointer(&result.raw_ptr()->url_, url.raw());
   result.raw_ptr()->private_key_ = Scanner::AllocatePrivateKey(result);
   result.raw_ptr()->dictionary_ = Object::empty_array().raw();
+  result.StorePointer(&result.raw_ptr()->metadata_,
+                      GrowableObjectArray::New(4, Heap::kOld));
   result.raw_ptr()->anonymous_classes_ = Object::empty_array().raw();
   result.raw_ptr()->num_anonymous_ = 0;
   result.raw_ptr()->imports_ = Object::empty_array().raw();
@@ -9090,13 +9202,43 @@
 }
 
 
-RawInstance* Instance::Canonicalize() const {
+RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
   ASSERT(!IsNull());
   if (this->IsCanonical()) {
     return this->raw();
   }
   Instance& result = Instance::Handle();
   const Class& cls = Class::Handle(this->clazz());
+  // TODO(srdjan): Check that predefined classes do not have fields that need
+  // to be checked/canonicalized as well.
+  if ((cls.id() >= kNumPredefinedCids) || cls.IsArray()) {
+    // Iterate over all fields, canonicalize numbers and strings, expect all
+    // other instances to be canonical otherwise report error (return
+    // Instance::null()).
+    Object& obj = Object::Handle();
+    const intptr_t end_field_offset = cls.instance_size() - kWordSize;
+    for (intptr_t field_offset = 0;
+         field_offset <= end_field_offset;
+         field_offset += kWordSize) {
+      obj = *this->FieldAddrAtOffset(field_offset);
+      if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
+        if (obj.IsNumber() || obj.IsString()) {
+          obj = Instance::Cast(obj).CheckAndCanonicalize(NULL);
+          ASSERT(!obj.IsNull());
+          this->SetFieldAtOffset(field_offset, obj);
+        } else {
+          ASSERT(error_str != NULL);
+          const char* kFormat = "field: %s\n";
+          const intptr_t len =
+              OS::SNPrint(NULL, 0, kFormat, obj.ToCString()) + 1;
+          char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+          OS::SNPrint(chars, len, kFormat, obj.ToCString());
+          *error_str = chars;
+          return Instance::null();
+        }
+      }
+    }
+  }
   Array& constants = Array::Handle(cls.constants());
   const intptr_t constants_len = constants.Length();
   // Linear search to see whether this value is already present in the
@@ -11444,7 +11586,7 @@
 }
 
 
-RawInstance* String::Canonicalize() const {
+RawInstance* String::CheckAndCanonicalize(const char** error_str) const {
   if (IsCanonical()) {
     return this->raw();
   }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 35786cb..492b595 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1368,11 +1368,6 @@
   static intptr_t code_offset() { return OFFSET_OF(RawFunction, code_); }
   inline bool HasCode() const;
 
-  RawArray* deopt_history() const { return raw_ptr()->deopt_history_; }
-  void set_deopt_history(const Array& value) const;
-  // If not yet present, allocate deoptimization history array.
-  void EnsureDeoptHistory() const;
-
   // Returns true if there is at least one debugger breakpoint
   // set in this function.
   bool HasBreakpoint() const;
@@ -2251,6 +2246,11 @@
 
   void AddExport(const Namespace& ns) const;
 
+  void AddClassMetadata(const Class& cls, intptr_t token_pos) const;
+  void AddFieldMetadata(const Field& field, intptr_t token_pos) const;
+  void AddFunctionMetadata(const Function& func, intptr_t token_pos) const;
+  RawObject* GetMetadata(const Object& obj) const;
+
   // Library imports.
   void AddImport(const Namespace& ns) const;
   intptr_t num_imports() const { return raw_ptr()->num_imports_; }
@@ -2333,6 +2333,7 @@
   RawArray* exports() const { return raw_ptr()->exports_; }
   bool HasExports() const;
   RawArray* loaded_scripts() const { return raw_ptr()->loaded_scripts_; }
+  RawGrowableObjectArray* metadata() const { return raw_ptr()->metadata_; }
   RawArray* dictionary() const { return raw_ptr()->dictionary_; }
   void InitClassDictionary() const;
   void InitImportList() const;
@@ -2341,6 +2342,12 @@
                                       bool import_core_lib);
   RawObject* LookupEntry(const String& name, intptr_t *index) const;
 
+  RawString* MakeMetadataName(const Object& obj) const;
+  RawField* GetMetadataField(const String& metaname) const;
+  void AddMetadata(const Class& cls,
+                   const String& name,
+                   intptr_t token_pos) const;
+
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Library, Object);
 
   friend class Bootstrap;
@@ -3517,7 +3524,12 @@
 class Instance : public Object {
  public:
   virtual bool Equals(const Instance& other) const;
-  virtual RawInstance* Canonicalize() const;
+  // Returns Instance::null() if instance cannot be canonicalized.
+  // Any non-canonical number of string will be canonicalized here.
+  // An instance cannot be canonicalized if it still contains non-canonical
+  // instances in its fields.
+  // Returns error in error_str, pass NULL if an error cannot occur.
+  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const;
 
   RawObject* GetField(const Field& field) const {
     return *FieldAddr(field);
@@ -3608,6 +3620,10 @@
       const AbstractTypeArguments& instantiator_type_arguments,
       Error* malformed_error) const;
 
+  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const {
+    return Canonicalize();
+  }
+
   // Return the canonical version of this type.
   virtual RawAbstractType* Canonicalize() const;
 
@@ -4061,7 +4077,7 @@
   virtual bool IsZero() const { return Value() == 0; }
   virtual bool IsNegative() const { return Value() < 0; }
   // Smi values are implicitly canonicalized.
-  virtual RawInstance* Canonicalize() const {
+  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const {
     return reinterpret_cast<RawSmi*>(raw_value());
   }
 
@@ -4391,7 +4407,7 @@
 
   bool StartsWith(const String& other) const;
 
-  virtual RawInstance* Canonicalize() const;
+  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const;
 
   bool IsSymbol() const { return raw()->IsCanonical(); }
 
@@ -5101,6 +5117,11 @@
 
   virtual bool Equals(const Instance& other) const;
 
+  virtual RawInstance* CheckAndCanonicalize(const char** error_str) const {
+    UNREACHABLE();
+    return Instance::null();
+  }
+
   static intptr_t type_arguments_offset() {
     return OFFSET_OF(RawGrowableObjectArray, type_arguments_);
   }
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 4a6ce55..0115294 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -6,6 +6,7 @@
 #include "vm/assembler.h"
 #include "vm/bigint_operations.h"
 #include "vm/class_finalizer.h"
+#include "vm/dart_api_impl.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
@@ -2770,14 +2771,14 @@
       "MyException\n"
       "#0      baz (dart:test-lib:2:3)\n"
       "#1      _OtherClass._OtherClass._named (dart:test-lib:7:8)\n"
-      "#2      globalVar= (dart:test-lib:12:3)\n"
+      "#2      globalVar= (dart:test-lib:12:7)\n"
       "#3      _bar (dart:test-lib:16:3)\n"
       "#4      MyClass.field (dart:test-lib:25:9)\n"
       "#5      MyClass.foo.fooHelper (dart:test-lib:30:7)\n"
       "#6      MyClass.foo (dart:test-lib:32:14)\n"
       "#7      MyClass.MyClass.<anonymous closure> (dart:test-lib:21:15)\n"
       "#8      MyClass.MyClass (dart:test-lib:21:18)\n"
-      "#9      main.<anonymous closure> (dart:test-lib:37:10)\n"
+      "#9      main.<anonymous closure> (dart:test-lib:37:14)\n"
       "#10     main (dart:test-lib:37:24)");
 }
 
@@ -3171,6 +3172,112 @@
 }
 
 
+static RawField* GetField(const Class& cls, const char* name) {
+  const Field& field =
+      Field::Handle(cls.LookupField(String::Handle(String::New(name))));
+  ASSERT(!field.IsNull());
+  return field.raw();
+}
+
+
+static RawClass* GetClass(const Library& lib, const char* name) {
+  const Class& cls =
+      Class::Handle(lib.LookupClass(String::Handle(Symbols::New(name))));
+  ASSERT(!cls.IsNull());
+  return cls.raw();
+}
+
+
+static void PrintMetadata(const char* name, const Object& data) {
+  if (data.IsError()) {
+    OS::Print("Error in metadata evaluation for %s: '%s'\n",
+              name,
+              Error::Cast(data).ToErrorCString());
+  }
+  ASSERT(data.IsArray());
+  const Array& metadata = Array::Cast(data);
+  OS::Print("Metadata for %s has %"Pd" values:\n", name, metadata.Length());
+  Object& elem = Object::Handle();
+  for (int i = 0; i < metadata.Length(); i++) {
+    elem = metadata.At(i);
+    OS::Print("  %d: %s\n", i, elem.ToCString());
+  }
+}
+
+
+TEST_CASE(Metadata) {
+  const char* kScriptChars =
+      "@metafoo                       \n"
+      "class Meta {                   \n"
+      "  final m;                     \n"
+      "  const Meta(this.m);          \n"
+      "}                              \n"
+      "                               \n"
+      "const metafoo = 'metafoo';     \n"
+      "const metabar = 'meta' 'bar';  \n"
+      "                               \n"
+      "@metafoo                       \n"
+      "@Meta(0) String gVar;          \n"
+      "                               \n"
+      "@metafoo                       \n"
+      "get tlGetter => gVar;          \n"
+      "                               \n"
+      "@metabar                       \n"
+      "class A {                      \n"
+      "  @metafoo                     \n"
+      "  @metabar                     \n"
+      "  @Meta('baz')                 \n"
+      "  var aField;                  \n"
+      "                               \n"
+      "  @metabar @Meta('baa')        \n"
+      "  int aFunc(a,b) => a + b;     \n"
+      "}                              \n"
+      "                               \n"
+      "@Meta('main')                  \n"
+      "A main() {                     \n"
+      "  return new A();              \n"
+      "}                              \n";
+
+  Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  EXPECT_VALID(h_lib);
+  Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+  Library& lib = Library::Handle();
+  lib ^= Api::UnwrapHandle(h_lib);
+  ASSERT(!lib.IsNull());
+  const Class& class_a = Class::Handle(GetClass(lib, "A"));
+  Object& res = Object::Handle(lib.GetMetadata(class_a));
+  PrintMetadata("A", res);
+
+  const Class& class_meta = Class::Handle(GetClass(lib, "Meta"));
+  res = lib.GetMetadata(class_meta);
+  PrintMetadata("Meta", res);
+
+  Field& field = Field::Handle(GetField(class_a, "aField"));
+  res = lib.GetMetadata(field);
+  PrintMetadata("A.aField", res);
+
+  Function& func = Function::Handle(GetFunction(class_a, "aFunc"));
+  res = lib.GetMetadata(func);
+  PrintMetadata("A.aFunc", res);
+
+  func = lib.LookupLocalFunction(String::Handle(Symbols::New("main")));
+  ASSERT(!func.IsNull());
+  res = lib.GetMetadata(func);
+  PrintMetadata("main", res);
+
+  func = lib.LookupLocalFunction(String::Handle(Symbols::New("get:tlGetter")));
+  ASSERT(!func.IsNull());
+  res = lib.GetMetadata(func);
+  PrintMetadata("tlGetter", res);
+
+  field = lib.LookupLocalField(String::Handle(Symbols::New("gVar")));
+  ASSERT(!field.IsNull());
+  res = lib.GetMetadata(field);
+  PrintMetadata("gVar", res);
+}
+
+
 TEST_CASE(FunctionSourceFingerprint) {
   const char* kScriptChars =
       "class A {\n"
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index eb3ea07..e2ade07 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -511,6 +511,7 @@
     has_var = false;
     has_factory = false;
     has_operator = false;
+    metadata_pos = -1;
     operator_token = Token::kILLEGAL;
     type = NULL;
     name_pos = 0;
@@ -543,6 +544,7 @@
   bool has_var;
   bool has_factory;
   bool has_operator;
+  intptr_t metadata_pos;
   Token::Kind operator_token;
   const AbstractType* type;
   intptr_t name_pos;
@@ -647,8 +649,8 @@
     return fields_;
   }
 
-  RawClass* clazz() const {
-    return clazz_.raw();
+  const Class& clazz() const {
+    return clazz_;
   }
 
   const String& class_name() const {
@@ -841,6 +843,63 @@
 }
 
 
+RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) {
+  Isolate* isolate = Isolate::Current();
+  StackZone zone(isolate);
+  LongJump* base = isolate->long_jump_base();
+  LongJump jump;
+  isolate->set_long_jump_base(&jump);
+  if (setjmp(*jump.Set()) == 0) {
+    const Script& script = Script::Handle(cls.script());
+    const Library& lib = Library::Handle(cls.library());
+    Parser parser(script, lib, token_pos);
+    parser.set_current_class(cls);
+    return parser.EvaluateMetadata();
+  } else {
+    Error& error = Error::Handle();
+    error = isolate->object_store()->sticky_error();
+    isolate->object_store()->clear_sticky_error();
+    isolate->set_long_jump_base(base);
+    return error.raw();
+  }
+  UNREACHABLE();
+  return Object::null();
+}
+
+
+RawArray* Parser::EvaluateMetadata() {
+  if (CurrentToken() != Token::kAT) {
+    ErrorMsg("Metadata character '@' expected");
+  }
+  GrowableObjectArray& meta_values =
+      GrowableObjectArray::Handle(GrowableObjectArray::New());
+  while (CurrentToken() == Token::kAT) {
+    ConsumeToken();
+    intptr_t expr_pos = TokenPos();
+    if (!IsIdentifier()) {
+      ExpectIdentifier("identifier expected");
+    }
+    AstNode* expr = NULL;
+    if ((LookaheadToken(1) == Token::kLPAREN) ||
+        ((LookaheadToken(1) == Token::kPERIOD) &&
+            (LookaheadToken(3) == Token::kLPAREN)) ||
+        ((LookaheadToken(1) == Token::kPERIOD) &&
+            (LookaheadToken(3) == Token::kPERIOD) &&
+            (LookaheadToken(5) == Token::kLPAREN))) {
+      expr = ParseNewOperator(Token::kCONST);
+    } else {
+      expr = ParsePrimary();
+    }
+    if (expr->EvalConstExpr() == NULL) {
+      ErrorMsg(expr_pos, "expression must be a compile-time constant");
+    }
+    const Instance& val = EvaluateConstExpr(expr);
+    meta_values.Add(val);
+  }
+  return Array::MakeArray(meta_values);
+}
+
+
 // TODO(regis): Since a const variable is implicitly final,
 // rename ParseStaticConstGetter to ParseStaticFinalGetter and
 // rename kConstImplicitGetter to kImplicitFinalGetter.
@@ -2824,6 +2883,9 @@
                     method_pos));
   func.set_result_type(*method->type);
   func.set_end_token_pos(method_end_pos);
+  if (method->metadata_pos > 0) {
+    library_.AddFunctionMetadata(func, method->metadata_pos);
+  }
 
   // If this method is a redirecting factory, set the redirection information.
   if (!redirection_type.IsNull()) {
@@ -2911,6 +2973,9 @@
     class_field.set_type(*field->type);
     class_field.set_has_initializer(has_initializer);
     members->AddField(class_field);
+    if (field->metadata_pos >= 0) {
+      library_.AddFieldMetadata(class_field, field->metadata_pos);
+    }
 
     // For static const fields, set value to "uninitialized" and
     // create a kConstImplicitGetter getter method.
@@ -3001,10 +3066,12 @@
 }
 
 
-void Parser::ParseClassMemberDefinition(ClassDesc* members) {
+void Parser::ParseClassMemberDefinition(ClassDesc* members,
+                                        intptr_t metadata_pos) {
   TRACE_PARSER("ParseClassMemberDefinition");
   MemberDesc member;
   current_member_ = &member;
+  member.metadata_pos = metadata_pos;
   if ((CurrentToken() == Token::kEXTERNAL) &&
       (LookaheadToken(1) != Token::kLPAREN)) {
     ConsumeToken();
@@ -3217,7 +3284,8 @@
 }
 
 
-void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes) {
+void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes,
+                                   intptr_t metadata_pos) {
   TRACE_PARSER("ParseClassDeclaration");
   bool is_patch = false;
   bool is_abstract = false;
@@ -3359,6 +3427,9 @@
     cls.set_is_patch();
   }
   pending_classes.Add(cls, Heap::kOld);
+  if (metadata_pos >= 0) {
+    library_.AddClassMetadata(cls, metadata_pos);
+  }
 
   if (CurrentToken() != Token::kLBRACE) {
     ErrorMsg("{ expected");
@@ -3379,8 +3450,8 @@
   }
   ExpectToken(Token::kLBRACE);
   while (CurrentToken() != Token::kRBRACE) {
-    SkipMetadata();
-    ParseClassMemberDefinition(&members);
+    intptr_t metadata_pos = SkipMetadata();
+    ParseClassMemberDefinition(&members, metadata_pos);
   }
   ExpectToken(Token::kRBRACE);
 
@@ -3719,7 +3790,11 @@
 }
 
 
-void Parser::SkipMetadata() {
+intptr_t Parser::SkipMetadata() {
+  if (CurrentToken() != Token::kAT) {
+    return -1;
+  }
+  intptr_t metadata_pos = TokenPos();
   while (CurrentToken() == Token::kAT) {
     ConsumeToken();
     ExpectIdentifier("identifier expected");
@@ -3735,6 +3810,7 @@
       SkipToMatchingParenthesis();
     }
   }
+  return metadata_pos;
 }
 
 
@@ -3973,7 +4049,8 @@
 }
 
 
-void Parser::ParseTopLevelVariable(TopLevel* top_level) {
+void Parser::ParseTopLevelVariable(TopLevel* top_level,
+                                   intptr_t metadata_pos) {
   TRACE_PARSER("ParseTopLevelVariable");
   const bool is_const = (CurrentToken() == Token::kCONST);
   // Const fields are implicitly final.
@@ -4013,6 +4090,9 @@
     field.set_value(Instance::Handle(Instance::null()));
     top_level->fields.Add(field);
     library_.AddObject(field, var_name);
+    if (metadata_pos >= 0) {
+      library_.AddFieldMetadata(field, metadata_pos);
+    }
     if (CurrentToken() == Token::kASSIGN) {
       ConsumeToken();
       Instance& field_value = Instance::Handle(Object::sentinel().raw());
@@ -4052,7 +4132,8 @@
 }
 
 
-void Parser::ParseTopLevelFunction(TopLevel* top_level) {
+void Parser::ParseTopLevelFunction(TopLevel* top_level,
+                                   intptr_t metadata_pos) {
   TRACE_PARSER("ParseTopLevelFunction");
   AbstractType& result_type = Type::Handle(Type::DynamicType());
   const bool is_static = true;
@@ -4137,10 +4218,14 @@
   } else {
     library_.ReplaceObject(func, func_name);
   }
+  if (metadata_pos >= 0) {
+    library_.AddFunctionMetadata(func, metadata_pos);
+  }
 }
 
 
-void Parser::ParseTopLevelAccessor(TopLevel* top_level) {
+void Parser::ParseTopLevelAccessor(TopLevel* top_level,
+                                   intptr_t metadata_pos) {
   TRACE_PARSER("ParseTopLevelAccessor");
   const bool is_static = true;
   bool is_external = false;
@@ -4258,6 +4343,9 @@
   } else {
     library_.ReplaceObject(func, accessor_name);
   }
+  if (metadata_pos >= 0) {
+    library_.AddFunctionMetadata(func, metadata_pos);
+  }
 }
 
 
@@ -4528,27 +4616,27 @@
   const Class& cls = Class::Handle(isolate());
   while (true) {
     set_current_class(cls);  // No current class.
-    SkipMetadata();
+    intptr_t metadata_pos = SkipMetadata();
     if (CurrentToken() == Token::kCLASS) {
-      ParseClassDeclaration(pending_classes);
+      ParseClassDeclaration(pending_classes, metadata_pos);
     } else if ((CurrentToken() == Token::kTYPEDEF) &&
                (LookaheadToken(1) != Token::kLPAREN)) {
       set_current_class(toplevel_class);
       ParseTypedef(pending_classes);
     } else if ((CurrentToken() == Token::kABSTRACT) &&
         (LookaheadToken(1) == Token::kCLASS)) {
-      ParseClassDeclaration(pending_classes);
+      ParseClassDeclaration(pending_classes, metadata_pos);
     } else if (is_patch_source() && IsLiteral("patch") &&
                (LookaheadToken(1) == Token::kCLASS)) {
-      ParseClassDeclaration(pending_classes);
+      ParseClassDeclaration(pending_classes, metadata_pos);
     } else {
       set_current_class(toplevel_class);
       if (IsVariableDeclaration()) {
-        ParseTopLevelVariable(&top_level);
+        ParseTopLevelVariable(&top_level, metadata_pos);
       } else if (IsFunctionDeclaration()) {
-        ParseTopLevelFunction(&top_level);
+        ParseTopLevelFunction(&top_level, metadata_pos);
       } else if (IsTopLevelAccessor()) {
-        ParseTopLevelAccessor(&top_level);
+        ParseTopLevelAccessor(&top_level, metadata_pos);
       } else if (CurrentToken() == Token::kEOS) {
         break;
       } else {
@@ -6803,8 +6891,8 @@
     arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle()));
   } else {
     const int total_num_parameters = function.NumParameters();
-    Array& array = Array::ZoneHandle(Array::New(total_num_parameters));
-    array ^= array.Canonicalize();
+    Array& array =
+        Array::ZoneHandle(Array::New(total_num_parameters, Heap::kOld));
     // Skip receiver.
     for (int i = 0; i < total_num_parameters; i++) {
       array.SetAt(i, String::Handle(function.ParameterNameAt(i)));
@@ -7437,8 +7525,23 @@
     ASSERT(field.value() != Object::transition_sentinel().raw());
     return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value()));
   }
-  // Access the field directly.
-  return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw()));
+  ASSERT(field.is_static());
+  const Class& field_owner = Class::ZoneHandle(field.owner());
+  const String& field_name = String::ZoneHandle(field.name());
+  const String& getter_name = String::Handle(Field::GetterName(field_name));
+  const Function& getter =
+      Function::Handle(field_owner.LookupStaticFunction(getter_name));
+  // Never load field directly if there is a getter (deterministic AST).
+  if (getter.IsNull()) {
+    return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw()));
+  } else {
+    ASSERT(getter.kind() == RawFunction::kConstImplicitGetter);
+    return new StaticGetterNode(ident_pos,
+                                NULL,  // Receiver.
+                                false,  // is_super_getter.
+                                field_owner,
+                                field_name);
+  }
 }
 
 
@@ -8059,11 +8162,24 @@
 }
 
 
+RawInstance* Parser::TryCanonicalize(const Instance& instance,
+                                     intptr_t token_pos) {
+  if (instance.IsNull()) {
+    return instance.raw();
+  }
+  const char* error_str = NULL;
+  Instance& result =
+      Instance::Handle(instance.CheckAndCanonicalize(&error_str));
+  if (result.IsNull()) {
+    ErrorMsg(token_pos, "Invalid const object %s", error_str);
+  }
+  return result.raw();
+}
 
-// If the field is constant, initialize the field if necessary and return
-// no ast (NULL).
-// Otherwise return NULL if no implicit getter exists (either never created
-// because trivial, or not needed or field not readable).
+
+// If the field is already initialized, return no ast (NULL).
+// Otherwise, if the field is constant, initialize the field and return no ast.
+// If the field is not initialized and not const, return the ast for the getter.
 AstNode* Parser::RunStaticFieldInitializer(const Field& field) {
   ASSERT(field.is_static());
   const Class& field_owner = Class::ZoneHandle(field.owner());
@@ -8121,9 +8237,7 @@
       ASSERT(const_value.IsNull() || const_value.IsInstance());
       Instance& instance = Instance::Handle();
       instance ^= const_value.raw();
-      if (!instance.IsNull()) {
-        instance ^= instance.Canonicalize();
-      }
+      instance = TryCanonicalize(instance, TokenPos());
       field.set_value(instance);
       return NULL;   // Constant
     } else {
@@ -8188,10 +8302,7 @@
         return Object::null();
       }
   } else {
-    if (!instance.IsNull()) {
-      instance ^= instance.Canonicalize();
-    }
-    return instance.raw();
+    return TryCanonicalize(instance, TokenPos());
   }
 }
 
@@ -8831,7 +8942,7 @@
       }
       const_list.SetAt(i, elem->AsLiteralNode()->literal());
     }
-    const_list ^= const_list.Canonicalize();
+    const_list ^= TryCanonicalize(const_list, literal_pos);
     const_list.MakeImmutable();
     return new LiteralNode(literal_pos, const_list);
   } else {
@@ -9028,7 +9139,7 @@
       }
       key_value_array.SetAt(i, arg->AsLiteralNode()->literal());
     }
-    key_value_array ^= key_value_array.Canonicalize();
+    key_value_array ^= TryCanonicalize(key_value_array, TokenPos());
     key_value_array.MakeImmutable();
 
     // Construct the map object.
@@ -9146,12 +9257,11 @@
 }
 
 
-AstNode* Parser::ParseNewOperator() {
+AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
   TRACE_PARSER("ParseNewOperator");
   const intptr_t new_pos = TokenPos();
-  ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST));
-  bool is_const = (CurrentToken() == Token::kCONST);
-  ConsumeToken();
+  ASSERT((op_kind == Token::kNEW) || (op_kind == Token::kCONST));
+  bool is_const = (op_kind == Token::kCONST);
   if (!IsIdentifier()) {
     ErrorMsg("type name expected");
   }
@@ -9619,7 +9729,8 @@
   } else if (CurrentToken() == Token::kSTRING) {
     primary = ParseStringLiteral();
   } else if (CurrentToken() == Token::kNEW) {
-    primary = ParseNewOperator();
+    ConsumeToken();
+    primary = ParseNewOperator(Token::kNEW);
   } else if (CurrentToken() == Token::kCONST) {
     if ((LookaheadToken(1) == Token::kLT) ||
         (LookaheadToken(1) == Token::kLBRACK) ||
@@ -9627,7 +9738,8 @@
         (LookaheadToken(1) == Token::kLBRACE)) {
       primary = ParseCompoundLiteral();
     } else {
-      primary = ParseNewOperator();
+      ConsumeToken();
+      primary = ParseNewOperator(Token::kCONST);
     }
   } else if (CurrentToken() == Token::kLT ||
              CurrentToken() == Token::kLBRACK ||
@@ -9701,9 +9813,7 @@
     ASSERT(result.IsInstance());
     Instance& value = Instance::ZoneHandle();
     value ^= result.raw();
-    if (!value.IsNull()) {
-      value ^= value.Canonicalize();
-    }
+    value = TryCanonicalize(value, TokenPos());
     return value;
   }
 }
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 42e1074..00681dc 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -141,6 +141,11 @@
 
   static void ParseFunction(ParsedFunction* parsed_function);
 
+  // Parse and evaluate the metadata expressions at token_pos in the
+  // class namespace of class cls (which can be the implicit toplevel
+  // class if the metadata is at the top-level).
+  static RawObject* ParseMetadata(const Class& cls, intptr_t token_pos);
+
   // Format and print a message with source location.
   // A null script means no source and a negative token_pos means no position.
   static void PrintMessage(const Script& script,
@@ -261,7 +266,7 @@
 
   void SkipIf(Token::Kind);
   void SkipBlock();
-  void SkipMetadata();
+  intptr_t SkipMetadata();
   void SkipToMatchingParenthesis();
   void SkipTypeArguments();
   void SkipType(bool allow_void);
@@ -325,13 +330,15 @@
 
   // Support for parsing of scripts.
   void ParseTopLevel();
-  void ParseClassDeclaration(const GrowableObjectArray& pending_classes);
+  void ParseClassDeclaration(const GrowableObjectArray& pending_classes,
+                             intptr_t metadata_pos);
   void ParseClassDefinition(const Class& cls);
   void ParseMixinTypedef(const GrowableObjectArray& pending_classes);
   void ParseTypedef(const GrowableObjectArray& pending_classes);
-  void ParseTopLevelVariable(TopLevel* top_level);
-  void ParseTopLevelFunction(TopLevel* top_level);
-  void ParseTopLevelAccessor(TopLevel* top_level);
+  void ParseTopLevelVariable(TopLevel* top_level, intptr_t metadata_pos);
+  void ParseTopLevelFunction(TopLevel* top_level, intptr_t metadata_pos);
+  void ParseTopLevelAccessor(TopLevel* top_level, intptr_t metadata_pos);
+  RawArray* EvaluateMetadata();
 
   // Support for parsing libraries.
   RawObject* CallLibraryTagHandler(Dart_LibraryTag tag,
@@ -358,7 +365,8 @@
   void ParseQualIdent(QualIdent* qual_ident);
   void ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method);
   void ParseFieldDefinition(ClassDesc* members, MemberDesc* field);
-  void ParseClassMemberDefinition(ClassDesc* members);
+  void ParseClassMemberDefinition(ClassDesc* members,
+                                  intptr_t metadata_pos);
   void ParseFormalParameter(bool allow_explicit_default_value,
                             ParamList* params);
   void ParseFormalParameters(bool allow_explicit_default_values,
@@ -522,7 +530,7 @@
   AstNode* ParseMapLiteral(intptr_t type_pos,
                            bool is_const,
                            const AbstractTypeArguments& type_arguments);
-  AstNode* ParseNewOperator();
+  AstNode* ParseNewOperator(Token::Kind op_kind);
   AstNode* ParseArgumentDefinitionTest();
 
   // An implicit argument, if non-null, is prepended to the returned list.
@@ -629,6 +637,8 @@
       const Function& constructor,
       ArgumentListNode* arguments);
 
+  RawInstance* TryCanonicalize(const Instance& instance, intptr_t token_pos);
+
   Isolate* isolate() const { return isolate_; }
 
   Isolate* isolate_;  // Cached current isolate.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 1ef30f4..9794c11 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -443,6 +443,7 @@
   friend class HeapProfilerRootVisitor;
   friend class MarkingVisitor;
   friend class Object;
+  friend class ObjectHistogram;
   friend class RawExternalTypedData;
   friend class RawInstructions;
   friend class RawInstance;
@@ -611,7 +612,6 @@
   RawArray* parameter_names_;
   RawCode* code_;  // Compiled code for the function.
   RawCode* unoptimized_code_;  // Unoptimized code, keep it after optimization.
-  RawArray* deopt_history_;  // Deopt Ids of past deoptimizations.
   RawObject* data_;  // Additional data specific to the function kind.
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->data_);
@@ -761,6 +761,7 @@
   RawScript* script_;
   RawString* private_key_;
   RawArray* dictionary_;         // Top-level names in this library.
+  RawGrowableObjectArray* metadata_;  // Metadata on classes, methods etc.
   RawArray* anonymous_classes_;  // Classes containing top-level elements.
   RawArray* imports_;            // List of Namespaces imported without prefix.
   RawArray* exports_;            // List of re-exported Namespaces.
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index d4f39a7..7f139db 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1711,7 +1711,8 @@
   if ((kind != Snapshot::kFull) && RawObject::IsCanonical(tags) &&
       (RawObject::IsCreatedFromSnapshot(tags) ||
        (kind == Snapshot::kMessage))) {
-    obj ^= obj.Canonicalize();
+    obj ^= obj.CheckAndCanonicalize(NULL);
+    ASSERT(!obj.IsNull());
   }
   reader->AddBackRef(object_id, &obj, kIsDeserialized);
 
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index ff22e03..3333f2d 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -479,7 +479,7 @@
   obj->ptr()->handle_vtable_ = fake.vtable();
   cls_ = obj;
   cls_.set_id(kIllegalCid);
-  isolate()->class_table()->Register(cls_);
+  isolate()->RegisterClass(cls_);
   return cls_.raw();
 }
 
@@ -795,7 +795,8 @@
     if (kind_ == Snapshot::kFull) {
       result->SetCreatedFromSnapshot();
     } else if (result->IsCanonical()) {
-      *result = result->Canonicalize();
+      *result = result->CheckAndCanonicalize(NULL);
+      ASSERT(!result->IsNull());
     }
     return result->raw();
   }
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index a1752a0..2688745 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -70,6 +70,8 @@
   V(UnresolvedClass, "UnresolvedClass")                                        \
   V(Type, "_Type")                                                             \
   V(TypeParameter, "_TypeParameter")                                           \
+  V(BoundedType, "_BoundedType")                                               \
+  V(MixinAppType, "_MixinAppType")                                             \
   V(TypeArguments, "TypeArguments")                                            \
   V(InstantiatedTypeArguments, "InstantiatedTypeArguments")                    \
   V(PatchClass, "PatchClass")                                                  \
@@ -347,6 +349,9 @@
   static const String& Slash() {
     return *(symbol_handles_[kNullCharId + '/']);
   }
+  static const String& At() {
+    return *(symbol_handles_[kNullCharId + '@']);
+  }
 
   // Access methods for symbol handles stored in the vm isolate.
 #define DEFINE_SYMBOL_HANDLE_ACCESSOR(symbol, literal)                         \
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 6c68fba..1d6ec29 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -170,6 +170,8 @@
     'hash_map_test.cc',
     'heap.cc',
     'heap.h',
+    'heap_histogram.cc',
+    'heap_histogram.h',
     'heap_profiler.cc',
     'heap_profiler.h',
     'heap_profiler_test.cc',
diff --git a/sdk/bin/dart2analyzer b/sdk/bin/dart2analyzer
deleted file mode 100755
index 4c17671..0000000
--- a/sdk/bin/dart2analyzer
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash --posix
-# 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.
-
-set -e
-
-BIN_DIR="$(cd "${BASH_SOURCE%/*}" ; pwd -P)"
-SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
-DART="$BIN_DIR/dart"
-PKG_ANALYZER="$BIN_DIR/../packages/analyzer_experimental/bin/analyzer.dart"
-
-FOUND_BATCH=0
-FOUND_SDK=0
-for ARG in "$@"
-do
-  case $ARG in
-    -batch|--batch)
-      FOUND_BATCH=1
-      ;;
-    --dart-sdk)
-      FOUND_SDK=1
-      ;;
-    *)
-      ;;
-  esac
-done
-
-if [ $FOUND_SDK = 0 ] ; then
-  exec "$DART" "${PKG_ANALYZER}" --dart-sdk "${SDK_DIR}" "$@"
-else
-  exec "$DART" "${PKG_ANALYZER}" "$@"
-fi
diff --git a/sdk/bin/dart2analyzer_developer b/sdk/bin/dart2analyzer_developer
deleted file mode 100755
index 5583382..0000000
--- a/sdk/bin/dart2analyzer_developer
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-# 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.
-
-. ${BASH_SOURCE%_developer}
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 04191ab..b51e9f5 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -913,7 +913,13 @@
     if (element.isClass()) {
       ClassElement cls = element;
       cls.ensureResolved(this);
-      cls.forEachLocalMember(world.addToWorkList);
+      cls.forEachLocalMember((e) {
+        if (e.isSynthesized) {
+          // TODO(ahe): Work-around for http://dartbug.com/11205.
+          if (e.getLibrary().isPlatformLibrary) return;
+        }
+        world.addToWorkList(e);
+      });
       world.registerInstantiatedClass(element, globalDependencies);
     } else {
       world.addToWorkList(element);
@@ -1308,7 +1314,9 @@
 
   const Tracer();
 
-  void traceCompilation(String methodName, ItemCompilationContext context) {
+  void traceCompilation(String methodName,
+                        ItemCompilationContext context,
+                        Compiler compiler) {
   }
 
   void traceGraph(String name, var graph) {
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index 5bc30cd..609b2be 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -418,7 +418,9 @@
           new EmptyStatement(new StringToken(SEMICOLON_INFO, ';', -1)),
           null, Modifiers.EMPTY, null, null);
 
-      classMembers[classElement].add(constructor);
+      if (!constructor.isSynthesized) {
+        classMembers[classElement].add(constructor);
+      }
       elementAsts[constructor] =
           new ElementAst(constructor.cachedNode, new TreeElementMapping(null));
     }
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 732e44c..66f97f4 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1959,6 +1959,8 @@
 
   void setDefaultConstructor(FunctionElement constructor, Compiler compiler) {
     addToScope(constructor, compiler);
+    // The default constructor, although synthetic, is part of a class' API.
+    localMembers = localMembers.prepend(constructor);
   }
 
   Link<DartType> computeTypeParameters(Compiler compiler) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 1dfe675..419f521 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -69,6 +69,14 @@
   Element getInterceptorMethod;
   Element interceptedNames;
 
+  HType stringType;
+  HType indexablePrimitiveType;
+  HType readableArrayType;
+  HType mutableArrayType;
+  HType fixedArrayType;
+  HType extendableArrayType;
+  
+
   // TODO(9577): Make it so that these are not needed when there are no native
   // classes.
   Element dispatchPropertyName;
@@ -371,6 +379,19 @@
         ..add(jsNullClass);
 
     validateInterceptorImplementsAllObjectMethods(jsInterceptorClass);
+
+    stringType = new HBoundedType(
+        new TypeMask.nonNullExact(jsStringClass.rawType));
+    indexablePrimitiveType = new HBoundedType(
+        new TypeMask.nonNullSubtype(jsIndexableClass.rawType));
+    readableArrayType = new HBoundedType(
+        new TypeMask.nonNullSubclass(jsArrayClass.rawType));
+    mutableArrayType = new HBoundedType(
+        new TypeMask.nonNullSubclass(jsMutableArrayClass.rawType));
+    fixedArrayType = new HBoundedType(
+        new TypeMask.nonNullExact(jsFixedArrayClass.rawType));
+    extendableArrayType = new HBoundedType(
+        new TypeMask.nonNullExact(jsExtendableArrayClass.rawType));
   }
 
   void validateInterceptorImplementsAllObjectMethods(
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index fb146ff..7721152 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1132,14 +1132,16 @@
   bool instanceFieldNeedsGetter(Element member) {
     assert(member.isField());
     if (fieldAccessNeverThrows(member)) return false;
-    return compiler.codegenWorld.hasInvokedGetter(member, compiler);
+    return compiler.mirrorsEnabled
+        || compiler.codegenWorld.hasInvokedGetter(member, compiler);
   }
 
   bool instanceFieldNeedsSetter(Element member) {
     assert(member.isField());
     if (fieldAccessNeverThrows(member)) return false;
     return (!member.modifiers.isFinalOrConst())
-        && compiler.codegenWorld.hasInvokedSetter(member, compiler);
+        && (compiler.mirrorsEnabled
+            || compiler.codegenWorld.hasInvokedSetter(member, compiler));
   }
 
   // We never access a field in a closure (a captured variable) without knowing
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index f7adf4a..3f29f71 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -172,17 +172,6 @@
         needed = true;
       }
 
-      // BUG.  There is a missing proto in the picture the DOM gives of the
-      // proto chain.
-      // TODO(9907): Fix DOM generation. We might need an annotation.
-      if (classElement.isNative()) {
-        List<String> nativeTags = nativeTagsOfClass(classElement);
-        if (nativeTags.contains('HTMLElement')) {
-          nonleafClasses.add(classElement);
-          needed = true;
-        }
-      }
-
       if (needed || neededClasses.contains(classElement)) {
         neededClasses.add(classElement);
         neededClasses.add(classElement.superclass);
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 6a70a51..df00f77 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -942,7 +942,7 @@
     HInstruction local = builder.localsHandler.readLocal(parameter);
     Constant arityConstant =
         builder.constantSystem.createInt(type.computeArity());
-    HInstruction arity = builder.graph.addConstant(arityConstant);
+    HInstruction arity = builder.graph.addConstant(arityConstant, compiler);
     // TODO(ngeoffray): For static methods, we could pass a method with a
     // defined arity.
     Element helper = builder.backend.getClosureConverter();
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index d0ffd9a..95f6edf 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -3336,10 +3336,17 @@
   void doApplyMixinTo(MixinApplicationElement mixinApplication,
                       DartType supertype,
                       DartType mixinType) {
-    assert(mixinApplication.supertype == null);
-    mixinApplication.supertype = supertype;
-
     Node node = mixinApplication.parseNode(compiler);
+
+    if (mixinApplication.supertype != null) {
+      // [supertype] is not null if there was a cycle.
+      assert(invariant(node, compiler.compilationFailed));
+      supertype = mixinApplication.supertype;
+      assert(invariant(node, supertype.element == compiler.objectClass));
+    } else {
+      mixinApplication.supertype = supertype;
+    }
+
     // Named mixin application may have an 'implements' clause.
     NamedMixinApplication namedMixinApplication =
         node.asNamedMixinApplication();
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
index b9db4c4..1396a72 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
@@ -110,7 +110,7 @@
   // Primitive types that are not null are valuable. These include
   // indexable arrays.
   bool typeValuable(HType type) {
-    return type.isPrimitive() && !type.isNull();
+    return type.isPrimitive(compiler) && !type.isNull();
   }
 
   bool get hasTypeGuards => work.guards.length != 0;
@@ -219,7 +219,8 @@
   bool willThrowArgumentError(Selector selector,
                               HInstruction receiver,
                               HType speculativeType) {
-    if (receiver != null && (receiver.isInteger() || receiver.isString())) {
+    if (receiver != null
+        && (receiver.isInteger() || receiver.isString(compiler))) {
       return selector.isOperator()
           && selector.name != const SourceString('==')
           && (speculativeType.isNumber() && !speculativeType.isInteger());
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 9121747..1cd2255 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -73,7 +73,8 @@
         } else {
           name = "${element.name.slowToString()}";
         }
-        compiler.tracer.traceCompilation(name, work.compilationContext);
+        compiler.tracer.traceCompilation(
+            name, work.compilationContext, compiler);
         compiler.tracer.traceGraph('builder', graph);
       }
       return graph;
@@ -829,7 +830,7 @@
       assert(label != null);
       HInstruction value = builder.graph.addConstantInt(
           targetIndexMap[label.target],
-          builder.constantSystem);
+          builder.compiler);
       builder.localsHandler.updateLocal(target, value);
 
       assert(label.target.labels.contains(label));
@@ -1017,11 +1018,11 @@
             () {
               HParameterValue parameter = parameters.values.first;
               push(new HIdentity(
-                  parameter, graph.addConstantNull(constantSystem)));
+                  parameter, graph.addConstantNull(compiler)));
             },
             () {
               closeAndGotoExit(new HReturn(
-                  graph.addConstantBool(false, constantSystem)));
+                  graph.addConstantBool(false, compiler)));
             },
             null);
       }
@@ -1183,7 +1184,7 @@
                                  ElementKind.VARIABLE,
                                  function);
     newLocalsHandler.updateLocal(returnElement,
-                                 graph.addConstantNull(constantSystem));
+                                 graph.addConstantNull(compiler));
     elements = compiler.enqueuer.resolution.getCachedElements(function);
     assert(elements != null);
     returnType = signature.returnType;
@@ -1343,7 +1344,7 @@
                || superclass.typeVariables == typeVariables);
         while (!typeVariables.isEmpty) {
           localsHandler.updateLocal(typeVariables.head.element,
-              graph.addConstantNull(constantSystem));
+              graph.addConstantNull(compiler));
           typeVariables = typeVariables.tail;
         }
       }
@@ -1490,7 +1491,7 @@
             SendSet assignment = node.asSendSet();
             HInstruction value;
             if (assignment == null) {
-              value = graph.addConstantNull(constantSystem);
+              value = graph.addConstantNull(compiler);
             } else {
               Node right = assignment.arguments.head;
               TreeElements savedElements = elements;
@@ -1677,11 +1678,12 @@
       // Fetch the original default value of [element];
       Constant constant = compileVariable(element);
       HConstant defaultValue = constant == null
-          ? graph.addConstantNull(constantSystem)
-          : graph.addConstant(constant);
+          ? graph.addConstantNull(compiler)
+          : graph.addConstant(constant, compiler);
 
       // Emit the equality check with the sentinel.
-      HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL);
+      HConstant sentinel =
+          graph.addConstant(SentinelConstant.SENTINEL, compiler);
       HInstruction operand = parameters[element];
       check = new HIdentity(sentinel, operand);
       add(check);
@@ -1943,7 +1945,7 @@
   }
 
   visitExpressionStatement(ExpressionStatement node) {
-    assert(isReachable);
+    if (!isReachable) return;
     Throw throwExpression = node.expression.asThrow();
     if (throwExpression != null && inliningStack.isEmpty) {
       visit(throwExpression.expression);
@@ -2243,7 +2245,7 @@
     }
     HInstruction buildCondition() {
       if (node.condition == null) {
-        return graph.addConstantBool(true, constantSystem);
+        return graph.addConstantBool(true, compiler);
       }
       visit(node.condition);
       return popBoolified();
@@ -2504,7 +2506,7 @@
       HConstant constant = operand;
       Constant folded = operation.fold(constant.constant);
       if (folded != null) {
-        stack.add(graph.addConstant(folded));
+        stack.add(graph.addConstant(folded, compiler));
         return;
       }
     }
@@ -2572,7 +2574,7 @@
         value = compileVariable(element);
       }
       if (value != null) {
-        stack.add(graph.addConstant(value));
+        stack.add(graph.addConstant(value, compiler));
       } else if (element.isField() && isLazilyInitialized(element)) {
         HInstruction instruction = new HLazyStatic(element);
         instruction.instructionType =
@@ -2689,13 +2691,17 @@
     return pop();
   }
 
+  HLiteralList buildLiteralList(List<HInstruction> inputs) {
+    return new HLiteralList(inputs, backend.extendableArrayType);
+  }
+
   // TODO(karlklose): change construction of the representations to be GVN'able
   // (dartbug.com/7182).
   HInstruction buildTypeArgumentRepresentations(DartType type) {
     // Compute the representation of the type arguments, including access
     // to the runtime type information for type variables as instructions.
     if (type.kind == TypeKind.TYPE_VARIABLE) {
-      return new HLiteralList(<HInstruction>[addTypeVariableReference(type)]);
+      return buildLiteralList(<HInstruction>[addTypeVariableReference(type)]);
     } else {
       assert(type.element.isClass());
       InterfaceType interface = type;
@@ -2710,7 +2716,7 @@
       }
       String template = '[${templates.join(', ')}]';
       HInstruction representation =
-        createForeign(template, HType.READABLE_ARRAY, inputs);
+        createForeign(template, backend.readableArrayType, inputs);
       return representation;
     }
   }
@@ -2789,7 +2795,7 @@
       HInstruction isFieldName = addConstantString(node, operator);
       HInstruction asFieldName = compiler.world.hasAnySubtype(element)
           ? addConstantString(node, backend.namer.substitutionName(element))
-          : graph.addConstantNull(constantSystem);
+          : graph.addConstantNull(compiler);
       List<HInstruction> inputs = <HInstruction>[expression,
                                                  isFieldName,
                                                  representations,
@@ -2848,7 +2854,7 @@
     } else {
       constant = compileConstant(parameter);
     }
-    return graph.addConstant(constant);
+    return graph.addConstant(constant, compiler);
   }
 
   /**
@@ -3131,7 +3137,7 @@
         constantSystem.createString(new DartString.literal(internalName), node);
 
     Element createInvocationMirror = backend.getCreateInvocationMirror();
-    var argumentsInstruction = new HLiteralList(arguments);
+    var argumentsInstruction = buildLiteralList(arguments);
     add(argumentsInstruction);
 
     var argumentNames = new List<HInstruction>();
@@ -3139,9 +3145,9 @@
       Constant argumentNameConstant =
           constantSystem.createString(new DartString.literal(
               argumentName.slowToString()), node);
-      argumentNames.add(graph.addConstant(argumentNameConstant));
+      argumentNames.add(graph.addConstant(argumentNameConstant, compiler));
     }
-    var argumentNamesInstruction = new HLiteralList(argumentNames);
+    var argumentNamesInstruction = buildLiteralList(argumentNames);
     add(argumentNamesInstruction);
 
     Constant kindConstant =
@@ -3149,9 +3155,9 @@
 
     pushInvokeStatic(null,
                      createInvocationMirror,
-                     [graph.addConstant(nameConstant),
-                      graph.addConstant(internalNameConstant),
-                      graph.addConstant(kindConstant),
+                     [graph.addConstant(nameConstant, compiler),
+                      graph.addConstant(internalNameConstant, compiler),
+                      graph.addConstant(kindConstant, compiler),
                       argumentsInstruction,
                       argumentNamesInstruction],
                       HType.UNKNOWN);
@@ -3214,7 +3220,7 @@
     int index = RuntimeTypes.getTypeVariableIndex(variable);
     String substitutionNameString = backend.namer.substitutionName(cls);
     HInstruction substitutionName = graph.addConstantString(
-        new LiteralDartString(substitutionNameString), null, constantSystem);
+        new LiteralDartString(substitutionNameString), null, compiler);
     HInstruction target = localsHandler.readThis();
     HInstruction substitution = createForeign('#[#]', HType.UNKNOWN,
         <HInstruction>[target, substitutionName]);
@@ -3223,7 +3229,7 @@
                      backend.getGetRuntimeTypeArgument(),
                      [target,
                       substitution,
-                      graph.addConstantInt(index, constantSystem)],
+                      graph.addConstantInt(index, compiler)],
                       HType.UNKNOWN);
     return pop();
   }
@@ -3271,7 +3277,7 @@
                      message: '$argument is malformed in checked mode'));
     if (argument == compiler.types.dynamicType || argument.isMalformed) {
       // Represent [dynamic] as [null].
-      return graph.addConstantNull(constantSystem);
+      return graph.addConstantNull(compiler);
     }
 
     List<HInstruction> inputs = <HInstruction>[];
@@ -3280,7 +3286,7 @@
       inputs.add(addTypeVariableReference(variable));
     });
 
-    HInstruction result = createForeign(template, HType.STRING, inputs);
+    HInstruction result = createForeign(template, backend.stringType, inputs);
     add(result);
     return result;
   }
@@ -3305,7 +3311,7 @@
       return;
     }
 
-    HInstruction typeInfo = new HLiteralList(rtiInputs);
+    HInstruction typeInfo = buildLiteralList(rtiInputs);
     add(typeInfo);
 
     // Set the runtime type information on the object.
@@ -3334,11 +3340,11 @@
       if (Elements.isFixedListConstructorCall(
               originalElement, send, compiler)) {
         isListConstructor = true;
-        return HType.FIXED_ARRAY;
+        return backend.fixedArrayType;
       } else if (Elements.isGrowableListConstructorCall(
                     originalElement, send, compiler)) {
         isListConstructor = true;
-        return HType.EXTENDABLE_ARRAY;
+        return backend.extendableArrayType;
       } else if (element.isGenerativeConstructor()) {
         ClassElement cls = element.getEnclosingClass();
         return new HType.nonNullExact(cls.thisType, compiler);
@@ -3413,7 +3419,7 @@
       // Also add null to non-provided type variables to call the
       // constructor with the right number of arguments.
       while (!typeVariable.isEmpty) {
-        inputs.add(graph.addConstantNull(constantSystem));
+        inputs.add(graph.addConstantNull(compiler));
         typeVariable = typeVariable.tail;
       }
     }
@@ -3458,7 +3464,7 @@
     }
     if (identical(element, compiler.assertMethod)
         && !compiler.enableUserAssertions) {
-      stack.add(graph.addConstantNull(constantSystem));
+      stack.add(graph.addConstantNull(compiler));
       return;
     }
     compiler.ensure(!element.isGenerativeConstructor());
@@ -3492,7 +3498,7 @@
   HConstant addConstantString(Node node, String string) {
     DartString dartString = new DartString.literal(string);
     Constant constant = constantSystem.createString(dartString, node);
-    return graph.addConstant(constant);
+    return graph.addConstant(constant, compiler);
   }
 
   visitTypeReferenceSend(Send node) {
@@ -3501,14 +3507,14 @@
       // TODO(karlklose): add type representation
       ConstantHandler handler = compiler.constantHandler;
       Constant constant = handler.compileNodeWithDefinitions(node, elements);
-      stack.add(graph.addConstant(constant));
+      stack.add(graph.addConstant(constant, compiler));
     } else if (element.isTypeVariable()) {
       HInstruction value =
           addTypeVariableReference(element.computeType(compiler));
       pushInvokeStatic(node,
                        backend.getRuntimeTypeToString(),
                        [value],
-                       HType.STRING);
+                       backend.stringType);
       pushInvokeStatic(node,
                        backend.getCreateRuntimeType(),
                        [pop()]);
@@ -3561,11 +3567,11 @@
     Element helper = backend.getThrowNoSuchMethod();
     Constant receiverConstant =
         constantSystem.createString(new DartString.empty(), diagnosticNode);
-    HInstruction receiver = graph.addConstant(receiverConstant);
+    HInstruction receiver = graph.addConstant(receiverConstant, compiler);
     DartString dartString = new DartString.literal(methodName);
     Constant nameConstant =
         constantSystem.createString(dartString, diagnosticNode);
-    HInstruction name = graph.addConstant(nameConstant);
+    HInstruction name = graph.addConstant(nameConstant, compiler);
     if (argumentValues == null) {
       argumentValues = <HInstruction>[];
       argumentNodes.forEach((argumentNode) {
@@ -3574,7 +3580,7 @@
         argumentValues.add(value);
       });
     }
-    HInstruction arguments = new HLiteralList(argumentValues);
+    HInstruction arguments = buildLiteralList(argumentValues);
     add(arguments);
     HInstruction existingNamesList;
     if (existingArguments != null) {
@@ -3582,13 +3588,13 @@
       for (String name in existingArguments) {
         HInstruction nameConstant =
             graph.addConstantString(new DartString.literal(name),
-                                    diagnosticNode, constantSystem);
+                                    diagnosticNode, compiler);
         existingNames.add(nameConstant);
       }
-      existingNamesList = new HLiteralList(existingNames);
+      existingNamesList = buildLiteralList(existingNames);
       add(existingNamesList);
     } else {
-      existingNamesList = graph.addConstantNull(constantSystem);
+      existingNamesList = graph.addConstantNull(compiler);
     }
     pushInvokeStatic(diagnosticNode,
                      helper,
@@ -3643,7 +3649,7 @@
       // TODO(karlklose): add type representation
       ConstantHandler handler = compiler.constantHandler;
       Constant constant = handler.compileNodeWithDefinitions(node, elements);
-      stack.add(graph.addConstant(constant));
+      stack.add(graph.addConstant(constant, compiler));
       if (isSymbolConstructor) {
         ConstructedConstant symbol = constant;
         StringConstant stringConstant = symbol.fields.single;
@@ -3794,7 +3800,7 @@
                                  Link<Node> arguments) {
     HInstruction rhs;
     if (node.isPrefix || node.isPostfix) {
-      rhs = graph.addConstantInt(1, constantSystem);
+      rhs = graph.addConstantInt(1, compiler);
     } else {
       visit(arguments.head);
       assert(arguments.tail.isEmpty);
@@ -3945,25 +3951,25 @@
   }
 
   void visitLiteralInt(LiteralInt node) {
-    stack.add(graph.addConstantInt(node.value, constantSystem));
+    stack.add(graph.addConstantInt(node.value, compiler));
   }
 
   void visitLiteralDouble(LiteralDouble node) {
-    stack.add(graph.addConstantDouble(node.value, constantSystem));
+    stack.add(graph.addConstantDouble(node.value, compiler));
   }
 
   void visitLiteralBool(LiteralBool node) {
-    stack.add(graph.addConstantBool(node.value, constantSystem));
+    stack.add(graph.addConstantBool(node.value, compiler));
   }
 
   void visitLiteralString(LiteralString node) {
-    stack.add(graph.addConstantString(node.dartString, node, constantSystem));
+    stack.add(graph.addConstantString(node.dartString, node, compiler));
   }
 
   void visitStringJuxtaposition(StringJuxtaposition node) {
     if (!node.isInterpolation) {
       // This is a simple string with no interpolations.
-      stack.add(graph.addConstantString(node.dartString, node, constantSystem));
+      stack.add(graph.addConstantString(node.dartString, node, compiler));
       return;
     }
     StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node);
@@ -3972,7 +3978,7 @@
   }
 
   void visitLiteralNull(LiteralNull node) {
-    stack.add(graph.addConstantNull(constantSystem));
+    stack.add(graph.addConstantNull(compiler));
   }
 
   visitNodeList(NodeList node) {
@@ -4016,7 +4022,7 @@
   visitRethrow(Rethrow node) {
     HInstruction exception = rethrowableException;
     if (exception == null) {
-      exception = graph.addConstantNull(constantSystem);
+      exception = graph.addConstantNull(compiler);
       compiler.internalError(
           'rethrowableException should not be null', node: node);
     }
@@ -4032,9 +4038,9 @@
     HInstruction value;
     if (node.isRedirectingFactoryBody) {
       // TODO(ahe): This is only for reflection, and it is not correct yet.
-      value = graph.addConstantNull(constantSystem);
+      value = graph.addConstantNull(compiler);
     } else if (node.expression == null) {
-      value = graph.addConstantNull(constantSystem);
+      value = graph.addConstantNull(compiler);
     } else {
       visit(node.expression);
       value = pop();
@@ -4071,7 +4077,7 @@
          link = link.tail) {
       Node definition = link.head;
       if (definition is Identifier) {
-        HInstruction initialValue = graph.addConstantNull(constantSystem);
+        HInstruction initialValue = graph.addConstantNull(compiler);
         localsHandler.updateLocal(elements[definition], initialValue);
       } else {
         assert(definition is SendSet);
@@ -4085,7 +4091,7 @@
     if (node.isConst()) {
       ConstantHandler handler = compiler.constantHandler;
       Constant constant = handler.compileNodeWithDefinitions(node, elements);
-      stack.add(graph.addConstant(constant));
+      stack.add(graph.addConstant(constant, compiler));
       return;
     }
 
@@ -4096,7 +4102,7 @@
       visit(link.head);
       inputs.add(pop());
     }
-    push(new HLiteralList(inputs));
+    push(buildLiteralList(inputs));
   }
 
   visitConditional(Conditional node) {
@@ -4280,7 +4286,7 @@
     if (node.isConst()) {
       ConstantHandler handler = compiler.constantHandler;
       Constant constant = handler.compileNodeWithDefinitions(node, elements);
-      stack.add(graph.addConstant(constant));
+      stack.add(graph.addConstant(constant, compiler));
       return;
     }
     List<HInstruction> inputs = <HInstruction>[];
@@ -4291,7 +4297,7 @@
       inputs.add(pop());
       inputs.add(pop());
     }
-    HLiteralList keyValuePairs = new HLiteralList(inputs);
+    HLiteralList keyValuePairs = buildLiteralList(inputs);
     add(keyValuePairs);
     HType mapType = new HType.nonNullSubtype(
         backend.mapLiteralClass.computeType(compiler), compiler);
@@ -4452,7 +4458,7 @@
     //   }
 
     TargetElement switchTarget = elements[node];
-    HInstruction initialValue = graph.addConstantNull(constantSystem);
+    HInstruction initialValue = graph.addConstantNull(compiler);
     localsHandler.updateLocal(switchTarget, initialValue);
 
     JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: false);
@@ -4485,11 +4491,11 @@
       if (switchCase != null) {
         // Generate 'target = i; break;' for switch case i.
         int index = caseIndex[switchCase];
-        HInstruction value = graph.addConstantInt(index, constantSystem);
+        HInstruction value = graph.addConstantInt(index, compiler);
         localsHandler.updateLocal(switchTarget, value);
       } else {
         // Generate synthetic default case 'target = null; break;'.
-        HInstruction value = graph.addConstantNull(constantSystem);
+        HInstruction value = graph.addConstantNull(compiler);
         localsHandler.updateLocal(switchTarget, value);
       }
       jumpTargets[switchTarget].generateBreak();
@@ -4504,7 +4510,7 @@
     jumpHandler.close();
 
     HInstruction buildCondition() =>
-        graph.addConstantBool(true, constantSystem);
+        graph.addConstantBool(true, compiler);
 
     void buildSwitch() {
       HInstruction buildExpression() {
@@ -4599,7 +4605,7 @@
       HBasicBlock block = graph.addNewBlock();
       for (Constant constant in getConstants(switchCase)) {
         caseConstants.add(constant);
-        HConstant hConstant = graph.addConstant(constant);
+        HConstant hConstant = graph.addConstant(constant, compiler);
         switchInstruction.inputs.add(hConstant);
         hConstant.usedBy.add(switchInstruction);
         expressionBlock.addSuccessor(block);
@@ -4786,7 +4792,7 @@
           if (type.isMalformed) {
             // TODO(johnniwinther): Handle malformed types in [HIs] instead.
             HInstruction condition =
-                graph.addConstantBool(true, constantSystem);
+                graph.addConstantBool(true, compiler);
             stack.add(condition);
           } else {
             // TODO(karlkose): support type arguments here.
@@ -4799,7 +4805,7 @@
           VariableDefinitions declaration = catchBlock.formals.nodes.head;
           HInstruction condition = null;
           if (declaration.type == null) {
-            condition = graph.addConstantBool(true, constantSystem);
+            condition = graph.addConstantBool(true, compiler);
             stack.add(condition);
           } else {
             // TODO(aprelev@gmail.com): Once old catch syntax is removed
@@ -4992,7 +4998,7 @@
     node.accept(builder);
     HInstruction expression = builder.pop();
     if (!expression.isConstantString()) {
-      expression = new HStringify(expression, node);
+      expression = new HStringify(expression, node, builder.backend.stringType);
       builder.add(expression);
     }
     result = (result == null) ? expression : concat(result, expression);
@@ -5016,7 +5022,8 @@
   }
 
   HInstruction concat(HInstruction left, HInstruction right) {
-    HInstruction instruction = new HStringConcat(left, right, diagnosticNode);
+    HInstruction instruction = new HStringConcat(
+        left, right, diagnosticNode, builder.backend.stringType);
     builder.add(instruction);
     return instruction;
   }
@@ -5290,7 +5297,7 @@
 
     handleIf(visitCondition, visitThen, null);
     HConstant notIsAnd =
-        builder.graph.addConstantBool(!isAnd, builder.constantSystem);
+        builder.graph.addConstantBool(!isAnd, builder.compiler);
     HPhi result = new HPhi.manyInputs(null,
                                       <HInstruction>[boolifiedRight, notIsAnd]);
     builder.current.addPhi(result);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 2287d54..01ad49e 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -289,7 +289,7 @@
   endLabeledBlock(HLabeledBlockInformation labeledBlockInfo);
 
   void preGenerateMethod(HGraph graph) {
-    new SsaInstructionMerger(generateAtUseSite).visitGraph(graph);
+    new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph);
     new SsaConditionMerger(
         generateAtUseSite, controlFlowOperators).visitGraph(graph);
     SsaLiveIntervalBuilder intervalBuilder =
@@ -620,6 +620,7 @@
       HCheck check = argument;
       use(check.checkedInput);
     } else {
+      assert(variableNames.hasName(argument));
       push(new js.VariableUse(variableNames.getName(argument)));
     }
   }
@@ -1221,7 +1222,7 @@
   void emitIdentityComparison(HInstruction left,
                               HInstruction right,
                               bool inverse) {
-    String op = singleIdentityComparison(left, right);
+    String op = singleIdentityComparison(left, right, compiler);
     if (op != null) {
       use(left);
       js.Expression jsLeft = pop();
@@ -1806,8 +1807,8 @@
 
       HInstruction left = relational.left;
       HInstruction right = relational.right;
-      if (left.instructionType.isUseful() && left.isString() &&
-          right.instructionType.isUseful() && right.isString()) {
+      if (left.instructionType.isUseful() && left.isString(compiler) &&
+          right.instructionType.isUseful() && right.isString(compiler)) {
         return true;
       }
 
@@ -2037,7 +2038,7 @@
 
   void visitStringify(HStringify node) {
     HInstruction input = node.inputs.first;
-    if (input.isString()) {
+    if (input.isString(compiler)) {
       use(input);
     } else if (input.isInteger() || input.isBoolean()) {
       // JavaScript's + operator with a string for the left operand will convert
@@ -2433,7 +2434,7 @@
       // input is !bool
       checkBool(input, '!==');
       test = pop();
-    } else if (node.isString()) {
+    } else if (node.isString(compiler)) {
       // input is !string
       checkString(input, '!==');
       test = pop();
@@ -3002,7 +3003,9 @@
   }
 }
 
-String singleIdentityComparison(HInstruction left, HInstruction right) {
+String singleIdentityComparison(HInstruction left,
+                                HInstruction right,
+                                Compiler compiler) {
   // Returns the single identity comparison (== or ===) or null if a more
   // complex expression is required.
   if ((left.isConstant() && left.isConstantSentinel()) ||
@@ -3011,7 +3014,7 @@
   HType rightType = right.instructionType;
   if (leftType.canBeNull() && rightType.canBeNull()) {
     if (left.isConstantNull() || right.isConstantNull() ||
-        (leftType.isPrimitive() && leftType == rightType)) {
+        (leftType.isPrimitive(compiler) && leftType == rightType)) {
       return '==';
     }
     return null;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
index c29f3e8..b501668 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
@@ -15,6 +15,7 @@
  *   t2 = add(4, 3);
  */
 class SsaInstructionMerger extends HBaseVisitor {
+  final Compiler compiler;
   /**
    * List of [HInstruction] that the instruction merger expects in
    * order when visiting the inputs of an instruction.
@@ -33,7 +34,7 @@
     generateAtUseSite.add(instruction);
   }
 
-  SsaInstructionMerger(this.generateAtUseSite);
+  SsaInstructionMerger(this.generateAtUseSite, this.compiler);
 
   void visitGraph(HGraph graph) {
     visitDominatorTree(graph);
@@ -104,7 +105,7 @@
   void visitIdentity(HIdentity instruction) {
     HInstruction left = instruction.left;
     HInstruction right = instruction.right;
-    if (singleIdentityComparison(left, right) != null) {
+    if (singleIdentityComparison(left, right, compiler) != null) {
       super.visitIdentity(instruction);
     }
     // Do nothing.
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
index 9c7de35..d36e593e 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -91,18 +91,20 @@
     HType type = input.instructionType;
     ClassElement constantInterceptor;
     JavaScriptBackend backend = compiler.backend;
-    if (type.isInteger()) {
+    if (type.canBeNull()) {
+      if (type.isNull()) {
+        constantInterceptor = backend.jsNullClass;
+      }
+    } else if (type.isInteger()) {
       constantInterceptor = backend.jsIntClass;
     } else if (type.isDouble()) {
       constantInterceptor = backend.jsDoubleClass;
     } else if (type.isBoolean()) {
       constantInterceptor = backend.jsBoolClass;
-    } else if (type.isString()) {
+    } else if (type.isString(compiler)) {
       constantInterceptor = backend.jsStringClass;
     } else if (type.isArray(compiler)) {
       constantInterceptor = backend.jsArrayClass;
-    } else if (type.isNull()) {
-      constantInterceptor = backend.jsNullClass;
     } else if (type.isNumber()
         && !interceptedClasses.contains(backend.jsIntClass)
         && !interceptedClasses.contains(backend.jsDoubleClass)) {
@@ -122,12 +124,9 @@
       // for a subclass or call methods defined on a subclass.  Provided the
       // code is completely insensitive to the specific instance subclasses, we
       // can use the non-leaf class directly.
-
-      if (!type.canBeNull()) {
-        ClassElement element = type.computeMask(compiler).singleClass(compiler);
-        if (element != null && element.isNative()) {
-          constantInterceptor = element;
-        }
+      ClassElement element = type.computeMask(compiler).singleClass(compiler);
+      if (element != null && element.isNative()) {
+        constantInterceptor = element;
       }
     }
 
@@ -138,7 +137,7 @@
 
     Constant constant = new InterceptorConstant(
         constantInterceptor.computeType(compiler));
-    return graph.addConstant(constant);
+    return graph.addConstant(constant, compiler);
   }
 
   HInstruction findDominator(Iterable<HInstruction> instructions) {
@@ -229,7 +228,7 @@
     if (!user.hasSameLoopHeaderAs(node)) return false;
 
     // Replace the user with a [HOneShotInterceptor].
-    HConstant nullConstant = graph.addConstantNull(constantSystem);
+    HConstant nullConstant = graph.addConstantNull(compiler);
     List<HInstruction> inputs = new List<HInstruction>.from(user.inputs);
     inputs[0] = nullConstant;
     HOneShotInterceptor interceptor = new HOneShotInterceptor(
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
index 5ea9e29..f86ac3c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -99,7 +99,8 @@
     HInstruction index = instruction.inputs[2];
     if (input == instruction.inputs[1] &&
         index.instructionType.canBePrimitiveNumber(compiler)) {
-      return HType.MUTABLE_ARRAY;
+      JavaScriptBackend backend = compiler.backend;
+      return backend.mutableArrayType;
     }
     // The index should be an int when the receiver is a string or array.
     // However it turns out that inserting an integer check in the optimized
@@ -133,7 +134,8 @@
     HInstruction index = instruction.inputs[2];
     if (input == instruction.inputs[1] &&
         index.instructionType.canBePrimitiveNumber(compiler)) {
-      return HType.INDEXABLE_PRIMITIVE;
+      JavaScriptBackend backend = compiler.backend;
+      return backend.indexablePrimitiveType;
     }
     // The index should be an int when the receiver is a string or array.
     // However it turns out that inserting an integer check in the optimized
@@ -182,7 +184,7 @@
                                   Compiler compiler) {
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
-    if (instruction.inputs[1].isPrimitiveOrNull()) return HType.INTEGER;
+    if (instruction.inputs[1].isPrimitiveOrNull(compiler)) return HType.INTEGER;
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
@@ -399,7 +401,7 @@
     // All bitwise operations on primitive types either produce an
     // integer or throw an error.
     HInstruction left = instruction.inputs[1];
-    if (left.isPrimitiveOrNull()) return HType.INTEGER;
+    if (left.isPrimitiveOrNull(compiler)) return HType.INTEGER;
     return super.computeTypeFromInputTypes(instruction, compiler);
   }
 
@@ -502,7 +504,7 @@
 
   HType computeTypeFromInputTypes(HInvokeDynamic instruction,
                                   Compiler compiler) {
-    if (instruction.inputs[1].instructionType.isPrimitiveOrNull()) {
+    if (instruction.inputs[1].instructionType.isPrimitiveOrNull(compiler)) {
       return HType.BOOLEAN;
     }
     return super.computeTypeFromInputTypes(instruction, compiler);
@@ -557,12 +559,13 @@
       return right.instructionType;
     }
     // String equality testing is much more common than array equality testing.
+    JavaScriptBackend backend = compiler.backend;
     if (input == left && left.isIndexablePrimitive(compiler)) {
-      return HType.READABLE_ARRAY;
+      return backend.readableArrayType;
     }
     // String equality testing is much more common than array equality testing.
     if (input == right && right.isIndexablePrimitive(compiler)) {
-      return HType.STRING;
+      return backend.stringType;
     }
     return HType.UNKNOWN;
   }
@@ -572,7 +575,7 @@
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     HType instructionType = left.instructionType;
-    if (right.isConstantNull() || instructionType.isPrimitiveOrNull()) {
+    if (right.isConstantNull() || instructionType.isPrimitiveOrNull(compiler)) {
       return newBuiltinVariant(instruction);
     }
     Selector selector = instructionType.refine(instruction.selector, compiler);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 915908f..3f47849 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -162,29 +162,26 @@
     return result;
   }
 
-  static HType mapConstantTypeToSsaType(Constant constant) {
+  static HType mapConstantTypeToSsaType(Constant constant, Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
     if (constant.isNull()) return HType.NULL;
     if (constant.isBool()) return HType.BOOLEAN;
     if (constant.isInt()) return HType.INTEGER;
     if (constant.isDouble()) return HType.DOUBLE;
-    if (constant.isString()) return HType.STRING;
-    if (constant.isList()) return HType.READABLE_ARRAY;
+    if (constant.isString()) return backend.stringType;
+    if (constant.isList()) return backend.readableArrayType;
     if (constant.isFunction()) return HType.UNKNOWN;
     if (constant.isSentinel()) return HType.UNKNOWN;
     // TODO(sra): What is the type of the prototype of an interceptor?
     if (constant.isInterceptor()) return HType.UNKNOWN;
-    // TODO(kasperl): This seems a bit fishy, but we do not have the
-    // compiler at hand so we cannot use the usual HType factory
-    // methods. At some point this should go away.
     ObjectConstant objectConstant = constant;
-    TypeMask mask = new TypeMask.nonNullExact(objectConstant.type);
-    return new HBoundedType(mask);
+    return new HBoundedType(new TypeMask.nonNullExact(objectConstant.type));
   }
 
-  HConstant addConstant(Constant constant) {
+  HConstant addConstant(Constant constant, Compiler compiler) {
     HConstant result = constants[constant];
     if (result == null) {
-      HType type = mapConstantTypeToSsaType(constant);
+      HType type = mapConstantTypeToSsaType(constant, compiler);
       result = new HConstant.internal(constant, type);
       entry.addAtExit(result);
       constants[constant] = result;
@@ -195,26 +192,30 @@
     return result;
   }
 
-  HConstant addConstantInt(int i, ConstantSystem constantSystem) {
-    return addConstant(constantSystem.createInt(i));
+  HConstant addConstantInt(int i, Compiler compiler) {
+    return addConstant(compiler.backend.constantSystem.createInt(i), compiler);
   }
 
-  HConstant addConstantDouble(double d, ConstantSystem constantSystem) {
-    return addConstant(constantSystem.createDouble(d));
+  HConstant addConstantDouble(double d, Compiler compiler) {
+    return addConstant(
+        compiler.backend.constantSystem.createDouble(d), compiler);
   }
 
   HConstant addConstantString(DartString str,
                               Node diagnosticNode,
-                              ConstantSystem constantSystem) {
-    return addConstant(constantSystem.createString(str, diagnosticNode));
+                              Compiler compiler) {
+    return addConstant(
+        compiler.backend.constantSystem.createString(str, diagnosticNode),
+        compiler);
   }
 
-  HConstant addConstantBool(bool value, ConstantSystem constantSystem) {
-    return addConstant(constantSystem.createBool(value));
+  HConstant addConstantBool(bool value, Compiler compiler) {
+    return addConstant(
+        compiler.backend.constantSystem.createBool(value), compiler);
   }
 
-  HConstant addConstantNull(ConstantSystem constantSystem) {
-    return addConstant(constantSystem.createNull());
+  HConstant addConstantNull(Compiler compiler) {
+    return addConstant(compiler.backend.constantSystem.createNull(), compiler);
   }
 
   void finalize() {
@@ -621,7 +622,9 @@
   void rewriteWithBetterUser(HInstruction from, HInstruction to) {
     Link<HCheck> better = const Link<HCheck>();
     for (HInstruction user in to.usedBy) {
-      if (user is HCheck && identical((user as HCheck).checkedInput, to)) {
+      if (user == from || user is! HCheck) continue;
+      HCheck check = user;
+      if (check.checkedInput == to) {
         better = better.prepend(user);
       }
     }
@@ -819,6 +822,10 @@
         && !canThrow();
   }
 
+  // Overridden by [HCheck] to return the actual non-[HCheck]
+  // instruction it checks against.
+  HInstruction nonCheck() => this;
+
   // Can this node throw an exception?
   bool canThrow() => false;
 
@@ -836,6 +843,12 @@
       instructionType.isExtendableArray(compiler);
   bool isFixedArray(Compiler compiler) =>
       instructionType.isFixedArray(compiler);
+  bool isString(Compiler compiler) =>
+      instructionType.isString(compiler);
+  bool isPrimitive(Compiler compiler) =>
+      instructionType.isPrimitive(compiler);
+  bool isPrimitiveOrNull(Compiler compiler) =>
+      instructionType.isPrimitiveOrNull(compiler);
   bool isBoolean() => instructionType.isBoolean();
   bool isInteger() => instructionType.isInteger();
   bool isIntegerOrNull() => instructionType.isIntegerOrNull();
@@ -843,9 +856,6 @@
   bool isDoubleOrNull() => instructionType.isDoubleOrNull();
   bool isNumber() => instructionType.isNumber();
   bool isNumberOrNull() => instructionType.isNumberOrNull();
-  bool isString() => instructionType.isString();
-  bool isPrimitive() => instructionType.isPrimitive();
-  bool isPrimitiveOrNull() => instructionType.isPrimitiveOrNull();
   bool isNull() => instructionType.isNull();
   bool canBeNull() => instructionType.canBeNull();
   bool canBePrimitive(Compiler compiler) =>
@@ -901,7 +911,9 @@
     final List<HInstruction> otherInputs = other.inputs;
     if (inputsLength != otherInputs.length) return false;
     for (int i = 0; i < inputsLength; i++) {
-      if (!identical(inputs[i], otherInputs[i])) return false;
+      if (!identical(inputs[i].nonCheck(), otherInputs[i].nonCheck())) {
+        return false;
+      }
     }
     // Check that the data in the instruction matches.
     return dataEquals(other);
@@ -911,7 +923,7 @@
     int result = typeCode();
     int length = inputs.length;
     for (int i = 0; i < length; i++) {
-      result = (result * 19) + (inputs[i].id) + (result >> 7);
+      result = (result * 19) + (inputs[i].nonCheck().id) + (result >> 7);
     }
     return result;
   }
@@ -1158,11 +1170,7 @@
   bool isJsStatement() => true;
   bool canThrow() => true;
 
-  HInstruction unwrap() {
-    var checked = checkedInput;
-    while (checked is HCheck) checked = checked.checkedInput;
-    return checked;
-  }
+  HInstruction nonCheck() => checkedInput.nonCheck();
 }
 
 class HBailoutTarget extends HInstruction {
@@ -1320,7 +1328,11 @@
   int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
   bool typeEquals(other) => other is HInvokeDynamic;
   bool dataEquals(HInvokeDynamic other) {
-    return selector == other.selector && element == other.element;
+    // Use the name and the kind instead of [Selector.operator==]
+    // because we don't need to check the arity (already checked in
+    // [gvnEquals]), and the receiver types may not be in sync.
+    return selector.name == other.selector.name
+        && selector.kind == other.selector.kind;
   }
 }
 
@@ -2137,8 +2149,8 @@
 }
 
 class HLiteralList extends HInstruction {
-  HLiteralList(inputs) : super(inputs) {
-    instructionType = HType.EXTENDABLE_ARRAY;
+  HLiteralList(List<HInstruction> inputs, HType type) : super(inputs) {
+    instructionType = type;
   }
   toString() => 'literal list';
   accept(HVisitor visitor) => visitor.visitLiteralList(this);
@@ -2291,6 +2303,7 @@
 
   int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
   bool typeEquals(HInstruction other) => other is HTypeConversion;
+  bool isCodeMotionInvariant() => kind == NO_CHECK;
 
   bool dataEquals(HTypeConversion other) {
     return kind == other.kind
@@ -2310,13 +2323,13 @@
 
 class HStringConcat extends HInstruction {
   final Node node;
-  HStringConcat(HInstruction left, HInstruction right, this.node)
+  HStringConcat(HInstruction left, HInstruction right, this.node, HType type)
       : super(<HInstruction>[left, right]) {
     // TODO(sra): Until Issue 9293 is fixed, this false dependency keeps the
     // concats bunched with stringified inputs for much better looking code with
     // fewer temps.
     sideEffects.setDependsOnSomething();
-    instructionType = HType.STRING;
+    instructionType = type;
   }
 
   HInstruction get left => inputs[0];
@@ -2332,10 +2345,11 @@
  */
 class HStringify extends HInstruction {
   final Node node;
-  HStringify(HInstruction input, this.node) : super(<HInstruction>[input]) {
+  HStringify(HInstruction input, this.node, HType type)
+      : super(<HInstruction>[input]) {
     sideEffects.setAllSideEffects();
     sideEffects.setDependsOnSomething();
-    instructionType = HType.STRING;
+    instructionType = type;
   }
 
   accept(HVisitor visitor) => visitor.visitStringify(this);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index 68d1455..c61ff48 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -195,7 +195,7 @@
     // TODO(kasperl): Get rid of the null check here once all HTypes
     // have a proper mask.
     if (mask != null && !mask.contains(booleanType, compiler)) {
-      return graph.addConstantBool(false, constantSystem);
+      return graph.addConstantBool(false, compiler);
     }
     return node;
   }
@@ -207,7 +207,7 @@
     if (input is HConstant) {
       HConstant constant = input;
       bool isTrue = constant.constant.isTrue();
-      return graph.addConstantBool(!isTrue, constantSystem);
+      return graph.addConstantBool(!isTrue, compiler);
     } else if (input is HNot) {
       return input.inputs[0];
     }
@@ -224,7 +224,7 @@
     if (operand is HConstant) {
       HConstant receiver = operand;
       Constant folded = operation.fold(receiver.constant);
-      if (folded != null) return graph.addConstant(folded);
+      if (folded != null) return graph.addConstant(folded, compiler);
     }
     return null;
   }
@@ -235,15 +235,15 @@
       if (actualReceiver.isConstantString()) {
         HConstant constantInput = actualReceiver;
         StringConstant constant = constantInput.constant;
-        return graph.addConstantInt(constant.length, constantSystem);
+        return graph.addConstantInt(constant.length, compiler);
       } else if (actualReceiver.isConstantList()) {
         HConstant constantInput = actualReceiver;
         ListConstant constant = constantInput.constant;
-        return graph.addConstantInt(constant.length, constantSystem);
+        return graph.addConstantInt(constant.length, compiler);
       }
       Element element = backend.jsIndexableLength;
       bool isAssignable = !actualReceiver.isFixedArray(compiler) &&
-          !actualReceiver.isString();
+          !actualReceiver.isString(compiler);
       HFieldGet result = new HFieldGet(
           element, actualReceiver, isAssignable: isAssignable);
       result.instructionType = HType.INTEGER;
@@ -251,7 +251,7 @@
     } else if (actualReceiver.isConstantMap()) {
       HConstant constantInput = actualReceiver;
       MapConstant constant = constantInput.constant;
-      return graph.addConstantInt(constant.length, constantSystem);
+      return graph.addConstantInt(constant.length, compiler);
     }
     return null;
   }
@@ -286,13 +286,13 @@
             target = backend.jsArrayAdd;
           }
         }
-      } else if (input.isString()) {
+      } else if (input.isString(compiler)) {
         if (selector.applies(backend.jsStringSplit, compiler)) {
-          if (node.inputs[2].isString()) {
+          if (node.inputs[2].isString(compiler)) {
             target = backend.jsStringSplit;
           }
         } else if (selector.applies(backend.jsStringConcat, compiler)) {
-          if (node.inputs[2].isString()) {
+          if (node.inputs[2].isString(compiler)) {
             target = backend.jsStringConcat;
           }
         } else if (selector.applies(backend.jsStringToString, compiler)) {
@@ -439,7 +439,7 @@
       HConstant op1 = left;
       HConstant op2 = right;
       Constant folded = operation.fold(op1.constant, op2.constant);
-      if (folded != null) return graph.addConstant(folded);
+      if (folded != null) return graph.addConstant(folded, compiler);
     }
     return null;
   }
@@ -482,11 +482,11 @@
     // we don't optimize on numbers to preserve the runtime semantics.
     if (!(left.isNumberOrNull() && right.isNumberOrNull()) &&
         leftType.intersection(rightType, compiler).isConflicting()) {
-      return graph.addConstantBool(false, constantSystem);
+      return graph.addConstantBool(false, compiler);
     }
 
     if (left.isNull() && right.isNull()) {
-      return graph.addConstantBool(true, constantSystem);
+      return graph.addConstantBool(true, compiler);
     }
 
     if (left.isConstantBoolean() && right.isBoolean()) {
@@ -538,7 +538,7 @@
     }
 
     if (element == compiler.objectClass || element == compiler.dynamicClass) {
-      return graph.addConstantBool(true, constantSystem);
+      return graph.addConstantBool(true, compiler);
     }
 
     HType expressionType = node.expression.instructionType;
@@ -546,40 +546,33 @@
       if (identical(element, compiler.intClass)
           || identical(element, compiler.numClass)
           || Elements.isNumberOrStringSupertype(element, compiler)) {
-        return graph.addConstantBool(true, constantSystem);
+        return graph.addConstantBool(true, compiler);
       } else if (identical(element, compiler.doubleClass)) {
         // We let the JS semantics decide for that check. Currently
         // the code we emit will always return true.
         return node;
       } else {
-        return graph.addConstantBool(false, constantSystem);
+        return graph.addConstantBool(false, compiler);
       }
     } else if (expressionType.isDouble()) {
       if (identical(element, compiler.doubleClass)
           || identical(element, compiler.numClass)
           || Elements.isNumberOrStringSupertype(element, compiler)) {
-        return graph.addConstantBool(true, constantSystem);
+        return graph.addConstantBool(true, compiler);
       } else if (identical(element, compiler.intClass)) {
         // We let the JS semantics decide for that check. Currently
         // the code we emit will return true for a double that can be
         // represented as a 31-bit integer and for -0.0.
         return node;
       } else {
-        return graph.addConstantBool(false, constantSystem);
+        return graph.addConstantBool(false, compiler);
       }
     } else if (expressionType.isNumber()) {
       if (identical(element, compiler.numClass)) {
-        return graph.addConstantBool(true, constantSystem);
-      }
-      // We cannot just return false, because the expression may be of
-      // type int or double.
-    } else if (expressionType.isString()) {
-      if (identical(element, compiler.stringClass)
-               || Elements.isStringOnlySupertype(element, compiler)
-               || Elements.isNumberOrStringSupertype(element, compiler)) {
-        return graph.addConstantBool(true, constantSystem);
+        return graph.addConstantBool(true, compiler);
       } else {
-        return graph.addConstantBool(false, constantSystem);
+        // We cannot just return false, because the expression may be of
+        // type int or double.
       }
     // We need the [:hasTypeArguments:] check because we don't have
     // the notion of generics in the backend. For example, [:this:] in
@@ -589,9 +582,9 @@
       TypeMask expressionMask = expressionType.computeMask(compiler);
       TypeMask typeMask = new TypeMask.nonNullSubtype(type);
       if (expressionMask.union(typeMask, compiler) == typeMask) {
-        return graph.addConstantBool(true, constantSystem);
+        return graph.addConstantBool(true, compiler);
       } else if (expressionMask.intersection(typeMask, compiler).isEmpty) {
-        return graph.addConstantBool(false, constantSystem);
+        return graph.addConstantBool(false, compiler);
       }
     }
     return node;
@@ -637,7 +630,7 @@
                  node.receiver.isConstantString()) {
         var instruction = node.receiver;
         return graph.addConstantInt(
-            instruction.constant.length, backend.constantSystem);
+            instruction.constant.length, compiler);
       }
     }
     return node;
@@ -650,7 +643,7 @@
       instruction = node.index;
       int index = instruction.constant.value;
       if (index >= 0 && index < entries.length) {
-        return graph.addConstant(entries[index]);
+        return graph.addConstant(entries[index], compiler);
       }
     }
     return node;
@@ -760,23 +753,24 @@
       if (leftString == null) return node;
     }
 
-    HInstruction folded =
-        graph.addConstant(constantSystem.createString(
+    HInstruction folded = graph.addConstant(
+        constantSystem.createString(
             new DartString.concat(leftString.value, rightString.value),
-            node.node));
+            node.node),
+        compiler);
     if (prefix == null) return folded;
-    return new HStringConcat(prefix, folded, node.node);
+    return new HStringConcat(prefix, folded, node.node, backend.stringType);
   }
 
   HInstruction visitStringify(HStringify node) {
     HInstruction input = node.inputs[0];
-    if (input.isString()) return input;
+    if (input.isString(compiler) && !input.canBeNull()) return input;
     if (input.isConstant()) {
       HConstant constant = input;
       if (!constant.constant.isPrimitive()) return node;
       PrimitiveConstant primitive = constant.constant;
       return graph.addConstant(constantSystem.createString(
-          primitive.toDartString(), node.node));
+          primitive.toDartString(), node.node), compiler);
     }
     return node;
   }
@@ -814,8 +808,9 @@
   HBoundsCheck insertBoundsCheck(HInstruction indexNode,
                                  HInstruction array,
                                  HInstruction indexArgument) {
+    Compiler compiler = backend.compiler;
     bool isAssignable =
-        !array.isFixedArray(backend.compiler) && !array.isString();
+        !array.isFixedArray(compiler) && !array.isString(compiler);
     HFieldGet length = new HFieldGet(
         backend.jsIndexableLength, array, isAssignable: isAssignable);
     length.instructionType = HType.INTEGER;
@@ -855,7 +850,7 @@
     if (element != backend.jsArrayRemoveLast) return;
     if (boundsChecked.contains(node)) return;
     insertBoundsCheck(
-        node, node.receiver, graph.addConstantInt(0, backend.constantSystem));
+        node, node.receiver, graph.addConstantInt(0, backend.compiler));
   }
 }
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index c603386..f408df4 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -14,6 +14,7 @@
 const String SSA_TRACE_FILTER = null;
 
 class HTracer extends HGraphVisitor implements Tracer {
+  Compiler compiler;
   JavaScriptItemCompilationContext context;
   int indent = 0;
   final EventSink<String> output;
@@ -27,9 +28,11 @@
   }
 
   void traceCompilation(String methodName,
-                        JavaScriptItemCompilationContext compilationContext) {
+                        JavaScriptItemCompilationContext compilationContext,
+                        Compiler compiler) {
     if (!enabled) return;
     this.context = compilationContext;
+    this.compiler = compiler;
     traceActive =
         SSA_TRACE_FILTER == null || methodName.contains(SSA_TRACE_FILTER);
     if (!traceActive) return;
@@ -92,7 +95,7 @@
 
   void visitBasicBlock(HBasicBlock block) {
     HInstructionStringifier stringifier =
-        new HInstructionStringifier(context, block);
+        new HInstructionStringifier(context, block, compiler);
     assert(block.id != null);
     tag("block", () {
       printProperty("name", "B${block.id}");
@@ -165,21 +168,22 @@
 }
 
 class HInstructionStringifier implements HVisitor<String> {
-  JavaScriptItemCompilationContext context;
-  HBasicBlock currentBlock;
+  final Compiler compiler;
+  final JavaScriptItemCompilationContext context;
+  final HBasicBlock currentBlock;
 
-  HInstructionStringifier(this.context, this.currentBlock);
+  HInstructionStringifier(this.context, this.currentBlock, this.compiler);
 
   visit(HInstruction node) => node.accept(this);
 
   String temporaryId(HInstruction instruction) {
     String prefix;
     HType type = instruction.instructionType;
-    if (type == HType.MUTABLE_ARRAY) {
+    if (type.isMutableArray(compiler)) {
       prefix = 'm';
-    } else if (type == HType.READABLE_ARRAY) {
+    } else if (type.isReadableArray(compiler)) {
       prefix = 'a';
-    } else if (type == HType.EXTENDABLE_ARRAY) {
+    } else if (type.isExtendableArray(compiler)) {
       prefix = 'e';
     } else if (type == HType.BOOLEAN) {
       prefix = 'b';
@@ -189,13 +193,13 @@
       prefix = 'd';
     } else if (type == HType.NUMBER) {
       prefix = 'n';
-    } else if (type == HType.STRING) {
+    } else if (type.isString(compiler)) {
       prefix = 's';
     } else if (type == HType.UNKNOWN) {
       prefix = 'v';
     } else if (type == HType.CONFLICTING) {
       prefix = 'c';
-    } else if (type == HType.INDEXABLE_PRIMITIVE) {
+    } else if (type.isIndexable(compiler)) {
       prefix = 'r';
     } else if (type == HType.NULL) {
       prefix = 'u';
@@ -505,12 +509,12 @@
   String visitTypeGuard(HTypeGuard node) {
     String type;
     HType guardedType = node.guardedType;
-    if (guardedType == HType.MUTABLE_ARRAY) {
-      type = "mutable_array";
-    } else if (guardedType == HType.READABLE_ARRAY) {
-      type = "readable_array";
-    } else if (guardedType == HType.EXTENDABLE_ARRAY) {
+    if (guardedType.isExtendableArray(compiler)) {
       type = "extendable_array";
+    } else if (guardedType.isMutableArray(compiler)) {
+      type = "mutable_array";
+    } else if (guardedType.isReadableArray(compiler)) {
+      type = "readable_array";
     } else if (guardedType == HType.BOOLEAN) {
       type = "bool";
     } else if (guardedType == HType.INTEGER) {
@@ -519,9 +523,9 @@
       type = "double";
     } else if (guardedType == HType.NUMBER) {
       type = "number";
-    } else if (guardedType == HType.STRING) {
+    } else if (guardedType.isString(compiler)) {
       type = "string";
-    } else if (guardedType == HType.INDEXABLE_PRIMITIVE) {
+    } else if (guardedType.isIndexable(compiler)) {
       type = "string_or_array";
     } else if (guardedType == HType.UNKNOWN) {
       type = 'unknown';
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index 06fa93d..ff49492 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -27,7 +27,12 @@
                || mask.satisfies(backend.jsNumberClass, compiler)) {
       return isNullable ? HType.NUMBER_OR_NULL : HType.NUMBER;
     } else if (mask.containsOnlyString(compiler)) {
-      return isNullable ? HType.STRING_OR_NULL : HType.STRING;
+      // TODO(ngeoffray): Avoid creating [TypeMask]s with the string
+      // class as base.
+      return isNullable
+          ? new HBoundedType(
+                  new TypeMask.exact(backend.jsStringClass.rawType))
+          : backend.stringType;
     } else if (mask.containsOnlyBool(compiler)) {
       return isNullable ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN;
     } else if (mask.containsOnlyNull(compiler)) {
@@ -40,19 +45,6 @@
       return isNullable ? HType.UNKNOWN : HType.NON_NULL;
     }
 
-    if (!isNullable) {
-      if (mask.containsOnly(backend.jsFixedArrayClass)) {
-        return HType.FIXED_ARRAY;
-      } else if (mask.containsOnly(backend.jsExtendableArrayClass)) {
-        return HType.EXTENDABLE_ARRAY;
-      } else if (mask.satisfies(backend.jsMutableArrayClass, compiler)) {
-        return HType.MUTABLE_ARRAY;
-      } else if (mask.satisfies(backend.jsArrayClass, compiler)) {
-        return HType.READABLE_ARRAY;
-      } else if (mask.satisfies(backend.jsIndexableClass, compiler)) {
-        return HType.INDEXABLE_PRIMITIVE;
-      }
-    }
     return new HBoundedType(mask);
   }
 
@@ -134,7 +126,8 @@
       return new HType.nonNullExact(
           compiler.objectClass.computeType(compiler), compiler);
     } else if (type == native.SpecialType.JsArray) {
-      return HType.READABLE_ARRAY;
+      JavaScriptBackend backend = compiler.backend;
+      return backend.readableArrayType;
     } else if (type.isVoid) {
       return HType.NULL;
     } else if (type.element == compiler.nullClass) {
@@ -157,19 +150,12 @@
   static const HType NUMBER = const HNumberType();
   static const HType INTEGER = const HIntegerType();
   static const HType DOUBLE = const HDoubleType();
-  static const HType INDEXABLE_PRIMITIVE = const HIndexablePrimitiveType();
-  static const HType STRING = const HStringType();
-  static const HType READABLE_ARRAY = const HReadableArrayType();
-  static const HType MUTABLE_ARRAY = const HMutableArrayType();
-  static const HType FIXED_ARRAY = const HFixedArrayType();
-  static const HType EXTENDABLE_ARRAY = const HExtendableArrayType();
   static const HType NULL = const HNullType();
 
   static const HType BOOLEAN_OR_NULL = const HBooleanOrNullType();
   static const HType NUMBER_OR_NULL = const HNumberOrNullType();
   static const HType INTEGER_OR_NULL = const HIntegerOrNullType();
   static const HType DOUBLE_OR_NULL = const HDoubleOrNullType();
-  static const HType STRING_OR_NULL = const HStringOrNullType();
 
   bool isConflicting() => identical(this, CONFLICTING);
   bool isUnknown() => identical(this, UNKNOWN);
@@ -179,20 +165,19 @@
   bool isNumber() => false;
   bool isInteger() => false;
   bool isDouble() => false;
-  bool isString() => false;
 
+  bool isString(Compiler compiler) => false;
   bool isFixedArray(Compiler compiler) => false;
   bool isReadableArray(Compiler compiler) => false;
   bool isMutableArray(Compiler compiler) => false;
   bool isExtendableArray(Compiler compiler) => false;
+  bool isPrimitive(Compiler compiler) => false;
+  bool isPrimitiveOrNull(Compiler compiler) => false;
 
-  bool isPrimitive() => false;
   bool isBooleanOrNull() => false;
   bool isNumberOrNull() => false;
   bool isIntegerOrNull() => false;
   bool isDoubleOrNull() => false;
-  bool isStringOrNull() => false;
-  bool isPrimitiveOrNull() => false;
 
   // TODO(kasperl): Get rid of this one.
   bool isIndexablePrimitive(Compiler compiler) => false;
@@ -326,9 +311,9 @@
 
 abstract class HPrimitiveType extends HType {
   const HPrimitiveType();
-  bool isPrimitive() => true;
+  bool isPrimitive(Compiler compiler) => true;
   bool canBePrimitive(Compiler compiler) => true;
-  bool isPrimitiveOrNull() => true;
+  bool isPrimitiveOrNull(Compiler compiler) => true;
 }
 
 class HNullType extends HPrimitiveType {
@@ -347,7 +332,7 @@
   const HPrimitiveOrNullType();
   bool canBePrimitive(Compiler compiler) => true;
   bool canBeNull() => true;
-  bool isPrimitiveOrNull() => true;
+  bool isPrimitiveOrNull(Compiler compiler) => true;
 }
 
 class HBooleanOrNullType extends HPrimitiveOrNullType {
@@ -457,97 +442,6 @@
   }
 }
 
-class HIndexablePrimitiveType extends HPrimitiveType {
-  const HIndexablePrimitiveType();
-  bool isIndexablePrimitive(Compiler compiler) => true;
-  String toString() => "indexable";
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    DartType base = backend.jsIndexableClass.computeType(compiler);
-    return new TypeMask.nonNullSubtype(base);
-  }
-}
-
-class HStringOrNullType extends HPrimitiveOrNullType {
-  const HStringOrNullType();
-  bool isStringOrNull() => true;
-  String toString() => "String or null";
-  bool canBePrimitiveString(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    DartType base = backend.jsStringClass.computeType(compiler);
-    return new TypeMask.exact(base);
-  }
-}
-
-class HStringType extends HIndexablePrimitiveType {
-  const HStringType();
-  bool isString() => true;
-  bool isStringOrNull() => true;
-  String toString() => "String";
-  bool isExact() => true;
-  bool canBePrimitiveString(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    DartType base = backend.jsStringClass.computeType(compiler);
-    return new TypeMask.nonNullExact(base);
-  }
-}
-
-class HReadableArrayType extends HIndexablePrimitiveType {
-  const HReadableArrayType();
-  bool isReadableArray(Compiler compiler) => true;
-  String toString() => "readable array";
-  bool canBePrimitiveArray(Compiler compiler) => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    DartType base = backend.jsArrayClass.computeType(compiler);
-    return new TypeMask.nonNullSubclass(base);
-  }
-}
-
-class HMutableArrayType extends HReadableArrayType {
-  const HMutableArrayType();
-  bool isMutableArray(Compiler compiler) => true;
-  String toString() => "mutable array";
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    DartType base = backend.jsMutableArrayClass.computeType(compiler);
-    return new TypeMask.nonNullSubclass(base);
-  }
-}
-
-class HFixedArrayType extends HMutableArrayType {
-  const HFixedArrayType();
-  bool isFixedArray(Compiler compiler) => true;
-  String toString() => "fixed array";
-  bool isExact() => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    DartType base = backend.jsFixedArrayClass.computeType(compiler);
-    return new TypeMask.nonNullExact(base);
-  }
-}
-
-class HExtendableArrayType extends HMutableArrayType {
-  const HExtendableArrayType();
-  bool isExtendableArray(Compiler compiler) => true;
-  String toString() => "extendable array";
-  bool isExact() => true;
-
-  TypeMask computeMask(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    DartType base = backend.jsExtendableArrayClass.computeType(compiler);
-    return new TypeMask.nonNullExact(base);
-  }
-}
-
 class HBoundedType extends HType {
   final TypeMask mask;
   const HBoundedType(this.mask);
@@ -591,8 +485,7 @@
 
   bool isIndexablePrimitive(Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
-    return mask.containsOnlyString(compiler)
-        || mask.satisfies(backend.jsIndexableClass, compiler);
+    return mask.satisfies(backend.jsIndexableClass, compiler);
   }
 
   bool isFixedArray(Compiler compiler) {
@@ -627,6 +520,18 @@
     return new HType.fromMask(mask.simplify(compiler), compiler);
   }
 
+  bool isString(Compiler compiler) {
+    return mask.containsOnlyString(compiler);
+  }
+
+  bool isPrimitive(Compiler compiler) {
+    return isIndexablePrimitive(compiler) && !mask.isNullable;
+  }
+
+  bool isPrimitiveOrNull(Compiler compiler) {
+    return isIndexablePrimitive(compiler);
+  }
+
   bool operator ==(HType other) {
     if (other is !HBoundedType) return false;
     HBoundedType bounded = other;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 6eed301..d2ef66c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -355,7 +355,7 @@
     }
     // TODO(ngeoffray): Allow speculative optimizations on
     // non-primitive types?
-    if (!desiredType.isPrimitive()) return newType;
+    if (!desiredType.isPrimitive(compiler)) return newType;
     desiredType = newType.intersection(desiredType, compiler);
     if (desiredType != newType && !hasBeenSpeculativelyOptimized(instruction)) {
       savedTypes[instruction] = oldType;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
index 092a99c..e067089 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
@@ -714,11 +714,11 @@
       handleEqualityCheck(relational);
     } else if (operation.apply(leftRange, rightRange)) {
       relational.block.rewrite(
-          relational, graph.addConstantBool(true, constantSystem));
+          relational, graph.addConstantBool(true, compiler));
       relational.block.remove(relational);
     } else if (reverseOperation(operation).apply(leftRange, rightRange)) {
       relational.block.rewrite(
-          relational, graph.addConstantBool(false, constantSystem));
+          relational, graph.addConstantBool(false, compiler));
       relational.block.remove(relational);
     }
     return info.newUnboundRange();
@@ -729,7 +729,7 @@
     Range left = ranges[node.left];
     if (left.isSingleValue && right.isSingleValue && left == right) {
       node.block.rewrite(
-          node, graph.addConstantBool(true, constantSystem));
+          node, graph.addConstantBool(true, compiler));
       node.block.remove(node);
     }
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
index aef770f..3df538d 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/variable_allocator.dart
@@ -233,7 +233,7 @@
       // [HCheck] will share the same live ranges.
       if (instruction is HCheck) {
         HCheck check = instruction;
-        HInstruction checked = check.unwrap();
+        HInstruction checked = check.nonCheck();
         if (!generateAtUseSite.contains(checked)) {
           environment.add(checked, instructionId);
         }
@@ -248,7 +248,7 @@
     // interval as the instruction it is checking.
     if (instruction is HCheck) {
       HCheck check = instruction;
-      HInstruction checked = check.unwrap();
+      HInstruction checked = check.nonCheck();
       if (!generateAtUseSite.contains(checked)) {
         liveIntervals.putIfAbsent(checked, () => new LiveInterval());
         // Unconditionally force the live ranges of the HCheck to
@@ -625,12 +625,7 @@
     if (instruction is HParameterValue) return true;
     if (instruction.usedBy.isEmpty) return false;
     if (generateAtUseSite.contains(instruction)) return false;
-    // A [HCheck] instruction needs a name only if its
-    // checked input does not have a fixed name or value.
-    if (instruction is HCheck) {
-      return !instruction.unwrap().isCodeMotionInvariant();
-    }
-    return true;
+    return !instruction.nonCheck().isCodeMotionInvariant();
   }
 
   /**
diff --git a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
index 59f6874..a318d0e 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -130,18 +130,9 @@
   }
 
   bool satisfies(ClassElement cls, Compiler compiler) {
-    if (isEmpty) {
-      return false;
-    } else if (base.element == cls) {
-      return true;
-    } else if (isExact) {
-      return false;
-    } else if (isSubclass) {
-      return isSubclassOf(base, cls.computeType(compiler).asRaw(), compiler);
-    } else {
-      assert(isSubtype);
-      return isSubtypeOf(base, cls.computeType(compiler).asRaw(), compiler);
-    }
+    if (isEmpty) return false;
+    return base.element == cls
+        || isSubtypeOf(base, cls.computeType(compiler).asRaw(), compiler);
   }
 
   /**
diff --git a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
new file mode 100644
index 0000000..68aa7ce
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
@@ -0,0 +1,728 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of simple_types_inferrer;
+
+TypeMask narrowType(TypeMask type,
+                    DartType annotation,
+                    Compiler compiler,
+                    {bool isNullable: true}) {
+  if (annotation.isDynamic) return type;
+  if (annotation.isMalformed) return type;
+  if (annotation.isVoid) return compiler.typesTask.typesInferrer.nullType;
+  if (annotation.element == compiler.objectClass) return type;
+  TypeMask otherType;
+  if (annotation.kind == TypeKind.TYPEDEF
+      || annotation.kind == TypeKind.FUNCTION) {
+    otherType = compiler.typesTask.typesInferrer.functionType;
+  } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
+    return type;
+  } else {
+    assert(annotation.kind == TypeKind.INTERFACE);
+    otherType = new TypeMask.nonNullSubtype(annotation);
+  }
+  if (isNullable) otherType = otherType.nullable();
+  if (type == null) return otherType;
+  return type.intersection(otherType, compiler);
+}
+
+/**
+ * Returns the least upper bound between [firstType] and
+ * [secondType].
+ */
+ TypeMask computeLUB(TypeMask firstType,
+                     TypeMask secondType,
+                     Compiler compiler) {
+  TypesInferrer inferrer = compiler.typesTask.typesInferrer;
+  TypeMask dynamicType = inferrer.dynamicType;
+  if (firstType == null) {
+    return secondType;
+  } else if (secondType == dynamicType) {
+    return secondType;
+  } else if (firstType == dynamicType) {
+    return firstType;
+  } else {
+    TypeMask union = firstType.union(secondType, compiler);
+    // TODO(kasperl): If the union isn't nullable it seems wasteful
+    // to use dynamic. Fix that.
+    return union.containsAll(compiler) ? dynamicType : union;
+  }
+}
+
+/**
+ * Placeholder for inferred types of local variables.
+ */
+class LocalsHandler {
+  final InternalSimpleTypesInferrer inferrer;
+  final Map<Element, TypeMask> locals;
+  final Map<Element, Element> capturedAndBoxed;
+  final Map<Element, TypeMask> fieldsInitializedInConstructor;
+  final bool inTryBlock;
+  bool isThisExposed;
+  bool seenReturn = false;
+  bool seenBreakOrContinue = false;
+
+  bool get aborts {
+    return seenReturn || seenBreakOrContinue;
+  }
+
+  LocalsHandler(this.inferrer)
+      : locals = new Map<Element, TypeMask>(),
+        capturedAndBoxed = new Map<Element, Element>(),
+        fieldsInitializedInConstructor = new Map<Element, TypeMask>(),
+        inTryBlock = false,
+        isThisExposed = true;
+  LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
+      : locals = new Map<Element, TypeMask>.from(other.locals),
+        capturedAndBoxed = new Map<Element, Element>.from(
+            other.capturedAndBoxed),
+        fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
+            other.fieldsInitializedInConstructor),
+        inTryBlock = other.inTryBlock || inTryBlock,
+        inferrer = other.inferrer,
+        isThisExposed = other.isThisExposed;
+
+  TypeMask use(Element local) {
+    if (capturedAndBoxed.containsKey(local)) {
+      return inferrer.getTypeOfElement(capturedAndBoxed[local]);
+    }
+    return locals[local];
+  }
+
+  void update(Element local, TypeMask type) {
+    assert(type != null);
+    Compiler compiler = inferrer.compiler;
+    if (compiler.trustTypeAnnotations || compiler.enableTypeAssertions) {
+      type = narrowType(type, local.computeType(compiler), compiler);
+    }
+    if (capturedAndBoxed.containsKey(local) || inTryBlock) {
+      // If a local is captured and boxed, or is set in a try block,
+      // we compute the LUB of its assignments.
+      //
+      // We don't know if an assignment in a try block
+      // will be executed, so all assigments in that block are
+      // potential types after we have left it.
+      type = computeLUB(locals[local], type, compiler);
+    }
+    locals[local] = type;
+  }
+
+  void setCapturedAndBoxed(Element local, Element field) {
+    capturedAndBoxed[local] = field;
+  }
+
+  /**
+   * Merge handlers [first] and [second] into [:this:] and returns
+   * whether the merge changed one of the variables types in [first].
+   */
+  bool merge(LocalsHandler other, {bool discardIfAborts: true}) {
+    bool changed = false;
+    List<Element> toRemove = <Element>[];
+    // Iterating over a map and just updating its entries is OK.
+    locals.forEach((Element local, TypeMask oldType) {
+      TypeMask otherType = other.locals[local];
+      bool isCaptured = capturedAndBoxed.containsKey(local);
+      if (otherType == null) {
+        if (!isCaptured) {
+          // If [local] is not in the other map and is not captured
+          // and boxed, we know it is not a
+          // local we want to keep. For example, in an if/else, we don't
+          // want to keep variables declared in the if or in the else
+          // branch at the merge point.
+          toRemove.add(local);
+        }
+        return;
+      }
+      if (!isCaptured && aborts && discardIfAborts) {
+        locals[local] = otherType;
+      } else if (!isCaptured && other.aborts && discardIfAborts) {
+        // Don't do anything.
+      } else {
+        TypeMask type = computeLUB(oldType, otherType, inferrer.compiler);
+        if (type != oldType) changed = true;
+        locals[local] = type;
+      }
+    });
+
+    // Remove locals that will not be used anymore.
+    toRemove.forEach((Element element) {
+      locals.remove(element);
+    });
+
+    // Update the locals that are captured and boxed. We
+    // unconditionally add them to [this] because we register the type
+    // of boxed variables after analyzing all closures.
+    other.capturedAndBoxed.forEach((Element local, Element field) {
+      capturedAndBoxed[local] =  field;
+      // If [element] is not in our [locals], we need to update it.
+      // Otherwise, we have already computed the LUB of it.
+      if (locals[local] == null) {
+        locals[local] = other.locals[local];
+      }
+    });
+
+    // Merge instance fields initialized in both handlers. This is
+    // only relevant for generative constructors.
+    toRemove = <Element>[];
+    // Iterate over the map in [:this:]. The map in [other] may
+    // contain different fields, but if this map does not contain it,
+    // then we know the field can be null and we don't need to track
+    // it.
+    fieldsInitializedInConstructor.forEach((Element element, TypeMask type) {
+      TypeMask otherType = other.fieldsInitializedInConstructor[element];
+      if (otherType == null) {
+        toRemove.add(element);
+      } else {
+        fieldsInitializedInConstructor[element] =
+            computeLUB(type, otherType, inferrer.compiler);
+      }
+    });
+    // Remove fields that were not initialized in [other].
+    toRemove.forEach((Element element) {
+      fieldsInitializedInConstructor.remove(element);
+    });
+    isThisExposed = isThisExposed || other.isThisExposed;
+    seenReturn = seenReturn && other.seenReturn;
+    seenBreakOrContinue = seenBreakOrContinue && other.seenBreakOrContinue;
+
+    return changed;
+  }
+
+  void updateField(Element element, TypeMask type) {
+    if (isThisExposed) return;
+    fieldsInitializedInConstructor[element] = type;
+  }
+}
+
+abstract class InferrerVisitor extends ResolvedVisitor<TypeMask> {
+  final Element analyzedElement;
+  final InternalSimpleTypesInferrer inferrer;
+  final Compiler compiler;
+  final Map<TargetElement, List<LocalsHandler>> breaksFor =
+      new Map<TargetElement, List<LocalsHandler>>();
+  final Map<TargetElement, List<LocalsHandler>> continuesFor =
+      new Map<TargetElement, List<LocalsHandler>>();
+  LocalsHandler locals;
+
+  bool accumulateIsChecks = false;
+  bool conditionIsSimple = false;
+  List<Send> isChecks;
+  int loopLevel = 0;
+
+  bool get inLoop => loopLevel > 0;
+  bool get isThisExposed => locals.isThisExposed;
+  void set isThisExposed(value) { locals.isThisExposed = value; }
+
+  InferrerVisitor(Element analyzedElement,
+                  this.inferrer,
+                  Compiler compiler,
+                  this.locals)
+    : this.compiler = compiler,
+      this.analyzedElement = analyzedElement,
+      super(compiler.enqueuer.resolution.getCachedElements(analyzedElement));
+
+  TypeMask visitSendSet(SendSet node);
+
+  TypeMask visitSuperSend(Send node);
+
+  TypeMask visitStaticSend(Send node);
+
+  TypeMask visitGetterSend(Send node);
+
+  TypeMask visitClosureSend(Send node);
+
+  TypeMask visitDynamicSend(Send node);
+
+  TypeMask visitForIn(ForIn node);
+
+  TypeMask visitReturn(Return node);
+
+  TypeMask visitNode(Node node) {
+    node.visitChildren(this);
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitNewExpression(NewExpression node) {
+    return node.send.accept(this);
+  }
+
+  TypeMask visit(Node node) {
+    return node == null ? inferrer.dynamicType : node.accept(this);
+  }
+
+  TypeMask visitFunctionExpression(FunctionExpression node) {
+    return inferrer.functionType;
+  }
+
+  TypeMask visitFunctionDeclaration(FunctionDeclaration node) {
+    locals.update(elements[node], inferrer.functionType);
+    return visit(node.function);
+  }
+
+  TypeMask visitLiteralString(LiteralString node) {
+    return inferrer.stringType;
+  }
+
+  TypeMask visitStringInterpolation(StringInterpolation node) {
+    node.visitChildren(this);
+    return inferrer.stringType;
+  }
+
+  TypeMask visitStringJuxtaposition(StringJuxtaposition node) {
+    node.visitChildren(this);
+    return inferrer.stringType;
+  }
+
+  TypeMask visitLiteralBool(LiteralBool node) {
+    return inferrer.boolType;
+  }
+
+  TypeMask visitLiteralDouble(LiteralDouble node) {
+    return inferrer.doubleType;
+  }
+
+  TypeMask visitLiteralInt(LiteralInt node) {
+    return inferrer.intType;
+  }
+
+  TypeMask visitLiteralList(LiteralList node) {
+    node.visitChildren(this);
+    return node.isConst()
+        ? inferrer.constListType
+        : inferrer.growableListType;
+  }
+
+  TypeMask visitLiteralMap(LiteralMap node) {
+    node.visitChildren(this);
+    return node.isConst()
+        ? inferrer.constMapType
+        : inferrer.mapType;
+  }
+
+  TypeMask visitLiteralNull(LiteralNull node) {
+    return inferrer.nullType;
+  }
+
+  TypeMask visitTypeReferenceSend(Send node) {
+    return inferrer.typeType;
+  }
+
+  bool isThisOrSuper(Node node) => node.isThis() || node.isSuper();
+
+  Element get outermostElement {
+    return
+        analyzedElement.getOutermostEnclosingMemberOrTopLevel().implementation;
+  }
+
+  TypeMask _thisType;
+  TypeMask get thisType {
+    if (_thisType != null) return _thisType;
+    ClassElement cls = outermostElement.getEnclosingClass();
+    if (compiler.world.isUsedAsMixin(cls)) {
+      return _thisType = new TypeMask.nonNullSubtype(inferrer.rawTypeOf(cls));
+    } else if (compiler.world.hasAnySubclass(cls)) {
+      return _thisType = new TypeMask.nonNullSubclass(inferrer.rawTypeOf(cls));
+    } else {
+      return _thisType = new TypeMask.nonNullExact(inferrer.rawTypeOf(cls));
+    }
+  }
+
+  TypeMask _superType;
+  TypeMask get superType {
+    if (_superType != null) return _superType;
+    return _superType = new TypeMask.nonNullExact(
+        inferrer.rawTypeOf(outermostElement.getEnclosingClass().superclass));
+  }
+
+  TypeMask visitIdentifier(Identifier node) {
+    if (node.isThis()) {
+      return thisType;
+    } else if (node.isSuper()) {
+      return superType;
+    }
+    return inferrer.dynamicType;
+  }
+
+  void potentiallyAddIsCheck(Send node) {
+    if (!accumulateIsChecks) return;
+    if (!Elements.isLocal(elements[node.receiver])) return;
+    isChecks.add(node);
+  }
+
+  void updateIsChecks(List<Node> tests, {bool usePositive}) {
+    if (tests == null) return;
+    for (Send node in tests) {
+      if (node.isIsNotCheck) {
+        if (usePositive) continue;
+      } else {
+        if (!usePositive) continue;
+      }
+      DartType type = elements.getType(node.typeAnnotationFromIsCheck);
+      Element element = elements[node.receiver];
+      TypeMask existing = locals.use(element);
+      TypeMask newType = narrowType(
+          existing, type, inferrer.compiler, isNullable: false);
+      locals.update(element, newType);
+    }
+  }
+
+  TypeMask visitOperatorSend(Send node) {
+    Operator op = node.selector;
+    if (const SourceString("[]") == op.source) {
+      return visitDynamicSend(node);
+    } else if (const SourceString("&&") == op.source) {
+      conditionIsSimple = false;
+      bool oldAccumulateIsChecks = accumulateIsChecks;
+      accumulateIsChecks = true;
+      if (isChecks == null) isChecks = <Send>[];
+      visit(node.receiver);
+      accumulateIsChecks = oldAccumulateIsChecks;
+      if (!accumulateIsChecks) isChecks = null;
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      updateIsChecks(isChecks, usePositive: true);
+      visit(node.arguments.head);
+      locals.merge(saved);
+      return inferrer.boolType;
+    } else if (const SourceString("||") == op.source) {
+      conditionIsSimple = false;
+      visit(node.receiver);
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      updateIsChecks(isChecks, usePositive: false);
+      bool oldAccumulateIsChecks = accumulateIsChecks;
+      accumulateIsChecks = false;
+      visit(node.arguments.head);
+      accumulateIsChecks = oldAccumulateIsChecks;
+      locals.merge(saved);
+      return inferrer.boolType;
+    } else if (const SourceString("!") == op.source) {
+      bool oldAccumulateIsChecks = accumulateIsChecks;
+      accumulateIsChecks = false;
+      node.visitChildren(this);
+      accumulateIsChecks = oldAccumulateIsChecks;
+      return inferrer.boolType;
+    } else if (const SourceString("is") == op.source) {
+      potentiallyAddIsCheck(node);
+      node.visitChildren(this);
+      return inferrer.boolType;
+    } else if (const SourceString("as") == op.source) {
+      TypeMask receiverType = visit(node.receiver);
+      DartType type = elements.getType(node.arguments.head);
+      return narrowType(receiverType, type, inferrer.compiler);
+    } else if (node.isParameterCheck) {
+      node.visitChildren(this);
+      return inferrer.boolType;
+    } else if (node.argumentsNode is Prefix) {
+      // Unary operator.
+      return visitDynamicSend(node);
+    } else if (const SourceString('===') == op.source
+               || const SourceString('!==') == op.source) {
+      node.visitChildren(this);
+      return inferrer.boolType;
+    } else {
+      // Binary operator.
+      return visitDynamicSend(node);
+    }
+  }
+
+  // Because some nodes just visit their children, we may end up
+  // visiting a type annotation, that may contain a send in case of a
+  // prefixed type. Therefore we explicitly visit the type annotation
+  // to avoid confusing the [ResolvedVisitor].
+  visitTypeAnnotation(TypeAnnotation node) {}
+
+  TypeMask visitConditional(Conditional node) {
+    List<Send> tests = <Send>[];
+    bool simpleCondition = handleCondition(node.condition, tests);
+    LocalsHandler saved = new LocalsHandler.from(locals);
+    updateIsChecks(tests, usePositive: true);
+    TypeMask firstType = visit(node.thenExpression);
+    LocalsHandler thenLocals = locals;
+    locals = saved;
+    if (simpleCondition) updateIsChecks(tests, usePositive: false);
+    TypeMask secondType = visit(node.elseExpression);
+    locals.merge(thenLocals);
+    TypeMask type = computeLUB(firstType, secondType, compiler);
+    return type;
+  }
+
+  TypeMask visitVariableDefinitions(VariableDefinitions node) {
+    for (Link<Node> link = node.definitions.nodes;
+         !link.isEmpty;
+         link = link.tail) {
+      Node definition = link.head;
+      if (definition is Identifier) {
+        locals.update(elements[definition], inferrer.nullType);
+      } else {
+        assert(definition.asSendSet() != null);
+        visit(definition);
+      }
+    }
+    return inferrer.dynamicType;
+  }
+
+  bool handleCondition(Node node, List<Send> tests) {
+    bool oldConditionIsSimple = conditionIsSimple;
+    bool oldAccumulateIsChecks = accumulateIsChecks;
+    List<Send> oldIsChecks = isChecks;
+    accumulateIsChecks = true;
+    conditionIsSimple = true;
+    isChecks = tests;
+    visit(node);
+    bool simpleCondition = conditionIsSimple;
+    accumulateIsChecks = oldAccumulateIsChecks;
+    isChecks = oldIsChecks;
+    conditionIsSimple = oldConditionIsSimple;
+    return simpleCondition;
+  }
+
+  TypeMask visitIf(If node) {
+    List<Send> tests = <Send>[];
+    bool simpleCondition = handleCondition(node.condition, tests);
+    LocalsHandler saved = new LocalsHandler.from(locals);
+    updateIsChecks(tests, usePositive: true);
+    visit(node.thenPart);
+    LocalsHandler thenLocals = locals;
+    locals = saved;
+    if (simpleCondition) updateIsChecks(tests, usePositive: false);
+    visit(node.elsePart);
+    locals.merge(thenLocals);
+    return inferrer.dynamicType;
+  }
+
+  void setupBreaksAndContinues(TargetElement element) {
+    if (element == null) return;
+    if (element.isContinueTarget) continuesFor[element] = <LocalsHandler>[];
+    if (element.isBreakTarget) breaksFor[element] = <LocalsHandler>[];
+  }
+
+  void clearBreaksAndContinues(TargetElement element) {
+    continuesFor.remove(element);
+    breaksFor.remove(element);
+  }
+
+  void mergeBreaks(TargetElement element) {
+    if (element == null) return;
+    if (!element.isBreakTarget) return;
+    for (LocalsHandler handler in breaksFor[element]) {
+      locals.merge(handler, discardIfAborts: false);
+    }
+  }
+
+  bool mergeContinues(TargetElement element) {
+    if (element == null) return false;
+    if (!element.isContinueTarget) return false;
+    bool changed = false;
+    for (LocalsHandler handler in continuesFor[element]) {
+      changed = locals.merge(handler, discardIfAborts: false) || changed;
+    }
+    return changed;
+  }
+
+  TypeMask handleLoop(Node node, void logic()) {
+    loopLevel++;
+    bool changed = false;
+    TargetElement target = elements[node];
+    setupBreaksAndContinues(target);
+    do {
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      logic();
+      changed = saved.merge(locals);
+      locals = saved;
+      changed = mergeContinues(target) || changed;
+    } while (changed);
+    loopLevel--;
+    mergeBreaks(target);
+    clearBreaksAndContinues(target);
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitWhile(While node) {
+    return handleLoop(node, () {
+      List<Send> tests = <Send>[];
+      handleCondition(node.condition, tests);
+      updateIsChecks(tests, usePositive: true);
+      visit(node.body);
+    });
+  }
+
+  TypeMask visitDoWhile(DoWhile node) {
+    return handleLoop(node, () {
+      visit(node.body);
+      List<Send> tests = <Send>[];
+      handleCondition(node.condition, tests);
+      updateIsChecks(tests, usePositive: true);
+    });
+  }
+
+  TypeMask visitFor(For node) {
+    visit(node.initializer);
+    return handleLoop(node, () {
+      List<Send> tests = <Send>[];
+      handleCondition(node.condition, tests);
+      updateIsChecks(tests, usePositive: true);
+      visit(node.body);
+      visit(node.update);
+    });
+  }
+
+  TypeMask visitTryStatement(TryStatement node) {
+    LocalsHandler saved = locals;
+    locals = new LocalsHandler.from(locals, inTryBlock: true);
+    visit(node.tryBlock);
+    saved.merge(locals);
+    locals = saved;
+    for (Node catchBlock in node.catchBlocks) {
+      saved = new LocalsHandler.from(locals);
+      visit(catchBlock);
+      saved.merge(locals);
+      locals = saved;
+    }
+    visit(node.finallyBlock);
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitThrow(Throw node) {
+    node.visitChildren(this);
+    locals.seenReturn = true;
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitCatchBlock(CatchBlock node) {
+    Node exception = node.exception;
+    if (exception != null) {
+      DartType type = elements.getType(node.type);
+      TypeMask mask = type == null
+          ? inferrer.dynamicType
+          : new TypeMask.nonNullSubtype(type.asRaw());
+      locals.update(elements[exception], mask);
+    }
+    Node trace = node.trace;
+    if (trace != null) {
+      locals.update(elements[trace], inferrer.dynamicType);
+    }
+    visit(node.block);
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitParenthesizedExpression(ParenthesizedExpression node) {
+    return visit(node.expression);
+  }
+
+  TypeMask visitBlock(Block node) {
+    if (node.statements != null) {
+      for (Node statement in node.statements) {
+        visit(statement);
+        if (locals.aborts) break;
+      }
+    }
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitLabeledStatement(LabeledStatement node) {
+    Statement body = node.statement;
+    if (body is Loop
+        || body is SwitchStatement
+        || Elements.isUnusedLabel(node, elements)) {
+      // Loops and switches handle their own labels.
+      visit(body);
+      return inferrer.dynamicType;
+    }
+
+    TargetElement targetElement = elements[body];
+    setupBreaksAndContinues(targetElement);
+    visit(body);
+    mergeBreaks(targetElement);
+    clearBreaksAndContinues(targetElement);
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitBreakStatement(BreakStatement node) {
+    TargetElement target = elements[node];
+    breaksFor[target].add(locals);
+    locals.seenBreakOrContinue = true;
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitContinueStatement(ContinueStatement node) {
+    TargetElement target = elements[node];
+    continuesFor[target].add(locals);
+    locals.seenBreakOrContinue = true;
+    return inferrer.dynamicType;
+  }
+
+  void internalError(String reason, {Node node}) {
+    compiler.internalError(reason, node: node);
+  }
+
+  TypeMask visitSwitchStatement(SwitchStatement node) {
+    visit(node.parenthesizedExpression);
+
+    setupBreaksAndContinues(elements[node]);
+    if (Elements.switchStatementHasContinue(node, elements)) {
+      void forEachLabeledCase(void action(TargetElement target)) {
+        for (SwitchCase switchCase in node.cases) {
+          for (Node labelOrCase in switchCase.labelsAndCases) {
+            if (labelOrCase.asLabel() == null) continue;
+            LabelElement labelElement = elements[labelOrCase];
+            if (labelElement != null) {
+              action(labelElement.target);
+            }
+          }
+        }
+      }
+
+      forEachLabeledCase((TargetElement target) {
+        setupBreaksAndContinues(target);
+      });
+
+      // If the switch statement has a continue, we conservatively
+      // visit all cases and update [locals] until we have reached a
+      // fixed point.
+      bool changed;
+      do {
+        changed = false;
+        for (Node switchCase in node.cases) {
+          LocalsHandler saved = new LocalsHandler.from(locals);
+          visit(switchCase);
+          changed = saved.merge(locals, discardIfAborts: false) || changed;
+          locals = saved;
+        }
+      } while (changed);
+
+      forEachLabeledCase((TargetElement target) {
+        clearBreaksAndContinues(target);
+      });
+    } else {
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      // If there is a default case, the current values of the local
+      // variable might be overwritten, so we don't need the current
+      // [locals] for the join block.
+      LocalsHandler result = Elements.switchStatementHasDefault(node)
+          ? null
+          : new LocalsHandler.from(locals);
+
+      for (Node switchCase in node.cases) {
+        locals = new LocalsHandler.from(saved);
+        visit(switchCase);
+        if (result == null) {
+          result = locals;
+        } else {
+          result.merge(locals, discardIfAborts: false);
+        }
+      }
+      locals = result;
+    }
+    clearBreaksAndContinues(elements[node]);
+    // In case there is a default in the switch we discard the
+    // incoming localsHandler, because the types it holds do not need
+    // to be merged after the switch statement. This means that, if all
+    // cases, including the default, break or continue, the [result]
+    // handler may think it just aborts the current block. Therefore
+    // we set the current locals to not have any break or continue, so
+    // that the [visitBlock] method does not assume the code after the
+    // switch is dead code.
+    locals.seenBreakOrContinue = false;
+    return inferrer.dynamicType;
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index a75f930..4a9b948 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -21,6 +21,8 @@
 import '../dart2jslib.dart' hide Selector, TypedSelector;
 import '../universe/universe.dart' show Selector, SideEffects, TypedSelector;
 
+part 'inferrer_visitor.dart';
+
 /**
  * A work queue that ensures there are no duplicates, and adds and
  * removes in FIFO.
@@ -97,32 +99,6 @@
   bool get isDone => constructorsToVisitCount == 0;
 }
 
-/**
- * A sentinel type mask class used by the inferrer for the give up
- * type, and the dynamic type.
- */
-class SentinelTypeMask extends FlatTypeMask {
-  final String name;
-
-  SentinelTypeMask(this.name) : super(null, 0, false);
-
-  bool operator==(other) {
-    return identical(this, other);
-  }
-
-  TypeMask nullable() {
-    throw 'Unsupported operation';
-  }
-
-  TypeMask intersection(TypeMask other, Compiler compiler) {
-    return other;
-  }
-
-  bool get isNullable => true;
-
-  String toString() => '$name sentinel type mask';
-}
-
 final OPTIMISTIC = 0;
 final RETRY = 1;
 final PESSIMISTIC = 2;
@@ -180,8 +156,6 @@
   }
 }
 
-
-
 class InternalSimpleTypesInferrer extends TypesInferrer {
   /**
    * Maps an element to its callers.
@@ -267,10 +241,6 @@
 
   int optimismState;
 
-  /**
-   * Sentinel used by the inferrer to notify that it does not know
-   * the type of a specific element.
-   */
   TypeMask dynamicType;
   bool isDynamicType(TypeMask type) => identical(type, dynamicType);
 
@@ -383,23 +353,23 @@
    * Query method after the analysis to know the type of [element].
    */
   TypeMask getReturnTypeOfElement(Element element) {
-    return getTypeIfValuable(returnTypeOf[element]);
+    return getNonNullType(returnTypeOf[element]);
   }
 
   TypeMask getTypeOfElement(Element element) {
-    return getTypeIfValuable(typeOf[element]);
+    return getNonNullType(typeOf[element]);
   }
 
   TypeMask getTypeOfSelector(Selector selector) {
-    return getTypeIfValuable(typeOfSelector(selector));
+    return getNonNullType(typeOfSelector(selector));
   }
 
   bool isTypeValuable(TypeMask returnType) {
     return !isDynamicType(returnType);
   }
 
-  TypeMask getTypeIfValuable(TypeMask returnType) {
-    return isTypeValuable(returnType) ? returnType : null;
+  TypeMask getNonNullType(TypeMask returnType) {
+    return returnType != null ? returnType : dynamicType;
   }
 
   /**
@@ -417,7 +387,7 @@
     if (selector == null || selector.isSetter() || selector.isIndexSet()) {
       return null;
     }
-    return getTypeIfValuable(typeOfSelector(selector));
+    return getNonNullType(typeOfSelector(selector));
   }
 
   void checkAnalyzedAll() {
@@ -678,7 +648,7 @@
         assert(annotation is FunctionType);
         annotation = annotation.returnType;
       }
-      newType = narrowType(newType, annotation);
+      newType = narrowType(newType, annotation, compiler);
     }
 
     // Fields and native methods of native classes are handled
@@ -721,7 +691,7 @@
               || element.isGetter()
               || element.isFactoryConstructor())) {
         FunctionType functionType = element.computeType(compiler);
-        returnType = narrowType(dynamicType, functionType.returnType);
+        returnType = narrowType(dynamicType, functionType.returnType, compiler);
       } else {
         returnType = dynamicType;
       }
@@ -763,7 +733,7 @@
       } else {
         mappedType = new TypeMask.nonNullExact(rawTypeOf(type.element));
       }
-      returnType = computeLUB(returnType, mappedType);
+      returnType = computeLUB(returnType, mappedType, compiler);
       if (!isTypeValuable(returnType)) {
         returnType = dynamicType;
         break;
@@ -797,7 +767,7 @@
           // therefore only trust their type after the checks.
           || (compiler.enableTypeAssertions
               && (element.isField() || element.isVariable()))) {
-        type = narrowType(dynamicType, element.computeType(compiler));
+        type = narrowType(dynamicType, element.computeType(compiler), compiler);
       } else {
         type = dynamicType;
       }
@@ -818,7 +788,7 @@
     iterateOverElements(selector, (Element element) {
       assert(element.isImplementation);
       TypeMask type = typeOfElementWithSelector(element, selector);
-      result = computeLUB(result, type);
+      result = computeLUB(result, type, compiler);
       return isTypeValuable(result);
     });
     if (result == null) {
@@ -1023,7 +993,8 @@
       TypeMask type;
       typeOfArguments[element].forEach((_, ArgumentsTypes arguments) {
         if (!visitingOptionalParameter) {
-          type = computeLUB(type, arguments.positional[parameterIndex]);
+          type = computeLUB(
+              type, arguments.positional[parameterIndex], compiler);
         } else {
           TypeMask argumentType = signature.optionalParametersAreNamed
               ? arguments.named[parameter.name]
@@ -1034,7 +1005,7 @@
             argumentType = defaultTypeOfParameter[parameter];
           }
           assert(argumentType != null);
-          type = computeLUB(type, argumentType);
+          type = computeLUB(type, argumentType, compiler);
         }
       });
       if (recordType(parameter, type)) {
@@ -1100,7 +1071,7 @@
         if (!selector.isSetter()) {
           TypeMask type = handleIntrisifiedSelector(selector, arguments);
           if (type == null) type = typeOfElementWithSelector(element, selector);
-          result = computeLUB(result, type);
+          result = computeLUB(result, type, compiler);
         }
       }
     }
@@ -1155,7 +1126,7 @@
         // use its type.
         constraints.add(constraint);
       } else {
-        fieldType = computeLUB(fieldType, mask);
+        fieldType = computeLUB(fieldType, mask, compiler);
       }
     });
 
@@ -1178,7 +1149,7 @@
           // Otherwise the constraint is on the form [: field = other.field :].
           assert(constraint.isGetter());
         }
-        fieldType = computeLUB(fieldType, typeOfSelector(constraint));
+        fieldType = computeLUB(fieldType, typeOfSelector(constraint), compiler);
       }
       if (existing == null) {
         typeOf.remove(element);
@@ -1262,47 +1233,6 @@
       }
     });
   }
-
-  /**
-   * Returns the least upper bound between [firstType] and
-   * [secondType].
-   */
-  TypeMask computeLUB(TypeMask firstType, TypeMask secondType) {
-    if (firstType == null) {
-      return secondType;
-    } else if (isDynamicType(secondType)) {
-      return secondType;
-    } else if (isDynamicType(firstType)) {
-      return firstType;
-    } else {
-      TypeMask union = firstType.union(secondType, compiler);
-      // TODO(kasperl): If the union isn't nullable it seems wasteful
-      // to use dynamic. Fix that.
-      return union.containsAll(compiler) ? dynamicType : union;
-    }
-  }
-
-  TypeMask narrowType(TypeMask type,
-                      DartType annotation,
-                      {bool isNullable: true}) {
-    if (annotation.isDynamic) return type;
-    if (annotation.isMalformed) return type;
-    if (annotation.isVoid) return nullType;
-    if (annotation.element == compiler.objectClass) return type;
-    TypeMask otherType;
-    if (annotation.kind == TypeKind.TYPEDEF
-        || annotation.kind == TypeKind.FUNCTION) {
-      otherType = functionType;
-    } else if (annotation.kind == TypeKind.TYPE_VARIABLE) {
-      return type;
-    } else {
-      assert(annotation.kind == TypeKind.INTERFACE);
-      otherType = new TypeMask.nonNullSubtype(annotation);
-    }
-    if (isNullable) otherType = otherType.nullable();
-    if (type == null) return otherType;
-    return type.intersection(otherType, compiler);
-  }
 }
 
 /**
@@ -1337,183 +1267,19 @@
   }
 }
 
-/**
- * Placeholder for inferred types of local variables.
- */
-class LocalsHandler {
-  final InternalSimpleTypesInferrer inferrer;
-  final Map<Element, TypeMask> locals;
-  final Map<Element, Element> capturedAndBoxed;
-  final Map<Element, TypeMask> fieldsInitializedInConstructor;
-  final bool inTryBlock;
-  bool isThisExposed;
-  bool seenReturn = false;
-  bool seenBreakOrContinue = false;
-
-  bool get aborts {
-    return seenReturn || seenBreakOrContinue;
-  }
-
-  LocalsHandler(this.inferrer)
-      : locals = new Map<Element, TypeMask>(),
-        capturedAndBoxed = new Map<Element, Element>(),
-        fieldsInitializedInConstructor = new Map<Element, TypeMask>(),
-        inTryBlock = false,
-        isThisExposed = true;
-  LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
-      : locals = new Map<Element, TypeMask>.from(other.locals),
-        capturedAndBoxed = new Map<Element, Element>.from(
-            other.capturedAndBoxed),
-        fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
-            other.fieldsInitializedInConstructor),
-        inTryBlock = other.inTryBlock || inTryBlock,
-        inferrer = other.inferrer,
-        isThisExposed = other.isThisExposed;
-
-  TypeMask use(Element local) {
-    if (capturedAndBoxed.containsKey(local)) {
-      return inferrer.typeOfElement(capturedAndBoxed[local]);
-    }
-    return locals[local];
-  }
-
-  void update(Element local, TypeMask type) {
-    assert(type != null);
-    if (inferrer.compiler.trustTypeAnnotations
-        || inferrer.compiler.enableTypeAssertions) {
-      type = inferrer.narrowType(type, local.computeType(inferrer.compiler));
-    }
-    if (capturedAndBoxed.containsKey(local) || inTryBlock) {
-      // If a local is captured and boxed, or is set in a try block,
-      // we compute the LUB of its assignments.
-      //
-      // We don't know if an assignment in a try block
-      // will be executed, so all assigments in that block are
-      // potential types after we have left it.
-      type = inferrer.computeLUB(locals[local], type);
-    }
-    locals[local] = type;
-  }
-
-  void setCapturedAndBoxed(Element local, Element field) {
-    capturedAndBoxed[local] = field;
-  }
-
-  /**
-   * Merge handlers [first] and [second] into [:this:] and returns
-   * whether the merge changed one of the variables types in [first].
-   */
-  bool merge(LocalsHandler other, {bool discardIfAborts: true}) {
-    bool changed = false;
-    List<Element> toRemove = <Element>[];
-    // Iterating over a map and just updating its entries is OK.
-    locals.forEach((Element local, TypeMask oldType) {
-      TypeMask otherType = other.locals[local];
-      bool isCaptured = capturedAndBoxed.containsKey(local);
-      if (otherType == null) {
-        if (!isCaptured) {
-          // If [local] is not in the other map and is not captured
-          // and boxed, we know it is not a
-          // local we want to keep. For example, in an if/else, we don't
-          // want to keep variables declared in the if or in the else
-          // branch at the merge point.
-          toRemove.add(local);
-        }
-        return;
-      }
-      if (!isCaptured && aborts && discardIfAborts) {
-        locals[local] = otherType;
-      } else if (!isCaptured && other.aborts && discardIfAborts) {
-        // Don't do anything.
-      } else {
-        TypeMask type = inferrer.computeLUB(oldType, otherType);
-        if (type != oldType) changed = true;
-        locals[local] = type;
-      }
-    });
-
-    // Remove locals that will not be used anymore.
-    toRemove.forEach((Element element) {
-      locals.remove(element);
-    });
-
-    // Update the locals that are captured and boxed. We
-    // unconditionally add them to [this] because we register the type
-    // of boxed variables after analyzing all closures.
-    other.capturedAndBoxed.forEach((Element local, Element field) {
-      capturedAndBoxed[local] =  field;
-      // If [element] is not in our [locals], we need to update it.
-      // Otherwise, we have already computed the LUB of it.
-      if (locals[local] == null) {
-        locals[local] = other.locals[local];
-      }
-    });
-
-    // Merge instance fields initialized in both handlers. This is
-    // only relevant for generative constructors.
-    toRemove = <Element>[];
-    // Iterate over the map in [:this:]. The map in [other] may
-    // contain different fields, but if this map does not contain it,
-    // then we know the field can be null and we don't need to track
-    // it.
-    fieldsInitializedInConstructor.forEach((Element element, TypeMask type) {
-      TypeMask otherType = other.fieldsInitializedInConstructor[element];
-      if (otherType == null) {
-        toRemove.add(element);
-      } else {
-        fieldsInitializedInConstructor[element] =
-            inferrer.computeLUB(type, otherType);
-      }
-    });
-    // Remove fields that were not initialized in [other].
-    toRemove.forEach((Element element) {
-      fieldsInitializedInConstructor.remove(element);
-    });
-    isThisExposed = isThisExposed || other.isThisExposed;
-    seenReturn = seenReturn && other.seenReturn;
-    seenBreakOrContinue = seenBreakOrContinue && other.seenBreakOrContinue;
-
-    return changed;
-  }
-
-  void updateField(Element element, TypeMask type) {
-    if (isThisExposed) return;
-    fieldsInitializedInConstructor[element] = type;
-  }
-}
-
-class SimpleTypeInferrerVisitor extends ResolvedVisitor<TypeMask> {
-  final Element analyzedElement;
-  final Element outermostElement;
-  final InternalSimpleTypesInferrer inferrer;
-  final Compiler compiler;
-  final Map<TargetElement, List<LocalsHandler>> breaksFor =
-      new Map<TargetElement, List<LocalsHandler>>();
-  final Map<TargetElement, List<LocalsHandler>> continuesFor =
-      new Map<TargetElement, List<LocalsHandler>>();
-  LocalsHandler locals;
+class SimpleTypeInferrerVisitor extends InferrerVisitor {
   TypeMask returnType;
-
   bool visitingInitializers = false;
   bool isConstructorRedirect = false;
-  bool accumulateIsChecks = false;
-  bool conditionIsSimple = false;
-
-  List<Send> isChecks;
-  int loopLevel = 0;
   SideEffects sideEffects = new SideEffects.empty();
+  final Element outermostElement;
 
-  bool get inLoop => loopLevel > 0;
-  bool get isThisExposed => locals.isThisExposed;
-  void set isThisExposed(value) { locals.isThisExposed = value; }
-
-  SimpleTypeInferrerVisitor.internal(TreeElements mapping,
-                                     this.analyzedElement,
+  SimpleTypeInferrerVisitor.internal(analyzedElement,
                                      this.outermostElement,
-                                     this.inferrer,
-                                     this.compiler,
-                                     this.locals)
-    : super(mapping);
+                                     inferrer,
+                                     compiler,
+                                     locals)
+    : super(analyzedElement, inferrer, compiler, locals);
 
   factory SimpleTypeInferrerVisitor(Element element,
                                     Compiler compiler,
@@ -1521,13 +1287,10 @@
                                     [LocalsHandler handler]) {
     Element outermostElement =
         element.getOutermostEnclosingMemberOrTopLevel().implementation;
-    TreeElements elements = compiler.enqueuer.resolution.resolvedElements[
-        outermostElement.declaration];
-    assert(elements != null);
     assert(outermostElement != null);
     handler = handler != null ? handler : new LocalsHandler(inferrer);
     return new SimpleTypeInferrerVisitor.internal(
-        elements, element, outermostElement, inferrer, compiler, handler);
+        element, outermostElement, inferrer, compiler, handler);
   }
 
   TypeMask run() {
@@ -1637,7 +1400,7 @@
         // bool.
         signature.forEachParameter((Element parameter) {
           if (inferrer.typeOfElement(parameter).isNullable){
-            returnType = inferrer.computeLUB(returnType, inferrer.boolType);
+            returnType = computeLUB(returnType, inferrer.boolType, compiler);
           }
         });
       }
@@ -1658,43 +1421,6 @@
     return returnType;
   }
 
-  TypeMask _thisType;
-  TypeMask get thisType {
-    if (_thisType != null) return _thisType;
-    ClassElement cls = outermostElement.getEnclosingClass();
-    if (compiler.world.isUsedAsMixin(cls)) {
-      return _thisType = new TypeMask.nonNullSubtype(inferrer.rawTypeOf(cls));
-    } else if (compiler.world.hasAnySubclass(cls)) {
-      return _thisType = new TypeMask.nonNullSubclass(inferrer.rawTypeOf(cls));
-    } else {
-      return _thisType = new TypeMask.nonNullExact(inferrer.rawTypeOf(cls));
-    }
-  }
-
-  TypeMask _superType;
-  TypeMask get superType {
-    if (_superType != null) return _superType;
-    return _superType = new TypeMask.nonNullExact(
-        inferrer.rawTypeOf(outermostElement.getEnclosingClass().superclass));
-  }
-
-  void recordReturnType(TypeMask type) {
-    returnType = inferrer.computeLUB(returnType, type);
-  }
-
-  TypeMask visitNode(Node node) {
-    node.visitChildren(this);
-    return inferrer.dynamicType;
-  }
-
-  TypeMask visitNewExpression(NewExpression node) {
-    return node.send.accept(this);
-  }
-
-  TypeMask visit(Node node) {
-    return node == null ? inferrer.dynamicType : node.accept(this);
-  }
-
   TypeMask visitFunctionExpression(FunctionExpression node) {
     Element element = elements[node];
     // We don't put the closure in the work queue of the
@@ -1725,59 +1451,6 @@
     return inferrer.functionType;
   }
 
-  TypeMask visitFunctionDeclaration(FunctionDeclaration node) {
-    locals.update(elements[node], inferrer.functionType);
-    return visit(node.function);
-  }
-
-  TypeMask visitLiteralString(LiteralString node) {
-    return inferrer.stringType;
-  }
-
-  TypeMask visitStringInterpolation(StringInterpolation node) {
-    node.visitChildren(this);
-    return inferrer.stringType;
-  }
-
-  TypeMask visitStringJuxtaposition(StringJuxtaposition node) {
-    node.visitChildren(this);
-    return inferrer.stringType;
-  }
-
-  TypeMask visitLiteralBool(LiteralBool node) {
-    return inferrer.boolType;
-  }
-
-  TypeMask visitLiteralDouble(LiteralDouble node) {
-    return inferrer.doubleType;
-  }
-
-  TypeMask visitLiteralInt(LiteralInt node) {
-    return inferrer.intType;
-  }
-
-  TypeMask visitLiteralList(LiteralList node) {
-    node.visitChildren(this);
-    return node.isConst()
-        ? inferrer.constListType
-        : inferrer.growableListType;
-  }
-
-  TypeMask visitLiteralMap(LiteralMap node) {
-    node.visitChildren(this);
-    return node.isConst()
-        ? inferrer.constMapType
-        : inferrer.mapType;
-  }
-
-  TypeMask visitLiteralNull(LiteralNull node) {
-    return inferrer.nullType;
-  }
-
-  TypeMask visitTypeReferenceSend(Send node) {
-    return inferrer.typeType;
-  }
-
   bool isThisOrSuper(Node node) => node.isThis() || node.isSuper();
 
   void checkIfExposesThis(Selector selector) {
@@ -1995,15 +1668,6 @@
     return rhsType;
   }
 
-  TypeMask visitIdentifier(Identifier node) {
-    if (node.isThis()) {
-      return thisType;
-    } else if (node.isSuper()) {
-      return superType;
-    }
-    return inferrer.dynamicType;
-  }
-
   TypeMask visitSuperSend(Send node) {
     Element element = elements[node];
     if (Elements.isUnresolved(element)) {
@@ -2092,92 +1756,6 @@
     return new ArgumentsTypes(positional, named);
   }
 
-  void potentiallyAddIsCheck(Send node) {
-    if (!accumulateIsChecks) return;
-    if (!Elements.isLocal(elements[node.receiver])) return;
-    isChecks.add(node);
-  }
-
-  void updateIsChecks(List<Node> tests, {bool usePositive}) {
-    if (tests == null) return;
-    for (Send node in tests) {
-      if (node.isIsNotCheck) {
-        if (usePositive) continue;
-      } else {
-        if (!usePositive) continue;
-      }
-      DartType type = elements.getType(node.typeAnnotationFromIsCheck);
-      Element element = elements[node.receiver];
-      TypeMask existing = locals.use(element);
-      TypeMask newType = inferrer.narrowType(existing, type, isNullable: false);
-      locals.update(element, newType);
-    }
-  }
-
-  TypeMask visitOperatorSend(Send node) {
-    Operator op = node.selector;
-    if (const SourceString("[]") == op.source) {
-      return visitDynamicSend(node);
-    } else if (const SourceString("&&") == op.source) {
-      conditionIsSimple = false;
-      bool oldAccumulateIsChecks = accumulateIsChecks;
-      accumulateIsChecks = true;
-      if (isChecks == null) isChecks = <Send>[];
-      visit(node.receiver);
-      accumulateIsChecks = oldAccumulateIsChecks;
-      if (!accumulateIsChecks) isChecks = null;
-      LocalsHandler saved = new LocalsHandler.from(locals);
-      updateIsChecks(isChecks, usePositive: true);
-      visit(node.arguments.head);
-      locals.merge(saved);
-      return inferrer.boolType;
-    } else if (const SourceString("||") == op.source) {
-      conditionIsSimple = false;
-      visit(node.receiver);
-      LocalsHandler saved = new LocalsHandler.from(locals);
-      updateIsChecks(isChecks, usePositive: false);
-      bool oldAccumulateIsChecks = accumulateIsChecks;
-      accumulateIsChecks = false;
-      visit(node.arguments.head);
-      accumulateIsChecks = oldAccumulateIsChecks;
-      locals.merge(saved);
-      return inferrer.boolType;
-    } else if (const SourceString("!") == op.source) {
-      bool oldAccumulateIsChecks = accumulateIsChecks;
-      accumulateIsChecks = false;
-      node.visitChildren(this);
-      accumulateIsChecks = oldAccumulateIsChecks;
-      return inferrer.boolType;
-    } else if (const SourceString("is") == op.source) {
-      potentiallyAddIsCheck(node);
-      node.visitChildren(this);
-      return inferrer.boolType;
-    } else if (const SourceString("as") == op.source) {
-      TypeMask receiverType = visit(node.receiver);
-      DartType type = elements.getType(node.arguments.head);
-      return inferrer.narrowType(receiverType, type);
-    } else if (node.isParameterCheck) {
-      node.visitChildren(this);
-      return inferrer.boolType;
-    } else if (node.argumentsNode is Prefix) {
-      // Unary operator.
-      return visitDynamicSend(node);
-    } else if (const SourceString('===') == op.source
-               || const SourceString('!==') == op.source) {
-      node.visitChildren(this);
-      return inferrer.boolType;
-    } else {
-      // Binary operator.
-      return visitDynamicSend(node);
-    }
-  }
-
-  // Because some nodes just visit their children, we may end up
-  // visiting a type annotation, that may contain a send in case of a
-  // prefixed type. Therefore we explicitly visit the type annotation
-  // to avoid confusing the [ResolvedVisitor].
-  visitTypeAnnotation(TypeAnnotation node) {}
-
   TypeMask visitGetterSend(Send node) {
     Element element = elements[node];
     Selector selector = elements.getSelector(node);
@@ -2292,6 +1870,10 @@
     return handleDynamicSend(node, selector, receiverType, arguments);
   }
 
+  void recordReturnType(TypeMask type) {
+    returnType = computeLUB(returnType, type, compiler);
+  }
+
   TypeMask visitReturn(Return node) {
     if (node.isRedirectingFactoryBody) {
       Element element = elements[node.expression];
@@ -2332,143 +1914,7 @@
     return inferrer.dynamicType;
   }
 
-  TypeMask visitConditional(Conditional node) {
-    List<Send> tests = <Send>[];
-    bool simpleCondition = handleCondition(node.condition, tests);
-    LocalsHandler saved = new LocalsHandler.from(locals);
-    updateIsChecks(tests, usePositive: true);
-    TypeMask firstType = visit(node.thenExpression);
-    LocalsHandler thenLocals = locals;
-    locals = saved;
-    if (simpleCondition) updateIsChecks(tests, usePositive: false);
-    TypeMask secondType = visit(node.elseExpression);
-    locals.merge(thenLocals);
-    TypeMask type = inferrer.computeLUB(firstType, secondType);
-    return type;
-  }
-
-  TypeMask visitVariableDefinitions(VariableDefinitions node) {
-    for (Link<Node> link = node.definitions.nodes;
-         !link.isEmpty;
-         link = link.tail) {
-      Node definition = link.head;
-      if (definition is Identifier) {
-        locals.update(elements[definition], inferrer.nullType);
-      } else {
-        assert(definition.asSendSet() != null);
-        visit(definition);
-      }
-    }
-    return inferrer.dynamicType;
-  }
-
-  bool handleCondition(Node node, List<Send> tests) {
-    bool oldConditionIsSimple = conditionIsSimple;
-    bool oldAccumulateIsChecks = accumulateIsChecks;
-    List<Send> oldIsChecks = isChecks;
-    accumulateIsChecks = true;
-    conditionIsSimple = true;
-    isChecks = tests;
-    visit(node);
-    bool simpleCondition = conditionIsSimple;
-    accumulateIsChecks = oldAccumulateIsChecks;
-    isChecks = oldIsChecks;
-    conditionIsSimple = oldConditionIsSimple;
-    return simpleCondition;
-  }
-
-  TypeMask visitIf(If node) {
-    List<Send> tests = <Send>[];
-    bool simpleCondition = handleCondition(node.condition, tests);
-    LocalsHandler saved = new LocalsHandler.from(locals);
-    updateIsChecks(tests, usePositive: true);
-    visit(node.thenPart);
-    LocalsHandler thenLocals = locals;
-    locals = saved;
-    if (simpleCondition) updateIsChecks(tests, usePositive: false);
-    visit(node.elsePart);
-    locals.merge(thenLocals);
-    return inferrer.dynamicType;
-  }
-
-  void setupBreaksAndContinues(TargetElement element) {
-    if (element == null) return;
-    if (element.isContinueTarget) continuesFor[element] = <LocalsHandler>[];
-    if (element.isBreakTarget) breaksFor[element] = <LocalsHandler>[];
-  }
-
-  void clearBreaksAndContinues(TargetElement element) {
-    continuesFor.remove(element);
-    breaksFor.remove(element);
-  }
-
-  void mergeBreaks(TargetElement element) {
-    if (element == null) return;
-    if (!element.isBreakTarget) return;
-    for (LocalsHandler handler in breaksFor[element]) {
-      locals.merge(handler, discardIfAborts: false);
-    }
-  }
-
-  bool mergeContinues(TargetElement element) {
-    if (element == null) return false;
-    if (!element.isContinueTarget) return false;
-    bool changed = false;
-    for (LocalsHandler handler in continuesFor[element]) {
-      changed = locals.merge(handler, discardIfAborts: false) || changed;
-    }
-    return changed;
-  }
-
-  TypeMask handleLoop(Node node, void logic()) {
-    loopLevel++;
-    bool changed = false;
-    TargetElement target = elements[node];
-    setupBreaksAndContinues(target);
-    do {
-      LocalsHandler saved = new LocalsHandler.from(locals);
-      logic();
-      changed = saved.merge(locals);
-      locals = saved;
-      changed = mergeContinues(target) || changed;
-    } while (changed);
-    loopLevel--;
-    mergeBreaks(target);
-    clearBreaksAndContinues(target);
-    return inferrer.dynamicType;
-  }
-
-  TypeMask visitWhile(While node) {
-    return handleLoop(node, () {
-      List<Send> tests = <Send>[];
-      handleCondition(node.condition, tests);
-      updateIsChecks(tests, usePositive: true);
-      visit(node.body);
-    });
-  }
-
-  TypeMask visitDoWhile(DoWhile node) {
-    return handleLoop(node, () {
-      visit(node.body);
-      List<Send> tests = <Send>[];
-      handleCondition(node.condition, tests);
-      updateIsChecks(tests, usePositive: true);
-    });
-  }
-
-  TypeMask visitFor(For node) {
-    visit(node.initializer);
-    return handleLoop(node, () {
-      List<Send> tests = <Send>[];
-      handleCondition(node.condition, tests);
-      updateIsChecks(tests, usePositive: true);
-      visit(node.body);
-      visit(node.update);
-    });
-  }
-
   TypeMask visitForIn(ForIn node) {
-    bool changed = false;
     TypeMask expressionType = visit(node.expression);
     Selector iteratorSelector = elements.getIteratorSelector(node);
     Selector currentSelector = elements.getCurrentSelector(node);
@@ -2509,164 +1955,4 @@
       visit(node.body);
     });
   }
-
-  TypeMask visitTryStatement(TryStatement node) {
-    LocalsHandler saved = locals;
-    locals = new LocalsHandler.from(locals, inTryBlock: true);
-    visit(node.tryBlock);
-    saved.merge(locals);
-    locals = saved;
-    for (Node catchBlock in node.catchBlocks) {
-      saved = new LocalsHandler.from(locals);
-      visit(catchBlock);
-      saved.merge(locals);
-      locals = saved;
-    }
-    visit(node.finallyBlock);
-    return inferrer.dynamicType;
-  }
-
-  TypeMask visitThrow(Throw node) {
-    node.visitChildren(this);
-    locals.seenReturn = true;
-    return inferrer.dynamicType;
-  }
-
-  TypeMask visitCatchBlock(CatchBlock node) {
-    Node exception = node.exception;
-    if (exception != null) {
-      DartType type = elements.getType(node.type);
-      TypeMask mask = type == null
-          ? inferrer.dynamicType
-          : new TypeMask.nonNullSubtype(type.asRaw());
-      locals.update(elements[exception], mask);
-    }
-    Node trace = node.trace;
-    if (trace != null) {
-      locals.update(elements[trace], inferrer.dynamicType);
-    }
-    visit(node.block);
-    return inferrer.dynamicType;
-  }
-
-  TypeMask visitParenthesizedExpression(ParenthesizedExpression node) {
-    return visit(node.expression);
-  }
-
-  TypeMask visitBlock(Block node) {
-    if (node.statements != null) {
-      for (Node statement in node.statements) {
-        visit(statement);
-        if (locals.aborts) break;
-      }
-    }
-    return inferrer.dynamicType;
-  }
-
-  TypeMask visitLabeledStatement(LabeledStatement node) {
-    Statement body = node.statement;
-    if (body is Loop
-        || body is SwitchStatement
-        || Elements.isUnusedLabel(node, elements)) {
-      // Loops and switches handle their own labels.
-      visit(body);
-      return inferrer.dynamicType;
-    }
-
-    TargetElement targetElement = elements[body];
-    setupBreaksAndContinues(targetElement);
-    visit(body);
-    mergeBreaks(targetElement);
-    clearBreaksAndContinues(targetElement);
-    return inferrer.dynamicType;
-  }
-
-  TypeMask visitBreakStatement(BreakStatement node) {
-    TargetElement target = elements[node];
-    breaksFor[target].add(locals);
-    locals.seenBreakOrContinue = true;
-    return inferrer.dynamicType;
-  }
-
-  TypeMask visitContinueStatement(ContinueStatement node) {
-    TargetElement target = elements[node];
-    continuesFor[target].add(locals);
-    locals.seenBreakOrContinue = true;
-    return inferrer.dynamicType;
-  }
-
-  void internalError(String reason, {Node node}) {
-    compiler.internalError(reason, node: node);
-  }
-
-  TypeMask visitSwitchStatement(SwitchStatement node) {
-    visit(node.parenthesizedExpression);
-
-    setupBreaksAndContinues(elements[node]);
-    if (Elements.switchStatementHasContinue(node, elements)) {
-      void forEachLabeledCase(void action(TargetElement target)) {
-        for (SwitchCase switchCase in node.cases) {
-          for (Node labelOrCase in switchCase.labelsAndCases) {
-            if (labelOrCase.asLabel() == null) continue;
-            LabelElement labelElement = elements[labelOrCase];
-            if (labelElement != null) {
-              action(labelElement.target);
-            }
-          }
-        }
-      }
-
-      forEachLabeledCase((TargetElement target) {
-        setupBreaksAndContinues(target);
-      });
-
-      // If the switch statement has a continue, we conservatively
-      // visit all cases and update [locals] until we have reached a
-      // fixed point.
-      bool changed;
-      do {
-        changed = false;
-        for (Node switchCase in node.cases) {
-          LocalsHandler saved = new LocalsHandler.from(locals);
-          visit(switchCase);
-          changed = saved.merge(locals, discardIfAborts: false) || changed;
-          locals = saved;
-        }
-      } while (changed);
-
-      forEachLabeledCase((TargetElement target) {
-        clearBreaksAndContinues(target);
-      });
-    } else {
-      LocalsHandler saved = new LocalsHandler.from(locals);
-      // If there is a default case, the current values of the local
-      // variable might be overwritten, so we don't need the current
-      // [locals] for the join block.
-      LocalsHandler result = Elements.switchStatementHasDefault(node)
-          ? null
-          : new LocalsHandler.from(locals);
-
-      for (Node switchCase in node.cases) {
-        locals = new LocalsHandler.from(saved);
-        visit(switchCase);
-        if (result == null) {
-          result = locals;
-        } else {
-          result.merge(locals, discardIfAborts: false);
-        }
-      }
-      locals = result;
-    }
-    clearBreaksAndContinues(elements[node]);
-    // In case there is a default in the switch we discard the
-    // incoming localsHandler, because the types it holds do not need
-    // to be merged after the switch statement. This means that, if all
-    // cases, including the default, break or continue, the [result]
-    // handler may think it just aborts the current block. Therefore
-    // we set the current locals to not have any break or continue, so
-    // that the [visitBlock] method does not assume the code after the
-    // switch is dead code.
-    locals.seenBreakOrContinue = false;
-    return inferrer.dynamicType;
-  }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart
index 5813cfe..60f3641 100644
--- a/sdk/lib/_internal/compiler/implementation/types/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -30,6 +30,22 @@
   TypeMask getTypeOfElement(Element element);
   TypeMask getTypeOfNode(Element owner, Node node);
   TypeMask getTypeOfSelector(Selector selector);
+
+  TypeMask get dynamicType;
+  TypeMask get nullType;
+  TypeMask get intType;
+  TypeMask get doubleType;
+  TypeMask get numType;
+  TypeMask get boolType;
+  TypeMask get functionType;
+  TypeMask get listType;
+  TypeMask get constListType;
+  TypeMask get fixedListType;
+  TypeMask get growableListType;
+  TypeMask get mapType;
+  TypeMask get constMapType;
+  TypeMask get stringType;
+  TypeMask get typeType;
 }
 
 /**
diff --git a/sdk/lib/_internal/docgen/docgen.dart b/sdk/lib/_internal/docgen/docgen.dart
deleted file mode 100644
index b245bf5..0000000
--- a/sdk/lib/_internal/docgen/docgen.dart
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * The docgen tool takes in a library as input and produces documentation
- * for the library as well as all libraries it imports and uses. The tool can
- * be run by passing in the path to a .dart file like this:
- *
- *   ./dart docgen.dart path/to/file.dart
- *
- * This outputs information about all classes, variables, functions, and
- * methods defined in the library and its imported libraries.
- */
-library docgen;
-
-import 'dart:io';
-import 'dart:async';
-import 'lib/src/dart2js_mirrors.dart';
-import 'lib/dart2yaml.dart';
-import '../../../../pkg/args/lib/args.dart';
-import '../compiler/implementation/mirrors/mirrors.dart';
-import '../compiler/implementation/mirrors/mirrors_util.dart';
-
-/**
- * Entry function to create YAML documentation from Dart files.
- */
-void main() {
-  // TODO(tmandel): Use args library once flags are clear.
-  Options opts = new Options();
-  
-  if (opts.arguments.length > 0) {
-    List<Path> libraries = [new Path(opts.arguments[0])];
-    Path sdkDirectory = new Path("../../../");
-    var workingMirrors = analyze(libraries, sdkDirectory, 
-        options: ['--preserve-comments', '--categories=Client,Server']);
-    workingMirrors.then( (MirrorSystem mirrorSystem) {
-      var mirrors = mirrorSystem.libraries;
-      if (mirrors.isEmpty) {
-        print("no LibraryMirrors");
-      } else {
-        mirrors.values.forEach( (library) {
-          // TODO(tmandel): Use flags to filter libraries.
-          if (library.uri.scheme != "dart") {
-            String result = _getDocumentation(library);
-            if (result != null) {
-              _writeToFile(result, "${library.qualifiedName}.yaml");
-            }
-          }
-        });
-      }
-    });
-  }
-}
-
-/**
- *  Creates YAML output from relevant libraries.
- */
-//TODO(tmandel): Also allow for output to JSON based on flags
-String _getDocumentation(LibraryMirror library) {
-  Map libMap = new Map();
-  String libraryName = library.qualifiedName;
-  
-  // Get library top-level information.
-  libMap[libraryName] = new Map();
-  
-  libMap[libraryName]["variables"] = new Map();
-  _getVariables(libMap[libraryName]["variables"], library.variables);
-  
-  libMap[libraryName]["functions"] = new Map();
-  _getMethods(libMap[libraryName]["functions"], library.functions);
-  
-  String comment = _getComment(library);
-  libMap[libraryName]["comment"] = comment != null ? comment.trim() : null;
-  
-  // Get specific information about each class.
-  Map classes = new Map();
-  library.classes.forEach( (String cName, ClassMirror mir) {
-    
-    classes[cName] = new Map();
-    _getMethods(classes[cName], mir.methods);
-    
-    classes[cName]["variables"] = new Map();
-    _getVariables(classes[cName]["variables"], mir.variables);
-    
-    classes[cName]["superclass"] = mir.superclass;
-    classes[cName]["interfaces"] = mir.superinterfaces;
-    classes[cName]["abstract"]   = mir.isAbstract;
-    
-    String comment = _getComment(mir);
-    classes[cName]["comment"] = comment != null ? comment.trim() : null;
-
-  });
-  libMap[libraryName]["classes"] = classes;
-  return getYamlString(libMap);
-}
-
-/**
- * Returns any documentation comments associated with a mirror.
- */
-// TODO(tmandel): Handle reference links in comments.
-String _getComment(DeclarationMirror mirror) {
-  String commentText;
-  mirror.metadata.forEach( (metadata) {
-    if (metadata is CommentInstanceMirror) {
-      CommentInstanceMirror comment = metadata;
-      if (comment.isDocComment) {
-        if (commentText == null) {
-          commentText = comment.trimmedText;
-        } else {
-          commentText = "$commentText ${comment.trimmedText}";
-        }
-      } 
-    }
-  });
-  return commentText;
-}
-  
-/**
- * Populates an input Map with characteristics of variables.
- */
-void _getVariables(Map data, Map<String, VariableMirror> mirrorMap) {
-  mirrorMap.forEach( (String name, VariableMirror mirror) {
-    data[name] = new Map();
-    data[name]["final"] = mirror.isFinal.toString();
-    data[name]["static"] = mirror.isStatic.toString();
-    data[name]["type"] = mirror.type.toString();
-    
-    String comment = _getComment(mirror);
-    data[name]["comment"] = comment != null ? comment.trim() : null;  
-  });
-}
-
-/**
- * Populates an input Map with characteristics of methods.
- */
-void _getMethods(Map data, Map<String, MethodMirror> mirrorMap) {
-  mirrorMap.forEach( (String mirrorName, MethodMirror mirror) {
-    String category = mirror.isSetter ? "setters" : 
-        mirror.isGetter ? "getters" :
-        mirror.isConstructor ? "constructors" : 
-        mirror.isTopLevel ? "functions" : "methods";
-    
-    if (data[category] == null) {
-      data[category] = new Map();
-    }
-    data[category][mirrorName] = new Map();
-    data[category][mirrorName]["operator"] = mirror.isOperator;
-    data[category][mirrorName]["static"] = mirror.isStatic;
-    data[category][mirrorName]["rtype"] = mirror.returnType;
-    data[category][mirrorName]["parameters"] = new Map();
-    List parameters = mirror.parameters;
-    parameters.forEach( (ParameterMirror param) {
-      String pName = param.simpleName;
-      data[category][mirrorName]
-        ["parameters"][pName] = new Map();
-      data[category][mirrorName]
-        ["parameters"][pName]["optional"] = param.isOptional;
-      data[category][mirrorName]
-        ["parameters"][pName]["default"] = param.defaultValue;
-      data[category][mirrorName]
-        ["parameters"][pName]["type"] = param.type.toString();
-    });  
-    String comment = _getComment(mirror);
-    data[category][mirrorName]["comment"] = 
-        comment != null ? comment.trim() : null;
-  });
-}
-
-/**
- * Writes documentation for a library to a file.
- */
-//TODO(tmandel): Use flags to put files in specific directory if supported.
-void _writeToFile(String text, String filename) {
-  File file = new File(filename);
-  if (!file.exists()) {
-    file.createSync();
-  }
-  file.openSync();
-  file.writeAsString(text);
-}
\ No newline at end of file
diff --git a/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart b/sdk/lib/_internal/lib/async_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/async_patch.dart
rename to sdk/lib/_internal/lib/async_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/collection_dev_patch.dart b/sdk/lib/_internal/lib/collection_dev_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/collection_dev_patch.dart
rename to sdk/lib/_internal/lib/collection_dev_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/collection_patch.dart b/sdk/lib/_internal/lib/collection_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/collection_patch.dart
rename to sdk/lib/_internal/lib/collection_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/constant_map.dart b/sdk/lib/_internal/lib/constant_map.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/constant_map.dart
rename to sdk/lib/_internal/lib/constant_map.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart b/sdk/lib/_internal/lib/core_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
rename to sdk/lib/_internal/lib/core_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart b/sdk/lib/_internal/lib/foreign_helper.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/foreign_helper.dart
rename to sdk/lib/_internal/lib/foreign_helper.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart b/sdk/lib/_internal/lib/interceptors.dart
similarity index 98%
rename from sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
rename to sdk/lib/_internal/lib/interceptors.dart
index b144a30..bcfef43 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
+++ b/sdk/lib/_internal/lib/interceptors.dart
@@ -22,7 +22,9 @@
                               stringReplaceAllFuncUnchecked,
                               stringReplaceAllUnchecked,
                               stringReplaceFirstUnchecked,
-                              lookupDispatchRecord;
+                              lookupDispatchRecord,
+                              StringMatch,
+                              firstMatchAfter;
 import 'dart:_foreign_helper' show JS;
 
 part 'js_array.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart b/sdk/lib/_internal/lib/io_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
rename to sdk/lib/_internal/lib/io_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
rename to sdk/lib/_internal/lib/isolate_helper.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart b/sdk/lib/_internal/lib/isolate_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
rename to sdk/lib/_internal/lib/isolate_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart b/sdk/lib/_internal/lib/js_array.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/js_array.dart
rename to sdk/lib/_internal/lib/js_array.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
rename to sdk/lib/_internal/lib/js_helper.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
similarity index 76%
rename from sdk/lib/_internal/compiler/implementation/lib/js_mirrors.dart
rename to sdk/lib/_internal/lib/js_mirrors.dart
index db8d87f..a4254b8 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -21,6 +21,11 @@
 
 String getName(Symbol symbol) => n(symbol);
 
+final Map<String, String> mangledNames = JsMirrorSystem.computeMangledNames();
+
+final Map<String, String> reflectiveNames =
+    JsMirrorSystem.computeReflectiveNames();
+
 class JsMirrorSystem implements MirrorSystem {
   TypeMirror get dynamicType => _dynamicType;
   TypeMirror get voidType => _voidType;
@@ -32,10 +37,6 @@
   static final Map<String, List<LibraryMirror>> librariesByName =
       computeLibrariesByName();
 
-  static final Map<String, String> mangledNames = computeMangledNames();
-
-  static final Map<String, String> reflectiveNames = computeReflectiveNames();
-
   Iterable<LibraryMirror> findLibrary(Symbol libraryName) {
     return new List<LibraryMirror>.from(librariesByName[n(libraryName)]);
   }
@@ -61,14 +62,7 @@
 
   static Map<String, String> computeMangledNames() {
     var mangledNames = JS('', 'init.mangledNames');
-    var keys = JS('List', '''
-(function(mangled, hasOwnProperty) {
-  var result = [];
-  for (var key in mangled) {
-    if (hasOwnProperty.call(mangled, key)) result.push(key);
-  }
-  return result;
-})(#, Object.prototype.hasOwnProperty)''', mangledNames);
+    var keys = extractKeys(mangledNames);
     var result = <String, String>{};
     for (String key in keys) {
       result[key] = JS('String', '#[#]', mangledNames, key);
@@ -133,12 +127,15 @@
       String name = _functions[i];
       Symbol symbol = s(name);
       int parameterCount = null; // TODO(ahe): Compute this.
+      bool isStatic = true; // Top-level functions are static.
+      bool isSetter = false; // TODO(ahe): Compute this.
+      bool isGetter = false; // TODO(ahe): Compute this.
       JsMethodMirror mirror =
           // TODO(ahe): Create accessor for accessing $.  It is also
           // used in js_helper.
           new JsMethodMirror(
               symbol, JS('', '#[#]', JS_CURRENT_ISOLATE(), name),
-              parameterCount);
+              parameterCount, isGetter, isSetter, isStatic);
       // TODO(ahe): Cache mirrors.
       result[symbol] = mirror;
       mirror._owner = this;
@@ -276,7 +273,7 @@
     // JavaScript.
     var jsList = new List.from(positionalArguments);
     String reflectiveName = '${n(memberName)}:${positionalArguments.length}:0';
-    String mangledName = JsMirrorSystem.reflectiveNames[reflectiveName];
+    String mangledName = reflectiveNames[reflectiveName];
     return _invoke(memberName, JSInvocationMirror.METHOD, mangledName, jsList);
   }
 
@@ -294,14 +291,14 @@
 
   InstanceMirror setField(Symbol fieldName, Object arg) {
     String reflectiveName = '${n(fieldName)}=';
-    String mangledName = JsMirrorSystem.reflectiveNames[reflectiveName];
+    String mangledName = reflectiveNames[reflectiveName];
     _invoke(s(reflectiveName), JSInvocationMirror.SETTER, mangledName, [arg]);
     return reflect(arg);
   }
 
   InstanceMirror getField(Symbol fieldName) {
     String reflectiveName = n(fieldName);
-    String mangledName = JsMirrorSystem.reflectiveNames[reflectiveName];
+    String mangledName = reflectiveNames[reflectiveName];
     return _invoke(fieldName, JSInvocationMirror.GETTER, mangledName, []);
   }
 
@@ -319,6 +316,7 @@
   final List _fieldsMetadata;
   List _metadata;
   JsClassMirror _superclass;
+  List<JsMethodMirror> _cachedMethods;
 
   // Set as side-effect of accessing JsLibraryMirror.classes.
   JsLibraryMirror _owner;
@@ -330,21 +328,57 @@
 
   Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
 
-  Map<Symbol, MethodMirror> get functions {
+  List<JsMethodMirror> get _methods {
+    if (_cachedMethods != null) return _cachedMethods;
+    var prototype = JS('', '#.prototype', _jsConstructor);
+    List<String> keys = extractKeys(prototype);
+    var result = <JsMethodMirror>[];
+    int i = 0;
+    for (String key in keys) {
+      if (key == '') continue;
+      String simpleName = mangledNames[key];
+      // [simpleName] can be null if [key] represents an implementation
+      // detail, for example, a bailout method, or runtime type support.
+      // It might also be null if the user has limited what is reified for
+      // reflection with metadata.
+      if (simpleName == null) continue;
+      var function = JS('', '#[#]', prototype, key);
+      var mirror = new JsMethodMirror.fromUnmangledName(simpleName, function);
+      result.add(mirror);
+      mirror._owner = this;
+    }
+    return _cachedMethods = result;
+  }
+
+  Map<Symbol, MethodMirror> get methods {
     var result = new Map<Symbol, MethodMirror>();
-    // TODO(ahe): Implement this.
+    for (JsMethodMirror method in _methods) {
+      if (!method.isGetter && !method.isSetter) {
+        result[method.simpleName] = method;
+      }
+    }
     return result;
   }
 
   Map<Symbol, MethodMirror> get getters {
+    // TODO(ahe): Should this include getters for fields?
     var result = new Map<Symbol, MethodMirror>();
-    // TODO(ahe): Implement this.
+    for (JsMethodMirror method in _methods) {
+      if (method.isGetter) {
+        result[method.simpleName] = method;
+      }
+    }
     return result;
   }
 
   Map<Symbol, MethodMirror> get setters {
+    // TODO(ahe): Should this include setters for fields?
     var result = new Map<Symbol, MethodMirror>();
-    // TODO(ahe): Implement this.
+    for (JsMethodMirror method in _methods) {
+      if (method.isSetter) {
+        result[method.simpleName] = method;
+      }
+    }
     return result;
   }
 
@@ -359,20 +393,26 @@
         metadata = _fieldsMetadata[fieldNumber++];
       }
       JsVariableMirror mirror = new JsVariableMirror.from(field, metadata);
-      result[mirror.simpleName] = mirror;
-      mirror._owner = this;
+      if (mirror != null) {
+        result[mirror.simpleName] = mirror;
+        mirror._owner = this;
+      }
     }
     return result;
   }
 
   Map<Symbol, Mirror> get members {
-    Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(functions);
-    addToResult(Symbol key, Mirror value) {
-      result[key] = value;
+    Map<Symbol, Mirror> result = new Map<Symbol, Mirror>.from(variables);
+    for (JsMethodMirror method in _methods) {
+      if (method.isSetter) {
+        String name = n(method.simpleName);
+        name = name.substring(0, name.length - 1);
+        // Filter-out setters corresponding to variables.
+        if (result[s(name)] is VariableMirror) continue;
+      }
+      // Use putIfAbsent to filter-out getters corresponding to variables.
+      result.putIfAbsent(method.simpleName, () => method);
     }
-    getters.forEach(addToResult);
-    setters.forEach(addToResult);
-    variables.forEach(addToResult);
     return result;
   }
 
@@ -392,15 +432,24 @@
 
   InstanceMirror newInstance(Symbol constructorName,
                              List positionalArguments,
-                             [Map<Symbol,dynamic> namedArguments]) {
+                             [Map<Symbol, dynamic> namedArguments]) {
     if (namedArguments != null && !namedArguments.isEmpty) {
       throw new UnsupportedError('Named arguments are not implemented');
     }
-    String constructorName = '${n(simpleName)}\$${n(constructorName)}';
-    return reflect(JS('', r'#[#].apply(#, #)', JS_CURRENT_ISOLATE(),
-                       constructorName,
-                       JS_CURRENT_ISOLATE(),
-                       new List.from(positionalArguments)));
+    String mangledName = '${n(simpleName)}\$${n(constructorName)}';
+    var factory = JS('', '#[#]', JS_CURRENT_ISOLATE(), mangledName);
+    if (factory == null) {
+      // TODO(ahe): Pass namedArguments when NoSuchMethodError has
+      // been fixed to use Symbol.
+      // TODO(ahe): What receiver to use?
+      throw new NoSuchMethodError(
+          this, "constructor ${n(constructorName)}", positionalArguments,
+          null);
+    }
+    return reflect(JS('', r'#.apply(#, #)',
+                      factory,
+                      JS_CURRENT_ISOLATE(),
+                      new List.from(positionalArguments)));
   }
 
   Future<InstanceMirror> newInstanceAsync(
@@ -476,15 +525,11 @@
     int length = descriptor.length;
     var code = fieldCode(descriptor.codeUnitAt(length - 1));
     bool isFinal = false;
-    // code might be 0 if the accessors aren't needed, or if they are
-    // inherited.
-    // TODO(ahe): Ensure code is only 0 for inherited fields.
-    if (code != 0) {
-      bool hasGetter = (code & 3) != 0;
-      bool hasSetter = (code >> 2) != 0;
-      isFinal = !hasSetter;
-      length--;
-    }
+    if (code == 0) return null; // Inherited field.
+    bool hasGetter = (code & 3) != 0;
+    bool hasSetter = (code >> 2) != 0;
+    isFinal = !hasSetter;
+    length--;
     String jsName;
     String accessorName = jsName = descriptor.substring(0, length);
     int divider = descriptor.indexOf(':');
@@ -512,6 +557,8 @@
 
   bool get isPrivate => n(simpleName).startsWith('_');
 
+  bool get isTopLevel => owner != null && owner is LibraryMirror;
+
   String toString() => 'VariableMirror(${n(qualifiedName)})';
 
   static int fieldCode(int code) {
@@ -540,14 +587,17 @@
       throw new RuntimeError('Cannot find callName on "$reflectee"');
     }
     int parameterCount = int.parse(callName.split(r'$')[1]);
+    bool isStatic = true; // TODO(ahe): Compute isStatic correctly.
     if (reflectee is BoundClosure) {
       var target = BoundClosure.targetOf(reflectee);
       var self = BoundClosure.selfOf(reflectee);
       return new JsMethodMirror(
-          s(target), JS('', '#[#]', self, target), parameterCount);
+          s(target), JS('', '#[#]', self, target), parameterCount,
+          false, false, isStatic);
     } else {
       var jsFunction = JS('', '#[#]', reflectee, callName);
-      return new JsMethodMirror(s(callName), jsFunction, parameterCount);
+      return new JsMethodMirror(
+          s(callName), jsFunction, parameterCount, false, false, isStatic);
     }
   }
 
@@ -568,10 +618,41 @@
   final Symbol simpleName;
   final _jsFunction;
   final int _parameterCount;
+  final bool isGetter;
+  final bool isSetter;
+  final bool isStatic;
   DeclarationMirror _owner;
   List _metadata;
 
-  JsMethodMirror(this.simpleName, this._jsFunction, this._parameterCount);
+  JsMethodMirror(this.simpleName,
+                 this._jsFunction,
+                 this._parameterCount,
+                 this.isGetter,
+                 this.isSetter,
+                 this.isStatic);
+
+  factory JsMethodMirror.fromUnmangledName(String name, jsFunction) {
+    List<String> info = name.split(':');
+    name = info[0];
+    bool isSetter = name.endsWith('=');
+    int requiredParameterCount = 0;
+    int optionalParameterCount = 0;
+    bool isGetter = false;
+    if (info.length == 1) {
+      if (isSetter) {
+        requiredParameterCount = 2;
+      } else {
+        isGetter = true;
+        requiredParameterCount = 1;
+      }
+    } else {
+      requiredParameterCount = int.parse(info[1]);
+      optionalParameterCount = int.parse(info[2]);
+    }
+    return new JsMethodMirror(
+        s(name), jsFunction, requiredParameterCount + optionalParameterCount,
+        isGetter, isSetter, false);
+  }
 
   List<ParameterMirror> get parameters {
     // TODO(ahe): Fill the list with parameter mirrors.
@@ -588,6 +669,18 @@
     }
     return _metadata.map(reflect).toList();
   }
+
+  // TODO(ahe): Share with VariableMirror.
+  bool get isPrivate => n(simpleName).startsWith('_');
+
+  // TODO(ahe): Share with VariableMirror.
+  bool get isTopLevel => owner != null && owner is LibraryMirror;
+
+  String toString() {
+    return
+        'MethodMirror(${n(simpleName)}'
+        '${isSetter ? ", setter" : (isGetter ? ", getter" : "")})';
+  }
 }
 
 Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
@@ -602,3 +695,14 @@
   return (metadataFunction == null)
       ? const [] : JS('', '#()', metadataFunction);
 }
+
+List extractKeys(victim) {
+  return JS('List', '''
+(function(victim, hasOwnProperty) {
+  var result = [];
+  for (var key in victim) {
+    if (hasOwnProperty.call(victim, key)) result.push(key);
+  }
+  return result;
+})(#, Object.prototype.hasOwnProperty)''', victim);
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_number.dart b/sdk/lib/_internal/lib/js_number.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/js_number.dart
rename to sdk/lib/_internal/lib/js_number.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart b/sdk/lib/_internal/lib/js_rti.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
rename to sdk/lib/_internal/lib/js_rti.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_string.dart b/sdk/lib/_internal/lib/js_string.dart
similarity index 78%
rename from sdk/lib/_internal/compiler/implementation/lib/js_string.dart
rename to sdk/lib/_internal/lib/js_string.dart
index 92d7c67..2da5ed4 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
+++ b/sdk/lib/_internal/lib/js_string.dart
@@ -25,6 +25,20 @@
     return allMatchesInStringUnchecked(this, str);
   }
 
+  Match matchAsPrefix(String string, [int start = 0]) {
+    if (start < 0 || start > string.length) {
+      throw new RangeError.range(start, 0, string.length);
+    }
+    if (start + this.length > string.length) return null;
+    // TODO(lrn): See if this can be optimized.
+    for (int i = 0; i < this.length; i++) {
+      if (string.codeUnitAt(start + i) != this.codeUnitAt(i)) {
+        return null;
+      }
+    }
+    return new StringMatch(start, string, this);
+  }
+
   String operator +(String other) {
     if (other is !String) throw new ArgumentError(other);
     return JS('String', r'# + #', this, other);
@@ -71,12 +85,15 @@
     }
   }
 
-  bool startsWith(String other) {
-    checkString(other);
-    int otherLength = other.length;
-    if (otherLength > length) return false;
-    return JS('bool', r'# == #', other,
-              JS('String', r'#.substring(0, #)', this, otherLength));
+  bool startsWith(Pattern pattern) {
+    if (pattern is String) {
+      String other = pattern;
+      int otherLength = other.length;
+      if (otherLength > length) return false;
+      return JS('bool', r'# == #', other,
+                JS('String', r'#.substring(0, #)', this, otherLength));
+    }
+    return pattern.matchAsPrefix(this, 0) != null;
   }
 
   String substring(int startIndex, [int endIndex]) {
@@ -196,28 +213,46 @@
 
   Runes get runes => new Runes(this);
 
-  int indexOf(String other, [int start = 0]) {
-    checkNull(other);
-    if (start is !int) throw new ArgumentError(start);
-    if (other is !String) throw new ArgumentError(other);
-    if (start < 0) return -1;
-    return JS('int', r'#.indexOf(#, #)', this, other, start);
+  int indexOf(Pattern pattern, [int start = 0]) {
+    checkNull(pattern);
+    if (start is! int) throw new ArgumentError(start);
+    if (start < 0 || start > this.length) {
+      throw new RangeError.range(start, 0, this.length);
+    }
+    if (pattern is String) {
+      return JS('int', r'#.indexOf(#, #)', this, pattern, start);
+    }
+    if (pattern is JSSyntaxRegExp) {
+      JSSyntaxRegExp re = pattern;
+      Match match = firstMatchAfter(re, this, start);
+      return (match == null) ? -1 : match.start;
+    }
+    for (int i = start; i <= this.length; i++) {
+      if (pattern.matchAsPrefix(this, i) != null) return i;
+    }
+    return -1;
   }
 
-  int lastIndexOf(String other, [int start]) {
-    checkNull(other);
-    if (other is !String) throw new ArgumentError(other);
-    if (start != null) {
-      if (start is !num) throw new ArgumentError(start);
-      if (start < 0) return -1;
-      if (start >= length) {
-        if (other == "") return length;
-        start = length - 1;
-      }
-    } else {
-      start = length - 1;
+  int lastIndexOf(Pattern pattern, [int start]) {
+    checkNull(pattern);
+    if (start == null) {
+      start = length;
+    } else if (start is! int) {
+      throw new ArgumentError(start);
+    } else if (start < 0 || start > this.length) {
+      throw new RangeError.range(start, 0, this.length);
     }
-    return stringLastIndexOfUnchecked(this, other, start);
+    if (pattern is String) {
+      String other = pattern;
+      if (start + other.length > this.length) {
+        start = this.length - other.length;
+      }
+      return stringLastIndexOfUnchecked(this, other, start);
+    }
+    for (int i = start; i >= 0; i--) {
+      if (pattern.matchAsPrefix(this, i) != null) return i;
+    }
+    return -1;
   }
 
   bool contains(Pattern other, [int startIndex = 0]) {
diff --git a/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart b/sdk/lib/_internal/lib/json_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/json_patch.dart
rename to sdk/lib/_internal/lib/json_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/math_patch.dart b/sdk/lib/_internal/lib/math_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/math_patch.dart
rename to sdk/lib/_internal/lib/math_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart b/sdk/lib/_internal/lib/mirrors_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/mirrors_patch.dart
rename to sdk/lib/_internal/lib/mirrors_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
rename to sdk/lib/_internal/lib/native_helper.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart b/sdk/lib/_internal/lib/regexp_helper.dart
similarity index 63%
rename from sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
rename to sdk/lib/_internal/lib/regexp_helper.dart
index 45ab03c..0e923a3 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/lib/regexp_helper.dart
@@ -33,6 +33,12 @@
                        other.isCaseSensitive,
                        true);
 
+  JSSyntaxRegExp._anchoredVersionOf(JSSyntaxRegExp other)
+      : this._internal(other.pattern + "|()",
+                       other.isMultiLine,
+                       other.isCaseSensitive,
+                       true);
+
   static makeNative(
       String pattern, bool multiLine, bool caseSensitive, bool global) {
     checkString(pattern);
@@ -82,21 +88,41 @@
     return new _AllMatchesIterable(this, str);
   }
 
+  Match matchAsPrefix(String string, [int start = 0]) {
+    if (start < 0 || start > string.length) {
+      throw new RangeError.range(start, 0, string.length);
+    }
+    // An "anchored version" of a regexp is created by adding "|()" to the
+    // source. This means that the regexp always matches at the first position
+    // that it tries, and you can see if the original regexp matched, or it
+    // was the added zero-width match that matched, by looking at the last
+    // capture. If it is a String, the match participated, otherwise it didn't.
+    JSSyntaxRegExp regexp = new JSSyntaxRegExp._anchoredVersionOf(this);
+    if (start > 0) {
+      JS("void", "#.lastIndex = #", regExpGetNative(regexp), start);
+    }
+    _MatchImplementation match = regexp.firstMatch(string);
+    if (match == null) return null;
+    if (match._groups[match._groups.length - 1] != null) return null;
+    match._groups.length -= 1;
+    return match;
+  }
+
   String get pattern => _pattern;
   bool get isMultiLine => _isMultiLine;
   bool get isCaseSensitive => _isCaseSensitive;
 }
 
 class _MatchImplementation implements Match {
-  final String pattern;
+  final Pattern pattern;
   final String str;
   final int start;
   final int end;
   final List<String> _groups;
 
   const _MatchImplementation(
-      String this.pattern,
-      String this.str,
+      this.pattern,
+      this.str,
       int this.start,
       int this.end,
       List<String> this._groups);
@@ -124,23 +150,46 @@
 }
 
 class _AllMatchesIterator implements Iterator<Match> {
-  final RegExp _re;
-  final String _str;
+  final RegExp _regExp;
+  final RegExp _globalRegExp;
+  String _str;
   Match _current;
 
   _AllMatchesIterator(JSSyntaxRegExp re, String this._str)
-    : _re = new JSSyntaxRegExp._globalVersionOf(re);
+    : _regExp = re,
+      _globalRegExp = new JSSyntaxRegExp._globalVersionOf(re);
 
   Match get current => _current;
 
   bool moveNext() {
+    if (_str == null) return false;
     // firstMatch actually acts as nextMatch because of
     // hidden global flag.
     if (_current != null && _current.start == _current.end) {
       // Advance implicit start-position if last match was empty.
-      JS("void", "#.lastIndex++", regExpGetNative(_re));
+      JS("void", "#.lastIndex++", regExpGetNative(_globalRegExp));
     }
-    _current = _re.firstMatch(_str);
-    return _current != null;
+    List<String> m =
+        JS('=List|Null', r'#.exec(#)', regExpGetNative(_globalRegExp), _str);
+    if (m == null) {
+      _current = null;
+      _str = null;  // Marks iteration as ended.
+      return false;
+    }
+    var matchStart = JS('int', r'#.index', m);
+    var matchEnd = matchStart + m[0].length;
+    _current = new _MatchImplementation(_regExp, _str, matchStart, matchEnd, m);
+    return true;
   }
 }
+
+Match firstMatchAfter(JSSyntaxRegExp re, String str, int start) {
+  JSSyntaxRegExp global = new JSSyntaxRegExp._globalVersionOf(re);
+  JS("void", "#.lastIndex = #", regExpGetNative(global), start);
+  List<String> m =
+      JS('=List|Null', r'#.exec(#)', regExpGetNative(global), checkString(str));
+  if (m == null) return null;
+  var matchStart = JS('int', r'#.index', m);
+  var matchEnd = matchStart + m[0].length;
+  return new _MatchImplementation(re, str, matchStart, matchEnd, m);
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart b/sdk/lib/_internal/lib/scalarlist_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart
rename to sdk/lib/_internal/lib/scalarlist_patch.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart b/sdk/lib/_internal/lib/string_helper.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
rename to sdk/lib/_internal/lib/string_helper.dart
diff --git a/sdk/lib/_internal/compiler/implementation/lib/typed_data_patch.dart b/sdk/lib/_internal/lib/typed_data_patch.dart
similarity index 100%
rename from sdk/lib/_internal/compiler/implementation/lib/typed_data_patch.dart
rename to sdk/lib/_internal/lib/typed_data_patch.dart
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 5c20d17..d56bdc3 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -24,7 +24,7 @@
 
   "async": const LibraryInfo(
       "async/async.dart",
-      dart2jsPatchPath: "_internal/compiler/implementation/lib/async_patch.dart"),
+      dart2jsPatchPath: "_internal/lib/async_patch.dart"),
 
   "chrome": const LibraryInfo(
       "chrome/dart2js/chrome_dart2js.dart",
@@ -32,11 +32,11 @@
 
   "collection": const LibraryInfo(
       "collection/collection.dart",
-      dart2jsPatchPath: "_internal/compiler/implementation/lib/collection_patch.dart"),
+      dart2jsPatchPath: "_internal/lib/collection_patch.dart"),
 
   "core": const LibraryInfo(
       "core/core.dart",
-      dart2jsPatchPath: "_internal/compiler/implementation/lib/core_patch.dart"),
+      dart2jsPatchPath: "_internal/lib/core_patch.dart"),
 
   "html": const LibraryInfo(
       "html/dartium/html_dartium.dart",
@@ -58,23 +58,23 @@
   "io": const LibraryInfo(
       "io/io.dart",
       category: "Server",
-      dart2jsPatchPath: "_internal/compiler/implementation/lib/io_patch.dart"),
+      dart2jsPatchPath: "_internal/lib/io_patch.dart"),
 
   "isolate": const LibraryInfo(
       "isolate/isolate.dart",
-      dart2jsPatchPath: "_internal/compiler/implementation/lib/isolate_patch.dart"),
+      dart2jsPatchPath: "_internal/lib/isolate_patch.dart"),
 
   "json": const LibraryInfo(
       "json/json.dart",
-      dart2jsPatchPath: "_internal/compiler/implementation/lib/json_patch.dart"),
+      dart2jsPatchPath: "_internal/lib/json_patch.dart"),
 
   "math": const LibraryInfo(
       "math/math.dart",
-      dart2jsPatchPath: "_internal/compiler/implementation/lib/math_patch.dart"),
+      dart2jsPatchPath: "_internal/lib/math_patch.dart"),
 
   "mirrors": const LibraryInfo(
       "mirrors/mirrors.dart",
-      dart2jsPatchPath: "_internal/compiler/implementation/lib/mirrors_patch.dart"),
+      dart2jsPatchPath: "_internal/lib/mirrors_patch.dart"),
 
   "nativewrappers": const LibraryInfo(
       "html/dartium/nativewrappers.dart",
@@ -121,34 +121,34 @@
       category: "Internal",
       documented: false,
       dart2jsPatchPath:
-          "_internal/compiler/implementation/lib/collection_dev_patch.dart"),
+          "_internal/lib/collection_dev_patch.dart"),
 
   "_js_helper": const LibraryInfo(
-      "_internal/compiler/implementation/lib/js_helper.dart",
+      "_internal/lib/js_helper.dart",
       category: "Internal",
       documented: false,
       platforms: DART2JS_PLATFORM),
 
   "_interceptors": const LibraryInfo(
-      "_internal/compiler/implementation/lib/interceptors.dart",
+      "_internal/lib/interceptors.dart",
       category: "Internal",
       documented: false,
       platforms: DART2JS_PLATFORM),
 
   "_foreign_helper": const LibraryInfo(
-      "_internal/compiler/implementation/lib/foreign_helper.dart",
+      "_internal/lib/foreign_helper.dart",
       category: "Internal",
       documented: false,
       platforms: DART2JS_PLATFORM),
 
   "_isolate_helper": const LibraryInfo(
-      "_internal/compiler/implementation/lib/isolate_helper.dart",
+      "_internal/lib/isolate_helper.dart",
       category: "Internal",
       documented: false,
       platforms: DART2JS_PLATFORM),
 
   "_js_mirrors": const LibraryInfo(
-      "_internal/compiler/implementation/lib/js_mirrors.dart",
+      "_internal/lib/js_mirrors.dart",
       category: "Internal",
       documented: false,
       platforms: DART2JS_PLATFORM),
diff --git a/sdk/lib/_internal/pub/test/error_group_test.dart b/sdk/lib/_internal/pub/test/error_group_test.dart
index 7cad9be..8fbd032 100644
--- a/sdk/lib/_internal/pub/test/error_group_test.dart
+++ b/sdk/lib/_internal/pub/test/error_group_test.dart
@@ -64,13 +64,13 @@
         "been called", () {
       completer.complete('value');
 
-      completer.future.then(expectAsync1((_) {
-        expect(() => errorGroup.registerFuture(new Future.value()),
+      expect(completer.future
+                 .then((_) => errorGroup.registerFuture(new Future.value())),
+             throwsStateError);
+      expect(completer.future
+                 .then((_) => errorGroup.registerStream(
+                     new StreamController(sync: true).stream)),
             throwsStateError);
-        expect(() => errorGroup.registerStream(
-            new StreamController(sync: true).stream),
-            throwsStateError);
-      }));
     });
 
     test('should pass through an exception from the future if it has a '
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index 03287d7..f77fc23 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.dart
@@ -12,6 +12,7 @@
 part 'maps.dart';
 part 'queue.dart';
 part 'splay_tree.dart';
+part 'linked_list.dart';
 part 'hash_set.dart';
 part 'hash_map.dart';
 part 'list.dart';
diff --git a/sdk/lib/collection/collection_sources.gypi b/sdk/lib/collection/collection_sources.gypi
index 7fe56d8..5f2ab98 100644
--- a/sdk/lib/collection/collection_sources.gypi
+++ b/sdk/lib/collection/collection_sources.gypi
@@ -14,6 +14,7 @@
     'iterator.dart',
     'linked_hash_map.dart',
     'linked_hash_set.dart',
+    'linked_list.dart',
     'list.dart',
     'maps.dart',
     'queue.dart',
diff --git a/sdk/lib/collection/linked_list.dart b/sdk/lib/collection/linked_list.dart
new file mode 100644
index 0000000..a9c8989
--- /dev/null
+++ b/sdk/lib/collection/linked_list.dart
@@ -0,0 +1,232 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.collection;
+
+
+/**
+ * A linked list implementation, providing O(1) removal(unlink) of elements and
+ * manual traversal through [next] and [previous].
+ *
+ * The list elements must extend [LinkedListEntry].
+ */
+class LinkedList<E extends LinkedListEntry<E>>
+    extends IterableBase<E>
+    implements _LinkedListLink {
+  int _modificationCount = 0;
+  int _length = 0;
+  _LinkedListLink _next;
+  _LinkedListLink _previous;
+
+  /**
+   * Construct a new empty linked list.
+   */
+  LinkedList() {
+    _next = _previous = this;
+  }
+
+  /**
+   * Add [entry] to the beginning of the list.
+   */
+  void addFirst(E entry) {
+    _insertAfter(this, entry);
+  }
+
+  /**
+   * Add [entry] to the end of the list.
+   */
+  void add(E entry) {
+    _insertAfter(_previous, entry);
+  }
+
+  /**
+   * Add [entries] to the end of the list.
+   */
+  void addAll(Iterable<E> entries) {
+    entries.forEach((entry) => _insertAfter(_previous, entry));
+  }
+
+  /**
+   * Remove [entry] from the list. This is the same as calling `entry.unlink()`.
+   *
+   * If [entry] is not in the list, `false` is returned.
+   */
+  bool remove(E entry) {
+    if (entry._list != this) return false;
+    _unlink(entry);  // Unlink will decrement length.
+    return true;
+  }
+
+  Iterator<E> get iterator => new _LinkedListIterator<E>(this);
+
+  String toString() => ToString.iterableToString(this);
+
+  int get length => _length;
+
+  void clear() {
+    _modificationCount++;
+    _LinkedListLink next = _next;
+    while (!identical(next, this)) {
+      E entry = next;
+      next = entry._next;
+      entry._next = entry._previous = entry._list = null;
+    }
+    _next = _previous = this;
+    _length = 0;
+  }
+
+  E get first {
+    if (identical(_next, this)) {
+      throw new StateError('No such element');
+    }
+    return _next;
+  }
+
+  E get last {
+    if (identical(_previous, this)) {
+      throw new StateError('No such element');
+    }
+    return _previous;
+  }
+
+  E get single {
+    if (identical(_previous, this)) {
+      throw new StateError('No such element');
+    }
+    if (!identical(_previous, _next)) {
+      throw new StateError('Too many elements');
+    }
+    return _next;
+  }
+
+  /**
+   * Call [action] with each entry in the list.
+   *
+   * It's an error if [action] modify the list.
+   */
+  void forEach(void action(E entry)) {
+    int modificationCount = _modificationCount;
+    _LinkedListLink current = _next;
+    while (!identical(current, this)) {
+      action(current);
+      if (modificationCount != _modificationCount) {
+        throw new ConcurrentModificationError(this);
+      }
+      current = current._next;
+    }
+  }
+
+  bool get isEmpty => _length == 0;
+
+  void _insertAfter(_LinkedListLink entry, E newEntry) {
+    if (newEntry.list != null) {
+      throw new StateError(
+          'LinkedListEntry is already in a LinkedList');
+    }
+    _modificationCount++;
+    newEntry._list = this;
+    var predecessor = entry;
+    var successor = entry._next;
+    successor._previous = newEntry;
+    newEntry._previous = predecessor;
+    newEntry._next = successor;
+    predecessor._next = newEntry;
+    _length++;
+  }
+
+  void _unlink(LinkedListEntry<E> entry) {
+    _modificationCount++;
+    entry._next._previous = entry._previous;
+    entry._previous._next = entry._next;
+    _length--;
+    entry._list = entry._next = entry._previous = null;
+  }
+}
+
+
+class _LinkedListIterator<E extends LinkedListEntry>
+    implements Iterator<E> {
+  final LinkedList<E> _list;
+  final int _modificationCount;
+  E _current;
+  _LinkedListLink _next;
+
+  _LinkedListIterator(LinkedList<E> list)
+    : _list = list,
+      _modificationCount = list._modificationCount,
+      _next = list._next;
+
+  E get current => _current;
+
+  bool moveNext() {
+    if (identical(_next, _list)) {
+      _current = null;
+      return false;
+    }
+    if (_modificationCount != _list._modificationCount) {
+      throw new ConcurrentModificationError(this);
+    }
+    _current = _next;
+    _next = _next._next;
+    return true;
+  }
+}
+
+
+class _LinkedListLink {
+  _LinkedListLink _next;
+  _LinkedListLink _previous;
+}
+
+
+/**
+ * Entry element for a [LinkedList]. Any entry must extend this class.
+ */
+abstract class LinkedListEntry<E> implements _LinkedListLink {
+  LinkedList<E> _list;
+  _LinkedListLink _next;
+  _LinkedListLink _previous;
+
+  /**
+   * Get the list containing this element.
+   */
+  LinkedList<E> get list => _list;
+
+  /**
+   * Unlink the element from the list.
+   */
+  void unlink() {
+    _list._unlink(this);
+  }
+
+  /**
+   * Return the succeeding element in the list.
+   */
+  E get next {
+    if (identical(_next, _list)) return null;
+    return _next as E;
+  }
+
+  /**
+   * Return the preceeding element in the list.
+   */
+  E get previous {
+    if (identical(_previous, _list)) return null;
+    return _previous as E;
+  }
+
+  /**
+   * insert an element after this.
+   */
+  void insertAfter(E entry) {
+    _list._insertAfter(this, entry);
+  }
+
+  /**
+   * Insert an element before this.
+   */
+  void insertBefore(E entry) {
+    _list._insertAfter(_previous, entry);
+  }
+}
diff --git a/sdk/lib/core/pattern.dart b/sdk/lib/core/pattern.dart
index ac7815d..d85c8ac 100644
--- a/sdk/lib/core/pattern.dart
+++ b/sdk/lib/core/pattern.dart
@@ -5,5 +5,28 @@
 part of dart.core;
 
 abstract class Pattern {
+  /**
+   * Match this pattern against the string repeatedly.
+   *
+   * The iterable will contain all the non-overlapping matches of the
+   * pattern on the string, ordered by start index.
+   *
+   * The matches are found by repeatedly finding the first match
+   * of the pattern on the string, starting from the end of the previous
+   * match, and initially starting from index zero.
+   *
+   * If the pattern matches the empty string at some point, the next
+   * match is found by starting at the previous match's end plus one.
+   */
   Iterable<Match> allMatches(String str);
+
+  /**
+   * Match this pattern against the start of string.
+   *
+   * If [start] is provided, it must be an integer in the range `0` ..
+   * `string.length`. In that case, this patten is tested against the
+   * string at the [start] position. That is, a match is returned if the
+   * pattern can match a part of the string starting from position [start].
+   */
+  Match matchAsPrefix(String string, [int start = 0]);
 }
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 0b4fbd4..0d2503a 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -105,23 +105,29 @@
   bool endsWith(String other);
 
   /**
-   * Returns whether this string starts with [other].
+   * Returns whether this string starts with a match of [pattern].
    */
-  bool startsWith(String other);
+  bool startsWith(Pattern pattern);
 
   /**
-   * Returns the first location of [other] in this string starting at
-   * [start] (inclusive).
-   * Returns -1 if [other] could not be found.
+   * Returns the first position of a match of [pattern] in this string,
+   * starting at [start] (inclusive).
+   *
+   * Returns -1 if a match could not be found.
+   *
+   * It is an error if start is negative or greater than [length].
    */
-  int indexOf(String other, [int start]);
+  int indexOf(Pattern pattern, [int start]);
 
   /**
-   * Returns the last location of [other] in this string, searching
+   * Returns the last position of a match [pattern] in this string, searching
    * backward starting at [start] (inclusive).
+   *
    * Returns -1 if [other] could not be found.
+   *
+   * It is an error if start is negative or greater than [length].
    */
-  int lastIndexOf(String other, [int start]);
+  int lastIndexOf(Pattern pattern, [int start]);
 
   /**
    * Returns whether this string is empty.
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index 75bd214..c0a7fdf 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -107,7 +107,7 @@
          query: _emptyIfNull(m[_COMPONENT_QUERY_DATA]),
          fragment: _emptyIfNull(m[_COMPONENT_FRAGMENT]));
 
-  /*
+  /**
    * Create a new URI from its components.
    *
    * Each component is set through a named argument. Any number of
@@ -177,7 +177,7 @@
     _path = _makePath(path, pathSegments);
   }
 
-  /*
+  /**
    * Returns the URI path split into its segments. Each of the
    * segments in the returned list have been decoded. If the path is
    * empty the empty list will be returned. A leading slash `/` does
@@ -200,30 +200,22 @@
     return _pathSegments;
   }
 
-  /*
+  /**
    * Returns the URI query split into a map according to the rules
-   * specified for FORM post in the HTML 4.01 specification. Each key
-   * and value in the returned map have been decoded. If there is no
-   * query the empty map will be returned.
+   * specified for FORM post in the [HTML 4.01 specification section 17.13.4]
+   * (http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4
+   * "HTML 4.01 section 17.13.4"). Each key and value in the returned map
+   * has been decoded. If there is no query the empty map is returned.
+   *
+   * Keys in the query string that have no value are mapped to the
+   * empty string.
    *
    * The returned map is unmodifiable and will throw [UnsupportedError] on any
    * calls that would mutate it.
    */
   Map<String, String> get queryParameters {
     if (_queryParameters == null) {
-      var map;
-      map = query.split("&").fold({}, (map, element) {
-        int index = element.indexOf("=");
-        if (index == -1) {
-          if (!element.isEmpty) map[decodeQueryComponent(element)] = "";
-        } else if (index != 0) {
-          var key = element.substring(0, index);
-          var value = element.substring(index + 1);
-          map[Uri.decodeQueryComponent(key)] = decodeQueryComponent(value);
-        }
-        return map;
-      });
-      _queryParameters = new _UnmodifiableMap(map);
+      _queryParameters = new _UnmodifiableMap(splitQueryString(query));
     }
     return _queryParameters;
   }
@@ -549,6 +541,9 @@
                    fragment: reference.fragment);
   }
 
+  /**
+   * Returns whether the URI has an [authority] component.
+   */
   bool get hasAuthority => host != "";
 
   /**
@@ -647,7 +642,7 @@
     return _uriEncode(_unreserved2396Table, component);
   }
 
-  /*
+  /**
    * Encode the string [component] according to the HTML 4.01 rules
    * for encoding the posting of a HTML form as a query string
    * component.
@@ -718,6 +713,32 @@
     return _uriDecode(uri);
   }
 
+  /**
+   * Returns the [query] split into a map according to the rules
+   * specified for FORM post in the
+   * [HTML 4.01 specification section 17.13.4]
+   * (http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4
+   * "HTML 4.01 section 17.13.4"). Each key and value in the returned
+   * map has been decoded. If the [query]
+   * is the empty string an empty map is returned.
+   *
+   * Keys in the query string that have no value are mapped to the
+   * empty string.
+   */
+  static Map<String, String> splitQueryString(String query) {
+    return query.split("&").fold({}, (map, element) {
+      int index = element.indexOf("=");
+      if (index == -1) {
+        if (element != "") map[decodeQueryComponent(element)] = "";
+      } else if (index != 0) {
+        var key = element.substring(0, index);
+        var value = element.substring(index + 1);
+        map[Uri.decodeQueryComponent(key)] = decodeQueryComponent(value);
+      }
+      return map;
+    });
+  }
+
   // Frequently used character codes.
   static const int _PERCENT = 0x25;
   static const int _PLUS = 0x2B;
@@ -1004,6 +1025,9 @@
   V putIfAbsent(K key, V ifAbsent()) {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
+  addAll(Map other) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
   V remove(K key) {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 1022653..abafc22 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -105,7 +105,7 @@
 
 @DocsEditable
 @DomName('HTMLAnchorElement')
-class AnchorElement extends Element native "HTMLAnchorElement" {
+class AnchorElement extends _HTMLElement native "HTMLAnchorElement" {
 
   @DomName('HTMLAnchorElement.HTMLAnchorElement')
   @DocsEditable
@@ -362,7 +362,7 @@
  * on MDN.
  */
 @DomName('HTMLAreaElement')
-class AreaElement extends Element native "HTMLAreaElement" {
+class AreaElement extends _HTMLElement native "HTMLAreaElement" {
 
   @DomName('HTMLAreaElement.HTMLAreaElement')
   @DocsEditable
@@ -464,7 +464,7 @@
 
 @DocsEditable
 @DomName('HTMLBRElement')
-class BRElement extends Element native "HTMLBRElement" {
+class BRElement extends _HTMLElement native "HTMLBRElement" {
 
   @DomName('HTMLBRElement.HTMLBRElement')
   @DocsEditable
@@ -492,7 +492,7 @@
 
 @DocsEditable
 @DomName('HTMLBaseElement')
-class BaseElement extends Element native "HTMLBaseElement" {
+class BaseElement extends _HTMLElement native "HTMLBaseElement" {
 
   @DomName('HTMLBaseElement.HTMLBaseElement')
   @DocsEditable
@@ -567,7 +567,7 @@
 
 @DocsEditable
 @DomName('HTMLBodyElement')
-class BodyElement extends Element native "HTMLBodyElement" {
+class BodyElement extends _HTMLElement native "HTMLBodyElement" {
 
   @DomName('HTMLBodyElement.blurEvent')
   @DocsEditable
@@ -676,7 +676,7 @@
 
 @DocsEditable
 @DomName('HTMLButtonElement')
-class ButtonElement extends Element native "HTMLButtonElement" {
+class ButtonElement extends _HTMLElement native "HTMLButtonElement" {
 
   @DomName('HTMLButtonElement.HTMLButtonElement')
   @DocsEditable
@@ -785,7 +785,15 @@
 
 
 @DomName('HTMLCanvasElement')
-class CanvasElement extends Element implements CanvasImageSource native "HTMLCanvasElement" {
+class CanvasElement extends _HTMLElement implements CanvasImageSource native "HTMLCanvasElement" {
+
+  @DomName('HTMLCanvasElement.webglcontextlostEvent')
+  @DocsEditable
+  static const EventStreamProvider<gl.ContextEvent> webGlContextLostEvent = const EventStreamProvider<gl.ContextEvent>('webglcontextlost');
+
+  @DomName('HTMLCanvasElement.webglcontextrestoredEvent')
+  @DocsEditable
+  static const EventStreamProvider<gl.ContextEvent> webGlContextRestoredEvent = const EventStreamProvider<gl.ContextEvent>('webglcontextrestored');
 
   @DomName('HTMLCanvasElement.HTMLCanvasElement')
   @DocsEditable
@@ -869,6 +877,14 @@
   @DocsEditable
   String toDataUrl(String type, [num quality]) native;
 
+  @DomName('HTMLCanvasElement.onwebglcontextlost')
+  @DocsEditable
+  Stream<gl.ContextEvent> get onWebGlContextLost => webGlContextLostEvent.forTarget(this);
+
+  @DomName('HTMLCanvasElement.onwebglcontextrestored')
+  @DocsEditable
+  Stream<gl.ContextEvent> get onWebGlContextRestored => webGlContextRestoredEvent.forTarget(this);
+
   /** An API for drawing on this canvas. */
   CanvasRenderingContext2D get context2D =>
       JS('Null|CanvasRenderingContext2D', '#.getContext(#)', this, '2d');
@@ -1807,7 +1823,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME, '26')
 @Experimental
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#content-element
-class ContentElement extends Element native "HTMLContentElement" {
+class ContentElement extends _HTMLElement native "HTMLContentElement" {
 
   @DomName('HTMLContentElement.HTMLContentElement')
   @DocsEditable
@@ -2096,7 +2112,7 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental
 // http://www.w3.org/TR/css3-animations/#CSSKeyframeRule-interface
-class CssKeyframeRule extends CssRule native "WebKitCSSKeyframeRule" {
+class CssKeyframeRule extends CssRule native "CSSKeyframeRule,MozCSSKeyframeRule,WebKitCSSKeyframeRule" {
 
   @DomName('WebKitCSSKeyframeRule.keyText')
   @DocsEditable
@@ -2117,7 +2133,7 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental
 // http://www.w3.org/TR/css3-animations/#csskeyframesrule
-class CssKeyframesRule extends CssRule native "WebKitCSSKeyframesRule" {
+class CssKeyframesRule extends CssRule native "CSSKeyframesRule,MozCSSKeyframesRule,WebKitCSSKeyframesRule" {
 
   @DomName('WebKitCSSKeyframesRule.cssRules')
   @DocsEditable
@@ -2141,9 +2157,14 @@
   @DocsEditable
   CssKeyframeRule findRule(String key) native;
 
-  @DomName('WebKitCSSKeyframesRule.insertRule')
-  @DocsEditable
-  void insertRule(String rule) native;
+
+  void appendRule(String rule) {
+    if (JS('bool', '("appendRule" in #)', this)) {
+      JS('', '#.appendRule(#)', this, rule);
+    } else {
+      JS('', '#.insertRule(#)', this, rule);
+    }
+  }
 }
 // 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
@@ -5959,7 +5980,7 @@
 
 @DocsEditable
 @DomName('HTMLDListElement')
-class DListElement extends Element native "HTMLDListElement" {
+class DListElement extends _HTMLElement native "HTMLDListElement" {
 
   @DomName('HTMLDListElement.HTMLDListElement')
   @DocsEditable
@@ -5976,7 +5997,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.IE, '10')
 @SupportedBrowser(SupportedBrowser.SAFARI)
-class DataListElement extends Element native "HTMLDataListElement" {
+class DataListElement extends _HTMLElement native "HTMLDataListElement" {
 
   @DomName('HTMLDataListElement.HTMLDataListElement')
   @DocsEditable
@@ -6146,7 +6167,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental
-class DetailsElement extends Element native "HTMLDetailsElement" {
+class DetailsElement extends _HTMLElement native "HTMLDetailsElement" {
 
   @DomName('HTMLDetailsElement.HTMLDetailsElement')
   @DocsEditable
@@ -6282,7 +6303,7 @@
 @DocsEditable
 @DomName('HTMLDialogElement')
 @Unstable
-class DialogElement extends Element native "HTMLDialogElement" {
+class DialogElement extends _HTMLElement native "HTMLDialogElement" {
 
   @DomName('HTMLDialogElement.open')
   @DocsEditable
@@ -6522,7 +6543,7 @@
  * * [Inline-level element](http://www.w3.org/TR/CSS2/visuren.html#inline-boxes) from W3C.
  */
 @DomName('HTMLDivElement')
-class DivElement extends Element native "HTMLDivElement" {
+class DivElement extends _HTMLElement native "HTMLDivElement" {
 
   @DomName('HTMLDivElement.HTMLDivElement')
   @DocsEditable
@@ -9483,7 +9504,7 @@
 @SupportedBrowser(SupportedBrowser.IE)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Unstable
-class EmbedElement extends Element native "HTMLEmbedElement" {
+class EmbedElement extends _HTMLElement native "HTMLEmbedElement" {
 
   @DomName('HTMLEmbedElement.HTMLEmbedElement')
   @DocsEditable
@@ -10149,7 +10170,7 @@
 @DocsEditable
 @DomName('HTMLFieldSetElement')
 @Unstable
-class FieldSetElement extends Element native "HTMLFieldSetElement" {
+class FieldSetElement extends _HTMLElement native "HTMLFieldSetElement" {
 
   @DomName('HTMLFieldSetElement.HTMLFieldSetElement')
   @DocsEditable
@@ -10908,7 +10929,7 @@
 
 @DocsEditable
 @DomName('HTMLFormElement')
-class FormElement extends Element native "HTMLFormElement" {
+class FormElement extends _HTMLElement native "HTMLFormElement" {
 
   @DomName('HTMLFormElement.autocompleteEvent')
   @DocsEditable
@@ -11178,7 +11199,7 @@
  * An `<hr>` tag.
  */
 @DomName('HTMLHRElement')
-class HRElement extends Element native "HTMLHRElement" {
+class HRElement extends _HTMLElement native "HTMLHRElement" {
 
   @DomName('HTMLHRElement.HTMLHRElement')
   @DocsEditable
@@ -11231,7 +11252,7 @@
 
 @DocsEditable
 @DomName('HTMLHeadElement')
-class HeadElement extends Element native "HTMLHeadElement" {
+class HeadElement extends _HTMLElement native "HTMLHeadElement" {
 
   @DomName('HTMLHeadElement.HTMLHeadElement')
   @DocsEditable
@@ -11244,7 +11265,7 @@
 
 @DocsEditable
 @DomName('HTMLHeadingElement')
-class HeadingElement extends Element native "HTMLHeadingElement" {
+class HeadingElement extends _HTMLElement native "HTMLHeadingElement" {
 
   @DomName('HTMLHeadingElement.HTMLHeadingElement')
   @DocsEditable
@@ -11645,7 +11666,7 @@
 
 @DocsEditable
 @DomName('HTMLHtmlElement')
-class HtmlElement extends Element native "HTMLHtmlElement" {
+class HtmlElement extends _HTMLElement native "HTMLHtmlElement" {
 
   @DomName('HTMLHtmlElement.HTMLHtmlElement')
   @DocsEditable
@@ -12307,7 +12328,7 @@
 
 @DocsEditable
 @DomName('HTMLIFrameElement')
-class IFrameElement extends Element native "HTMLIFrameElement" {
+class IFrameElement extends _HTMLElement native "HTMLIFrameElement" {
 
   @DomName('HTMLIFrameElement.HTMLIFrameElement')
   @DocsEditable
@@ -12377,7 +12398,7 @@
 
 
 @DomName('HTMLImageElement')
-class ImageElement extends Element implements CanvasImageSource native "HTMLImageElement" {
+class ImageElement extends _HTMLElement implements CanvasImageSource native "HTMLImageElement" {
 
   @DomName('HTMLImageElement.HTMLImageElement')
   @DocsEditable
@@ -12456,7 +12477,7 @@
 
 
 @DomName('HTMLInputElement')
-class InputElement extends Element implements
+class InputElement extends _HTMLElement implements
     HiddenInputElement,
     SearchInputElement,
     TextInputElement,
@@ -13515,7 +13536,7 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-keygen-element
-class KeygenElement extends Element native "HTMLKeygenElement" {
+class KeygenElement extends _HTMLElement native "HTMLKeygenElement" {
 
   @DomName('HTMLKeygenElement.HTMLKeygenElement')
   @DocsEditable
@@ -13586,7 +13607,7 @@
 
 @DocsEditable
 @DomName('HTMLLIElement')
-class LIElement extends Element native "HTMLLIElement" {
+class LIElement extends _HTMLElement native "HTMLLIElement" {
 
   @DomName('HTMLLIElement.HTMLLIElement')
   @DocsEditable
@@ -13609,7 +13630,7 @@
 
 @DocsEditable
 @DomName('HTMLLabelElement')
-class LabelElement extends Element native "HTMLLabelElement" {
+class LabelElement extends _HTMLElement native "HTMLLabelElement" {
 
   @DomName('HTMLLabelElement.HTMLLabelElement')
   @DocsEditable
@@ -13634,7 +13655,7 @@
 
 @DocsEditable
 @DomName('HTMLLegendElement')
-class LegendElement extends Element native "HTMLLegendElement" {
+class LegendElement extends _HTMLElement native "HTMLLegendElement" {
 
   @DomName('HTMLLegendElement.HTMLLegendElement')
   @DocsEditable
@@ -13651,7 +13672,7 @@
 
 @DocsEditable
 @DomName('HTMLLinkElement')
-class LinkElement extends Element native "HTMLLinkElement" {
+class LinkElement extends _HTMLElement native "HTMLLinkElement" {
 
   @DomName('HTMLLinkElement.HTMLLinkElement')
   @DocsEditable
@@ -13786,7 +13807,7 @@
 
 @DocsEditable
 @DomName('HTMLMapElement')
-class MapElement extends Element native "HTMLMapElement" {
+class MapElement extends _HTMLElement native "HTMLMapElement" {
 
   @DomName('HTMLMapElement.HTMLMapElement')
   @DocsEditable
@@ -13896,7 +13917,7 @@
 @DocsEditable
 @DomName('HTMLMediaElement')
 @Unstable
-class MediaElement extends Element native "HTMLMediaElement" {
+class MediaElement extends _HTMLElement native "HTMLMediaElement" {
 
   @DomName('HTMLMediaElement.canplayEvent')
   @DocsEditable
@@ -14224,6 +14245,7 @@
 
   @DomName('HTMLMediaElement.canPlayType')
   @DocsEditable
+  @Unstable
   String canPlayType(String type, String keySystem) native;
 
   @DomName('HTMLMediaElement.load')
@@ -15034,7 +15056,7 @@
  *  * [Menu Element](http://www.w3.org/TR/html5/the-menu-element.html#the-menu-element) from the W3C.
  */
 @DomName('HTMLMenuElement')
-class MenuElement extends Element native "HTMLMenuElement" {
+class MenuElement extends _HTMLElement native "HTMLMenuElement" {
 
   @DomName('HTMLMenuElement.HTMLMenuElement')
   @DocsEditable
@@ -15192,7 +15214,7 @@
 
 @DocsEditable
 @DomName('HTMLMetaElement')
-class MetaElement extends Element native "HTMLMetaElement" {
+class MetaElement extends _HTMLElement native "HTMLMetaElement" {
 
   @DomName('HTMLMetaElement.HTMLMetaElement')
   @DocsEditable
@@ -15254,7 +15276,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Unstable
-class MeterElement extends Element native "HTMLMeterElement" {
+class MeterElement extends _HTMLElement native "HTMLMeterElement" {
 
   @DomName('HTMLMeterElement.HTMLMeterElement')
   @DocsEditable
@@ -15568,7 +15590,7 @@
 @DocsEditable
 @DomName('HTMLModElement')
 @Unstable
-class ModElement extends Element native "HTMLModElement" {
+class ModElement extends _HTMLElement native "HTMLModElement" {
 
   @DomName('HTMLModElement.cite')
   @DocsEditable
@@ -17132,7 +17154,7 @@
 
 @DocsEditable
 @DomName('HTMLOListElement')
-class OListElement extends Element native "HTMLOListElement" {
+class OListElement extends _HTMLElement native "HTMLOListElement" {
 
   @DomName('HTMLOListElement.HTMLOListElement')
   @DocsEditable
@@ -17161,7 +17183,7 @@
 @SupportedBrowser(SupportedBrowser.IE)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Unstable
-class ObjectElement extends Element native "HTMLObjectElement" {
+class ObjectElement extends _HTMLElement native "HTMLObjectElement" {
 
   @DomName('HTMLObjectElement.HTMLObjectElement')
   @DocsEditable
@@ -17239,7 +17261,7 @@
 
 @DocsEditable
 @DomName('HTMLOptGroupElement')
-class OptGroupElement extends Element native "HTMLOptGroupElement" {
+class OptGroupElement extends _HTMLElement native "HTMLOptGroupElement" {
 
   @DomName('HTMLOptGroupElement.HTMLOptGroupElement')
   @DocsEditable
@@ -17260,7 +17282,7 @@
 
 @DocsEditable
 @DomName('HTMLOptionElement')
-class OptionElement extends Element native "HTMLOptionElement" {
+class OptionElement extends _HTMLElement native "HTMLOptionElement" {
 
   @DomName('HTMLOptionElement.HTMLOptionElement')
   @DocsEditable
@@ -17323,7 +17345,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.SAFARI)
-class OutputElement extends Element native "HTMLOutputElement" {
+class OutputElement extends _HTMLElement native "HTMLOutputElement" {
 
   @DomName('HTMLOutputElement.HTMLOutputElement')
   @DocsEditable
@@ -17439,7 +17461,7 @@
 
 @DocsEditable
 @DomName('HTMLParagraphElement')
-class ParagraphElement extends Element native "HTMLParagraphElement" {
+class ParagraphElement extends _HTMLElement native "HTMLParagraphElement" {
 
   @DomName('HTMLParagraphElement.HTMLParagraphElement')
   @DocsEditable
@@ -17453,7 +17475,7 @@
 @DocsEditable
 @DomName('HTMLParamElement')
 @Unstable
-class ParamElement extends Element native "HTMLParamElement" {
+class ParamElement extends _HTMLElement native "HTMLParamElement" {
 
   @DomName('HTMLParamElement.HTMLParamElement')
   @DocsEditable
@@ -18063,7 +18085,7 @@
 
 @DocsEditable
 @DomName('HTMLPreElement')
-class PreElement extends Element native "HTMLPreElement" {
+class PreElement extends _HTMLElement native "HTMLPreElement" {
 
   @DomName('HTMLPreElement.HTMLPreElement')
   @DocsEditable
@@ -18109,7 +18131,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.IE, '10')
 @SupportedBrowser(SupportedBrowser.SAFARI)
-class ProgressElement extends Element native "HTMLProgressElement" {
+class ProgressElement extends _HTMLElement native "HTMLProgressElement" {
 
   @DomName('HTMLProgressElement.HTMLProgressElement')
   @DocsEditable
@@ -18165,7 +18187,7 @@
 
 @DocsEditable
 @DomName('HTMLQuoteElement')
-class QuoteElement extends Element native "HTMLQuoteElement" {
+class QuoteElement extends _HTMLElement native "HTMLQuoteElement" {
 
   @DomName('HTMLQuoteElement.HTMLQuoteElement')
   @DocsEditable
@@ -18220,6 +18242,9 @@
 class Range native "Range" {
   factory Range() => document.$dom_createRange();
 
+  factory Range.fromPoint(Point point) =>
+      document.$dom_caretRangeFromPoint(point.x, point.y);
+
   @DomName('Range.END_TO_END')
   @DocsEditable
   static const int END_TO_END = 2;
@@ -18429,7 +18454,7 @@
 @DomName('RTCDataChannel')
 // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCDataChannel
 @Experimental
-class RtcDataChannel extends EventTarget native "RTCDataChannel" {
+class RtcDataChannel extends EventTarget native "RTCDataChannel,DataChannel" {
 
   @DomName('RTCDataChannel.closeEvent')
   @DocsEditable
@@ -19119,7 +19144,7 @@
 
 @DocsEditable
 @DomName('HTMLScriptElement')
-class ScriptElement extends Element native "HTMLScriptElement" {
+class ScriptElement extends _HTMLElement native "HTMLScriptElement" {
 
   @DomName('HTMLScriptElement.HTMLScriptElement')
   @DocsEditable
@@ -19297,7 +19322,7 @@
 
 
 @DomName('HTMLSelectElement')
-class SelectElement extends Element native "HTMLSelectElement" {
+class SelectElement extends _HTMLElement native "HTMLSelectElement" {
 
   @DomName('HTMLSelectElement.HTMLSelectElement')
   @DocsEditable
@@ -19538,7 +19563,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME, '26')
 @Experimental
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#shadow-element
-class ShadowElement extends Element native "HTMLShadowElement" {
+class ShadowElement extends _HTMLElement native "HTMLShadowElement" {
 
   @DomName('HTMLShadowElement.HTMLShadowElement')
   @DocsEditable
@@ -19733,7 +19758,7 @@
 
 @DocsEditable
 @DomName('HTMLSourceElement')
-class SourceElement extends Element native "HTMLSourceElement" {
+class SourceElement extends _HTMLElement native "HTMLSourceElement" {
 
   @DomName('HTMLSourceElement.HTMLSourceElement')
   @DocsEditable
@@ -19758,7 +19783,7 @@
 
 @DocsEditable
 @DomName('HTMLSpanElement')
-class SpanElement extends Element native "HTMLSpanElement" {
+class SpanElement extends _HTMLElement native "HTMLSpanElement" {
 
   @DomName('HTMLSpanElement.HTMLSpanElement')
   @DocsEditable
@@ -20655,7 +20680,7 @@
 
 @DocsEditable
 @DomName('HTMLStyleElement')
-class StyleElement extends Element native "HTMLStyleElement" {
+class StyleElement extends _HTMLElement native "HTMLStyleElement" {
 
   @DomName('HTMLStyleElement.HTMLStyleElement')
   @DocsEditable
@@ -20744,7 +20769,7 @@
 
 @DocsEditable
 @DomName('HTMLTableCaptionElement')
-class TableCaptionElement extends Element native "HTMLTableCaptionElement" {
+class TableCaptionElement extends _HTMLElement native "HTMLTableCaptionElement" {
 
   @DomName('HTMLTableCaptionElement.HTMLTableCaptionElement')
   @DocsEditable
@@ -20757,7 +20782,7 @@
 
 @DocsEditable
 @DomName('HTMLTableCellElement')
-class TableCellElement extends Element native "HTMLTableCellElement" {
+class TableCellElement extends _HTMLElement native "HTMLTableCellElement" {
 
   @DomName('HTMLTableCellElement.HTMLTableCellElement')
   @DocsEditable
@@ -20786,7 +20811,7 @@
 
 @DocsEditable
 @DomName('HTMLTableColElement')
-class TableColElement extends Element native "HTMLTableColElement" {
+class TableColElement extends _HTMLElement native "HTMLTableColElement" {
 
   @DomName('HTMLTableColElement.HTMLTableColElement')
   @DocsEditable
@@ -20803,7 +20828,7 @@
 
 @DocsEditable
 @DomName('HTMLTableElement')
-class TableElement extends Element native "HTMLTableElement" {
+class TableElement extends _HTMLElement native "HTMLTableElement" {
 
   @DomName('HTMLTableElement.tBodies')
   List<TableSectionElement> get tBodies =>
@@ -20911,7 +20936,7 @@
 
 @DocsEditable
 @DomName('HTMLTableRowElement')
-class TableRowElement extends Element native "HTMLTableRowElement" {
+class TableRowElement extends _HTMLElement native "HTMLTableRowElement" {
 
   @DomName('HTMLTableRowElement.cells')
   List<TableCellElement> get cells =>
@@ -20957,7 +20982,7 @@
 
 @DocsEditable
 @DomName('HTMLTableSectionElement')
-class TableSectionElement extends Element native "HTMLTableSectionElement" {
+class TableSectionElement extends _HTMLElement native "HTMLTableSectionElement" {
 
   @DomName('HTMLTableSectionElement.rows')
   List<TableRowElement> get rows =>
@@ -20996,7 +21021,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#template-element
-class TemplateElement extends Element native "HTMLTemplateElement" {
+class TemplateElement extends _HTMLElement native "HTMLTemplateElement" {
 
   @DomName('HTMLTemplateElement.HTMLTemplateElement')
   @DocsEditable
@@ -21203,7 +21228,7 @@
 
 @DocsEditable
 @DomName('HTMLTextAreaElement')
-class TextAreaElement extends Element native "HTMLTextAreaElement" {
+class TextAreaElement extends _HTMLElement native "HTMLTextAreaElement" {
 
   @DomName('HTMLTextAreaElement.HTMLTextAreaElement')
   @DocsEditable
@@ -21735,7 +21760,7 @@
 
 @DocsEditable
 @DomName('HTMLTitleElement')
-class TitleElement extends Element native "HTMLTitleElement" {
+class TitleElement extends _HTMLElement native "HTMLTitleElement" {
 
   @DomName('HTMLTitleElement.HTMLTitleElement')
   @DocsEditable
@@ -21995,7 +22020,7 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#the-track-element
 @Experimental
-class TrackElement extends Element native "HTMLTrackElement" {
+class TrackElement extends _HTMLElement native "HTMLTrackElement" {
 
   @DomName('HTMLTrackElement.HTMLTrackElement')
   @DocsEditable
@@ -22262,7 +22287,7 @@
 
 @DocsEditable
 @DomName('HTMLUListElement')
-class UListElement extends Element native "HTMLUListElement" {
+class UListElement extends _HTMLElement native "HTMLUListElement" {
 
   @DomName('HTMLUListElement.HTMLUListElement')
   @DocsEditable
@@ -22275,7 +22300,7 @@
 
 @DocsEditable
 @DomName('HTMLUnknownElement')
-class UnknownElement extends Element native "HTMLUnknownElement" {
+class UnknownElement extends _HTMLElement native "HTMLUnknownElement" {
 }
 // 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
@@ -22916,12 +22941,17 @@
   }
 
   /**
-   * Returns a Future that completes just before the window is about to repaint
-   * so the user can draw an animation frame
+   * Returns a Future that completes just before the window is about to 
+   * repaint so the user can draw an animation frame.
    *
    * If you need to later cancel this animation, use [requestAnimationFrame]
    * instead.
    *
+   * The [Future] completes to a timestamp that represents a floating
+   * point value of the number of milliseconds that have elapsed since the page 
+   * started to load (which is also the timestamp at this call to 
+   * animationFrame).
+   *
    * Note: The code that runs when the future completes should call
    * [animationFrame] again for the animation to continue.
    */
@@ -25012,7 +25042,7 @@
 @DomName('HTMLAppletElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#the-applet-element
 @deprecated // deprecated
-abstract class _HTMLAppletElement extends Element native "HTMLAppletElement" {
+abstract class _HTMLAppletElement extends _HTMLElement native "HTMLAppletElement" {
 }
 // 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
@@ -25023,7 +25053,7 @@
 @DomName('HTMLBaseFontElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#basefont
 @deprecated // deprecated
-abstract class _HTMLBaseFontElement extends Element native "HTMLBaseFontElement" {
+abstract class _HTMLBaseFontElement extends _HTMLElement native "HTMLBaseFontElement" {
 }
 // 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
@@ -25034,7 +25064,7 @@
 @DomName('HTMLDirectoryElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dir
 @deprecated // deprecated
-abstract class _HTMLDirectoryElement extends Element native "HTMLDirectoryElement" {
+abstract class _HTMLDirectoryElement extends _HTMLElement native "HTMLDirectoryElement" {
 }
 // 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
@@ -25045,7 +25075,7 @@
 @DomName('HTMLFontElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#htmlfontelement
 @deprecated // deprecated
-abstract class _HTMLFontElement extends Element native "HTMLFontElement" {
+abstract class _HTMLFontElement extends _HTMLElement native "HTMLFontElement" {
 }
 // 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
@@ -25056,7 +25086,7 @@
 @DomName('HTMLFrameElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#htmlframeelement
 @deprecated // deprecated
-abstract class _HTMLFrameElement extends Element native "HTMLFrameElement" {
+abstract class _HTMLFrameElement extends _HTMLElement native "HTMLFrameElement" {
 }
 // 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
@@ -25067,7 +25097,7 @@
 @DomName('HTMLFrameSetElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#frameset
 @deprecated // deprecated
-abstract class _HTMLFrameSetElement extends Element native "HTMLFrameSetElement" {
+abstract class _HTMLFrameSetElement extends _HTMLElement native "HTMLFrameSetElement" {
 }
 // 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
@@ -25078,7 +25108,7 @@
 @DomName('HTMLMarqueeElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#the-marquee-element
 @deprecated // deprecated
-abstract class _HTMLMarqueeElement extends Element native "HTMLMarqueeElement" {
+abstract class _HTMLMarqueeElement extends _HTMLElement native "HTMLMarqueeElement" {
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 8409fee..a97473f 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -114,7 +114,7 @@
 
 @DocsEditable
 @DomName('HTMLAnchorElement')
-class AnchorElement extends _Element_Merged {
+class AnchorElement extends _HTMLElement {
   AnchorElement.internal() : super.internal();
 
   @DomName('HTMLAnchorElement.HTMLAnchorElement')
@@ -445,7 +445,7 @@
  * on MDN.
  */
 @DomName('HTMLAreaElement')
-class AreaElement extends _Element_Merged {
+class AreaElement extends _HTMLElement {
   AreaElement.internal() : super.internal();
 
   @DomName('HTMLAreaElement.HTMLAreaElement')
@@ -583,7 +583,7 @@
 
 @DocsEditable
 @DomName('HTMLBRElement')
-class BRElement extends _Element_Merged {
+class BRElement extends _HTMLElement {
   BRElement.internal() : super.internal();
 
   @DomName('HTMLBRElement.HTMLBRElement')
@@ -619,7 +619,7 @@
 
 @DocsEditable
 @DomName('HTMLBaseElement')
-class BaseElement extends _Element_Merged {
+class BaseElement extends _HTMLElement {
   BaseElement.internal() : super.internal();
 
   @DomName('HTMLBaseElement.HTMLBaseElement')
@@ -717,7 +717,7 @@
 
 @DocsEditable
 @DomName('HTMLBodyElement')
-class BodyElement extends _Element_Merged {
+class BodyElement extends _HTMLElement {
   BodyElement.internal() : super.internal();
 
   @DomName('HTMLBodyElement.blurEvent')
@@ -830,7 +830,7 @@
 
 @DocsEditable
 @DomName('HTMLButtonElement')
-class ButtonElement extends _Element_Merged {
+class ButtonElement extends _HTMLElement {
   ButtonElement.internal() : super.internal();
 
   @DomName('HTMLButtonElement.HTMLButtonElement')
@@ -991,9 +991,17 @@
 
 
 @DomName('HTMLCanvasElement')
-class CanvasElement extends _Element_Merged implements CanvasImageSource {
+class CanvasElement extends _HTMLElement implements CanvasImageSource {
   CanvasElement.internal() : super.internal();
 
+  @DomName('HTMLCanvasElement.webglcontextlostEvent')
+  @DocsEditable
+  static const EventStreamProvider<gl.ContextEvent> webGlContextLostEvent = const EventStreamProvider<gl.ContextEvent>('webglcontextlost');
+
+  @DomName('HTMLCanvasElement.webglcontextrestoredEvent')
+  @DocsEditable
+  static const EventStreamProvider<gl.ContextEvent> webGlContextRestoredEvent = const EventStreamProvider<gl.ContextEvent>('webglcontextrestored');
+
   @DomName('HTMLCanvasElement.HTMLCanvasElement')
   @DocsEditable
   factory CanvasElement({int width, int height}) {
@@ -1071,6 +1079,14 @@
   @DocsEditable
   String toDataUrl(String type, [num quality]) native "HTMLCanvasElement_toDataURL_Callback";
 
+  @DomName('HTMLCanvasElement.onwebglcontextlost')
+  @DocsEditable
+  Stream<gl.ContextEvent> get onWebGlContextLost => webGlContextLostEvent.forTarget(this);
+
+  @DomName('HTMLCanvasElement.onwebglcontextrestored')
+  @DocsEditable
+  Stream<gl.ContextEvent> get onWebGlContextRestored => webGlContextRestoredEvent.forTarget(this);
+
   /** An API for drawing on this canvas. */
   CanvasRenderingContext2D get context2D => getContext('2d');
 
@@ -2172,7 +2188,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME, '26')
 @Experimental
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#content-element
-class ContentElement extends _Element_Merged {
+class ContentElement extends _HTMLElement {
   ContentElement.internal() : super.internal();
 
   @DomName('HTMLContentElement.HTMLContentElement')
@@ -2541,8 +2557,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 
 @DocsEditable
 @DomName('WebKitCSSKeyframesRule')
@@ -2579,7 +2593,8 @@
 
   @DomName('WebKitCSSKeyframesRule.insertRule')
   @DocsEditable
-  void insertRule(String rule) native "CSSKeyframesRule_insertRule_Callback";
+  void appendRule(String rule) native "CSSKeyframesRule_insertRule_Callback";
+
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -6534,7 +6549,7 @@
 
 @DocsEditable
 @DomName('HTMLDListElement')
-class DListElement extends _Element_Merged {
+class DListElement extends _HTMLElement {
   DListElement.internal() : super.internal();
 
   @DomName('HTMLDListElement.HTMLDListElement')
@@ -6555,7 +6570,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.IE, '10')
 @SupportedBrowser(SupportedBrowser.SAFARI)
-class DataListElement extends _Element_Merged {
+class DataListElement extends _HTMLElement {
   DataListElement.internal() : super.internal();
 
   @DomName('HTMLDataListElement.HTMLDataListElement')
@@ -6754,7 +6769,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental
-class DetailsElement extends _Element_Merged {
+class DetailsElement extends _HTMLElement {
   DetailsElement.internal() : super.internal();
 
   @DomName('HTMLDetailsElement.HTMLDetailsElement')
@@ -6910,7 +6925,7 @@
 @DocsEditable
 @DomName('HTMLDialogElement')
 @Unstable
-class DialogElement extends _Element_Merged {
+class DialogElement extends _HTMLElement {
   DialogElement.internal() : super.internal();
 
   @DomName('HTMLDialogElement.open')
@@ -7081,7 +7096,7 @@
  * * [Inline-level element](http://www.w3.org/TR/CSS2/visuren.html#inline-boxes) from W3C.
  */
 @DomName('HTMLDivElement')
-class DivElement extends _Element_Merged {
+class DivElement extends _HTMLElement {
   DivElement.internal() : super.internal();
 
   @DomName('HTMLDivElement.HTMLDivElement')
@@ -9906,7 +9921,7 @@
 @SupportedBrowser(SupportedBrowser.IE)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Unstable
-class EmbedElement extends _Element_Merged {
+class EmbedElement extends _HTMLElement {
   EmbedElement.internal() : super.internal();
 
   @DomName('HTMLEmbedElement.HTMLEmbedElement')
@@ -10603,7 +10618,7 @@
 @DocsEditable
 @DomName('HTMLFieldSetElement')
 @Unstable
-class FieldSetElement extends _Element_Merged {
+class FieldSetElement extends _HTMLElement {
   FieldSetElement.internal() : super.internal();
 
   @DomName('HTMLFieldSetElement.HTMLFieldSetElement')
@@ -11395,7 +11410,7 @@
 
 @DocsEditable
 @DomName('HTMLFormElement')
-class FormElement extends _Element_Merged {
+class FormElement extends _HTMLElement {
   FormElement.internal() : super.internal();
 
   @DomName('HTMLFormElement.autocompleteEvent')
@@ -11695,7 +11710,7 @@
  * An `<hr>` tag.
  */
 @DomName('HTMLHRElement')
-class HRElement extends _Element_Merged {
+class HRElement extends _HTMLElement {
   HRElement.internal() : super.internal();
 
   @DomName('HTMLHRElement.HTMLHRElement')
@@ -11750,7 +11765,7 @@
 
 @DocsEditable
 @DomName('HTMLHeadElement')
-class HeadElement extends _Element_Merged {
+class HeadElement extends _HTMLElement {
   HeadElement.internal() : super.internal();
 
   @DomName('HTMLHeadElement.HTMLHeadElement')
@@ -11767,7 +11782,7 @@
 
 @DocsEditable
 @DomName('HTMLHeadingElement')
-class HeadingElement extends _Element_Merged {
+class HeadingElement extends _HTMLElement {
   HeadingElement.internal() : super.internal();
 
   @DomName('HTMLHeadingElement.HTMLHeadingElement')
@@ -12181,7 +12196,7 @@
 
 @DocsEditable
 @DomName('HTMLHtmlElement')
-class HtmlElement extends _Element_Merged {
+class HtmlElement extends _HTMLElement {
   HtmlElement.internal() : super.internal();
 
   @DomName('HTMLHtmlElement.HTMLHtmlElement')
@@ -12878,7 +12893,7 @@
 
 @DocsEditable
 @DomName('HTMLIFrameElement')
-class IFrameElement extends _Element_Merged {
+class IFrameElement extends _HTMLElement {
   IFrameElement.internal() : super.internal();
 
   @DomName('HTMLIFrameElement.HTMLIFrameElement')
@@ -12983,7 +12998,7 @@
 
 
 @DomName('HTMLImageElement')
-class ImageElement extends _Element_Merged implements CanvasImageSource {
+class ImageElement extends _HTMLElement implements CanvasImageSource {
   ImageElement.internal() : super.internal();
 
   @DomName('HTMLImageElement.HTMLImageElement')
@@ -13101,7 +13116,7 @@
 
 
 @DomName('HTMLInputElement')
-class InputElement extends _Element_Merged implements
+class InputElement extends _HTMLElement implements
     HiddenInputElement,
     SearchInputElement,
     TextInputElement,
@@ -14354,7 +14369,7 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Experimental
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-keygen-element
-class KeygenElement extends _Element_Merged {
+class KeygenElement extends _HTMLElement {
   KeygenElement.internal() : super.internal();
 
   @DomName('HTMLKeygenElement.HTMLKeygenElement')
@@ -14447,7 +14462,7 @@
 
 @DocsEditable
 @DomName('HTMLLIElement')
-class LIElement extends _Element_Merged {
+class LIElement extends _HTMLElement {
   LIElement.internal() : super.internal();
 
   @DomName('HTMLLIElement.HTMLLIElement')
@@ -14484,7 +14499,7 @@
 
 @DocsEditable
 @DomName('HTMLLabelElement')
-class LabelElement extends _Element_Merged {
+class LabelElement extends _HTMLElement {
   LabelElement.internal() : super.internal();
 
   @DomName('HTMLLabelElement.HTMLLabelElement')
@@ -14517,7 +14532,7 @@
 
 @DocsEditable
 @DomName('HTMLLegendElement')
-class LegendElement extends _Element_Merged {
+class LegendElement extends _HTMLElement {
   LegendElement.internal() : super.internal();
 
   @DomName('HTMLLegendElement.HTMLLegendElement')
@@ -14538,7 +14553,7 @@
 
 @DocsEditable
 @DomName('HTMLLinkElement')
-class LinkElement extends _Element_Merged {
+class LinkElement extends _HTMLElement {
   LinkElement.internal() : super.internal();
 
   @DomName('HTMLLinkElement.HTMLLinkElement')
@@ -14735,7 +14750,7 @@
 
 @DocsEditable
 @DomName('HTMLMapElement')
-class MapElement extends _Element_Merged {
+class MapElement extends _HTMLElement {
   MapElement.internal() : super.internal();
 
   @DomName('HTMLMapElement.HTMLMapElement')
@@ -14877,7 +14892,7 @@
 @DocsEditable
 @DomName('HTMLMediaElement')
 @Unstable
-class MediaElement extends _Element_Merged {
+class MediaElement extends _HTMLElement {
   MediaElement.internal() : super.internal();
 
   @DomName('HTMLMediaElement.canplayEvent')
@@ -15285,6 +15300,7 @@
 
   @DomName('HTMLMediaElement.canPlayType')
   @DocsEditable
+  @Unstable
   String canPlayType(String type, String keySystem) native "HTMLMediaElement_canPlayType_Callback";
 
   @DomName('HTMLMediaElement.load')
@@ -16175,7 +16191,7 @@
  *  * [Menu Element](http://www.w3.org/TR/html5/the-menu-element.html#the-menu-element) from the W3C.
  */
 @DomName('HTMLMenuElement')
-class MenuElement extends _Element_Merged {
+class MenuElement extends _HTMLElement {
   MenuElement.internal() : super.internal();
 
   @DomName('HTMLMenuElement.HTMLMenuElement')
@@ -16317,7 +16333,7 @@
 
 @DocsEditable
 @DomName('HTMLMetaElement')
-class MetaElement extends _Element_Merged {
+class MetaElement extends _HTMLElement {
   MetaElement.internal() : super.internal();
 
   @DomName('HTMLMetaElement.HTMLMetaElement')
@@ -16396,7 +16412,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Unstable
-class MeterElement extends _Element_Merged {
+class MeterElement extends _HTMLElement {
   MeterElement.internal() : super.internal();
 
   @DomName('HTMLMeterElement.HTMLMeterElement')
@@ -16774,7 +16790,7 @@
 @DocsEditable
 @DomName('HTMLModElement')
 @Unstable
-class ModElement extends _Element_Merged {
+class ModElement extends _HTMLElement {
   ModElement.internal() : super.internal();
 
   @DomName('HTMLModElement.cite')
@@ -18322,7 +18338,7 @@
 
 @DocsEditable
 @DomName('HTMLOListElement')
-class OListElement extends _Element_Merged {
+class OListElement extends _HTMLElement {
   OListElement.internal() : super.internal();
 
   @DomName('HTMLOListElement.HTMLOListElement')
@@ -18367,7 +18383,7 @@
 @SupportedBrowser(SupportedBrowser.IE)
 @SupportedBrowser(SupportedBrowser.SAFARI)
 @Unstable
-class ObjectElement extends _Element_Merged {
+class ObjectElement extends _HTMLElement {
   ObjectElement.internal() : super.internal();
 
   @DomName('HTMLObjectElement.HTMLObjectElement')
@@ -18479,7 +18495,7 @@
 
 @DocsEditable
 @DomName('HTMLOptGroupElement')
-class OptGroupElement extends _Element_Merged {
+class OptGroupElement extends _HTMLElement {
   OptGroupElement.internal() : super.internal();
 
   @DomName('HTMLOptGroupElement.HTMLOptGroupElement')
@@ -18512,7 +18528,7 @@
 
 @DocsEditable
 @DomName('HTMLOptionElement')
-class OptionElement extends _Element_Merged {
+class OptionElement extends _HTMLElement {
   OptionElement.internal() : super.internal();
 
   @DomName('HTMLOptionElement.HTMLOptionElement')
@@ -18585,7 +18601,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.SAFARI)
-class OutputElement extends _Element_Merged {
+class OutputElement extends _HTMLElement {
   OutputElement.internal() : super.internal();
 
   @DomName('HTMLOutputElement.HTMLOutputElement')
@@ -18723,7 +18739,7 @@
 
 @DocsEditable
 @DomName('HTMLParagraphElement')
-class ParagraphElement extends _Element_Merged {
+class ParagraphElement extends _HTMLElement {
   ParagraphElement.internal() : super.internal();
 
   @DomName('HTMLParagraphElement.HTMLParagraphElement')
@@ -18741,7 +18757,7 @@
 @DocsEditable
 @DomName('HTMLParamElement')
 @Unstable
-class ParamElement extends _Element_Merged {
+class ParamElement extends _HTMLElement {
   ParamElement.internal() : super.internal();
 
   @DomName('HTMLParamElement.HTMLParamElement')
@@ -19412,7 +19428,7 @@
 
 @DocsEditable
 @DomName('HTMLPreElement')
-class PreElement extends _Element_Merged {
+class PreElement extends _HTMLElement {
   PreElement.internal() : super.internal();
 
   @DomName('HTMLPreElement.HTMLPreElement')
@@ -19476,7 +19492,7 @@
 @SupportedBrowser(SupportedBrowser.FIREFOX)
 @SupportedBrowser(SupportedBrowser.IE, '10')
 @SupportedBrowser(SupportedBrowser.SAFARI)
-class ProgressElement extends _Element_Merged {
+class ProgressElement extends _HTMLElement {
   ProgressElement.internal() : super.internal();
 
   @DomName('HTMLProgressElement.HTMLProgressElement')
@@ -19546,7 +19562,7 @@
 
 @DocsEditable
 @DomName('HTMLQuoteElement')
-class QuoteElement extends _Element_Merged {
+class QuoteElement extends _HTMLElement {
   QuoteElement.internal() : super.internal();
 
   @DomName('HTMLQuoteElement.HTMLQuoteElement')
@@ -19606,6 +19622,9 @@
 @Unstable
 class Range extends NativeFieldWrapperClass1 {
   factory Range() => document.$dom_createRange();
+
+  factory Range.fromPoint(Point point) =>
+      document.$dom_caretRangeFromPoint(point.x, point.y);
   Range.internal();
 
   @DomName('Range.END_TO_END')
@@ -20470,7 +20489,7 @@
 
 @DocsEditable
 @DomName('HTMLScriptElement')
-class ScriptElement extends _Element_Merged {
+class ScriptElement extends _HTMLElement {
   ScriptElement.internal() : super.internal();
 
   @DomName('HTMLScriptElement.HTMLScriptElement')
@@ -20698,7 +20717,7 @@
 
 
 @DomName('HTMLSelectElement')
-class SelectElement extends _Element_Merged {
+class SelectElement extends _HTMLElement {
   SelectElement.internal() : super.internal();
 
   @DomName('HTMLSelectElement.HTMLSelectElement')
@@ -20980,7 +20999,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME, '26')
 @Experimental
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#shadow-element
-class ShadowElement extends _Element_Merged {
+class ShadowElement extends _HTMLElement {
   ShadowElement.internal() : super.internal();
 
   @DomName('HTMLShadowElement.HTMLShadowElement')
@@ -21200,7 +21219,7 @@
 
 @DocsEditable
 @DomName('HTMLSourceElement')
-class SourceElement extends _Element_Merged {
+class SourceElement extends _HTMLElement {
   SourceElement.internal() : super.internal();
 
   @DomName('HTMLSourceElement.HTMLSourceElement')
@@ -21241,7 +21260,7 @@
 
 @DocsEditable
 @DomName('HTMLSpanElement')
-class SpanElement extends _Element_Merged {
+class SpanElement extends _HTMLElement {
   SpanElement.internal() : super.internal();
 
   @DomName('HTMLSpanElement.HTMLSpanElement')
@@ -22291,7 +22310,7 @@
 
 @DocsEditable
 @DomName('HTMLStyleElement')
-class StyleElement extends _Element_Merged {
+class StyleElement extends _HTMLElement {
   StyleElement.internal() : super.internal();
 
   @DomName('HTMLStyleElement.HTMLStyleElement')
@@ -22412,7 +22431,7 @@
 
 @DocsEditable
 @DomName('HTMLTableCaptionElement')
-class TableCaptionElement extends _Element_Merged {
+class TableCaptionElement extends _HTMLElement {
   TableCaptionElement.internal() : super.internal();
 
   @DomName('HTMLTableCaptionElement.HTMLTableCaptionElement')
@@ -22429,7 +22448,7 @@
 
 @DocsEditable
 @DomName('HTMLTableCellElement')
-class TableCellElement extends _Element_Merged {
+class TableCellElement extends _HTMLElement {
   TableCellElement.internal() : super.internal();
 
   @DomName('HTMLTableCellElement.HTMLTableCellElement')
@@ -22474,7 +22493,7 @@
 
 @DocsEditable
 @DomName('HTMLTableColElement')
-class TableColElement extends _Element_Merged {
+class TableColElement extends _HTMLElement {
   TableColElement.internal() : super.internal();
 
   @DomName('HTMLTableColElement.HTMLTableColElement')
@@ -22497,7 +22516,7 @@
 
 @DocsEditable
 @DomName('HTMLTableElement')
-class TableElement extends _Element_Merged {
+class TableElement extends _HTMLElement {
 
   @DomName('HTMLTableElement.tBodies')
   List<TableSectionElement> get tBodies =>
@@ -22611,7 +22630,7 @@
 
 @DocsEditable
 @DomName('HTMLTableRowElement')
-class TableRowElement extends _Element_Merged {
+class TableRowElement extends _HTMLElement {
 
   @DomName('HTMLTableRowElement.cells')
   List<TableCellElement> get cells =>
@@ -22656,7 +22675,7 @@
 
 @DocsEditable
 @DomName('HTMLTableSectionElement')
-class TableSectionElement extends _Element_Merged {
+class TableSectionElement extends _HTMLElement {
 
   @DomName('HTMLTableSectionElement.rows')
   List<TableRowElement> get rows =>
@@ -22694,7 +22713,7 @@
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#template-element
-class TemplateElement extends _Element_Merged {
+class TemplateElement extends _HTMLElement {
   TemplateElement.internal() : super.internal();
 
   @DomName('HTMLTemplateElement.HTMLTemplateElement')
@@ -22903,7 +22922,7 @@
 
 @DocsEditable
 @DomName('HTMLTextAreaElement')
-class TextAreaElement extends _Element_Merged {
+class TextAreaElement extends _HTMLElement {
   TextAreaElement.internal() : super.internal();
 
   @DomName('HTMLTextAreaElement.HTMLTextAreaElement')
@@ -23598,7 +23617,7 @@
 
 @DocsEditable
 @DomName('HTMLTitleElement')
-class TitleElement extends _Element_Merged {
+class TitleElement extends _HTMLElement {
   TitleElement.internal() : super.internal();
 
   @DomName('HTMLTitleElement.HTMLTitleElement')
@@ -23851,7 +23870,7 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#the-track-element
 @Experimental
-class TrackElement extends _Element_Merged {
+class TrackElement extends _HTMLElement {
   TrackElement.internal() : super.internal();
 
   @DomName('HTMLTrackElement.HTMLTrackElement')
@@ -24143,7 +24162,7 @@
 
 @DocsEditable
 @DomName('HTMLUListElement')
-class UListElement extends _Element_Merged {
+class UListElement extends _HTMLElement {
   UListElement.internal() : super.internal();
 
   @DomName('HTMLUListElement.HTMLUListElement')
@@ -24160,7 +24179,7 @@
 
 @DocsEditable
 @DomName('HTMLUnknownElement')
-class UnknownElement extends _Element_Merged {
+class UnknownElement extends _HTMLElement {
   UnknownElement.internal() : super.internal();
 
 }
@@ -24719,12 +24738,17 @@
   }
 
   /**
-   * Returns a Future that completes just before the window is about to repaint
-   * so the user can draw an animation frame
+   * Returns a Future that completes just before the window is about to 
+   * repaint so the user can draw an animation frame.
    *
    * If you need to later cancel this animation, use [requestAnimationFrame]
    * instead.
    *
+   * The [Future] completes to a timestamp that represents a floating
+   * point value of the number of milliseconds that have elapsed since the page 
+   * started to load (which is also the timestamp at this call to 
+   * animationFrame).
+   *
    * Note: The code that runs when the future completes should call
    * [animationFrame] again for the animation to continue.
    */
@@ -26482,159 +26506,6 @@
 
 
 @DocsEditable
-@DomName('HTMLElement')
-class _Element_Merged extends Element {
-  _Element_Merged.internal() : super.internal();
-
-  @DomName('HTMLElement.contentEditable')
-  @DocsEditable
-  String get contentEditable native "HTMLElement_contentEditable_Getter";
-
-  @DomName('HTMLElement.contentEditable')
-  @DocsEditable
-  void set contentEditable(String value) native "HTMLElement_contentEditable_Setter";
-
-  @DomName('HTMLElement.dir')
-  @DocsEditable
-  String get dir native "HTMLElement_dir_Getter";
-
-  @DomName('HTMLElement.dir')
-  @DocsEditable
-  void set dir(String value) native "HTMLElement_dir_Setter";
-
-  @DomName('HTMLElement.draggable')
-  @DocsEditable
-  bool get draggable native "HTMLElement_draggable_Getter";
-
-  @DomName('HTMLElement.draggable')
-  @DocsEditable
-  void set draggable(bool value) native "HTMLElement_draggable_Setter";
-
-  @DomName('HTMLElement.hidden')
-  @DocsEditable
-  bool get hidden native "HTMLElement_hidden_Getter";
-
-  @DomName('HTMLElement.hidden')
-  @DocsEditable
-  void set hidden(bool value) native "HTMLElement_hidden_Setter";
-
-  @DomName('HTMLElement.id')
-  @DocsEditable
-  String get id native "HTMLElement_id_Getter";
-
-  @DomName('HTMLElement.id')
-  @DocsEditable
-  void set id(String value) native "HTMLElement_id_Setter";
-
-  @DomName('HTMLElement.innerHTML')
-  @DocsEditable
-  String get innerHtml native "HTMLElement_innerHTML_Getter";
-
-  @DomName('HTMLElement.innerHTML')
-  @DocsEditable
-  void set innerHtml(String value) native "HTMLElement_innerHTML_Setter";
-
-  @DomName('HTMLElement.isContentEditable')
-  @DocsEditable
-  bool get isContentEditable native "HTMLElement_isContentEditable_Getter";
-
-  @DomName('HTMLElement.lang')
-  @DocsEditable
-  String get lang native "HTMLElement_lang_Getter";
-
-  @DomName('HTMLElement.lang')
-  @DocsEditable
-  void set lang(String value) native "HTMLElement_lang_Setter";
-
-  @DomName('HTMLElement.outerHTML')
-  @DocsEditable
-  String get outerHtml native "HTMLElement_outerHTML_Getter";
-
-  @DomName('HTMLElement.spellcheck')
-  @DocsEditable
-  // http://blog.whatwg.org/the-road-to-html-5-spellchecking
-  @Experimental // nonstandard
-  bool get spellcheck native "HTMLElement_spellcheck_Getter";
-
-  @DomName('HTMLElement.spellcheck')
-  @DocsEditable
-  // http://blog.whatwg.org/the-road-to-html-5-spellchecking
-  @Experimental // nonstandard
-  void set spellcheck(bool value) native "HTMLElement_spellcheck_Setter";
-
-  @DomName('HTMLElement.tabIndex')
-  @DocsEditable
-  int get tabIndex native "HTMLElement_tabIndex_Getter";
-
-  @DomName('HTMLElement.tabIndex')
-  @DocsEditable
-  void set tabIndex(int value) native "HTMLElement_tabIndex_Setter";
-
-  @DomName('HTMLElement.title')
-  @DocsEditable
-  String get title native "HTMLElement_title_Getter";
-
-  @DomName('HTMLElement.title')
-  @DocsEditable
-  void set title(String value) native "HTMLElement_title_Setter";
-
-  @DomName('HTMLElement.translate')
-  @DocsEditable
-  bool get translate native "HTMLElement_translate_Getter";
-
-  @DomName('HTMLElement.translate')
-  @DocsEditable
-  void set translate(bool value) native "HTMLElement_translate_Setter";
-
-  @DomName('HTMLElement.webkitdropzone')
-  @DocsEditable
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-dropzone-attribute
-  String get dropzone native "HTMLElement_webkitdropzone_Getter";
-
-  @DomName('HTMLElement.webkitdropzone')
-  @DocsEditable
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-dropzone-attribute
-  void set dropzone(String value) native "HTMLElement_webkitdropzone_Setter";
-
-  @DomName('HTMLElement.click')
-  @DocsEditable
-  void click() native "HTMLElement_click_Callback";
-
-  @DomName('HTMLElement.getInputContext')
-  @DocsEditable
-  // http://www.w3.org/TR/ime-api/#the-getinputcontext-method
-  @Experimental
-  InputMethodContext getInputContext() native "HTMLElement_getInputContext_Callback";
-
-  @DomName('HTMLElement.insertAdjacentElement')
-  @DocsEditable
-  @Experimental // non-standard
-  Element insertAdjacentElement(String where, Element element) native "HTMLElement_insertAdjacentElement_Callback";
-
-  @DomName('HTMLElement.insertAdjacentHTML')
-  @DocsEditable
-  void insertAdjacentHtml(String where, String html) native "HTMLElement_insertAdjacentHTML_Callback";
-
-  @DomName('HTMLElement.insertAdjacentText')
-  @DocsEditable
-  @Experimental // non-standard
-  void insertAdjacentText(String where, String text) native "HTMLElement_insertAdjacentText_Callback";
-
-}
-// 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.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable
 @DomName('Entity')
 @deprecated // deprecated
 class _Entity extends Node {
@@ -26937,7 +26808,7 @@
 @DomName('HTMLAppletElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#the-applet-element
 @deprecated // deprecated
-abstract class _HTMLAppletElement extends _Element_Merged {
+abstract class _HTMLAppletElement extends _HTMLElement {
   _HTMLAppletElement.internal() : super.internal();
 
 }
@@ -26952,7 +26823,7 @@
 @DomName('HTMLBaseFontElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#basefont
 @deprecated // deprecated
-abstract class _HTMLBaseFontElement extends _Element_Merged {
+abstract class _HTMLBaseFontElement extends _HTMLElement {
   _HTMLBaseFontElement.internal() : super.internal();
 
 }
@@ -26967,7 +26838,7 @@
 @DomName('HTMLDirectoryElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#dir
 @deprecated // deprecated
-abstract class _HTMLDirectoryElement extends _Element_Merged {
+abstract class _HTMLDirectoryElement extends _HTMLElement {
   _HTMLDirectoryElement.internal() : super.internal();
 
 }
@@ -26979,10 +26850,163 @@
 
 
 @DocsEditable
+@DomName('HTMLElement')
+class _HTMLElement extends Element {
+  _HTMLElement.internal() : super.internal();
+
+  @DomName('HTMLElement.contentEditable')
+  @DocsEditable
+  String get contentEditable native "HTMLElement_contentEditable_Getter";
+
+  @DomName('HTMLElement.contentEditable')
+  @DocsEditable
+  void set contentEditable(String value) native "HTMLElement_contentEditable_Setter";
+
+  @DomName('HTMLElement.dir')
+  @DocsEditable
+  String get dir native "HTMLElement_dir_Getter";
+
+  @DomName('HTMLElement.dir')
+  @DocsEditable
+  void set dir(String value) native "HTMLElement_dir_Setter";
+
+  @DomName('HTMLElement.draggable')
+  @DocsEditable
+  bool get draggable native "HTMLElement_draggable_Getter";
+
+  @DomName('HTMLElement.draggable')
+  @DocsEditable
+  void set draggable(bool value) native "HTMLElement_draggable_Setter";
+
+  @DomName('HTMLElement.hidden')
+  @DocsEditable
+  bool get hidden native "HTMLElement_hidden_Getter";
+
+  @DomName('HTMLElement.hidden')
+  @DocsEditable
+  void set hidden(bool value) native "HTMLElement_hidden_Setter";
+
+  @DomName('HTMLElement.id')
+  @DocsEditable
+  String get id native "HTMLElement_id_Getter";
+
+  @DomName('HTMLElement.id')
+  @DocsEditable
+  void set id(String value) native "HTMLElement_id_Setter";
+
+  @DomName('HTMLElement.innerHTML')
+  @DocsEditable
+  String get innerHtml native "HTMLElement_innerHTML_Getter";
+
+  @DomName('HTMLElement.innerHTML')
+  @DocsEditable
+  void set innerHtml(String value) native "HTMLElement_innerHTML_Setter";
+
+  @DomName('HTMLElement.isContentEditable')
+  @DocsEditable
+  bool get isContentEditable native "HTMLElement_isContentEditable_Getter";
+
+  @DomName('HTMLElement.lang')
+  @DocsEditable
+  String get lang native "HTMLElement_lang_Getter";
+
+  @DomName('HTMLElement.lang')
+  @DocsEditable
+  void set lang(String value) native "HTMLElement_lang_Setter";
+
+  @DomName('HTMLElement.outerHTML')
+  @DocsEditable
+  String get outerHtml native "HTMLElement_outerHTML_Getter";
+
+  @DomName('HTMLElement.spellcheck')
+  @DocsEditable
+  // http://blog.whatwg.org/the-road-to-html-5-spellchecking
+  @Experimental // nonstandard
+  bool get spellcheck native "HTMLElement_spellcheck_Getter";
+
+  @DomName('HTMLElement.spellcheck')
+  @DocsEditable
+  // http://blog.whatwg.org/the-road-to-html-5-spellchecking
+  @Experimental // nonstandard
+  void set spellcheck(bool value) native "HTMLElement_spellcheck_Setter";
+
+  @DomName('HTMLElement.tabIndex')
+  @DocsEditable
+  int get tabIndex native "HTMLElement_tabIndex_Getter";
+
+  @DomName('HTMLElement.tabIndex')
+  @DocsEditable
+  void set tabIndex(int value) native "HTMLElement_tabIndex_Setter";
+
+  @DomName('HTMLElement.title')
+  @DocsEditable
+  String get title native "HTMLElement_title_Getter";
+
+  @DomName('HTMLElement.title')
+  @DocsEditable
+  void set title(String value) native "HTMLElement_title_Setter";
+
+  @DomName('HTMLElement.translate')
+  @DocsEditable
+  bool get translate native "HTMLElement_translate_Getter";
+
+  @DomName('HTMLElement.translate')
+  @DocsEditable
+  void set translate(bool value) native "HTMLElement_translate_Setter";
+
+  @DomName('HTMLElement.webkitdropzone')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-dropzone-attribute
+  String get dropzone native "HTMLElement_webkitdropzone_Getter";
+
+  @DomName('HTMLElement.webkitdropzone')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#the-dropzone-attribute
+  void set dropzone(String value) native "HTMLElement_webkitdropzone_Setter";
+
+  @DomName('HTMLElement.click')
+  @DocsEditable
+  void click() native "HTMLElement_click_Callback";
+
+  @DomName('HTMLElement.getInputContext')
+  @DocsEditable
+  // http://www.w3.org/TR/ime-api/#the-getinputcontext-method
+  @Experimental
+  InputMethodContext getInputContext() native "HTMLElement_getInputContext_Callback";
+
+  @DomName('HTMLElement.insertAdjacentElement')
+  @DocsEditable
+  @Experimental // non-standard
+  Element insertAdjacentElement(String where, Element element) native "HTMLElement_insertAdjacentElement_Callback";
+
+  @DomName('HTMLElement.insertAdjacentHTML')
+  @DocsEditable
+  void insertAdjacentHtml(String where, String html) native "HTMLElement_insertAdjacentHTML_Callback";
+
+  @DomName('HTMLElement.insertAdjacentText')
+  @DocsEditable
+  @Experimental // non-standard
+  void insertAdjacentText(String where, String text) native "HTMLElement_insertAdjacentText_Callback";
+
+}
+// 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
 @DomName('HTMLFontElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#htmlfontelement
 @deprecated // deprecated
-abstract class _HTMLFontElement extends _Element_Merged {
+abstract class _HTMLFontElement extends _HTMLElement {
   _HTMLFontElement.internal() : super.internal();
 
 }
@@ -26997,7 +27021,7 @@
 @DomName('HTMLFrameElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#htmlframeelement
 @deprecated // deprecated
-abstract class _HTMLFrameElement extends _Element_Merged {
+abstract class _HTMLFrameElement extends _HTMLElement {
   _HTMLFrameElement.internal() : super.internal();
 
 }
@@ -27012,7 +27036,7 @@
 @DomName('HTMLFrameSetElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#frameset
 @deprecated // deprecated
-abstract class _HTMLFrameSetElement extends _Element_Merged {
+abstract class _HTMLFrameSetElement extends _HTMLElement {
   _HTMLFrameSetElement.internal() : super.internal();
 
 }
@@ -27027,7 +27051,7 @@
 @DomName('HTMLMarqueeElement')
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#the-marquee-element
 @deprecated // deprecated
-abstract class _HTMLMarqueeElement extends _Element_Merged {
+abstract class _HTMLMarqueeElement extends _HTMLElement {
   _HTMLMarqueeElement.internal() : super.internal();
 
 }
diff --git a/sdk/lib/html/html_common/conversions.dart b/sdk/lib/html/html_common/conversions.dart
index 063c7e9..12591d5 100644
--- a/sdk/lib/html/html_common/conversions.dart
+++ b/sdk/lib/html/html_common/conversions.dart
@@ -173,38 +173,10 @@
 
       int i = 0;
 
-      if (isJavaScriptArray(e) &&
-          // We have to copy immutable lists, otherwise the structured clone
-          // algorithm will copy the .immutable$list marker property, making the
-          // list immutable when received!
-          !isImmutableJavaScriptArray(e)) {
-        writeSlot(slot, true);  // Deferred copy.
-        for ( ; i < length; i++) {
-          var element = e[i];
-          var elementCopy = walk(element);
-          if (!identical(elementCopy, element)) {
-            copy = readSlot(slot);   // Cyclic reference may have created it.
-            if (true == copy) {
-              copy = JS('=List', 'new Array(#)', length);
-              writeSlot(slot, copy);
-            }
-            for (int j = 0; j < i; j++) {
-              copy[j] = e[j];
-            }
-            copy[i] = elementCopy;
-            i++;
-            break;
-          }
-        }
-        if (copy == null) {
-          copy = e;
-          writeSlot(slot, copy);
-        }
-      } else {
-        // Not a JavaScript Array.  We are forced to make a copy.
-        copy = JS('=List', 'new Array(#)', length);
-        writeSlot(slot, copy);
-      }
+      // Always clone the list, as it may have non-native properties or methods
+      // from interceptors and such.
+      copy = JS('=List', 'new Array(#)', length);
+      writeSlot(slot, copy);
 
       for ( ; i < length; i++) {
         copy[i] = walk(e[i]);
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index 31ce72b..ba5f07d 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -100,7 +100,7 @@
 // Only builtin Lists can be serialized through. If user-defined Lists
 // get here, the contents is copied to a Uint8List. This has the added
 // benefit that it is faster to access from the C code as well.
-_BufferAndStart _ensureFastAndSerializableBuffer(
+_BufferAndStart _ensureFastAndSerializableData(
     List buffer, int start, int end) {
   if (buffer is Uint8List ||
       buffer is Int8List ||
@@ -131,6 +131,28 @@
 }
 
 
+_BufferAndStart _ensureFastAndSerializableByteData(
+    List buffer, int start, int end) {
+  if (buffer is Uint8List) {
+    return new _BufferAndStart(buffer, start);
+  }
+  int length = end - start;
+  var newBuffer = new Uint8List(length);
+  int j = start;
+  for (int i = 0; i < length; i++) {
+    int value = buffer[j];
+    if (value is! int ||
+        value < 0 || 255 < value) {
+      throw new ArgumentError(
+          "List element is not a byte value (value $value at index $j)");
+    }
+    newBuffer[i] = value;
+    j++;
+  }
+  return new _BufferAndStart(newBuffer, 0);
+}
+
+
 // TODO(ager): The only reason for the class here is that
 // we cannot patch a top-level function.
 class _BufferUtils {
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 34808d8..59695a2 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -770,7 +770,7 @@
 
     _BufferAndStart result;
     try {
-      result = _ensureFastAndSerializableBuffer(buffer, start, end);
+      result = _ensureFastAndSerializableData(buffer, start, end);
     } catch (e) {
       return new Future.error(e);
     }
@@ -805,7 +805,7 @@
     if (end == start) return;
     _checkReadWriteListArguments(buffer.length, start, end);
     _BufferAndStart bufferAndStart =
-        _ensureFastAndSerializableBuffer(buffer, start, end);
+        _ensureFastAndSerializableData(buffer, start, end);
     var result = _writeFrom(_id,
                             bufferAndStart.buffer,
                             bufferAndStart.start,
diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
index 223b246..41ab104 100644
--- a/sdk/lib/io/http_headers.dart
+++ b/sdk/lib/io/http_headers.dart
@@ -140,7 +140,7 @@
     List<String> values = _headers[HttpHeaders.IF_MODIFIED_SINCE];
     if (values != null) {
       try {
-        return _HttpUtils.parseDate(values[0]);
+        return HttpDate.parse(values[0]);
       } on Exception catch (e) {
         return null;
       }
@@ -151,7 +151,7 @@
   void set ifModifiedSince(DateTime ifModifiedSince) {
     _checkMutable();
     // Format "ifModifiedSince" header with date in Greenwich Mean Time (GMT).
-    String formatted = _HttpUtils.formatDate(ifModifiedSince.toUtc());
+    String formatted = HttpDate.format(ifModifiedSince.toUtc());
     _set(HttpHeaders.IF_MODIFIED_SINCE, formatted);
   }
 
@@ -159,7 +159,7 @@
     List<String> values = _headers[HttpHeaders.DATE];
     if (values != null) {
       try {
-        return _HttpUtils.parseDate(values[0]);
+        return HttpDate.parse(values[0]);
       } on Exception catch (e) {
         return null;
       }
@@ -170,7 +170,7 @@
   void set date(DateTime date) {
     _checkMutable();
     // Format "DateTime" header with date in Greenwich Mean Time (GMT).
-    String formatted = _HttpUtils.formatDate(date.toUtc());
+    String formatted = HttpDate.format(date.toUtc());
     _set("date", formatted);
   }
 
@@ -178,7 +178,7 @@
     List<String> values = _headers[HttpHeaders.EXPIRES];
     if (values != null) {
       try {
-        return _HttpUtils.parseDate(values[0]);
+        return HttpDate.parse(values[0]);
       } on Exception catch (e) {
         return null;
       }
@@ -189,7 +189,7 @@
   void set expires(DateTime expires) {
     _checkMutable();
     // Format "Expires" header with date in Greenwich Mean Time (GMT).
-    String formatted = _HttpUtils.formatDate(expires.toUtc());
+    String formatted = HttpDate.format(expires.toUtc());
     _set(HttpHeaders.EXPIRES, formatted);
   }
 
@@ -288,7 +288,7 @@
       _headers[name] = values;
     }
     if (value is DateTime) {
-      values.add(_HttpUtils.formatDate(value));
+      values.add(HttpDate.format(value));
     } else {
       values.add(value.toString());
     }
@@ -750,7 +750,7 @@
     sb.write(value);
     if (expires != null) {
       sb.write("; Expires=");
-      sb.write(_HttpUtils.formatDate(expires));
+      sb.write(HttpDate.format(expires));
     }
     if (maxAge != null) {
       sb.write("; Max-Age=");
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index b272976..e82d329 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -1705,7 +1705,7 @@
     }
 
     // Default to using the process current environment.
-    if (environment == null) environment = Platform.environment;
+    if (environment == null) environment = _platformEnvironmentCache;
 
     String proxyCfg;
 
@@ -1730,10 +1730,12 @@
     }
     return "DIRECT";
   }
+
+  static Map<String, String> _platformEnvironmentCache = Platform.environment;
 }
 
 
-class _HttpConnection {
+class _HttpConnection extends LinkedListEntry<_HttpConnection> {
   static const _ACTIVE = 0;
   static const _IDLE = 1;
   static const _CLOSING = 2;
@@ -1952,9 +1954,9 @@
   final bool _closeServer;
 
   // Set of currently connected clients.
-  final Set<_HttpConnection> _connections = new Set<_HttpConnection>();
+  final LinkedList<_HttpConnection> _connections
+      = new LinkedList<_HttpConnection>();
   StreamController<HttpRequest> _controller;
-
   // TODO(ajohnsen): Use close queue?
 }
 
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index bcd27e0..f863e4fc 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -99,13 +99,13 @@
   StreamController<List<int>> controller;
   final StreamSubscription subscription;
 
-  List<int> carryOverData;
+  List<int> bufferedData;
   bool paused;
 
   Completer resumeCompleter;
 
   _HttpDetachedIncoming(StreamSubscription this.subscription,
-                        List<int> this.carryOverData) {
+                        List<int> this.bufferedData) {
     controller = new StreamController<List<int>>(
         sync: true,
         onListen: resume,
@@ -114,7 +114,7 @@
         onCancel: () => subscription.cancel());
     if (subscription == null) {
       // Socket was already closed.
-      if (carryOverData != null) controller.add(carryOverData);
+      if (bufferedData != null) controller.add(bufferedData);
       controller.close();
     } else {
       pause();
@@ -138,9 +138,9 @@
 
   void resume() {
     paused = false;
-    if (carryOverData != null) {
-      var data = carryOverData;
-      carryOverData = null;
+    if (bufferedData != null) {
+      var data = bufferedData;
+      bufferedData = null;
       controller.add(data);
       // If the consumer pauses again after the carry-over data, we'll not
       // continue our subscriber until the next resume.
diff --git a/sdk/lib/io/http_session.dart b/sdk/lib/io/http_session.dart
index deeebd0..85c9b3c 100644
--- a/sdk/lib/io/http_session.dart
+++ b/sdk/lib/io/http_session.dart
@@ -53,6 +53,7 @@
   operator [](key) => _data[key];
   void operator []=(key, value) { _data[key] = value; }
   putIfAbsent(key, ifAbsent) => _data.putIfAbsent(key, ifAbsent);
+  addAll(Map other) => _data.addAll(other);
   remove(key) => _data.remove(key);
   void clear() => _data.clear();
   void forEach(void f(key, value)) => _data.forEach(f);
diff --git a/sdk/lib/io/http_utils.dart b/sdk/lib/io/http_utils.dart
index 82db7de..487096c 100644
--- a/sdk/lib/io/http_utils.dart
+++ b/sdk/lib/io/http_utils.dart
@@ -4,112 +4,14 @@
 
 part of dart.io;
 
-class _HttpUtils {
-  static String decodeUrlEncodedString(
-      String urlEncoded,
-      {Encoding encoding: Encoding.UTF_8}) {
-    // First check the string for any encoding.
-    int index = 0;
-    bool encoded = false;
-    while (!encoded && index < urlEncoded.length) {
-      encoded = urlEncoded[index] == "+" || urlEncoded[index] == "%";
-      index++;
-    }
-    if (!encoded) return urlEncoded;
-    index--;
-
-    // Start decoding from the first encoded character.
-    List<int> bytes = new List<int>();
-    for (int i = 0; i < index; i++) bytes.add(urlEncoded.codeUnitAt(i));
-    for (int i = index; i < urlEncoded.length; i++) {
-      if (urlEncoded[i] == "+") {
-        bytes.add(32);
-      } else if (urlEncoded[i] == "%") {
-        if (urlEncoded.length - i < 2) {
-          throw new HttpException("Invalid URL encoding");
-        }
-        int byte = 0;
-        for (int j = 0; j < 2; j++) {
-          var charCode = urlEncoded.codeUnitAt(i + j + 1);
-          if (0x30 <= charCode && charCode <= 0x39) {
-            byte = byte * 16 + charCode - 0x30;
-          } else {
-            // Check ranges A-F (0x41-0x46) and a-f (0x61-0x66).
-            charCode |= 0x20;
-            if (0x61 <= charCode && charCode <= 0x66) {
-              byte = byte * 16 + charCode - 0x57;
-            } else {
-              throw new ArgumentError("Invalid URL encoding");
-            }
-          }
-        }
-        bytes.add(byte);
-        i += 2;
-      } else {
-        bytes.add(urlEncoded.codeUnitAt(i));
-      }
-    }
-    return _decodeString(bytes, encoding);
-  }
-
-  static Map<String, String> splitQueryString(
-      String queryString,
-      {Encoding encoding: Encoding.UTF_8}) {
-    Map<String, String> result = new Map<String, String>();
-    int currentPosition = 0;
-    int length = queryString.length;
-
-    while (currentPosition < length) {
-
-      // Find the first equals character between current position and
-      // the provided end.
-      int indexOfEquals(int end) {
-        int index = currentPosition;
-        while (index < end) {
-          if (queryString.codeUnitAt(index) == _CharCode.EQUAL) return index;
-          index++;
-        }
-        return -1;
-      }
-
-      // Find the next separator (either & or ;), see
-      // http://www.w3.org/TR/REC-html40/appendix/notes.html#ampersands-in-uris
-      // relating the ; separator. If no separator is found returns
-      // the length of the query string.
-      int indexOfSeparator() {
-        int end = length;
-        int index = currentPosition;
-        while (index < end) {
-          int codeUnit = queryString.codeUnitAt(index);
-          if (codeUnit == _CharCode.AMPERSAND ||
-              codeUnit == _CharCode.SEMI_COLON) {
-            return index;
-          }
-          index++;
-        }
-        return end;
-      }
-
-      int seppos = indexOfSeparator();
-      int equalspos = indexOfEquals(seppos);
-      String name;
-      String value;
-      if (equalspos == -1) {
-        name = queryString.substring(currentPosition, seppos);
-        value = '';
-      } else {
-        name = queryString.substring(currentPosition, equalspos);
-        value = queryString.substring(equalspos + 1, seppos);
-      }
-      currentPosition = seppos + 1;  // This also works when seppos == length.
-      if (name == '') continue;
-      result[_HttpUtils.decodeUrlEncodedString(name, encoding: encoding)] =
-        _HttpUtils.decodeUrlEncodedString(value, encoding: encoding);
-    }
-    return result;
-  }
-
-  // From RFC 2616 section "3.3.1 Full Date"
+/**
+ * Utility functions for working with dates with HTTP specific date
+ * formats.
+ */
+class HttpDate {
+  // From RFC-2616 section "3.3.1 Full Date",
+  // http://tools.ietf.org/html/rfc2616#section-3.3.1
+  //
   // HTTP-date    = rfc1123-date | rfc850-date | asctime-date
   // rfc1123-date = wkday "," SP date1 SP time SP "GMT"
   // rfc850-date  = weekday "," SP date2 SP time SP "GMT"
@@ -130,8 +32,12 @@
   //              | "May" | "Jun" | "Jul" | "Aug"
   //              | "Sep" | "Oct" | "Nov" | "Dec"
 
-  // Format as RFC 1123 date.
-  static String formatDate(DateTime date) {
+  /**
+   * Format a date according to
+   * [RFC-1123](http://tools.ietf.org/html/rfc1123 "RFC-1123"),
+   * e.g. `Thu, 1 Jan 1970 00:00:00 GMT`.
+   */
+  static String format(DateTime date) {
     const List wkday = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
     const List month = const ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
@@ -155,7 +61,21 @@
     return sb.toString();
   }
 
-  static DateTime parseDate(String date) {
+  /**
+   * Parse a date string in either of the formats
+   * [RFC-1123](http://tools.ietf.org/html/rfc1123 "RFC-1123"),
+   * [RFC-850](http://tools.ietf.org/html/rfc850 "RFC-850") or
+   * ANSI C's asctime() format. These formats are listed here.
+   *
+   *     Thu, 1 Jan 1970 00:00:00 GMT
+   *     Thursday, 1-Jan-1970 00:00:00 GMT
+   *     Thu Jan  1 00:00:00 1970
+   *
+   * For more information see [RFC-2616 section 3.1.1]
+   * (http://tools.ietf.org/html/rfc2616#section-3.3.1
+   * "RFC-2616 section 3.1.1").
+   */
+  static DateTime parse(String date) {
     final int SP = 32;
     const List wkdays = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
     const List weekdays = const ["Monday", "Tuesday", "Wednesday", "Thursday",
@@ -282,6 +202,112 @@
     expectEnd();
     return new DateTime.utc(year, month + 1, day, hours, minutes, seconds, 0);
   }
+}
+
+class _HttpUtils {
+  static String decodeUrlEncodedString(
+      String urlEncoded,
+      {Encoding encoding: Encoding.UTF_8}) {
+    // First check the string for any encoding.
+    int index = 0;
+    bool encoded = false;
+    while (!encoded && index < urlEncoded.length) {
+      encoded = urlEncoded[index] == "+" || urlEncoded[index] == "%";
+      index++;
+    }
+    if (!encoded) return urlEncoded;
+    index--;
+
+    // Start decoding from the first encoded character.
+    List<int> bytes = new List<int>();
+    for (int i = 0; i < index; i++) bytes.add(urlEncoded.codeUnitAt(i));
+    for (int i = index; i < urlEncoded.length; i++) {
+      if (urlEncoded[i] == "+") {
+        bytes.add(32);
+      } else if (urlEncoded[i] == "%") {
+        if (urlEncoded.length - i < 2) {
+          throw new HttpException("Invalid URL encoding");
+        }
+        int byte = 0;
+        for (int j = 0; j < 2; j++) {
+          var charCode = urlEncoded.codeUnitAt(i + j + 1);
+          if (0x30 <= charCode && charCode <= 0x39) {
+            byte = byte * 16 + charCode - 0x30;
+          } else {
+            // Check ranges A-F (0x41-0x46) and a-f (0x61-0x66).
+            charCode |= 0x20;
+            if (0x61 <= charCode && charCode <= 0x66) {
+              byte = byte * 16 + charCode - 0x57;
+            } else {
+              throw new ArgumentError("Invalid URL encoding");
+            }
+          }
+        }
+        bytes.add(byte);
+        i += 2;
+      } else {
+        bytes.add(urlEncoded.codeUnitAt(i));
+      }
+    }
+    return _decodeString(bytes, encoding);
+  }
+
+  static Map<String, String> splitQueryString(
+      String queryString,
+      {Encoding encoding: Encoding.UTF_8}) {
+    Map<String, String> result = new Map<String, String>();
+    int currentPosition = 0;
+    int length = queryString.length;
+
+    while (currentPosition < length) {
+
+      // Find the first equals character between current position and
+      // the provided end.
+      int indexOfEquals(int end) {
+        int index = currentPosition;
+        while (index < end) {
+          if (queryString.codeUnitAt(index) == _CharCode.EQUAL) return index;
+          index++;
+        }
+        return -1;
+      }
+
+      // Find the next separator (either & or ;), see
+      // http://www.w3.org/TR/REC-html40/appendix/notes.html#ampersands-in-uris
+      // relating the ; separator. If no separator is found returns
+      // the length of the query string.
+      int indexOfSeparator() {
+        int end = length;
+        int index = currentPosition;
+        while (index < end) {
+          int codeUnit = queryString.codeUnitAt(index);
+          if (codeUnit == _CharCode.AMPERSAND ||
+              codeUnit == _CharCode.SEMI_COLON) {
+            return index;
+          }
+          index++;
+        }
+        return end;
+      }
+
+      int seppos = indexOfSeparator();
+      int equalspos = indexOfEquals(seppos);
+      String name;
+      String value;
+      if (equalspos == -1) {
+        name = queryString.substring(currentPosition, seppos);
+        value = '';
+      } else {
+        name = queryString.substring(currentPosition, equalspos);
+        value = queryString.substring(equalspos + 1, seppos);
+      }
+      currentPosition = seppos + 1;  // This also works when seppos == length.
+      if (name == '') continue;
+      result[_HttpUtils.decodeUrlEncodedString(name, encoding: encoding)] =
+        _HttpUtils.decodeUrlEncodedString(value, encoding: encoding);
+    }
+    return result;
+  }
 
   static DateTime parseCookieDate(String date) {
     const List monthsLowerCase = const ["jan", "feb", "mar", "apr", "may",
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index 6c1d699..3e69849 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -13,10 +13,9 @@
 library dart.io;
 
 import 'dart:async';
-import 'dart:collection' show Queue,
-                              LinkedHashSet,
-                              DoubleLinkedQueue,
-                              DoubleLinkedQueueEntry;
+import 'dart:collection' show LinkedHashSet,
+                              LinkedList,
+                              LinkedListEntry;
 import 'dart:isolate';
 import 'dart:json' as JSON;
 import 'dart:math';
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index cee4e38..89fc2a0 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.dart
@@ -80,6 +80,9 @@
   V putIfAbsent(String key, V ifAbsent()) {
     _map.putIfAbsent(key.toUpperCase(), ifAbsent);
   }
+  addAll(Map other) {
+    other.forEach((key, value) => this[key.toUpperCase()] = value);
+  }
   V remove(String key) => _map.remove(key.toUpperCase());
   void clear() => _map.clear();
   void forEach(void f(String key, V value)) => _map.forEach(f);
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 808bce5..6c79c12 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -115,13 +115,16 @@
    * passed in.
    *
    * If [runInShell] is true, the process will be spawned through a system
-   * shell. On Linux and Mac OS, [:/bin/sh:] is used, while
-   * [:%WINDIR%\system32\cmd.exe:] is used on Windows.
+   * shell. On Linux and Mac OS, `/bin/sh` is used, while
+   * `%WINDIR%\system32\cmd.exe` is used on Windows.
    *
-   * The encoding used for text on stdout and stderr can be set by changing
-   * [stdoutEncoding] and [stderrEncoding]. The default encoding is SYSTEM.
+   * The encoding used for decoding `stdout` and `stderr` into text is
+   * controlled through [stdoutEncoding] and [stderrEncoding]. The
+   * default encoding is `Encoding.SYSTEM`. If `null` is used no
+   * decoding will happen and the [ProcessResult] will hold binary
+   * data.
    *
-   * Returns a [:Future<ProcessResult>:] that completes with the
+   * Returns a `Future<ProcessResult>` that completes with the
    * result of running the process, i.e., exit code, standard out and
    * standard in.
    */
@@ -200,14 +203,20 @@
   int get exitCode;
 
   /**
-   * Standard output from the process as a string.
+   * Standard output from the process. The value used for the
+   * `stdoutEncoding` argument to `Process.run` determins the type. If
+   * `null` was used this value is of type `List<int> otherwise it is
+   * of type `String`.
    */
-  String get stdout;
+  get stdout;
 
   /**
-   * Standard error from the process as a string.
+   * Standard error from the process. The value used for the
+   * `stderrEncoding` argument to `Process.run` determins the type. If
+   * `null` was used this value is of type `List<int>
+   * otherwise it is of type `String`.
    */
-  String get stderr;
+  get stderr;
 
   /**
    * Process id from the process.
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 05ec18c..d6f5734 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -103,7 +103,7 @@
    * the right thing to do.
    *
    * If some of the data of the TLS handshake has already been read
-   * from the socket this data can be passed in the [carryOverData]
+   * from the socket this data can be passed in the [bufferedData]
    * parameter. This data will be processed before any other data
    * available on the socket.
    *
@@ -114,7 +114,7 @@
   static Future<SecureSocket> secureServer(
       Socket socket,
       String certificateName,
-      {List<int> carryOverData,
+      {List<int> bufferedData,
        bool requestClientCertificate: false,
        bool requireClientCertificate: false}) {
     var completer = new Completer();
@@ -124,7 +124,7 @@
             detachedRaw[0],
             certificateName,
             subscription: detachedRaw[1],
-            carryOverData: carryOverData,
+            bufferedData: bufferedData,
             requestClientCertificate: requestClientCertificate,
             requireClientCertificate: requireClientCertificate);
           })
@@ -284,7 +284,7 @@
    * events.
    *
    * If some of the data of the TLS handshake has already been read
-   * from the socket this data can be passed in the [carryOverData]
+   * from the socket this data can be passed in the [bufferedData]
    * parameter. This data will be processed before any other data
    * available on the socket.
    *
@@ -296,7 +296,7 @@
       RawSocket socket,
       String certificateName,
       {StreamSubscription subscription,
-       List<int> carryOverData,
+       List<int> bufferedData,
        bool requestClientCertificate: false,
        bool requireClientCertificate: false}) {
     socket.readEventsEnabled = false;
@@ -308,7 +308,7 @@
         is_server: true,
         socket: socket,
         subscription: subscription,
-        carryOverData: carryOverData,
+        bufferedData: bufferedData,
         requestClientCertificate: requestClientCertificate,
         requireClientCertificate: requireClientCertificate);
   }
@@ -362,8 +362,8 @@
   StreamController<RawSocketEvent> _controller;
   Stream<RawSocketEvent> _stream;
   StreamSubscription<RawSocketEvent> _socketSubscription;
-  List<int> _carryOverData;
-  int _carryOverDataIndex = 0;
+  List<int> _bufferedData;
+  int _bufferedDataIndex = 0;
   final InternetAddress address;
   final bool is_server;
   final String certificateName;
@@ -391,7 +391,7 @@
       {bool is_server,
        RawSocket socket,
        StreamSubscription subscription,
-       List<int> carryOverData,
+       List<int> bufferedData,
        bool requestClientCertificate: false,
        bool requireClientCertificate: false,
        bool sendClientCertificate: false,
@@ -409,7 +409,7 @@
                                  is_server,
                                  socket,
                                  subscription,
-                                 carryOverData,
+                                 bufferedData,
                                  requestClientCertificate,
                                  requireClientCertificate,
                                  sendClientCertificate,
@@ -425,7 +425,7 @@
       bool this.is_server,
       RawSocket socket,
       StreamSubscription this._socketSubscription,
-      List<int> this._carryOverData,
+      List<int> this._bufferedData,
       bool this.requestClientCertificate,
       bool this.requireClientCertificate,
       bool this.sendClientCertificate,
@@ -441,7 +441,7 @@
     // errors will be reported through the future or the stream.
     _verifyFields();
     _secureFilter.init();
-    if (_carryOverData != null) _readFromCarryOver();
+    if (_bufferedData != null) _readFromBuffered();
     _secureFilter.registerHandshakeCompleteCallback(
         _secureHandshakeCompleteHandler);
     if (onBadCertificate != null) {
@@ -723,19 +723,19 @@
     }
   }
 
-  void _readFromCarryOver() {
-    assert(_carryOverData != null);
+  void _readFromBuffered() {
+    assert(_bufferedData != null);
     var encrypted = _secureFilter.buffers[READ_ENCRYPTED];
-    var bytes = _carryOverData.length - _carryOverDataIndex;
+    var bytes = _bufferedData.length - _bufferedDataIndex;
     int startIndex = encrypted.start + encrypted.length;
     encrypted.data.setRange(startIndex,
                             startIndex + bytes,
-                            _carryOverData,
-                            _carryOverDataIndex);
+                            _bufferedData,
+                            _bufferedDataIndex);
     encrypted.length += bytes;
-    _carryOverDataIndex += bytes;
-    if (_carryOverData.length == _carryOverDataIndex) {
-      _carryOverData = null;
+    _bufferedDataIndex += bytes;
+    if (_bufferedData.length == _bufferedDataIndex) {
+      _bufferedData = null;
     }
   }
 
@@ -873,8 +873,8 @@
         }
       }
       if (!_socketClosedRead && encrypted.free > 0) {
-        if (_carryOverData != null) {
-          _readFromCarryOver();
+        if (_bufferedData != null) {
+          _readFromBuffered();
           progress = true;
         } else {
           List<int> data = _socket.read(encrypted.free);
diff --git a/sdk/lib/io/timer_impl.dart b/sdk/lib/io/timer_impl.dart
index 3072f5c..5a7981e 100644
--- a/sdk/lib/io/timer_impl.dart
+++ b/sdk/lib/io/timer_impl.dart
@@ -4,25 +4,29 @@
 
 part of dart.io;
 
-class _Timer implements Timer {
-  // Set jitter to wake up timer events that would happen in _TIMER_JITTER ms.
-  static const int _TIMER_JITTER = 0;
-
+class _Timer extends LinkedListEntry<_Timer> implements Timer {
   // Disables the timer.
   static const int _NO_TIMER = -1;
 
+  // Timers are ordered by wakeup time.
+  static LinkedList<_Timer> _timers = new LinkedList<_Timer>();
+
+  static ReceivePort _receivePort;
+  static bool _handling_callbacks = false;
+
+  Function _callback;
+  int _milliSeconds;
+  int _wakeupTime;
+
   static Timer _createTimer(void callback(Timer timer),
-                           int milliSeconds,
-                           bool repeating) {
+                            int milliSeconds,
+                            bool repeating) {
     _EventHandler._start();
-    if (_timers == null) {
-      _timers = new DoubleLinkedQueue<_Timer>();
-    }
     _Timer timer = new _Timer._internal();
     timer._callback = callback;
-    timer._milliSeconds = milliSeconds;
-    timer._wakeupTime = (new DateTime.now()).millisecondsSinceEpoch + milliSeconds;
-    timer._repeating = repeating;
+    timer._wakeupTime =
+        new DateTime.now().millisecondsSinceEpoch + milliSeconds;
+    timer._milliSeconds = repeating ? milliSeconds : -1;
     timer._addTimerToList();
     timer._notifyEventHandler();
     return timer;
@@ -42,50 +46,43 @@
     _callback = null;
     _milliSeconds = 0;
     _wakeupTime = 0;
-    _repeating = false;
   }
 
+  bool get _repeating => _milliSeconds >= 0;
+
 
   // Cancels a set timer. The timer is removed from the timer list and if
   // the given timer is the earliest timer the native timer is reset.
   void cancel() {
     _clear();
-    DoubleLinkedQueueEntry<_Timer> entry = _timers.firstEntry();
-    DoubleLinkedQueueEntry<_Timer> first = _timers.firstEntry();
-
-     while (entry != null) {
-      if (identical(entry.element, this)) {
-        entry.remove();
-        if (first.element == this) {
-          entry = _timers.firstEntry();
-          _notifyEventHandler();
-        }
-        return;
-      }
-      entry = entry.nextEntry();
+    // Return if already canceled.
+    if (list == null) return;
+    assert(!_timers.isEmpty);
+    _Timer first = _timers.first;
+    unlink();
+    if (identical(first, this)) {
+      _notifyEventHandler();
     }
   }
 
   void _advanceWakeupTime() {
+    assert(_milliSeconds >= 0);
     _wakeupTime += _milliSeconds;
   }
 
   // Adds a timer to the timer list and resets the native timer if it is the
-  // earliest timer in the list.  Timers with the same wakeup time are enqueued
+  // earliest timer in the list. Timers with the same wakeup time are enqueued
   // in order and notified in FIFO order.
   void _addTimerToList() {
-    if (_callback != null) {
-
-      DoubleLinkedQueueEntry<_Timer> entry = _timers.firstEntry();
-      while (entry != null) {
-        if (_wakeupTime < entry.element._wakeupTime) {
-          entry.prepend(this);
-          return;
-        }
-        entry = entry.nextEntry();
+    _Timer entry = _timers.isEmpty ? null : _timers.first;
+    while (entry != null) {
+      if (_wakeupTime < entry._wakeupTime) {
+        entry.insertBefore(this);
+        return;
       }
-      _timers.add(this);
+      entry = entry.next;
     }
+    _timers.add(this);
   }
 
 
@@ -97,7 +94,7 @@
       return;
     }
 
-    if (_timers.firstEntry() == null) {
+    if (_timers.isEmpty) {
       // No pending timers: Close the receive port and let the event handler
       // know.
       if (_receivePort != null) {
@@ -112,7 +109,7 @@
       }
       _EventHandler._sendData(null,
                               _receivePort,
-                              _timers.firstEntry().element._wakeupTime);
+                              _timers.first._wakeupTime);
     }
   }
 
@@ -122,18 +119,15 @@
   void _createTimerHandler() {
 
     void _handleTimeout() {
-      int currentTime =
-          (new DateTime.now()).millisecondsSinceEpoch + _TIMER_JITTER;
+      int currentTime = new DateTime.now().millisecondsSinceEpoch;
 
       // Collect all pending timers.
-      DoubleLinkedQueueEntry<_Timer> entry = _timers.firstEntry();
       var pending_timers = new List();
-      while (entry != null) {
-        _Timer timer = entry.element;
-        if (timer._wakeupTime <= currentTime) {
-          entry.remove();
-          pending_timers.add(timer);
-          entry = _timers.firstEntry();
+      while (!_timers.isEmpty) {
+        _Timer entry = _timers.first;
+        if (entry._wakeupTime <= currentTime) {
+          entry.unlink();
+          pending_timers.add(entry);
         } else {
           break;
         }
@@ -174,18 +168,6 @@
     _receivePort.close();
     _receivePort = null;
   }
-
-
-  // Timers are ordered by wakeup time.
-  static DoubleLinkedQueue<_Timer> _timers;
-
-  static ReceivePort _receivePort;
-  static bool _handling_callbacks = false;
-
-  var _callback;
-  int _milliSeconds;
-  int _wakeupTime;
-  bool _repeating;
 }
 
 // Provide a closure which will allocate a Timer object to be able to hook
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 8108084..d903061 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -531,9 +531,27 @@
       header.setRange(index, index + 4, maskBytes);
       index += 4;
       if (data != null) {
-        var list = new Uint8List(data.length);
-        for (int i = 0; i < data.length; i++) {
-          list[i] = data[i] ^ maskBytes[i % 4];
+        var list;
+        // If this is a text message just do the masking inside the
+        // encoded data.
+        if (opcode == _WebSocketOpcode.TEXT) {
+          list = data;
+        } else {
+          list = new Uint8List(data.length);
+        }
+        if (data is Uint8List) {
+          for (int i = 0; i < data.length; i++) {
+            list[i] = data[i] ^ maskBytes[i % 4];
+          }
+        } else {
+          for (int i = 0; i < data.length; i++) {
+            if (data[i] < 0 || 255 < data[i]) {
+              throw new ArgumentError(
+                  "List element is not a byte value "
+                  "(value ${data[i]} at index $i)");
+            }
+            list[i] = data[i] ^ maskBytes[i % 4];
+          }
         }
         data = list;
       }
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 7a856a4..8e13499 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -404,6 +404,8 @@
 Language/11_Expressions/18_Assignment_A05_t05: Fail, OK # co19 issue 409
 Language/11_Expressions/18_Assignment_A08_t04: Fail, OK # co19 issue 409
 
+LibTest/core/String/indexOf_A01_t02: Fail # Issue 427
+LibTest/core/String/lastIndexOf_A01_t02: Fail # Issue 427
 
 [ $compiler == dart2dart && $minified ]
 Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 396
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index b2f3f82..fb5aa0d 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -257,9 +257,7 @@
 LibTest/core/AssertionError/failedAssertion_A01_t01: Fail # TODO(ahe): Please triage this failure.
 LibTest/core/AssertionError/line_A01_t02: Fail # TODO(ahe): Please triage this failure.
 LibTest/core/AssertionError/url_A01_t01: Fail # TODO(ahe): Please triage this failure.
-LibTest/core/Match/pattern_A01_t01: Fail # TODO(ahe): Please triage this failure.
 LibTest/core/Match/str_A01_t01: Fail # TODO(ahe): Please triage this failure.
-LibTest/core/RegExp/allMatches_A01_t01: Fail # TODO(ahe): Please triage this failure.
 LibTest/core/Set/intersection_A03_t01: Fail # TODO(ahe): Please triage this failure.
 LibTest/core/TypeError/column_A01_t01: Fail # TODO(ahe): Please triage this failure.
 LibTest/core/TypeError/dstName_A01_t01: Fail # TODO(ahe): Please triage this failure.
@@ -537,6 +535,11 @@
 Language/14_Types/5_Function_Types_A01_t10: Fail # co19 issue 410
 Language/14_Types/5_Function_Types_A02_t06: Fail # co19 issue 410
 
+LibTest/core/Match/pattern_A01_t01: Fail # co19 Issue 400, 422
+LibTest/core/RegExp/allMatches_A01_t01: Fail # co19 Issue 400, 422
+
+LibTest/core/String/indexOf_A01_t02: Fail # Issue 427
+LibTest/core/String/lastIndexOf_A01_t02: Fail # Issue 427
 
 [ $compiler == dart2js && $unchecked ]
 LibTest/core/List/setRange_A05_t01: Fail # setRange throws StateError if there aren't enough elements in the iterable. Issue 402
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 960a6cb..b38e62f 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -6,17 +6,6 @@
 Language/11_Expressions/33_Argument_Definition_Test_A02_t02: Crash, Pass # http://dartbug.com/9597
 Language/07_Classes/6_Constructors_A02_t01: Skip # co19 issue 415.
 
-[ $compiler == none && $runtime == vm && $unchecked ]
-Language/11_Expressions/11_Instance_Creation_A05_t02: Fail # TODO(vm-team): Please triage this failure.
-
-
-[ $compiler == none && $runtime == vm && $checked ]
-LibTest/core/AssertionError/line_A01_t02: Fail # TODO(vm-team): Please triage this failure.
-LibTest/core/Set/intersection_A03_t01: Fail # TODO(vm-team): Please triage this failure.
-LibTest/core/TypeError/line_A01_t01: Fail # TODO(vm-team): Please triage this failure.
-
-
-
 [ $compiler == none && $runtime == vm ]
 Language/05_Variables/05_Variables_A07_t01: Fail # TODO(vm-team): Please triage this failure.
 Language/05_Variables/05_Variables_A07_t02: Fail # TODO(vm-team): Please triage this failure.
@@ -70,29 +59,6 @@
 LibTest/core/Match/pattern_A01_t01: Fail # Issue 422
 LibTest/core/RegExp/allMatches_A01_t01: Fail # Issue 422
 
-[ $compiler == none && $runtime == vm && $checked ]
-LibTest/core/Strings/concatAll_A04_t01: Fail, OK # checks for ArgumentError. TypeError is ok too. co19 issue 366
-LibTest/core/Strings/join_A04_t01: Fail, OK # checks for ArgumentError. TypeError is ok too. co19 issue 366
-
-LibTest/core/int/operator_division_A01_t01: Fail # ~/ returns ints, issue 361
-
-Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t02: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t06: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t01: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t02: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t03: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t04: Fail, OK # co19 issue 405
-Language/11_Expressions/17_Getter_Invocation_A02_t01: Fail, OK # co19 issue 405
-Language/11_Expressions/17_Getter_Invocation_A02_t02: Fail, OK # co19 issue 405
-Language/11_Expressions/18_Assignment_A05_t02: Fail, OK # co19 issue 405
-Language/11_Expressions/18_Assignment_A05_t04: Fail, OK # co19 issue 405
-Language/11_Expressions/18_Assignment_A05_t05: Fail, OK # co19 issue 405
-Language/11_Expressions/18_Assignment_A08_t04: Fail, OK # co19 issue 405
-
-
-[ $compiler == none && $runtime == vm ]
 Language/13_Libraries_and_Scripts/1_Imports_A02_t21: Crash # Dart issue 6060
 Language/13_Libraries_and_Scripts/1_Imports_A02_t22: Crash # Dart issue 6060
 
@@ -107,11 +73,8 @@
 Language/07_Classes/4_Abstract_Instance_Members_A04_t05: Fail # Dart issue 978
 Language/07_Classes/4_Abstract_Instance_Members_A04_t06: Fail # Dart issue 978
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: Fail # Dart issue 6954
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: Fail # Dart issue 811
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: Fail # Dart issue 811
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t03: Fail # Dart issue 811
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: Fail # Dart issue 811
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: Fail # Dart issue 811
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: Fail # co19 issue 426
 Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t04: Fail # Dart issue 7246
 Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t05: Fail # Dart issue 7246
 Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t06: Fail # Dart issue 7246
@@ -233,12 +196,6 @@
 Language/11_Expressions/18_Assignment_A05_t05: Fail, OK # co19 issue 409
 Language/11_Expressions/18_Assignment_A08_t04: Fail, OK # co19 issue 409
 
-
-[ $compiler == none && $runtime == vm && $checked ]
-Language/12_Statements/09_Switch_A05_t01: Fail # TODO(vm-team): Please triage this failure.
-
-
-[ $compiler == none && $runtime == vm ]
 Language/11_Expressions/01_Constants_A16_t01: Fail # Not properly reporting exception in initializer expressions
 Language/11_Expressions/01_Constants_A16_t02: Fail # Not properly reporting exception in initializer expressions
 
@@ -282,8 +239,6 @@
 
 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: Fail
 
-
-[ $compiler == none && $runtime == vm ]
 LibTest/core/Date/Date.fromString_A03_t01: Pass # Issue co19 - 121  (currently passing due to co19 issues 373 and 374)
 LibTest/core/Match/operator_subscript_A01_t01: Fail
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail
@@ -292,33 +247,8 @@
 LibTest/core/double/toRadixString_A01_t01: Fail # Issue 463
 LibTest/core/int/toRadixString_A01_t01: Fail # Issue 461
 
-
-[ $compiler == none && $runtime == vm ]
 LibTest/math/sin_A01_t01: Fail, OK # Issue co19 - 44
 
-
-[ $compiler == none && $runtime == vm && $system == macos ]
-LibTest/math/exp_A01_t01: Fail, OK # Issue co19 - 44
-LibTest/math/acos_A01_t01: Fail, OK # Issue co19 - 44
-LibTest/math/asin_A01_t01: Fail, OK # Issue co19 - 44
-LibTest/math/atan_A01_t01: Fail, OK # Issue co19 - 44
-LibTest/math/tan_A01_t01: Fail, OK  # Issue co19 - 44
-
-
-[ $compiler == none && $runtime == vm && $system == linux ]
-LibTest/math/exp_A01_t01: Fail
-
-
-[ $compiler == none && $runtime == vm && $system == linux && $arch == ia32 ]
-LibTest/math/sin_A01_t01: Fail
-LibTest/math/tan_A01_t01: Fail
-
-
-[ $compiler == none && $runtime == vm && $arch == x64 && $mode == debug ]
-LibTest/core/Map/Map_class_A01_t04: Skip # Timeout
-
-
-[ $compiler == none && $runtime == vm ]
 LibTest/core/Date/toString_A02_t01: Fail # Argument error. Year 999999 is out of range. Needs to be specified (and then potentially reported to co19): issue 1878.
 LibTest/core/Date/year_A01_t01: Fail # Year out of range. Needs to be specified: issue 8808. Possibly a co19 bug.
 
@@ -333,18 +263,10 @@
 Language/11_Expressions/07_Maps_A07_t03: Fail, OK # co19 issue 287
 Language/11_Expressions/07_Maps_A04_t02: Fail, OK # co19 issue 287
 
-
-[ $compiler == none && $runtime == vm ]
 LibTest/core/String/contains_A01_t03: Skip # Times out.
 
 LibTest/core/String/contains_A01_t02: Fail
 
-
-[ $compiler == none && $runtime == vm && $arch == ia32 ]
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-
-
-[ $compiler == none && $runtime == vm ]
 Language/07_Classes/07_Classes_A02_t29: Fail
 Language/07_Classes/07_Classes_A02_t31: Fail
 Language/11_Expressions/05_Strings_A20_t01: Fail
@@ -358,16 +280,6 @@
 # parameter name or type expected
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A15_t07: Fail
 
-
-[ $compiler == none && $runtime == vm && $checked ]
-Language/03_Overview/1_Scoping_A02_t30: Fail
-
-
-[ $compiler == none && $runtime == vm && $mode == debug ]
-LibTest/isolate/isolate_api/spawnFunction_A02_t01: Crash
-
-
-[ $compiler == none && $runtime == vm ]
 LibTest/core/Strings/join_A01_t01: Fail # Strings class has been removed. co19 issue 380
 LibTest/core/Strings/join_A04_t01: Fail # Strings class has been removed. co19 issue 380
 LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
@@ -491,7 +403,47 @@
 LibTest/async/Future/then_A01_t01: Fail # Completer is now asynchronous. Issue 419
 LibTest/async/Future/then_A01_t04: Fail # Completer is now asynchronous. Issue 419
 
+LibTest/core/String/indexOf_A01_t02: Fail # Issue 427
+LibTest/core/String/lastIndexOf_A01_t02: Fail # Issue 427
+
+# end [ $compiler == none && $runtime == vm ]
+
+
+[ $compiler == none && $runtime == vm && $unchecked ]
+Language/11_Expressions/11_Instance_Creation_A05_t02: Fail # TODO(vm-team): Please triage this failure.
+
+LibTest/core/List/setRange_A05_t01: Fail # setRange now takes end-argument. Issue 402
+
+
 [ $compiler == none && $runtime == vm && $checked ]
+LibTest/core/AssertionError/line_A01_t02: Fail # TODO(vm-team): Please triage this failure.
+LibTest/core/Set/intersection_A03_t01: Fail # TODO(vm-team): Please triage this failure.
+LibTest/core/TypeError/line_A01_t01: Fail # TODO(vm-team): Please triage this failure.
+
+LibTest/core/Strings/concatAll_A04_t01: Fail, OK # checks for ArgumentError. TypeError is ok too. co19 issue 366
+LibTest/core/Strings/join_A04_t01: Fail, OK # checks for ArgumentError. TypeError is ok too. co19 issue 366
+
+LibTest/core/int/operator_division_A01_t01: Fail # ~/ returns ints, issue 361
+
+Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 405
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t02: Fail, OK # co19 issue 405
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: Fail, OK # co19 issue 405
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t06: Fail, OK # co19 issue 405
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t01: Fail, OK # co19 issue 405
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t02: Fail, OK # co19 issue 405
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t03: Fail, OK # co19 issue 405
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t04: Fail, OK # co19 issue 405
+Language/11_Expressions/17_Getter_Invocation_A02_t01: Fail, OK # co19 issue 405
+Language/11_Expressions/17_Getter_Invocation_A02_t02: Fail, OK # co19 issue 405
+Language/11_Expressions/18_Assignment_A05_t02: Fail, OK # co19 issue 405
+Language/11_Expressions/18_Assignment_A05_t04: Fail, OK # co19 issue 405
+Language/11_Expressions/18_Assignment_A05_t05: Fail, OK # co19 issue 405
+Language/11_Expressions/18_Assignment_A08_t04: Fail, OK # co19 issue 405
+
+Language/12_Statements/09_Switch_A05_t01: Fail # TODO(vm-team): Please triage this failure.
+
+Language/03_Overview/1_Scoping_A02_t30: Fail
+
 LibTest/core/Set/intersection_A01_t01: Fail # issue 390
 LibTest/core/Set/intersection_A01_t02: Fail # issue 390
 LibTest/core/Set/intersection_A01_t03: Fail # issue 390
@@ -506,50 +458,76 @@
 LibTest/async/Future/catchError_A01_t01: Fail # No AsyncError anymore. Issue 407
 LibTest/async/Future/catchError_A01_t02: Fail # No AsyncError anymore. Issue 407
 
-[ $compiler == none && $runtime == vm && $unchecked ]
-LibTest/core/List/setRange_A05_t01: Fail # setRange now takes end-argument. Issue 402
+#end [ $compiler == none && $runtime == vm && $checked ]
+
+
+[ $compiler == none && $runtime == vm && $mode == debug ]
+LibTest/isolate/isolate_api/spawnFunction_A02_t01: Crash
+
+
+[ $compiler == none && $runtime == vm && $system == macos ]
+LibTest/math/exp_A01_t01: Fail, OK # Issue co19 - 44
+LibTest/math/acos_A01_t01: Fail, OK # Issue co19 - 44
+LibTest/math/asin_A01_t01: Fail, OK # Issue co19 - 44
+LibTest/math/atan_A01_t01: Fail, OK # Issue co19 - 44
+LibTest/math/tan_A01_t01: Fail, OK  # Issue co19 - 44
+
+
+[ $compiler == none && $runtime == vm && $system == linux ]
+LibTest/math/exp_A01_t01: Fail
+
+
+[ $compiler == none && $runtime == vm && $system == linux && $arch == ia32 ]
+LibTest/math/sin_A01_t01: Fail
+LibTest/math/tan_A01_t01: Fail
+
+
+[ $compiler == none && $runtime == vm && $arch == x64 && $mode == debug ]
+LibTest/core/Map/Map_class_A01_t04: Skip # Timeout
+
+
+[ $compiler == none && $runtime == vm && $arch == ia32 ]
+LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
+
 
 [ $compiler == none && $runtime == vm && $arch == arm ]
 LibTest/math/tan_A01_t01: Pass, Fail
-LibTest/math/cos_A01_t01: Pass, Fail
 LibTest/math/sin_A01_t01: Pass, Fail
-LibTest/math/Random/nextDouble_A01_t01: Pass, Crash, Fail
-LibTest/core/int/operator_left_shift_A01_t02: Fail
-LibTest/core/int/operator_unary_minus_A01_t01: Fail, Pass
+LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
+LibTest/core/int/operator_unary_minus_A01_t01: Pass, Fail
+LibTest/math/Random/nextDouble_A01_t01: Pass, Fail
+
 
 [ $compiler == none && $runtime == vm && $arch == arm && $mode == debug ]
 LibTest/core/Expect/throws_A01_t04: Crash
-LibTest/core/List/sort_A01_t04: Crash
 LibTest/core/List/sort_A01_t05: Crash
 LibTest/core/List/sort_A01_t06: Crash
-LibTest/core/double/ceil_A01_t02: Fail, Pass
-LibTest/core/double/floor_A01_t02: Fail, Pass
-LibTest/core/double/truncate_A01_t01: Fail, Pass
-LibTest/core/int/operator_left_shift_A01_t02: Fail
-LibTest/core/int/operator_unary_minus_A01_t01: Fail, Pass
+LibTest/core/double/ceil_A01_t02: Fail
+LibTest/core/double/floor_A01_t02: Fail
+LibTest/core/double/truncate_A01_t01: Fail
+
 
 [ $compiler == none && $runtime == vm && $arch == simarm ]
 LibTest/math/tan_A01_t01: Pass, Fail
-LibTest/math/cos_A01_t01: Pass, Fail
-LibTest/math/sin_A01_t01: Pass, Fail
-LibTest/math/Random/nextDouble_A01_t01: Pass, Crash, Fail
-LibTest/core/int/operator_left_shift_A01_t02: Fail
-LibTest/core/int/operator_unary_minus_A01_t01: Fail, Pass
+LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
+LibTest/core/int/operator_unary_minus_A01_t01: Fail, Pass # Pass on Mac
+LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
+LibTest/math/Random/nextDouble_A01_t01: Pass, Crash
+
 
 [ $compiler == none && $runtime == vm && $arch == simarm && $mode == debug ]
 LibTest/core/Expect/throws_A01_t04: Crash
-LibTest/core/List/sort_A01_t04: Crash
 LibTest/core/List/sort_A01_t05: Crash
 LibTest/core/List/sort_A01_t06: Crash
-LibTest/core/double/ceil_A01_t02: Fail, Pass
-LibTest/core/double/floor_A01_t02: Fail, Pass
-LibTest/core/double/truncate_A01_t01: Fail, Pass
-LibTest/core/int/operator_left_shift_A01_t02: Fail
-LibTest/core/int/operator_unary_minus_A01_t01: Fail, Pass
+LibTest/core/double/ceil_A01_t02: Fail, Pass # Pass on Mac
+LibTest/core/double/floor_A01_t02: Fail, Pass # Pass on Mac
+LibTest/core/double/truncate_A01_t01: Fail, Pass # Pass on Mac
+
 
 [ $compiler == none && $runtime == vm && $arch == mips ]
 *: Skip
 
+
 [ $compiler == none && $runtime == vm && $arch == simmips ]
 *: Skip
 
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index c801442..581b26b 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -33,7 +33,8 @@
         var parameter =
           printElement.computeSignature(compiler).requiredParameters.head;
         var type = compiler.typesTask.getGuaranteedTypeOfElement(parameter);
-        Expect.isNull(type);
+        var inferrer = compiler.typesTask.typesInferrer;
+        Expect.identical(inferrer.dynamicType, type);
       });
 
   compileAndFind(
diff --git a/tests/compiler/dart2js/generate_at_use_site_test.dart b/tests/compiler/dart2js/generate_at_use_site_test.dart
index 8204f6a..573b302 100644
--- a/tests/compiler/dart2js/generate_at_use_site_test.dart
+++ b/tests/compiler/dart2js/generate_at_use_site_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 "package:expect/expect.dart";
 import 'compiler_helper.dart';
 
 const String FIB = r"""
@@ -34,6 +35,19 @@
 }
 """;
 
+// Test that a synthesized [HTypeConversion] node added due to the is
+// check is code motion invariant. No 'else' should be generated in
+// this code snippet (the new [HTypeConversion] is put in the else
+// branch, but the else branch dominates the rest of the code in this
+// snippet).
+const String TEST = r"""
+foo(a) {
+  if (a is !int) throw a;
+  if (a < 0) throw a;
+  return a + a;
+}
+""";
+
 main() {
   // Make sure we don't introduce a new variable.
   RegExp regexp = new RegExp("var $anyIdentifier =");
@@ -41,4 +55,10 @@
 
   regexp = new RegExp("isLeaf");
   compileAndDoNotMatch(BAR, 'bar', regexp);
+
+  String generated = compile(TEST, entry: 'foo');
+  Expect.isFalse(generated.contains('else'));
+  // Regression check to ensure that there is no floating variable
+  // expression.
+  Expect.isFalse(new RegExp('^[ ]*a;').hasMatch(generated));
 }
diff --git a/tests/compiler/dart2js/gvn_test.dart b/tests/compiler/dart2js/gvn_test.dart
index b580aca..b648bca 100644
--- a/tests/compiler/dart2js/gvn_test.dart
+++ b/tests/compiler/dart2js/gvn_test.dart
@@ -41,6 +41,25 @@
 }
 """;
 
+// Check that [HCheck] instructions do not prevent GVN.
+const String TEST_FIVE = r"""
+class A {
+  var foo = 21;
+}
+
+class B {}
+
+main() {
+  var a = [new B(), new A()][0];
+  var b = a.foo;
+  var c = a.foo;
+  if (a is B) {
+    c = a.foo;
+  }
+  return b + c;
+}
+""";
+
 main() {
   String generated = compile(TEST_ONE, entry: 'foo');
   RegExp regexp = new RegExp(r"1 \+ [a-z]+");
@@ -54,4 +73,8 @@
 
   generated = compile(TEST_FOUR, entry: 'foo');
   checkNumberOfMatches(new RegExp("shr").allMatches(generated).iterator, 1);
+
+  generated = compileAll(TEST_FIVE);
+  checkNumberOfMatches(
+      new RegExp("get\\\$foo").allMatches(generated).iterator, 1);
 }
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 7102f8b..08a8630 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -1139,7 +1139,9 @@
       ClassElement classElement = element;
       classElement.ensureResolved(compiler);
       // Analyze last class member.
-      classElement.forEachLocalMember((Element e) => element = e);
+      classElement.forEachLocalMember((Element e) {
+        if (!e.isSynthesized) element = e;
+      });
     }
     Node node = element.parseNode(compiler);
     TreeElements mapping = compiler.resolver.resolve(element);
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index 3fea40e..f1a1366 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -14,17 +14,10 @@
 const NUMBER = HType.NUMBER;
 const INTEGER = HType.INTEGER;
 const DOUBLE = HType.DOUBLE;
-const INDEXABLE_PRIMITIVE = HType.INDEXABLE_PRIMITIVE;
-const STRING = HType.STRING;
-const READABLE_ARRAY = HType.READABLE_ARRAY;
-const MUTABLE_ARRAY = HType.MUTABLE_ARRAY;
-const FIXED_ARRAY = HType.FIXED_ARRAY;
-const EXTENDABLE_ARRAY = HType.EXTENDABLE_ARRAY;
 const BOOLEAN_OR_NULL = HType.BOOLEAN_OR_NULL;
 const NUMBER_OR_NULL = HType.NUMBER_OR_NULL;
 const INTEGER_OR_NULL = HType.INTEGER_OR_NULL;
 const DOUBLE_OR_NULL = HType.DOUBLE_OR_NULL;
-const STRING_OR_NULL = HType.STRING_OR_NULL;
 const NULL = HType.NULL;
 const NON_NULL = HType.NON_NULL;
 
@@ -35,6 +28,13 @@
 HType potentialString;
 HType jsInterceptor;
 
+HType jsIndexable;
+HType jsReadableArray;
+HType jsMutableArray;
+HType jsFixedArray;
+HType jsExtendableArray;
+HType jsString;
+HType jsStringOrNull;
 HType jsArrayOrNull;
 HType jsMutableArrayOrNull;
 HType jsFixedArrayOrNull;
@@ -107,11 +107,11 @@
   rule(CONFLICTING, NUMBER, NUMBER);
   rule(CONFLICTING, INTEGER, INTEGER);
   rule(CONFLICTING, DOUBLE, DOUBLE);
-  rule(CONFLICTING, INDEXABLE_PRIMITIVE, INDEXABLE_PRIMITIVE);
-  rule(CONFLICTING, STRING, STRING);
-  rule(CONFLICTING, READABLE_ARRAY, READABLE_ARRAY);
-  rule(CONFLICTING, MUTABLE_ARRAY, MUTABLE_ARRAY);
-  rule(CONFLICTING, EXTENDABLE_ARRAY, EXTENDABLE_ARRAY);
+  rule(CONFLICTING, jsIndexable, jsIndexable);
+  rule(CONFLICTING, jsString, jsString);
+  rule(CONFLICTING, jsReadableArray, jsReadableArray);
+  rule(CONFLICTING, jsMutableArray, jsMutableArray);
+  rule(CONFLICTING, jsExtendableArray, jsExtendableArray);
   rule(CONFLICTING, nonPrimitive1, nonPrimitive1);
   rule(CONFLICTING, nonPrimitive2, nonPrimitive2);
   rule(CONFLICTING, potentialArray, potentialArray);
@@ -120,20 +120,20 @@
   rule(CONFLICTING, NUMBER_OR_NULL, NUMBER_OR_NULL);
   rule(CONFLICTING, INTEGER_OR_NULL, INTEGER_OR_NULL);
   rule(CONFLICTING, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(CONFLICTING, STRING_OR_NULL, STRING_OR_NULL);
+  rule(CONFLICTING, jsStringOrNull, jsStringOrNull);
   rule(CONFLICTING, NULL, NULL);
-  rule(CONFLICTING, FIXED_ARRAY, FIXED_ARRAY);
+  rule(CONFLICTING, jsFixedArray, jsFixedArray);
 
   rule(UNKNOWN, UNKNOWN, UNKNOWN);
   rule(UNKNOWN, BOOLEAN, UNKNOWN);
   rule(UNKNOWN, NUMBER, UNKNOWN);
   rule(UNKNOWN, INTEGER, UNKNOWN);
   rule(UNKNOWN, DOUBLE, UNKNOWN);
-  rule(UNKNOWN, INDEXABLE_PRIMITIVE, UNKNOWN);
-  rule(UNKNOWN, STRING, UNKNOWN);
-  rule(UNKNOWN, READABLE_ARRAY, UNKNOWN);
-  rule(UNKNOWN, MUTABLE_ARRAY, UNKNOWN);
-  rule(UNKNOWN, EXTENDABLE_ARRAY, UNKNOWN);
+  rule(UNKNOWN, jsIndexable, UNKNOWN);
+  rule(UNKNOWN, jsString, UNKNOWN);
+  rule(UNKNOWN, jsReadableArray, UNKNOWN);
+  rule(UNKNOWN, jsMutableArray, UNKNOWN);
+  rule(UNKNOWN, jsExtendableArray, UNKNOWN);
   rule(UNKNOWN, nonPrimitive1, UNKNOWN);
   rule(UNKNOWN, nonPrimitive2, UNKNOWN);
   rule(UNKNOWN, potentialArray, UNKNOWN);
@@ -142,19 +142,19 @@
   rule(UNKNOWN, NUMBER_OR_NULL, UNKNOWN);
   rule(UNKNOWN, INTEGER_OR_NULL, UNKNOWN);
   rule(UNKNOWN, DOUBLE_OR_NULL, UNKNOWN);
-  rule(UNKNOWN, STRING_OR_NULL, UNKNOWN);
+  rule(UNKNOWN, jsStringOrNull, UNKNOWN);
   rule(UNKNOWN, NULL, UNKNOWN);
-  rule(UNKNOWN, FIXED_ARRAY, UNKNOWN);
+  rule(UNKNOWN, jsFixedArray, UNKNOWN);
 
   rule(BOOLEAN, BOOLEAN, BOOLEAN);
   rule(BOOLEAN, NUMBER, jsInterceptor);
   rule(BOOLEAN, INTEGER, jsInterceptor);
   rule(BOOLEAN, DOUBLE, jsInterceptor);
-  rule(BOOLEAN, INDEXABLE_PRIMITIVE, NON_NULL);
-  rule(BOOLEAN, STRING, jsInterceptor);
-  rule(BOOLEAN, READABLE_ARRAY, jsInterceptor);
-  rule(BOOLEAN, MUTABLE_ARRAY, jsInterceptor);
-  rule(BOOLEAN, EXTENDABLE_ARRAY, jsInterceptor);
+  rule(BOOLEAN, jsIndexable, NON_NULL);
+  rule(BOOLEAN, jsString, jsInterceptor);
+  rule(BOOLEAN, jsReadableArray, jsInterceptor);
+  rule(BOOLEAN, jsMutableArray, jsInterceptor);
+  rule(BOOLEAN, jsExtendableArray, jsInterceptor);
   rule(BOOLEAN, nonPrimitive1, NON_NULL);
   rule(BOOLEAN, nonPrimitive2, NON_NULL);
   rule(BOOLEAN, potentialArray, UNKNOWN);
@@ -163,18 +163,18 @@
   rule(BOOLEAN, NUMBER_OR_NULL, jsInterceptorOrNull);
   rule(BOOLEAN, INTEGER_OR_NULL, jsInterceptorOrNull);
   rule(BOOLEAN, DOUBLE_OR_NULL, jsInterceptorOrNull);
-  rule(BOOLEAN, STRING_OR_NULL, jsInterceptorOrNull);
+  rule(BOOLEAN, jsStringOrNull, jsInterceptorOrNull);
   rule(BOOLEAN, NULL, BOOLEAN_OR_NULL);
-  rule(BOOLEAN, FIXED_ARRAY, jsInterceptor);
+  rule(BOOLEAN, jsFixedArray, jsInterceptor);
 
   rule(NUMBER, NUMBER, NUMBER);
   rule(NUMBER, INTEGER, NUMBER);
   rule(NUMBER, DOUBLE, NUMBER);
-  rule(NUMBER, INDEXABLE_PRIMITIVE, NON_NULL);
-  rule(NUMBER, STRING, jsInterceptor);
-  rule(NUMBER, READABLE_ARRAY, jsInterceptor);
-  rule(NUMBER, MUTABLE_ARRAY, jsInterceptor);
-  rule(NUMBER, EXTENDABLE_ARRAY, jsInterceptor);
+  rule(NUMBER, jsIndexable, NON_NULL);
+  rule(NUMBER, jsString, jsInterceptor);
+  rule(NUMBER, jsReadableArray, jsInterceptor);
+  rule(NUMBER, jsMutableArray, jsInterceptor);
+  rule(NUMBER, jsExtendableArray, jsInterceptor);
   rule(NUMBER, nonPrimitive1, NON_NULL);
   rule(NUMBER, nonPrimitive2, NON_NULL);
   rule(NUMBER, potentialArray, UNKNOWN);
@@ -183,17 +183,17 @@
   rule(NUMBER, NUMBER_OR_NULL, NUMBER_OR_NULL);
   rule(NUMBER, INTEGER_OR_NULL, NUMBER_OR_NULL);
   rule(NUMBER, DOUBLE_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER, STRING_OR_NULL, jsInterceptorOrNull);
+  rule(NUMBER, jsStringOrNull, jsInterceptorOrNull);
   rule(NUMBER, NULL, NUMBER_OR_NULL);
-  rule(NUMBER, FIXED_ARRAY, jsInterceptor);
+  rule(NUMBER, jsFixedArray, jsInterceptor);
 
   rule(INTEGER, INTEGER, INTEGER);
   rule(INTEGER, DOUBLE, NUMBER);
-  rule(INTEGER, INDEXABLE_PRIMITIVE, NON_NULL);
-  rule(INTEGER, STRING, jsInterceptor);
-  rule(INTEGER, READABLE_ARRAY, jsInterceptor);
-  rule(INTEGER, MUTABLE_ARRAY, jsInterceptor);
-  rule(INTEGER, EXTENDABLE_ARRAY, jsInterceptor);
+  rule(INTEGER, jsIndexable, NON_NULL);
+  rule(INTEGER, jsString, jsInterceptor);
+  rule(INTEGER, jsReadableArray, jsInterceptor);
+  rule(INTEGER, jsMutableArray, jsInterceptor);
+  rule(INTEGER, jsExtendableArray, jsInterceptor);
   rule(INTEGER, nonPrimitive1, NON_NULL);
   rule(INTEGER, nonPrimitive2, NON_NULL);
   rule(INTEGER, potentialArray, UNKNOWN);
@@ -202,16 +202,16 @@
   rule(INTEGER, NUMBER_OR_NULL, NUMBER_OR_NULL);
   rule(INTEGER, INTEGER_OR_NULL, INTEGER_OR_NULL);
   rule(INTEGER, DOUBLE_OR_NULL, NUMBER_OR_NULL);
-  rule(INTEGER, STRING_OR_NULL, jsInterceptorOrNull);
+  rule(INTEGER, jsStringOrNull, jsInterceptorOrNull);
   rule(INTEGER, NULL, INTEGER_OR_NULL);
-  rule(INTEGER, FIXED_ARRAY, jsInterceptor);
+  rule(INTEGER, jsFixedArray, jsInterceptor);
 
   rule(DOUBLE, DOUBLE, DOUBLE);
-  rule(DOUBLE, INDEXABLE_PRIMITIVE, NON_NULL);
-  rule(DOUBLE, STRING, jsInterceptor);
-  rule(DOUBLE, READABLE_ARRAY, jsInterceptor);
-  rule(DOUBLE, MUTABLE_ARRAY, jsInterceptor);
-  rule(DOUBLE, EXTENDABLE_ARRAY, jsInterceptor);
+  rule(DOUBLE, jsIndexable, NON_NULL);
+  rule(DOUBLE, jsString, jsInterceptor);
+  rule(DOUBLE, jsReadableArray, jsInterceptor);
+  rule(DOUBLE, jsMutableArray, jsInterceptor);
+  rule(DOUBLE, jsExtendableArray, jsInterceptor);
   rule(DOUBLE, nonPrimitive1, NON_NULL);
   rule(DOUBLE, nonPrimitive2, NON_NULL);
   rule(DOUBLE, potentialArray, UNKNOWN);
@@ -220,84 +220,84 @@
   rule(DOUBLE, NUMBER_OR_NULL, NUMBER_OR_NULL);
   rule(DOUBLE, INTEGER_OR_NULL, NUMBER_OR_NULL);
   rule(DOUBLE, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE, STRING_OR_NULL, jsInterceptorOrNull);
+  rule(DOUBLE, jsStringOrNull, jsInterceptorOrNull);
   rule(DOUBLE, NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE, FIXED_ARRAY, jsInterceptor);
+  rule(DOUBLE, jsFixedArray, jsInterceptor);
 
-  rule(INDEXABLE_PRIMITIVE, INDEXABLE_PRIMITIVE, INDEXABLE_PRIMITIVE);
-  rule(INDEXABLE_PRIMITIVE, STRING, INDEXABLE_PRIMITIVE);
-  rule(INDEXABLE_PRIMITIVE, READABLE_ARRAY, INDEXABLE_PRIMITIVE);
-  rule(INDEXABLE_PRIMITIVE, MUTABLE_ARRAY, INDEXABLE_PRIMITIVE);
-  rule(INDEXABLE_PRIMITIVE, EXTENDABLE_ARRAY, INDEXABLE_PRIMITIVE);
-  rule(INDEXABLE_PRIMITIVE, nonPrimitive1, NON_NULL);
-  rule(INDEXABLE_PRIMITIVE, nonPrimitive2, NON_NULL);
-  rule(INDEXABLE_PRIMITIVE, potentialArray, UNKNOWN);
-  rule(INDEXABLE_PRIMITIVE, potentialString, UNKNOWN);
-  rule(INDEXABLE_PRIMITIVE, BOOLEAN_OR_NULL, UNKNOWN);
-  rule(INDEXABLE_PRIMITIVE, NUMBER_OR_NULL, UNKNOWN);
-  rule(INDEXABLE_PRIMITIVE, INTEGER_OR_NULL, UNKNOWN);
-  rule(INDEXABLE_PRIMITIVE, DOUBLE_OR_NULL, UNKNOWN);
-  rule(INDEXABLE_PRIMITIVE, STRING_OR_NULL, jsIndexableOrNull);
-  rule(INDEXABLE_PRIMITIVE, NULL, jsIndexableOrNull);
-  rule(INDEXABLE_PRIMITIVE, FIXED_ARRAY, INDEXABLE_PRIMITIVE);
+  rule(jsIndexable, jsIndexable, jsIndexable);
+  rule(jsIndexable, jsString, jsIndexable);
+  rule(jsIndexable, jsReadableArray, jsIndexable);
+  rule(jsIndexable, jsMutableArray, jsIndexable);
+  rule(jsIndexable, jsExtendableArray, jsIndexable);
+  rule(jsIndexable, nonPrimitive1, NON_NULL);
+  rule(jsIndexable, nonPrimitive2, NON_NULL);
+  rule(jsIndexable, potentialArray, UNKNOWN);
+  rule(jsIndexable, potentialString, UNKNOWN);
+  rule(jsIndexable, BOOLEAN_OR_NULL, UNKNOWN);
+  rule(jsIndexable, NUMBER_OR_NULL, UNKNOWN);
+  rule(jsIndexable, INTEGER_OR_NULL, UNKNOWN);
+  rule(jsIndexable, DOUBLE_OR_NULL, UNKNOWN);
+  rule(jsIndexable, jsStringOrNull, jsIndexableOrNull);
+  rule(jsIndexable, NULL, jsIndexableOrNull);
+  rule(jsIndexable, jsFixedArray, jsIndexable);
 
-  rule(STRING, STRING, STRING);
-  rule(STRING, READABLE_ARRAY, INDEXABLE_PRIMITIVE);
-  rule(STRING, MUTABLE_ARRAY, INDEXABLE_PRIMITIVE);
-  rule(STRING, EXTENDABLE_ARRAY, INDEXABLE_PRIMITIVE);
-  rule(STRING, nonPrimitive1, NON_NULL);
-  rule(STRING, nonPrimitive2, NON_NULL);
-  rule(STRING, potentialArray, UNKNOWN);
-  rule(STRING, potentialString, potentialString);
-  rule(STRING, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(STRING, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(STRING, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(STRING, DOUBLE_OR_NULL, jsInterceptorOrNull);
-  rule(STRING, STRING_OR_NULL, STRING_OR_NULL);
-  rule(STRING, NULL, STRING_OR_NULL);
-  rule(STRING, FIXED_ARRAY, INDEXABLE_PRIMITIVE);
+  rule(jsString, jsString, jsString);
+  rule(jsString, jsReadableArray, jsIndexable);
+  rule(jsString, jsMutableArray, jsIndexable);
+  rule(jsString, jsExtendableArray, jsIndexable);
+  rule(jsString, nonPrimitive1, NON_NULL);
+  rule(jsString, nonPrimitive2, NON_NULL);
+  rule(jsString, potentialArray, UNKNOWN);
+  rule(jsString, potentialString, potentialString);
+  rule(jsString, BOOLEAN_OR_NULL, jsInterceptorOrNull);
+  rule(jsString, NUMBER_OR_NULL, jsInterceptorOrNull);
+  rule(jsString, INTEGER_OR_NULL, jsInterceptorOrNull);
+  rule(jsString, DOUBLE_OR_NULL, jsInterceptorOrNull);
+  rule(jsString, jsStringOrNull, jsStringOrNull);
+  rule(jsString, NULL, jsStringOrNull);
+  rule(jsString, jsFixedArray, jsIndexable);
 
-  rule(READABLE_ARRAY, READABLE_ARRAY, READABLE_ARRAY);
-  rule(READABLE_ARRAY, MUTABLE_ARRAY, READABLE_ARRAY);
-  rule(READABLE_ARRAY, EXTENDABLE_ARRAY, READABLE_ARRAY);
-  rule(READABLE_ARRAY, nonPrimitive1, NON_NULL);
-  rule(READABLE_ARRAY, nonPrimitive2, NON_NULL);
-  rule(READABLE_ARRAY, potentialArray, potentialArray);
-  rule(READABLE_ARRAY, potentialString, UNKNOWN);
-  rule(READABLE_ARRAY, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(READABLE_ARRAY, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(READABLE_ARRAY, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(READABLE_ARRAY, DOUBLE_OR_NULL, jsInterceptorOrNull);
-  rule(READABLE_ARRAY, STRING_OR_NULL, jsIndexableOrNull);
-  rule(READABLE_ARRAY, NULL, jsArrayOrNull);
-  rule(READABLE_ARRAY, FIXED_ARRAY, READABLE_ARRAY);
+  rule(jsReadableArray, jsReadableArray, jsReadableArray);
+  rule(jsReadableArray, jsMutableArray, jsReadableArray);
+  rule(jsReadableArray, jsExtendableArray, jsReadableArray);
+  rule(jsReadableArray, nonPrimitive1, NON_NULL);
+  rule(jsReadableArray, nonPrimitive2, NON_NULL);
+  rule(jsReadableArray, potentialArray, potentialArray);
+  rule(jsReadableArray, potentialString, UNKNOWN);
+  rule(jsReadableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
+  rule(jsReadableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
+  rule(jsReadableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
+  rule(jsReadableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+  rule(jsReadableArray, jsStringOrNull, jsIndexableOrNull);
+  rule(jsReadableArray, NULL, jsArrayOrNull);
+  rule(jsReadableArray, jsFixedArray, jsReadableArray);
 
-  rule(MUTABLE_ARRAY, MUTABLE_ARRAY, MUTABLE_ARRAY);
-  rule(MUTABLE_ARRAY, EXTENDABLE_ARRAY, MUTABLE_ARRAY);
-  rule(MUTABLE_ARRAY, nonPrimitive1, NON_NULL);
-  rule(MUTABLE_ARRAY, nonPrimitive2, NON_NULL);
-  rule(MUTABLE_ARRAY, potentialArray, potentialArray);
-  rule(MUTABLE_ARRAY, potentialString, UNKNOWN);
-  rule(MUTABLE_ARRAY, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(MUTABLE_ARRAY, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(MUTABLE_ARRAY, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(MUTABLE_ARRAY, DOUBLE_OR_NULL, jsInterceptorOrNull);
-  rule(MUTABLE_ARRAY, STRING_OR_NULL, jsIndexableOrNull);
-  rule(MUTABLE_ARRAY, NULL, jsMutableArrayOrNull);
-  rule(MUTABLE_ARRAY, FIXED_ARRAY, MUTABLE_ARRAY);
+  rule(jsMutableArray, jsMutableArray, jsMutableArray);
+  rule(jsMutableArray, jsExtendableArray, jsMutableArray);
+  rule(jsMutableArray, nonPrimitive1, NON_NULL);
+  rule(jsMutableArray, nonPrimitive2, NON_NULL);
+  rule(jsMutableArray, potentialArray, potentialArray);
+  rule(jsMutableArray, potentialString, UNKNOWN);
+  rule(jsMutableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
+  rule(jsMutableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
+  rule(jsMutableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
+  rule(jsMutableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+  rule(jsMutableArray, jsStringOrNull, jsIndexableOrNull);
+  rule(jsMutableArray, NULL, jsMutableArrayOrNull);
+  rule(jsMutableArray, jsFixedArray, jsMutableArray);
 
-  rule(EXTENDABLE_ARRAY, EXTENDABLE_ARRAY, EXTENDABLE_ARRAY);
-  rule(EXTENDABLE_ARRAY, nonPrimitive1, NON_NULL);
-  rule(EXTENDABLE_ARRAY, nonPrimitive2, NON_NULL);
-  rule(EXTENDABLE_ARRAY, potentialArray, potentialArray);
-  rule(EXTENDABLE_ARRAY, potentialString, UNKNOWN);
-  rule(EXTENDABLE_ARRAY, BOOLEAN_OR_NULL, jsInterceptorOrNull);
-  rule(EXTENDABLE_ARRAY, NUMBER_OR_NULL, jsInterceptorOrNull);
-  rule(EXTENDABLE_ARRAY, INTEGER_OR_NULL, jsInterceptorOrNull);
-  rule(EXTENDABLE_ARRAY, DOUBLE_OR_NULL, jsInterceptorOrNull);
-  rule(EXTENDABLE_ARRAY, STRING_OR_NULL, jsIndexableOrNull);
-  rule(EXTENDABLE_ARRAY, NULL, jsExtendableArrayOrNull);
-  rule(EXTENDABLE_ARRAY, FIXED_ARRAY, MUTABLE_ARRAY);
+  rule(jsExtendableArray, jsExtendableArray, jsExtendableArray);
+  rule(jsExtendableArray, nonPrimitive1, NON_NULL);
+  rule(jsExtendableArray, nonPrimitive2, NON_NULL);
+  rule(jsExtendableArray, potentialArray, potentialArray);
+  rule(jsExtendableArray, potentialString, UNKNOWN);
+  rule(jsExtendableArray, BOOLEAN_OR_NULL, jsInterceptorOrNull);
+  rule(jsExtendableArray, NUMBER_OR_NULL, jsInterceptorOrNull);
+  rule(jsExtendableArray, INTEGER_OR_NULL, jsInterceptorOrNull);
+  rule(jsExtendableArray, DOUBLE_OR_NULL, jsInterceptorOrNull);
+  rule(jsExtendableArray, jsStringOrNull, jsIndexableOrNull);
+  rule(jsExtendableArray, NULL, jsExtendableArrayOrNull);
+  rule(jsExtendableArray, jsFixedArray, jsMutableArray);
 
   rule(nonPrimitive1, nonPrimitive1, nonPrimitive1);
   rule(nonPrimitive1, nonPrimitive2, NON_NULL);
@@ -307,8 +307,8 @@
   rule(nonPrimitive1, NUMBER_OR_NULL, UNKNOWN);
   rule(nonPrimitive1, INTEGER_OR_NULL, UNKNOWN);
   rule(nonPrimitive1, DOUBLE_OR_NULL, UNKNOWN);
-  rule(nonPrimitive1, STRING_OR_NULL, UNKNOWN);
-  rule(nonPrimitive1, FIXED_ARRAY, NON_NULL);
+  rule(nonPrimitive1, jsStringOrNull, UNKNOWN);
+  rule(nonPrimitive1, jsFixedArray, NON_NULL);
 
   rule(nonPrimitive2, nonPrimitive2, nonPrimitive2);
   rule(nonPrimitive2, potentialArray, UNKNOWN);
@@ -317,8 +317,8 @@
   rule(nonPrimitive2, NUMBER_OR_NULL, UNKNOWN);
   rule(nonPrimitive2, INTEGER_OR_NULL, UNKNOWN);
   rule(nonPrimitive2, DOUBLE_OR_NULL, UNKNOWN);
-  rule(nonPrimitive2, STRING_OR_NULL, UNKNOWN);
-  rule(nonPrimitive2, FIXED_ARRAY, NON_NULL);
+  rule(nonPrimitive2, jsStringOrNull, UNKNOWN);
+  rule(nonPrimitive2, jsFixedArray, NON_NULL);
 
   rule(potentialArray, potentialArray, potentialArray);
   rule(potentialArray, potentialString, UNKNOWN);
@@ -326,53 +326,53 @@
   rule(potentialArray, NUMBER_OR_NULL, UNKNOWN);
   rule(potentialArray, INTEGER_OR_NULL, UNKNOWN);
   rule(potentialArray, DOUBLE_OR_NULL, UNKNOWN);
-  rule(potentialArray, STRING_OR_NULL, UNKNOWN);
+  rule(potentialArray, jsStringOrNull, UNKNOWN);
   rule(potentialArray, NULL, potentialArray);
-  rule(potentialArray, FIXED_ARRAY, potentialArray);
+  rule(potentialArray, jsFixedArray, potentialArray);
 
   rule(potentialString, potentialString, potentialString);
   rule(potentialString, BOOLEAN_OR_NULL, UNKNOWN);
   rule(potentialString, NUMBER_OR_NULL, UNKNOWN);
   rule(potentialString, INTEGER_OR_NULL, UNKNOWN);
   rule(potentialString, DOUBLE_OR_NULL, UNKNOWN);
-  rule(potentialString, STRING_OR_NULL, potentialString);
+  rule(potentialString, jsStringOrNull, potentialString);
   rule(potentialString, NULL, potentialString);
-  rule(potentialString, FIXED_ARRAY, UNKNOWN);
+  rule(potentialString, jsFixedArray, UNKNOWN);
 
   rule(BOOLEAN_OR_NULL, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
   rule(BOOLEAN_OR_NULL, NUMBER_OR_NULL, jsInterceptorOrNull);
   rule(BOOLEAN_OR_NULL, INTEGER_OR_NULL, jsInterceptorOrNull);
   rule(BOOLEAN_OR_NULL, DOUBLE_OR_NULL, jsInterceptorOrNull);
-  rule(BOOLEAN_OR_NULL, STRING_OR_NULL, jsInterceptorOrNull);
+  rule(BOOLEAN_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
   rule(BOOLEAN_OR_NULL, NULL, BOOLEAN_OR_NULL);
-  rule(BOOLEAN_OR_NULL, FIXED_ARRAY, jsInterceptorOrNull);
+  rule(BOOLEAN_OR_NULL, jsFixedArray, jsInterceptorOrNull);
 
   rule(NUMBER_OR_NULL, NUMBER_OR_NULL, NUMBER_OR_NULL);
   rule(NUMBER_OR_NULL, INTEGER_OR_NULL, NUMBER_OR_NULL);
   rule(NUMBER_OR_NULL, DOUBLE_OR_NULL, NUMBER_OR_NULL);
-  rule(NUMBER_OR_NULL, STRING_OR_NULL, jsInterceptorOrNull);
+  rule(NUMBER_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
   rule(NUMBER_OR_NULL, NULL, NUMBER_OR_NULL);
-  rule(NUMBER_OR_NULL, FIXED_ARRAY, jsInterceptorOrNull);
+  rule(NUMBER_OR_NULL, jsFixedArray, jsInterceptorOrNull);
 
   rule(INTEGER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
   rule(INTEGER_OR_NULL, DOUBLE_OR_NULL, NUMBER_OR_NULL);
-  rule(INTEGER_OR_NULL, STRING_OR_NULL, jsInterceptorOrNull);
+  rule(INTEGER_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
   rule(INTEGER_OR_NULL, NULL, INTEGER_OR_NULL);
-  rule(INTEGER_OR_NULL, FIXED_ARRAY, jsInterceptorOrNull);
+  rule(INTEGER_OR_NULL, jsFixedArray, jsInterceptorOrNull);
 
   rule(DOUBLE_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE_OR_NULL, STRING_OR_NULL, jsInterceptorOrNull);
+  rule(DOUBLE_OR_NULL, jsStringOrNull, jsInterceptorOrNull);
   rule(DOUBLE_OR_NULL, NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE_OR_NULL, FIXED_ARRAY, jsInterceptorOrNull);
+  rule(DOUBLE_OR_NULL, jsFixedArray, jsInterceptorOrNull);
 
-  rule(STRING_OR_NULL, STRING_OR_NULL, STRING_OR_NULL);
-  rule(STRING_OR_NULL, NULL, STRING_OR_NULL);
-  rule(STRING_OR_NULL, FIXED_ARRAY, jsIndexableOrNull);
+  rule(jsStringOrNull, jsStringOrNull, jsStringOrNull);
+  rule(jsStringOrNull, NULL, jsStringOrNull);
+  rule(jsStringOrNull, jsFixedArray, jsIndexableOrNull);
 
   rule(NULL, NULL, NULL);
-  rule(NULL, FIXED_ARRAY, jsFixedArrayOrNull);
+  rule(NULL, jsFixedArray, jsFixedArrayOrNull);
 
-  rule(FIXED_ARRAY, FIXED_ARRAY, FIXED_ARRAY);
+  rule(jsFixedArray, jsFixedArray, jsFixedArray);
 
   check(nonPrimitive1, NULL, (type) => type is HBoundedType);
   check(nonPrimitive2, NULL, (type) => type is HBoundedType);
@@ -393,11 +393,11 @@
   rule(CONFLICTING, NUMBER, CONFLICTING);
   rule(CONFLICTING, INTEGER, CONFLICTING);
   rule(CONFLICTING, DOUBLE, CONFLICTING);
-  rule(CONFLICTING, INDEXABLE_PRIMITIVE, CONFLICTING);
-  rule(CONFLICTING, STRING, CONFLICTING);
-  rule(CONFLICTING, READABLE_ARRAY, CONFLICTING);
-  rule(CONFLICTING, MUTABLE_ARRAY, CONFLICTING);
-  rule(CONFLICTING, EXTENDABLE_ARRAY, CONFLICTING);
+  rule(CONFLICTING, jsIndexable, CONFLICTING);
+  rule(CONFLICTING, jsString, CONFLICTING);
+  rule(CONFLICTING, jsReadableArray, CONFLICTING);
+  rule(CONFLICTING, jsMutableArray, CONFLICTING);
+  rule(CONFLICTING, jsExtendableArray, CONFLICTING);
   rule(CONFLICTING, nonPrimitive1, CONFLICTING);
   rule(CONFLICTING, nonPrimitive2, CONFLICTING);
   rule(CONFLICTING, potentialArray, CONFLICTING);
@@ -406,20 +406,20 @@
   rule(CONFLICTING, NUMBER_OR_NULL, CONFLICTING);
   rule(CONFLICTING, INTEGER_OR_NULL, CONFLICTING);
   rule(CONFLICTING, DOUBLE_OR_NULL, CONFLICTING);
-  rule(CONFLICTING, STRING_OR_NULL, CONFLICTING);
+  rule(CONFLICTING, jsStringOrNull, CONFLICTING);
   rule(CONFLICTING, NULL, CONFLICTING);
-  rule(CONFLICTING, FIXED_ARRAY, CONFLICTING);
+  rule(CONFLICTING, jsFixedArray, CONFLICTING);
 
   rule(UNKNOWN, UNKNOWN, UNKNOWN);
   rule(UNKNOWN, BOOLEAN, BOOLEAN);
   rule(UNKNOWN, NUMBER, NUMBER);
   rule(UNKNOWN, INTEGER, INTEGER);
   rule(UNKNOWN, DOUBLE, DOUBLE);
-  rule(UNKNOWN, INDEXABLE_PRIMITIVE, INDEXABLE_PRIMITIVE);
-  rule(UNKNOWN, STRING, STRING);
-  rule(UNKNOWN, READABLE_ARRAY, READABLE_ARRAY);
-  rule(UNKNOWN, MUTABLE_ARRAY, MUTABLE_ARRAY);
-  rule(UNKNOWN, EXTENDABLE_ARRAY, EXTENDABLE_ARRAY);
+  rule(UNKNOWN, jsIndexable, jsIndexable);
+  rule(UNKNOWN, jsString, jsString);
+  rule(UNKNOWN, jsReadableArray, jsReadableArray);
+  rule(UNKNOWN, jsMutableArray, jsMutableArray);
+  rule(UNKNOWN, jsExtendableArray, jsExtendableArray);
   rule(UNKNOWN, nonPrimitive1, nonPrimitive1);
   rule(UNKNOWN, nonPrimitive2, nonPrimitive2);
   rule(UNKNOWN, potentialArray, potentialArray);
@@ -428,19 +428,19 @@
   rule(UNKNOWN, NUMBER_OR_NULL, NUMBER_OR_NULL);
   rule(UNKNOWN, INTEGER_OR_NULL, INTEGER_OR_NULL);
   rule(UNKNOWN, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(UNKNOWN, STRING_OR_NULL, STRING_OR_NULL);
+  rule(UNKNOWN, jsStringOrNull, jsStringOrNull);
   rule(UNKNOWN, NULL, NULL);
-  rule(UNKNOWN, FIXED_ARRAY, FIXED_ARRAY);
+  rule(UNKNOWN, jsFixedArray, jsFixedArray);
 
   rule(BOOLEAN, BOOLEAN, BOOLEAN);
   rule(BOOLEAN, NUMBER, CONFLICTING);
   rule(BOOLEAN, INTEGER, CONFLICTING);
   rule(BOOLEAN, DOUBLE, CONFLICTING);
-  rule(BOOLEAN, INDEXABLE_PRIMITIVE, CONFLICTING);
-  rule(BOOLEAN, STRING, CONFLICTING);
-  rule(BOOLEAN, READABLE_ARRAY, CONFLICTING);
-  rule(BOOLEAN, MUTABLE_ARRAY, CONFLICTING);
-  rule(BOOLEAN, EXTENDABLE_ARRAY, CONFLICTING);
+  rule(BOOLEAN, jsIndexable, CONFLICTING);
+  rule(BOOLEAN, jsString, CONFLICTING);
+  rule(BOOLEAN, jsReadableArray, CONFLICTING);
+  rule(BOOLEAN, jsMutableArray, CONFLICTING);
+  rule(BOOLEAN, jsExtendableArray, CONFLICTING);
   rule(BOOLEAN, nonPrimitive1, CONFLICTING);
   rule(BOOLEAN, nonPrimitive2, CONFLICTING);
   rule(BOOLEAN, potentialArray, CONFLICTING);
@@ -449,18 +449,18 @@
   rule(BOOLEAN, NUMBER_OR_NULL, CONFLICTING);
   rule(BOOLEAN, INTEGER_OR_NULL, CONFLICTING);
   rule(BOOLEAN, DOUBLE_OR_NULL, CONFLICTING);
-  rule(BOOLEAN, STRING_OR_NULL, CONFLICTING);
+  rule(BOOLEAN, jsStringOrNull, CONFLICTING);
   rule(BOOLEAN, NULL, CONFLICTING);
-  rule(BOOLEAN, FIXED_ARRAY, CONFLICTING);
+  rule(BOOLEAN, jsFixedArray, CONFLICTING);
 
   rule(NUMBER, NUMBER, NUMBER);
   rule(NUMBER, INTEGER, INTEGER);
   rule(NUMBER, DOUBLE, DOUBLE);
-  rule(NUMBER, INDEXABLE_PRIMITIVE, CONFLICTING);
-  rule(NUMBER, STRING, CONFLICTING);
-  rule(NUMBER, READABLE_ARRAY, CONFLICTING);
-  rule(NUMBER, MUTABLE_ARRAY, CONFLICTING);
-  rule(NUMBER, EXTENDABLE_ARRAY, CONFLICTING);
+  rule(NUMBER, jsIndexable, CONFLICTING);
+  rule(NUMBER, jsString, CONFLICTING);
+  rule(NUMBER, jsReadableArray, CONFLICTING);
+  rule(NUMBER, jsMutableArray, CONFLICTING);
+  rule(NUMBER, jsExtendableArray, CONFLICTING);
   rule(NUMBER, nonPrimitive1, CONFLICTING);
   rule(NUMBER, nonPrimitive2, CONFLICTING);
   rule(NUMBER, potentialArray, CONFLICTING);
@@ -469,17 +469,17 @@
   rule(NUMBER, NUMBER_OR_NULL, NUMBER);
   rule(NUMBER, INTEGER_OR_NULL, INTEGER);
   rule(NUMBER, DOUBLE_OR_NULL, DOUBLE);
-  rule(NUMBER, STRING_OR_NULL, CONFLICTING);
+  rule(NUMBER, jsStringOrNull, CONFLICTING);
   rule(NUMBER, NULL, CONFLICTING);
-  rule(NUMBER, FIXED_ARRAY, CONFLICTING);
+  rule(NUMBER, jsFixedArray, CONFLICTING);
 
   rule(INTEGER, INTEGER, INTEGER);
   rule(INTEGER, DOUBLE, CONFLICTING);
-  rule(INTEGER, INDEXABLE_PRIMITIVE, CONFLICTING);
-  rule(INTEGER, STRING, CONFLICTING);
-  rule(INTEGER, READABLE_ARRAY, CONFLICTING);
-  rule(INTEGER, MUTABLE_ARRAY, CONFLICTING);
-  rule(INTEGER, EXTENDABLE_ARRAY, CONFLICTING);
+  rule(INTEGER, jsIndexable, CONFLICTING);
+  rule(INTEGER, jsString, CONFLICTING);
+  rule(INTEGER, jsReadableArray, CONFLICTING);
+  rule(INTEGER, jsMutableArray, CONFLICTING);
+  rule(INTEGER, jsExtendableArray, CONFLICTING);
   rule(INTEGER, nonPrimitive1, CONFLICTING);
   rule(INTEGER, nonPrimitive2, CONFLICTING);
   rule(INTEGER, potentialArray, CONFLICTING);
@@ -488,16 +488,16 @@
   rule(INTEGER, NUMBER_OR_NULL, INTEGER);
   rule(INTEGER, INTEGER_OR_NULL, INTEGER);
   rule(INTEGER, DOUBLE_OR_NULL, CONFLICTING);
-  rule(INTEGER, STRING_OR_NULL, CONFLICTING);
+  rule(INTEGER, jsStringOrNull, CONFLICTING);
   rule(INTEGER, NULL, CONFLICTING);
-  rule(INTEGER, FIXED_ARRAY, CONFLICTING);
+  rule(INTEGER, jsFixedArray, CONFLICTING);
 
   rule(DOUBLE, DOUBLE, DOUBLE);
-  rule(DOUBLE, INDEXABLE_PRIMITIVE, CONFLICTING);
-  rule(DOUBLE, STRING, CONFLICTING);
-  rule(DOUBLE, READABLE_ARRAY, CONFLICTING);
-  rule(DOUBLE, MUTABLE_ARRAY, CONFLICTING);
-  rule(DOUBLE, EXTENDABLE_ARRAY, CONFLICTING);
+  rule(DOUBLE, jsIndexable, CONFLICTING);
+  rule(DOUBLE, jsString, CONFLICTING);
+  rule(DOUBLE, jsReadableArray, CONFLICTING);
+  rule(DOUBLE, jsMutableArray, CONFLICTING);
+  rule(DOUBLE, jsExtendableArray, CONFLICTING);
   rule(DOUBLE, nonPrimitive1, CONFLICTING);
   rule(DOUBLE, nonPrimitive2, CONFLICTING);
   rule(DOUBLE, potentialArray, CONFLICTING);
@@ -506,84 +506,85 @@
   rule(DOUBLE, NUMBER_OR_NULL, DOUBLE);
   rule(DOUBLE, INTEGER_OR_NULL, CONFLICTING);
   rule(DOUBLE, DOUBLE_OR_NULL, DOUBLE);
-  rule(DOUBLE, STRING_OR_NULL, CONFLICTING);
+  rule(DOUBLE, jsStringOrNull, CONFLICTING);
   rule(DOUBLE, NULL, CONFLICTING);
-  rule(DOUBLE, FIXED_ARRAY, CONFLICTING);
+  rule(DOUBLE, jsFixedArray, CONFLICTING);
 
-  rule(INDEXABLE_PRIMITIVE, INDEXABLE_PRIMITIVE, INDEXABLE_PRIMITIVE);
-  rule(INDEXABLE_PRIMITIVE, STRING, STRING);
-  rule(INDEXABLE_PRIMITIVE, READABLE_ARRAY, READABLE_ARRAY);
-  rule(INDEXABLE_PRIMITIVE, MUTABLE_ARRAY, MUTABLE_ARRAY);
-  rule(INDEXABLE_PRIMITIVE, EXTENDABLE_ARRAY, EXTENDABLE_ARRAY);
-  rule(INDEXABLE_PRIMITIVE, nonPrimitive1, CONFLICTING);
-  rule(INDEXABLE_PRIMITIVE, nonPrimitive2, CONFLICTING);
-  rule(INDEXABLE_PRIMITIVE, potentialArray, READABLE_ARRAY);
-  rule(INDEXABLE_PRIMITIVE, potentialString, STRING);
-  rule(INDEXABLE_PRIMITIVE, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(INDEXABLE_PRIMITIVE, NUMBER_OR_NULL, CONFLICTING);
-  rule(INDEXABLE_PRIMITIVE, INTEGER_OR_NULL, CONFLICTING);
-  rule(INDEXABLE_PRIMITIVE, DOUBLE_OR_NULL, CONFLICTING);
-  rule(INDEXABLE_PRIMITIVE, STRING_OR_NULL, STRING);
-  rule(INDEXABLE_PRIMITIVE, NULL, CONFLICTING);
-  rule(INDEXABLE_PRIMITIVE, FIXED_ARRAY, FIXED_ARRAY);
+  rule(jsIndexable, jsIndexable, jsIndexable);
+  rule(jsIndexable, jsString, jsString);
+  rule(jsIndexable, jsReadableArray, jsReadableArray);
+  rule(jsIndexable, jsMutableArray, jsMutableArray);
+  rule(jsIndexable, jsExtendableArray, jsExtendableArray);
+  rule(jsIndexable, nonPrimitive1, CONFLICTING);
+  rule(jsIndexable, nonPrimitive2, CONFLICTING);
+  rule(jsIndexable, potentialArray, new HType.nonNullSubtype(
+      compiler.backend.jsArrayClass.computeType(compiler), compiler));
+  rule(jsIndexable, potentialString, jsString);
+  rule(jsIndexable, BOOLEAN_OR_NULL, CONFLICTING);
+  rule(jsIndexable, NUMBER_OR_NULL, CONFLICTING);
+  rule(jsIndexable, INTEGER_OR_NULL, CONFLICTING);
+  rule(jsIndexable, DOUBLE_OR_NULL, CONFLICTING);
+  rule(jsIndexable, jsStringOrNull, jsString);
+  rule(jsIndexable, NULL, CONFLICTING);
+  rule(jsIndexable, jsFixedArray, jsFixedArray);
 
-  rule(STRING, STRING, STRING);
-  rule(STRING, READABLE_ARRAY, CONFLICTING);
-  rule(STRING, MUTABLE_ARRAY, CONFLICTING);
-  rule(STRING, EXTENDABLE_ARRAY, CONFLICTING);
-  rule(STRING, nonPrimitive1, CONFLICTING);
-  rule(STRING, nonPrimitive2, CONFLICTING);
-  rule(STRING, potentialArray, CONFLICTING);
-  rule(STRING, potentialString, STRING);
-  rule(STRING, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(STRING, NUMBER_OR_NULL, CONFLICTING);
-  rule(STRING, INTEGER_OR_NULL, CONFLICTING);
-  rule(STRING, DOUBLE_OR_NULL, CONFLICTING);
-  rule(STRING, STRING_OR_NULL, STRING);
-  rule(STRING, NULL, CONFLICTING);
-  rule(STRING, FIXED_ARRAY, CONFLICTING);
+  rule(jsString, jsString, jsString);
+  rule(jsString, jsReadableArray, CONFLICTING);
+  rule(jsString, jsMutableArray, CONFLICTING);
+  rule(jsString, jsExtendableArray, CONFLICTING);
+  rule(jsString, nonPrimitive1, CONFLICTING);
+  rule(jsString, nonPrimitive2, CONFLICTING);
+  rule(jsString, potentialArray, CONFLICTING);
+  rule(jsString, potentialString, jsString);
+  rule(jsString, BOOLEAN_OR_NULL, CONFLICTING);
+  rule(jsString, NUMBER_OR_NULL, CONFLICTING);
+  rule(jsString, INTEGER_OR_NULL, CONFLICTING);
+  rule(jsString, DOUBLE_OR_NULL, CONFLICTING);
+  rule(jsString, jsStringOrNull, jsString);
+  rule(jsString, NULL, CONFLICTING);
+  rule(jsString, jsFixedArray, CONFLICTING);
 
-  rule(READABLE_ARRAY, READABLE_ARRAY, READABLE_ARRAY);
-  rule(READABLE_ARRAY, MUTABLE_ARRAY, MUTABLE_ARRAY);
-  rule(READABLE_ARRAY, EXTENDABLE_ARRAY, EXTENDABLE_ARRAY);
-  rule(READABLE_ARRAY, nonPrimitive1, CONFLICTING);
-  rule(READABLE_ARRAY, nonPrimitive2, CONFLICTING);
-  rule(READABLE_ARRAY, potentialArray, READABLE_ARRAY);
-  rule(READABLE_ARRAY, potentialString, CONFLICTING);
-  rule(READABLE_ARRAY, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(READABLE_ARRAY, NUMBER_OR_NULL, CONFLICTING);
-  rule(READABLE_ARRAY, INTEGER_OR_NULL, CONFLICTING);
-  rule(READABLE_ARRAY, DOUBLE_OR_NULL, CONFLICTING);
-  rule(READABLE_ARRAY, STRING_OR_NULL, CONFLICTING);
-  rule(READABLE_ARRAY, NULL, CONFLICTING);
-  rule(READABLE_ARRAY, FIXED_ARRAY, FIXED_ARRAY);
+  rule(jsReadableArray, jsReadableArray, jsReadableArray);
+  rule(jsReadableArray, jsMutableArray, jsMutableArray);
+  rule(jsReadableArray, jsExtendableArray, jsExtendableArray);
+  rule(jsReadableArray, nonPrimitive1, CONFLICTING);
+  rule(jsReadableArray, nonPrimitive2, CONFLICTING);
+  rule(jsReadableArray, potentialArray, jsReadableArray);
+  rule(jsReadableArray, potentialString, CONFLICTING);
+  rule(jsReadableArray, BOOLEAN_OR_NULL, CONFLICTING);
+  rule(jsReadableArray, NUMBER_OR_NULL, CONFLICTING);
+  rule(jsReadableArray, INTEGER_OR_NULL, CONFLICTING);
+  rule(jsReadableArray, DOUBLE_OR_NULL, CONFLICTING);
+  rule(jsReadableArray, jsStringOrNull, CONFLICTING);
+  rule(jsReadableArray, NULL, CONFLICTING);
+  rule(jsReadableArray, jsFixedArray, jsFixedArray);
 
-  rule(MUTABLE_ARRAY, MUTABLE_ARRAY, MUTABLE_ARRAY);
-  rule(MUTABLE_ARRAY, EXTENDABLE_ARRAY, EXTENDABLE_ARRAY);
-  rule(MUTABLE_ARRAY, nonPrimitive1, CONFLICTING);
-  rule(MUTABLE_ARRAY, nonPrimitive2, CONFLICTING);
-  rule(MUTABLE_ARRAY, potentialArray, MUTABLE_ARRAY);
-  rule(MUTABLE_ARRAY, potentialString, CONFLICTING);
-  rule(MUTABLE_ARRAY, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(MUTABLE_ARRAY, NUMBER_OR_NULL, CONFLICTING);
-  rule(MUTABLE_ARRAY, INTEGER_OR_NULL, CONFLICTING);
-  rule(MUTABLE_ARRAY, DOUBLE_OR_NULL, CONFLICTING);
-  rule(MUTABLE_ARRAY, STRING_OR_NULL, CONFLICTING);
-  rule(MUTABLE_ARRAY, NULL, CONFLICTING);
-  rule(MUTABLE_ARRAY, FIXED_ARRAY, FIXED_ARRAY);
+  rule(jsMutableArray, jsMutableArray, jsMutableArray);
+  rule(jsMutableArray, jsExtendableArray, jsExtendableArray);
+  rule(jsMutableArray, nonPrimitive1, CONFLICTING);
+  rule(jsMutableArray, nonPrimitive2, CONFLICTING);
+  rule(jsMutableArray, potentialArray, jsMutableArray);
+  rule(jsMutableArray, potentialString, CONFLICTING);
+  rule(jsMutableArray, BOOLEAN_OR_NULL, CONFLICTING);
+  rule(jsMutableArray, NUMBER_OR_NULL, CONFLICTING);
+  rule(jsMutableArray, INTEGER_OR_NULL, CONFLICTING);
+  rule(jsMutableArray, DOUBLE_OR_NULL, CONFLICTING);
+  rule(jsMutableArray, jsStringOrNull, CONFLICTING);
+  rule(jsMutableArray, NULL, CONFLICTING);
+  rule(jsMutableArray, jsFixedArray, jsFixedArray);
 
-  rule(EXTENDABLE_ARRAY, EXTENDABLE_ARRAY, EXTENDABLE_ARRAY);
-  rule(EXTENDABLE_ARRAY, nonPrimitive1, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, nonPrimitive2, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, potentialArray, EXTENDABLE_ARRAY);
-  rule(EXTENDABLE_ARRAY, potentialString, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, BOOLEAN_OR_NULL, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, NUMBER_OR_NULL, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, INTEGER_OR_NULL, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, DOUBLE_OR_NULL, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, STRING_OR_NULL, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, NULL, CONFLICTING);
-  rule(EXTENDABLE_ARRAY, FIXED_ARRAY, CONFLICTING);
+  rule(jsExtendableArray, jsExtendableArray, jsExtendableArray);
+  rule(jsExtendableArray, nonPrimitive1, CONFLICTING);
+  rule(jsExtendableArray, nonPrimitive2, CONFLICTING);
+  rule(jsExtendableArray, potentialArray, jsExtendableArray);
+  rule(jsExtendableArray, potentialString, CONFLICTING);
+  rule(jsExtendableArray, BOOLEAN_OR_NULL, CONFLICTING);
+  rule(jsExtendableArray, NUMBER_OR_NULL, CONFLICTING);
+  rule(jsExtendableArray, INTEGER_OR_NULL, CONFLICTING);
+  rule(jsExtendableArray, DOUBLE_OR_NULL, CONFLICTING);
+  rule(jsExtendableArray, jsStringOrNull, CONFLICTING);
+  rule(jsExtendableArray, NULL, CONFLICTING);
+  rule(jsExtendableArray, jsFixedArray, CONFLICTING);
 
   rule(nonPrimitive1, nonPrimitive1, nonPrimitive1);
   rule(nonPrimitive1, nonPrimitive2, CONFLICTING);
@@ -593,9 +594,9 @@
   rule(nonPrimitive1, NUMBER_OR_NULL, CONFLICTING);
   rule(nonPrimitive1, INTEGER_OR_NULL, CONFLICTING);
   rule(nonPrimitive1, DOUBLE_OR_NULL, CONFLICTING);
-  rule(nonPrimitive1, STRING_OR_NULL, CONFLICTING);
+  rule(nonPrimitive1, jsStringOrNull, CONFLICTING);
   rule(nonPrimitive1, NULL, CONFLICTING);
-  rule(nonPrimitive1, FIXED_ARRAY, CONFLICTING);
+  rule(nonPrimitive1, jsFixedArray, CONFLICTING);
 
   rule(nonPrimitive2, nonPrimitive2, nonPrimitive2);
   rule(nonPrimitive2, potentialArray, CONFLICTING);
@@ -604,9 +605,9 @@
   rule(nonPrimitive2, NUMBER_OR_NULL, CONFLICTING);
   rule(nonPrimitive2, INTEGER_OR_NULL, CONFLICTING);
   rule(nonPrimitive2, DOUBLE_OR_NULL, CONFLICTING);
-  rule(nonPrimitive2, STRING_OR_NULL, CONFLICTING);
+  rule(nonPrimitive2, jsStringOrNull, CONFLICTING);
   rule(nonPrimitive2, NULL, CONFLICTING);
-  rule(nonPrimitive2, FIXED_ARRAY, CONFLICTING);
+  rule(nonPrimitive2, jsFixedArray, CONFLICTING);
 
   rule(potentialArray, potentialArray, potentialArray);
   rule(potentialArray, potentialString, NULL);
@@ -614,53 +615,53 @@
   rule(potentialArray, NUMBER_OR_NULL, NULL);
   rule(potentialArray, INTEGER_OR_NULL, NULL);
   rule(potentialArray, DOUBLE_OR_NULL, NULL);
-  rule(potentialArray, STRING_OR_NULL, NULL);
+  rule(potentialArray, jsStringOrNull, NULL);
   rule(potentialArray, NULL, NULL);
-  rule(potentialArray, FIXED_ARRAY, FIXED_ARRAY);
+  rule(potentialArray, jsFixedArray, jsFixedArray);
 
   rule(potentialString, potentialString, potentialString);
   rule(potentialString, BOOLEAN_OR_NULL, NULL);
   rule(potentialString, NUMBER_OR_NULL, NULL);
   rule(potentialString, INTEGER_OR_NULL, NULL);
   rule(potentialString, DOUBLE_OR_NULL, NULL);
-  rule(potentialString, STRING_OR_NULL, STRING_OR_NULL);
+  rule(potentialString, jsStringOrNull, jsStringOrNull);
   rule(potentialString, NULL, NULL);
-  rule(potentialString, FIXED_ARRAY, CONFLICTING);
+  rule(potentialString, jsFixedArray, CONFLICTING);
 
   rule(BOOLEAN_OR_NULL, BOOLEAN_OR_NULL, BOOLEAN_OR_NULL);
   rule(BOOLEAN_OR_NULL, NUMBER_OR_NULL, NULL);
   rule(BOOLEAN_OR_NULL, INTEGER_OR_NULL, NULL);
   rule(BOOLEAN_OR_NULL, DOUBLE_OR_NULL, NULL);
-  rule(BOOLEAN_OR_NULL, STRING_OR_NULL, NULL);
+  rule(BOOLEAN_OR_NULL, jsStringOrNull, NULL);
   rule(BOOLEAN_OR_NULL, NULL, NULL);
-  rule(BOOLEAN_OR_NULL, FIXED_ARRAY, CONFLICTING);
+  rule(BOOLEAN_OR_NULL, jsFixedArray, CONFLICTING);
 
   rule(NUMBER_OR_NULL, NUMBER_OR_NULL, NUMBER_OR_NULL);
   rule(NUMBER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
   rule(NUMBER_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(NUMBER_OR_NULL, STRING_OR_NULL, NULL);
+  rule(NUMBER_OR_NULL, jsStringOrNull, NULL);
   rule(NUMBER_OR_NULL, NULL, NULL);
-  rule(NUMBER_OR_NULL, FIXED_ARRAY, CONFLICTING);
+  rule(NUMBER_OR_NULL, jsFixedArray, CONFLICTING);
 
   rule(INTEGER_OR_NULL, INTEGER_OR_NULL, INTEGER_OR_NULL);
   rule(INTEGER_OR_NULL, DOUBLE_OR_NULL, NULL);
-  rule(INTEGER_OR_NULL, STRING_OR_NULL, NULL);
+  rule(INTEGER_OR_NULL, jsStringOrNull, NULL);
   rule(INTEGER_OR_NULL, NULL, NULL);
-  rule(INTEGER_OR_NULL, FIXED_ARRAY, CONFLICTING);
+  rule(INTEGER_OR_NULL, jsFixedArray, CONFLICTING);
 
   rule(DOUBLE_OR_NULL, DOUBLE_OR_NULL, DOUBLE_OR_NULL);
-  rule(DOUBLE_OR_NULL, STRING_OR_NULL, NULL);
+  rule(DOUBLE_OR_NULL, jsStringOrNull, NULL);
   rule(DOUBLE_OR_NULL, NULL, NULL);
-  rule(DOUBLE_OR_NULL, FIXED_ARRAY, CONFLICTING);
+  rule(DOUBLE_OR_NULL, jsFixedArray, CONFLICTING);
 
-  rule(STRING_OR_NULL, STRING_OR_NULL, STRING_OR_NULL);
-  rule(STRING_OR_NULL, NULL, NULL);
-  rule(STRING_OR_NULL, FIXED_ARRAY, CONFLICTING);
+  rule(jsStringOrNull, jsStringOrNull, jsStringOrNull);
+  rule(jsStringOrNull, NULL, NULL);
+  rule(jsStringOrNull, jsFixedArray, CONFLICTING);
 
   rule(NULL, NULL, NULL);
-  rule(NULL, FIXED_ARRAY, CONFLICTING);
+  rule(NULL, jsFixedArray, CONFLICTING);
 
-  rule(FIXED_ARRAY, FIXED_ARRAY, FIXED_ARRAY);
+  rule(jsFixedArray, jsFixedArray, jsFixedArray);
 
   ruleSet.validateCoverage();
 }
@@ -669,7 +670,7 @@
   HType nonNullPotentialString = new HType.nonNullSubtype(
       patternClass.computeType(compiler), compiler);
   Expect.equals(
-      potentialString, STRING_OR_NULL.union(nonNullPotentialString, compiler));
+      potentialString, jsStringOrNull.union(nonNullPotentialString, compiler));
 }
 
 void main() {
@@ -700,16 +701,30 @@
       compiler.backend.jsInterceptorClass.computeType(compiler), compiler);
   jsArrayOrNull = new HType.subclass(
       compiler.backend.jsArrayClass.computeType(compiler), compiler);
+  jsReadableArray = new HType.nonNullSubclass(
+      compiler.backend.jsArrayClass.computeType(compiler), compiler);
   jsMutableArrayOrNull = new HType.subclass(
       compiler.backend.jsMutableArrayClass.computeType(compiler), compiler);
+  jsMutableArray = new HType.nonNullSubclass(
+      compiler.backend.jsMutableArrayClass.computeType(compiler), compiler);
   jsFixedArrayOrNull = new HType.exact(
       compiler.backend.jsFixedArrayClass.computeType(compiler), compiler);
+  jsFixedArray = new HType.nonNullExact(
+      compiler.backend.jsFixedArrayClass.computeType(compiler), compiler);
   jsExtendableArrayOrNull = new HType.exact(
       compiler.backend.jsExtendableArrayClass.computeType(compiler), compiler);
+  jsExtendableArray = new HType.nonNullExact(
+      compiler.backend.jsExtendableArrayClass.computeType(compiler), compiler);
   jsIndexableOrNull = new HType.subtype(
       compiler.backend.jsIndexableClass.computeType(compiler), compiler);
+  jsIndexable = new HType.nonNullSubtype(
+      compiler.backend.jsIndexableClass.computeType(compiler), compiler);
   jsInterceptorOrNull = new HType.subclass(
       compiler.backend.jsInterceptorClass.computeType(compiler), compiler);
+  jsStringOrNull = new HType.exact(
+      compiler.backend.jsStringClass.computeType(compiler), compiler);
+  jsString = new HType.nonNullExact(
+      compiler.backend.jsStringClass.computeType(compiler), compiler);
 
   testUnion(compiler);
   testIntersection(compiler);
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index c155d64..6e91831 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -104,8 +104,8 @@
 list_insert_test: fail
 list_removeat_test: fail
 
-[ $arch == simarm ]
-*: Skip
+[ $arch == simarm && $mode == debug ]
+collection_to_string_test: Crash # Issue: 11207
 
 [ $arch == mips ]
 *: Skip
diff --git a/tests/corelib/hidden_library2_test.dart b/tests/corelib/hidden_library2_test.dart
index d47aca7..277ed54 100644
--- a/tests/corelib/hidden_library2_test.dart
+++ b/tests/corelib/hidden_library2_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 // Test that the internal hidden library doesn't make problems with taking
 // stack-traces.
 
@@ -8,7 +9,7 @@
   print(['x'].where((_) {
     // We actually don't really care for the successful case. We just want to
     // make sure that the test doesn't crash when it is negative.
-    throw 'fisk';  /// 1: runtime error
+    throw 'fisk';  /// 01: runtime error
     return true;
-  }));
+  }).toList());
 }
diff --git a/tests/corelib/string_pattern_test.dart b/tests/corelib/string_pattern_test.dart
index 46b4e75..25e12e7 100644
--- a/tests/corelib/string_pattern_test.dart
+++ b/tests/corelib/string_pattern_test.dart
@@ -14,6 +14,7 @@
   testEmptyPattern();
   testEmptyString();
   testEmptyPatternAndString();
+  testMatchAsPrefix();
 }
 
 testNoMatch() {
@@ -77,3 +78,22 @@
   Iterable<Match> matches = pattern.allMatches(str);
   Expect.isTrue(matches.iterator.moveNext());
 }
+
+testMatchAsPrefix() {
+  String pattern = "an";
+  String str = "banana";
+  Expect.isNull(pattern.matchAsPrefix(str));
+  Expect.isNull(pattern.matchAsPrefix(str, 0));
+  var m = pattern.matchAsPrefix(str, 1);
+  Expect.equals("an", m[0]);
+  Expect.equals(1, m.start);
+  Expect.isNull(pattern.matchAsPrefix(str, 2));
+  m = pattern.matchAsPrefix(str, 3);
+  Expect.equals("an", m[0]);
+  Expect.equals(3, m.start);
+  Expect.isNull(pattern.matchAsPrefix(str, 4));
+  Expect.isNull(pattern.matchAsPrefix(str, 5));
+  Expect.isNull(pattern.matchAsPrefix(str, 6));
+  Expect.throws(() => pattern.matchAsPrefix(str, -1));
+  Expect.throws(() => pattern.matchAsPrefix(str, 7));
+}
diff --git a/tests/corelib/string_test.dart b/tests/corelib/string_test.dart
index dbcd630..4519733 100644
--- a/tests/corelib/string_test.dart
+++ b/tests/corelib/string_test.dart
@@ -40,7 +40,7 @@
     } on RangeError catch (e) {
       exception_caught = true;
     }
-    Expect.equals(true, exception_caught);
+    Expect.isTrue(exception_caught);
   }
 
   static testIllegalArgument() {
@@ -48,19 +48,19 @@
     bool exception_caught = false;
     try {
       var c = a[2.2];  // Throw exception.
-      Expect.equals(true, false);
+      Expect.fail("Accepting double as index");
     } on ArgumentError catch (e) {
       exception_caught = true;
     } on TypeError catch (e) {  // Thrown in checked mode only.
       exception_caught = true;
     }
-    Expect.equals(true, exception_caught);
+    Expect.isTrue(exception_caught);
   }
 
   static testIndex() {
     String str = "string";
     for (int i = 0; i < str.length; i++) {
-      Expect.equals(true, str[i] is String);
+      Expect.isTrue(str[i] is String);
       testStringLength(1, str[i]);
     }
   }
@@ -68,7 +68,7 @@
   static testCodeUnitAt() {
     String str = "string";
     for (int i = 0; i < str.length; i++) {
-      Expect.equals(true, str.codeUnitAt(i) is int);
+      Expect.isTrue(str.codeUnitAt(i) is int);
     }
   }
 
@@ -86,46 +86,60 @@
     Expect.equals("str", "s" + "t" + "r");
     Expect.equals("s" + "t" + "r", "str");
 
-    Expect.equals(false, "str" == "s");
-    Expect.equals(false, "str" == "r");
-    Expect.equals(false, "str" == "st");
-    Expect.equals(false, "str" == "tr");
+    Expect.isFalse("str" == "s");
+    Expect.isFalse("str" == "r");
+    Expect.isFalse("str" == "st");
+    Expect.isFalse("str" == "tr");
 
-    Expect.equals(false, "s" == "str");
-    Expect.equals(false, "r" == "str");
-    Expect.equals(false, "st" == "str");
-    Expect.equals(false, "tr" == "str");
+    Expect.isFalse("s" == "str");
+    Expect.isFalse("r" == "str");
+    Expect.isFalse("st" == "str");
+    Expect.isFalse("tr" == "str");
 
-    Expect.equals(false, "" == "s");
+    Expect.isFalse("" == "s");
     Expect.equals("", "");
   }
 
   static testEndsWith() {
-    Expect.equals(true, "str".endsWith("r"));
-    Expect.equals(true, "str".endsWith("tr"));
-    Expect.equals(true, "str".endsWith("str"));
+    Expect.isTrue("str".endsWith("r"));
+    Expect.isTrue("str".endsWith("tr"));
+    Expect.isTrue("str".endsWith("str"));
 
-    Expect.equals(false, "str".endsWith("stri"));
-    Expect.equals(false, "str".endsWith("t"));
-    Expect.equals(false, "str".endsWith("st"));
-    Expect.equals(false, "str".endsWith("s"));
+    Expect.isFalse("str".endsWith("stri"));
+    Expect.isFalse("str".endsWith("t"));
+    Expect.isFalse("str".endsWith("st"));
+    Expect.isFalse("str".endsWith("s"));
 
-    Expect.equals(true, "".endsWith(""));
-    Expect.equals(false, "".endsWith("s"));
+    Expect.isTrue("".endsWith(""));
+    Expect.isFalse("".endsWith("s"));
   }
 
   static testStartsWith() {
-    Expect.equals(true, "str".startsWith("s"));
-    Expect.equals(true, "str".startsWith("st"));
-    Expect.equals(true, "str".startsWith("str"));
+    Expect.isTrue("str".startsWith("s"));
+    Expect.isTrue("str".startsWith("st"));
+    Expect.isTrue("str".startsWith("str"));
 
-    Expect.equals(false, "str".startsWith("stri"));
-    Expect.equals(false, "str".startsWith("r"));
-    Expect.equals(false, "str".startsWith("tr"));
-    Expect.equals(false, "str".startsWith("t"));
+    Expect.isFalse("str".startsWith("stri"));
+    Expect.isFalse("str".startsWith("r"));
+    Expect.isFalse("str".startsWith("tr"));
+    Expect.isFalse("str".startsWith("t"));
 
-    Expect.equals(true, "".startsWith(""));
-    Expect.equals(false, "".startsWith("s"));
+    Expect.isTrue("".startsWith(""));
+    Expect.isFalse("".startsWith("s"));
+
+    var regexp = new RegExp("s(?:tr?)?");
+    Expect.isTrue("s".startsWith(regexp));
+    Expect.isTrue("st".startsWith(regexp));
+    Expect.isTrue("str".startsWith(regexp));
+    Expect.isTrue("sX".startsWith(regexp));
+    Expect.isTrue("stX".startsWith(regexp));
+    Expect.isTrue("strX".startsWith(regexp));
+
+    Expect.isFalse("".startsWith(regexp));
+    Expect.isFalse("astr".startsWith(regexp));
+
+    Expect.isTrue("".startsWith(new RegExp("")));
+    Expect.isTrue("".startsWith(new RegExp("a?")));
   }
 
   static testIndexOf() {
@@ -162,13 +176,29 @@
 
     String str = "hello";
     for (int i = 0; i < 10; i++) {
-      int result = str.indexOf("", i);
       if (i > str.length) {
-        Expect.equals(str.length, result);
+        Expect.throws(() => str.indexOf("", i));
       } else {
+        int result = str.indexOf("", i);
         Expect.equals(i, result);
       }
     }
+
+    var re = new RegExp("an?");
+    Expect.equals(1, "banana".indexOf(re));
+    Expect.equals(1, "banana".indexOf(re, 0));
+    Expect.equals(1, "banana".indexOf(re, 1));
+    Expect.equals(3, "banana".indexOf(re, 2));
+    Expect.equals(3, "banana".indexOf(re, 3));
+    Expect.equals(5, "banana".indexOf(re, 4));
+    Expect.equals(5, "banana".indexOf(re, 5));
+    Expect.equals(-1, "banana".indexOf(re, 6));
+    Expect.throws(() => "banana".indexOf(re, -1));
+    Expect.throws(() => "banana".indexOf(re, 7));
+    re = new RegExp("x?");
+    for (int i = 0; i <= str.length; i++) {
+      Expect.equals(i, str.indexOf(re, i));
+    }
   }
 
   static testLastIndexOf() {
@@ -190,8 +220,9 @@
     Expect.equals(3, "strstr".lastIndexOf("st", 5));
     Expect.equals(3, "strstr".lastIndexOf("s", 5));
     Expect.equals(5, "strstr".lastIndexOf("r", 5));
-    Expect.equals(-1, "str".lastIndexOf("string", 5));
-
+    Expect.throws(() {
+        "str".lastIndexOf("string", 5);
+    });
     Expect.equals(4, "strstr".lastIndexOf("t", 5));
     Expect.equals(4, "strstr".lastIndexOf("tr", 5));
     Expect.equals(3, "strstr".lastIndexOf("str", 5));
@@ -203,33 +234,49 @@
     Expect.equals(2, "strstr".lastIndexOf("r", 4));
     Expect.equals(2, "strstr".lastIndexOf("r", 3));
     Expect.equals(5, "strstr".lastIndexOf("r"));
-    Expect.equals(5, "strstr".lastIndexOf("r"), null);
+    Expect.equals(5, "strstr".lastIndexOf("r", null));
 
     String str = "hello";
     for (int i = 0; i < 10; i++) {
-      int result = str.lastIndexOf("", i);
       if (i > str.length) {
-        Expect.equals(str.length, result);
+        Expect.throws(() => str.indexOf("", i));
       } else {
+        int result = str.lastIndexOf("", i);
         Expect.equals(i, result);
       }
     }
+
+    var re = new RegExp("an?");
+    Expect.equals(5, "banana".lastIndexOf(re));
+    Expect.equals(5, "banana".lastIndexOf(re, 6));
+    Expect.equals(5, "banana".lastIndexOf(re, 5));
+    Expect.equals(3, "banana".lastIndexOf(re, 4));
+    Expect.equals(3, "banana".lastIndexOf(re, 3));
+    Expect.equals(1, "banana".lastIndexOf(re, 2));
+    Expect.equals(1, "banana".lastIndexOf(re, 1));
+    Expect.equals(-1, "banana".lastIndexOf(re, 0));
+    Expect.throws(() => "banana".lastIndexOf(re, -1));
+    Expect.throws(() => "banana".lastIndexOf(re, 7));
+    re = new RegExp("x?");
+    for (int i = 0; i <= str.length; i++) {
+      Expect.equals(i, str.indexOf(re, i));
+    }
   }
 
   static testContains() {
-    Expect.equals(true, "str".contains("s", 0));
-    Expect.equals(true, "str".contains("st", 0));
-    Expect.equals(true, "str".contains("str", 0));
-    Expect.equals(true, "str".contains("t", 0));
-    Expect.equals(true, "str".contains("r", 0));
-    Expect.equals(true, "str".contains("tr", 0));
+    Expect.isTrue("str".contains("s", 0));
+    Expect.isTrue("str".contains("st", 0));
+    Expect.isTrue("str".contains("str", 0));
+    Expect.isTrue("str".contains("t", 0));
+    Expect.isTrue("str".contains("r", 0));
+    Expect.isTrue("str".contains("tr", 0));
 
-    Expect.equals(false, "str".contains("sr", 0));
-    Expect.equals(false, "str".contains("string", 0));
+    Expect.isFalse("str".contains("sr", 0));
+    Expect.isFalse("str".contains("string", 0));
 
-    Expect.equals(true, "str".contains("", 0));
-    Expect.equals(true, "".contains("", 0));
-    Expect.equals(false, "".contains("s", 0));
+    Expect.isTrue("str".contains("", 0));
+    Expect.isTrue("".contains("", 0));
+    Expect.isFalse("".contains("s", 0));
   }
 
   static testReplaceAll() {
diff --git a/tests/corelib/uri_query_test.dart b/tests/corelib/uri_query_test.dart
index 03c9aba..bb21f9b 100644
--- a/tests/corelib/uri_query_test.dart
+++ b/tests/corelib/uri_query_test.dart
@@ -29,6 +29,9 @@
         Expect.equals("?$normalizedQuery", uri.toString());
       }
       if (parameters.containsValue(null)) {
+        var map = new Map.from(parameters);
+        map.forEach((k, v) { if (v == null) map[k] = ""; });
+        Expect.mapEquals(map, uri.queryParameters);
       } else {
         Expect.mapEquals(parameters, uri.queryParameters);
       }
@@ -42,6 +45,13 @@
     check(uri3);
     Expect.equals(uri1, uri3);
     Expect.equals(uri2, uri3);
+    if (parameters.containsValue(null)) {
+      var map = new Map.from(parameters);
+      map.forEach((k, v) { if (v == null) map[k] = ""; });
+      Expect.mapEquals(map, Uri.splitQueryString(query));
+    } else {
+      Expect.mapEquals(parameters, Uri.splitQueryString(query));
+    }
   }
 
   test("", {});
diff --git a/tests/html/indexeddb_2_test.dart b/tests/html/indexeddb_2_test.dart
index 9a9feac3e..03a0fd4 100644
--- a/tests/html/indexeddb_2_test.dart
+++ b/tests/html/indexeddb_2_test.dart
@@ -46,6 +46,14 @@
     });
 }
 
+List<String> get nonNativeListData {
+  var list = new List<String>();
+  list.add("data");
+  list.add("clone");
+  list.add("error");
+  list.add("test");
+  return list;
+}
 
 main() {
   useHtmlConfiguration();
@@ -93,5 +101,6 @@
     go('array_deferred_copy', [1,2,3, obj3, obj3, 6]);
     go('array_deferred_copy_2', [1,2,3, [4, 5, obj3], [obj3, 6]]);
     go('cyclic_list', cyclic_list);
+    go('non-native lists', nonNativeListData);
   }
 }
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index e001f6d..527f220 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -138,20 +138,33 @@
 [ $compiler == dart2js && ( $runtime == ff || $runtime == safari ) ]
 isolate_stress_test: Pass, Timeout # http://dartbug.com/10697
 
-[ $arch == simarm ]
-*: Skip
+[ $arch == simarm && $mode == debug ]
+message_test: Crash # Issue: 11207
+unresolved_ports_test: Pass, Crash # Issue: 11207
 
-[ $arch == arm ]
-count_stream_test: Crash # Issue: 11207
+[ ($arch == arm || $arch == simarm) && $checked ]
+count_test: Pass, Crash # Issue: 11207
+isolate_complex_messages_test: Pass, Crash # Issue: 11207
+mandel_isolate_test: Pass, Crash # Issue 11207
+cross_isolate_message_test: Pass, Crash # Issue: 11207
+nested_spawn_test: Pass, Crash # Issue: 11207
+
+[ $arch == arm || $arch == simarm ]
+request_reply_test: Pass, Crash # Issue: 11207
+nested_spawn_test: Pass, Crash # Issue: 11207
+nested_spawn2_test: Pass, Crash # Issue: 11207
+count_stream_test: Pass, Crash # Issue: 11207
 cross_isolate_message_stream_test: Crash # Issue: 11207
 mandel_isolate_stream_test: Crash # Issue: 11207
-message2_test: Crash # Issue: 11207
+message2_test: Pass, Crash # Issue: 11207
 message_stream2_test: Crash # Issue: 11207
-nested_spawn_stream2_test: Crash # Issue: 11207
-nested_spawn_stream_test: Crash # Issue: 11207
-spawn_function_negative_test: Crash # Issue: 11207
-spawn_uri_vm_negative_test: Crash # Issue: 11207
+nested_spawn_stream_test: Crash, Pass # Issue: 11207
+nested_spawn_stream2_test: Pass, Crash # Issue: 11207
+spawn_function_negative_test: Pass, Crash # Issue: 11207
+spawn_uri_vm_negative_test: Crash, Pass # Issue: 11207 (Pass on Mac)
 stream_mangling_test: Crash # Issue: 11207
+message_test: Pass, Crash # Issue: 11207
+mint_maker_test: Pass, Crash # Issue: 11207
 
 [ $arch == mips ]
 *: Skip
diff --git a/tests/language/aborting_switch_case_test.dart b/tests/language/aborting_switch_case_test.dart
new file mode 100644
index 0000000..69037ad
--- /dev/null
+++ b/tests/language/aborting_switch_case_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js that used to be confused when inlining
+// method that always aborts in a switch case.
+
+import "package:expect/expect.dart";
+
+foo() { throw 42; }
+
+main() {
+  var exception;
+  try {
+    switch (42) {
+      case 42:
+        foo();
+        foo();
+        break;
+    }
+  } catch (e) {
+    exception = e;
+  }
+  Expect.equals(42, exception);
+}
diff --git a/tests/language/arithmetic_test.dart b/tests/language/arithmetic_test.dart
index e28ab716..bde573d 100644
--- a/tests/language/arithmetic_test.dart
+++ b/tests/language/arithmetic_test.dart
@@ -435,11 +435,24 @@
     Expect.throws(() => mySqrt("abc"));
   }
 
+  static self_equality(x) {
+    return x == x;
+  }
+
+  static testDoubleEquality() {
+    Expect.isFalse(self_equality(double.NAN));
+    for (int i = 0; i < 2000; i++) {
+      self_equality(3.0);
+    }
+    Expect.isFalse(self_equality(double.NAN));
+  }
+
   static testMain() {
     for (int i = 0; i < 1500; i++) {
       runOne();
       testSmiDivDeopt();
       testSqrtDeopt();
+      testDoubleEquality();
     }
   }
 }
diff --git a/tests/language/canonical_const3_test.dart b/tests/language/canonical_const3_test.dart
new file mode 100644
index 0000000..7dad367
--- /dev/null
+++ b/tests/language/canonical_const3_test.dart
@@ -0,0 +1,31 @@
+// 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.
+//
+// Check proper canonicalization (fields must be canonicalized as well).
+
+import "package:expect/expect.dart";
+
+
+main() {
+  Expect.isFalse(identical(new Duration(days: 1), new Duration(days: 1)));
+  Expect.isTrue(identical(const Duration(days: 2), const Duration(days: 2)));
+  Expect.isTrue(identical(const B(3.0), const B(3.0)));
+  Expect.isTrue(identical(const F(main), const F(main)));
+}
+
+
+class A {
+  final a;
+  const A(v) : a = v + 3.4;
+}
+
+class B extends A {
+  final b;
+  const B(v) : super(v), b = v + 1.0;
+}
+
+class F {
+  final f;
+  const F(v) : f = v;
+}
diff --git a/tests/language/generic_test.dart b/tests/language/generic_test.dart
index 55c6d41..7e7c56c 100644
--- a/tests/language/generic_test.dart
+++ b/tests/language/generic_test.dart
@@ -63,7 +63,7 @@
       String subs = error.url.substring(pos + 1, error.url.length);
       Expect.equals("generic_test.dart", subs);
       Expect.equals(31, error.line);  // new B<T>(t); AX does not extend A.
-      Expect.equals(17, error.column);
+      Expect.equals(21, error.column);
     }
     return result;
   }
diff --git a/tests/language/language.status b/tests/language/language.status
index 305a45a..7554f25 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -347,7 +347,6 @@
 # Mixins fail on the VM.
 mixin_mixin_test: Fail                      # VM issue
 mixin_issue10216_2_test: Fail               # VM issue
-mixin_illegal_constructor_test/none: Fail   # VM issue
 
 
 # Malformed types not handled as unresolved:
@@ -528,17 +527,16 @@
 super_call4_test: Fail, OK # hardcoded names.
 
 [ $arch == simarm || $arch == arm ]
-arithmetic_test: Fail, Crash
 bit_operations_test: Crash, Fail
-char_escape_test: Pass, Crash
 deopt_smi_op_test: Fail
-div_with_power_of_two_test: Fail
 gc_test: Crash
 invocation_mirror_test: Fail
 load_to_load_forwarding_vm_test: Fail
 named_parameters_with_conversions_test: Pass, Crash
-positive_bit_operations_test: Pass, Fail, Crash
-left_shift_test: Pass, Fail
+arithmetic_test: Pass, Crash, Fail # Fails on Mac
+left_shift_test: Pass, Fail # Fails on Mac
+positive_bit_operations_test: Pass, Fail, Crash # Fails and crashes on Mac
+
 
 # large_implicit_getter_test Passes on ReleaseARM, Crashes in SIMARM and
 # DebugARM. Should crash on ReleaseARM, but there is no exception on an
@@ -548,6 +546,9 @@
 stack_overflow_test: Crash, Pass
 stack_overflow_stacktrace_test: Crash, Pass
 
+[ ($arch == simarm || $arch == arm) && $mode == debug ]
+char_escape_test: Pass, Crash
+
 [ $arch == mips ]
 *: Skip
 
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index ebaff6e..456c164 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -104,7 +104,6 @@
 list_literal_syntax_test/03: fail
 map_literal1_negative_test: fail
 map_literal3_test: fail
-method_override2_test/03: fail
 mixin_illegal_constructor_test/13: fail
 mixin_illegal_constructor_test/14: fail
 mixin_illegal_constructor_test/15: fail
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index 31cf098..be8fb29 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -104,7 +104,6 @@
 list_literal_syntax_test/03: fail
 map_literal1_negative_test: fail
 map_literal3_test: fail
-method_override2_test/03: fail
 mixin_illegal_constructor_test/13: fail
 mixin_illegal_constructor_test/14: fail
 mixin_illegal_constructor_test/15: fail
diff --git a/tests/language/licm3_test.dart b/tests/language/licm3_test.dart
new file mode 100644
index 0000000..99e93b1
--- /dev/null
+++ b/tests/language/licm3_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that a loop invariant code motion optimization correctly hoists
+// instructions that may cause deoptimization.
+
+import "package:expect/expect.dart";
+
+foo(o) {
+  var r = 0;
+  for (var i = 0; i < 3; i++) {
+    r += o.z;
+  }
+  return r;
+}
+
+
+class A {
+  var z = 3;
+}
+
+main() {
+  var a = new A();
+  for(var i = 0; i < 10000; i++) foo(a);
+  Expect.equals(9, foo(a));
+  Expect.throws(() => foo(42));
+  for(var i = 0; i < 10000; i++) foo(a);
+  Expect.throws(() => foo(42));
+}
+
diff --git a/tests/language/reg_exp_test.dart b/tests/language/reg_exp_test.dart
index 26826a9..c51663c 100644
--- a/tests/language/reg_exp_test.dart
+++ b/tests/language/reg_exp_test.dart
@@ -25,4 +25,40 @@
   exp = new RegExp("^", multiLine: true);  // Any zero-length match will work.
   str = "foo\nbar\nbaz";
   Expect.equals(" foo\n bar\n baz", str.replaceAll(exp, " "));
+
+  exp = new RegExp(r"(\w+)");
+  Expect.isNull(exp.matchAsPrefix(" xyz ab"));
+  Expect.isNull(exp.matchAsPrefix(" xyz ab", 0));
+
+  var m = exp.matchAsPrefix(" xyz ab", 1);
+  Expect.equals("xyz", m[0]);
+  Expect.equals("xyz", m[1]);
+  Expect.equals(1, m.groupCount);
+
+  m = exp.matchAsPrefix(" xyz ab", 2);
+  Expect.equals("yz", m[0]);
+  Expect.equals("yz", m[1]);
+  Expect.equals(1, m.groupCount);
+
+  m = exp.matchAsPrefix(" xyz ab", 3);
+  Expect.equals("z", m[0]);
+  Expect.equals("z", m[1]);
+  Expect.equals(1, m.groupCount);
+
+  Expect.isNull(exp.matchAsPrefix(" xyz ab", 4));
+
+  m = exp.matchAsPrefix(" xyz ab", 5);
+  Expect.equals("ab", m[0]);
+  Expect.equals("ab", m[1]);
+  Expect.equals(1, m.groupCount);
+
+  m = exp.matchAsPrefix(" xyz ab", 6);
+  Expect.equals("b", m[0]);
+  Expect.equals("b", m[1]);
+  Expect.equals(1, m.groupCount);
+
+  Expect.isNull(exp.matchAsPrefix(" xyz ab", 7));
+
+  Expect.throws(() => exp.matchAsPrefix(" xyz ab", -1));
+  Expect.throws(() => exp.matchAsPrefix(" xyz ab", 8));
 }
diff --git a/tests/lib/analyzer/analyze_tests.status b/tests/lib/analyzer/analyze_tests.status
index 3406d43..fb163a8 100644
--- a/tests/lib/analyzer/analyze_tests.status
+++ b/tests/lib/analyzer/analyze_tests.status
@@ -28,9 +28,8 @@
 standalone/typed_data_view_test: Fail
 
 # Tests using fake "part" and/or "part of" directive.
-standalone/crypto/base64_test: Fail
 standalone/typed_data_test: Fail
-standalone/io/http_date_test: Fail
+standalone/io/http_cookie_date_test: Fail
 standalone/io/http_headers_test: Fail
 standalone/io/http_parser_test: Fail
 standalone/io/web_socket_protocol_processor_test: Fail
diff --git a/tests/lib/collection/linked_list_test.dart b/tests/lib/collection/linked_list_test.dart
new file mode 100644
index 0000000..3ed06b7
--- /dev/null
+++ b/tests/lib/collection/linked_list_test.dart
@@ -0,0 +1,175 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+import "package:expect/expect.dart";
+
+class MyEntry extends LinkedListEntry<MyEntry> {
+  final int value;
+
+  MyEntry(int this.value);
+
+  String toString() => value.toString();
+}
+
+
+testInsert() {
+  // Insert last.
+  var list = new LinkedList<MyEntry>();
+  for (int i = 0; i < 10; i++) {
+    list.add(new MyEntry(i));
+  }
+
+  Expect.equals(10, list.length);
+
+  int i = 0;
+  for (var entry in list) {
+    Expect.equals(i, entry.value);
+    i++;
+  }
+
+  Expect.equals(10, i);
+
+  list.clear();
+
+  // Insert first.
+  for (int i = 0; i < 10; i++) {
+    list.addFirst(new MyEntry(i));
+  }
+
+  Expect.equals(10, list.length);
+
+  i = 10;
+  for (var entry in list) {
+    Expect.equals(--i, entry.value);
+  }
+  Expect.equals(0, i);
+
+  list.clear();
+
+  // Insert after.
+  list.addFirst(new MyEntry(0));
+  for (int i = 1; i < 10; i++) {
+    list.last.insertAfter(new MyEntry(i));
+  }
+
+  Expect.equals(10, list.length);
+
+  i = 0;
+  for (var entry in list) {
+    Expect.equals(i, entry.value);
+    i++;
+  }
+
+  Expect.equals(10, i);
+
+  list.clear();
+
+  // Insert before.
+  list.addFirst(new MyEntry(0));
+  for (int i = 1; i < 10; i++) {
+    list.first.insertBefore(new MyEntry(i));
+  }
+
+  Expect.equals(10, list.length);
+
+  i = 10;
+  for (var entry in list) {
+    Expect.equals(--i, entry.value);
+  }
+  Expect.equals(0, i);
+
+  list.clear();
+}
+
+
+testRemove() {
+  var list = new LinkedList<MyEntry>();
+  for (int i = 0; i < 10; i++) {
+    list.add(new MyEntry(i));
+  }
+
+  Expect.equals(10, list.length);
+
+  list.remove(list.skip(5).first);
+
+  Expect.equals(9, list.length);
+
+  int i = 0;
+  for (var entry in list) {
+    if (i == 5) i++;
+    Expect.equals(i, entry.value);
+    i++;
+  }
+
+  Expect.listEquals([0, 1, 2, 3, 4, 6, 7, 8, 9],
+                    list.map((e) => e.value).toList());
+
+  for (int i = 0; i < 9; i++) {
+    list.first.unlink();
+  }
+
+  Expect.throws(() => list.first);
+
+  Expect.equals(0, list.length);
+}
+
+
+testBadAdd() {
+  var list1 = new LinkedList<MyEntry>();
+  list1.addFirst(new MyEntry(0));
+
+  var list2 = new LinkedList<MyEntry>();
+  Expect.throws(() => list2.addFirst(list1.first));
+
+  Expect.throws(() => new MyEntry(0).unlink());
+}
+
+testConcurrentModificationError() {
+
+  test(function(LinkedList ll)) {
+    var ll = new LinkedList<MyEntry>();
+    for (int i = 0; i < 10; i++) {
+      ll.add(new MyEntry(i));
+    }
+    Expect.throws(() => function(ll), (e) => e is ConcurrentModificationError);
+  }
+  test((ll) { for(var x in ll) { ll.remove(x); } });
+  test((ll) { ll.forEach((x) { ll.remove(x); }); });
+  test((ll) { ll.any((x) { ll.remove(x); return false; }); });
+  test((ll) { ll.every((x) { ll.remove(x); return true; }); });
+  test((ll) { ll.fold(0, (x, y) { ll.remove(y); return x; }); });
+  test((ll) { ll.reduce((x, y) { ll.remove(y); return x; }); });
+  test((ll) { ll.where((x) { ll.remove(x); return true; }).forEach((_) {}); });
+  test((ll) { ll.map((x) { ll.remove(x); return x; }).forEach((_) {}); });
+  test((ll) { ll.expand((x) { ll.remove(x); return[x];}).forEach((_) {}); });
+  test((ll) { ll.takeWhile((x) {
+      ll.remove(x); return true;}).forEach((_) {}); });
+  test((ll) { ll.skipWhile((x) {
+      ll.remove(x); return true;}).forEach((_) {}); });
+  test((ll) {
+    bool first = true;
+    ll.firstWhere((x) {
+      ll.remove(x);
+      if (!first) return true;
+      return first = false;
+    });
+  });
+  test((ll) { ll.lastWhere((x) { ll.remove(x); return true;}); });
+  test((ll) {
+    bool first = true;
+    ll.singleWhere((x) {
+      ll.remove(x);
+      if (!first) return false;
+      return !(first = false);
+    });
+  });
+}
+
+main() {
+  testInsert();
+  testRemove();
+  testBadAdd();
+  testConcurrentModificationError();
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 093283e..cdf2a9d 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -21,13 +21,16 @@
 
 [ $compiler == dart2js && $minified ]
 mirrors/mirrors_resolve_fields_test: Fail # Issue 6490
+mirrors/reflectively_instantiate_uninstantiated_class_test: Fail # Issue 6490
 mirrors/disable_tree_shaking_test: Fail # Issue 6490
+mirrors/reflect_model_test: Fail # Issue 6490
 
 [ $csp ]
 mirrors/metadata_test: Fail # Issue 6490
 mirrors/reflect_runtime_type_test: Fail # Issue 6490
 mirrors/reflect_uninstantiated_class_test: Fail # Issue 6490
 mirrors/superclass_test: Fail # Issue 6490
+mirrors/reflect_model_test: Fail # Issue 6490
 
 [ $compiler == dart2js && $checked ]
 async/stream_event_transform_test: Fail # Issue 7733.
@@ -62,6 +65,7 @@
 mirrors/mirrors_test: Fail              # Issue 10957
 mirrors/library_uri_package_test: Fail  # Issue 10957
 async/run_async6_test: Fail             # Issue 10957 - may be related to issue 10910
+mirrors/reflect_model_test: Fail # http://dartbug.com/11219
 
 [ $compiler == dart2dart && $minified ]
 json/json_test: Fail                           # Issue 10961
@@ -99,6 +103,8 @@
 async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9001.
 mirrors/metadata_test: Fail # http://dartbug.com/10906
 mirrors/superclass_test: Fail # http://dartbug.com/11142
+mirrors/reflectively_instantiate_uninstantiated_class_test: Fail # http://dartbug.com/11187
+mirrors/reflect_model_test: Fail # http://dartbug.com/11219
 
 [ $compiler == none && $runtime == drt ]
 async/timer_isolate_test: Skip # See Issue 4997
@@ -111,24 +117,31 @@
 async/multiple_timer_test: Fail, Pass # See Issue 10982
 async/timer_test: Fail, Pass # See Issue 10982
 
-[ $arch == simarm ]
-*: Skip
 
-[ $arch == arm ]
-async/slow_consumer2_test: Crash # Issue: 11207
-async/slow_consumer3_test: Crash # Issue: 11207
-async/slow_consumer_test: Crash # Issue: 11207
-async/stream_controller_async_test: Crash # Issue: 11207
-async/stream_from_iterable_test: Crash # Issue: 11207
-async/stream_periodic3_test: Crash # Issue: 11207
-async/stream_periodic4_test: Crash # Issue: 11207
-async/stream_periodic5_test: Crash # Issue: 11207
-async/stream_state_nonzero_timer_test: Crash # Issue: 11207
-async/stream_state_test: Crash # Issue: 11207
-async/stream_subscription_as_future_test: Crash # Issue: 11207
-async/stream_transform_test: Crash # Issue: 11207
-math/pi_test: Fail # Issue: 11207
+[ $arch == arm || $arch == simarm ]
+async/future_test: Pass, Crash # Issue: 11207
+async/run_async6_test: Pass, Fail # Issue: 11207
+async/run_async_test: Pass, Crash # Issue: 11207
+async/slow_consumer2_test: Pass, Crash # Issue: 11207
+async/slow_consumer3_test: Pass, Crash # Issue: 11207
+async/slow_consumer_test: Pass, Crash # Issue: 11207
+async/stream_controller_async_test: Pass, Crash # Issue: 11207
+async/stream_controller_test: Timeout, Pass, Crash # Issue: 11207
+async/stream_from_iterable_test: Pass, Crash # Issue: 11207
+async/stream_periodic2_test: Pass, Crash # Issue: 11207
+async/stream_periodic3_test: Pass, Crash # Issue: 11207
+async/stream_periodic4_test: Pass, Crash # Issue: 11207
+async/stream_periodic5_test: Pass, Crash # Issue: 11207
+async/stream_single_to_multi_subscriber_test: Pass, Crash # Issue: 11207
+async/stream_state_nonzero_timer_test: Pass, Crash # Issue: 11207
+async/stream_state_test: Pass, Crash # Issue: 11207
+async/stream_subscription_as_future_test: Pass, Crash # Issue: 11207
+async/stream_transform_test: Pass, Crash # Issue: 11207
+async/timer_cancel1_test: Pass, Crash # Issue: 11207
+async/timer_cancel2_test: Pass, Crash # Issue: 11207
+math/pi_test: Crash, Fail # Issue: 11207
 math/random_test: Fail # Issue: 11207
+mirrors/reflect_model_test: Pass, Crash # Issue: 11207
 typed_data/float32x4_list_test: Crash # Issue: 11207
 typed_data/float32x4_test: Crash # Issue: 11207
 typed_data/float32x4_unbox_phi_test: Crash # Issue: 11207
diff --git a/tests/lib/mirrors/model.dart b/tests/lib/mirrors/model.dart
new file mode 100644
index 0000000..a06c757
--- /dev/null
+++ b/tests/lib/mirrors/model.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.model;
+
+var accessorA;
+
+var accessorB;
+
+var accessorC;
+
+var fieldC;
+
+class A {
+  var field;
+  instanceMethod(x) => 'A:instanceMethod($x)';
+  get accessor => 'A:get accessor';
+  set accessor(x) {
+    accessorA = x;
+  }
+  aMethod() => 'aMethod';
+}
+
+class B extends A {
+  get field => 'B:get field';
+  instanceMethod(x) => 'B:instanceMethod($x)';
+  get accessor => 'B:get accessor';
+  set accessor(x) {
+    accessorB = x;
+  }
+  bMethod() => 'bMethod';
+}
+
+class C extends B {
+  set field(x) {
+    fieldC = x;
+  }
+  instanceMethod(x) => 'C:instanceMethod($x)';
+  get accessor => 'C:get accessor';
+  set accessor(x) {
+    accessorC = x;
+  }
+  cMethod() => 'cMethod';
+}
diff --git a/tests/lib/mirrors/model_test.dart b/tests/lib/mirrors/model_test.dart
new file mode 100644
index 0000000..1e3c292
--- /dev/null
+++ b/tests/lib/mirrors/model_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.model_test;
+
+import 'package:expect/expect.dart';
+
+import 'model.dart';
+
+isNoSuchMethodError(e) => e is NoSuchMethodError;
+
+main() {
+  var a = new A();
+  var b = new B();
+  var c = new C();
+
+  Expect.isNull(a.field);
+  Expect.equals('B:get field', b.field);
+  Expect.equals('B:get field', c.field);
+
+  a.field = 42;
+  b.field = 87;
+  c.field = 89;
+  Expect.equals(42, a.field);
+  Expect.equals('B:get field', b.field);
+  Expect.equals('B:get field', c.field);
+  Expect.equals(89, fieldC);
+
+  Expect.equals('A:instanceMethod(7)', a.instanceMethod(7));
+  Expect.equals('B:instanceMethod(9)', b.instanceMethod(9));
+  Expect.equals('C:instanceMethod(13)', c.instanceMethod(13));
+
+  Expect.equals('A:get accessor', a.accessor);
+  Expect.equals('B:get accessor', b.accessor);
+  Expect.equals('C:get accessor', c.accessor);
+
+  a.accessor = 'foo';
+  b.accessor = 'bar';
+  c.accessor = 'baz';
+
+  Expect.equals('foo', accessorA);
+  Expect.equals('bar', accessorB);
+  Expect.equals('baz', accessorC);
+
+  Expect.equals('aMethod', a.aMethod());
+  Expect.equals('aMethod', b.aMethod());
+  Expect.equals('aMethod', c.aMethod());
+
+  Expect.throws(() { a.bMethod(); }, isNoSuchMethodError);
+  Expect.equals('bMethod', b.bMethod());
+  Expect.equals('bMethod', c.bMethod());
+
+  Expect.throws(() { a.cMethod(); }, isNoSuchMethodError);
+  Expect.throws(() { b.cMethod(); }, isNoSuchMethodError);
+  Expect.equals('cMethod', c.cMethod());
+}
diff --git a/tests/lib/mirrors/reflect_model_test.dart b/tests/lib/mirrors/reflect_model_test.dart
new file mode 100644
index 0000000..e96124a
--- /dev/null
+++ b/tests/lib/mirrors/reflect_model_test.dart
@@ -0,0 +1,169 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.reflect_model_test;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+import 'model.dart';
+
+isNoSuchMethodError(e) => e is NoSuchMethodError;
+
+name(DeclarationMirror mirror) {
+  return (mirror == null) ? '<null>' : stringify(mirror.simpleName);
+}
+
+stringifyMap(Map map) {
+  var buffer = new StringBuffer('{');
+  bool first = true;
+  for (String key in map.keys.map(MirrorSystem.getName).toList()..sort()) {
+    if (!first) buffer.write(', ');
+    first = false;
+    buffer.write(key);
+    buffer.write(': ');
+    buffer.write(stringify(map[new Symbol(key)]));
+  }
+  return (buffer..write('}')).toString();
+}
+
+stringifySymbol(Symbol symbol) => 's(${MirrorSystem.getName(symbol)})';
+
+writeDeclarationOn(DeclarationMirror mirror, StringBuffer buffer) {
+  buffer.write(stringify(mirror.simpleName));
+  if (mirror.owner != null) {
+    buffer.write(' in ');
+    buffer.write(name(mirror.owner));
+  }
+  if (mirror.isPrivate) buffer.write(', private');
+  if (mirror.isTopLevel) buffer.write(', top-level');
+}
+
+stringifyVariable(VariableMirror variable) {
+  var buffer = new StringBuffer('Variable(');
+  writeDeclarationOn(variable, buffer);
+  if (variable.isStatic) buffer.write(', static');
+  if (variable.isFinal) buffer.write(', final');
+  return (buffer..write(')')).toString();
+}
+
+stringifyMethod(MethodMirror method) {
+  var buffer = new StringBuffer('Method(');
+  writeDeclarationOn(method, buffer);
+  if (method.isStatic) buffer.write(', static');
+  if (method.isGetter) buffer.write(', getter');
+  if (method.isSetter) buffer.write(', setter');
+  return (buffer..write(')')).toString();
+}
+
+stringify(value) {
+  if (value is Map) return stringifyMap(value);
+  if (value is VariableMirror) return stringifyVariable(value);
+  if (value is MethodMirror) return stringifyMethod(value);
+  if (value is Symbol) return stringifySymbol(value);
+  if (value == null) return '<null>';
+  throw 'Unexpected value: $value';
+}
+
+expect(expected, actual) => Expect.stringEquals(expected, stringify(actual));
+
+main() {
+  var unnamed = new Symbol('');
+  var field = new Symbol('field');
+  var instanceMethod = new Symbol('instanceMethod');
+  var accessor = new Symbol('accessor');
+  var aMethod = new Symbol('aMethod');
+  var bMethod = new Symbol('bMethod');
+  var cMethod = new Symbol('cMethod');
+
+  var aClass = reflectClass(A);
+  var bClass = reflectClass(B);
+  var cClass = reflectClass(C);
+  var a = aClass.newInstance(unnamed, []);
+  var b = bClass.newInstance(unnamed, []);
+  var c = cClass.newInstance(unnamed, []);
+
+  expect('{field: Variable(s(field) in s(A))}', aClass.variables);
+  expect('{}', bClass.variables);
+  expect('{}', cClass.variables);
+
+  Expect.isNull(a.getField(field).reflectee);
+  Expect.equals('B:get field', b.getField(field).reflectee);
+  Expect.equals('B:get field', c.getField(field).reflectee);
+
+  Expect.equals(42, a.setField(field, 42).reflectee);
+  Expect.equals(87, b.setField(field, 87).reflectee);
+  Expect.equals(89, c.setField(field, 89).reflectee);
+
+  Expect.equals(42, a.getField(field).reflectee);
+  Expect.equals('B:get field', b.getField(field).reflectee);
+  Expect.equals('B:get field', c.getField(field).reflectee);
+  Expect.equals(89, fieldC);
+
+  expect('{accessor: Method(s(accessor) in s(A), getter)'
+         // TODO(ahe): Include instance field getters?
+         ', field: Method(s(field) in s(A), getter)'
+         '}',
+         aClass.getters);
+  expect('{accessor: Method(s(accessor) in s(B), getter)'
+         ', field: Method(s(field) in s(B), getter)}',
+         bClass.getters);
+  expect('{accessor: Method(s(accessor) in s(C), getter)}',
+         cClass.getters);
+
+  expect('{accessor=: Method(s(accessor=) in s(A), setter)'
+         // TODO(ahe): Include instance field setters?
+         ', field=: Method(s(field=) in s(A), setter)'
+         '}',
+         aClass.setters);
+  expect('{accessor=: Method(s(accessor=) in s(B), setter)}',
+         bClass.setters);
+  expect('{accessor=: Method(s(accessor=) in s(C), setter)'
+         ', field=: Method(s(field=) in s(C), setter)}',
+         cClass.setters);
+
+  Expect.equals('A:instanceMethod(7)', a.invoke(instanceMethod, [7]).reflectee);
+  Expect.equals('B:instanceMethod(9)', b.invoke(instanceMethod, [9]).reflectee);
+  Expect.equals(
+      'C:instanceMethod(13)', c.invoke(instanceMethod, [13]).reflectee);
+
+  expect(
+      '{aMethod: Method(s(aMethod) in s(A))'
+      ', instanceMethod: Method(s(instanceMethod) in s(A))}',
+      aClass.methods);
+
+  expect(
+      '{bMethod: Method(s(bMethod) in s(B))'
+      ', instanceMethod: Method(s(instanceMethod) in s(B))}',
+      bClass.methods);
+  expect(
+      '{cMethod: Method(s(cMethod) in s(C))'
+      ', instanceMethod: Method(s(instanceMethod) in s(C))}',
+      cClass.methods);
+
+  Expect.equals('A:get accessor', a.getField(accessor).reflectee);
+  Expect.equals('B:get accessor', b.getField(accessor).reflectee);
+  Expect.equals('C:get accessor', c.getField(accessor).reflectee);
+
+  Expect.equals('foo', a.setField(accessor, 'foo').reflectee);
+  Expect.equals('bar', b.setField(accessor, 'bar').reflectee);
+  Expect.equals('baz', c.setField(accessor, 'baz').reflectee);
+
+  Expect.equals('foo', accessorA);
+  Expect.equals('bar', accessorB);
+  Expect.equals('baz', accessorC);
+
+  Expect.equals('aMethod', a.invoke(aMethod, []).reflectee);
+  Expect.equals('aMethod', b.invoke(aMethod, []).reflectee);
+  Expect.equals('aMethod', c.invoke(aMethod, []).reflectee);
+
+  Expect.throws(() { a.invoke(bMethod, []); }, isNoSuchMethodError);
+  Expect.equals('bMethod', b.invoke(bMethod, []).reflectee);
+  Expect.equals('bMethod', c.invoke(bMethod, []).reflectee);
+
+  Expect.throws(() { a.invoke(cMethod, []); }, isNoSuchMethodError);
+  Expect.throws(() { b.invoke(cMethod, []); }, isNoSuchMethodError);
+  Expect.equals('cMethod', c.invoke(cMethod, []).reflectee);
+}
diff --git a/tests/lib/mirrors/reflectively_instantiate_uninstantiated_class_test.dart b/tests/lib/mirrors/reflectively_instantiate_uninstantiated_class_test.dart
new file mode 100644
index 0000000..4d18126
--- /dev/null
+++ b/tests/lib/mirrors/reflectively_instantiate_uninstantiated_class_test.dart
@@ -0,0 +1,28 @@
+// 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.
+
+// Ensure that otherwise uninstantiated classes can be instantiated
+// reflectively.
+
+import "dart:mirrors";
+
+class Foo {
+  int a;
+}
+
+main() {
+  // Do NOT instantiate Foo.
+  var m = reflectClass(Foo);
+  var instance = m.newInstance(const Symbol(''), []);
+  print(instance);
+  bool threw = false;
+  try {
+    m.newInstance(const Symbol('noSuchConstructor'), []);
+    throw 'Expected an exception';
+  } on NoSuchMethodError catch (e) {
+    print(e);
+    threw = true;
+  }
+  if (!threw) throw 'Expected a NoSuchMethodError';
+}
diff --git a/tests/standalone/io/http_cookie_date_test.dart b/tests/standalone/io/http_cookie_date_test.dart
new file mode 100644
index 0000000..b9c76ea
--- /dev/null
+++ b/tests/standalone/io/http_cookie_date_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:math";
+import "dart:collection";
+
+part "../../../sdk/lib/io/common.dart";
+part "../../../sdk/lib/io/io_sink.dart";
+part "../../../sdk/lib/io/http.dart";
+part "../../../sdk/lib/io/http_impl.dart";
+part "../../../sdk/lib/io/http_parser.dart";
+part "../../../sdk/lib/io/http_utils.dart";
+part "../../../sdk/lib/io/socket.dart";
+
+void testParseHttpCookieDate() {
+  Expect.throws(() => _HttpUtils.parseCookieDate(""));
+
+  test(int year,
+       int month,
+       int day,
+       int hours,
+       int minutes,
+       int seconds,
+       String formatted) {
+    DateTime date = new DateTime.utc(year, month, day, hours, minutes, seconds, 0);
+    Expect.equals(date, _HttpUtils.parseCookieDate(formatted));
+  }
+
+  test(2012, DateTime.JUNE, 19, 14, 15, 01, "tue, 19-jun-12 14:15:01 gmt");
+  test(2021, DateTime.JUNE, 09, 10, 18, 14, "Wed, 09-Jun-2021 10:18:14 GMT");
+  test(2021, DateTime.JANUARY, 13, 22, 23, 01, "Wed, 13-Jan-2021 22:23:01 GMT");
+  test(2013, DateTime.JANUARY, 15, 21, 47, 38, "Tue, 15-Jan-2013 21:47:38 GMT");
+  test(1970, DateTime.JANUARY, 01, 00, 00, 01, "Thu, 01-Jan-1970 00:00:01 GMT");
+}
+
+void main() {
+  testParseHttpCookieDate();
+}
diff --git a/tests/standalone/io/http_date_test.dart b/tests/standalone/io/http_date_test.dart
index f3205ab..960ff82 100644
--- a/tests/standalone/io/http_date_test.dart
+++ b/tests/standalone/io/http_date_test.dart
@@ -5,32 +5,25 @@
 import "package:expect/expect.dart";
 import "dart:async";
 import "dart:math";
-
-part '../../../sdk/lib/io/common.dart';
-part "../../../sdk/lib/io/io_sink.dart";
-part "../../../sdk/lib/io/http.dart";
-part "../../../sdk/lib/io/http_impl.dart";
-part "../../../sdk/lib/io/http_parser.dart";
-part "../../../sdk/lib/io/http_utils.dart";
-part "../../../sdk/lib/io/socket.dart";
+import "dart:io";
 
 void testParseHttpDate() {
   DateTime date;
   date = new DateTime.utc(1999, DateTime.JUNE, 11, 18, 46, 53, 0);
-  Expect.equals(date, _HttpUtils.parseDate("Fri, 11 Jun 1999 18:46:53 GMT"));
-  Expect.equals(date, _HttpUtils.parseDate("Friday, 11-Jun-1999 18:46:53 GMT"));
-  Expect.equals(date, _HttpUtils.parseDate("Fri Jun 11 18:46:53 1999"));
+  Expect.equals(date, HttpDate.parse("Fri, 11 Jun 1999 18:46:53 GMT"));
+  Expect.equals(date, HttpDate.parse("Friday, 11-Jun-1999 18:46:53 GMT"));
+  Expect.equals(date, HttpDate.parse("Fri Jun 11 18:46:53 1999"));
 
   date = new DateTime.utc(1970, DateTime.JANUARY, 1, 0, 0, 0, 0);
-  Expect.equals(date, _HttpUtils.parseDate("Thu, 1 Jan 1970 00:00:00 GMT"));
+  Expect.equals(date, HttpDate.parse("Thu, 1 Jan 1970 00:00:00 GMT"));
   Expect.equals(date,
-                _HttpUtils.parseDate("Thursday, 1-Jan-1970 00:00:00 GMT"));
-  Expect.equals(date, _HttpUtils.parseDate("Thu Jan  1 00:00:00 1970"));
+                HttpDate.parse("Thursday, 1-Jan-1970 00:00:00 GMT"));
+  Expect.equals(date, HttpDate.parse("Thu Jan  1 00:00:00 1970"));
 
   date = new DateTime.utc(2012, DateTime.MARCH, 5, 23, 59, 59, 0);
-  Expect.equals(date, _HttpUtils.parseDate("Mon, 5 Mar 2012 23:59:59 GMT"));
-  Expect.equals(date, _HttpUtils.parseDate("Monday, 5-Mar-2012 23:59:59 GMT"));
-  Expect.equals(date, _HttpUtils.parseDate("Mon Mar  5 23:59:59 2012"));
+  Expect.equals(date, HttpDate.parse("Mon, 5 Mar 2012 23:59:59 GMT"));
+  Expect.equals(date, HttpDate.parse("Monday, 5-Mar-2012 23:59:59 GMT"));
+  Expect.equals(date, HttpDate.parse("Mon Mar  5 23:59:59 2012"));
 }
 
 void testFormatParseHttpDate() {
@@ -44,9 +37,9 @@
     DateTime date;
     String formatted;
     date = new DateTime.utc(year, month, day, hours, minutes, seconds, 0);
-    formatted = _HttpUtils.formatDate(date);
+    formatted = HttpDate.format(date);
     Expect.equals(expectedFormatted, formatted);
-    Expect.equals(date, _HttpUtils.parseDate(formatted));
+    Expect.equals(date, HttpDate.parse(formatted));
   }
 
   test(1999, DateTime.JUNE, 11, 18, 46, 53, "Fri, 11 Jun 1999 18:46:53 GMT");
@@ -56,59 +49,37 @@
 
 void testParseHttpDateFailures() {
   Expect.throws(() {
-    _HttpUtils.parseDate("");
+    HttpDate.parse("");
   });
   String valid = "Mon, 5 Mar 2012 23:59:59 GMT";
   for (int i = 1; i < valid.length - 1; i++) {
     String tmp = valid.substring(0, i);
     Expect.throws(() {
-      _HttpUtils.parseDate(tmp);
+      HttpDate.parse(tmp);
     });
     Expect.throws(() {
-      _HttpUtils.parseDate(" $tmp");
+      HttpDate.parse(" $tmp");
     });
     Expect.throws(() {
-      _HttpUtils.parseDate(" $tmp ");
+      HttpDate.parse(" $tmp ");
     });
     Expect.throws(() {
-      _HttpUtils.parseDate("$tmp ");
+      HttpDate.parse("$tmp ");
     });
   }
   Expect.throws(() {
-    _HttpUtils.parseDate(" $valid");
+    HttpDate.parse(" $valid");
   });
   Expect.throws(() {
-    _HttpUtils.parseDate(" $valid ");
+    HttpDate.parse(" $valid ");
   });
   Expect.throws(() {
-    _HttpUtils.parseDate("$valid ");
+    HttpDate.parse("$valid ");
   });
 }
 
-void testParseHttpCookieDate() {
-  Expect.throws(() => _HttpUtils.parseCookieDate(""));
-
-  test(int year,
-       int month,
-       int day,
-       int hours,
-       int minutes,
-       int seconds,
-       String formatted) {
-    DateTime date = new DateTime.utc(year, month, day, hours, minutes, seconds, 0);
-    Expect.equals(date, _HttpUtils.parseCookieDate(formatted));
-  }
-
-  test(2012, DateTime.JUNE, 19, 14, 15, 01, "tue, 19-jun-12 14:15:01 gmt");
-  test(2021, DateTime.JUNE, 09, 10, 18, 14, "Wed, 09-Jun-2021 10:18:14 GMT");
-  test(2021, DateTime.JANUARY, 13, 22, 23, 01, "Wed, 13-Jan-2021 22:23:01 GMT");
-  test(2013, DateTime.JANUARY, 15, 21, 47, 38, "Tue, 15-Jan-2013 21:47:38 GMT");
-  test(1970, DateTime.JANUARY, 01, 00, 00, 01, "Thu, 01-Jan-1970 00:00:01 GMT");
-}
-
 void main() {
   testParseHttpDate();
   testFormatParseHttpDate();
   testParseHttpDateFailures();
-  testParseHttpCookieDate();
 }
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index a6cca81..14ae21e 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -5,6 +5,7 @@
 import "package:expect/expect.dart";
 import 'dart:async';
 import 'dart:math';
+import 'dart:collection';
 
 part '../../../sdk/lib/io/common.dart';
 part "../../../sdk/lib/io/io_sink.dart";
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index 8ff7713..6757633 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -7,6 +7,7 @@
 import 'dart:math';
 import 'dart:typed_data';
 import 'dart:isolate';
+import 'dart:collection';
 
 part '../../../sdk/lib/io/common.dart';
 part '../../../sdk/lib/io/io_sink.dart';
diff --git a/tests/standalone/io/process_run_output_test.dart b/tests/standalone/io/process_run_output_test.dart
index 6bdbf44..f8b06d4 100644
--- a/tests/standalone/io/process_run_output_test.dart
+++ b/tests/standalone/io/process_run_output_test.dart
@@ -16,6 +16,9 @@
     Expect.equals(output, 'æøå');
   } else if (encoding == 'utf8') {
     Expect.listEquals(output.codeUnits, [955]);
+  } else if (encoding == 'binary') {
+    print(output);
+    Expect.listEquals(output, [0, 1, 2]);
   }
 }
 
@@ -27,6 +30,8 @@
     enc = Encoding.ISO_8859_1;
   } else if (encoding == 'utf8') {
     enc = Encoding.UTF_8;
+  } else if (encoding == 'binary') {
+    enc = null;
   }
 
   if (stream == 'stdout') {
@@ -61,5 +66,6 @@
   test(scriptFile.path, 'latin1', 'stderr');
   test(scriptFile.path, 'utf8', 'stdout');
   test(scriptFile.path, 'utf8', 'stderr');
-
+  test(scriptFile.path, 'binary', 'stdout');
+  test(scriptFile.path, 'binary', 'stderr');
 }
diff --git a/tests/standalone/io/process_std_io_script2.dart b/tests/standalone/io/process_std_io_script2.dart
index b6ff026..db57929 100644
--- a/tests/standalone/io/process_std_io_script2.dart
+++ b/tests/standalone/io/process_std_io_script2.dart
@@ -9,11 +9,19 @@
 
 writeData(data, encoding, stream) {
   if (stream == "stdout") {
-    stdout.encoding = encoding;
-    stdout.write(data);
+    if (encoding == null) {
+      stdout.add(data);
+    } else {
+      stdout.encoding = encoding;
+      stdout.write(data);
+    }
   } else if (stream == "stderr") {
-    stderr.encoding = encoding;
-    stderr.write(data);
+    if (encoding == null) {
+      stderr.add(data);
+    } else {
+      stderr.encoding = encoding;
+      stderr.write(data);
+    }
   }
 }
 
@@ -21,6 +29,7 @@
   var asciiString = 'abc';
   var latin1String = 'æøå';
   var utf8String = new String.fromCharCodes([955]);
+  var binary = [0, 1, 2];
   var options = new Options();
   if (options.arguments.length > 1) {
     var stream = options.arguments[1];
@@ -30,6 +39,8 @@
       writeData(latin1String, Encoding.ISO_8859_1, stream);
     } else if (options.arguments[0] == "utf8") {
       writeData(utf8String, Encoding.UTF_8, stream);
+    } else if (options.arguments[0] == "binary") {
+      writeData(binary, null, stream);
     }
   }
 }
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
ind