Version 0.5.10.0

svn merge -r 22870:23017 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@23028 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/args/lib/args.dart b/pkg/args/lib/args.dart
index be1a6ef..3898b9f 100644
--- a/pkg/args/lib/args.dart
+++ b/pkg/args/lib/args.dart
@@ -169,17 +169,46 @@
  * option passed to the command. You can add a command like so:
  *
  *     var parser = new ArgParser();
- *     var command = parser.addCommand("commit");
+ *     var command = parser.addCommand('commit');
+ *
+ * It returns another [ArgParser] which you can then use to define options
+ * specific to that command. If you already have an [ArgParser] for the
+ * command's options, you can pass it to [addCommand]:
+ *
+ *     var parser = new ArgParser();
+ *     var command = new ArgParser();
+ *     parser.addCommand('commit', command);
+ *
+ * The [ArgParser] for a command can then define whatever options or flags:
+ *
  *     command.addFlag('all', abbr: 'a');
  *
- * It returns another [ArgParser] which you can use to define options and
- * subcommands on that command. When an argument list is parsed, you can then
- * determine which command was entered and what options were provided for it.
+ * You can add multiple commands to the same parser so that a user can select
+ * one from a range of possible commands. When an argument list is parsed,
+ * you can then determine which command was entered and what options were
+ * provided for it.
  *
  *     var results = parser.parse(['commit', '-a']);
  *     print(results.command.name); // "commit"
  *     print(results.command['a']); // true
  *
+ * Options for a command must appear after the command in the argument list.
+ * For example, given the above parser, "git -a commit" is *not* valid. The
+ * parser will try to find the right-most command that accepts an option. For
+ * example:
+ *
+ *     var parser = new ArgParser();
+ *     parser.addFlag('all', abbr: 'a');
+ *     var command = new ArgParser().addCommand('commit');
+ *     parser.addFlag('all', abbr: 'a');
+ *     var results = parser.parse(['commit', '-a']);
+ *     print(results.command['a']); // true
+ *
+ * Here, both the top-level parser and the "commit" command can accept a "-a"
+ * (which is probably a bad command line interface, admittedly). In that case,
+ * when "-a" appears after "commit", it will be applied to that command. If it
+ * appears to the left of "commit", it will be given to the top-level parser.
+ *
  * ## Displaying usage ##
  *
  * This library can also be used to automatically generate nice usage help
@@ -248,19 +277,21 @@
   ArgParser();
 
   /**
-   * Defines a command. A command is a named argument which may in turn
-   * define its own options and subcommands. Returns an [ArgParser] that can
-   * be used to define the command's options.
+   * Defines a command.
+   *
+   * A command is a named argument which may in turn define its own options and
+   * subcommands using the given parser. If [parser] is omitted, implicitly
+   * creates a new one. Returns the parser for the command.
    */
-  ArgParser addCommand(String name) {
+  ArgParser addCommand(String name, [ArgParser parser]) {
     // Make sure the name isn't in use.
     if (commands.containsKey(name)) {
       throw new ArgumentError('Duplicate command "$name".');
     }
 
-    var command = new ArgParser();
-    commands[name] = command;
-    return command;
+    if (parser == null) parser = new ArgParser();
+    commands[name] = parser;
+    return parser;
   }
 
   /**
diff --git a/pkg/args/test/command_test.dart b/pkg/args/test/command_test.dart
index 5079425..6115ab1 100644
--- a/pkg/args/test/command_test.dart
+++ b/pkg/args/test/command_test.dart
@@ -9,6 +9,21 @@
 
 main() {
   group('ArgParser.addCommand()', () {
+    test('creates a new ArgParser if none is given', () {
+      var parser = new ArgParser();
+      var command = parser.addCommand('install');
+      expect(parser.commands['install'], equals(command));
+      expect(command is ArgParser, isTrue);
+    });
+
+    test('uses the command parser if given one', () {
+      var parser = new ArgParser();
+      var command = new ArgParser();
+      var result = parser.addCommand('install', command);
+      expect(parser.commands['install'], equals(command));
+      expect(result, equals(command));
+    });
+
     test('throws on a duplicate command name', () {
       var parser = new ArgParser();
       parser.addCommand('install');
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 6f9e10e..e4229f4 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -126,6 +126,17 @@
 unittest/test/mock_test: Fail
 unittest/test/mock_regexp_negative_test: Fail
 
+# The unminified unittest tests test that the real names of Dart types are
+# printed. Minified versions of these tests exist that test the behavior when
+# minified.
+unittest/test/*_unminified_test: Skip
+
+[ $minified == false ]
+# The minified unittest tests test that the minified names of Dart types are
+# printed. Unminified versions of these tests exist that test the behavior when
+# not minified.
+unittest/test/*_minified_test: Skip
+
 [ $compiler == none && $runtime == drt ]
 dartdoc/test/dartdoc_test: Skip # See dartbug.com/4541.
 
diff --git a/pkg/scheduled_test/test/descriptor/file_test.dart b/pkg/scheduled_test/test/descriptor/file_test.dart
index 5b64577..958f431 100644
--- a/pkg/scheduled_test/test/descriptor/file_test.dart
+++ b/pkg/scheduled_test/test/descriptor/file_test.dart
@@ -229,7 +229,7 @@
     test('test 2', () {
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
       expect(errors.map((e) => e.error.message), equals([
-        "Expected: contains 'baaz'\n     but: was 'barfoobaz'.\n"
+        "Expected: contains 'baaz'\n     But: was 'barfoobaz'.\n"
       ]), verbose: true);
     });
   }, passing: ['test 2']);
@@ -270,7 +270,7 @@
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
       expect(errors.map((e) => e.error.message), equals([
         "Expected: contains <12>\n"
-        "     but: was <[98, 97, 114, 102, 111, 111, 98, 97, 122]>.\n"
+        "     But: was [98, 97, 114, 102, 111, 111, 98, 97, 122].\n"
       ]), verbose: true);
     });
   }, passing: ['test 2']);
diff --git a/pkg/unittest/lib/matcher.dart b/pkg/unittest/lib/matcher.dart
index fd6412e..1bdb226 100644
--- a/pkg/unittest/lib/matcher.dart
+++ b/pkg/unittest/lib/matcher.dart
@@ -29,6 +29,9 @@
 
 import 'dart:async';
 
+import 'src/pretty_print.dart';
+import 'src/utils.dart';
+
 part 'src/basematcher.dart';
 part 'src/iterable_matchers.dart';
 part 'src/core_matchers.dart';
diff --git a/pkg/unittest/lib/src/core_matchers.dart b/pkg/unittest/lib/src/core_matchers.dart
index 980e7a0..1c8d2f6 100644
--- a/pkg/unittest/lib/src/core_matchers.dart
+++ b/pkg/unittest/lib/src/core_matchers.dart
@@ -173,26 +173,14 @@
         }
       } else {
         reason = new StringDescription();
-        var eType = typeName(expected);
-        var aType = typeName(actual);
-        var includeTypes = eType != aType;
         // If we have recursed, show the expected value too; if not,
         // expect() will show it for us.
         if (depth > 0) {
           reason.add('expected ');
-          if (includeTypes) {
-            reason.add(eType).add(':');
-          }
           reason.addDescriptionOf(expected).add(' but ');
         }
         reason.add('was ');
-        if (includeTypes) {
-          reason.add(aType).add(':');
-        }
         reason.addDescriptionOf(actual);
-        if (includeTypes && depth == 0) {
-          reason.add(' (not type ').add(eType).add(')');
-        }
       }
     }
     if (reason != null && location.length > 0) {
@@ -201,17 +189,6 @@
     return reason;
   }
 
-  String typeName(x) {
-    // dart2js blows up on some objects (e.g. window.navigator).
-    // So we play safe here.
-    try {
-      if (x == null) return "null";
-      return x.runtimeType.toString();
-    } catch (e) {
-      return "Unknown";
-    }
-  }
-
   String _match(expected, actual) {
     Description reason = _recursiveMatch(expected, actual, '', 0);
     return reason == null ? null : reason.toString();
@@ -583,17 +560,16 @@
 
   Description describeMismatch(item, Description mismatchDescription,
                                MatchState matchState, bool verbose) {
-    super.describeMismatch(item, mismatchDescription, matchState, verbose);
     try {
       // We want to generate a different description if there is no length
       // property. This is harmless code that will throw if no length property
       // but subtle enough that an optimizer shouldn't strip it out.
       if (item.length * item.length >= 0) {
-        return mismatchDescription.add(' with length of ').
+        return mismatchDescription.add('had length of ').
             addDescriptionOf(item.length);
       }
     } catch (e) {
-      return mismatchDescription.add(' has no length property');
+      return mismatchDescription.add('had no length property');
     }
   }
 }
diff --git a/pkg/unittest/lib/src/description.dart b/pkg/unittest/lib/src/description.dart
index cdd8193..cde5243 100644
--- a/pkg/unittest/lib/src/description.dart
+++ b/pkg/unittest/lib/src/description.dart
@@ -41,23 +41,8 @@
   Description addDescriptionOf(value) {
     if (value is Matcher) {
       value.describe(this);
-    } else if (value is String) {
-      _addEscapedString(value);
     } else {
-      String description = (value == null) ? "null" : value.toString();
-      if (description.startsWith('<') && description.endsWith('>')) {
-          add(description);
-      } else if (description.startsWith("Instance of")) {
-        add('<');
-        add(description);
-        add(':');
-        add(value.hashCode.toString());
-        add('>');
-      } else {
-        add('<');
-        add(description);
-        add('>');
-      }
+      add(prettyPrint(value, maxLineLength: 80, maxItems: 25));
     }
     return this;
   }
@@ -85,23 +70,7 @@
   /** Escape the control characters in [string] so that they are visible. */
   _addEscapedString(String string) {
     add("'");
-    for (var i = 0; i < string.length; i++) {
-      add(_escape(string[i]));
-    }
+    add(escapeString(string));
     add("'");
   }
-
-  /** Return the escaped form of a character [ch]. */
-  _escape(ch) {
-    if (ch == "'")
-      return "\'";
-    else if (ch == '\n')
-      return '\\n';
-    else if (ch == '\r')
-      return '\\r';
-    else if (ch == '\t')
-      return '\\t';
-    else
-      return ch;
-  }
 }
diff --git a/pkg/unittest/lib/src/expect.dart b/pkg/unittest/lib/src/expect.dart
index 3542f7a..f10309d 100644
--- a/pkg/unittest/lib/src/expect.dart
+++ b/pkg/unittest/lib/src/expect.dart
@@ -137,28 +137,15 @@
 String _defaultErrorFormatter(actual, Matcher matcher, String reason,
     MatchState matchState, bool verbose) {
   var description = new StringDescription();
-  description.add('Expected: ').addDescriptionOf(matcher).
-      add('\n     but: ');
-  matcher.describeMismatch(actual, description, matchState, verbose);
-  description.add('.\n');
-  if (verbose) {
-    if (actual is Iterable) {
-      description.add('Actual: ').addDescriptionOf(actual).add('\n');
-    } else if (actual is Map) {
-      description.add('Actual: ');
-      var count = 25;
-      for (var k in actual.keys) {
-        if (count == 0) {
-          description.add('...\n');
-          break;
-        }
-        description.addDescriptionOf(k);
-        description.add(' : ');
-        description.addDescriptionOf(actual[k]);
-        description.add('\n');
-        --count;
-      }
-    }
+  description.add('Expected: ').addDescriptionOf(matcher).add('\n');
+
+  var mismatchDescription = new StringDescription();
+  matcher.describeMismatch(actual, mismatchDescription, matchState, verbose);
+  description.add('     But: ')
+      .add(mismatchDescription.toString()).add('.\n');
+
+  if (!mismatchDescription.toString().startsWith("was ")) {
+    description.add('Actual: ').addDescriptionOf(actual);
   }
   if (reason != null) {
     description.add(reason).add('\n');
diff --git a/pkg/unittest/lib/src/iterable_matchers.dart b/pkg/unittest/lib/src/iterable_matchers.dart
index acf41d0..65bc610 100644
--- a/pkg/unittest/lib/src/iterable_matchers.dart
+++ b/pkg/unittest/lib/src/iterable_matchers.dart
@@ -42,8 +42,9 @@
     if (matchState.state != null) {
       var index = matchState.state['index'];
       var element = matchState.state['element'];
+      mismatchDescription.add('position $index ');
       return _matcher.describeMismatch(element, mismatchDescription,
-            matchState.state['state'], verbose).add(' at position $index');
+            matchState.state['state'], verbose);
     }
     return super.describeMismatch(item, mismatchDescription,
           matchState, verbose);
diff --git a/pkg/unittest/lib/src/map_matchers.dart b/pkg/unittest/lib/src/map_matchers.dart
index eccc4ec..72984f9 100644
--- a/pkg/unittest/lib/src/map_matchers.dart
+++ b/pkg/unittest/lib/src/map_matchers.dart
@@ -44,8 +44,8 @@
   Description describeMismatch(item, Description mismatchDescription,
                                MatchState matchState, bool verbose) {
     if (!item.containsKey(_key)) {
-      return mismatchDescription.addDescriptionOf(item).
-          add(" doesn't contain key ").addDescriptionOf(_key);
+      return mismatchDescription.add(" doesn't contain key ")
+          .addDescriptionOf(_key);
     } else {
       mismatchDescription.add(' contains key ').addDescriptionOf(_key).
           add(' but with value ');
diff --git a/pkg/unittest/lib/src/numeric_matchers.dart b/pkg/unittest/lib/src/numeric_matchers.dart
index e5dd7ef..84afb49 100644
--- a/pkg/unittest/lib/src/numeric_matchers.dart
+++ b/pkg/unittest/lib/src/numeric_matchers.dart
@@ -150,14 +150,11 @@
   Description describeMismatch(item, Description mismatchDescription,
                                MatchState matchState, bool verbose) {
     if (item is !num) {
-      return mismatchDescription.
-          addDescriptionOf(item).
-          add(' not numeric');
+      return mismatchDescription.add(' not numeric');
     } else {
       var diff = item - _value;
       if (diff < 0) diff = -diff;
       return mismatchDescription.
-          addDescriptionOf(item).
           add(' differed by ').
           addDescriptionOf(diff);
     }
diff --git a/pkg/unittest/lib/src/operator_matchers.dart b/pkg/unittest/lib/src/operator_matchers.dart
index d5142be..c7421b7 100644
--- a/pkg/unittest/lib/src/operator_matchers.dart
+++ b/pkg/unittest/lib/src/operator_matchers.dart
@@ -94,9 +94,9 @@
   Description describeMismatch(item, Description mismatchDescription,
                                MatchState matchState, bool verbose) {
     var matcher = matchState.state['matcher'];
-    mismatchDescription.addDescriptionOf(matcher).add(' ');
-        matcher.describeMismatch(item, mismatchDescription,
-            matchState.state['state'], verbose);
+    matcher.describeMismatch(item, mismatchDescription,
+        matchState.state['state'], verbose);
+    mismatchDescription.add(" (wasn't ").addDescriptionOf(matcher).add(')');
     return mismatchDescription;
   }
 
diff --git a/pkg/unittest/lib/src/pretty_print.dart b/pkg/unittest/lib/src/pretty_print.dart
new file mode 100644
index 0000000..1608e10
--- /dev/null
+++ b/pkg/unittest/lib/src/pretty_print.dart
@@ -0,0 +1,102 @@
+// 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 pretty_print;
+
+import 'utils.dart';
+
+/**
+ * Returns a pretty-printed representation of [object].
+ *
+ * If [maxLineLength] is passed, this will attempt to ensure that each line is
+ * no longer than [maxLineLength] characters long. This isn't guaranteed, since
+ * individual objects may have string representations that are too long, but
+ * most lines will be less than [maxLineLength] long.
+ *
+ * If [maxItems] is passed, [Iterable]s and [Map]s will only print their first
+ * [maxItems] members or key/value pairs, respectively.
+ */
+String prettyPrint(object, {int maxLineLength, int maxItems}) {
+  String _prettyPrint(object, int indent, Set seen, bool top) {
+    // Avoid looping infinitely on recursively-nested data structures.
+    if (seen.contains(object)) return "(recursive)";
+    seen = seen.union(new Set.from([object]));
+    String pp(child) => _prettyPrint(child, indent + 2, seen, false);
+
+    if (object is Iterable) {
+      // Print the type name for non-List iterables.
+      var type = object is List ? "" : typeName(object) + ":";
+
+      // Truncate the list of strings if it's longer than [maxItems].
+      var strings = object.map(pp).toList();
+      if (maxItems != null && strings.length > maxItems) {
+        strings.replaceRange(maxItems - 1, strings.length, ['...']);
+      }
+
+      // If the printed string is short and doesn't contain a newline, print it
+      // as a single line.
+      var singleLine = "$type[${strings.join(', ')}]";
+      if ((maxLineLength == null ||
+              singleLine.length + indent <= maxLineLength) &&
+          !singleLine.contains("\n")) {
+        return singleLine;
+      }
+
+      // Otherwise, print each member on its own line.
+      return "$type[\n" + strings.map((string) {
+        return _indent(indent + 2) + string;
+      }).join(",\n") + "\n" + _indent(indent) + "]";
+    } else if (object is Map) {
+      // Convert the contents of the map to string representations.
+      var strings = object.keys.map((key) {
+        return '${pp(key)}: ${pp(object[key])}';
+      }).toList();
+
+      // Truncate the list of strings if it's longer than [maxItems].
+      if (maxItems != null && strings.length > maxItems) {
+        strings.replaceRange(maxItems - 1, strings.length, ['...']);
+      }
+
+      // If the printed string is short and doesn't contain a newline, print it
+      // as a single line.
+      var singleLine = "{${strings.join(", ")}}";
+      if ((maxLineLength == null ||
+              singleLine.length + indent <= maxLineLength) &&
+          !singleLine.contains("\n")) {
+        return singleLine;
+      }
+
+      // Otherwise, print each key/value pair on its own line.
+      return "{\n" + strings.map((string) {
+        return _indent(indent + 2) + string;
+      }).join(",\n") + "\n" + _indent(indent) + "}";
+    } else if (object is String) {
+      // Escape strings and print each line on its own line.
+      var lines = object.split("\n");
+      return "'" + lines.map(escapeString)
+          .join("\\n'\n${_indent(indent + 2)}'") + "'";
+    } else {
+      var value = object.toString().replaceAll("\n", _indent(indent) + "\n");
+      var defaultToString = value.startsWith("Instance of ");
+
+      // If this is the top-level call to [prettyPrint], wrap the value on angle
+      // brackets to set it apart visually.
+      if (top) value = "<$value>";
+
+      // Print the type of objects with custom [toString] methods. Primitive
+      // objects and objects that don't implement a custom [toString] don't need
+      // to have their types printed.
+      if (object is num || object is bool || object is Function ||
+          object == null || defaultToString) {
+        return value;
+      } else {
+        return "${typeName(object)}:$value";
+      }
+    }
+  }
+
+  return _prettyPrint(object, 0, new Set(), true);
+}
+
+String _indent(int length) => new List.filled(length, ' ').join('');
diff --git a/pkg/unittest/lib/src/utils.dart b/pkg/unittest/lib/src/utils.dart
new file mode 100644
index 0000000..6442ac4
--- /dev/null
+++ b/pkg/unittest/lib/src/utils.dart
@@ -0,0 +1,48 @@
+// 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 utils;
+
+/**
+ * Returns the name of the type of [x], or "Unknown" if the type name can't be
+ * determined.
+ */
+String typeName(x) {
+  // dart2js blows up on some objects (e.g. window.navigator).
+  // So we play safe here.
+  try {
+    if (x == null) return "null";
+    var type = x.runtimeType.toString();
+    // TODO(nweiz): if the object's type is private, find a public superclass to
+    // display once there's a portable API to do that.
+    return type.startsWith("_") ? "?" : type;
+  } catch (e) {
+    return "?";
+  }
+}
+
+/**
+ * Returns [source] with any control characters replaced by their escape
+ * sequences.
+ *
+ * This doesn't add quotes to the string, but it does escape single quote
+ * characters so that single quotes can be applied externally.
+ */
+String escapeString(String source) =>
+    source.split("").map(_escapeChar).join("");
+
+/** Return the escaped form of a character [ch]. */
+String _escapeChar(String ch) {
+  if (ch == "'")
+    return "\\'";
+  else if (ch == '\n')
+    return '\\n';
+  else if (ch == '\r')
+    return '\\r';
+  else if (ch == '\t')
+    return '\\t';
+  else
+    return ch;
+}
+
diff --git a/pkg/unittest/test/instance_test.dart b/pkg/unittest/test/instance_test.dart
index deb1c21..bda0561 100644
--- a/pkg/unittest/test/instance_test.dart
+++ b/pkg/unittest/test/instance_test.dart
@@ -5,9 +5,7 @@
 library unittestTests;
 import 'package:unittest/unittest.dart';
 
-part 'test_utils.dart';
-
-doesThrow() { throw 'X'; }
+import 'test_utils.dart';
 
 main() {
   initUtils();
@@ -15,15 +13,17 @@
   group('Type Matchers', () {
     test('isInstanceOf', () {
       shouldFail(0, new isInstanceOf<String>('String'),
-        "Expected: an instance of String but: was <0>.");
+          "Expected: an instance of String But: was <0>.");
       shouldPass('cow', new isInstanceOf<String>('String'));
     });
 
     test('throwsA', () {
       shouldPass(doesThrow, throwsA(equals('X')));
       shouldFail(doesThrow, throwsA(equals('Y')),
-        "Expected: throws an exception which matches 'Y' "
-        "but:  exception 'X' does not match 'Y'.");
+          "Expected: throws an exception which matches 'Y' "
+          "But:  exception 'X' does not match 'Y'. "
+          "Actual: <Closure: (dynamic) => dynamic "
+              "from Function 'doesThrow': static.>");
     });
   });
 }
diff --git a/pkg/unittest/test/matchers_minified_test.dart b/pkg/unittest/test/matchers_minified_test.dart
new file mode 100644
index 0000000..3fb875d
--- /dev/null
+++ b/pkg/unittest/test/matchers_minified_test.dart
@@ -0,0 +1,140 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This file is for matcher tests that rely on the names of various Dart types.
+// These tests normally fail when run in minified dart2js, since the names will
+// be mangled. This version of the file is modified to expect minified names.
+
+import 'package:unittest/unittest.dart';
+
+import 'test_common.dart';
+import 'test_utils.dart';
+
+// A regexp fragment matching a minified name.
+final _minifiedName = r"[A-Za-z0-9]{1,3}";
+
+void main() {
+  initUtils();
+
+  group('Core matchers', () {
+    test('throwsFormatException', () {
+      shouldPass(() { throw new FormatException(''); },
+          throwsFormatException);
+      shouldFail(() { throw new Exception(); },
+          throwsFormatException,
+          matches(
+              r"Expected: throws an exception which matches FormatException +"
+              r"But:  exception " + _minifiedName + r":<Exception> "
+                  r"does not match FormatException\."
+              r"Actual: <Closure>"));
+    });
+
+    test('throwsArgumentError', () {
+      shouldPass(() { throw new ArgumentError(''); },
+          throwsArgumentError);
+      shouldFail(() { throw new Exception(); },
+          throwsArgumentError,
+          matches(
+              r"Expected: throws an exception which matches ArgumentError +"
+              r"But:  exception " + _minifiedName + r":<Exception> "
+                  r"does not match ArgumentError\."
+              r"Actual: <Closure>"));
+    });
+
+    test('throwsRangeError', () {
+      shouldPass(() { throw new RangeError(0); },
+          throwsRangeError);
+      shouldFail(() { throw new Exception(); },
+          throwsRangeError,
+          matches(
+              r"Expected: throws an exception which matches RangeError +"
+              r"But:  exception " + _minifiedName + r":<Exception> "
+                  r"does not match RangeError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsNoSuchMethodError', () {
+      shouldPass(() { throw new NoSuchMethodError(null, '', null, null); },
+          throwsNoSuchMethodError);
+      shouldFail(() { throw new Exception(); },
+          throwsNoSuchMethodError,
+          matches(
+              r"Expected: throws an exception which matches NoSuchMethodError +"
+              r"But:  exception " + _minifiedName + r":<Exception> "
+                  r"does not match NoSuchMethodError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsUnimplementedError', () {
+      shouldPass(() { throw new UnimplementedError(''); },
+          throwsUnimplementedError);
+      shouldFail(() { throw new Exception(); },
+          throwsUnimplementedError,
+          matches(
+              r"Expected: throws an exception which matches "
+                  r"UnimplementedError +"
+              r"But:  exception " + _minifiedName + r":<Exception> "
+                  r"does not match UnimplementedError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsUnsupportedError', () {
+      shouldPass(() { throw new UnsupportedError(''); },
+          throwsUnsupportedError);
+      shouldFail(() { throw new Exception(); },
+          throwsUnsupportedError,
+          matches(
+              r"Expected: throws an exception which matches UnsupportedError +"
+              r"But:  exception " + _minifiedName + r":<Exception> "
+                  r"does not match UnsupportedError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsStateError', () {
+      shouldPass(() { throw new StateError(''); },
+          throwsStateError);
+      shouldFail(() { throw new Exception(); },
+          throwsStateError,
+          matches(
+              r"Expected: throws an exception which matches StateError +"
+              r"But:  exception " + _minifiedName + r":<Exception> "
+                  r"does not match StateError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+  });
+
+  group('Iterable Matchers', () {
+    test('isEmpty', () {
+      var d = new SimpleIterable(0);
+      var e = new SimpleIterable(1);
+      shouldPass(d, isEmpty);
+      shouldFail(e, isEmpty,
+          matches(r"Expected: empty +But: was " + _minifiedName + r":\[1\]\."));
+    });
+
+    test('contains', () {
+      var d = new SimpleIterable(3);
+      shouldPass(d, contains(2));
+      shouldFail(d, contains(5),
+          matches(
+              r"Expected: contains <5> +"
+              r"But: was " + _minifiedName + r":\[3, 2, 1\]\."));
+    });
+  });
+
+  group('Feature Matchers', () {
+    test("Feature Matcher", () {
+      var w = new Widget();
+      w.price = 10;
+      shouldPass(w, new HasPrice(10));
+      shouldPass(w, new HasPrice(greaterThan(0)));
+      shouldFail(w, new HasPrice(greaterThan(10)),
+          matches(
+              r"Expected: Widget with a price that is a value greater than "
+                  r"<10> +"
+              r"But: price was <10>\."
+              r"Actual: <Instance of '" + _minifiedName + r"'>"));
+    });
+  });
+}
diff --git a/pkg/unittest/test/matchers_test.dart b/pkg/unittest/test/matchers_test.dart
index 10592da..4e53e16 100644
--- a/pkg/unittest/test/matchers_test.dart
+++ b/pkg/unittest/test/matchers_test.dart
@@ -2,77 +2,13 @@
 // for 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 unittestTests;
-import 'package:unittest/unittest.dart';
 import 'dart:async';
 import 'dart:collection';
-part 'test_utils.dart';
 
-doesNotThrow() {}
-doesThrow() { throw 'X'; }
+import 'package:unittest/unittest.dart';
 
-class PrefixMatcher extends BaseMatcher {
-  final String _prefix;
-  const PrefixMatcher(this._prefix);
-  bool matches(item, MatchState matchState) {
-    return item is String &&
-        (collapseWhitespace(item)).startsWith(collapseWhitespace(_prefix));
-  }
-
-  Description describe(Description description) =>
-    description.add('a string starting with ').
-        addDescriptionOf(collapseWhitespace(_prefix)).
-        add(' ignoring whitespace');
-}
-
-class Widget {
-  int price;
-}
-
-class HasPrice extends CustomMatcher {
-  HasPrice(matcher) :
-    super("Widget with a price that is", "price", matcher);
-  featureValueOf(actual) => actual.price;
-}
-
-class SimpleIterable extends IterableBase {
-  int count;
-  SimpleIterable(this.count);
-
-  bool contains(int val) => count < val ? false : true;
-
-  bool any(bool f(element)) {
-    for(var i = 0; i <= count; i++) {
-      if(f(i)) return true;
-    }
-    return false;
-  }
-
-  String toString() => "<[$count]>";
-
-  Iterator get iterator {
-    return new SimpleIterator(count);
-  }
-}
-
-class SimpleIterator implements Iterator {
-  int _count;
-  int _current;
-
-  SimpleIterator(this._count);
-
-  bool moveNext() {
-    if (_count > 0) {
-      _current = _count;
-      _count--;
-      return true;
-    }
-    _current = null;
-    return false;
-  }
-
-  get current => _current;
-}
+import 'test_common.dart';
+import 'test_utils.dart';
 
 void main() {
 
@@ -84,30 +20,30 @@
 
     test('isTrue', () {
       shouldPass(true, isTrue);
-      shouldFail(false, isTrue, "Expected: true but: was <false>.");
+      shouldFail(false, isTrue, "Expected: true But: was <false>.");
     });
 
     test('isFalse', () {
       shouldPass(false, isFalse);
-      shouldFail(10, isFalse, "Expected: false but: was <10>.");
-      shouldFail(true, isFalse, "Expected: false but: was <true>.");
+      shouldFail(10, isFalse, "Expected: false But: was <10>.");
+      shouldFail(true, isFalse, "Expected: false But: was <true>.");
     });
 
     test('isNull', () {
       shouldPass(null, isNull);
-      shouldFail(false, isNull, "Expected: null but: was <false>.");
+      shouldFail(false, isNull, "Expected: null But: was <false>.");
     });
 
     test('isNotNull', () {
       shouldPass(false, isNotNull);
-      shouldFail(null, isNotNull, "Expected: not null but: was <null>.");
+      shouldFail(null, isNotNull, "Expected: not null But: was <null>.");
     });
 
     test('same', () {
       var a = new Map();
       var b = new Map();
       shouldPass(a, same(a));
-      shouldFail(b, same(a), "Expected: same instance as <{}> but: was <{}>.");
+      shouldFail(b, same(a), "Expected: same instance as {} But: was {}.");
     });
 
     test('equals', () {
@@ -122,96 +58,38 @@
       shouldPass(0, anything);
       shouldPass(null, anything);
       shouldPass(a, anything);
-      shouldFail(a, isNot(anything), "Expected: not anything but: was <{}>.");
+      shouldFail(a, isNot(anything), "Expected: not anything But: was {}.");
     });
 
     test('throws', () {
       shouldFail(doesNotThrow, throws,
-        "Expected: throws an exception but: no exception.");
+          matches(
+              r"Expected: throws an exception +But:  no exception\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic "
+                  r"from Function 'doesNotThrow': static\.)?>"));
       shouldPass(doesThrow, throws);
       shouldFail(true, throws,
-          "Expected: throws an exception but: not a Function or Future.");
+          "Expected: throws an exception But: not a Function or Future. "
+          "Actual: <true>");
     });
 
     test('throwsA', () {
       shouldPass(doesThrow, throwsA(equals('X')));
       shouldFail(doesThrow, throwsA(equals('Y')),
-        "Expected: throws an exception which matches 'Y' "
-        "but:  exception 'X' does not match 'Y'.");
-    });
-
-    test('throwsFormatException', () {
-      shouldPass(() { throw new FormatException(''); },
-          throwsFormatException);
-      shouldFail(() { throw new Exception(); },
-          throwsFormatException,
-        "Expected: throws an exception which matches FormatException "
-        "but:  exception <Exception> does not match FormatException.");
-    });
-
-    test('throwsArgumentError', () {
-      shouldPass(() { throw new ArgumentError(''); },
-          throwsArgumentError);
-      shouldFail(() { throw new Exception(); },
-          throwsArgumentError,
-        "Expected: throws an exception which matches ArgumentError "
-        "but:  exception <Exception> does not match "
-            "ArgumentError.");
-    });
-
-    test('throwsRangeError', () {
-      shouldPass(() { throw new RangeError(0); },
-          throwsRangeError);
-      shouldFail(() { throw new Exception(); },
-          throwsRangeError,
-        "Expected: throws an exception which matches RangeError "
-        "but:  exception <Exception> does not match RangeError.");
-    });
-
-    test('throwsNoSuchMethodError', () {
-      shouldPass(() { throw new NoSuchMethodError(null, '', null, null); },
-          throwsNoSuchMethodError);
-      shouldFail(() { throw new Exception(); },
-          throwsNoSuchMethodError,
-        "Expected: throws an exception which matches NoSuchMethodError "
-        "but:  exception <Exception> does not match "
-            "NoSuchMethodError.");
-    });
-
-    test('throwsUnimplementedError', () {
-      shouldPass(() { throw new UnimplementedError(''); },
-          throwsUnimplementedError);
-      shouldFail(() { throw new Exception(); },
-          throwsUnimplementedError,
-        "Expected: throws an exception which matches UnimplementedError "
-        "but:  exception <Exception> does not match "
-            "UnimplementedError.");
-    });
-
-    test('throwsUnsupportedError', () {
-      shouldPass(() { throw new UnsupportedError(''); },
-          throwsUnsupportedError);
-      shouldFail(() { throw new Exception(); },
-          throwsUnsupportedError,
-        "Expected: throws an exception which matches UnsupportedError "
-        "but:  exception <Exception> does not match "
-            "UnsupportedError.");
-    });
-
-    test('throwsStateError', () {
-      shouldPass(() { throw new StateError(''); },
-          throwsStateError);
-      shouldFail(() { throw new Exception(); },
-          throwsStateError,
-        "Expected: throws an exception which matches StateError "
-        "but:  exception <Exception> does not match "
-            "StateError.");
+          matches(
+              r"Expected: throws an exception which matches 'Y' +"
+              r"But:  exception 'X' does not match 'Y'\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic "
+                  r"from Function 'doesThrow': static\.)?>"));
     });
 
     test('returnsNormally', () {
       shouldPass(doesNotThrow, returnsNormally);
       shouldFail(doesThrow, returnsNormally,
-        "Expected: return normally but: threw 'X'.");
+          matches(
+              r"Expected: return normally +But:  threw 'X'\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic "
+                  r"from Function 'doesThrow': static\.)?>"));
     });
 
     test('hasLength', () {
@@ -221,41 +99,44 @@
       shouldPass(b, hasLength(0));
       shouldPass('a', hasLength(1));
       shouldFail(0, hasLength(0), new PrefixMatcher(
-        "Expected: an object with length of <0> "
-        "but: was <0> has no length property."));
+          "Expected: an object with length of <0> "
+          "But: had no length property."
+          "Actual: <0>"));
 
       b.add(0);
       shouldPass(b, hasLength(1));
       shouldFail(b, hasLength(2),
-        "Expected: an object with length of <2> "
-        "but: was <[0]> with length of <1>.");
+          "Expected: an object with length of <2> "
+          "But: had length of <1>. "
+          "Actual: [0]");
 
       b.add(0);
       shouldFail(b, hasLength(1),
-        "Expected: an object with length of <1> "
-        "but: was <[0, 0]> with length of <2>.");
+          "Expected: an object with length of <1> "
+          "But: had length of <2>. "
+          "Actual: [0, 0]");
       shouldPass(b, hasLength(2));
     });
 
     test('scalar type mismatch', () {
       shouldFail('error', equals(5.1),
-          matches("^Expected: <5\.1>"
-                  "     but: was .*:'error' \\(not type .*\\)\.\$"));
+          "Expected: <5.1> "
+          "But: was 'error'.");
     });
 
     test('nested type mismatch', () {
       shouldFail(['error'], equals([5.1]),
-          matches(r"^Expected: <\[5\.1\]>"
-                  "     but: expected double:<5\.1> "
-                  "but was .*:'error' mismatch at position 0\.\$"));
+          "Expected: [5.1] "
+          "But: expected <5.1> but was 'error' mismatch at position 0. "
+          "Actual: ['error']");
     });
 
     test('doubly-nested type mismatch', () {
       shouldFail([['error']], equals([[5.1]]),
-          matches(r"^Expected: <\[\[5\.1\]\]>"
-                  "     but: expected double:<5\.1> "
-                  "but was .*:'error' mismatch at position 0 "
-                  "mismatch at position 0\.\$"));
+          "Expected: [[5.1]] "
+          "But: expected <5.1> but was 'error' "
+          "mismatch at position 0 mismatch at position 0. "
+          "Actual: [['error']]");
     });
   });
 
@@ -264,64 +145,64 @@
     test('greaterThan', () {
       shouldPass(10, greaterThan(9));
       shouldFail(9, greaterThan(10),
-        "Expected: a value greater than <10> but: was <9>.");
+        "Expected: a value greater than <10> But: was <9>.");
     });
 
     test('greaterThanOrEqualTo', () {
       shouldPass(10, greaterThanOrEqualTo(10));
       shouldFail(9, greaterThanOrEqualTo(10),
-        "Expected: a value greater than or equal to <10> but: was <9>.");
+        "Expected: a value greater than or equal to <10> But: was <9>.");
     });
 
     test('lessThan', () {
       shouldFail(10, lessThan(9), "Expected: a value less than <9> "
-          "but: was <10>.");
+          "But: was <10>.");
       shouldPass(9, lessThan(10));
     });
 
     test('lessThanOrEqualTo', () {
       shouldPass(10, lessThanOrEqualTo(10));
       shouldFail(11, lessThanOrEqualTo(10),
-        "Expected: a value less than or equal to <10> but: was <11>.");
+        "Expected: a value less than or equal to <10> But: was <11>.");
     });
 
     test('isZero', () {
       shouldPass(0, isZero);
-      shouldFail(1, isZero, "Expected: a value equal to <0> but: was <1>.");
+      shouldFail(1, isZero, "Expected: a value equal to <0> But: was <1>.");
     });
 
     test('isNonZero', () {
       shouldFail(0, isNonZero, "Expected: a value not equal to <0> "
-          "but: was <0>.");
+          "But: was <0>.");
       shouldPass(1, isNonZero);
     });
 
     test('isPositive', () {
       shouldFail(-1, isPositive, "Expected: a positive value "
-          "but: was <-1>.");
+          "But: was <-1>.");
       shouldFail(0, isPositive, "Expected: a positive value "
-          "but: was <0>.");
+          "But: was <0>.");
       shouldPass(1, isPositive);
     });
 
     test('isNegative', () {
       shouldPass(-1, isNegative);
       shouldFail(0, isNegative,
-          "Expected: a negative value but: was <0>.");
+          "Expected: a negative value But: was <0>.");
     });
 
     test('isNonPositive', () {
       shouldPass(-1, isNonPositive);
       shouldPass(0, isNonPositive);
       shouldFail(1, isNonPositive,
-          "Expected: a non-positive value but: was <1>.");
+          "Expected: a non-positive value But: was <1>.");
     });
 
     test('isNonNegative', () {
       shouldPass(1, isNonNegative);
       shouldPass(0, isNonNegative);
       shouldFail(-1, isNonNegative,
-        "Expected: a non-negative value but: was <-1>.");
+        "Expected: a non-negative value But: was <-1>.");
     });
 
     test('closeTo', () {
@@ -330,38 +211,40 @@
       shouldPass(1, closeTo(0, 1));
       shouldFail(1.001, closeTo(0, 1),
           "Expected: a numeric value within <1> of <0> "
-          "but: <1.001> differed by <1.001>.");
+          "But: differed by <1.001>. "
+          "Actual: <1.001>");
       shouldFail(-1.001, closeTo(0, 1),
           "Expected: a numeric value within <1> of <0> "
-          "but: <-1.001> differed by <1.001>.");
+          "But: differed by <1.001>. "
+          "Actual: <-1.001>");
     });
 
     test('inInclusiveRange', () {
       shouldFail(-1, inInclusiveRange(0,2),
           "Expected: be in range from 0 (inclusive) to 2 (inclusive) "
-          "but: was <-1>.");
+          "But: was <-1>.");
       shouldPass(0, inInclusiveRange(0,2));
       shouldPass(1, inInclusiveRange(0,2));
       shouldPass(2, inInclusiveRange(0,2));
       shouldFail(3, inInclusiveRange(0,2),
           "Expected: be in range from 0 (inclusive) to 2 (inclusive) "
-          "but: was <3>.");
+          "But: was <3>.");
     });
 
     test('inExclusiveRange', () {
       shouldFail(0, inExclusiveRange(0,2),
           "Expected: be in range from 0 (exclusive) to 2 (exclusive) "
-          "but: was <0>.");
+          "But: was <0>.");
       shouldPass(1, inExclusiveRange(0,2));
       shouldFail(2, inExclusiveRange(0,2),
           "Expected: be in range from 0 (exclusive) to 2 (exclusive) "
-          "but: was <2>.");
+          "But: was <2>.");
     });
 
     test('inOpenClosedRange', () {
       shouldFail(0, inOpenClosedRange(0,2),
           "Expected: be in range from 0 (exclusive) to 2 (inclusive) "
-          "but: was <0>.");
+          "But: was <0>.");
       shouldPass(1, inOpenClosedRange(0,2));
       shouldPass(2, inOpenClosedRange(0,2));
     });
@@ -371,7 +254,7 @@
       shouldPass(1, inClosedOpenRange(0,2));
       shouldFail(2, inClosedOpenRange(0,2),
           "Expected: be in range from 0 (inclusive) to 2 (exclusive) "
-          "but: was <2>.");
+          "But: was <2>.");
     });
   });
 
@@ -380,22 +263,22 @@
     test('isEmpty', () {
       shouldPass('', isEmpty);
       shouldFail(null, isEmpty,
-          "Expected: empty but: was <null>.");
+          "Expected: empty But: was <null>.");
       shouldFail(0, isEmpty,
-          "Expected: empty but: was <0>.");
-      shouldFail('a', isEmpty, "Expected: empty but: was 'a'.");
+          "Expected: empty But: was <0>.");
+      shouldFail('a', isEmpty, "Expected: empty But: was 'a'.");
     });
 
     test('equalsIgnoringCase', () {
       shouldPass('hello', equalsIgnoringCase('HELLO'));
       shouldFail('hi', equalsIgnoringCase('HELLO'),
-          "Expected: 'HELLO' ignoring case but: was 'hi'.");
+          "Expected: 'HELLO' ignoring case But: was 'hi'.");
     });
 
     test('equalsIgnoringWhitespace', () {
       shouldPass(' hello   world  ', equalsIgnoringWhitespace('hello world'));
       shouldFail(' helloworld  ', equalsIgnoringWhitespace('hello world'),
-          "Expected: 'hello world' ignoring whitespace but: was 'helloworld'.");
+          "Expected: 'hello world' ignoring whitespace But: was 'helloworld'.");
     });
 
     test('startsWith', () {
@@ -403,7 +286,7 @@
       shouldPass('hello', startsWith('hell'));
       shouldPass('hello', startsWith('hello'));
       shouldFail('hello', startsWith('hello '),
-          "Expected: a string starting with 'hello ' but: was 'hello'.");
+          "Expected: a string starting with 'hello ' But: was 'hello'.");
     });
 
     test('endsWith', () {
@@ -411,7 +294,7 @@
       shouldPass('hello', endsWith('lo'));
       shouldPass('hello', endsWith('hello'));
       shouldFail('hello', endsWith(' hello'),
-          "Expected: a string ending with ' hello' but: was 'hello'.");
+          "Expected: a string ending with ' hello' But: was 'hello'.");
     });
 
     test('contains', () {
@@ -421,7 +304,7 @@
       shouldPass('hello', contains('hell'));
       shouldPass('hello', contains('hello'));
       shouldFail('hello', contains(' '),
-          "Expected: contains ' ' but: was 'hello'.");
+          "Expected: contains ' ' But: was 'hello'.");
     });
 
     test('stringContainsInOrder', () {
@@ -440,29 +323,14 @@
       shouldFail('goodbye cruel world',
         stringContainsInOrder(['goo', 'cruel', 'bye']),
         "Expected: a string containing 'goo', 'cruel', 'bye' in order "
-        "but: was 'goodbye cruel world'.");
+        "But: was 'goodbye cruel world'.");
     });
 
     test('matches', () {
       shouldPass('c0d', matches('[a-z][0-9][a-z]'));
       shouldPass('c0d', matches(new RegExp('[a-z][0-9][a-z]')));
       shouldFail('cOd', matches('[a-z][0-9][a-z]'),
-          "Expected: match '[a-z][0-9][a-z]' but: was 'cOd'.");
-    });
-  });
-
-  group('Iterable Matchers', () {
-    test('isEmpty', () {
-      var d = new SimpleIterable(0);
-      var e = new SimpleIterable(1);
-      shouldPass(d, isEmpty);
-      shouldFail(e, isEmpty, "Expected: empty but: was <[1]>.");
-    });
-
-    test('contains', () {
-      var d = new SimpleIterable(3);
-      shouldPass(d, contains(2));
-      shouldFail(d, contains(5), "Expected: contains <5> but: was <[3]>.");
+          "Expected: match '[a-z][0-9][a-z]' But: was 'cOd'.");
     });
   });
 
@@ -470,26 +338,27 @@
 
     test('isEmpty', () {
       shouldPass([], isEmpty);
-      shouldFail([1], isEmpty, "Expected: empty but: was <[1]>.");
+      shouldFail([1], isEmpty, "Expected: empty But: was [1].");
     });
 
     test('contains', () {
       var d = [1, 2];
       shouldPass(d, contains(1));
-      shouldFail(d, contains(0), "Expected: contains <0> but: was <[1, 2]>.");
+      shouldFail(d, contains(0), "Expected: contains <0> But: was [1, 2].");
     });
 
     test('isIn', () {
       var d = [1, 2];
       shouldPass(1, isIn(d));
-      shouldFail(0, isIn(d), "Expected: is in <[1, 2]> but: was <0>.");
+      shouldFail(0, isIn(d), "Expected: is in [1, 2] But: was <0>.");
     });
 
     test('everyElement', () {
       var d = [1, 2];
       var e = [1, 1, 1];
       shouldFail(d, everyElement(1),
-          "Expected: every element <1> but: was <2> at position 1.");
+          "Expected: every element <1> But: position 1 was <2>. "
+          "Actual: [1, 2]");
       shouldPass(e, everyElement(1));
     });
 
@@ -498,7 +367,7 @@
       var e = [1, 1, 1];
       shouldPass(d, someElement(2));
       shouldFail(e, someElement(2),
-          "Expected: some element <2> but: was <[1, 1, 1]>.");
+          "Expected: some element <2> But: was [1, 1, 1].");
     });
 
     test('orderedEquals', () {
@@ -506,22 +375,26 @@
       var d = [1, 2];
       shouldPass(d, orderedEquals([1, 2]));
       shouldFail(d, orderedEquals([2, 1]),
-          "Expected: equals <[2, 1]> ordered "
-          "but: expected <2> but was <1> mismatch at position 0.");
+          "Expected: equals [2, 1] ordered "
+          "But: expected <2> but was <1> mismatch at position 0. "
+          "Actual: [1, 2]");
     });
 
     test('unorderedEquals', () {
       var d = [1, 2];
       shouldPass(d, unorderedEquals([2, 1]));
       shouldFail(d, unorderedEquals([1]),
-          "Expected: equals <[1]> unordered "
-          "but: has too many elements (2 > 1).");
+          "Expected: equals [1] unordered "
+          "But: has too many elements (2 > 1). "
+          "Actual: [1, 2]");
       shouldFail(d, unorderedEquals([3, 2, 1]),
-          "Expected: equals <[3, 2, 1]> unordered "
-          "but: has too few elements (2 < 3).");
+          "Expected: equals [3, 2, 1] unordered "
+          "But: has too few elements (2 < 3). "
+          "Actual: [1, 2]");
       shouldFail(d, unorderedEquals([3, 1]),
-          "Expected: equals <[3, 1]> unordered "
-          "but: has no match for element <3> at position 0.");
+          "Expected: equals [3, 1] unordered "
+          "But: has no match for element <3> at position 0. "
+          "Actual: [1, 2]");
     });
 
     test('pairwise compare', () {
@@ -530,19 +403,23 @@
       var e = [1, 4, 9];
       shouldFail('x', pairwiseCompare(e, (e,a) => a <= e,
           "less than or equal"),
-          "Expected: pairwise less than or equal <[1, 4, 9]> but: "
-          "not an Iterable.");
+          "Expected: pairwise less than or equal [1, 4, 9] "
+          "But: not an Iterable. "
+          "Actual: 'x'");
       shouldFail(c, pairwiseCompare(e, (e,a) => a <= e, "less than or equal"),
-          "Expected: pairwise less than or equal <[1, 4, 9]> but: "
-          "length was 2 instead of 3.");
+          "Expected: pairwise less than or equal [1, 4, 9] "
+          "But: length was 2 instead of 3. "
+          "Actual: [1, 2]");
       shouldPass(d, pairwiseCompare(e, (e,a) => a <= e, "less than or equal"));
       shouldFail(d, pairwiseCompare(e, (e,a) => a < e, "less than"),
-          "Expected: pairwise less than <[1, 4, 9]> but: "
-          "<1> not less than <1> at position 0.");
+          "Expected: pairwise less than [1, 4, 9] "
+          "But: <1> not less than <1> at position 0. "
+          "Actual: [1, 2, 3]");
       shouldPass(d, pairwiseCompare(e, (e,a) => a * a == e, "square root of"));
       shouldFail(d, pairwiseCompare(e, (e,a) => a + a == e, "double"),
-          "Expected: pairwise double <[1, 4, 9]> but: "
-          "<1> not double <1> at position 0.");
+          "Expected: pairwise double [1, 4, 9] "
+          "But: <1> not double <1> at position 0. "
+          "Actual: [1, 2, 3]");
     });
   });
 
@@ -553,7 +430,7 @@
       shouldPass({}, isEmpty);
       shouldPass(a, isEmpty);
       a['foo'] = 'bar';
-      shouldFail(a, isEmpty, "Expected: empty but: was <{foo: bar}>.");
+      shouldFail(a, isEmpty, "Expected: empty But: was {'foo': 'bar'}.");
     });
 
     test('equals', () {
@@ -565,7 +442,8 @@
       c['bar'] = 'foo';
       shouldPass(a, equals(b));
       shouldFail(b, equals(c),
-          "Expected: <{bar: foo}> but: missing map key 'bar'.");
+          "Expected: {'bar': 'foo'} But: missing map key 'bar'. "
+          "Actual: {'foo': 'bar'}");
     });
 
     test('equals with different lengths', () {
@@ -578,23 +456,29 @@
       c['bar'] = 'foo';
       c['barrista'] = 'caffeine';
       shouldFail(a, equals(b),
-          "Expected: <{foo: bar, bar: foo}> "
-          "but: different map lengths; missing map key 'bar'.");
+          "Expected: {'foo': 'bar', 'bar': 'foo'} "
+          "But: different map lengths; missing map key 'bar'. "
+          "Actual: {'foo': 'bar'}");
       shouldFail(b, equals(a),
-          "Expected: <{foo: bar}> "
-          "but: different map lengths; extra map key 'bar'.");
+          "Expected: {'foo': 'bar'} "
+          "But: different map lengths; extra map key 'bar'. "
+          "Actual: {'foo': 'bar', 'bar': 'foo'}");
       shouldFail(b, equals(c),
-          "Expected: <{bar: foo, barrista: caffeine}> "
-          "but: missing map key 'barrista'.");
+          "Expected: {'bar': 'foo', 'barrista': 'caffeine'} "
+          "But: missing map key 'barrista'. "
+          "Actual: {'foo': 'bar', 'bar': 'foo'}");
       shouldFail(c, equals(b),
-          "Expected: <{foo: bar, bar: foo}> "
-          "but: missing map key 'foo'.");
+          "Expected: {'foo': 'bar', 'bar': 'foo'} "
+          "But: missing map key 'foo'. "
+          "Actual: {'bar': 'foo', 'barrista': 'caffeine'}");
       shouldFail(a, equals(c),
-          "Expected: <{bar: foo, barrista: caffeine}> "
-          "but: different map lengths; missing map key 'bar'.");
+          "Expected: {'bar': 'foo', 'barrista': 'caffeine'} "
+          "But: different map lengths; missing map key 'bar'. "
+          "Actual: {'foo': 'bar'}");
       shouldFail(c, equals(a),
-          "Expected: <{foo: bar}> "
-          "but: different map lengths; missing map key 'foo'.");
+          "Expected: {'foo': 'bar'} "
+          "But: different map lengths; missing map key 'foo'. "
+          "Actual: {'bar': 'foo', 'barrista': 'caffeine'}");
     });
 
     test('contains', () {
@@ -603,9 +487,9 @@
       var b = new Map();
       shouldPass(a, contains('foo'));
       shouldFail(b, contains('foo'),
-          "Expected: contains 'foo' but: was <{}>.");
+          "Expected: contains 'foo' But: was {}.");
       shouldFail(10, contains('foo'),
-          "Expected: contains 'foo' but: was <10>.");
+          "Expected: contains 'foo' But: was <10>.");
     });
 
     test('containsValue', () {
@@ -613,7 +497,7 @@
       a['foo'] = 'bar';
       shouldPass(a, containsValue('bar'));
       shouldFail(a, containsValue('ba'),
-          "Expected: contains value 'ba' but: was <{foo: bar}>.");
+          "Expected: contains value 'ba' But: was {'foo': 'bar'}.");
     });
 
     test('containsPair', () {
@@ -622,10 +506,12 @@
       shouldPass(a, containsPair('foo', 'bar'));
       shouldFail(a, containsPair('foo', 'ba'),
           "Expected: contains pair 'foo' => 'ba' "
-          "but:  contains key 'foo' but with value was 'bar'.");
+          "But:  contains key 'foo' but with value was 'bar'. "
+          "Actual: {'foo': 'bar'}");
       shouldFail(a, containsPair('fo', 'bar'),
           "Expected: contains pair 'fo' => 'bar' "
-          "but: <{foo: bar}> doesn't contain key 'fo'.");
+          "But: doesn't contain key 'fo'. "
+          "Actual: {'foo': 'bar'}");
     });
 
     test('hasLength', () {
@@ -635,7 +521,8 @@
       shouldPass(a, hasLength(1));
       shouldFail(b, hasLength(1),
           "Expected: an object with length of <1> "
-          "but: was <{}> with length of <0>.");
+          "But: had length of <0>. "
+          "Actual: {}");
     });
   });
 
@@ -643,7 +530,7 @@
 
     test('anyOf', () {
       shouldFail(0, anyOf([equals(1), equals(2)]),
-          "Expected: (<1> or <2>) but: was <0>.");
+          "Expected: (<1> or <2>) But: was <0>.");
       shouldPass(1, anyOf([equals(1), equals(2)]));
     });
 
@@ -651,7 +538,7 @@
       shouldPass(1, allOf([lessThan(10), greaterThan(0)]));
       shouldFail(-1, allOf([lessThan(10), greaterThan(0)]),
           "Expected: (a value less than <10> and a value greater than <0>) "
-          "but: a value greater than <0> was <-1>.");
+          "But: was <-1> (wasn't a value greater than <0>).");
     });
   });
 
@@ -711,7 +598,7 @@
       var completer = new Completer();
       completer.completeError('X');
       shouldFail(completer.future, throwsA(equals('Y')),
-          "Expected: 'Y' but: was 'X'.",
+          "Expected: 'Y' But: was 'X'.",
           isAsync: true);
     });
   });
@@ -719,21 +606,9 @@
   group('Predicate Matchers', () {
     test('isInstanceOf', () {
       shouldFail(0, predicate((x) => x is String, "an instance of String"),
-          "Expected: an instance of String but: was <0>.");
+          "Expected: an instance of String But: was <0>.");
       shouldPass('cow', predicate((x) => x is String, "an instance of String"));
     });
   });
-
-  group('Feature Matchers', () {
-    test("Feature Matcher", () {
-      var w = new Widget();
-      w.price = 10;
-      shouldPass(w, new HasPrice(10));
-      shouldPass(w, new HasPrice(greaterThan(0)));
-      shouldFail(w, new HasPrice(greaterThan(10)),
-          'Expected: Widget with a price that is a value greater than <10> '
-          'but: price was <10>.');
-    });
-  });
 }
 
diff --git a/pkg/unittest/test/matchers_unminified_test.dart b/pkg/unittest/test/matchers_unminified_test.dart
new file mode 100644
index 0000000..7435a0c
--- /dev/null
+++ b/pkg/unittest/test/matchers_unminified_test.dart
@@ -0,0 +1,132 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This file is for matcher tests that rely on the names of various Dart types.
+// These tests will fail when run in minified dart2js, since the names will be
+// mangled. A version of this file that works in minified dart2js is in
+// matchers_minified_test.dart.
+
+import 'package:unittest/unittest.dart';
+
+import 'test_common.dart';
+import 'test_utils.dart';
+
+void main() {
+  initUtils();
+
+  group('Core matchers', () {
+    test('throwsFormatException', () {
+      shouldPass(() { throw new FormatException(''); },
+          throwsFormatException);
+      shouldFail(() { throw new Exception(); },
+          throwsFormatException,
+          matches(
+              r"Expected: throws an exception which matches FormatException +"
+              r"But:  exception \?:<Exception> does not match FormatException\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsArgumentError', () {
+      shouldPass(() { throw new ArgumentError(''); },
+          throwsArgumentError);
+      shouldFail(() { throw new Exception(); },
+          throwsArgumentError,
+          matches(
+              r"Expected: throws an exception which matches ArgumentError +"
+              r"But:  exception \?:<Exception> does not match "
+                  r"ArgumentError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsRangeError', () {
+      shouldPass(() { throw new RangeError(0); },
+          throwsRangeError);
+      shouldFail(() { throw new Exception(); },
+          throwsRangeError,
+          matches(
+              r"Expected: throws an exception which matches RangeError +"
+              r"But:  exception \?:<Exception> does not match RangeError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsNoSuchMethodError', () {
+      shouldPass(() { throw new NoSuchMethodError(null, '', null, null); },
+          throwsNoSuchMethodError);
+      shouldFail(() { throw new Exception(); },
+          throwsNoSuchMethodError,
+          matches(
+              r"Expected: throws an exception which matches NoSuchMethodError +"
+              r"But:  exception \?:<Exception> does not match "
+                  r"NoSuchMethodError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsUnimplementedError', () {
+      shouldPass(() { throw new UnimplementedError(''); },
+          throwsUnimplementedError);
+      shouldFail(() { throw new Exception(); },
+          throwsUnimplementedError,
+          matches(
+              r"Expected: throws an exception which matches "
+                  r"UnimplementedError +"
+              r"But:  exception \?:<Exception> does not match "
+                  r"UnimplementedError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsUnsupportedError', () {
+      shouldPass(() { throw new UnsupportedError(''); },
+          throwsUnsupportedError);
+      shouldFail(() { throw new Exception(); },
+          throwsUnsupportedError,
+          matches(
+              r"Expected: throws an exception which matches UnsupportedError +"
+              r"But:  exception \?:<Exception> does not match "
+                  r"UnsupportedError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+
+    test('throwsStateError', () {
+      shouldPass(() { throw new StateError(''); },
+          throwsStateError);
+      shouldFail(() { throw new Exception(); },
+          throwsStateError,
+          matches(
+              r"Expected: throws an exception which matches StateError +"
+              r"But:  exception \?:<Exception> does not match "
+                  r"StateError\."
+              r"Actual: <Closure(: \(dynamic\) => dynamic)?>"));
+    });
+  });
+
+  group('Iterable Matchers', () {
+    test('isEmpty', () {
+      var d = new SimpleIterable(0);
+      var e = new SimpleIterable(1);
+      shouldPass(d, isEmpty);
+      shouldFail(e, isEmpty, "Expected: empty But: was SimpleIterable:[1].");
+    });
+
+    test('contains', () {
+      var d = new SimpleIterable(3);
+      shouldPass(d, contains(2));
+      shouldFail(d, contains(5),
+          "Expected: contains <5> "
+          "But: was SimpleIterable:[3, 2, 1].");
+    });
+  });
+
+  group('Feature Matchers', () {
+    test("Feature Matcher", () {
+      var w = new Widget();
+      w.price = 10;
+      shouldPass(w, new HasPrice(10));
+      shouldPass(w, new HasPrice(greaterThan(0)));
+      shouldFail(w, new HasPrice(greaterThan(10)),
+          "Expected: Widget with a price that is a value greater than <10> "
+          "But: price was <10>. "
+          "Actual: <Instance of 'Widget'>");
+    });
+  });
+}
diff --git a/pkg/unittest/test/pretty_print_minified_test.dart b/pkg/unittest/test/pretty_print_minified_test.dart
new file mode 100644
index 0000000..16c5cd6
--- /dev/null
+++ b/pkg/unittest/test/pretty_print_minified_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This file is for pretty-print tests that rely on the names of various Dart
+// types. These tests normally fail when run in minified dart2js, since the
+// names will be mangled. This version of the file is modified to expect
+// minified names.
+
+import 'dart:collection';
+
+import 'package:unittest/src/pretty_print.dart';
+import 'package:unittest/unittest.dart';
+
+class DefaultToString {}
+
+class CustomToString {
+  String toString() => "string representation";
+}
+
+class _PrivateName {
+  String toString() => "string representation";
+}
+
+class _PrivateNameIterable extends IterableMixin {
+  Iterator get iterator => [1, 2, 3].iterator;
+}
+
+// A regexp fragment matching a minified name.
+final _minifiedName = r"[A-Za-z0-9]{1,3}";
+
+void main() {
+  group('with an object', () {
+    test('with a default [toString]', () {
+      expect(prettyPrint(new DefaultToString()),
+          matches(r"<Instance of '" + _minifiedName + r"'>"));
+    });
+
+    test('with a custom [toString]', () {
+      expect(prettyPrint(new CustomToString()),
+          matches(_minifiedName + r':<string representation>'));
+    });
+
+    test('with a custom [toString] and a private name', () {
+      expect(prettyPrint(new _PrivateName()),
+          matches(_minifiedName + r':<string representation>'));
+    });
+  });
+
+  group('with an iterable', () {
+    test("that's not a list", () {
+      expect(prettyPrint([1, 2, 3, 4].map((n) => n * 2)),
+          matches(_minifiedName + r":\[2, 4, 6, 8\]"));
+    });
+
+    test("that's not a list and has a private name", () {
+      expect(prettyPrint(new _PrivateNameIterable()),
+          matches(_minifiedName + r":\[1, 2, 3\]"));
+    });
+  });
+}
diff --git a/pkg/unittest/test/pretty_print_test.dart b/pkg/unittest/test/pretty_print_test.dart
new file mode 100644
index 0000000..e5cd2e2
--- /dev/null
+++ b/pkg/unittest/test/pretty_print_test.dart
@@ -0,0 +1,181 @@
+// 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/src/pretty_print.dart';
+import 'package:unittest/unittest.dart';
+
+void main() {
+  test('with primitive objects', () {
+    expect(prettyPrint(12), equals('<12>'));
+    expect(prettyPrint(12.13), equals('<12.13>'));
+    expect(prettyPrint(true), equals('<true>'));
+    expect(prettyPrint(null), equals('<null>'));
+    expect(prettyPrint(() => 12),
+        matches(r'<Closure(: \(dynamic\) => dynamic)?>'));
+  });
+
+  group('with a string', () {
+    test('containing simple characters', () {
+      expect(prettyPrint('foo'), equals("'foo'"));
+    });
+
+    test('containing newlines', () {
+      expect(prettyPrint('foo\nbar\nbaz'), equals(
+          "'foo\\n'\n"
+          "  'bar\\n'\n"
+          "  'baz'"));
+    });
+
+    test('containing escapable characters', () {
+      expect(prettyPrint("foo\rbar\tbaz'qux"),
+          equals("'foo\\rbar\\tbaz\\'qux'"));
+    });
+  });
+
+  group('with an iterable', () {
+    test('containing primitive objects', () {
+      expect(prettyPrint([1, true, 'foo']), equals("[1, true, 'foo']"));
+    });
+
+    test('containing a multiline string', () {
+      expect(prettyPrint(['foo', 'bar\nbaz\nbip', 'qux']), equals("[\n"
+          "  'foo',\n"
+          "  'bar\\n'\n"
+          "    'baz\\n'\n"
+          "    'bip',\n"
+          "  'qux'\n"
+          "]"));
+    });
+
+    test("that's under maxLineLength", () {
+      expect(prettyPrint([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxLineLength: 30),
+          equals("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"));
+    });
+
+    test("that's over maxLineLength", () {
+      expect(prettyPrint([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxLineLength: 29),
+          equals("[\n"
+              "  0,\n"
+              "  1,\n"
+              "  2,\n"
+              "  3,\n"
+              "  4,\n"
+              "  5,\n"
+              "  6,\n"
+              "  7,\n"
+              "  8,\n"
+              "  9\n"
+              "]"));
+    });
+
+    test("factors indentation into maxLineLength", () {
+      expect(prettyPrint([
+        "foo\nbar",
+        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
+      ], maxLineLength: 30), equals("[\n"
+          "  'foo\\n'\n"
+          "    'bar',\n"
+          "  [\n"
+          "    0,\n"
+          "    1,\n"
+          "    2,\n"
+          "    3,\n"
+          "    4,\n"
+          "    5,\n"
+          "    6,\n"
+          "    7,\n"
+          "    8,\n"
+          "    9\n"
+          "  ]\n"
+          "]"));
+    });
+
+    test("that's under maxItems", () {
+      expect(prettyPrint([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxItems: 10),
+          equals("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"));
+    });
+
+    test("that's over maxItems", () {
+      expect(prettyPrint([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxItems: 9),
+          equals("[0, 1, 2, 3, 4, 5, 6, 7, ...]"));
+    });
+
+    test("that's recursive", () {
+      var list = [1, 2, 3];
+      list.add(list);
+      expect(prettyPrint(list), equals("[1, 2, 3, (recursive)]"));
+    });
+  });
+
+  group("with a map", () {
+    test('containing primitive objects', () {
+      expect(prettyPrint({'foo': 1, 'bar': true}),
+          equals("{'foo': 1, 'bar': true}"));
+    });
+
+    test('containing a multiline string key', () {
+      expect(prettyPrint({'foo\nbar': 1, 'bar': true}), equals("{\n"
+          "  'foo\\n'\n"
+          "    'bar': 1,\n"
+          "  'bar': true\n"
+          "}"));
+    });
+
+    test('containing a multiline string value', () {
+      expect(prettyPrint({'foo': 'bar\nbaz', 'qux': true}), equals("{\n"
+          "  'foo': 'bar\\n'\n"
+          "    'baz',\n"
+          "  'qux': true\n"
+          "}"));
+    });
+
+    test('containing a multiline string key/value pair', () {
+      expect(prettyPrint({'foo\nbar': 'baz\nqux'}), equals("{\n"
+          "  'foo\\n'\n"
+          "    'bar': 'baz\\n'\n"
+          "    'qux'\n"
+          "}"));
+    });
+
+    test("that's under maxLineLength", () {
+      expect(prettyPrint({'0': 1, '2': 3, '4': 5, '6': 7}, maxLineLength: 32),
+          equals("{'0': 1, '2': 3, '4': 5, '6': 7}"));
+    });
+
+    test("that's over maxLineLength", () {
+      expect(prettyPrint({'0': 1, '2': 3, '4': 5, '6': 7}, maxLineLength: 31),
+          equals("{\n"
+              "  '0': 1,\n"
+              "  '2': 3,\n"
+              "  '4': 5,\n"
+              "  '6': 7\n"
+              "}"));
+    });
+
+    test("factors indentation into maxLineLength", () {
+      expect(prettyPrint(["foo\nbar", {'0': 1, '2': 3, '4': 5, '6': 7}],
+              maxLineLength: 32),
+          equals("[\n"
+              "  'foo\\n'\n"
+              "    'bar',\n"
+              "  {\n"
+              "    '0': 1,\n"
+              "    '2': 3,\n"
+              "    '4': 5,\n"
+              "    '6': 7\n"
+              "  }\n"
+              "]"));
+    });
+
+    test("that's under maxItems", () {
+      expect(prettyPrint({'0': 1, '2': 3, '4': 5, '6': 7}, maxItems: 4),
+          equals("{'0': 1, '2': 3, '4': 5, '6': 7}"));
+    });
+
+    test("that's over maxItems", () {
+      expect(prettyPrint({'0': 1, '2': 3, '4': 5, '6': 7}, maxItems: 3),
+          equals("{'0': 1, '2': 3, ...}"));
+    });
+  });
+}
diff --git a/pkg/unittest/test/pretty_print_unminified_test.dart b/pkg/unittest/test/pretty_print_unminified_test.dart
new file mode 100644
index 0000000..4417bcb
--- /dev/null
+++ b/pkg/unittest/test/pretty_print_unminified_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This file is for pretty-print tests that rely on the names of various Dart
+// types. These tests will fail when run in minified dart2js, since the names
+// will be mangled. A version of this file that works in minified dart2js is in
+// pretty_print_minified_test.dart.
+
+import 'dart:collection';
+
+import 'package:unittest/src/pretty_print.dart';
+import 'package:unittest/unittest.dart';
+
+class DefaultToString {}
+
+class CustomToString {
+  String toString() => "string representation";
+}
+
+class _PrivateName {
+  String toString() => "string representation";
+}
+
+class _PrivateNameIterable extends IterableMixin {
+  Iterator get iterator => [1, 2, 3].iterator;
+}
+
+void main() {
+  group('with an object', () {
+    test('with a default [toString]', () {
+      expect(prettyPrint(new DefaultToString()),
+          equals("<Instance of 'DefaultToString'>"));
+    });
+
+    test('with a custom [toString]', () {
+      expect(prettyPrint(new CustomToString()),
+          equals('CustomToString:<string representation>'));
+    });
+
+    test('with a custom [toString] and a private name', () {
+      expect(prettyPrint(new _PrivateName()),
+          equals('?:<string representation>'));
+    });
+  });
+
+  group('with an iterable', () {
+    test("that's not a list", () {
+      expect(prettyPrint([1, 2, 3, 4].map((n) => n * 2)),
+          equals("MappedListIterable:[2, 4, 6, 8]"));
+    });
+
+    test("that's not a list and has a private name", () {
+      expect(prettyPrint(new _PrivateNameIterable()),
+          equals("?:[1, 2, 3]"));
+    });
+  });
+}
diff --git a/pkg/unittest/test/test_common.dart b/pkg/unittest/test/test_common.dart
new file mode 100644
index 0000000..8631768
--- /dev/null
+++ b/pkg/unittest/test/test_common.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test_common;
+
+import 'dart:collection';
+
+import 'package:unittest/unittest.dart';
+
+class Widget {
+  int price;
+}
+
+class HasPrice extends CustomMatcher {
+  HasPrice(matcher) :
+    super("Widget with a price that is", "price", matcher);
+  featureValueOf(actual) => actual.price;
+}
+
+class SimpleIterable extends IterableBase {
+  int count;
+  SimpleIterable(this.count);
+
+  bool contains(int val) => count < val ? false : true;
+
+  bool any(bool f(element)) {
+    for(var i = 0; i <= count; i++) {
+      if(f(i)) return true;
+    }
+    return false;
+  }
+
+  String toString() => "<[$count]>";
+
+  Iterator get iterator {
+    return new SimpleIterator(count);
+  }
+}
+
+class SimpleIterator implements Iterator {
+  int _count;
+  int _current;
+
+  SimpleIterator(this._count);
+
+  bool moveNext() {
+    if (_count > 0) {
+      _current = _count;
+      _count--;
+      return true;
+    }
+    _current = null;
+    return false;
+  }
+
+  get current => _current;
+}
+
diff --git a/pkg/unittest/test/test_utils.dart b/pkg/unittest/test/test_utils.dart
index d783665..f0b276d 100644
--- a/pkg/unittest/test/test_utils.dart
+++ b/pkg/unittest/test/test_utils.dart
@@ -2,7 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of unittestTests;
+library test_utils;
+
+import 'package:unittest/unittest.dart';
+
+import 'dart:async';
 
 int errorCount;
 String errorString;
@@ -58,3 +62,20 @@
     afterTest();
   }
 }
+
+doesNotThrow() {}
+doesThrow() { throw 'X'; }
+
+class PrefixMatcher extends BaseMatcher {
+  final String _prefix;
+  const PrefixMatcher(this._prefix);
+  bool matches(item, MatchState matchState) {
+    return item is String &&
+        (collapseWhitespace(item)).startsWith(collapseWhitespace(_prefix));
+  }
+
+  Description describe(Description description) =>
+    description.add('a string starting with ').
+        addDescriptionOf(collapseWhitespace(_prefix)).
+        add(' ignoring whitespace');
+}
diff --git a/pkg/unittest/test/unittest_test.dart b/pkg/unittest/test/unittest_test.dart
index 1bbfb18..cc28d9e 100644
--- a/pkg/unittest/test/unittest_test.dart
+++ b/pkg/unittest/test/unittest_test.dart
@@ -405,7 +405,7 @@
   var tests = {
     'single correct test': buildStatusString(1, 0, 0, 'single correct test'),
     'single failing test': buildStatusString(0, 1, 0, 'single failing test',
-        message: 'Expected: <5> but: was <4>.'),
+        message: 'Expected: <5> But: was <4>.'),
     'exception test': buildStatusString(0, 1, 0, 'exception test',
         message: 'Caught Exception: Fail.'),
     'group name test': buildStatusString(2, 0, 0, 'a a::a b b'),
@@ -427,7 +427,7 @@
         message: 'Callback called (2) after test case testOne has already '
                  'been marked as pass.:testTwo:'),
     'middle exception test': buildStatusString(2, 1, 0,
-        'testOne::testTwo:Expected: false but: was <true>.:testThree'),
+        'testOne::testTwo:Expected: false But: was <true>.:testThree'),
     'async setup/teardown test': buildStatusString(2, 0, 3,
         'good setup/good teardown foo1::'
         'good setup/bad teardown foo2:good setup/bad teardown '
@@ -440,13 +440,13 @@
     'test returning future': buildStatusString(2, 4, 0,
         'successful::'
         'error1:Callback called more times than expected (1).:'
-        'fail1:Expected: <false> but: was <true>.:'
+        'fail1:Expected: <false> But: was <true>.:'
         'error2:Callback called more times than expected (1).:'
         'fail2:failure:'
         'foo5'),
     'test returning future using runAsync': buildStatusString(2, 4, 0,
         'successful::'
-        'fail1:Expected: <false> but: was <true>.:'
+        'fail1:Expected: <false> But: was <true>.:'
         'error1:Callback called more times than expected (1).:'
         'fail2:failure:'
         'error2:Callback called more times than expected (1).:'
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 41d71f1..5e5b61a 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -267,6 +267,17 @@
 }
 
 
+static Builtin::BuiltinLibraryId BuiltinId(const char* url) {
+  if (DartUtils::IsDartBuiltinLibURL(url)) {
+    return Builtin::kBuiltinLibrary;
+  }
+  if (DartUtils::IsDartIOLibURL(url)) {
+    return Builtin::kIOLibrary;
+  }
+  return Builtin::kInvalidLibrary;
+}
+
+
 static Dart_Handle CreateSnapshotLibraryTagHandler(Dart_LibraryTag tag,
                                                    Dart_Handle library,
                                                    Dart_Handle url) {
@@ -292,17 +303,36 @@
   const char* mapped_url_string = DartUtils::MapLibraryUrl(url_mapping,
                                                            url_string);
 
+  Builtin::BuiltinLibraryId libraryBuiltinId = BuiltinId(library_url_string);
   if (tag == kCanonicalizeUrl) {
-    // Keep original names for libraries that have a mapping (e.g. dart:io).
     if (mapped_url_string) {
       return url;
     }
+    // Parts of internal libraries are handled internally.
+    if (libraryBuiltinId != Builtin::kInvalidLibrary) {
+      return url;
+    }
     return ResolveUri(library_url_string, url_string);
   }
 
-  if (DartUtils::IsDartIOLibURL(url_string) && mapped_url_string == NULL) {
-    // No url mapping for dart:io. Load original version.
-    return Builtin::LoadAndCheckLibrary(Builtin::kIOLibrary);
+  Builtin::BuiltinLibraryId builtinId = BuiltinId(url_string);
+  if (builtinId != Builtin::kInvalidLibrary) {
+    // Special case for importing a builtin library.
+    if (tag == kImportTag) {
+      return Builtin::LoadAndCheckLibrary(builtinId);
+    }
+    ASSERT(tag == kSourceTag);
+    return Dart_Error("Unable to part '%s' ", url_string);
+  }
+
+  if (libraryBuiltinId != Builtin::kInvalidLibrary) {
+    // Special case for parting sources of a builtin library.
+    if (tag == kSourceTag) {
+      return Dart_LoadSource(
+          library, url, Builtin::PartSource(libraryBuiltinId, url_string));
+    }
+    ASSERT(tag == kImportTag);
+    return Dart_Error("Unable to import '%s' ", url_string);
   }
 
   Dart_Handle resolved_url = url;
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index d10f3ae..3de4c29 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -867,13 +867,12 @@
 
   void done([error]) {
     if (streamCompleter != null) {
-      var tmp = streamCompleter;
-      streamCompleter = null;
       if (error != null) {
-        tmp.completeError(error);
+        streamCompleter.completeError(error);
       } else {
-        tmp.complete(socket);
+        streamCompleter.complete(socket);
       }
+      streamCompleter = null;
     }
   }
 
diff --git a/runtime/embedders/openglui/build_skia.sh b/runtime/embedders/openglui/build_skia.sh
index 03f0f5b..42710a8 100755
--- a/runtime/embedders/openglui/build_skia.sh
+++ b/runtime/embedders/openglui/build_skia.sh
@@ -61,7 +61,7 @@
 
 if [ ${DO_ANDROID} != 0 ] ; then
   echo "Building for Android ${TARGET_ARCH}"
-  curl http://skia.googlecode.com/svn/android/gclient.config -o .gclient
+  curl http://skia.googlecode.com/svn/trunk/platform_tools/android/gclient.config -o .gclient
   gclient sync
 
   export ANDROID_SDK_ROOT=`readlink -f ../android_tools/sdk`
@@ -71,9 +71,10 @@
 
   echo "Using SDK ${ANDROID_SDK_ROOT}"
   if [ ${CLEAN} != 0 ] ; then
-    ../android/bin/android_make -d $TARGET_ARCH -j clean
+    ./platform_tools/android/bin/android_make -d $TARGET_ARCH -j clean
   else
-    env -i BUILDTYPE=$BUILD ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" PATH="${PATH}:${GSUTIL_LOCATION}" ../android/bin/android_make BUILDTYPE=$BUILD -d $TARGET_ARCH -j --debug=j
+    echo env -i BUILDTYPE=$BUILD ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" PATH="${PATH}:${GSUTIL_LOCATION}" ../android/bin/android_make BUILDTYPE=$BUILD -d $TARGET_ARCH -j --debug=j
+    env -i BUILDTYPE=$BUILD ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" PATH="${PATH}:${GSUTIL_LOCATION}" ./platform_tools/android/bin/android_make BUILDTYPE=$BUILD -d $TARGET_ARCH -j --debug=j
   fi
 
 else
diff --git a/runtime/embedders/openglui/openglui_embedder.gypi b/runtime/embedders/openglui/openglui_embedder.gypi
index c3671ee..c67cf90 100644
--- a/runtime/embedders/openglui/openglui_embedder.gypi
+++ b/runtime/embedders/openglui/openglui_embedder.gypi
@@ -50,6 +50,7 @@
               '../../vm/version.h',
               '../../../third_party/android_tools/ndk/sources/android/native_app_glue/android_native_app_glue.h',
               '../../../third_party/android_tools/ndk/sources/android/native_app_glue/android_native_app_glue.c',
+              '../../../third_party/skia/trunk/src/core/SkPaintOptionsAndroid.cpp',
               'android/android_graphics_handler.cc',
               'android/android_graphics_handler.h',
               'android/android_input_handler.h',
@@ -115,6 +116,10 @@
                 '-lgif',
                 '-ljpeg',
                 '-lpng',
+                '-lwebp_dec',
+                '-lwebp_utils',
+                '-lwebp_dsp',
+                '-lwebp_enc',
                 '-lskia_core',
                 '-lskia_effects',
                 '-lskia_gr',
@@ -264,7 +269,8 @@
                 '-lGL',
                 '-lglut',
                 '-lGLU',
-                '-lm'
+                '-lm',
+                '-lwebp'
               ],
             },
             'conditions': [
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 2b1f1c7..dbc6886 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -80,8 +80,8 @@
     Exceptions::ThrowByType(Exceptions::kUnsupported, args);
   }
   const Bigint& big = Bigint::Handle(BigintOperations::NewFromDouble(val));
-  if (BigintOperations::FitsIntoMint(big)) {
-    return Integer::New(BigintOperations::ToMint(big));
+  if (BigintOperations::FitsIntoInt64(big)) {
+    return Integer::New(BigintOperations::ToInt64(big));
   } else {
     return big.raw();
   }
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index d368415..eb8bd93 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -24,7 +24,7 @@
   if (i.IsBigint()) {
     const Bigint& bigint = Bigint::Cast(i);
     return !BigintOperations::FitsIntoSmi(bigint) &&
-        !BigintOperations::FitsIntoMint(bigint);
+        !BigintOperations::FitsIntoInt64(bigint);
   }
   if (i.IsMint()) {
     const Mint& mint = Mint::Cast(i);
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index a0c7711..c279c19 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -68,27 +68,31 @@
   // The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32.
   // http://en.wikipedia.org/wiki/Multiply-with-carry
   // The constant A is selected from "Numerical Recipes 3rd Edition" p.348 B1.
-  int _nextInt32() {
+  void _nextState() {
     var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
     _state[kSTATE_LO] = state & _MASK_32;
     _state[kSTATE_HI] = state >> 32;
-    return _state[kSTATE_LO];
   }
 
   int nextInt(int max) {
-    if (max <= 0 || max > _POW2_32) {
+    // TODO(srdjan): Remove the 'limit' check once optimizing  comparison of
+    // Smi-s with Mint constants.
+    final limit = 0x3FFFFFFF;
+    if (max <= 0 || ((max > limit) && (max > _POW2_32))) {
       throw new ArgumentError("max must be positive and < 2^32:"
                                          " $max");
     }
     if ((max & -max) == max) {
       // Fast case for powers of two.
-      return _nextInt32() & (max - 1);
+      _nextState();
+      return _state[kSTATE_LO] & (max - 1);
     }
 
     var rnd32;
     var result;
     do {
-      rnd32 = _nextInt32();
+      _nextState();
+      rnd32 = _state[kSTATE_LO];
       result = rnd32 % max;
     } while ((rnd32 - result + max) >= _POW2_32);
     return result;
@@ -119,6 +123,7 @@
       _prng = new Random(new DateTime.now().millisecondsSinceEpoch);
     }
     // Trigger the PRNG once to change the internal state.
-    return _prng._nextInt32();
+    _prng._nextState();
+    return _prng._state[kSTATE_LO];
   }
 }
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index ac26d087..a4a3faf 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -17,8 +17,7 @@
 
 DEFINE_NATIVE_ENTRY(Object_cid, 1) {
   const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
-  const Class& cls = Class::Handle(instance.clazz());
-  return Smi::New(cls.id());
+  return Smi::New(instance.GetClassId());
 }
 
 
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index e9f5759..dbe8dc0 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -199,6 +199,43 @@
   String _substringUncheckedNative(int startIndex, int endIndex)
       native "StringBase_substringUnchecked";
 
+  // Checks for one-byte whitespaces only.
+  static bool _isOneByteWhitespace(int codePoint) {
+    return
+      (codePoint == 32) || // Space.
+      ((9 <= codePoint) && (codePoint <= 13)) || // CR, LF, TAB, etc.
+      (codePoint == 0x85) ||  // NEL
+      (codePoint == 0xA0);  // NBSP
+  }
+
+  // Characters with Whitespace property (Unicode 6.2).
+  // 0009..000D    ; White_Space # Cc       <control-0009>..<control-000D>
+  // 0020          ; White_Space # Zs       SPACE
+  // 0085          ; White_Space # Cc       <control-0085>
+  // 00A0          ; White_Space # Zs       NO-BREAK SPACE
+  // 1680          ; White_Space # Zs       OGHAM SPACE MARK
+  // 180E          ; White_Space # Zs       MONGOLIAN VOWEL SEPARATOR
+  // 2000..200A    ; White_Space # Zs       EN QUAD..HAIR SPACE
+  // 2028          ; White_Space # Zl       LINE SEPARATOR
+  // 2029          ; White_Space # Zp       PARAGRAPH SEPARATOR
+  // 202F          ; White_Space # Zs       NARROW NO-BREAK SPACE
+  // 205F          ; White_Space # Zs       MEDIUM MATHEMATICAL SPACE
+  // 3000          ; White_Space # Zs       IDEOGRAPHIC SPACE
+  //
+  // BOM: 0xFEFF
+  static bool _isTwoByteWhitespace(int codePoint) {
+    if (codePoint < 256) return _isOneByteWhitespace(codePoint);
+    return (codePoint == 0x1680) ||
+        (codePoint == 0x180E) ||
+        ((0x2000 <= codePoint) && (codePoint <= 0x200A)) ||
+        (codePoint == 0x2028) ||
+        (codePoint == 0x2029) ||
+        (codePoint == 0x202F) ||
+        (codePoint == 0x205F) ||
+        (codePoint == 0x3000) ||
+        (codePoint == 0xFEFF);
+  }
+
   String trim() {
     final int len = this.length;
     int first = 0;
@@ -510,13 +547,8 @@
 
   int get hashCode native "String_getHashCode";
 
-  // Checks for one-byte whitespaces only.
-  // TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid
-  // whitespaces for one byte strings.
   bool _isWhitespace(int codePoint) {
-    return
-      (codePoint == 32) || // Space.
-      ((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc.
+    return _StringBase._isOneByteWhitespace(codePoint);
   }
 
   String _substringUncheckedNative(int startIndex, int endIndex)
@@ -568,30 +600,8 @@
         "_TwoByteString can only be allocated by the VM");
   }
 
-  // Checks for one-byte whitespaces only.
-  // TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid
-  // whitespaces. Add checking for multi-byte whitespace codepoints.
   bool _isWhitespace(int codePoint) {
-    return
-      (codePoint == 32) || // Space.
-      ((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc.
-  }
-}
-
-
-class _FourByteString extends _StringBase implements String {
-  factory _FourByteString._uninstantiable() {
-    throw new UnsupportedError(
-        "_FourByteString can only be allocated by the VM");
-  }
-
-  // Checks for one-byte whitespaces only.
-  // TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid
-  // whitespaces. Add checking for multi-byte whitespace codepoints.
-  bool _isWhitespace(int codePoint) {
-    return
-      (codePoint == 32) || // Space.
-      ((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc.
+    return _StringBase._isTwoByteWhitespace(codePoint);
   }
 }
 
@@ -602,13 +612,8 @@
         "_ExternalOneByteString can only be allocated by the VM");
   }
 
-  // Checks for one-byte whitespaces only.
-  // TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid
-  // whitespaces for one byte strings.
   bool _isWhitespace(int codePoint) {
-    return
-      (codePoint == 32) || // Space.
-      ((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc.
+    return _StringBase._isOneByteWhitespace(codePoint);
   }
 }
 
@@ -619,13 +624,8 @@
         "_ExternalTwoByteString can only be allocated by the VM");
   }
 
-  // Checks for one-byte whitespaces only.
-  // TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid
-  // whitespaces. Add checking for multi-byte whitespace codepoints.
   bool _isWhitespace(int codePoint) {
-    return
-      (codePoint == 32) || // Space.
-      ((9 <= codePoint) && (codePoint <= 13)); // CR, LF, TAB, etc.
+    return _StringBase._isTwoByteWhitespace(codePoint);
   }
 }
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 5787071..a79042d 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -81,3 +81,8 @@
 cc/CustomIsolates: Skip # Bug 6890
 cc/NewNativePort: Skip # Bug 6890
 cc/RunLoop_ExceptionParent: Skip # Bug 6890
+
+[ $compiler == dartanalyzer ]
+# has compilation error, as designed
+dart/isolate_mirror_local_test: fail
+
diff --git a/runtime/vm/bigint_operations.cc b/runtime/vm/bigint_operations.cc
index 118a836..709baa2 100644
--- a/runtime/vm/bigint_operations.cc
+++ b/runtime/vm/bigint_operations.cc
@@ -605,7 +605,7 @@
 }
 
 
-bool BigintOperations::FitsIntoMint(const Bigint& bigint) {
+bool BigintOperations::FitsIntoInt64(const Bigint& bigint) {
   intptr_t bigint_length = bigint.Length();
   if (bigint_length == 0) {
     return true;
@@ -663,11 +663,11 @@
 }
 
 
-int64_t BigintOperations::ToMint(const Bigint& bigint) {
+int64_t BigintOperations::ToInt64(const Bigint& bigint) {
   if (bigint.IsZero()) {
     return 0;
   }
-  ASSERT(FitsIntoMint(bigint));
+  ASSERT(FitsIntoInt64(bigint));
   int64_t value = AbsToUint64(bigint);
   if (bigint.IsNegative()) {
     value = -value;
diff --git a/runtime/vm/bigint_operations.h b/runtime/vm/bigint_operations.h
index e9c31a2..892ee6c 100644
--- a/runtime/vm/bigint_operations.h
+++ b/runtime/vm/bigint_operations.h
@@ -62,8 +62,8 @@
   static bool FitsIntoSmi(const Bigint& bigint);
   static RawSmi* ToSmi(const Bigint& bigint);
 
-  static bool FitsIntoMint(const Bigint& bigint);
-  static int64_t ToMint(const Bigint& bigint);
+  static bool FitsIntoInt64(const Bigint& bigint);
+  static int64_t ToInt64(const Bigint& bigint);
 
   static bool FitsIntoUint64(const Bigint& bigint);
   static bool AbsFitsIntoUint64(const Bigint& bigint);
diff --git a/runtime/vm/bigint_operations_test.cc b/runtime/vm/bigint_operations_test.cc
index 0c141a1..b43ff90 100644
--- a/runtime/vm/bigint_operations_test.cc
+++ b/runtime/vm/bigint_operations_test.cc
@@ -79,45 +79,45 @@
 
   const Bigint& one = Bigint::Handle(BigintOperations::NewFromInt64(1));
   big = BigintOperations::NewFromInt64(kMinInt64);
-  EXPECT(BigintOperations::FitsIntoMint(big));
-  int64_t back = BigintOperations::ToMint(big);
+  EXPECT(BigintOperations::FitsIntoInt64(big));
+  int64_t back = BigintOperations::ToInt64(big);
   EXPECT_EQ(kMinInt64, back);
 
   big = BigintOperations::Subtract(big, one);
-  EXPECT(!BigintOperations::FitsIntoMint(big));
+  EXPECT(!BigintOperations::FitsIntoInt64(big));
 
   big = BigintOperations::NewFromInt64(kMaxInt64);
-  EXPECT(BigintOperations::FitsIntoMint(big));
-  back = BigintOperations::ToMint(big);
+  EXPECT(BigintOperations::FitsIntoInt64(big));
+  back = BigintOperations::ToInt64(big);
   EXPECT_EQ(kMaxInt64, back);
 
   big = BigintOperations::Add(big, one);
-  EXPECT(!BigintOperations::FitsIntoMint(big));
+  EXPECT(!BigintOperations::FitsIntoInt64(big));
 }
 
 
 TEST_CASE(BigintUint64) {
   const Bigint& one = Bigint::Handle(BigintOperations::NewFromUint64(1));
-  EXPECT(BigintOperations::FitsIntoMint(one));
+  EXPECT(BigintOperations::FitsIntoInt64(one));
   EXPECT(BigintOperations::FitsIntoUint64(one));
 
   Bigint& big = Bigint::Handle(BigintOperations::NewFromUint64(kMaxUint64));
-  EXPECT(!BigintOperations::FitsIntoMint(big));
+  EXPECT(!BigintOperations::FitsIntoInt64(big));
   EXPECT(BigintOperations::FitsIntoUint64(big));
 
   uint64_t back = BigintOperations::ToUint64(big);
   EXPECT_EQ(kMaxUint64, back);
 
   big = BigintOperations::Add(big, one);
-  EXPECT(!BigintOperations::FitsIntoMint(big));
+  EXPECT(!BigintOperations::FitsIntoInt64(big));
   EXPECT(!BigintOperations::FitsIntoUint64(big));
 
   big = BigintOperations::Subtract(big, one);
-  EXPECT(!BigintOperations::FitsIntoMint(big));
+  EXPECT(!BigintOperations::FitsIntoInt64(big));
   EXPECT(BigintOperations::FitsIntoUint64(big));
 
   big = BigintOperations::ShiftRight(big, 1);
-  EXPECT(BigintOperations::FitsIntoMint(big));
+  EXPECT(BigintOperations::FitsIntoInt64(big));
   EXPECT(BigintOperations::FitsIntoUint64(big));
 }
 
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 673df7a..aa843a5 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -115,7 +115,7 @@
   ASSERT(isolate != NULL);
   HANDLESCOPE(isolate);
   ObjectStore* object_store = isolate->object_store();
-  const Error& error = Error::Handle(object_store->sticky_error());
+  const Error& error = Error::Handle(isolate, object_store->sticky_error());
   if (!error.IsNull()) {
     return false;
   }
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 8d74e7b..fb7a9e8 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -893,13 +893,12 @@
       Function::Handle(target_code.function());
   ASSERT(!target_function.IsNull());
   if (args.length() == 1) {
-    ic_data.AddReceiverCheck(Class::Handle(args[0]->clazz()).id(),
-                             target_function);
+    ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function);
   } else {
     GrowableArray<intptr_t> class_ids(args.length());
     ASSERT(ic_data.num_args_tested() == args.length());
     for (intptr_t i = 0; i < args.length(); i++) {
-      class_ids.Add(Class::Handle(args[i]->clazz()).id());
+      class_ids.Add(args[i]->GetClassId());
     }
     ic_data.AddCheck(class_ids, target_function);
   }
@@ -921,7 +920,7 @@
           args.length(),
           caller_frame->pc(),
           Class::Handle(receiver.clazz()).ToCString(),
-          Class::Handle(receiver.clazz()).id(),
+          receiver.GetClassId(),
           target_function.ToCString());
     }
   }
@@ -1088,8 +1087,8 @@
   ASSERT(!target_function.IsNull());
   GrowableArray<intptr_t> class_ids(kNumArguments);
   ASSERT(ic_data.num_args_tested() == kNumArguments);
-  class_ids.Add(Class::Handle(receiver.clazz()).id());
-  class_ids.Add(Class::Handle(arg1.clazz()).id());
+  class_ids.Add(receiver.GetClassId());
+  class_ids.Add(arg1.GetClassId());
   ic_data.AddCheck(class_ids, target_function);
 }
 
@@ -1771,7 +1770,7 @@
   const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
   const Object& value = Object::Handle(arguments.ArgAt(1));
 
-  field.UpdateCid(Class::Handle(value.clazz()).id());
+  field.UpdateCid(value.GetClassId());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 696dbb2..764dfbc 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -121,7 +121,6 @@
   bool is_compiled = false;
   Isolate* isolate = Isolate::Current();
   HANDLESCOPE(isolate);
-  ASSERT(isolate->ic_data_array() == Array::null());  // Must be reset to null.
   const intptr_t prev_deopt_id = isolate->deopt_id();
   isolate->set_deopt_id(0);
   LongJump* old_base = isolate->long_jump_base();
@@ -135,6 +134,7 @@
       TimerScope timer(FLAG_compiler_stats,
                        &CompilerStats::graphbuilder_timer,
                        isolate);
+      Array& ic_data_array = Array::Handle();
       if (optimized) {
         ASSERT(parsed_function.function().HasCode());
         // Extract type feedback before the graph is built, as the graph
@@ -145,13 +145,14 @@
             FLAG_deoptimization_counter_threshold) {
           const Code& unoptimized_code =
               Code::Handle(parsed_function.function().unoptimized_code());
-          isolate->set_ic_data_array(
-              unoptimized_code.ExtractTypeFeedbackArray());
+          ic_data_array = unoptimized_code.ExtractTypeFeedbackArray();
         }
       }
 
       // Build the flow graph.
-      FlowGraphBuilder builder(parsed_function, NULL);  // NULL = not inlining.
+      FlowGraphBuilder builder(parsed_function,
+                               ic_data_array,
+                               NULL);  // NULL = not inlining.
       flow_graph = builder.BuildGraph();
     }
 
@@ -396,7 +397,6 @@
     is_compiled = false;
   }
   // Reset global isolate state.
-  isolate->set_ic_data_array(Array::null());
   isolate->set_long_jump_base(old_base);
   isolate->set_deopt_id(prev_deopt_id);
   return is_compiled;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index aa6738a..0707a20 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1326,7 +1326,7 @@
   if (int_obj.IsNull()) {
     RETURN_TYPE_ERROR(isolate, integer, Integer);
   }
-  ASSERT(!BigintOperations::FitsIntoMint(Bigint::Cast(int_obj)));
+  ASSERT(!BigintOperations::FitsIntoInt64(Bigint::Cast(int_obj)));
   *fits = false;
   return Api::Success(isolate);
 }
@@ -1402,8 +1402,8 @@
     return Api::Success(isolate);
   } else {
     const Bigint& bigint = Bigint::Cast(int_obj);
-    if (BigintOperations::FitsIntoMint(bigint)) {
-      *value = BigintOperations::ToMint(bigint);
+    if (BigintOperations::FitsIntoInt64(bigint)) {
+      *value = BigintOperations::ToInt64(bigint);
       return Api::Success(isolate);
     }
   }
@@ -1949,7 +1949,7 @@
       // Check for a non-canonical Mint range value.
       ASSERT(retval.IsBigint());
       const Bigint& bigint = Bigint::Handle();
-      if (BigintOperations::FitsIntoMint(bigint)) {
+      if (BigintOperations::FitsIntoInt64(bigint)) {
         int64_t bigint_value = bigint.AsInt64Value();
         if (bigint_value >= kIntptrMin && bigint_value <= kIntptrMax) {
           *len = static_cast<intptr_t>(bigint_value);
@@ -3934,10 +3934,14 @@
     RETURN_TYPE_ERROR(isolate, name, String);
   }
 
-  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(container));
-
+  // Finalize all classes.
+  Dart_Handle state = Api::CheckIsolateState(isolate);
+  if (::Dart_IsError(state)) {
+    return state;
+  }
   Field& field = Field::Handle(isolate);
   Function& getter = Function::Handle(isolate);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(container));
   if (obj.IsNull()) {
     return Api::NewError("%s expects argument 'container' to be non-null.",
                          CURRENT_FUNC);
@@ -3973,11 +3977,6 @@
     return Api::NewHandle(isolate, DartEntry::InvokeFunction(getter, args));
 
   } else if (obj.IsClass()) {
-    // Finalize all classes.
-    Dart_Handle state = Api::CheckIsolateState(isolate);
-    if (::Dart_IsError(state)) {
-      return state;
-    }
     // To access a static field we may need to use the Field or the
     // getter Function.
     const Class& cls = Class::Cast(obj);
@@ -4000,8 +3999,6 @@
     }
 
   } else if (obj.IsLibrary()) {
-    // TODO(turnidge): Do we need to call CheckIsolateState here?
-
     // To access a top-level we may need to use the Field or the
     // getter Function.  The getter function may either be in the
     // library or in the field's owner class, depending.
@@ -4061,6 +4058,11 @@
   Instance& value_instance = Instance::Handle(isolate);
   value_instance ^= value_obj.raw();
 
+  // Finalize all classes.
+  Dart_Handle state = Api::CheckIsolateState(isolate);
+  if (::Dart_IsError(state)) {
+    return state;
+  }
   Field& field = Field::Handle(isolate);
   Function& setter = Function::Handle(isolate);
   const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(container));
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 047df63..6d8626a 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3516,6 +3516,53 @@
 }
 
 
+TEST_CASE(GetField_CheckIsolate) {
+  const char* kScriptChars =
+      "class TestClass  {\n"
+      "  static int fld2 = 11;\n"
+      "  static void testMain() {\n"
+      "  }\n"
+      "}\n";
+  Dart_Handle result;
+  int64_t value = 0;
+
+  // Create a test library and Load up a test script in it.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_Handle cls = Dart_GetClass(lib, NewString("TestClass"));
+  EXPECT_VALID(cls);
+
+  result = Dart_GetField(cls, NewString("fld2"));
+  EXPECT_VALID(result);
+  result = Dart_IntegerToInt64(result, &value);
+  EXPECT_EQ(11, value);
+}
+
+
+TEST_CASE(SetField_CheckIsolate) {
+  const char* kScriptChars =
+      "class TestClass  {\n"
+      "  static int fld2 = 11;\n"
+      "  static void testMain() {\n"
+      "  }\n"
+      "}\n";
+  Dart_Handle result;
+  int64_t value = 0;
+
+  // Create a test library and Load up a test script in it.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_Handle cls = Dart_GetClass(lib, NewString("TestClass"));
+  EXPECT_VALID(cls);
+
+  result = Dart_SetField(cls, NewString("fld2"), Dart_NewInteger(13));
+  EXPECT_VALID(result);
+
+  result = Dart_GetField(cls, NewString("fld2"));
+  EXPECT_VALID(result);
+  result = Dart_IntegerToInt64(result, &value);
+  EXPECT_EQ(13, value);
+}
+
+
 TEST_CASE(New) {
   const char* kScriptChars =
       "class MyClass {\n"
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 1b9e361..89ebb10 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -176,17 +176,17 @@
 
 
 intptr_t ArgumentsDescriptor::count_offset() {
-  return Array::data_offset() + (kCountIndex * kWordSize);
+  return Array::element_offset(kCountIndex);
 }
 
 
 intptr_t ArgumentsDescriptor::positional_count_offset() {
-  return Array::data_offset() + (kPositionalCountIndex * kWordSize);
+  return Array::element_offset(kPositionalCountIndex);
 }
 
 
 intptr_t ArgumentsDescriptor::first_named_entry_offset() {
-  return Array::data_offset() + (kFirstNamedEntryIndex * kWordSize);
+  return Array::element_offset(kFirstNamedEntryIndex);
 }
 
 
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index a470b0a..0d80af0 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -779,7 +779,6 @@
       src_breakpoints_(NULL),
       code_breakpoints_(NULL),
       resume_action_(kContinue),
-      last_bpt_line_(-1),
       ignore_breakpoints_(false),
       exc_pause_info_(kNoPauseOnExceptions) {
 }
@@ -1024,8 +1023,6 @@
   if (!ShouldPauseOnException(stack_trace, exc)) {
     return;
   }
-  // No single-stepping possible after this pause event.
-  last_bpt_line_ = -1;
   ASSERT(stack_trace_ == NULL);
   stack_trace_ = stack_trace;
   ASSERT(obj_cache_ == NULL);
@@ -1532,31 +1529,19 @@
               top_frame->pc());
   }
 
-  if (!bpt->IsInternal()) {
-    // This is a user-defined breakpoint so we call the breakpoint
-    // callback even if it is on the same line as the previous breakpoint.
-    last_bpt_line_ = -1;
-  }
-
-  bool notify_frontend =
-    (last_bpt_line_ < 0) || (last_bpt_line_ != bpt->LineNumber());
-
-  if (notify_frontend) {
-    resume_action_ = kContinue;
-    if (event_handler_ != NULL) {
-      ASSERT(stack_trace_ == NULL);
-      ASSERT(obj_cache_ == NULL);
-      obj_cache_ = new RemoteObjectCache(64);
-      stack_trace_ = stack_trace;
-      DebuggerEvent event;
-      event.type = kBreakpointReached;
-      ASSERT(stack_trace->Length() > 0);
-      event.top_frame = stack_trace->ActivationFrameAt(0);
-      (*event_handler_)(&event);
-      stack_trace_ = NULL;
-      obj_cache_ = NULL;  // Remote object cache is zone allocated.
-      last_bpt_line_ = bpt->LineNumber();
-    }
+  resume_action_ = kContinue;
+  if (event_handler_ != NULL) {
+    ASSERT(stack_trace_ == NULL);
+    ASSERT(obj_cache_ == NULL);
+    obj_cache_ = new RemoteObjectCache(64);
+    stack_trace_ = stack_trace;
+    DebuggerEvent event;
+    event.type = kBreakpointReached;
+    ASSERT(stack_trace->Length() > 0);
+    event.top_frame = stack_trace->ActivationFrameAt(0);
+    (*event_handler_)(&event);
+    stack_trace_ = NULL;
+    obj_cache_ = NULL;  // Remote object cache is zone allocated.
   }
 
   Function& currently_instrumented_func = Function::Handle();
@@ -1656,7 +1641,6 @@
 
   if (func_to_instrument.IsNull() ||
       (func_to_instrument.raw() != currently_instrumented_func.raw())) {
-    last_bpt_line_ = -1;
     RemoveInternalBreakpoints();  // *bpt is now invalid.
     if (!func_to_instrument.IsNull()) {
       InstrumentForStepping(func_to_instrument);
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index d184d3b..9df08bd 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -373,10 +373,6 @@
   // Tells debugger what to do when resuming execution after a breakpoint.
   ResumeAction resume_action_;
 
-  // If >= 0, last_bpt_line contains the line number of the last breakpoint
-  // location for which the breakpoint callback function was called.
-  intptr_t last_bpt_line_;
-
   // Do not call back to breakpoint handler if this flag is set.
   // Effectively this means ignoring breakpoints. Set when Dart code may
   // be run as a side effect of getting values of fields.
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 43a80d4..123db7c 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -492,7 +492,7 @@
   DARTSCOPE(isolate);
   UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
   CHECK_NOT_NULL(class_id);
-  *class_id = Class::Handle(obj.clazz()).id();
+  *class_id = obj.GetClassId();
   return Api::True(isolate);
 }
 
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index a10bbeb..6810a61b 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -361,10 +361,12 @@
           "f1",
         "foo",
           "X.X.",
+          "X.X.",
         "foo",
           "X.kvmk",
             "f2",
           "X.kvmk",
+          "X.kvmk",
         "foo",
       "main"
   };
@@ -418,11 +420,7 @@
   LoadScript(kScriptChars);
   Dart_SetPausedEventHandler(&TestStepIntoHandler);
 
-  // Set a breakpoint in function f1, then repeatedly step out until
-  // we get to main. We should see one breakpoint each in f1,
-  // foo, main, but not in f2.
   SetBreakpointAtEntry("", "main");
-
   breakpoint_hit = false;
   breakpoint_hit_counter = 0;
   Dart_Handle retval = Invoke("main");
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index bd43c7a..d27f76c 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -42,8 +42,10 @@
 
 
 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function,
+                                   const Array& ic_data_array,
                                    InlineExitCollector* exit_collector)
   : parsed_function_(parsed_function),
+    ic_data_array_(ic_data_array),
     num_copied_params_(parsed_function.num_copied_params()),
     // All parameters are copied if any parameter is.
     num_non_copied_params_((num_copied_params_ == 0)
@@ -926,7 +928,8 @@
                                                   node->kind(),
                                                   arguments,
                                                   Array::ZoneHandle(),
-                                                  2);
+                                                  2,
+                                                  owner()->ic_data_array());
   ReturnDefinition(call);
 }
 
@@ -1168,7 +1171,8 @@
       node->kind(),
       arguments,
       Array::ZoneHandle(),  // No argument names.
-      kNumArgsChecked);
+      kNumArgsChecked,
+      owner()->ic_data_array());
   ReturnDefinition(call);
 }
 
@@ -1237,7 +1241,8 @@
         node->kind(),
         arguments,
         Array::ZoneHandle(),  // No argument names.
-        kNumArgsChecked);
+        kNumArgsChecked,
+        owner()->ic_data_array());
     ReturnDefinition(call);
   }
 }
@@ -1282,7 +1287,8 @@
           node->token_pos(),
           Token::kEQ,
           for_left_value.value(),
-          for_right_value.value());
+          for_right_value.value(),
+          owner()->ic_data_array());
       if (node->kind() == Token::kEQ) {
         ReturnDefinition(comp);
       } else {
@@ -1295,7 +1301,8 @@
           node->token_pos(),
           node->kind(),
           for_left_value.value(),
-          for_right_value.value());
+          for_right_value.value(),
+          owner()->ic_data_array());
       ReturnDefinition(comp);
     }
     return;
@@ -1310,7 +1317,8 @@
   RelationalOpInstr* comp = new RelationalOpInstr(node->token_pos(),
                                                   node->kind(),
                                                   for_left_value.value(),
-                                                  for_right_value.value());
+                                                  for_right_value.value(),
+                                                  owner()->ic_data_array());
   ReturnDefinition(comp);
 }
 
@@ -1345,7 +1353,8 @@
                             node->kind(),
                             arguments,
                             Array::ZoneHandle(),
-                            1);
+                            1,
+                            owner()->ic_data_array());
   ReturnDefinition(call);
 }
 
@@ -1913,7 +1922,9 @@
   InstanceCallInstr* call = new InstanceCallInstr(
       node->token_pos(),
       node->function_name(), Token::kILLEGAL, arguments,
-      node->arguments()->names(), 1);
+      node->arguments()->names(),
+      1,
+      owner()->ic_data_array());
   ReturnDefinition(call);
 }
 
@@ -2017,32 +2028,37 @@
 
   // In checked mode, if the type arguments are uninstantiated, they may need to
   // be checked against declared bounds at run time.
-  Definition* allocate_comp = NULL;
+  Definition* allocation = NULL;
   if (FLAG_enable_type_checks &&
       requires_type_arguments &&
       !node->type_arguments().IsNull() &&
       !node->type_arguments().IsInstantiated() &&
       node->type_arguments().IsBounded()) {
-    Value* type_arguments = NULL;
-    Value* instantiator = NULL;
-    BuildConstructorTypeArguments(node, &type_arguments, &instantiator, NULL);
+    ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments =
+        new ZoneGrowableArray<PushArgumentInstr*>(4);
+    // Argument 1: Empty argument slot for return value.
+    Value* null_val = Bind(new ConstantInstr(Object::ZoneHandle()));
+    allocate_arguments->Add(PushArgument(null_val));
+    // Argument 2: Class.
+    Value* cls_val =
+        Bind(new ConstantInstr(Class::ZoneHandle(node->constructor().Owner())));
+    allocate_arguments->Add(PushArgument(cls_val));
+    // Build arguments 3 and 4.
+    BuildConstructorTypeArguments(node, allocate_arguments);
 
     // The uninstantiated type arguments cannot be verified to be within their
     // bounds at compile time, so verify them at runtime.
-    allocate_comp = new AllocateObjectWithBoundsCheckInstr(node,
-                                                           type_arguments,
-                                                           instantiator);
+    allocation = new AllocateObjectWithBoundsCheckInstr(node);
   } else {
     ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments =
         new ZoneGrowableArray<PushArgumentInstr*>();
-
     if (requires_type_arguments) {
-      BuildConstructorTypeArguments(node, NULL, NULL, allocate_arguments);
+      BuildConstructorTypeArguments(node, allocate_arguments);
     }
 
-    allocate_comp = new AllocateObjectInstr(node, allocate_arguments);
+    allocation = new AllocateObjectInstr(node, allocate_arguments);
   }
-  return Bind(allocate_comp);
+  return Bind(allocation);
 }
 
 
@@ -2249,73 +2265,69 @@
 
 void EffectGraphVisitor::BuildConstructorTypeArguments(
     ConstructorCallNode* node,
-    Value** type_arguments,
-    Value** instantiator,
     ZoneGrowableArray<PushArgumentInstr*>* call_arguments) {
   const Class& cls = Class::ZoneHandle(node->constructor().Owner());
   ASSERT(cls.HasTypeArguments() && !node->constructor().IsFactory());
   if (node->type_arguments().IsNull() ||
       node->type_arguments().IsInstantiated()) {
     Value* type_arguments_val = Bind(new ConstantInstr(node->type_arguments()));
-    if (call_arguments != NULL) {
-      ASSERT(type_arguments == NULL);
-      call_arguments->Add(PushArgument(type_arguments_val));
-    } else {
-      ASSERT(type_arguments != NULL);
-      *type_arguments = type_arguments_val;
-    }
+    call_arguments->Add(PushArgument(type_arguments_val));
 
     // No instantiator required.
     Value* instantiator_val = Bind(new ConstantInstr(
         Smi::ZoneHandle(Smi::New(StubCode::kNoInstantiator))));
-    if (call_arguments != NULL) {
-      ASSERT(instantiator == NULL);
-      call_arguments->Add(PushArgument(instantiator_val));
-    } else {
-      ASSERT(instantiator != NULL);
-      *instantiator = instantiator_val;
-    }
+    call_arguments->Add(PushArgument(instantiator_val));
     return;
   }
+
   // The type arguments are uninstantiated. We use expression_temp_var to save
-  // the instantiator type arguments becuase they have two uses.
+  // the instantiator type arguments because they have two uses.
   ASSERT(owner()->parsed_function().expression_temp_var() != NULL);
   const LocalVariable& temp = *owner()->parsed_function().expression_temp_var();
   const Class& instantiator_class = Class::Handle(
       owner()->parsed_function().function().Owner());
-  Value* instantiator_type_arguments = BuildInstantiatorTypeArguments(
+  Value* type_arguments_val = BuildInstantiatorTypeArguments(
       node->token_pos(), instantiator_class, NULL);
-  Value* stored_instantiator =
-      Bind(BuildStoreTemp(temp, instantiator_type_arguments));
 
-  Value* type_arguments_val = Bind(
-      new ExtractConstructorTypeArgumentsInstr(
-          node->token_pos(),
-          node->type_arguments(),
-          instantiator_class,
-          stored_instantiator));
+  const bool use_instantiator_type_args =
+      node->type_arguments().IsUninstantiatedIdentity() ||
+      node->type_arguments().CanShareInstantiatorTypeArguments(
+          instantiator_class);
 
-  if (call_arguments != NULL) {
-    ASSERT(type_arguments == NULL);
-    call_arguments->Add(PushArgument(type_arguments_val));
-  } else {
-    ASSERT(type_arguments != NULL);
-    *type_arguments = type_arguments_val;
+  if (!use_instantiator_type_args) {
+    const intptr_t len = node->type_arguments().Length();
+    if (node->type_arguments().IsRawInstantiatedRaw(len)) {
+      type_arguments_val =
+          Bind(BuildStoreTemp(temp, type_arguments_val));
+      type_arguments_val = Bind(
+          new ExtractConstructorTypeArgumentsInstr(
+              node->token_pos(),
+              node->type_arguments(),
+              instantiator_class,
+              type_arguments_val));
+    } else {
+      Do(BuildStoreTemp(temp, type_arguments_val));
+      type_arguments_val = Bind(new ConstantInstr(node->type_arguments()));
+    }
   }
+  call_arguments->Add(PushArgument(type_arguments_val));
 
-  Value* load_instantiator = Bind(BuildLoadLocal(temp));
-  Value* instantiator_val =
-      Bind(new ExtractConstructorInstantiatorInstr(node,
-                                                   instantiator_class,
-                                                   load_instantiator));
-
-  if (call_arguments != NULL) {
-    ASSERT(instantiator == NULL);
-    call_arguments->Add(PushArgument(instantiator_val));
+  Value* instantiator_val = NULL;
+  if (!use_instantiator_type_args) {
+    instantiator_val = Bind(BuildLoadLocal(temp));
+    const intptr_t len = node->type_arguments().Length();
+    if (node->type_arguments().IsRawInstantiatedRaw(len)) {
+      instantiator_val =
+          Bind(new ExtractConstructorInstantiatorInstr(node,
+                                                       instantiator_class,
+                                                       instantiator_val));
+    }
   } else {
-    ASSERT(instantiator != NULL);
-    *instantiator = instantiator_val;
+    // No instantiator required.
+    instantiator_val = Bind(new ConstantInstr(
+        Smi::ZoneHandle(Smi::New(StubCode::kNoInstantiator))));
   }
+  call_arguments->Add(PushArgument(instantiator_val));
 }
 
 
@@ -2357,8 +2369,12 @@
   const String& name =
       String::ZoneHandle(Field::GetterSymbol(node->field_name()));
   InstanceCallInstr* call = new InstanceCallInstr(
-      node->token_pos(), name, Token::kGET,
-      arguments, Array::ZoneHandle(), 1);
+      node->token_pos(),
+      name,
+      Token::kGET,
+      arguments, Array::ZoneHandle(),
+      1,
+      owner()->ic_data_array());
   ReturnDefinition(call);
 }
 
@@ -2397,7 +2413,8 @@
                                                   Token::kSET,
                                                   arguments,
                                                   Array::ZoneHandle(),
-                                                  2);  // Checked arg count.
+                                                  2,  // Checked arg count.
+                                                  owner()->ic_data_array());
   ReturnDefinition(call);
 }
 
@@ -2413,7 +2430,8 @@
                            Token::kSET,
                            arguments,
                            Array::ZoneHandle(),
-                           2));  // Checked argument count.
+                           2,  // Checked argument count.
+                           owner()->ic_data_array()));
   ReturnDefinition(BuildLoadExprTemp());
 }
 
@@ -2778,7 +2796,8 @@
                                                     Token::kINDEX,
                                                     arguments,
                                                     Array::ZoneHandle(),
-                                                    checked_argument_count);
+                                                    checked_argument_count,
+                                                    owner()->ic_data_array());
     ReturnDefinition(load);
   }
 }
@@ -2877,7 +2896,8 @@
                               Token::kASSIGN_INDEX,
                               arguments,
                               Array::ZoneHandle(),
-                              checked_argument_count);
+                              checked_argument_count,
+                              owner()->ic_data_array());
     if (result_is_needed) {
       Do(store);
       return BuildLoadExprTemp();
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 950224f..59a752d 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -102,11 +102,13 @@
  public:
   // The inlining context is NULL if not inlining.
   FlowGraphBuilder(const ParsedFunction& parsed_function,
+                   const Array& ic_data_array,
                    InlineExitCollector* exit_collector);
 
   FlowGraph* BuildGraph();
 
   const ParsedFunction& parsed_function() const { return parsed_function_; }
+  const Array& ic_data_array() const { return ic_data_array_; }
 
   void Bailout(const char* reason);
 
@@ -147,6 +149,7 @@
   }
 
   const ParsedFunction& parsed_function_;
+  const Array& ic_data_array_;
 
   const intptr_t num_copied_params_;
   const intptr_t num_non_copied_params_;
@@ -263,8 +266,6 @@
   // May be called only if allocating an object of a parameterized class.
   void BuildConstructorTypeArguments(
       ConstructorCallNode* node,
-      Value** type_arguments,
-      Value** instantiator,
       ZoneGrowableArray<PushArgumentInstr*>* call_arguments);
 
   void BuildTypecheckPushArguments(
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 7b0e38b..a5d50b1 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -219,7 +219,7 @@
       continue;
     }
 
-    entry->PrepareEntry(this);
+    entry->EmitNativeCode(this);
     // Compile all successors until an exit, branch, or a block entry.
     for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
       Instruction* instr = it.Current();
@@ -338,9 +338,10 @@
 void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id,
                                             intptr_t token_pos) {
   ASSERT(is_optimizing());
-  CompilerDeoptInfo* info = new CompilerDeoptInfo(deopt_id, kDeoptAtCall);
-  ASSERT(pending_deoptimization_env_ != NULL);
-  info->set_deoptimization_env(pending_deoptimization_env_);
+  CompilerDeoptInfo* info =
+      new CompilerDeoptInfo(deopt_id,
+                            kDeoptAtCall,
+                            pending_deoptimization_env_);
   info->set_pc_offset(assembler()->CodeSize());
   deopt_infos_.Add(info);
 }
@@ -399,11 +400,11 @@
 
 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id,
                                        DeoptReasonId reason) {
-  CompilerDeoptInfoWithStub* stub =
-      new CompilerDeoptInfoWithStub(deopt_id, reason);
   ASSERT(is_optimizing_);
-  ASSERT(pending_deoptimization_env_ != NULL);
-  stub->set_deoptimization_env(pending_deoptimization_env_);
+  CompilerDeoptInfoWithStub* stub =
+      new CompilerDeoptInfoWithStub(deopt_id,
+                                    reason,
+                                    pending_deoptimization_env_);
   deopt_infos_.Add(stub);
   return stub->entry_label();
 }
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index f301879..0cb7843 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -107,11 +107,15 @@
 // For deoptimization before instruction use class CompilerDeoptInfoWithStub.
 class CompilerDeoptInfo : public ZoneAllocated {
  public:
-  CompilerDeoptInfo(intptr_t deopt_id, DeoptReasonId reason)
+  CompilerDeoptInfo(intptr_t deopt_id,
+                    DeoptReasonId reason,
+                    Environment* deopt_env)
       : pc_offset_(-1),
         deopt_id_(deopt_id),
         reason_(reason),
-        deoptimization_env_(NULL) {}
+        deopt_env_(deopt_env) {
+    ASSERT(deopt_env != NULL);
+  }
 
   RawDeoptInfo* CreateDeoptInfo(FlowGraphCompiler* compiler,
                                 DeoptInfoBuilder* builder);
@@ -124,11 +128,8 @@
   void set_pc_offset(intptr_t offset) { pc_offset_ = offset; }
 
   intptr_t deopt_id() const { return deopt_id_; }
-
   DeoptReasonId reason() const { return reason_; }
-
-  const Environment* deoptimization_env() const { return deoptimization_env_; }
-  void set_deoptimization_env(Environment* env) { deoptimization_env_ = env; }
+  const Environment* deopt_env() const { return deopt_env_; }
 
  private:
   void EmitMaterializations(Environment* env, DeoptInfoBuilder* builder);
@@ -139,7 +140,7 @@
   intptr_t pc_offset_;
   const intptr_t deopt_id_;
   const DeoptReasonId reason_;
-  Environment* deoptimization_env_;
+  Environment* deopt_env_;
 
   DISALLOW_COPY_AND_ASSIGN(CompilerDeoptInfo);
 };
@@ -148,8 +149,9 @@
 class CompilerDeoptInfoWithStub : public CompilerDeoptInfo {
  public:
   CompilerDeoptInfoWithStub(intptr_t deopt_id,
-                            DeoptReasonId reason)
-      : CompilerDeoptInfo(deopt_id, reason), entry_label_() {
+                            DeoptReasonId reason,
+                            Environment* deopt_env)
+      : CompilerDeoptInfo(deopt_id, reason, deopt_env), entry_label_() {
     ASSERT(reason != kDeoptAtCall);
   }
 
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index f7db7fe..d1e17a8 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -45,17 +45,17 @@
 
 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder) {
-  if (deoptimization_env_ == NULL) return DeoptInfo::null();
+  if (deopt_env_ == NULL) return DeoptInfo::null();
 
   intptr_t stack_height = compiler->StackSize();
-  AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height);
+  AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
 
   intptr_t slot_ix = 0;
-  Environment* current = deoptimization_env_;
+  Environment* current = deopt_env_;
 
   // Emit all kMaterializeObject instructions describing objects to be
   // materialized on the deoptimization as a prefix to the deoptimization info.
-  EmitMaterializations(deoptimization_env_, builder);
+  EmitMaterializations(deopt_env_, builder);
 
   // The real frame starts here.
   builder->MarkFrameStart();
@@ -150,7 +150,7 @@
   __ Bind(entry_label());
   if (FLAG_trap_on_deoptimization) __ bkpt(0);
 
-  ASSERT(deoptimization_env() != NULL);
+  ASSERT(deopt_env() != NULL);
 
   __ BranchLink(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index a4af2f8..aa731d9 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -48,17 +48,17 @@
 
 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder) {
-  if (deoptimization_env_ == NULL) return DeoptInfo::null();
+  if (deopt_env_ == NULL) return DeoptInfo::null();
 
   intptr_t stack_height = compiler->StackSize();
-  AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height);
+  AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
 
   intptr_t slot_ix = 0;
-  Environment* current = deoptimization_env_;
+  Environment* current = deopt_env_;
 
   // Emit all kMaterializeObject instructions describing objects to be
   // materialized on the deoptimization as a prefix to the deoptimization info.
-  EmitMaterializations(deoptimization_env_, builder);
+  EmitMaterializations(deopt_env_, builder);
 
   // The real frame starts here.
   builder->MarkFrameStart();
@@ -148,7 +148,7 @@
   __ Bind(entry_label());
   if (FLAG_trap_on_deoptimization) __ int3();
 
-  ASSERT(deoptimization_env() != NULL);
+  ASSERT(deopt_env() != NULL);
 
   __ call(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 27f6d64..4b88a5f 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -60,7 +60,7 @@
   __ Bind(entry_label());
   if (FLAG_trap_on_deoptimization) __ break_(0);
 
-  ASSERT(deoptimization_env() != NULL);
+  ASSERT(deopt_env() != NULL);
 
   __ BranchLink(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 2ae5235..dd764ea 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -46,17 +46,17 @@
 
 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
                                                  DeoptInfoBuilder* builder) {
-  if (deoptimization_env_ == NULL) return DeoptInfo::null();
+  if (deopt_env_ == NULL) return DeoptInfo::null();
 
   intptr_t stack_height = compiler->StackSize();
-  AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height);
+  AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
 
   intptr_t slot_ix = 0;
-  Environment* current = deoptimization_env_;
+  Environment* current = deopt_env_;
 
   // Emit all kMaterializeObject instructions describing objects to be
   // materialized on the deoptimization as a prefix to the deoptimization info.
-  EmitMaterializations(deoptimization_env_, builder);
+  EmitMaterializations(deopt_env_, builder);
 
   // The real frame starts here.
   builder->MarkFrameStart();
@@ -146,7 +146,7 @@
   __ Bind(entry_label());
   if (FLAG_trap_on_deoptimization) __ int3();
 
-  ASSERT(deoptimization_env() != NULL);
+  ASSERT(deopt_env() != NULL);
 
   __ call(&StubCode::DeoptimizeLabel());
   set_pc_offset(assem->CodeSize());
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index d3f7d7d..541b3f6 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -465,9 +465,6 @@
     }
 
     Isolate* isolate = Isolate::Current();
-    // Save and clear IC data.
-    const Array& prev_ic_data = Array::Handle(isolate->ic_data_array());
-    isolate->set_ic_data_array(Array::null());
     // Save and clear deopt id.
     const intptr_t prev_deopt_id = isolate->deopt_id();
     isolate->set_deopt_id(0);
@@ -487,16 +484,17 @@
       }
 
       // Load IC data for the callee.
+      Array& ic_data_array = Array::Handle();
       if (function.HasCode()) {
         const Code& unoptimized_code =
             Code::Handle(function.unoptimized_code());
-        isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray());
+        ic_data_array = unoptimized_code.ExtractTypeFeedbackArray();
       }
 
       // Build the callee graph.
       InlineExitCollector* exit_collector =
           new InlineExitCollector(caller_graph_, call);
-      FlowGraphBuilder builder(*parsed_function, exit_collector);
+      FlowGraphBuilder builder(*parsed_function, ic_data_array, exit_collector);
       builder.SetInitialBlockId(caller_graph_->max_block_id());
       FlowGraph* callee_graph;
       {
@@ -597,7 +595,6 @@
         }
         isolate->set_long_jump_base(base);
         isolate->set_deopt_id(prev_deopt_id);
-        isolate->set_ic_data_array(prev_ic_data.raw());
         TRACE_INLINING(OS::Print("     Bailout: heuristics with "
                                  "code size:  %"Pd", "
                                  "call sites: %"Pd", "
@@ -621,7 +618,6 @@
       inlined_size_ += size;
       isolate->set_long_jump_base(base);
       isolate->set_deopt_id(prev_deopt_id);
-      isolate->set_ic_data_array(prev_ic_data.raw());
 
       call_data->callee_graph = callee_graph;
       call_data->parameter_stubs = param_stubs;
@@ -634,7 +630,6 @@
       isolate->object_store()->clear_sticky_error();
       isolate->set_long_jump_base(base);
       isolate->set_deopt_id(prev_deopt_id);
-      isolate->set_ic_data_array(prev_ic_data.raw());
       TRACE_INLINING(OS::Print("     Bailout: %s\n", error.ToErrorCString()));
       return false;
     }
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index f818958..2da6e02 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -5984,7 +5984,8 @@
         new EqualityCompareInstr(equality_compare->token_pos(),
                                  comparison->kind(),
                                  left,
-                                 right);
+                                 right,
+                                 Array::Handle());
     new_equality_compare->set_ic_data(equality_compare->ic_data());
     new_comparison = new_equality_compare;
   } else {
@@ -5994,7 +5995,8 @@
         new RelationalOpInstr(relational_op->token_pos(),
                               comparison->kind(),
                               left,
-                              right);
+                              right,
+                              Array::Handle());
     new_relational_op->set_ic_data(relational_op->ic_data());
     new_comparison = new_relational_op;
   }
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index f709124..d096872 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -736,7 +736,7 @@
 
   if (value().IsInstance()) {
     return CompileType::Create(
-        Class::Handle(value().clazz()).id(),
+        value().GetClassId(),
         AbstractType::ZoneHandle(Instance::Cast(value()).GetType()));
   } else {
     ASSERT(value().IsAbstractTypeArguments());
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 91eca39..ed56e35 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -42,6 +42,17 @@
 }
 
 
+ICData* Instruction::GetICData(const Array& ic_data_array) const {
+  ICData& ic_data = ICData::ZoneHandle();
+  // The deopt_id can be outside the range of the IC data array for
+  // computations added in the optimizing compiler.
+  if (!ic_data_array.IsNull() && (deopt_id_ < ic_data_array.Length())) {
+    ic_data ^= ic_data_array.At(deopt_id_);
+  }
+  return &ic_data;
+}
+
+
 intptr_t Instruction::Hashcode() const {
   intptr_t result = tag();
   for (intptr_t i = 0; i < InputCount(); ++i) {
@@ -1396,56 +1407,13 @@
 }
 
 
-// Shared code generation methods (EmitNativeCode, MakeLocationSummary, and
-// PrepareEntry). Only assembly code that can be shared across all architectures
-// can be used. Machine specific register allocation and code generation
-// is located in intermediate_language_<arch>.cc
+// Shared code generation methods (EmitNativeCode and
+// MakeLocationSummary). Only assembly code that can be shared across all
+// architectures can be used. Machine specific register allocation and code
+// generation is located in intermediate_language_<arch>.cc
 
 #define __ compiler->assembler()->
 
-void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
-  // Nothing to do.
-}
-
-
-void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
-  if (!compiler->is_optimizing()) {
-    compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
-                                   deopt_id_,
-                                   Scanner::kDummyTokenIndex);
-  }
-  __ Bind(compiler->GetJumpLabel(this));
-  if (HasParallelMove()) {
-    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
-  }
-}
-
-
-void TargetEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
-  if (!compiler->is_optimizing()) {
-    compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
-                                   deopt_id_,
-                                   Scanner::kDummyTokenIndex);
-  }
-  __ Bind(compiler->GetJumpLabel(this));
-  if (HasParallelMove()) {
-    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
-  }
-}
-
-
-void CatchBlockEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) {
-  __ Bind(compiler->GetJumpLabel(this));
-  compiler->AddExceptionHandler(catch_try_index(),
-                                try_index(),
-                                compiler->assembler()->CodeSize(),
-                                catch_handler_types_);
-  if (HasParallelMove()) {
-    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
-  }
-}
-
-
 LocationSummary* GraphEntryInstr::MakeLocationSummary() const {
   UNREACHABLE();
   return NULL;
@@ -1453,7 +1421,7 @@
 
 
 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
+  // Nothing to do.
 }
 
 
@@ -1464,7 +1432,15 @@
 
 
 void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
+  if (!compiler->is_optimizing()) {
+    compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
+                                   deopt_id_,
+                                   Scanner::kDummyTokenIndex);
+  }
+  __ Bind(compiler->GetJumpLabel(this));
+  if (HasParallelMove()) {
+    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
+  }
 }
 
 
@@ -1475,7 +1451,15 @@
 
 
 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
+  if (!compiler->is_optimizing()) {
+    compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
+                                   deopt_id_,
+                                   Scanner::kDummyTokenIndex);
+  }
+  __ Bind(compiler->GetJumpLabel(this));
+  if (HasParallelMove()) {
+    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
+  }
 }
 
 
@@ -1486,7 +1470,14 @@
 
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
+  __ Bind(compiler->GetJumpLabel(this));
+  compiler->AddExceptionHandler(catch_try_index(),
+                                try_index(),
+                                compiler->assembler()->CodeSize(),
+                                catch_handler_types_);
+  if (HasParallelMove()) {
+    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
+  }
 }
 
 
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index f881959..42c8470 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -646,6 +646,8 @@
     return deopt_id_;
   }
 
+  ICData* GetICData(const Array& ic_data_array) const;
+
   bool IsBlockEntry() { return (AsBlockEntry() != NULL); }
   virtual BlockEntryInstr* AsBlockEntry() { return NULL; }
 
@@ -1070,7 +1072,6 @@
 
   virtual intptr_t PredecessorCount() const = 0;
   virtual BlockEntryInstr* PredecessorAt(intptr_t index) const = 0;
-  virtual void PrepareEntry(FlowGraphCompiler* compiler) = 0;
 
   intptr_t preorder_number() const { return preorder_number_; }
   void set_preorder_number(intptr_t number) { preorder_number_ = number; }
@@ -1292,8 +1293,6 @@
 
   CatchBlockEntryInstr* GetCatchEntry(intptr_t index);
 
-  virtual void PrepareEntry(FlowGraphCompiler* compiler);
-
   GrowableArray<Definition*>* initial_definitions() {
     return &initial_definitions_;
   }
@@ -1359,8 +1358,6 @@
 
   ZoneGrowableArray<PhiInstr*>* phis() const { return phis_; }
 
-  virtual void PrepareEntry(FlowGraphCompiler* compiler);
-
   void InsertPhi(intptr_t var_index, intptr_t var_count);
   void RemoveDeadPhis(Definition* replacement);
 
@@ -1429,8 +1426,6 @@
     return predecessor_;
   }
 
-  virtual void PrepareEntry(FlowGraphCompiler* compiler);
-
   virtual void PrintTo(BufferFormatter* f) const;
 
  private:
@@ -1478,8 +1473,6 @@
     return &initial_definitions_;
   }
 
-  virtual void PrepareEntry(FlowGraphCompiler* compiler);
-
   virtual void PrintTo(BufferFormatter* f) const;
 
  private:
@@ -2600,8 +2593,9 @@
                     Token::Kind token_kind,
                     ZoneGrowableArray<PushArgumentInstr*>* arguments,
                     const Array& argument_names,
-                    intptr_t checked_argument_count)
-      : ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
+                    intptr_t checked_argument_count,
+                    const Array& ic_data_array)
+      : ic_data_(GetICData(ic_data_array)),
         token_pos_(token_pos),
         function_name_(function_name),
         token_kind_(token_kind),
@@ -2842,12 +2836,12 @@
   EqualityCompareInstr(intptr_t token_pos,
                        Token::Kind kind,
                        Value* left,
-                       Value* right)
+                       Value* right,
+                       const Array& ic_data_array)
       : ComparisonInstr(kind, left, right),
+        ic_data_(GetICData(ic_data_array)),
         token_pos_(token_pos),
         receiver_class_id_(kIllegalCid) {
-    // deopt_id() checks receiver_class_id_ value.
-    ic_data_ = Isolate::Current()->GetICDataForDeoptId(deopt_id());
     ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
   }
 
@@ -2921,12 +2915,12 @@
   RelationalOpInstr(intptr_t token_pos,
                     Token::Kind kind,
                     Value* left,
-                    Value* right)
+                    Value* right,
+                    const Array& ic_data_array)
       : ComparisonInstr(kind, left, right),
+        ic_data_(GetICData(ic_data_array)),
         token_pos_(token_pos),
         operands_class_id_(kIllegalCid) {
-    // deopt_id() checks operands_class_id_ value.
-    ic_data_ = Isolate::Current()->GetICDataForDeoptId(deopt_id());
     ASSERT(Token::IsRelationalOperator(kind));
   }
 
@@ -3719,18 +3713,16 @@
 };
 
 
-class AllocateObjectWithBoundsCheckInstr : public TemplateDefinition<2> {
+class AllocateObjectWithBoundsCheckInstr : public TemplateDefinition<0> {
  public:
-  AllocateObjectWithBoundsCheckInstr(ConstructorCallNode* node,
-                                     Value* type_arguments,
-                                     Value* instantiator)
+  explicit AllocateObjectWithBoundsCheckInstr(ConstructorCallNode* node)
       : ast_node_(*node) {
-    SetInputAt(0, type_arguments);
-    SetInputAt(1, instantiator);
   }
 
   DECLARE_INSTRUCTION(AllocateObjectWithBoundsCheck)
 
+  virtual intptr_t ArgumentCount() const { return 4; }
+
   const Function& constructor() const { return ast_node_.constructor(); }
   intptr_t token_pos() const { return ast_node_.token_pos(); }
 
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 9d93594..ecbaf96 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -1405,9 +1405,9 @@
 
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
-  const intptr_t num_temps =  0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
-      new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall);
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -1610,27 +1610,24 @@
 
   // instantiator_reg is the instantiator type argument vector, i.e. an
   // AbstractTypeArguments object (or null).
-  if (!type_arguments().IsUninstantiatedIdentity() &&
-      !type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    Label type_arguments_instantiated;
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      __ CompareImmediate(instantiator_reg,
-                          reinterpret_cast<intptr_t>(Object::null()));
-      __ b(&type_arguments_instantiated, EQ);
-    }
-    // Instantiate non-null type arguments.
-    // In the non-factory case, we rely on the allocation stub to
-    // instantiate the type arguments.
-    __ LoadObject(result_reg, type_arguments());
-    // result_reg: uninstantiated type arguments.
-    __ Bind(&type_arguments_instantiated);
-  }
-  ASSERT(instantiator_reg == result_reg);
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments.
+  Label type_arguments_instantiated;
+  ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
+  __ CompareImmediate(instantiator_reg,
+                      reinterpret_cast<intptr_t>(Object::null()));
+  __ b(&type_arguments_instantiated, EQ);
+  // Instantiate non-null type arguments.
+  // In the non-factory case, we rely on the allocation stub to
+  // instantiate the type arguments.
+  __ LoadObject(result_reg, type_arguments());
+  // result_reg: uninstantiated type arguments.
+  __ Bind(&type_arguments_instantiated);
+
   // result_reg: uninstantiated or instantiated type arguments.
 }
 
@@ -1654,30 +1651,23 @@
 
   // instantiator_reg is the instantiator AbstractTypeArguments object
   // (or null).
-  if (type_arguments().IsUninstantiatedIdentity() ||
-      type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // The instantiator was used in VisitExtractConstructorTypeArguments as the
-    // instantiated type arguments, no proper instantiator needed.
-    __ LoadImmediate(instantiator_reg,
-                     Smi::RawValue(StubCode::kNoInstantiator));
-  } else {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments and do not pass the instantiator.
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      Label instantiator_not_null;
-      __ CompareImmediate(instantiator_reg,
-                          reinterpret_cast<intptr_t>(Object::null()));
-      __ b(&instantiator_not_null, NE);
-      // Null was used in VisitExtractConstructorTypeArguments as the
-      // instantiated type arguments, no proper instantiator needed.
-      __ LoadImmediate(instantiator_reg,
-                       Smi::RawValue(StubCode::kNoInstantiator));
-      __ Bind(&instantiator_not_null);
-    }
-  }
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments and do not pass the instantiator.
+  ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
+  Label instantiator_not_null;
+  __ CompareImmediate(instantiator_reg,
+                      reinterpret_cast<intptr_t>(Object::null()));
+  __ b(&instantiator_not_null, NE);
+  // Null was used in VisitExtractConstructorTypeArguments as the
+  // instantiated type arguments, no proper instantiator needed.
+  __ LoadImmediate(instantiator_reg,
+                   Smi::RawValue(StubCode::kNoInstantiator));
+  __ Bind(&instantiator_not_null);
   // instantiator_reg: instantiator or kNoInstantiator.
 }
 
@@ -2640,9 +2630,9 @@
 
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  // Add deoptimization descriptor for deoptimizing instructions
-  // that may be inserted before this instruction.
   if (!compiler->is_optimizing()) {
+    // Add deoptimization descriptor for deoptimizing instructions that may
+    // be inserted before this instruction.
     compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
                                    GetDeoptId(),
                                    0);  // No token position.
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 8e43726..6569c52 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -1704,9 +1704,9 @@
 
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
-  const intptr_t num_temps =  0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
-      new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall);
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -1828,37 +1828,19 @@
 
 LocationSummary*
 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(EAX));
-  locs->set_in(1, Location::RegisterLocation(ECX));
-  locs->set_out(Location::RegisterLocation(EAX));
-  return locs;
+  return MakeCallSummary();
 }
 
 
 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
     FlowGraphCompiler* compiler) {
-  const Class& cls = Class::ZoneHandle(constructor().Owner());
-  Register type_arguments = locs()->in(0).reg();
-  Register instantiator_type_arguments = locs()->in(1).reg();
-  Register result = locs()->out().reg();
-
-  // Push the result place holder initialized to NULL.
-  __ PushObject(Object::ZoneHandle());
-  __ PushObject(cls);
-  __ pushl(type_arguments);
-  __ pushl(instantiator_type_arguments);
   compiler->GenerateCallRuntime(token_pos(),
                                 deopt_id(),
                                 kAllocateObjectWithBoundsCheckRuntimeEntry,
                                 locs());
-  // Pop instantiator type arguments, type arguments, and class.
-  // source location.
   __ Drop(3);
-  __ popl(result);  // Pop new instance.
+  ASSERT(locs()->out().reg() == EAX);
+  __ popl(EAX);  // Pop new instance.
 }
 
 
@@ -1947,28 +1929,25 @@
 
   // instantiator_reg is the instantiator type argument vector, i.e. an
   // AbstractTypeArguments object (or null).
-  if (!type_arguments().IsUninstantiatedIdentity() &&
-      !type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    Label type_arguments_instantiated;
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      const Immediate& raw_null =
-          Immediate(reinterpret_cast<intptr_t>(Object::null()));
-      __ cmpl(instantiator_reg, raw_null);
-      __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
-    }
-    // Instantiate non-null type arguments.
-    // In the non-factory case, we rely on the allocation stub to
-    // instantiate the type arguments.
-    __ LoadObject(result_reg, type_arguments());
-    // result_reg: uninstantiated type arguments.
-    __ Bind(&type_arguments_instantiated);
-  }
-  ASSERT(instantiator_reg == result_reg);
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+          instantiator_class()));
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments.
+  ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
+  Label type_arguments_instantiated;
+  const Immediate& raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  __ cmpl(instantiator_reg, raw_null);
+  __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
+  // Instantiate non-null type arguments.
+  // In the non-factory case, we rely on the allocation stub to
+  // instantiate the type arguments.
+  __ LoadObject(result_reg, type_arguments());
+  // result_reg: uninstantiated type arguments.
+
+  __ Bind(&type_arguments_instantiated);
   // result_reg: uninstantiated or instantiated type arguments.
 }
 
@@ -1992,31 +1971,24 @@
 
   // instantiator_reg is the instantiator AbstractTypeArguments object
   // (or null).
-  if (type_arguments().IsUninstantiatedIdentity() ||
-      type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // The instantiator was used in VisitExtractConstructorTypeArguments as the
-    // instantiated type arguments, no proper instantiator needed.
-    __ movl(instantiator_reg,
-            Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
-  } else {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments and do not pass the instantiator.
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      const Immediate& raw_null =
-          Immediate(reinterpret_cast<intptr_t>(Object::null()));
-      Label instantiator_not_null;
-      __ cmpl(instantiator_reg, raw_null);
-      __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump);
-      // Null was used in VisitExtractConstructorTypeArguments as the
-      // instantiated type arguments, no proper instantiator needed.
-      __ movl(instantiator_reg,
-              Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
-      __ Bind(&instantiator_not_null);
-    }
-  }
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments and do not pass the instantiator.
+  ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
+  const Immediate& raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  Label instantiator_not_null;
+  __ cmpl(instantiator_reg, raw_null);
+  __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump);
+  // Null was used in VisitExtractConstructorTypeArguments as the
+  // instantiated type arguments, no proper instantiator needed.
+  __ movl(instantiator_reg,
+          Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
+  __ Bind(&instantiator_not_null);
   // instantiator_reg: instantiator or kNoInstantiator.
 }
 
@@ -4290,9 +4262,9 @@
 
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  // Add deoptimization descriptor for deoptimizing instructions
-  // that may be inserted before this instruction.
   if (!compiler->is_optimizing()) {
+    // Add deoptimization descriptor for deoptimizing instructions that may
+    // be inserted before this instruction.
     compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
                                    GetDeoptId(),
                                    0);  // No token position.
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index c07ff89..f9e270b 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -1342,9 +1342,9 @@
 
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
-  const intptr_t num_temps =  0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
-      new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall);
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -1556,27 +1556,24 @@
 
   // instantiator_reg is the instantiator type argument vector, i.e. an
   // AbstractTypeArguments object (or null).
-  if (!type_arguments().IsUninstantiatedIdentity() &&
-      !type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    Label type_arguments_instantiated;
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      __ BranchEqual(instantiator_reg,
-                     reinterpret_cast<intptr_t>(Object::null()),
-                     &type_arguments_instantiated);
-    }
-    // Instantiate non-null type arguments.
-    // In the non-factory case, we rely on the allocation stub to
-    // instantiate the type arguments.
-    __ LoadObject(result_reg, type_arguments());
-    // result_reg: uninstantiated type arguments.
-    __ Bind(&type_arguments_instantiated);
-  }
-  ASSERT(instantiator_reg == result_reg);
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments.
+  Label type_arguments_instantiated;
+  ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
+  __ BranchEqual(instantiator_reg,
+                 reinterpret_cast<intptr_t>(Object::null()),
+                 &type_arguments_instantiated);
+  // Instantiate non-null type arguments.
+  // In the non-factory case, we rely on the allocation stub to
+  // instantiate the type arguments.
+  __ LoadObject(result_reg, type_arguments());
+  // result_reg: uninstantiated type arguments.
+  __ Bind(&type_arguments_instantiated);
+
   // result_reg: uninstantiated or instantiated type arguments.
 }
 
@@ -1600,29 +1597,22 @@
 
   // instantiator_reg is the instantiator AbstractTypeArguments object
   // (or null).
-  if (type_arguments().IsUninstantiatedIdentity() ||
-      type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // The instantiator was used in VisitExtractConstructorTypeArguments as the
-    // instantiated type arguments, no proper instantiator needed.
-    __ LoadImmediate(instantiator_reg,
-                     Smi::RawValue(StubCode::kNoInstantiator));
-  } else {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments and do not pass the instantiator.
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      Label instantiator_not_null;
-      __ BranchNotEqual(instantiator_reg,
-          reinterpret_cast<intptr_t>(Object::null()), &instantiator_not_null);
-      // Null was used in VisitExtractConstructorTypeArguments as the
-      // instantiated type arguments, no proper instantiator needed.
-      __ LoadImmediate(instantiator_reg,
-                       Smi::RawValue(StubCode::kNoInstantiator));
-      __ Bind(&instantiator_not_null);
-    }
-  }
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments and do not pass the instantiator.
+  ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
+  Label instantiator_not_null;
+  __ BranchNotEqual(instantiator_reg,
+      reinterpret_cast<intptr_t>(Object::null()), &instantiator_not_null);
+  // Null was used in VisitExtractConstructorTypeArguments as the
+  // instantiated type arguments, no proper instantiator needed.
+  __ LoadImmediate(instantiator_reg,
+                   Smi::RawValue(StubCode::kNoInstantiator));
+  __ Bind(&instantiator_not_null);
   // instantiator_reg: instantiator or kNoInstantiator.
 }
 
@@ -2618,9 +2608,9 @@
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ TraceSimMsg("GotoInstr");
-  // Add deoptimization descriptor for deoptimizing instructions
-  // that may be inserted before this instruction.
   if (!compiler->is_optimizing()) {
+    // Add deoptimization descriptor for deoptimizing instructions that may
+    // be inserted before this instruction.
     compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
                                    GetDeoptId(),
                                    0);  // No token position.
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index f089bed..88557a7 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -1689,9 +1689,9 @@
 
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
-  const intptr_t num_temps = 0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
-      new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall);
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, ShouldEmitStoreBarrier()
                        ? Location::WritableRegister()
@@ -1811,36 +1811,19 @@
 
 LocationSummary*
 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(RAX));
-  locs->set_in(1, Location::RegisterLocation(RCX));
-  locs->set_out(Location::RegisterLocation(RAX));
-  return locs;
+  return MakeCallSummary();
 }
 
 
 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
     FlowGraphCompiler* compiler) {
-  const Class& cls = Class::ZoneHandle(constructor().Owner());
-  Register type_arguments = locs()->in(0).reg();
-  Register instantiator_type_arguments = locs()->in(1).reg();
-  Register result = locs()->out().reg();
-
-  // Push the result place holder initialized to NULL.
-  __ PushObject(Object::ZoneHandle());
-  __ PushObject(cls);
-  __ pushq(type_arguments);
-  __ pushq(instantiator_type_arguments);
   compiler->GenerateCallRuntime(token_pos(),
                                 deopt_id(),
                                 kAllocateObjectWithBoundsCheckRuntimeEntry,
                                 locs());
-  // Pop instantiator type arguments, type arguments, and class.
   __ Drop(3);
-  __ popq(result);  // Pop new instance.
+  ASSERT(locs()->out().reg() == RAX);
+  __ popq(RAX);  // Pop new instance.
 }
 
 
@@ -1929,28 +1912,25 @@
 
   // instantiator_reg is the instantiator type argument vector, i.e. an
   // AbstractTypeArguments object (or null).
-  if (!type_arguments().IsUninstantiatedIdentity() &&
-      !type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    Label type_arguments_instantiated;
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      const Immediate& raw_null =
-          Immediate(reinterpret_cast<intptr_t>(Object::null()));
-      __ cmpq(instantiator_reg, raw_null);
-      __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
-    }
-    // Instantiate non-null type arguments.
-    // In the non-factory case, we rely on the allocation stub to
-    // instantiate the type arguments.
-    __ LoadObject(result_reg, type_arguments());
-    // result_reg: uninstantiated type arguments.
-    __ Bind(&type_arguments_instantiated);
-  }
-  ASSERT(instantiator_reg == result_reg);
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments.
+  Label type_arguments_instantiated;
+  ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
+  const Immediate& raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  __ cmpq(instantiator_reg, raw_null);
+  __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
+  // Instantiate non-null type arguments.
+  // In the non-factory case, we rely on the allocation stub to
+  // instantiate the type arguments.
+  __ LoadObject(result_reg, type_arguments());
+  // result_reg: uninstantiated type arguments.
+
+  __ Bind(&type_arguments_instantiated);
   // result_reg: uninstantiated or instantiated type arguments.
 }
 
@@ -1974,31 +1954,24 @@
 
   // instantiator_reg is the instantiator AbstractTypeArguments object
   // (or null).
-  if (type_arguments().IsUninstantiatedIdentity() ||
-      type_arguments().CanShareInstantiatorTypeArguments(
-          instantiator_class())) {
-    // The instantiator was used in VisitExtractConstructorTypeArguments as the
-    // instantiated type arguments, no proper instantiator needed.
-    __ movq(instantiator_reg,
-            Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
-  } else {
-    // If the instantiator is null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments and do not pass the instantiator.
-    const intptr_t len = type_arguments().Length();
-    if (type_arguments().IsRawInstantiatedRaw(len)) {
-      const Immediate& raw_null =
-          Immediate(reinterpret_cast<intptr_t>(Object::null()));
-      Label instantiator_not_null;
-      __ cmpq(instantiator_reg, raw_null);
-      __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump);
-      // Null was used in VisitExtractConstructorTypeArguments as the
-      // instantiated type arguments, no proper instantiator needed.
-      __ movq(instantiator_reg,
-              Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
-      __ Bind(&instantiator_not_null);
-    }
-  }
+  ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
+         !type_arguments().CanShareInstantiatorTypeArguments(
+             instantiator_class()));
+
+  // If the instantiator is null and if the type argument vector
+  // instantiated from null becomes a vector of dynamic, then use null as
+  // the type arguments and do not pass the instantiator.
+  ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
+  const Immediate& raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  Label instantiator_not_null;
+  __ cmpq(instantiator_reg, raw_null);
+  __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump);
+  // Null was used in VisitExtractConstructorTypeArguments as the
+  // instantiated type arguments, no proper instantiator needed.
+  __ movq(instantiator_reg,
+          Immediate(Smi::RawValue(StubCode::kNoInstantiator)));
+  __ Bind(&instantiator_not_null);
   // instantiator_reg: instantiator or kNoInstantiator.
 }
 
@@ -4090,9 +4063,9 @@
 
 
 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  // Add deoptimization descriptor for deoptimizing instructions
-  // that may be inserted before this instruction.
   if (!compiler->is_optimizing()) {
+    // Add deoptimization descriptor for deoptimizing instructions that may
+    // be inserted before this instruction.
     compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
                                    GetDeoptId(),
                                    0);  // No token position.
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 4828657..d55d3c1 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -91,6 +91,7 @@
   V(::, sqrt, Math_sqrt, 1662640002)                                           \
   V(::, sin, Math_sin, 1273932041)                                             \
   V(::, cos, Math_cos, 1749547468)                                             \
+  V(_Random, _nextState, Random_nextState, 77315414)                           \
 
 
 #define TYPED_DATA_LIB_INTRINSIC_LIST(V)                                       \
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index d263973..49d87c0 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -311,6 +311,11 @@
 }
 
 
+bool Intrinsifier::Random_nextState(Assembler* assembler) {
+  return false;
+}
+
+
 bool Intrinsifier::Object_equal(Assembler* assembler) {
   return false;
 }
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 097da1b..8d5ff5a 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -14,6 +14,7 @@
 #include "vm/intrinsifier.h"
 
 #include "vm/assembler.h"
+#include "vm/flow_graph_compiler.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/os.h"
@@ -1427,6 +1428,52 @@
 }
 
 
+//    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
+//    _state[kSTATE_LO] = state & _MASK_32;
+//    _state[kSTATE_HI] = state >> 32;
+bool Intrinsifier::Random_nextState(Assembler* assembler) {
+  const Library& math_lib = Library::Handle(Library::MathLibrary());
+  ASSERT(!math_lib.IsNull());
+  const Class& random_class =
+      Class::Handle(math_lib.LookupClassAllowPrivate(Symbols::_Random()));
+  ASSERT(!random_class.IsNull());
+  const Field& state_field = Field::ZoneHandle(
+      random_class.LookupInstanceField(Symbols::_state()));
+  ASSERT(!state_field.IsNull());
+  const Field& random_A_field = Field::ZoneHandle(
+      random_class.LookupStaticField(Symbols::_A()));
+  ASSERT(!random_A_field.IsNull());
+  ASSERT(random_A_field.is_const());
+  const Instance& a_value = Instance::Handle(random_A_field.value());
+  const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
+  // 'a_int_value' is a mask.
+  ASSERT(Utils::IsUint(32, a_int_value));
+  int32_t a_int32_value = static_cast<int32_t>(a_int_value);
+  __ movl(EAX, Address(ESP, + 1 * kWordSize));  // Receiver.
+  __ movl(EBX, FieldAddress(EAX, state_field.Offset()));  // Field '_state'.
+  // Addresses of _state[0] and _state[1].
+  Address addr_0 = FlowGraphCompiler::ElementAddressForIntIndex(
+      kTypedDataUint32ArrayCid,
+      FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid),
+      EBX,
+      0);
+  Address addr_1 = FlowGraphCompiler::ElementAddressForIntIndex(
+      kTypedDataUint32ArrayCid,
+      FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid),
+      EBX,
+      1);
+  __ movl(EAX, Immediate(a_int32_value));
+  // 64-bit multiply EAX * value -> EDX:EAX.
+  __ mull(addr_0);
+  __ addl(EAX, addr_1);
+  __ adcl(EDX, Immediate(0));
+  __ movl(addr_1, EDX);
+  __ movl(addr_0, EAX);
+  __ ret();
+  return true;
+}
+
+
 // Identity comparison.
 bool Intrinsifier::Object_equal(Assembler* assembler) {
   Label is_true;
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index eaa50ef..d2d00bb 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -311,6 +311,11 @@
 }
 
 
+bool Intrinsifier::Random_nextState(Assembler* assembler) {
+  return false;
+}
+
+
 bool Intrinsifier::Object_equal(Assembler* assembler) {
   return false;
 }
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index c9befeb..15bec3d 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -8,6 +8,7 @@
 #include "vm/intrinsifier.h"
 
 #include "vm/assembler.h"
+#include "vm/flow_graph_compiler.h"
 #include "vm/instructions.h"
 #include "vm/object_store.h"
 #include "vm/symbols.h"
@@ -1343,6 +1344,52 @@
 }
 
 
+//    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
+//    _state[kSTATE_LO] = state & _MASK_32;
+//    _state[kSTATE_HI] = state >> 32;
+bool Intrinsifier::Random_nextState(Assembler* assembler) {
+  const Library& math_lib = Library::Handle(Library::MathLibrary());
+  ASSERT(!math_lib.IsNull());
+  const Class& random_class =
+      Class::Handle(math_lib.LookupClassAllowPrivate(Symbols::_Random()));
+  ASSERT(!random_class.IsNull());
+  const Field& state_field = Field::ZoneHandle(
+      random_class.LookupInstanceField(Symbols::_state()));
+  ASSERT(!state_field.IsNull());
+  const Field& random_A_field = Field::ZoneHandle(
+      random_class.LookupStaticField(Symbols::_A()));
+  ASSERT(!random_A_field.IsNull());
+  ASSERT(random_A_field.is_const());
+  const Instance& a_value = Instance::Handle(random_A_field.value());
+  const int64_t a_int_value = Integer::Cast(a_value).AsInt64Value();
+  __ movq(RAX, Address(RSP, + 1 * kWordSize));  // Receiver.
+  __ movq(RBX, FieldAddress(RAX, state_field.Offset()));  // Field '_state'.
+  // Addresses of _state[0] and _state[1].
+  Address addr_0 = FlowGraphCompiler::ElementAddressForIntIndex(
+      kTypedDataUint32ArrayCid,
+      FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid),
+      RBX,
+      0);
+  Address addr_1 = FlowGraphCompiler::ElementAddressForIntIndex(
+      kTypedDataUint32ArrayCid,
+      FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid),
+      RBX,
+      1);
+
+  __ movq(RAX, Immediate(a_int_value));
+  __ movl(RCX, addr_0);
+  __ imulq(RCX, RAX);
+  __ movl(RDX, addr_1);
+  __ addq(RDX, RCX);
+  __ movl(addr_0, RDX);
+  __ shrq(RDX, Immediate(32));
+  __ movl(addr_1, RDX);
+  __ ret();
+  return true;
+}
+
+
+
 // Identity comparison.
 bool Intrinsifier::Object_equal(Assembler* assembler) {
   Label is_true;
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index fe15ff3..6c41997 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -382,7 +382,6 @@
       long_jump_base_(NULL),
       timer_list_(),
       deopt_id_(0),
-      ic_data_array_(Array::null()),
       mutex_(new Mutex()),
       stack_limit_(0),
       saved_stack_limit_(0),
@@ -650,21 +649,6 @@
 }
 
 
-ICData* Isolate::GetICDataForDeoptId(intptr_t deopt_id) const {
-  if (ic_data_array() == Array::null()) {
-    return &ICData::ZoneHandle();
-  }
-  const Array& array_handle = Array::Handle(ic_data_array());
-  if (deopt_id >= array_handle.Length()) {
-    // For computations being added in the optimizing compiler.
-    return &ICData::ZoneHandle();
-  }
-  ICData& ic_data_handle = ICData::ZoneHandle();
-  ic_data_handle ^= array_handle.At(deopt_id);
-  return &ic_data_handle;
-}
-
-
 static int MostUsedFunctionFirst(const Function* const* a,
                                  const Function* const* b) {
   if ((*a)->usage_counter() > (*b)->usage_counter()) {
@@ -837,9 +821,6 @@
   // Visit the top context which is stored in the isolate.
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_context_));
 
-  // Visit the currently active IC data array.
-  visitor->VisitPointer(reinterpret_cast<RawObject**>(&ic_data_array_));
-
   // Visit objects in the debugger.
   debugger()->VisitObjectPointers(visitor);
 }
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 407a9f8..e0059cf 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -405,10 +405,6 @@
     return (deopt_id % kDeoptIdStep) == kDeoptIdAfterOffset;
   }
 
-  RawArray* ic_data_array() const { return ic_data_array_; }
-  void set_ic_data_array(RawArray* value) { ic_data_array_ = value; }
-  ICData* GetICDataForDeoptId(intptr_t deopt_id) const;
-
   Mutex* mutex() const { return mutex_; }
 
   Debugger* debugger() const { return debugger_; }
@@ -615,7 +611,6 @@
   LongJump* long_jump_base_;
   TimerList timer_list_;
   intptr_t deopt_id_;
-  RawArray* ic_data_array_;
   Mutex* mutex_;  // protects stack_limit_ and saved_stack_limit_.
   uword stack_limit_;
   uword saved_stack_limit_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f620fe3..ae6e05b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -943,12 +943,14 @@
 
   cls = Class::New<Instance>(kIllegalCid);
   RegisterClass(cls, Symbols::Float32x4(), lib);
+  cls.set_is_prefinalized();
   pending_classes.Add(cls, Heap::kOld);
   type = Type::NewNonParameterizedType(cls);
   object_store->set_float32x4_type(type);
 
   cls = Class::New<Instance>(kIllegalCid);
   RegisterClass(cls, Symbols::Uint32x4(), lib);
+  cls.set_is_prefinalized();
   pending_classes.Add(cls, Heap::kOld);
   type = Type::NewNonParameterizedType(cls);
   object_store->set_uint32x4_type(type);
@@ -976,18 +978,21 @@
 
   cls = Class::New<Instance>(kIllegalCid);
   RegisterClass(cls, Symbols::Int(), core_lib);
+  cls.set_is_prefinalized();
   pending_classes.Add(cls, Heap::kOld);
   type = Type::NewNonParameterizedType(cls);
   object_store->set_int_type(type);
 
   cls = Class::New<Instance>(kIllegalCid);
   RegisterClass(cls, Symbols::Double(), core_lib);
+  cls.set_is_prefinalized();
   pending_classes.Add(cls, Heap::kOld);
   type = Type::NewNonParameterizedType(cls);
   object_store->set_double_type(type);
 
   name = Symbols::New("String");
   cls = Class::New<Instance>(kIllegalCid);
+  cls.set_is_prefinalized();
   RegisterClass(cls, name, core_lib);
   pending_classes.Add(cls, Heap::kOld);
   type = Type::NewNonParameterizedType(cls);
@@ -995,6 +1000,7 @@
 
   cls = Class::New<Instance>(kIllegalCid);
   RegisterClass(cls, Symbols::List(), core_lib);
+  cls.set_is_prefinalized();
   pending_classes.Add(cls, Heap::kOld);
   object_store->set_list_class(cls);
 
@@ -2482,7 +2488,7 @@
     field ^= flds.At(i);
     field_name ^= field.name();
     if (String::EqualsIgnoringPrivateKey(field_name, name)) {
-        return field.raw();
+      return field.raw();
     }
   }
   // No field found.
@@ -4820,6 +4826,9 @@
 
 
 const char* Field::ToCString() const {
+  if (IsNull()) {
+    return "Field::null";
+  }
   const char* kF0 = is_static() ? " static" : "";
   const char* kF1 = is_final() ? " final" : "";
   const char* kF2 = is_const() ? " const" : "";
@@ -6054,7 +6063,8 @@
     }
 
     // Create the array of scripts and cache it in loaded_scripts_.
-    StorePointer(&raw_ptr()->loaded_scripts_, Array::MakeArray(scripts));
+    const Array& scripts_array = Array::Handle(Array::MakeArray(scripts));
+    StorePointer(&raw_ptr()->loaded_scripts_, scripts_array.raw());
   }
   return loaded_scripts();
 }
@@ -7091,7 +7101,7 @@
 
 const char* PcDescriptors::KindAsStr(intptr_t index) const {
   switch (DescriptorKind(index)) {
-    case PcDescriptors::kDeopt:         return "deopt ";
+    case PcDescriptors::kDeopt:         return "deopt        ";
     case PcDescriptors::kEntryPatch:    return "entry-patch  ";
     case PcDescriptors::kPatchCode:     return "patch        ";
     case PcDescriptors::kLazyDeoptJump: return "lazy-deopt   ";
@@ -10344,7 +10354,7 @@
   if (!OS::StringToInt64(str.ToCString(), &value)) {
     const Bigint& big = Bigint::Handle(Bigint::New(str, space));
     ASSERT(!BigintOperations::FitsIntoSmi(big));
-    ASSERT(!BigintOperations::FitsIntoMint(big));
+    ASSERT(!BigintOperations::FitsIntoInt64(big));
     return big.raw();
   }
   return Integer::New(value, space);
@@ -10358,7 +10368,7 @@
   if (!OS::StringToInt64(str.ToCString(), &value)) {
     const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str));
     ASSERT(!BigintOperations::FitsIntoSmi(big));
-    ASSERT(!BigintOperations::FitsIntoMint(big));
+    ASSERT(!BigintOperations::FitsIntoInt64(big));
     return big.raw();
   }
   if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) {
@@ -10410,8 +10420,8 @@
   big_value ^= raw();
   if (BigintOperations::FitsIntoSmi(big_value)) {
     return BigintOperations::ToSmi(big_value);
-  } else if (BigintOperations::FitsIntoMint(big_value)) {
-    return Mint::New(BigintOperations::ToMint(big_value));
+  } else if (BigintOperations::FitsIntoInt64(big_value)) {
+    return Mint::New(BigintOperations::ToInt64(big_value));
   } else {
     return big_value.raw();
   }
@@ -10512,7 +10522,7 @@
   const Bigint& left_big = Bigint::Handle(AsBigint());
   const Bigint& right_big = Bigint::Handle(other.AsBigint());
   const Bigint& result =
-      Bigint::Handle(left_big.ArithmeticOp(operation, right_big));
+      Bigint::Handle(left_big.BigArithmeticOp(operation, right_big));
   return Integer::Handle(result.AsValidInteger()).raw();
 }
 
@@ -10776,7 +10786,7 @@
     }
   }
   if (other.IsBigint()) {
-    ASSERT(!BigintOperations::FitsIntoMint(Bigint::Cast(other)));
+    ASSERT(!BigintOperations::FitsIntoInt64(Bigint::Cast(other)));
     if (this->IsNegative() == other.IsNegative()) {
       return this->IsNegative() ? 1 : -1;
     }
@@ -10918,8 +10928,8 @@
 }
 
 
-RawBigint* Bigint::ArithmeticOp(Token::Kind operation,
-                                const Bigint& other) const {
+RawBigint* Bigint::BigArithmeticOp(Token::Kind operation,
+                                   const Bigint& other) const {
   switch (operation) {
     case Token::kADD:
       return BigintOperations::Add(*this, other);
@@ -10971,7 +10981,7 @@
 RawBigint* Bigint::New(const String& str, Heap::Space space) {
   const Bigint& result = Bigint::Handle(
       BigintOperations::NewFromCString(str.ToCString(), space));
-  ASSERT(!BigintOperations::FitsIntoMint(result));
+  ASSERT(!BigintOperations::FitsIntoInt64(result));
   return result.raw();
 }
 
@@ -10979,7 +10989,7 @@
 RawBigint* Bigint::NewCanonical(const String& str) {
   const Bigint& value = Bigint::Handle(
       BigintOperations::NewFromCString(str.ToCString(), Heap::kOld));
-  ASSERT(!BigintOperations::FitsIntoMint(value));
+  ASSERT(!BigintOperations::FitsIntoInt64(value));
   const Class& cls =
       Class::Handle(Isolate::Current()->object_store()->bigint_class());
   const Array& constants = Array::Handle(cls.constants());
@@ -11012,17 +11022,17 @@
 
 
 int64_t Bigint::AsInt64Value() const {
-  if (!BigintOperations::FitsIntoMint(*this)) {
+  if (!BigintOperations::FitsIntoInt64(*this)) {
     UNREACHABLE();
   }
-  return BigintOperations::ToMint(*this);
+  return BigintOperations::ToInt64(*this);
 }
 
 
 // For positive values: Smi < Mint < Bigint.
 int Bigint::CompareWith(const Integer& other) const {
   ASSERT(!FitsIntoSmi(*this));
-  ASSERT(!BigintOperations::FitsIntoMint(*this));
+  ASSERT(!BigintOperations::FitsIntoInt64(*this));
   if (other.IsBigint()) {
     return BigintOperations::Compare(*this, Bigint::Cast(other));
   }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index b5406ff..755262e 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -216,7 +216,10 @@
     ASSERT(!IsNull());
     raw()->SetCanonical();
   }
-
+  intptr_t GetClassId() const {
+    return !raw()->IsHeapObject() ?
+        static_cast<intptr_t>(kSmiCid) : raw()->GetClassId();
+  }
   inline RawClass* clazz() const;
   static intptr_t tags_offset() { return OFFSET_OF(RawObject, tags_); }
 
@@ -4096,12 +4099,12 @@
     return RoundedAllocationSize(sizeof(RawBigint) + (len * kBytesPerElement));
   }
 
-  RawBigint* ArithmeticOp(Token::Kind operation, const Bigint& other) const;
-
  protected:
   // Only Integer::NewXXX is allowed to call Bigint::NewXXX directly.
   friend class Integer;
 
+  RawBigint* BigArithmeticOp(Token::Kind operation, const Bigint& other) const;
+
   static RawBigint* New(const String& str, Heap::Space space = Heap::kNew);
 
   // Returns a canonical Bigint object allocated in the old gen space.
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 33db8c2..2628ce3 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -3250,7 +3250,8 @@
     } else {
       // Not patching a class, but it has been found. This must be one of the
       // pre-registered classes from object.cc or a duplicate definition.
-      if (cls.functions() != Object::empty_array().raw()) {
+      if (!(cls.is_prefinalized() ||
+            RawObject::IsTypedDataViewClassId(cls.id()))) {
         ErrorMsg(classname_pos, "class '%s' is already defined",
                  class_name.ToCString());
       }
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 60a22ec..30df9e1 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -138,8 +138,9 @@
   intptr_t num_flds = (unresolved_class.raw()->to() -
                        unresolved_class.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
+    (*reader->ObjectHandle()) = reader->ReadObjectRef();
     unresolved_class.StorePointer((unresolved_class.raw()->from() + i),
-                                  reader->ReadObjectRef());
+                                  reader->ObjectHandle()->raw());
   }
   return unresolved_class.raw();
 }
@@ -201,7 +202,8 @@
   // allocations may happen.
   intptr_t num_flds = (type.raw()->to() - type.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    type.StorePointer((type.raw()->from() + i), reader->ReadObjectRef());
+    (*reader->ObjectHandle()) = reader->ReadObjectRef();
+    type.StorePointer((type.raw()->from() + i), reader->ObjectHandle()->raw());
   }
 
   // If object needs to be a canonical object, Canonicalize it.
@@ -315,8 +317,9 @@
   intptr_t num_flds = (type_parameter.raw()->to() -
                        type_parameter.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
+    (*reader->ObjectHandle()) = reader->ReadObjectRef();
     type_parameter.StorePointer((type_parameter.raw()->from() + i),
-                                reader->ReadObjectRef());
+                                reader->ObjectHandle()->raw());
   }
 
   return type_parameter.raw();
@@ -386,8 +389,9 @@
   intptr_t num_flds = (bounded_type.raw()->to() -
                        bounded_type.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
+    (*reader->ObjectHandle()) = reader->ReadObjectRef();
     bounded_type.StorePointer((bounded_type.raw()->from() + i),
-                              reader->ReadObjectRef());
+                              reader->ObjectHandle()->raw());
   }
 
   bounded_type.set_is_being_checked(false);
@@ -536,9 +540,10 @@
   intptr_t num_flds = (instantiated_type_arguments.raw()->to() -
                        instantiated_type_arguments.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
+    (*reader->ObjectHandle()) = reader->ReadObjectRef();
     instantiated_type_arguments.StorePointer(
         (instantiated_type_arguments.raw()->from() + i),
-        reader->ReadObjectRef());
+        reader->ObjectHandle()->raw());
   }
   return instantiated_type_arguments.raw();
 }
@@ -1352,7 +1357,9 @@
   // allocations may happen.
   intptr_t num_flds = (context.raw()->to(num_vars) - context.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
-    context.StorePointer((context.raw()->from() + i), reader->ReadObjectRef());
+    (*reader->ObjectHandle()) = reader->ReadObjectRef();
+    context.StorePointer((context.raw()->from() + i),
+                         reader->ObjectHandle()->raw());
   }
 
   return context.raw();
@@ -1481,8 +1488,9 @@
   // allocations may happen.
   intptr_t num_flds = (api_error.raw()->to() - api_error.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
+    (*reader->ObjectHandle()) = reader->ReadObjectRef();
     api_error.StorePointer((api_error.raw()->from() + i),
-                           reader->ReadObjectRef());
+                           reader->ObjectHandle()->raw());
   }
 
   return api_error.raw();
@@ -1527,8 +1535,9 @@
   intptr_t num_flds =
       (language_error.raw()->to() - language_error.raw()->from());
   for (intptr_t i = 0; i <= num_flds; i++) {
+    (*reader->ObjectHandle()) = reader->ReadObjectRef();
     language_error.StorePointer((language_error.raw()->from() + i),
-                                reader->ReadObjectRef());
+                                reader->ObjectHandle()->raw());
   }
 
   return language_error.raw();
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 59d6d29..4e161c6 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -18,6 +18,7 @@
 #include "vm/constants_arm.h"
 #include "vm/disassembler.h"
 #include "vm/native_arguments.h"
+#include "vm/stack_frame.h"
 #include "vm/thread.h"
 
 namespace dart {
@@ -113,6 +114,13 @@
   bool GetFValue(char* desc, float* value);
   bool GetDValue(char* desc, double* value);
 
+  void PrintDartFrame(uword pc, uword fp, uword sp,
+                      const Function& function,
+                      intptr_t token_pos,
+                      bool is_optimized,
+                      bool is_inlined);
+  void PrintBacktrace();
+
   // Set or delete a breakpoint. Returns true if successful.
   bool SetBreakpoint(Instr* breakpc);
   bool DeleteBreakpoint(Instr* breakpc);
@@ -254,6 +262,79 @@
 }
 
 
+void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp,
+                                       const Function& function,
+                                       intptr_t token_pos,
+                                       bool is_optimized,
+                                       bool is_inlined) {
+  const Script& script = Script::Handle(function.script());
+  const String& func_name = String::Handle(function.QualifiedUserVisibleName());
+  const String& url = String::Handle(script.url());
+  intptr_t line = -1;
+  intptr_t column = -1;
+  if (token_pos >= 0) {
+    script.GetTokenLocation(token_pos, &line, &column);
+  }
+  OS::Print("pc=0x%"Px" fp=0x%"Px" sp=0x%"Px" %s%s (%s:%"Pd":%"Pd")\n",
+            pc, fp, sp,
+            is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
+            func_name.ToCString(),
+            url.ToCString(),
+            line, column);
+}
+
+
+void SimulatorDebugger::PrintBacktrace() {
+  StackFrameIterator frames(sim_->get_register(FP),
+                            sim_->get_register(SP),
+                            sim_->get_pc(),
+                            StackFrameIterator::kDontValidateFrames);
+  StackFrame* frame = frames.NextFrame();
+  ASSERT(frame != NULL);
+  Function& function = Function::Handle();
+  Function& inlined_function = Function::Handle();
+  Code& code = Code::Handle();
+  Code& unoptimized_code = Code::Handle();
+  while (frame != NULL) {
+    if (frame->IsDartFrame()) {
+      code = frame->LookupDartCode();
+      function = code.function();
+      if (code.is_optimized()) {
+        // For optimized frames, extract all the inlined functions if any
+        // into the stack trace.
+        InlinedFunctionsIterator it(frame);
+        while (!it.Done()) {
+          // Print each inlined frame with its pc in the corresponding
+          // unoptimized frame.
+          inlined_function = it.function();
+          unoptimized_code = it.code();
+          uword unoptimized_pc = it.pc();
+          it.Advance();
+          if (!it.Done()) {
+            PrintDartFrame(unoptimized_pc, frame->fp(), frame->sp(),
+                           inlined_function,
+                           unoptimized_code.GetTokenIndexOfPC(unoptimized_pc),
+                           true, true);
+          }
+        }
+        // Print the optimized inlining frame below.
+      }
+      PrintDartFrame(frame->pc(), frame->fp(), frame->sp(),
+                     function,
+                     code.GetTokenIndexOfPC(frame->pc()),
+                     code.is_optimized(), false);
+    } else {
+      OS::Print("pc=0x%"Px" fp=0x%"Px" sp=0x%"Px" %s frame\n",
+                frame->pc(), frame->fp(), frame->sp(),
+                frame->IsEntryFrame() ? "entry" :
+                    frame->IsExitFrame() ? "exit" :
+                        frame->IsStubFrame() ? "stub" : "invalid");
+    }
+    frame = frames.NextFrame();
+  }
+}
+
+
 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) {
   // Check if a breakpoint can be set. If not return without any side-effects.
   if (sim_->break_pc_ != NULL) {
@@ -350,6 +431,8 @@
                   "pd/printdouble <dreg or *addr> -- print double value\n"
                   "po/printobject <*reg or *addr> -- print object\n"
                   "si/stepi -- single step an instruction\n"
+                  "trace -- toggle execution tracing mode\n"
+                  "bt -- print backtrace\n"
                   "unstop -- if current pc is a stop instr make it a nop\n"
                   "q/quit -- Quit the debugger and exit the program\n");
       } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) {
@@ -481,6 +564,11 @@
         } else {
           OS::Print("Not at debugger stop.\n");
         }
+      } else if (strcmp(cmd, "trace") == 0) {
+        FLAG_trace_sim = !FLAG_trace_sim;
+        OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off");
+      } else if (strcmp(cmd, "bt") == 0) {
+        PrintBacktrace();
       } else {
         OS::Print("Unknown command: %s\n", cmd);
       }
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index b45d133..163e653 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -215,6 +215,7 @@
   uword exit_marker = *reinterpret_cast<uword*>(exit_address);
   frames_.fp_ = exit_marker;
   frames_.sp_ = 0;
+  frames_.pc_ = 0;
 }
 
 
@@ -223,29 +224,52 @@
   SetupLastExitFrameData();  // Setup data for last exit frame.
 }
 
+
 StackFrameIterator::StackFrameIterator(uword last_fp, bool validate)
     : validate_(validate), entry_(), exit_(), current_frame_(NULL) {
   frames_.fp_ = last_fp;
+  frames_.sp_ = 0;
+  frames_.pc_ = 0;
+}
+
+
+StackFrameIterator::StackFrameIterator(uword fp, uword sp, uword pc,
+                                       bool validate)
+    : validate_(validate), entry_(), exit_(), current_frame_(NULL) {
+  frames_.fp_ = fp;
+  frames_.sp_ = sp;
+  frames_.pc_ = pc;
 }
 
 
 StackFrame* StackFrameIterator::NextFrame() {
   // When we are at the start of iteration after having created an
-  // iterator object current_frame_ will be NULL as we haven't seen
-  // any frames yet. At this point if NextFrame is called it tries
+  // iterator object, current_frame_ will be NULL as we haven't seen
+  // any frames yet (unless we start iterating in the simulator from a given
+  // triplet of fp, sp, and pc). At this point, if NextFrame is called, it tries
   // to set up the next exit frame by reading the top_exit_frame_info
-  // from the isolate. If we do not have any dart invocations yet
+  // from the isolate. If we do not have any dart invocations yet,
   // top_exit_frame_info will be 0 and so we would return NULL.
 
   // current_frame_ will also be NULL, when we are at the end of having
-  // iterated through all the frames. if NextFrame is called at this
-  // point we will try and set up the next exit frame but since we are
-  // at the end of the iteration fp_ will be 0 and we would return NULL.
+  // iterated through all the frames. If NextFrame is called at this
+  // point, we will try and set up the next exit frame, but since we are
+  // at the end of the iteration, fp_ will be 0 and we would return NULL.
   if (current_frame_ == NULL) {
     if (!HasNextFrame()) {
       return NULL;
     }
-    current_frame_ = NextExitFrame();
+    if (frames_.pc_ == 0) {
+      // Iteration starts from an exit frame given by its fp.
+      current_frame_ = NextExitFrame();
+    } else if (*(reinterpret_cast<uword*>(
+        frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) == 0) {
+      // Iteration starts from an entry frame given by its fp, sp, and pc.
+      current_frame_ = NextEntryFrame();
+    } else {
+      // Iteration starts from a Dart or stub frame given by its fp, sp, and pc.
+      current_frame_ = frames_.NextFrame(validate_);
+    }
     return current_frame_;
   }
   ASSERT((validate_ == kDontValidateFrames) || current_frame_->IsValid());
@@ -276,8 +300,10 @@
   frame = &stack_frame_;
   frame->sp_ = sp_;
   frame->fp_ = fp_;
+  frame->pc_ = pc_;
   sp_ = frame->GetCallerSp();
   fp_ = frame->GetCallerFp();
+  pc_ = frame->GetCallerPc();
   ASSERT((validate == kDontValidateFrames) || frame->IsValid());
   return frame;
 }
@@ -286,8 +312,10 @@
 ExitFrame* StackFrameIterator::NextExitFrame() {
   exit_.sp_ = frames_.sp_;
   exit_.fp_ = frames_.fp_;
+  exit_.pc_ = frames_.pc_;
   frames_.sp_ = exit_.GetCallerSp();
   frames_.fp_ = exit_.GetCallerFp();
+  frames_.pc_ = exit_.GetCallerPc();
   ASSERT(exit_.IsValid());
   return &exit_;
 }
@@ -297,6 +325,7 @@
   ASSERT(!frames_.HasNext());
   entry_.sp_ = frames_.sp_;
   entry_.fp_ = frames_.fp_;
+  entry_.pc_ = frames_.pc_;
   SetupNextExitFrameData();  // Setup data for next exit frame in chain.
   ASSERT(entry_.IsValid());
   return &entry_;
@@ -317,7 +346,7 @@
   intptr_t deopt_reason = kDeoptUnknown;
   deopt_info_ = code_.GetDeoptInfoAtPc(frame->pc(), &deopt_reason);
   if (deopt_info_.IsNull()) {
-    // This is the case when a call without deopt info in optimzed code
+    // This is the case when a call without deopt info in optimized code
     // throws an exception. (e.g. in the parameter copying prologue).
     // In that case there won't be any inlined frames.
     function_ = code_.function();
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 10b63c5..2b206fa 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -36,9 +36,7 @@
   // Accessors to get the pc, sp and fp of a frame.
   uword sp() const { return sp_; }
   uword fp() const { return fp_; }
-  uword pc() const {
-    return *reinterpret_cast<uword*>(sp_ + (kSavedPcSlotFromSp * kWordSize));
-  }
+  uword pc() const { return pc_; }
 
   // The pool pointer is not implemented on all architectures.
   static int SavedCallerPpSlotFromFp() {
@@ -79,7 +77,7 @@
 
 
  protected:
-  StackFrame() : fp_(0), sp_(0) { }
+  StackFrame() : fp_(0), sp_(0), pc_(0) { }
 
   // Name of the frame, used for generic frame printing functionality.
   virtual const char* GetName() const { return IsStubFrame()? "stub" : "dart"; }
@@ -94,9 +92,14 @@
     return *(reinterpret_cast<uword*>(
         fp() + (kSavedCallerFpSlotFromFp * kWordSize)));
   }
+  uword GetCallerPc() const {
+    return *(reinterpret_cast<uword*>(
+        fp() + (kSavedCallerPcSlotFromFp * kWordSize)));
+  }
 
   uword fp_;
   uword sp_;
+  uword pc_;
 
   // The iterators FrameSetIterator and StackFrameIterator set the private
   // fields fp_ and sp_ when they return the respective frame objects.
@@ -154,16 +157,20 @@
 };
 
 
-// Iterator for iterating over all frames from the last ExitFrame to the
-// first EntryFrame.
 class StackFrameIterator : public ValueObject {
  public:
   static const bool kValidateFrames = true;
   static const bool kDontValidateFrames = false;
 
+  // Iterators for iterating over all frames from the last ExitFrame to the
+  // first EntryFrame.
   explicit StackFrameIterator(bool validate);
   StackFrameIterator(uword last_fp, bool validate);
 
+  // Iterator for iterating over all frames from the current frame (given by its
+  // fp, sp, and pc) to the first EntryFrame.
+  StackFrameIterator(uword fp, uword sp, uword pc, bool validate);
+
   // Checks if a next frame exists.
   bool HasNextFrame() const { return frames_.fp_ != 0; }
 
@@ -189,10 +196,11 @@
     StackFrame* NextFrame(bool validate);
 
    private:
-    FrameSetIterator() : fp_(0), sp_(0), stack_frame_() { }
+    FrameSetIterator() : fp_(0), sp_(0), pc_(0), stack_frame_() { }
 
     uword fp_;
     uword sp_;
+    uword pc_;
     StackFrame stack_frame_;  // Singleton frame returned by NextFrame().
 
     friend class StackFrameIterator;
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 2c85c1c..efe97a0 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -257,6 +257,9 @@
   V(DartTypedData, "dart:typed_data")                                          \
   V(DartUri, "dart:uri")                                                       \
   V(DartUtf, "dart:utf")                                                       \
+  V(_Random, "_Random")                                                        \
+  V(_state, "_state")                                                          \
+  V(_A, "_A")                                                                  \
 
 
 // Contains a list of frequently used strings in a canonicalized form. This
diff --git a/sdk/lib/_internal/compiler/implementation/apiimpl.dart b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
index 2c94493..69d3cfa 100644
--- a/sdk/lib/_internal/compiler/implementation/apiimpl.dart
+++ b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
@@ -38,6 +38,8 @@
             outputProvider: outputProvider,
             enableTypeAssertions: hasOption(options, '--enable-checked-mode'),
             enableUserAssertions: hasOption(options, '--enable-checked-mode'),
+            trustTypeAnnotations:
+                hasOption(options, '--trust-type-annotations'),
             enableMinification: hasOption(options, '--minify'),
             enableNativeLiveTypeAnalysis:
                 !hasOption(options, '--disable-native-live-type-analysis'),
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index fff0b37..b1d62ca 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -67,7 +67,9 @@
 // move these classes to elements/modelx.dart or see if we can find a
 // more general solution.
 class ClosureFieldElement extends ElementX {
-  ClosureFieldElement(SourceString name, ClassElement enclosing)
+  ClosureFieldElement(SourceString name,
+                      this.variableElement,
+                      ClassElement enclosing)
       : super(name, ElementKind.FIELD, enclosing);
 
   bool isInstanceMember() => true;
@@ -77,9 +79,16 @@
   bool hasFixedBackendName() => true;
   String fixedBackendName() => name.slowToString();
 
-  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+  DartType computeType(Compiler compiler) {
+    return variableElement.computeType(compiler);
+  }
 
   String toString() => "ClosureFieldElement($name)";
+
+  /**
+   * The source variable this element refers to.
+   */
+  final Element variableElement;
 }
 
 // TODO(ahe): These classes continuously cause problems.  We need to
@@ -114,10 +123,12 @@
 
   Token position() => node.getBeginToken();
 
+  Node parseNode(DiagnosticListener listener) => node;
+
   /**
    * The most outer method this closure is declared into.
    */
-  Element methodElement;
+  final Element methodElement;
 }
 
 // TODO(ahe): These classes continuously cause problems.  We need to
@@ -126,6 +137,24 @@
 class BoxElement extends ElementX {
   BoxElement(SourceString name, Element enclosingElement)
       : super(name, ElementKind.VARIABLE, enclosingElement);
+
+  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+}
+
+// TODO(ngeoffray, ahe): These classes continuously cause problems.  We need to
+// move these classes to elements/modelx.dart or see if we can find a
+// more general solution.
+class BoxFieldElement extends ElementX {
+  BoxFieldElement(SourceString name,
+                  this.variableElement,
+                  BoxElement enclosingBox)
+      : super(name, ElementKind.FIELD, enclosingBox);
+
+  DartType computeType(Compiler compiler) {
+    return variableElement.computeType(compiler);
+  }
+
+  final Element variableElement;
 }
 
 // TODO(ahe): These classes continuously cause problems.  We need to
@@ -137,6 +166,8 @@
 
   bool isAssignable() => false;
 
+  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+
   // Since there is no declaration corresponding to 'this', use the position of
   // the enclosing method.
   Token position() => enclosingElement.position();
@@ -150,6 +181,8 @@
   CheckVariableElement(SourceString name, this.parameter, Element enclosing)
       : super(name, ElementKind.VARIABLE, enclosing);
 
+  DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+
   // Since there is no declaration for the synthetic 'check' variable, use
   // parameter.
   Token position() => parameter.position();
@@ -226,25 +259,25 @@
     return copy != null && !copy.isMember();
   }
 
-  void forEachCapturedVariable(void f(Element element)) {
-    freeVariableMapping.forEach((variable, _) {
+  void forEachCapturedVariable(void f(Element local, Element field)) {
+    freeVariableMapping.forEach((variable, copy) {
       if (variable is BoxElement) return;
-      f(variable);
+      f(variable, copy);
     });
   }
 
-  void forEachBoxedVariable(void f(Element element)) {
+  void forEachBoxedVariable(void f(Element local, Element field)) {
     freeVariableMapping.forEach((variable, copy) {
       if (!isVariableBoxed(variable)) return;
-      f(variable);
+      f(variable, copy);
     });
   }
 
-  void forEachNonBoxedCapturedVariable(void f(Element element)) {
+  void forEachNonBoxedCapturedVariable(void f(Element local, Element field)) {
     freeVariableMapping.forEach((variable, copy) {
       if (variable is BoxElement) return;
       if (isVariableBoxed(variable)) return;
-      f(variable);
+      f(variable, copy);
     });
   }
 }
@@ -342,8 +375,9 @@
       assert(closureElement != null ||
              (fieldCaptures.isEmpty && boxes.isEmpty));
       void addElement(Element element, SourceString name) {
-        Element fieldElement = new ClosureFieldElement(name, closureElement);
-        closureElement.addBackendMember(fieldElement);
+        Element fieldElement = new ClosureFieldElement(
+            name, element, closureElement);
+        closureElement.addMember(fieldElement, compiler);
         data.capturedFieldMapping[fieldElement] = element;
         freeVariableMapping[element] = fieldElement;
       }
@@ -568,7 +602,7 @@
             namer.getClosureVariableName(new SourceString(elementName),
                                          boxedFieldCounter++);
         // TODO(kasperl): Should this be a FieldElement instead?
-        Element boxed = new ElementX(boxedName, ElementKind.FIELD, box);
+        Element boxed = new BoxFieldElement(boxedName, element, box);
         // No need to rename the fields of a box, so we give them a native name
         // right now.
         boxed.setFixedBackendName(boxedName.slowToString());
@@ -658,7 +692,7 @@
         new FunctionElementX.from(Compiler.CALL_OPERATOR_NAME,
                                   element,
                                   globalizedElement);
-    globalizedElement.addBackendMember(callElement);
+    globalizedElement.addMember(callElement, compiler);
     // The nested function's 'this' is the same as the one for the outer
     // function. It could be [null] if we are inside a static method.
     Element thisElement = closureData.thisElement;
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index dc99d27..47b66c2 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -884,8 +884,7 @@
           }
           jsNewArguments.add(fieldValue);
         },
-        includeBackendMembers: true,
-        includeSuperMembers: true);
+        includeSuperAndInjectedMembers: true);
     return jsNewArguments;
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index c2de002..a292e28 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -137,7 +137,8 @@
                                  Enqueuer enqueuer,
                                  TreeElements elements) {}
   void registerStringInterpolation(TreeElements elements) {}
-  void registerCatchStatement(TreeElements elements) {}
+  void registerCatchStatement(Enqueuer enqueuer,
+                              TreeElements elements) {}
   void registerWrapException(TreeElements elements) {}
   void registerThrowExpression(TreeElements elements) {}
   void registerLazyField(TreeElements elements) {}
@@ -251,6 +252,7 @@
   final bool enableMinification;
   final bool enableTypeAssertions;
   final bool enableUserAssertions;
+  final bool trustTypeAnnotations;
   final bool enableConcreteTypeInference;
   /**
    * The maximum size of a concrete type before it widens to dynamic during
@@ -440,6 +442,7 @@
   Compiler({this.tracer: const Tracer(),
             this.enableTypeAssertions: false,
             this.enableUserAssertions: false,
+            this.trustTypeAnnotations: false,
             this.enableConcreteTypeInference: false,
             this.maxConcreteTypeSize: 5,
             this.enableMinification: false,
@@ -1024,7 +1027,6 @@
     if (message is TypeWarning) {
       // TODO(ahe): Don't supress these warning when the type checker
       // is more complete.
-      if (identical(message.message.kind, MessageKind.NOT_ASSIGNABLE)) return;
       if (identical(message.message.kind, MessageKind.MISSING_RETURN)) return;
       if (identical(message.message.kind, MessageKind.MAYBE_MISSING_RETURN)) {
         return;
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index 1afb82b..20856b7 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library dart2js;
+library dart2js.cmdline;
 
 import 'dart:async';
 import 'dart:collection' show Queue, LinkedHashMap;
@@ -212,6 +212,8 @@
                       (_) => passThrough('--enable-checked-mode')),
     new OptionHandler('--enable-concrete-type-inference',
                       (_) => passThrough('--enable-concrete-type-inference')),
+    new OptionHandler('--trust-type-annotations',
+                      (_) => passThrough('--trust-type-annotations')),
     new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
     new OptionHandler('--package-root=.+|-p.+', setPackageRoot),
     new OptionHandler('--disallow-unsafe-eval', passThrough),
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index ecee2ba..bcec921 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -341,6 +341,8 @@
     return visitor.visitMalformedType(this, argument);
   }
 
+  bool operator ==(other) => identical(this, other);
+
   String toString() {
     var sb = new StringBuffer();
     if (typeArguments != null) {
@@ -446,8 +448,9 @@
   }
 
   bool operator ==(other) {
-    if (!identical(element, other.element)) return false;
-    return typeArguments == other.typeArguments;
+    if (other is !GenericType) return false;
+    return identical(element, other.element)
+        && typeArguments == other.typeArguments;
   }
 
   bool get isRaw => typeArguments.isEmpty || identical(this, element.rawType);
@@ -521,7 +524,9 @@
     ClassElement classElement = element;
     InterfaceType receiver = this;
     InterfaceType declarer = receiver;
-    Element member = classElement.lookupLocalMember(name);
+    // TODO(johnniwinther): Lookup and callers should handle private members and
+    // injected members.
+    Element member = classElement.implementation.lookupLocalMember(name);
     if (member != null) {
       return createMember(receiver, declarer, member);
     }
@@ -533,7 +538,7 @@
       if (supertype.element.isMixinApplication) continue;
       declarer = supertype;
       ClassElement lookupTarget = declarer.element;
-      member = lookupTarget.lookupLocalMember(name);
+      member = lookupTarget.implementation.lookupLocalMember(name);
       if (member != null) {
         return createMember(receiver, declarer, member);
       }
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index cecab14..c0bc01e4 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -198,6 +198,7 @@
   bool isTypedef();
   bool isTypeVariable();
   bool isField();
+  bool isFieldParameter();
   bool isAbstractField();
   bool isGetter();
   bool isSetter();
@@ -488,15 +489,13 @@
   /// A `compareTo` function that places [Element]s in a consistent order based
   /// on the source code order.
   static int compareByPosition(Element a, Element b) {
-    CompilationUnitElement unitA = a.getCompilationUnit();
-    CompilationUnitElement unitB = b.getCompilationUnit();
-    if (!identical(unitA, unitB)) {
-      int r = unitA.script.uri.path.compareTo(unitB.script.uri.path);
-      if (r != 0) return r;
-    }
+    int r = a.getLibrary().compareTo(b.getLibrary());
+    if (r != 0) return r;
+    r = a.getCompilationUnit().compareTo(b.getCompilationUnit());
+    if (r != 0) return r;
     Token positionA = a.position();
     Token positionB = b.position();
-    int r = positionA.charOffset.compareTo(positionB.charOffset);
+    r = positionA.charOffset.compareTo(positionB.charOffset);
     if (r != 0) return r;
     r = a.name.slowToString().compareTo(b.name.slowToString());
     if (r != 0) return r;
@@ -548,6 +547,16 @@
     }
     return false;
   }
+
+  static bool isUnusedLabel(LabeledStatement node, TreeElements elements) {
+    Node body = node.statement;
+    TargetElement element = elements[body];
+    // Labeled statements with no element on the body have no breaks.
+    // A different target statement only happens if the body is itself
+    // a break or continue for a different target. In that case, this
+    // label is also always unused.
+    return element == null || element.statement != body;
+  }
 }
 
 abstract class ErroneousElement extends Element implements FunctionElement {
@@ -578,6 +587,8 @@
   void addMember(Element element, DiagnosticListener listener);
   void setPartOf(PartOf tag, DiagnosticListener listener);
   bool get hasMembers;
+
+  int compareTo(CompilationUnitElement other);
 }
 
 abstract class LibraryElement extends Element implements ScopeContainerElement {
@@ -639,6 +650,8 @@
 
   bool hasLibraryName();
   String getLibraryOrScriptName();
+
+  int compareTo(LibraryElement other);
 }
 
 abstract class PrefixElement extends Element {
@@ -837,11 +850,10 @@
 
   void forEachMember(void f(ClassElement enclosingClass, Element member),
                      {includeBackendMembers: false,
-                      includeSuperMembers: false});
+                      includeSuperAndInjectedMembers: false});
 
   void forEachInstanceField(void f(ClassElement enclosingClass, Element field),
-                            {includeBackendMembers: false,
-                             includeSuperMembers: false});
+                            {includeSuperAndInjectedMembers: false});
 
   void forEachBackendMember(void f(Element member));
 }
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 0cb0a4d..d8f90d4 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -84,6 +84,7 @@
   bool isTypedef() => identical(kind, ElementKind.TYPEDEF);
   bool isTypeVariable() => identical(kind, ElementKind.TYPE_VARIABLE);
   bool isField() => identical(kind, ElementKind.FIELD);
+  bool isFieldParameter() => identical(kind, ElementKind.FIELD_PARAMETER);
   bool isAbstractField() => identical(kind, ElementKind.ABSTRACT_FIELD);
   bool isGetter() => identical(kind, ElementKind.GETTER);
   bool isSetter() => identical(kind, ElementKind.SETTER);
@@ -525,6 +526,11 @@
   }
 
   bool get hasMembers => !localMembers.isEmpty;
+
+  int compareTo(CompilationUnitElement other) {
+    if (this == other) return 0;
+    return '${script.uri}'.compareTo('${other.script.uri}');
+  }
 }
 
 class LibraryElementX extends ElementX implements LibraryElement {
@@ -770,6 +776,11 @@
       return 'library(${getLibraryOrScriptName()})';
     }
   }
+
+  int compareTo(LibraryElement other) {
+    if (this == other) return 0;
+    return getLibraryOrScriptName().compareTo(other.getLibraryOrScriptName());
+  }
 }
 
 class PrefixElementX extends ElementX implements PrefixElement {
@@ -1498,6 +1509,8 @@
   void setDefaultConstructor(FunctionElement constructor, Compiler compiler);
 
   void addBackendMember(Element member) {
+    // TODO(ngeoffray): Deprecate this method.
+    assert(member.isGenerativeConstructorBody());
     backendMembers = backendMembers.prepend(member);
   }
 
@@ -1590,6 +1603,11 @@
          current != null;
          current = current.superclass) {
       Element member = current.lookupLocalMember(name);
+      if (member == null && current.isPatched) {
+        // Doing lookups on selectors is done after resolution, so it
+        // is safe to look in the patch class.
+        member = current.patch.lookupLocalMember(name);
+      }
       if (member == null) continue;
       // Private members from a different library are not visible.
       if (isPrivate && !identical(library, member.getLibrary())) continue;
@@ -1715,7 +1733,7 @@
    * Runs through all members of this class.
    *
    * The enclosing class is passed to the callback. This is useful when
-   * [includeSuperMembers] is [:true:].
+   * [includeSuperAndInjectedMembers] is [:true:].
    *
    * When called on an implementation element both the members in the origin
    * and patch class are included.
@@ -1723,8 +1741,8 @@
   // TODO(johnniwinther): Clean up lookup to get rid of the include predicates.
   void forEachMember(void f(ClassElement enclosingClass, Element member),
                      {includeBackendMembers: false,
-                      includeSuperMembers: false}) {
-    bool includeInjectedMembers = isPatch;
+                      includeSuperAndInjectedMembers: false}) {
+    bool includeInjectedMembers = includeSuperAndInjectedMembers || isPatch;
     Set<ClassElement> seen = new Set<ClassElement>();
     ClassElement classElement = declaration;
     do {
@@ -1746,7 +1764,9 @@
           });
         }
       }
-      classElement = includeSuperMembers ? classElement.superclass : null;
+      classElement = includeSuperAndInjectedMembers
+          ? classElement.superclass
+          : null;
     } while(classElement != null);
   }
 
@@ -1754,18 +1774,13 @@
    * Runs through all instance-field members of this class.
    *
    * The enclosing class is passed to the callback. This is useful when
-   * [includeSuperMembers] is [:true:].
-   *
-   * When [includeBackendMembers] and [includeSuperMembers] are both [:true:]
-   * then the fields are visited in the same order as they need to be given
-   * to the JavaScript constructor.
+   * [includeSuperAndInjectedMembers] is [:true:].
    *
    * When called on the implementation element both the fields declared in the
    * origin and in the patch are included.
    */
   void forEachInstanceField(void f(ClassElement enclosingClass, Element field),
-                            {includeBackendMembers: false,
-                             includeSuperMembers: false}) {
+                            {includeSuperAndInjectedMembers: false}) {
     // Filters so that [f] is only invoked with instance fields.
     void fieldFilter(ClassElement enclosingClass, Element member) {
       if (member.isInstanceMember() && member.kind == ElementKind.FIELD) {
@@ -1774,8 +1789,7 @@
     }
 
     forEachMember(fieldFilter,
-                  includeBackendMembers: includeBackendMembers,
-                  includeSuperMembers: includeSuperMembers);
+        includeSuperAndInjectedMembers: includeSuperAndInjectedMembers);
   }
 
   void forEachBackendMember(void f(Element member)) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 79ad151..b4bfbdb 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -646,6 +646,7 @@
   ClassElement jsDoubleClass;
   ClassElement jsNullClass;
   ClassElement jsBoolClass;
+  ClassElement jsUnknownClass;
 
   ClassElement jsIndexableClass;
   ClassElement jsMutableIndexableClass;
@@ -862,7 +863,7 @@
     if (uses == null) return null;
     Set<ClassElement> result = null;
     for (MixinApplicationElement use in uses) {
-      Iterable<ClassElement> subclasses = compiler.world.subclasses[use];
+      Iterable<ClassElement> subclasses = compiler.world.subclassesOf(use);
       if (subclasses != null) {
         for (ClassElement subclass in subclasses) {
           if (subclass.isNative()) {
@@ -921,7 +922,10 @@
       jsFixedArrayClass =
           compiler.findInterceptor(const SourceString('JSFixedArray')),
       jsExtendableArrayClass =
-          compiler.findInterceptor(const SourceString('JSExtendableArray'))];
+          compiler.findInterceptor(const SourceString('JSExtendableArray')),
+      jsUnknownClass =
+          compiler.findInterceptor(const SourceString('JSUnknown')),
+    ];
 
     jsIndexableClass =
         compiler.findInterceptor(const SourceString('JSIndexable'));
@@ -1012,7 +1016,7 @@
           classesMixedIntoNativeClasses.add(mixinApplication.mixin);
         }
       },
-      includeSuperMembers: true);
+      includeSuperAndInjectedMembers: true);
     }
   }
 
@@ -1028,7 +1032,7 @@
               member.name, () => new Set<Element>());
           set.add(member);
         },
-        includeSuperMembers: true);
+        includeSuperAndInjectedMembers: true);
     }
     enqueuer.registerInstantiatedClass(cls, elements);
   }
@@ -1124,6 +1128,8 @@
       addInterceptors(jsIntClass, enqueuer, elements);
       addInterceptors(jsDoubleClass, enqueuer, elements);
       addInterceptors(jsNumberClass, enqueuer, elements);
+    } else if (cls == jsUnknownClass) {
+      addInterceptors(jsUnknownClass, enqueuer, elements);
     } else if (cls.isNative()) {
       addInterceptorsForNativeClassMembers(cls, enqueuer);
     }
@@ -1134,7 +1140,7 @@
         if (!member.isInstanceMember() || !member.isField()) return;
         DartType type = member.computeType(compiler);
         enqueuer.registerIsCheck(type, elements);
-      }, includeSuperMembers: true);
+      }, includeSuperAndInjectedMembers: true);
     }
   }
 
@@ -1177,8 +1183,11 @@
     enqueueInResolution(getStringInterpolationHelper(), elements);
   }
 
-  void registerCatchStatement(TreeElements elements) {
+  void registerCatchStatement(Enqueuer enqueuer, TreeElements elements) {
     enqueueInResolution(getExceptionUnwrapper(), elements);
+    if (jsUnknownClass != null) {
+      enqueuer.registerInstantiatedClass(jsUnknownClass, elements);
+    }
   }
 
   void registerWrapException(TreeElements elements) {
@@ -1680,7 +1689,8 @@
             ? const SourceString("stringSuperTypeCast")
             : const SourceString('stringSuperTypeCheck');
       }
-    } else if (element == compiler.listClass || element == jsArrayClass) {
+    } else if ((element == compiler.listClass || element == jsArrayClass) &&
+               type.isRaw) {
       if (nativeCheckOnly) return null;
       return typeCast
           ? const SourceString("listTypeCast")
@@ -1704,15 +1714,18 @@
               ? const SourceString("interceptedTypeCast")
               : const SourceString('interceptedTypeCheck');
         } else {
-          if (typeCast) {
-            return const SourceString("propertyTypeCast");
-          }
           if (type.kind == TypeKind.INTERFACE && !type.isRaw) {
-            return const SourceString('assertSubtype');
+            return typeCast
+                ? const SourceString('subtypeCast')
+                : const SourceString('assertSubtype');
           } else if (type.kind == TypeKind.TYPE_VARIABLE) {
-            return const SourceString('assertSubtypeOfRuntimeType');
+            return typeCast
+                ? const SourceString('subtypeOfRuntimeTypeCast')
+                : const SourceString('assertSubtypeOfRuntimeType');
           } else {
-            return const SourceString('propertyTypeCheck');
+            return typeCast
+                ? const SourceString('propertyTypeCast')
+                : const SourceString('propertyTypeCheck');
           }
         }
       }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
index 9273ad7..2b4d152 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -269,8 +269,7 @@
           }
           emittedArgumentCount++;
         },
-        includeBackendMembers: true,
-        includeSuperMembers: true);
+        includeSuperAndInjectedMembers: true);
 
     if ((constant.protoValue == null && emittedArgumentCount != 3) ||
         (constant.protoValue != null && emittedArgumentCount != 4)) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index a1f1c9a..e269d41 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1197,8 +1197,7 @@
 
     classElement.implementation.forEachMember(
         visitMember,
-        includeBackendMembers: true,
-        includeSuperMembers: false);
+        includeBackendMembers: true);
 
     if (identical(classElement, compiler.objectClass)
         && compiler.enabledNoSuchMethod) {
@@ -1349,8 +1348,7 @@
     // superclasses for non-instantiated classes.
     classElement.implementation.forEachInstanceField(
         visitField,
-        includeBackendMembers: true,
-        includeSuperMembers: isInstantiated);
+        includeSuperAndInjectedMembers: isInstantiated);
   }
 
   void generateGetter(Element member, String fieldName, String accessorName,
@@ -1800,8 +1798,15 @@
             .where(isStaticFunction)
             .toSet();
 
+    LibraryElement previousLibrary = null;
     for (Element element in Elements.sortedByPosition(elements)) {
       CodeBuffer buffer = bufferForElement(element, eagerBuffer);
+      LibraryElement library = element.getLibrary();
+      if (library != previousLibrary) {
+        previousLibrary = library;
+        addComment(
+            'Library: ${library.getLibraryOrScriptName()}', buffer);
+      }
       jsAst.Expression code = backend.generatedCode[element];
       emitStaticFunction(buffer, namer.getName(element), code);
       jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
@@ -1811,6 +1816,9 @@
       }
     }
 
+    if (!pendingElementsWithBailouts.isEmpty) {
+      addComment('pendingElementsWithBailouts', eagerBuffer);
+    }
     // Is it possible the primary function was inlined but the bailout was not?
     for (Element element in
              Elements.sortedByPosition(pendingElementsWithBailouts)) {
@@ -2601,6 +2609,14 @@
                   ['receiver'])));
 
     } else {
+      ClassElement jsUnknown = backend.jsUnknownClass;
+      if (compiler.codegenWorld.instantiatedClasses.contains(jsUnknown)) {
+        block.statements.add(
+            js.if_(js('!(receiver instanceof #)',
+                      js(namer.isolateAccess(compiler.objectClass))),
+                   buildReturnInterceptor(jsUnknown)));
+      }
+
       block.statements.add(js.return_(js('receiver')));
     }
 
@@ -2958,7 +2974,14 @@
       // Might create boundClosures.
       if (!regularClasses.isEmpty) {
         addComment('Classes', mainBuffer);
+        LibraryElement previousLibrary = null;
         for (ClassElement element in regularClasses) {
+          LibraryElement library =  element.getLibrary();
+          if (library != previousLibrary) {
+            previousLibrary = library;
+            addComment(
+                'Library: ${library.getLibraryOrScriptName()}', mainBuffer);
+          }
           generateClass(element, mainBuffer);
         }
       }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
index 0c02e6e..21f07e2 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -115,7 +115,7 @@
       classesNeedingRti.add(cls);
 
       // TODO(ngeoffray): This should use subclasses, not subtypes.
-      Set<ClassElement> classes = compiler.world.subtypes[cls];
+      Set<ClassElement> classes = compiler.world.subtypesOf(cls);
       if (classes != null) {
         classes.forEach((ClassElement sub) {
           potentiallyAddForRti(sub);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
index d5dccf6..35de8a8 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
@@ -139,6 +139,9 @@
   }
 
   record = lookupDispatchRecord(object);
+  if (record == null) {
+    return const JSUnknown();
+  }
   setDispatchProperty(JS('', 'Object.getPrototypeOf(#)', object), record);
   return getNativeInterceptor(object);
 }
@@ -335,6 +338,15 @@
   Type get runtimeType => Null;
 }
 
+class JSUnknown extends Interceptor {
+  const JSUnknown();
+
+  String toString() => JS('String', 'String(#)', this);
+
+  int get hashCode => 0;
+
+  Type get runtimeType => null;
+}
 
 /**
  * The supertype for JSString and JSArray. Used by the backend as to
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index f5350d1..56e7221 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -19,7 +19,8 @@
                                  makeDispatchRecord,
                                  setDispatchProperty,
                                  Interceptor,
-                                 JSMutableIndexable;
+                                 JSMutableIndexable,
+                                 JSUnknown;
 import "dart:_collection-dev" as _symbol_dev;
 
 part 'constant_map.dart';
@@ -294,6 +295,13 @@
   /** [: r"$".codeUnitAt(0) :] */
   static const int DOLLAR_CHAR_VALUE = 36;
 
+  /// Creates a string containing the complete type for the class [className]
+  /// with the given type arguments.
+  static String formatType(String className, List typeArguments) {
+    return '$className${joinArguments(typeArguments, 0)}';
+  }
+
+  /// Returns the type of [object] as a string (including type arguments).
   static String objectTypeName(Object object) {
     String name = constructorNameFallback(object);
     if (name == 'Object') {
@@ -306,8 +314,10 @@
     }
     // TODO(kasperl): If the namer gave us a fresh global name, we may
     // want to remove the numeric suffix that makes it unique too.
-    if (identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) name = name.substring(1);
-    return name;
+    if (identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) {
+      name = name.substring(1);
+    }
+    return formatType(name, getRuntimeTypeInfo(object));
   }
 
   static String objectToString(Object object) {
@@ -757,8 +767,13 @@
 unwrapException(ex) {
   // Note that we are checking if the object has the property. If it
   // has, it could be set to null if the thrown value is null.
+  if (ex == null) return null;
+  if (JS('bool', 'typeof # !== "object"', ex)) return ex;
+
   if (JS('bool', r'"dartException" in #', ex)) {
     return JS('', r'#.dartException', ex);
+  } else if (!JS('bool', r'"message" in #', ex)) {
+    return ex;
   }
 
   // Grab hold of the exception message. This field is available on
@@ -795,7 +810,7 @@
           message.endsWith('is null or undefined') ||
           message.endsWith('of undefined') ||
           message.endsWith('of null')) {
-        return new NoSuchMethodError(null, '<unknown>', [], {});
+        return new NoSuchMethodError(null, message, [], {});
       } else if (contains(message, ' has no method ') ||
                  contains(message, ' is not a function') ||
                  (ieErrorCode == 438 && ieFacilityNumber == 10)) {
@@ -805,7 +820,7 @@
         // Object doesn't support property or method 'foo' which sets the error
         // code 438 in IE.
         // TODO(kasperl): Compute the right name if possible.
-        return new NoSuchMethodError('', '<unknown>', [], {});
+        return new NoSuchMethodError('', message, [], {});
       }
     }
 
@@ -846,7 +861,13 @@
  * exception.
  */
 StackTrace getTraceFromException(exception) {
-  return new _StackTrace(JS("var", r"#.stack", exception));
+  if (exception == null) return null;
+  if (JS('bool', 'typeof # !== "object"', exception)) return null;
+  if (JS('bool', r'"stack" in #', exception)) {
+    return new _StackTrace(JS("var", r"#.stack", exception));
+  } else {
+    return null;
+  }
 }
 
 class _StackTrace implements StackTrace {
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
index 2085dc4..21be9af 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
@@ -134,14 +134,27 @@
   return checkArguments(substitution, arguments, checks);
 }
 
+String computeTypeName(String isField, List arguments) {
+  // Shorten the field name to the class name and append the textual
+  // representation of the type arguments.
+  int prefixLength = JS_OPERATOR_IS_PREFIX().length;
+  return Primitives.formatType(isField.substring(prefixLength, isField.length),
+                               arguments);
+}
+
+Object subtypeCast(Object object, String isField, List checks, String asField) {
+  if (!checkSubtype(object, isField, checks, asField)) {
+    String actualType = Primitives.objectTypeName(object);
+    String typeName = computeTypeName(isField, checks);
+    throw new CastErrorImplementation(object, typeName);
+  }
+  return object;
+}
+
 Object assertSubtype(Object object, String isField, List checks,
                      String asField) {
   if (!checkSubtype(object, isField, checks, asField)) {
-    // Shorten the field name to the class name and append the textual
-    // representation of the type arguments.
-    int prefixLength = JS_OPERATOR_IS_PREFIX().length;
-    String typeName = '${isField.substring(prefixLength, isField.length)}'
-                      '${joinArguments(checks, 0)}';
+    String typeName = computeTypeName(isField, checks);
     throw new TypeErrorImplementation(object, typeName);
   }
   return object;
@@ -212,6 +225,14 @@
   return isSubtype(type, t);
 }
 
+Object subtypeOfRuntimeTypeCast(Object object, var type) {
+  if (!checkSubtypeOfRuntimeType(object, type)) {
+    String actualType = Primitives.objectTypeName(object);
+    throw new CastErrorImplementation(actualType, runtimeTypeToString(type));
+  }
+  return object;
+}
+
 Object assertSubtypeOfRuntimeType(Object object, var type) {
   if (!checkSubtypeOfRuntimeType(object, type)) {
     throw new TypeErrorImplementation(object, runtimeTypeToString(type));
diff --git a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
index 1fa69ec..b7a1f44 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart
@@ -79,9 +79,11 @@
   if (object == null) return 'Null';
   var constructor = JS('var', "#.constructor", object);
   if (identical(JS('String', "typeof(#)", constructor), 'function')) {
+    var name = JS('var', r'#.builtin$cls', constructor);
+    if (name != null) return name;
     // The constructor isn't null or undefined at this point. Try
     // to grab hold of its name.
-    var name = JS('var', '#.name', constructor);
+    name = JS('var', '#.name', constructor);
     // If the name is a non-empty string, we use that as the type
     // name of this object. On Firefox, we often get 'Object' as
     // the constructor name even for more specialized objects so
@@ -269,6 +271,7 @@
 
 lookupInterceptor(var hasOwnPropertyFunction, String tag) {
   var map = interceptorsByTag;
+  if (map == null) return null;
   return callHasOwnProperty(hasOwnPropertyFunction, map, tag)
       ? propertyGet(map, tag)
       : null;
@@ -288,11 +291,17 @@
     }
   }
   if (interceptor == null) {
-    // TODO(sra): Think about the error case.
-    interceptor = JS('', '{__what: "interceptor not found", __tag: #}', tag);
+    // This object is not known to Dart.  There could be several
+    // reasons for that, including (but not limited to):
+    // * A bug in native code (hopefully this is caught during development).
+    // * An unknown DOM object encountered.
+    // * JavaScript code running in an unexpected context.  For
+    //   example, on node.js.
+    return null;
   }
-  var isLeaf = JS('', '#[#]', leafTags, tag);
-  if (true == isLeaf) {
+  var isLeaf =
+      (leafTags != null) && JS('bool', '(#[#]) === true', leafTags, tag);
+  if (isLeaf) {
     return makeDispatchRecord(interceptor, false, null);
   } else {
     var proto = JS('', 'Object.getPrototypeOf(#)', obj);
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index e196afa..9be802d 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -1587,7 +1587,7 @@
           String fieldName = field.name.slowToString();
           _fieldMapCache.putIfAbsent(fieldName, () => _constant.fields[index]);
           index++;
-        }, includeBackendMembers: true, includeSuperMembers: true);
+        }, includeSuperAndInjectedMembers: true);
       }
     }
     return _fieldMapCache;
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index c6a7a9a..b4fe9d9 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -876,7 +876,7 @@
     // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
     element.mapping = mapping;
     return compiler.withCurrentElement(element, () {
-      measure(() {
+      return measure(() {
         Typedef node =
           compiler.parser.measure(() => element.parseNode(compiler));
         TypedefResolverVisitor visitor =
@@ -2201,6 +2201,10 @@
         compiler.backend.registerClassUsingVariableExpression(cls);
         compiler.backend.registerTypeVariableExpression(mapping);
       } else if (target.impliesType() && !sendIsMemberAccess) {
+        // Set the type of the node to [Type] to mark this send as a
+        // type literal.
+        mapping.setType(node, compiler.typeClass.computeType(compiler));
+        world.registerInstantiatedClass(compiler.typeClass, mapping);
         compiler.backend.registerTypeLiteral(mapping);
       }
     }
@@ -2556,8 +2560,7 @@
         (ClassElement enclosingClass, Element member) {
           world.addToWorkList(member);
         },
-        includeBackendMembers: false,
-        includeSuperMembers: true);
+        includeSuperAndInjectedMembers: true);
 
     if (isSymbolConstructor) {
       if (node.isConst()) {
@@ -2968,7 +2971,7 @@
   }
 
   visitCatchBlock(CatchBlock node) {
-    compiler.backend.registerCatchStatement(mapping);
+    compiler.backend.registerCatchStatement(world, mapping);
     // Check that if catch part is present, then
     // it has one or two formal parameters.
     if (node.formals != null) {
@@ -3740,7 +3743,19 @@
       requiredParameterCount  = parametersBuilder.length;
       parameters = parametersBuilder.toLink();
     }
-    DartType returnType = compiler.resolveReturnType(element, returnNode);
+    DartType returnType;
+    if (element.isFactoryConstructor()) {
+      returnType = element.getEnclosingClass().computeType(compiler);
+      // Because there is no type annotation for the return type of
+      // this element, we explicitly add one.
+      if (compiler.enableTypeAssertions) {
+        compiler.enqueuer.resolution.registerIsCheck(
+            returnType, new TreeElementMapping(element));
+      }
+    } else {
+      returnType = compiler.resolveReturnType(element, returnNode);
+    }
+
     if (element.isSetter() && (requiredParameterCount != 1 ||
                                visitor.optionalParameterCount != 0)) {
       // If there are no formal parameters, we already reported an error above.
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 1722f9f..ae43bed 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -103,10 +103,7 @@
   }
 
   HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) {
-    // The body of the constructor will be generated in a separate function.
-    final ClassElement classElement = work.element.getEnclosingClass();
-    return builder.buildFactory(classElement.implementation,
-                                work.element.implementation);
+    return builder.buildFactory(work.element);
   }
 }
 
@@ -279,8 +276,7 @@
       builder.graph.thisInstruction = thisInstruction;
       builder.graph.entry.addAtEntry(thisInstruction);
       updateLocal(closureData.closureElement, thisInstruction);
-    } else if (element.isInstanceMember()
-               || element.isGenerativeConstructor()) {
+    } else if (element.isInstanceMember()) {
       // Once closures have been mapped to classes their instance members might
       // not have any thisElement if the closure was created inside a static
       // context.
@@ -376,7 +372,7 @@
       Element redirect = redirectionMapping[element];
       HInstruction receiver = readLocal(closureData.closureElement);
       HInstruction fieldGet = new HFieldGet(redirect, receiver);
-      fieldGet.instructionType = builder.getTypeOfCapturedVariable(element);
+      fieldGet.instructionType = builder.getTypeOfCapturedVariable(redirect);
       builder.add(fieldGet);
       return fieldGet;
     } else if (isBoxed(element)) {
@@ -389,7 +385,7 @@
       assert(redirect.enclosingElement.isVariable());
       HInstruction box = readLocal(redirect.enclosingElement);
       HInstruction lookup = new HFieldGet(redirect, box);
-      lookup.instructionType = builder.getTypeOfCapturedVariable(element);
+      lookup.instructionType = builder.getTypeOfCapturedVariable(redirect);
       builder.add(lookup);
       return lookup;
     } else {
@@ -1014,6 +1010,7 @@
       new Map<Element, HType>();
 
   HType getTypeOfCapturedVariable(Element element) {
+    assert(element.isField());
     return cachedTypesOfCapturedVariables.putIfAbsent(element, () {
       return new HType.inferredTypeForElement(element, compiler);
     });
@@ -1116,6 +1113,7 @@
   }
 
   HParameterValue addParameter(Element element) {
+    assert(inliningStack.isEmpty);
     HParameterValue result = new HParameterValue(element);
     if (lastAddedParameter == null) {
       graph.entry.addBefore(graph.entry.first, result);
@@ -1178,7 +1176,7 @@
     // may have an impact on the state of the current method.
     InliningState state = new InliningState(
         function, returnElement, returnType, elements, stack, localsHandler);
-    LocalsHandler newLocalsHandler = new LocalsHandler.from(localsHandler);
+    LocalsHandler newLocalsHandler = new LocalsHandler(this);
     newLocalsHandler.closureData =
         compiler.closureToClassMapper.computeClosureToClassMapping(
             function, function.parseNode(compiler), elements);
@@ -1272,7 +1270,6 @@
     if (element is !PartialFunctionElement) return false;
     // TODO(ngeoffray): try to inline generative constructors. They
     // don't have any body, which make it more difficult.
-    if (element.isGenerativeConstructor()) return false;
     if (inliningStack.length > MAX_INLINING_DEPTH) return false;
     // Don't inline recursive calls. We use the same elements for the inlined
     // functions and would thus clobber our local variables.
@@ -1319,18 +1316,20 @@
     }
 
     assert(canBeInlined);
-    InliningState state = enterInlinedMethod(
-        function, selector, argumentsNodes, providedArguments, currentNode);
-    // Add an explicit null check on the receiver. We use [element]
-    // to get the same name in the NoSuchMethodError message as if we had
-    // called it.
+    // Add an explicit null check on the receiver before doing the
+    // inlining. We use [element] to get the same name in the NoSuchMethodError
+    // message as if we had called it.
     if (element.isInstanceMember()
         && (selector.mask == null || selector.mask.isNullable)) {
       addWithPosition(
           new HFieldGet(element, providedArguments[0]), currentNode);
     }
+    InliningState state = enterInlinedMethod(
+        function, selector, argumentsNodes, providedArguments, currentNode);
     inlinedFrom(element, () {
-      functionExpression.body.accept(this);
+      element.isGenerativeConstructor()
+          ? buildFactory(element)
+          : functionExpression.body.accept(this);
     });
     leaveInlinedMethod(state);
     return true;
@@ -1436,11 +1435,6 @@
       ClosureClassMap newClosureData =
           compiler.closureToClassMapper.computeClosureToClassMapping(
               constructor, node, elements);
-      // The [:this:] element now refers to the one in the new closure
-      // data, that is the [:this:] of the super constructor. We
-      // update the element to refer to the current [:this:].
-      localsHandler.updateLocal(newClosureData.thisElement,
-                                localsHandler.readThis());
       localsHandler.closureData = newClosureData;
 
       params.orderedForEachParameter((Element parameterElement) {
@@ -1564,9 +1558,7 @@
             }
             fieldValues[member] = value;
           });
-        },
-        includeBackendMembers: true,
-        includeSuperMembers: false);
+        });
   }
 
 
@@ -1578,21 +1570,20 @@
    *    to, starting from the current constructor.
    *  - Call the the constructor bodies, starting from the constructor(s) in the
    *    super class(es).
-   *
-   * Invariant: Both [classElement] and [functionElement] must be
-   * implementation elements.
    */
-  HGraph buildFactory(ClassElement classElement,
-                      FunctionElement functionElement) {
-    assert(invariant(classElement, classElement.isImplementation));
-    assert(invariant(functionElement, functionElement.isImplementation));
+  HGraph buildFactory(FunctionElement functionElement) {
+    functionElement = functionElement.implementation;
+    ClassElement classElement =
+        functionElement.getEnclosingClass().implementation;
     FunctionExpression function = functionElement.parseNode(compiler);
     // Note that constructors (like any other static function) do not need
     // to deal with optional arguments. It is the callers job to provide all
     // arguments as if they were positional.
 
-    // The initializer list could contain closures.
-    openFunction(functionElement, function);
+    if (inliningStack.isEmpty) {
+      // The initializer list could contain closures.
+      openFunction(functionElement, function);
+    }
 
     Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>();
 
@@ -1624,8 +1615,7 @@
           constructorArguments.add(potentiallyCheckType(
               fieldValues[member], member.computeType(compiler)));
         },
-        includeBackendMembers: true,
-        includeSuperMembers: true);
+        includeSuperAndInjectedMembers: true);
 
     InterfaceType type = classElement.computeType(compiler);
     HType ssaType = new HType.nonNullExact(type, compiler);
@@ -1696,24 +1686,18 @@
         bodyCallInputs.add(localsHandler.readLocal(scopeData.boxElement));
       }
 
-      // TODO(ahe): The constructor name is statically resolved. See
-      // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner
-      // way to do this?
-      SourceString name =
-          new SourceString(backend.namer.getName(body.declaration));
-      // TODO(kasperl): This seems fishy. We shouldn't be inventing all
-      // these selectors. Maybe the resolver can do more of the work
-      // for us here?
-      LibraryElement library = body.getLibrary();
-      Selector selector = new Selector.call(
-          name, library, bodyCallInputs.length - 1);
-      HInvokeDynamic invoke =
-          new HInvokeDynamicMethod(selector, bodyCallInputs);
-      invoke.element = body;
+      HInvokeConstructorBody invoke =
+          new HInvokeConstructorBody(body, bodyCallInputs);
+      invoke.sideEffects = compiler.world.getSideEffectsOfElement(constructor);
       add(invoke);
     }
-    closeAndGotoExit(new HReturn(newObject));
-    return closeFunction();
+    if (inliningStack.isEmpty) {
+      closeAndGotoExit(new HReturn(newObject));
+      return closeFunction();
+    } else {
+      localsHandler.updateLocal(returnElement, newObject);
+      return null;
+    }
   }
 
   void addParameterCheckInstruction(Element element) {
@@ -1830,14 +1814,12 @@
     }
   }
 
-  HInstruction buildTypeConversion(Compiler compiler, HInstruction original,
-                                   DartType type, int kind) {
+  HInstruction buildTypeConversion(HInstruction original,
+                                   DartType type,
+                                   int kind) {
     if (type == null) return original;
     if (type.kind == TypeKind.INTERFACE && !type.isMalformed && !type.isRaw) {
      HType subtype = new HType.subtype(type, compiler);
-     if (type.isRaw) {
-       return new HTypeConversion(type, kind, subtype, original);
-     }
      HInstruction representations = buildTypeArgumentRepresentations(type);
      add(representations);
      return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
@@ -1855,8 +1837,7 @@
   HInstruction potentiallyCheckType(HInstruction original, DartType type,
       { int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
     if (!compiler.enableTypeAssertions) return original;
-    HInstruction other =
-        buildTypeConversion(compiler,  original, type, kind);
+    HInstruction other = buildTypeConversion(original, type, kind);
     if (other != original) add(other);
     return other;
   }
@@ -2487,10 +2468,9 @@
     // TODO(ahe): This should be registered in codegen, not here.
     compiler.enqueuer.codegen.registerInstantiatedClass(
         closureClassElement, work.resolutionTree);
-    assert(!closureClassElement.hasLocalScopeMembers);
 
     List<HInstruction> capturedVariables = <HInstruction>[];
-    closureClassElement.forEachBackendMember((Element member) {
+    closureClassElement.forEachMember((_, Element member) {
       // The backendMembers also contains the call method(s). We are only
       // interested in the fields.
       if (member.isField()) {
@@ -2802,8 +2782,8 @@
       Node argument = node.arguments.head;
       TypeAnnotation typeAnnotation = argument.asTypeAnnotation();
       DartType type = elements.getType(typeAnnotation);
-      HInstruction converted = expression.convertType(
-          compiler, type, HTypeConversion.CAST_TYPE_CHECK);
+      HInstruction converted = buildTypeConversion(
+          expression, type, HTypeConversion.CAST_TYPE_CHECK);
       if (converted != expression) add(converted);
       stack.add(converted);
     } else {
@@ -2847,7 +2827,7 @@
       return new HIs(type, <HInstruction>[expression, call],
                      HIs.VARIABLE_CHECK);
     } else if (RuntimeTypes.hasTypeArguments(type)) {
-      Element element = type.element;
+      ClassElement element = type.element;
       Element helper = backend.getCheckSubtype();
       HInstruction representations =
           buildTypeArgumentRepresentations(type);
@@ -2855,10 +2835,9 @@
       String operator =
           backend.namer.operatorIs(backend.getImplementationClass(element));
       HInstruction isFieldName = addConstantString(node, operator);
-      // TODO(karlklose): use [:null:] for [asField] if [element] does not
-      // have a subclass.
-      HInstruction asFieldName =
-          addConstantString(node, backend.namer.substitutionName(element));
+      HInstruction asFieldName = compiler.world.hasAnySubtype(element)
+          ? addConstantString(node, backend.namer.substitutionName(element))
+          : graph.addConstantNull(constantSystem);
       List<HInstruction> inputs = <HInstruction>[expression,
                                                  isFieldName,
                                                  representations,
@@ -4274,21 +4253,14 @@
 
   visitLabeledStatement(LabeledStatement node) {
     Statement body = node.statement;
-    if (body is Loop || body is SwitchStatement) {
+    if (body is Loop
+        || body is SwitchStatement
+        || Elements.isUnusedLabel(node, elements)) {
       // Loops and switches handle their own labels.
       visit(body);
       return;
     }
-    // Non-loop statements can only be break targets, not continue targets.
     TargetElement targetElement = elements[body];
-    if (targetElement == null || !identical(targetElement.statement, body)) {
-      // Labeled statements with no element on the body have no breaks.
-      // A different target statement only happens if the body is itself
-      // a break or continue for a different target. In that case, this
-      // label is also always unused.
-      visit(body);
-      return;
-    }
     LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler);
     assert(targetElement.isBreakTarget);
     JumpHandler handler = new JumpHandler(this, targetElement);
@@ -5083,6 +5055,7 @@
   static bool canBeInlined(FunctionExpression functionExpression,
                            TreeElements elements) {
     InlineWeeder weeder = new InlineWeeder(elements);
+    weeder.visit(functionExpression.initializers);
     weeder.visit(functionExpression.body);
     if (weeder.tooDifficult) return false;
     return true;
@@ -5098,7 +5071,7 @@
   }
 
   void visit(Node node) {
-    node.accept(this);
+    if (node != null) node.accept(this);
   }
 
   void visitNode(Node node) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 48d4466..d420f27 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -741,6 +741,10 @@
     js.Catch catchPart = null;
     js.Block finallyPart = null;
     if (info.catchBlock != null) {
+      if (backend.jsUnknownClass != null) {
+        world.registerInstantiatedClass(
+            backend.jsUnknownClass, work.resolutionTree);
+      }
       HLocalValue exception = info.catchVariable;
       String name = variableNames.getName(exception);
       js.VariableDeclaration decl = new js.VariableDeclaration(name);
@@ -1483,32 +1487,26 @@
     List<js.Expression> arguments = visitArguments(node.inputs);
     Element target = node.element;
 
-    if (target != null) {
-      // Avoid adding the generative constructor name to the list of
-      // seen selectors.
-      if (target.isGenerativeConstructorBody()) {
-        methodName = name.slowToString();
-      } else if (!node.isInterceptedCall) {
-        if (target == backend.jsArrayAdd) {
-          methodName = 'push';
-        } else if (target == backend.jsArrayRemoveLast) {
-          methodName = 'pop';
-        } else if (target == backend.jsStringSplit) {
-          methodName = 'split';
-          // Split returns a List, so we make sure the backend knows the
-          // list class is instantiated.
-          world.registerInstantiatedClass(
-              compiler.listClass, work.resolutionTree);
-        } else if (target == backend.jsStringConcat) {
-          push(new js.Binary('+', object, arguments[0]), node);
-          return;
-        } else if (target.isNative() && target.isFunction()
-                   && !node.isInterceptedCall) {
-          // A direct (i.e. non-interceptor) native call is the result of
-          // optimization.  The optimization ensures any type checks or
-          // conversions have been satisified.
-          methodName = target.fixedBackendName();
-        }
+    if (target != null && !node.isInterceptedCall) {
+      if (target == backend.jsArrayAdd) {
+        methodName = 'push';
+      } else if (target == backend.jsArrayRemoveLast) {
+        methodName = 'pop';
+      } else if (target == backend.jsStringSplit) {
+        methodName = 'split';
+        // Split returns a List, so we make sure the backend knows the
+        // list class is instantiated.
+        world.registerInstantiatedClass(
+            compiler.listClass, work.resolutionTree);
+      } else if (target == backend.jsStringConcat) {
+        push(new js.Binary('+', object, arguments[0]), node);
+        return;
+      } else if (target.isNative() && target.isFunction()
+                 && !node.isInterceptedCall) {
+        // A direct (i.e. non-interceptor) native call is the result of
+        // optimization.  The optimization ensures any type checks or
+        // conversions have been satisified.
+        methodName = target.fixedBackendName();
       }
     }
 
@@ -1519,6 +1517,14 @@
     push(jsPropertyCall(object, methodName, arguments), node);
   }
 
+  void visitInvokeConstructorBody(HInvokeConstructorBody node) {
+    use(node.inputs[0]);
+    js.Expression object = pop();
+    String methodName = backend.namer.getName(node.element);
+    List<js.Expression> arguments = visitArguments(node.inputs);
+    push(jsPropertyCall(object, methodName, arguments), node);
+  }
+
   void visitOneShotInterceptor(HOneShotInterceptor node) {
     List<js.Expression> arguments = visitArguments(node.inputs);
     var isolate = new js.VariableUse(backend.namer.CURRENT_ISOLATE);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
index ce3c0e3..c29f3e8 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen_helpers.dart
@@ -357,11 +357,17 @@
     // the builder. Mark the if instruction as such.
     controlFlowOperators.add(startIf);
 
+    // Find the next non-HGoto instruction following the phi.
+    HInstruction nextInstruction = phi.block.first;
+    while (nextInstruction is HGoto) {
+      nextInstruction = nextInstruction.block.successors[0].first;
+    }
+
     // If the operation is only used by the first instruction
     // of its block and is safe to be generated at use site, mark it
     // so.
     if (phi.usedBy.length == 1
-        && identical(phi.usedBy[0], phi.block.first)
+        && phi.usedBy[0] == nextInstruction
         && isSafeToGenerateAtUseSite(phi.usedBy[0], phi)) {
       markAsGenerateAtUseSite(phi);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 2eb8faa..088fe6e 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -37,6 +37,7 @@
   R visitInvokeDynamicSetter(HInvokeDynamicSetter node);
   R visitInvokeStatic(HInvokeStatic node);
   R visitInvokeSuper(HInvokeSuper node);
+  R visitInvokeConstructorBody(HInvokeConstructorBody node);
   R visitIs(HIs node);
   R visitLazyStatic(HLazyStatic node);
   R visitLess(HLess node);
@@ -303,6 +304,8 @@
   visitInterceptor(HInterceptor node) => visitInstruction(node);
   visitInvokeClosure(HInvokeClosure node)
       => visitInvokeDynamic(node);
+  visitInvokeConstructorBody(HInvokeConstructorBody node)
+      => visitInvokeStatic(node);
   visitInvokeDynamicMethod(HInvokeDynamicMethod node)
       => visitInvokeDynamic(node);
   visitInvokeDynamicGetter(HInvokeDynamicGetter node)
@@ -310,7 +313,7 @@
   visitInvokeDynamicSetter(HInvokeDynamicSetter node)
       => visitInvokeDynamicField(node);
   visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
-  visitInvokeSuper(HInvokeSuper node) => visitInvoke(node);
+  visitInvokeSuper(HInvokeSuper node) => visitInvokeStatic(node);
   visitJump(HJump node) => visitControlFlow(node);
   visitLazyStatic(HLazyStatic node) => visitInstruction(node);
   visitLess(HLess node) => visitRelational(node);
@@ -1083,6 +1086,15 @@
 
   HInstruction convertType(Compiler compiler, DartType type, int kind) {
     if (type == null) return this;
+    // Only the builder knows how to create [HTypeConversion]
+    // instructions with generics. It has the generic type context
+    // available.
+    assert(type.kind != TypeKind.TYPE_VARIABLE);
+    // TODO(5022): Generic typedefs should not be handled here.
+    assert(type.isRaw
+           || type.isMalformed
+           || type.kind == TypeKind.TYPEDEF
+           || type.kind == TypeKind.FUNCTION);
     if (identical(type.element, compiler.dynamicClass)) return this;
     if (identical(type.element, compiler.objectClass)) return this;
     if (type.isMalformed || type.kind != TypeKind.INTERFACE) {
@@ -1399,6 +1411,14 @@
   }
 }
 
+class HInvokeConstructorBody extends HInvokeStatic {
+  HInvokeConstructorBody(element, inputs)
+      : super(element, inputs, HType.UNKNOWN);
+
+  String toString() => 'invoke constructor body: ${element.name}';
+  accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this);
+}
+
 abstract class HFieldAccess extends HInstruction {
   final Element element;
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index 09df7c1..26523a5 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -1586,8 +1586,7 @@
               element, node.inputs[j].instructionType);
           j++;
         },
-        includeBackendMembers: false,
-        includeSuperMembers: true);
+        includeSuperAndInjectedMembers: true);
   }
 
   visitFieldSet(HFieldSet node) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index f11f5d5..02d7cfe 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -355,9 +355,7 @@
 
   String visitInvokeStatic(HInvokeStatic invoke) {
     String target = invoke.element.name.slowToString();
-    int offset = HInvoke.ARGUMENTS_OFFSET;
-    List arguments = invoke.inputs.sublist(offset);
-    return visitGenericInvoke("Invoke", target, arguments);
+    return visitGenericInvoke("Invoke", target, invoke.inputs);
   }
 
   String visitInvokeSuper(HInvokeSuper invoke) {
@@ -367,6 +365,13 @@
     return visitGenericInvoke("Invoke super", target, arguments);
   }
 
+  String visitInvokeConstructorBody(HInvokeConstructorBody invoke) {
+    String target = invoke.element.name.slowToString();
+    int offset = HInvoke.ARGUMENTS_OFFSET + 1;
+    List arguments = invoke.inputs.sublist(offset);
+    return visitGenericInvoke("Invoke constructor body", target, arguments);
+  }
+
   String visitForeign(HForeign foreign) {
     return visitGenericInvoke("Foreign", "${foreign.codeAst}", foreign.inputs);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index 20a0b64..d1d22bf 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -18,11 +18,13 @@
       return isNullable ? HType.NULL : HType.CONFLICTING;
     }
 
+    JavaScriptBackend backend = compiler.backend;
     if (mask.containsOnlyInt(compiler)) {
       return isNullable ? HType.INTEGER_OR_NULL : HType.INTEGER;
     } else if (mask.containsOnlyDouble(compiler)) {
       return isNullable ? HType.DOUBLE_OR_NULL : HType.DOUBLE;
-    } else if (mask.containsOnlyNum(compiler)) {
+    } else if (mask.containsOnlyNum(compiler)
+               || 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;
@@ -38,18 +40,17 @@
       return isNullable ? HType.UNKNOWN : HType.NON_NULL;
     }
 
-    JavaScriptBackend backend = compiler.backend;
     if (!isNullable) {
-      if (mask.containsOnly(backend.jsIndexableClass)) {
-        return HType.INDEXABLE_PRIMITIVE;
-      } else if (mask.containsOnly(backend.jsArrayClass)) {
-        return HType.READABLE_ARRAY;
-      } else if (mask.containsOnly(backend.jsMutableArrayClass)) {
-        return HType.MUTABLE_ARRAY;
-      } else if (mask.containsOnly(backend.jsFixedArrayClass)) {
+      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);
@@ -270,6 +271,8 @@
     TypeMask union = mask.union(otherMask, compiler);
     return new HType.fromMask(union, compiler);
   }
+
+  HType simplify(Compiler compiler) => this;
 }
 
 /** Used to represent [HType.UNKNOWN] and [HType.CONFLICTING]. */
@@ -561,7 +564,11 @@
   bool canBePrimitiveNumber(Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
     DartType jsNumberType = backend.jsNumberClass.computeType(compiler);
-    return mask.contains(jsNumberType, compiler);
+    DartType jsIntType = backend.jsIntClass.computeType(compiler);
+    DartType jsDoubleType = backend.jsDoubleClass.computeType(compiler);
+    return mask.contains(jsNumberType, compiler)
+        || mask.contains(jsIntType, compiler)
+        || mask.contains(jsDoubleType, compiler);
   }
 
   bool canBePrimitiveBoolean(Compiler compiler) {
@@ -588,6 +595,10 @@
 
   TypeMask computeMask(Compiler compiler) => mask;
 
+  HType simplify(Compiler compiler) {
+    return new HType.fromMask(mask.simplify(compiler), compiler);
+  }
+
   bool operator ==(HType other) {
     if (other is !HBoundedType) return false;
     HBoundedType bounded = other;
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 24faf77..b58a0eb 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -18,6 +18,22 @@
 }
 
 /**
+ * Class used to report different warnings for differrent kinds of members.
+ */
+class MemberKind {
+  static const MemberKind METHOD = const MemberKind("method");
+  static const MemberKind OPERATOR = const MemberKind("operator");
+  static const MemberKind PROPERTY = const MemberKind("property");
+
+  final String name;
+
+  const MemberKind(this.name);
+
+  String toString() => name;
+}
+
+
+/**
  * [ElementAccess] represents the access of [element], either as a property
  * access or invocation.
  */
@@ -49,6 +65,8 @@
   Element get element => member.element;
 
   DartType computeType(Compiler compiler) => member.computeType(compiler);
+
+  String toString() => 'MemberAccess($member)';
 }
 
 /// An access of an unresolved element.
@@ -60,6 +78,8 @@
   DartType computeType(Compiler compiler) => compiler.types.dynamicType;
 
   bool isCallable(Compiler compiler) => true;
+
+  String toString() => 'DynamicAccess';
 }
 
 /**
@@ -73,7 +93,19 @@
     assert(element != null);
   }
 
-  DartType computeType(Compiler compiler) => element.computeType(compiler);
+  DartType computeType(Compiler compiler) {
+    if (element.isGetter()) {
+      FunctionType functionType = element.computeType(compiler);
+      return functionType.returnType;
+    } else if (element.isSetter()) {
+      FunctionType functionType = element.computeType(compiler);
+      return functionType.parameterTypes.head;
+    } else {
+      return element.computeType(compiler);
+    }
+  }
+
+  String toString() => 'ResolvedAccess($element)';
 }
 
 /**
@@ -89,6 +121,23 @@
   Element get element => type.element;
 
   DartType computeType(Compiler compiler) => type;
+
+  String toString() => 'TypeAccess($type)';
+}
+
+/**
+ * An access of a type literal.
+ */
+class TypeLiteralAccess extends ElementAccess {
+  final Element element;
+  TypeLiteralAccess(Element this.element) {
+    assert(element != null);
+  }
+
+  DartType computeType(Compiler compiler) =>
+      compiler.typeClass.computeType(compiler);
+
+  String toString() => 'TypeLiteralAccess($element)';
 }
 
 class TypeCheckerVisitor implements Visitor<DartType> {
@@ -98,7 +147,7 @@
 
   Node lastSeenNode;
   DartType expectedReturnType;
-  ClassElement currentClass;
+  final ClassElement currentClass;
 
   Link<DartType> cascadeTypes = const Link<DartType>();
 
@@ -109,7 +158,10 @@
   DartType objectType;
   DartType listType;
 
-  TypeCheckerVisitor(this.compiler, this.elements, this.types) {
+  TypeCheckerVisitor(this.compiler, TreeElements elements, this.types)
+      : this.elements = elements,
+        currentClass = elements.currentElement != null
+            ? elements.currentElement.getEnclosingClass() : null {
     intType = compiler.intClass.computeType(compiler);
     doubleType = compiler.doubleClass.computeType(compiler);
     boolType = compiler.boolClass.computeType(compiler);
@@ -122,6 +174,11 @@
     compiler.reportWarning(node, new TypeWarning(kind, arguments));
   }
 
+  reportTypeInfo(Spannable node, MessageKind kind, [Map arguments = const {}]) {
+    compiler.reportDiagnostic(compiler.spanFromSpannable(node),
+        'Info: ${kind.message(arguments)}', api.Diagnostic.INFO);
+  }
+
   // TODO(karlklose): remove these functions.
   DartType unhandledStatement() => StatementType.NOT_RETURNING;
   DartType unhandledExpression() => types.dynamicType;
@@ -160,15 +217,17 @@
    * Check if a value of type t can be assigned to a variable,
    * parameter or return value of type s.
    */
-  checkAssignable(Node node, DartType s, DartType t) {
-    if (!types.isAssignable(s, t)) {
+  bool checkAssignable(Node node, DartType from, DartType to) {
+    if (!types.isAssignable(from, to)) {
       reportTypeWarning(node, MessageKind.NOT_ASSIGNABLE,
-                        {'fromType': s, 'toType': t});
+                        {'fromType': from, 'toType': to});
+      return false;
     }
+    return true;
   }
 
   checkCondition(Expression condition) {
-    checkAssignable(condition, boolType, analyze(condition));
+    checkAssignable(condition, analyze(condition), boolType);
   }
 
   void pushCascadeType(DartType type) {
@@ -260,7 +319,6 @@
     }
     DartType previous = expectedReturnType;
     expectedReturnType = returnType;
-    if (element.isMember()) currentClass = element.getEnclosingClass();
     StatementType bodyType = analyze(node.body);
     if (returnType != types.voidType && returnType != types.dynamicType
         && bodyType != StatementType.RETURNING) {
@@ -297,7 +355,8 @@
     return unhandledStatement();
   }
 
-  ElementAccess lookupMethod(Node node, DartType type, SourceString name) {
+  ElementAccess lookupMember(Node node, DartType type, SourceString name,
+                             MemberKind memberKind) {
     if (identical(type, types.dynamicType)) {
       return const DynamicAccess();
     }
@@ -305,17 +364,35 @@
     if (member != null) {
       return new MemberAccess(member);
     }
-    reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND,
-                      {'className': type.name, 'memberName': name});
+    switch (memberKind) {
+      case MemberKind.METHOD:
+        reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND,
+            {'className': type.name, 'memberName': name});
+        break;
+      case MemberKind.OPERATOR:
+        reportTypeWarning(node, MessageKind.OPERATOR_NOT_FOUND,
+            {'className': type.name, 'memberName': name});
+        break;
+      case MemberKind.PROPERTY:
+        reportTypeWarning(node, MessageKind.PROPERTY_NOT_FOUND,
+            {'className': type.name, 'memberName': name});
+        break;
+    }
     return const DynamicAccess();
   }
 
-  // TODO(johnniwinther): Provide the element from which the type came in order
-  // to give better error messages.
-  void analyzeArguments(Send send, DartType type) {
+  DartType lookupMemberType(Node node, DartType type, SourceString name,
+                            MemberKind memberKind) {
+    return lookupMember(node, type, name, memberKind).computeType(compiler);
+  }
+
+  void analyzeArguments(Send send, Element element, DartType type,
+                        [LinkBuilder<DartType> argumentTypes]) {
     Link<Node> arguments = send.arguments;
     DartType unaliasedType = type.unalias(compiler);
     if (identical(unaliasedType.kind, TypeKind.FUNCTION)) {
+      assert(invariant(send, element != null, message: 'No element for $send'));
+      bool error = false;
       FunctionType funType = unaliasedType;
       Link<DartType> parameterTypes = funType.parameterTypes;
       Link<DartType> optionalParameterTypes = funType.optionalParameterTypes;
@@ -328,57 +405,80 @@
           DartType namedParameterType =
               funType.getNamedParameterType(argumentName);
           if (namedParameterType == null) {
+            error = true;
             // TODO(johnniwinther): Provide better information on the called
             // function.
             reportTypeWarning(argument, MessageKind.NAMED_ARGUMENT_NOT_FOUND,
                 {'argumentName': argumentName});
 
-            analyze(argument);
+            DartType argumentType = analyze(argument);
+            if (argumentTypes != null) argumentTypes.addLast(argumentType);
           } else {
-            checkAssignable(argument, namedParameterType, analyze(argument));
+            DartType argumentType = analyze(argument);
+            if (argumentTypes != null) argumentTypes.addLast(argumentType);
+            if (!checkAssignable(argument, argumentType, namedParameterType)) {
+              error = true;
+            }
           }
         } else {
           if (parameterTypes.isEmpty) {
             if (optionalParameterTypes.isEmpty) {
+              error = true;
               // TODO(johnniwinther): Provide better information on the
               // called function.
               reportTypeWarning(argument, MessageKind.ADDITIONAL_ARGUMENT);
 
-              analyze(argument);
+              DartType argumentType = analyze(argument);
+              if (argumentTypes != null) argumentTypes.addLast(argumentType);
             } else {
-              checkAssignable(argument, optionalParameterTypes.head,
-                              analyze(argument));
+              DartType argumentType = analyze(argument);
+              if (argumentTypes != null) argumentTypes.addLast(argumentType);
+              if (!checkAssignable(argument,
+                                   argumentType, optionalParameterTypes.head)) {
+                error = true;
+              }
               optionalParameterTypes = optionalParameterTypes.tail;
             }
           } else {
-            checkAssignable(argument, parameterTypes.head, analyze(argument));
+            DartType argumentType = analyze(argument);
+            if (argumentTypes != null) argumentTypes.addLast(argumentType);
+            if (!checkAssignable(argument, argumentType, parameterTypes.head)) {
+              error = true;
+            }
             parameterTypes = parameterTypes.tail;
           }
         }
         arguments = arguments.tail;
       }
       if (!parameterTypes.isEmpty) {
+        error = true;
         // TODO(johnniwinther): Provide better information on the called
         // function.
         reportTypeWarning(send, MessageKind.MISSING_ARGUMENT,
             {'argumentType': parameterTypes.head});
       }
+      if (error) {
+        reportTypeInfo(element, MessageKind.THIS_IS_THE_METHOD);
+      }
     } else {
       while(!arguments.isEmpty) {
-        analyze(arguments.head);
+        DartType argumentType = analyze(arguments.head);
+        if (argumentTypes != null) argumentTypes.addLast(argumentType);
         arguments = arguments.tail;
       }
     }
   }
 
-  DartType analyzeInvocation(Send node, ElementAccess elementAccess) {
+  DartType analyzeInvocation(Send node, ElementAccess elementAccess,
+                             [LinkBuilder<DartType> argumentTypes]) {
     DartType type = elementAccess.computeType(compiler);
     if (elementAccess.isCallable(compiler)) {
-      analyzeArguments(node, type);
+      analyzeArguments(node, elementAccess.element, type, argumentTypes);
     } else {
       reportTypeWarning(node, MessageKind.NOT_CALLABLE,
           {'elementName': elementAccess.element.name});
-      analyzeArguments(node, types.dynamicType);
+      analyzeArguments(node, elementAccess.element, types.dynamicType,
+                       argumentTypes);
     }
     if (identical(type.kind, TypeKind.FUNCTION)) {
       FunctionType funType = type;
@@ -388,6 +488,104 @@
     }
   }
 
+  /**
+   * Computes the [ElementAccess] for [name] on the [node] possibly using the
+   * [element] provided for [node] by the resolver.
+   */
+  ElementAccess computeAccess(Send node, SourceString name, Element element,
+                              MemberKind memberKind) {
+    if (node.receiver != null) {
+      Element receiverElement = elements[node.receiver];
+      if (receiverElement != null) {
+        if (receiverElement.isPrefix()) {
+          assert(invariant(node, element != null,
+              message: 'Prefixed node has no element.'));
+          return computeResolvedAccess(node, name, element, memberKind);
+        }
+      }
+      // e.foo() for some expression e.
+      DartType receiverType = analyze(node.receiver);
+      if (receiverType.isDynamic ||
+          receiverType.isMalformed ||
+          receiverType.isVoid) {
+        return const DynamicAccess();
+      }
+      TypeKind receiverKind = receiverType.kind;
+      if (identical(receiverKind, TypeKind.TYPEDEF)) {
+        // TODO(johnniwinther): handle typedefs.
+        return const DynamicAccess();
+      }
+      if (identical(receiverKind, TypeKind.FUNCTION)) {
+        // TODO(johnniwinther): handle functions.
+        return const DynamicAccess();
+      }
+      if (identical(receiverKind, TypeKind.TYPE_VARIABLE)) {
+        // TODO(johnniwinther): handle type variables.
+        return const DynamicAccess();
+      }
+      assert(invariant(node.receiver,
+          identical(receiverKind, TypeKind.INTERFACE),
+          message: "interface type expected, got ${receiverKind}"));
+      return lookupMember(node, receiverType, name, memberKind);
+    } else {
+      return computeResolvedAccess(node, name, element, memberKind);
+    }
+  }
+
+  /**
+   * Computes the [ElementAccess] for [name] on the [node] using the [element]
+   * provided for [node] by the resolver.
+   */
+  ElementAccess computeResolvedAccess(Send node, SourceString name,
+                                      Element element, MemberKind memberKind) {
+    if (Elements.isUnresolved(element)) {
+      // foo() where foo is unresolved.
+      return const DynamicAccess();
+    } else if (element.isMember()) {
+      // foo() where foo is an instance member.
+      return lookupMember(node, currentClass.computeType(compiler),
+          name, memberKind);
+    } else if (element.isFunction()) {
+      // foo() where foo is a method in the same class.
+      return new ResolvedAccess(element);
+    } else if (element.isVariable() ||
+        element.isParameter() ||
+        element.isField()) {
+      // foo() where foo is a field in the same class.
+      return new ResolvedAccess(element);
+    } else if (element.impliesType()) {
+      // The literal `Foo` where Foo is a class, a typedef, or a type variable.
+      if (elements.getType(node) != null) {
+        assert(invariant(node, identical(compiler.typeClass,
+            elements.getType(node).element),
+            message: 'Expected type literal type: '
+              '${elements.getType(node)}'));
+        return new TypeLiteralAccess(element);
+      }
+      return new ResolvedAccess(element);
+    } else if (element.isGetter() || element.isSetter()) {
+      return new ResolvedAccess(element);
+    } else {
+      compiler.internalErrorOnElement(
+          element, 'unexpected element kind ${element.kind}');
+    }
+  }
+
+  /**
+   * Computes the type of the access of [name] on the [node] possibly using the
+   * [element] provided for [node] by the resolver.
+   */
+  DartType computeAccessType(Send node, SourceString name, Element element,
+                             MemberKind memberKind) {
+    DartType type =
+        computeAccess(node, name, element, memberKind).computeType(compiler);
+    if (type == null) {
+      compiler.internalError('type is null on access of $name on $node',
+                             node: node);
+    }
+    return type;
+  }
+
   DartType visitSend(Send node) {
     Element element = elements[node];
 
@@ -408,117 +606,252 @@
     if (node.isOperator && identical(name, 'is')) {
       analyze(node.receiver);
       return boolType;
+    } if (node.isOperator && identical(name, 'as')) {
+      analyze(node.receiver);
+      return elements.getType(node.arguments.head);
     } else if (node.isOperator) {
-      final Node firstArgument = node.receiver;
-      final DartType firstArgumentType = analyze(node.receiver);
-      final arguments = node.arguments;
-      final Node secondArgument = arguments.isEmpty ? null : arguments.head;
-      final DartType secondArgumentType =
-          analyzeWithDefault(secondArgument, null);
-
-      if (identical(name, '+') || identical(name, '=') ||
-          identical(name, '-') || identical(name, '*') ||
-          identical(name, '/') || identical(name, '%') ||
-          identical(name, '~/') || identical(name, '|') ||
-          identical(name, '&') || identical(name, '^') ||
-          identical(name, '~')|| identical(name, '<<') ||
-          identical(name, '>>') || identical(name, '[]')) {
-        return types.dynamicType;
-      } else if (identical(name, '<') || identical(name, '>') ||
-                 identical(name, '<=') || identical(name, '>=') ||
-                 identical(name, '==') || identical(name, '!=') ||
-                 identical(name, '===') || identical(name, '!==')) {
+      final Node receiver = node.receiver;
+      final DartType receiverType = analyze(receiver);
+      if (identical(name, '==') || identical(name, '!=')
+          // TODO(johnniwinther): Remove these.
+          || identical(name, '===') || identical(name, '!==')) {
+        // Analyze argument.
+        analyze(node.arguments.head);
         return boolType;
       } else if (identical(name, '||') ||
-                 identical(name, '&&') ||
-                 identical(name, '!')) {
-        checkAssignable(firstArgument, boolType, firstArgumentType);
-        if (!arguments.isEmpty) {
-          // TODO(karlklose): check number of arguments in validator.
-          checkAssignable(secondArgument, boolType, secondArgumentType);
-        }
+                 identical(name, '&&')) {
+        checkAssignable(receiver, receiverType, boolType);
+        final Node argument = node.arguments.head;
+        final DartType argumentType = analyze(argument);
+        checkAssignable(argument, argumentType, boolType);
         return boolType;
-      } else {
-        return unhandledExpression();
+      } else if (identical(name, '!')) {
+        checkAssignable(receiver, receiverType, boolType);
+        return boolType;
+      } else if (identical(name, '?')) {
+        return boolType;
       }
+      SourceString operatorName = selector.source;
+      if (identical(name, '-') && node.arguments.isEmpty) {
+        operatorName = const SourceString('unary-');
+      }
+      assert(invariant(node,
+                       identical(name, '+') || identical(name, '=') ||
+                       identical(name, '-') || identical(name, '*') ||
+                       identical(name, '/') || identical(name, '%') ||
+                       identical(name, '~/') || identical(name, '|') ||
+                       identical(name, '&') || identical(name, '^') ||
+                       identical(name, '~')|| identical(name, '<<') ||
+                       identical(name, '>>') ||
+                       identical(name, '<') || identical(name, '>') ||
+                       identical(name, '<=') || identical(name, '>=') ||
+                       identical(name, '[]'),
+                       message: 'Unexpected operator $name'));
 
+      ElementAccess access = lookupMember(node, receiverType,
+                                          operatorName, MemberKind.OPERATOR);
+      LinkBuilder<DartType> argumentTypesBuilder = new LinkBuilder<DartType>();
+      DartType resultType =
+          analyzeInvocation(node, access, argumentTypesBuilder);
+      if (identical(receiverType.element, compiler.intClass)) {
+        if (identical(name, '+') ||
+            identical(operatorName, const SourceString('-')) ||
+            identical(name, '*') ||
+            identical(name, '%')) {
+          DartType argumentType = argumentTypesBuilder.toLink().head;
+          if (identical(argumentType.element, compiler.intClass)) {
+            return intType;
+          } else if (identical(argumentType.element, compiler.doubleClass)) {
+            return doubleType;
+          }
+        }
+      }
+      return resultType;
     } else if (node.isPropertyAccess) {
-      if (node.receiver != null) {
-        // TODO(karlklose): we cannot handle fields.
-        return unhandledExpression();
-      }
-      if (element == null) return types.dynamicType;
-      return computeType(element);
-
+      ElementAccess access =
+          computeAccess(node, selector.source, element, MemberKind.PROPERTY);
+      return access.computeType(compiler);
     } else if (node.isFunctionObjectInvocation) {
       return unhandledExpression();
     } else {
-      ElementAccess computeMethod() {
-        if (node.receiver != null) {
-          // e.foo() for some expression e.
-          DartType receiverType = analyze(node.receiver);
-          if (receiverType.element == compiler.dynamicClass ||
-              receiverType == null ||
-              receiverType.isMalformed ||
-              receiverType.isVoid) {
-            return const DynamicAccess();
-          }
-          TypeKind receiverKind = receiverType.kind;
-          if (identical(receiverKind, TypeKind.TYPEDEF)) {
-            // TODO(karlklose): handle typedefs.
-            return const DynamicAccess();
-          }
-          if (identical(receiverKind, TypeKind.TYPE_VARIABLE)) {
-            // TODO(karlklose): handle type variables.
-            return const DynamicAccess();
-          }
-          if (identical(receiverKind, TypeKind.FUNCTION)) {
-            // TODO(karlklose): handle getters.
-            return const DynamicAccess();
-          }
-          assert(invariant(node.receiver,
-              identical(receiverKind, TypeKind.INTERFACE),
-              message: "interface type expected, got ${receiverKind}"));
-          return lookupMethod(selector, receiverType, selector.source);
-        } else {
-          if (Elements.isUnresolved(element)) {
-            // foo() where foo is unresolved.
-            return const DynamicAccess();
-          } else if (element.isFunction()) {
-            // foo() where foo is a method in the same class.
-            return new ResolvedAccess(element);
-          } else if (element.isVariable() || element.isField()) {
-            // foo() where foo is a field in the same class.
-            return new ResolvedAccess(element);
-          } else if (element.isGetter()) {
-            // TODO(karlklose): handle getters.
-            return const DynamicAccess();
-          } else if (element.isClass()) {
-            // TODO(karlklose): handle type literals.
-            return const DynamicAccess();
-          } else {
-            compiler.internalErrorOnElement(
-                element, 'unexpected element kind ${element.kind}');
-          }
-        }
-      }
-      return analyzeInvocation(node, computeMethod());
+      ElementAccess access =
+          computeAccess(node, selector.source, element, MemberKind.METHOD);
+      return analyzeInvocation(node, access);
     }
   }
 
+  /**
+   * Checks [: target o= value :] for some operator o, and returns the type
+   * of the result. This method also handles increment/decrement expressions
+   * like [: target++ :].
+   */
+  DartType checkAssignmentOperator(SendSet node,
+                                   SourceString operatorName,
+                                   Node valueNode,
+                                   DartType value) {
+    assert(invariant(node, !node.isIndex));
+    Element element = elements[node];
+    Identifier selector = node.selector;
+    DartType target =
+        computeAccessType(node, selector.source, element, MemberKind.PROPERTY);
+    // [operator] is the type of operator+ or operator- on [target].
+    DartType operator =
+        lookupMemberType(node, target, operatorName, MemberKind.OPERATOR);
+    if (operator is FunctionType) {
+      FunctionType operatorType = operator;
+      // [result] is the type of target o value.
+      DartType result = operatorType.returnType;
+      DartType operatorArgument = operatorType.parameterTypes.head;
+      // Check target o value.
+      bool validValue = checkAssignable(valueNode, value, operatorArgument);
+      if (validValue || !(node.isPrefix || node.isPostfix)) {
+        // Check target = result.
+        checkAssignable(node.assignmentOperator, result, target);
+      }
+      return node.isPostfix ? target : result;
+    }
+    return types.dynamicType;
+  }
+
+  /**
+   * Checks [: base[key] o= value :] for some operator o, and returns the type
+   * of the result. This method also handles increment/decrement expressions
+   * like [: base[key]++ :].
+   */
+  DartType checkIndexAssignmentOperator(SendSet node,
+                                        SourceString operatorName,
+                                        Node valueNode,
+                                        DartType value) {
+    assert(invariant(node, node.isIndex));
+    final DartType base = analyze(node.receiver);
+    final Node keyNode = node.arguments.head;
+    final DartType key = analyze(keyNode);
+
+    // [indexGet] is the type of operator[] on [base].
+    DartType indexGet = lookupMemberType(
+        node, base, const SourceString('[]'), MemberKind.OPERATOR);
+    if (indexGet is FunctionType) {
+      FunctionType indexGetType = indexGet;
+      DartType indexGetKey = indexGetType.parameterTypes.head;
+      // Check base[key].
+      bool validKey = checkAssignable(keyNode, key, indexGetKey);
+
+      // [element] is the type of base[key].
+      DartType element = indexGetType.returnType;
+      // [operator] is the type of operator o on [element].
+      DartType operator = lookupMemberType(
+          node, element, operatorName, MemberKind.OPERATOR);
+      if (operator is FunctionType) {
+        FunctionType operatorType = operator;
+
+        // Check base[key] o value.
+        DartType operatorArgument = operatorType.parameterTypes.head;
+        bool validValue = checkAssignable(valueNode, value, operatorArgument);
+
+        // [result] is the type of base[key] o value.
+        DartType result = operatorType.returnType;
+
+        // [indexSet] is the type of operator[]= on [base].
+        DartType indexSet = lookupMemberType(
+            node, base, const SourceString('[]='), MemberKind.OPERATOR);
+        if (indexSet is FunctionType) {
+          FunctionType indexSetType = indexSet;
+          DartType indexSetKey = indexSetType.parameterTypes.head;
+          DartType indexSetValue =
+              indexSetType.parameterTypes.tail.head;
+
+          if (validKey || indexGetKey != indexSetKey) {
+            // Only check base[key] on []= if base[key] was valid for [] or
+            // if the key types differ.
+            checkAssignable(keyNode, key, indexSetKey);
+          }
+          // Check base[key] = result
+          if (validValue || !(node.isPrefix || node.isPostfix)) {
+            checkAssignable(node.assignmentOperator, result, indexSetValue);
+          }
+        }
+        return node.isPostfix ? element : result;
+      }
+    }
+    return types.dynamicType;
+  }
+
   visitSendSet(SendSet node) {
+    Element element = elements[node];
     Identifier selector = node.selector;
     final name = node.assignmentOperator.source.stringValue;
-    if (identical(name, '++') || identical(name, '--')) {
-      final Element element = elements[node.selector];
-      final DartType receiverType = computeType(element);
-      // TODO(karlklose): this should be the return type instead of int.
-      return node.isPrefix ? intType : receiverType;
+    if (identical(name, '=')) {
+      // e1 = value
+      if (node.isIndex) {
+         // base[key] = value
+        final DartType base = analyze(node.receiver);
+        final Node keyNode = node.arguments.head;
+        final DartType key = analyze(keyNode);
+        final Node valueNode = node.arguments.tail.head;
+        final DartType value = analyze(valueNode);
+        DartType indexSet = lookupMemberType(
+            node, base, const SourceString('[]='), MemberKind.OPERATOR);
+        if (indexSet is FunctionType) {
+          FunctionType indexSetType = indexSet;
+          DartType indexSetKey = indexSetType.parameterTypes.head;
+          checkAssignable(keyNode, key, indexSetKey);
+          DartType indexSetValue = indexSetType.parameterTypes.tail.head;
+          checkAssignable(node.assignmentOperator, value, indexSetValue);
+        }
+        return value;
+      } else {
+        // target = value
+        DartType target = computeAccessType(node, selector.source,
+                                            element, MemberKind.PROPERTY);
+        final Node valueNode = node.arguments.head;
+        final DartType value = analyze(valueNode);
+        checkAssignable(node.assignmentOperator, value, target);
+        return value;
+      }
+    } else if (identical(name, '++') || identical(name, '--')) {
+      // e++ or e--
+      SourceString operatorName = identical(name, '++')
+          ? const SourceString('+') : const SourceString('-');
+      if (node.isIndex) {
+        // base[key]++, base[key]--, ++base[key], or --base[key]
+        return checkIndexAssignmentOperator(
+            node, operatorName, node.assignmentOperator, intType);
+      } else {
+        // target++, target--, ++target, or --target
+        return checkAssignmentOperator(
+            node, operatorName, node.assignmentOperator, intType);
+      }
     } else {
-      DartType targetType = computeType(elements[node]);
-      Node value = node.arguments.head;
-      checkAssignable(value, targetType, analyze(value));
-      return targetType;
+      // e1 o= e2 for some operator o.
+      SourceString operatorName;
+      switch (name) {
+        case '+=': operatorName = const SourceString('+'); break;
+        case '-=': operatorName = const SourceString('-'); break;
+        case '*=': operatorName = const SourceString('*'); break;
+        case '/=': operatorName = const SourceString('/'); break;
+        case '%=': operatorName = const SourceString('%'); break;
+        case '~/=': operatorName = const SourceString('~/'); break;
+        case '&=': operatorName = const SourceString('&'); break;
+        case '|=': operatorName = const SourceString('|'); break;
+        case '^=': operatorName = const SourceString('^'); break;
+        case '<<=': operatorName = const SourceString('<<'); break;
+        case '>>=': operatorName = const SourceString('>>'); break;
+        default:
+          compiler.internalError(
+              'Unexpected assignment operator $name', node: node);
+      }
+      if (node.isIndex) {
+        // base[key] o= value for some operator o.
+        final Node valueNode = node.arguments.tail.head;
+        final DartType value = analyze(valueNode);
+        return checkIndexAssignmentOperator(
+            node, operatorName, valueNode, value);
+      } else {
+        // target o= value for some operator o.
+        final Node valueNode = node.arguments.head;
+        final DartType value = analyze(valueNode);
+        return checkAssignmentOperator(node, operatorName, valueNode, value);
+      }
     }
   }
 
@@ -550,11 +883,30 @@
 
   DartType visitNewExpression(NewExpression node) {
     Element element = elements[node.send];
-    analyzeArguments(node.send, computeType(element));
-    return analyze(node.send.selector);
+    DartType constructorType = computeType(element);
+    DartType newType = elements.getType(node);
+    // TODO(johnniwinther): Use [:lookupMember:] to account for type variable
+    // substitution of parameter types.
+    if (identical(newType.kind, TypeKind.INTERFACE)) {
+      InterfaceType newInterfaceType = newType;
+      constructorType = constructorType.subst(
+          newInterfaceType.typeArguments,
+          newInterfaceType.element.typeVariables);
+    }
+    analyzeArguments(node.send, element, constructorType);
+    return newType;
   }
 
   DartType visitLiteralList(LiteralList node) {
+    InterfaceType listType = elements.getType(node);
+    DartType listElementType = listType.typeArguments.head;
+    for (Link<Node> link = node.elements.nodes;
+         !link.isEmpty;
+         link = link.tail) {
+      Node element = link.head;
+      DartType elementType = analyze(element);
+      checkAssignable(element, elementType, listElementType);
+    }
     return listType;
   }
 
@@ -610,7 +962,7 @@
           && !types.isAssignable(expressionType, types.voidType)) {
         reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID);
       } else {
-        checkAssignable(expression, expectedReturnType, expressionType);
+        checkAssignable(expression, expressionType, expectedReturnType);
       }
 
     // Let f be the function immediately enclosing a return statement of the
@@ -630,6 +982,7 @@
     return types.dynamicType;
   }
 
+  // TODO(johnniwinther): Remove this.
   DartType computeType(Element element) {
     if (Elements.isUnresolved(element)) return types.dynamicType;
     DartType result = element.computeType(compiler);
@@ -652,12 +1005,12 @@
     }
     for (Link<Node> link = node.definitions.nodes; !link.isEmpty;
          link = link.tail) {
-      Node initialization = link.head;
-      compiler.ensure(initialization is Identifier
-                      || initialization is Send);
-      if (initialization is Send) {
-        DartType initializer = analyzeNonVoid(link.head);
-        checkAssignable(node, type, initializer);
+      Node definition = link.head;
+      compiler.ensure(definition is Identifier || definition is SendSet);
+      if (definition is Send) {
+        SendSet initialization = definition;
+        DartType initializer = analyzeNonVoid(initialization.arguments.head);
+        checkAssignable(initialization.assignmentOperator, initializer, type);
       }
     }
     return StatementType.NOT_RETURNING;
@@ -733,7 +1086,19 @@
   }
 
   visitLiteralMap(LiteralMap node) {
-    return unhandledExpression();
+    InterfaceType mapType = elements.getType(node);
+    DartType mapKeyType = mapType.typeArguments.head;
+    DartType mapValueType = mapType.typeArguments.tail.head;
+    for (Link<Node> link = node.entries.nodes;
+         !link.isEmpty;
+         link = link.tail) {
+      LiteralMapEntry entry = link.head;
+      DartType keyType = analyze(entry.key);
+      checkAssignable(entry.key, keyType, mapKeyType);
+      DartType valueType = analyze(entry.value);
+      checkAssignable(entry.value, valueType, mapValueType);
+    }
+    return mapType;
   }
 
   visitLiteralMapEntry(LiteralMapEntry node) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index 2bd8266..501beed 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -851,6 +851,8 @@
     if (concreteType == null) return null;
     TypeMask typeMask = new TypeMask.nonNullEmpty();
     for (BaseType baseType in concreteType.baseTypes) {
+      TypeMask other = baseTypeToTypeMask(baseType);
+      if (other == null) return null;
       typeMask = typeMask.union(baseTypeToTypeMask(baseType), compiler);
     }
     return typeMask;
@@ -1098,7 +1100,7 @@
       } else if (type.element == compiler.boolClass) {
         concreteType = singletonConcreteType(baseTypes.boolBaseType);
       } else {
-        Set<ClassElement> subtypes = compiler.world.subtypes[type.element];
+        Set<ClassElement> subtypes = compiler.world.subtypesOf(type.element);
         if (subtypes == null) continue;
         concreteType = emptyConcreteType;
         for (ClassElement subtype in subtypes) {
@@ -1221,7 +1223,7 @@
       if (type == null) {
         uninitializedFields.add(field);
       }
-    }, includeSuperMembers: false);
+    });
 
     // handle initializing formals
     element.functionSignature.forEachParameter((param) {
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 4e2bf37..8f3cda3 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -62,6 +62,7 @@
   bool get isEmpty => (flags >> 1) == EMPTY;
   bool get isExact => (flags >> 1) == EXACT;
   bool get isNullable => (flags & 1) != 0;
+  bool get isUnion => false;
 
   // TODO(kasperl): Get rid of these. They should not be a visible
   // part of the implementation because they make it hard to add
@@ -77,6 +78,8 @@
     return isNullable ? new FlatTypeMask.internal(base, flags & ~1) : this;
   }
 
+  TypeMask simplify(Compiler compiler) => this;
+
   bool contains(DartType type, Compiler compiler) {
     if (isEmpty) {
       return false;
@@ -126,6 +129,21 @@
     return base.element == cls;
   }
 
+  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);
+    }
+  }
+
   /**
    * Returns the [ClassElement] if this type represents a single class,
    * otherwise returns `null`.  This method is conservative.
@@ -153,23 +171,26 @@
         || identical(base.element, compiler.dynamicClass);
   }
 
-  TypeMask union(FlatTypeMask other, Compiler compiler) {
+  TypeMask union(TypeMask other, Compiler compiler) {
+    assert(other != null);
+    if (other is! FlatTypeMask) return other.union(this, compiler);
+    FlatTypeMask flatOther = other;
     if (isEmpty) {
-      return isNullable ? other.nullable() : other;
-    } else if (other.isEmpty) {
-      return other.isNullable ? nullable() : this;
-    } else if (base == other.base) {
-      return unionSame(other, compiler);
-    } else if (isSubclassOf(other.base, base, compiler)) {
-      return unionSubclass(other, compiler);
-    } else if (isSubclassOf(base, other.base, compiler)) {
-      return other.unionSubclass(this, compiler);
-    } else if (isSubtypeOf(other.base, base, compiler)) {
-      return unionSubtype(other, compiler);
-    } else if (isSubtypeOf(base, other.base, compiler)) {
-      return other.unionSubtype(this, compiler);
+      return isNullable ? flatOther.nullable() : flatOther;
+    } else if (flatOther.isEmpty) {
+      return flatOther.isNullable ? nullable() : this;
+    } else if (base == flatOther.base) {
+      return unionSame(flatOther, compiler);
+    } else if (isSubclassOf(flatOther.base, base, compiler)) {
+      return unionSubclass(flatOther, compiler);
+    } else if (isSubclassOf(base, flatOther.base, compiler)) {
+      return flatOther.unionSubclass(this, compiler);
+    } else if (isSubtypeOf(flatOther.base, base, compiler)) {
+      return unionSubtype(flatOther, compiler);
+    } else if (isSubtypeOf(base, flatOther.base, compiler)) {
+      return flatOther.unionSubtype(this, compiler);
     } else {
-      return unionDisjoint(other, compiler);
+      return new UnionTypeMask._(<FlatTypeMask>[this, flatOther]);
     }
   }
 
@@ -222,78 +243,26 @@
         : this;
   }
 
-  TypeMask unionDisjoint(FlatTypeMask other, Compiler compiler) {
-    assert(base != other.base);
-    assert(!isSubtypeOf(base, other.base, compiler));
-    assert(!isSubtypeOf(other.base, base, compiler));
-    // If either type mask is a subtype type mask, we cannot use a
-    // subclass type mask to represent their union.
-    bool useSubclass = !isSubtype && !other.isSubtype;
-    // Compute the common supertypes of the two types.
-    ClassElement thisElement = base.element;
-    ClassElement otherElement = other.base.element;
-    Iterable<ClassElement> candidates =
-        compiler.world.commonSupertypesOf(thisElement, otherElement);
-    if (candidates.isEmpty) {
-      // TODO(kasperl): Get rid of this check. It can only happen when
-      // at least one of the two base types is 'unseen'.
-      return new TypeMask(compiler.objectClass.rawType,
-                          SUBCLASS,
-                          isNullable || other.isNullable);
-    }
-    // Compute the best candidate and its kind.
-    ClassElement bestElement;
-    int bestKind;
-    int bestSize;
-    for (ClassElement candidate in candidates) {
-      Set<ClassElement> subclasses = useSubclass
-          ? compiler.world.subclasses[candidate]
-          : null;
-      int size;
-      int kind;
-      if (subclasses != null &&
-          subclasses.contains(thisElement) &&
-          subclasses.contains(otherElement)) {
-        // If both [this] and [other] are subclasses of the supertype,
-        // then we prefer to construct a subclass type mask because it
-        // will always be at least as small as the corresponding
-        // subtype type mask.
-        kind = SUBCLASS;
-        size = subclasses.length;
-        assert(size <= compiler.world.subtypes[candidate].length);
-      } else {
-        kind = SUBTYPE;
-        size = compiler.world.subtypes[candidate].length;
-      }
-      // Update the best candidate if the new one is better.
-      if (bestElement == null || size < bestSize) {
-        bestElement = candidate;
-        bestSize = size;
-        bestKind = kind;
-      }
-    }
-    return new TypeMask(bestElement.computeType(compiler),
-                        bestKind,
-                        isNullable || other.isNullable);
-  }
-
-  TypeMask intersection(FlatTypeMask other, Compiler compiler) {
+  TypeMask intersection(TypeMask other, Compiler compiler) {
+    assert(other != null);
+    if (other is! FlatTypeMask) return other.intersection(this, compiler);
+    FlatTypeMask flatOther = other;
     if (isEmpty) {
-      return other.isNullable ? this : nonNullable();
-    } else if (other.isEmpty) {
-      return isNullable ? other : other.nonNullable();
-    } else if (base == other.base) {
-      return intersectionSame(other, compiler);
-    } else if (isSubclassOf(other.base, base, compiler)) {
-      return intersectionSubclass(other, compiler);
-    } else if (isSubclassOf(base, other.base, compiler)) {
-      return other.intersectionSubclass(this, compiler);
-    } else if (isSubtypeOf(other.base, base, compiler)) {
-      return intersectionSubtype(other, compiler);
-    } else if (isSubtypeOf(base, other.base, compiler)) {
-      return other.intersectionSubtype(this, compiler);
+      return flatOther.isNullable ? this : nonNullable();
+    } else if (flatOther.isEmpty) {
+      return isNullable ? flatOther : other.nonNullable();
+    } else if (base == flatOther.base) {
+      return intersectionSame(flatOther, compiler);
+    } else if (isSubclassOf(flatOther.base, base, compiler)) {
+      return intersectionSubclass(flatOther, compiler);
+    } else if (isSubclassOf(base, flatOther.base, compiler)) {
+      return flatOther.intersectionSubclass(this, compiler);
+    } else if (isSubtypeOf(flatOther.base, base, compiler)) {
+      return intersectionSubtype(flatOther, compiler);
+    } else if (isSubtypeOf(base, flatOther.base, compiler)) {
+      return flatOther.intersectionSubtype(this, compiler);
     } else {
-      return intersectionDisjoint(other, compiler);
+      return intersectionDisjoint(flatOther, compiler);
     }
   }
 
@@ -402,10 +371,10 @@
     if (isExact) {
       return new Set<ClassElement>()..add(element);
     } else if (isSubclass) {
-      return compiler.world.subclasses[element];
+      return compiler.world.subclassesOf(element);
     } else {
       assert(isSubtype);
-      return compiler.world.subtypes[element];
+      return compiler.world.subtypesOf(element);
     }
   }
 
@@ -510,10 +479,10 @@
     if (isExact) {
       return false;
     } else if (isSubtype) {
-      subtypesToCheck = compiler.world.subtypes[cls];
+      subtypesToCheck = compiler.world.subtypesOf(cls);
     } else {
       assert(isSubclass);
-      subtypesToCheck = compiler.world.subclasses[cls];
+      subtypesToCheck = compiler.world.subclassesOf(cls);
     }
 
     return subtypesToCheck != null
@@ -562,14 +531,14 @@
   static bool isSubclassOf(DartType x, DartType y, Compiler compiler) {
     ClassElement xElement = x.element;
     ClassElement yElement = y.element;
-    Set<ClassElement> subclasses = compiler.world.subclasses[yElement];
+    Set<ClassElement> subclasses = compiler.world.subclassesOf(yElement);
     return (subclasses != null) ? subclasses.contains(xElement) : false;
   }
 
   static bool isSubtypeOf(DartType x, DartType y, Compiler compiler) {
     ClassElement xElement = x.element;
     ClassElement yElement = y.element;
-    Set<ClassElement> subtypes = compiler.world.subtypes[yElement];
+    Set<ClassElement> subtypes = compiler.world.subtypesOf(yElement);
     return (subtypes != null) ? subtypes.contains(xElement) : false;
   }
 
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 658ce4e..587e404 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -7,7 +7,8 @@
 import 'dart:collection' show Queue, LinkedHashSet;
 
 import '../closure.dart' show ClosureClassMap, ClosureScope;
-import '../dart_types.dart' show DartType, FunctionType, TypeKind;
+import '../dart_types.dart'
+    show DartType, InterfaceType, FunctionType, TypeKind;
 import '../elements/elements.dart';
 import '../native_handler.dart' as native;
 import '../tree/tree.dart';
@@ -113,12 +114,12 @@
     throw 'Unsupported operation';
   }
 
-  bool get isNullable => true;
-
   TypeMask intersection(TypeMask other, Compiler compiler) {
     return other;
   }
 
+  bool get isNullable => true;
+
   String toString() => '$name sentinel type mask';
 }
 
@@ -265,7 +266,7 @@
    * Sentinel used by the inferrer to notify that it does not know
    * the type of a specific element.
    */
-  TypeMask dynamicType = new SentinelTypeMask('dynamic');
+  TypeMask dynamicType;
   bool isDynamicType(TypeMask type) => identical(type, dynamicType);
 
   TypeMask nullType;
@@ -547,6 +548,8 @@
         rawTypeOf(backend.functionImplementation));
     typeType = new TypeMask.nonNullExact(
         rawTypeOf(backend.typeImplementation));
+
+    dynamicType = new TypeMask.subclass(rawTypeOf(compiler.objectClass));
   }
 
   dump() {
@@ -623,6 +626,9 @@
 
   bool recordType(Element analyzedElement, TypeMask type) {
     assert(type != null);
+    assert(analyzedElement.isField()
+           || analyzedElement.isParameter()
+           || analyzedElement.isFieldParameter());
     return internalRecordType(analyzedElement, type, typeOf);
   }
 
@@ -653,6 +659,18 @@
   bool internalRecordType(Element analyzedElement,
                           TypeMask newType,
                           Map<Element, TypeMask> types) {
+    if (compiler.trustTypeAnnotations
+        // Parameters are being checked by the method, and we can
+        // therefore only trust their type after the checks.
+        || (compiler.enableTypeAssertions && !analyzedElement.isParameter())) {
+      var annotation = analyzedElement.computeType(compiler);
+      if (types == returnTypeOf) {
+        assert(annotation is FunctionType);
+        annotation = annotation.returnType;
+      }
+      newType = narrowType(newType, annotation);
+    }
+
     // Fields and native methods of native classes are handled
     // specially when querying for their type or return type.
     if (isNativeElement(analyzedElement)) return false;
@@ -688,9 +706,16 @@
     }
     TypeMask returnType = returnTypeOf[element];
     if (returnType == null) {
-      return dynamicType;
+      if ((compiler.trustTypeAnnotations || compiler.enableTypeAssertions)
+          && (element.isFunction()
+              || element.isGetter()
+              || element.isFactoryConstructor())) {
+        FunctionType functionType = element.computeType(compiler);
+        returnType = narrowType(dynamicType, functionType.returnType);
+      } else {
+        returnType = dynamicType;
+      }
     }
-    assert(returnType != null);
     return returnType;
   }
 
@@ -746,16 +771,27 @@
     element = element.implementation;
     if (isNativeElement(element) && element.isField()) {
       var type = typeOf.putIfAbsent(element, () {
-        return new TypeMask.subtype(element.computeType(compiler).asRaw());
+        InterfaceType rawType = element.computeType(compiler).asRaw();
+        return rawType.isDynamic ? dynamicType : new TypeMask.subtype(rawType);
       });
       assert(type != null);
       return type;
     }
     TypeMask type = typeOf[element];
     if (type == null) {
-      return dynamicType;
+      if ((compiler.trustTypeAnnotations
+           && (element.isField()
+               || element.isParameter()
+               || element.isVariable()))
+          // Parameters are being checked by the method, and we can
+          // therefore only trust their type after the checks.
+          || (compiler.enableTypeAssertions
+              && (element.isField() || element.isVariable()))) {
+        type = narrowType(dynamicType, element.computeType(compiler));
+      } else {
+        type = dynamicType;
+      }
     }
-    assert(type != null);
     return type;
   }
 
@@ -793,6 +829,8 @@
         return functionType == null ? dynamicType : functionType;
       } else if (element.isField()) {
         return typeOfElement(element);
+      } else if (Elements.isUnresolved(element)) {
+        return dynamicType;
       } else {
         assert(element.isGetter());
         return returnTypeOfElement(element);
@@ -1234,7 +1272,6 @@
    * [secondType].
    */
   TypeMask computeLUB(TypeMask firstType, TypeMask secondType) {
-    assert(secondType != null);
     if (firstType == null) {
       return secondType;
     } else if (isDynamicType(secondType)) {
@@ -1254,6 +1291,7 @@
                       {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
@@ -1266,6 +1304,7 @@
       otherType = new TypeMask.nonNullSubtype(annotation);
     }
     if (isNullable) otherType = otherType.nullable();
+    if (type == null) return otherType;
     return type.intersection(otherType, compiler);
   }
 }
@@ -1308,21 +1347,27 @@
 class LocalsHandler {
   final InternalSimpleTypesInferrer inferrer;
   final Map<Element, TypeMask> locals;
-  final Set<Element> capturedAndBoxed;
+  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 Set<Element>(),
+        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 Set<Element>.from(other.capturedAndBoxed),
+        capturedAndBoxed = new Map<Element, Element>.from(
+            other.capturedAndBoxed),
         fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
             other.fieldsInitializedInConstructor),
         inTryBlock = other.inTryBlock || inTryBlock,
@@ -1330,15 +1375,19 @@
         isThisExposed = other.isThisExposed;
 
   TypeMask use(Element local) {
-    if (capturedAndBoxed.contains(local)) {
-      return inferrer.typeOfElement(local);
+    if (capturedAndBoxed.containsKey(local)) {
+      return inferrer.typeOfElement(capturedAndBoxed[local]);
     }
     return locals[local];
   }
 
   void update(Element local, TypeMask type) {
     assert(type != null);
-    if (capturedAndBoxed.contains(local) || inTryBlock) {
+    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.
       //
@@ -1350,22 +1399,23 @@
     locals[local] = type;
   }
 
-  void setCapturedAndBoxed(Element local) {
-    capturedAndBoxed.add(local);
+  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 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 (!capturedAndBoxed.contains(local)) {
+        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
@@ -1375,9 +1425,15 @@
         }
         return;
       }
-      TypeMask type = inferrer.computeLUB(oldType, otherType);
-      if (type != oldType) changed = true;
-      locals[local] = type;
+      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.
@@ -1388,12 +1444,12 @@
     // 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 element) {
-      capturedAndBoxed.add(element);
+    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[element] == null) {
-        locals[element] = other.locals[element];
+      if (locals[local] == null) {
+        locals[local] = other.locals[local];
       }
     });
 
@@ -1419,6 +1475,7 @@
     });
     isThisExposed = isThisExposed || other.isThisExposed;
     seenReturn = seenReturn && other.seenReturn;
+    seenBreakOrContinue = seenBreakOrContinue && other.seenBreakOrContinue;
 
     return changed;
   }
@@ -1434,6 +1491,10 @@
   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;
   TypeMask returnType;
 
@@ -1481,14 +1542,14 @@
     // Update the locals that are boxed in [locals]. These locals will
     // be handled specially, in that we are computing their LUB at
     // each update, and reading them yields the type that was found in a
-    // previous analysis ouf [outermostElement].
+    // previous analysis of [outermostElement].
     ClosureClassMap closureData =
         compiler.closureToClassMapper.computeClosureToClassMapping(
             analyzedElement, node, elements);
     ClosureScope scopeData = closureData.capturingScopes[node];
     if (scopeData != null) {
-      scopeData.capturedVariableMapping.forEach((Element variable, _) {
-        locals.setCapturedAndBoxed(variable);
+      scopeData.capturedVariableMapping.forEach((variable, field) {
+        locals.setCapturedAndBoxed(variable, field);
       });
     }
     if (analyzedElement.isField()) {
@@ -1586,14 +1647,16 @@
 
     if (analyzedElement == outermostElement) {
       bool changed = false;
-      locals.capturedAndBoxed.forEach((Element local) {
-        if (inferrer.recordType(local, locals.locals[local])) {
+      locals.capturedAndBoxed.forEach((Element local, Element field) {
+        if (inferrer.recordType(field, locals.locals[local])) {
           changed = true;
         }
       });
       // TODO(ngeoffray): Re-analyze method if [changed]?
     }
     compiler.world.registerSideEffects(analyzedElement, sideEffects);    
+    assert(breaksFor.isEmpty);
+    assert(continuesFor.isEmpty);
     return returnType;
   }
 
@@ -1654,11 +1717,11 @@
     // same as [newType].
     ClosureClassMap nestedClosureData =
         compiler.closureToClassMapper.getMappingForNestedFunction(node);
-    nestedClosureData.forEachNonBoxedCapturedVariable((Element variable) {
+    nestedClosureData.forEachNonBoxedCapturedVariable((variable, field) {
       // The type may be null for instance contexts (this and type
       // parameters), as well as captured argument checks.
       if (locals.locals[variable] == null) return;
-      inferrer.recordType(variable, locals.locals[variable]);
+      inferrer.recordType(field, locals.locals[variable]);
     });
 
     return inferrer.functionType;
@@ -1848,9 +1911,8 @@
       ArgumentsTypes operatorArguments = new ArgumentsTypes([rhsType], null);
       if (Elements.isStaticOrTopLevelField(element)) {
         Element getterElement = elements[node.selector];
-        getterType = getterElement.isField()
-            ? inferrer.typeOfElement(element)
-            : inferrer.returnTypeOfElement(element);
+        getterType =
+            inferrer.typeOfElementWithSelector(getterElement, getterSelector);
         handleStaticSend(node, getterSelector, getterElement, null);
         newType = handleDynamicSend(
             node, operatorSelector, getterType, operatorArguments);
@@ -1955,7 +2017,7 @@
     isThisExposed = true;
     if (node.isPropertyAccess) {
       handleStaticSend(node, selector, element, null);
-      return inferrer.typeOfElement(element);
+      return inferrer.typeOfElementWithSelector(element, selector);
     } else if (element.isFunction()) {
       if (!selector.applies(element, compiler)) return inferrer.dynamicType;
       ArgumentsTypes arguments = analyzeArguments(node.arguments);
@@ -2120,7 +2182,7 @@
     Selector selector = elements.getSelector(node);
     if (Elements.isStaticOrTopLevelField(element)) {
       handleStaticSend(node, selector, element, null);
-      return inferrer.typeOfElement(element);
+      return inferrer.typeOfElementWithSelector(element, selector);
     } else if (Elements.isInstanceSend(node, elements)) {
       return visitDynamicSend(node);
     } else if (Elements.isStaticOrTopLevelFunction(element)) {
@@ -2314,51 +2376,77 @@
     return inferrer.dynamicType;
   }
 
-  TypeMask visitWhile(While node) {
+  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 = handleCondition(node.condition);
       updateIsChecks(tests, usePositive: true);
       visit(node.body);
-      changed = saved.merge(locals);
-      locals = saved;
-    } while (changed);
-    loopLevel--;
-    return inferrer.dynamicType;
+    });
   }
 
   TypeMask visitDoWhile(DoWhile node) {
-    loopLevel++;
-    bool changed = false;
-    do {
-      LocalsHandler saved = new LocalsHandler.from(locals);
+    return handleLoop(node, () {
       visit(node.body);
       List<Send> tests = handleCondition(node.condition);
       updateIsChecks(tests, usePositive: true);
-      changed = saved.merge(locals);
-      locals = saved;
-    } while (changed);
-    loopLevel--;
-    return inferrer.dynamicType;
+    });
   }
 
   TypeMask visitFor(For node) {
-    bool changed = false;
     visit(node.initializer);
-    loopLevel++;
-    do {
-      LocalsHandler saved = new LocalsHandler.from(locals);
+    return handleLoop(node, () {
       List<Send> tests = handleCondition(node.condition);
       updateIsChecks(tests, usePositive: true);
       visit(node.body);
       visit(node.update);
-      changed = saved.merge(locals);
-      locals = saved;
-    } while (changed);
-    loopLevel--;
-    return inferrer.dynamicType;
+    });
   }
 
   TypeMask visitForIn(ForIn node) {
@@ -2380,15 +2468,9 @@
     handlePlainAssignment(identifier, variable, selector,
                           inferrer.dynamicType, inferrer.dynamicType,
                           node.expression);
-    loopLevel++;
-    do {
-      LocalsHandler saved = new LocalsHandler.from(locals);
+    return handleLoop(node, () {
       visit(node.body);
-      changed = saved.merge(locals);
-      locals = saved;
-    } while (changed);
-    loopLevel--;
-    return inferrer.dynamicType;
+    });
   }
 
   TypeMask visitTryStatement(TryStatement node) {
@@ -2434,6 +2516,48 @@
     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);
   }
@@ -2441,7 +2565,24 @@
   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.
@@ -2451,10 +2592,14 @@
         for (Node switchCase in node.cases) {
           LocalsHandler saved = new LocalsHandler.from(locals);
           visit(switchCase);
-          changed = saved.merge(locals) || changed;
+          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
@@ -2465,17 +2610,17 @@
           : new LocalsHandler.from(locals);
 
       for (Node switchCase in node.cases) {
-        locals = saved;
+        locals = new LocalsHandler.from(saved);
         visit(switchCase);
         if (result == null) {
           result = locals;
         } else {
-          result.merge(locals);
+          result.merge(locals, discardIfAborts: false);
         }
       }
-
       locals = result;
     }
+    clearBreaksAndContinues(elements[node]);
     return inferrer.dynamicType;
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
index 47740ea..905021c 100644
--- a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
@@ -28,6 +28,10 @@
   factory TypeMask.nonNullSubtype(DartType base)
       => new FlatTypeMask.nonNullSubtype(base);
 
+  factory TypeMask.unionOf(Iterable<TypeMask> masks, Compiler compiler) {
+    return UnionTypeMask.unionOf(masks, compiler);
+  }
+
   /**
    * Returns a nullable variant of [this] type mask.
    */
@@ -38,9 +42,12 @@
    */
   TypeMask nonNullable();
 
+  TypeMask simplify(Compiler compiler);
+
   bool get isEmpty;
   bool get isNullable;
   bool get isExact;
+  bool get isUnion;
 
   bool containsOnlyInt(Compiler compiler);
   bool containsOnlyDouble(Compiler compiler);
@@ -49,6 +56,11 @@
   bool containsOnlyBool(Compiler compiler);
   bool containsOnlyString(Compiler compiler);
   bool containsOnly(ClassElement element);
+  
+  /**
+   * Returns whether this type mask is an instance of [cls].
+   */
+  bool satisfies(ClassElement cls, Compiler compiler);
 
   /**
    * Returns whether or not this type mask contains the given type.
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart
index 34444fd..5813cfe 100644
--- a/sdk/lib/_internal/compiler/implementation/types/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -19,6 +19,7 @@
 part 'concrete_types_inferrer.dart';
 part 'flat_type_mask.dart';
 part 'type_mask.dart';
+part 'union_type_mask.dart';
 
 /**
  * Common super class for our type inferrers.
@@ -91,6 +92,9 @@
    * is for debugging purposes only and can be omitted.
    */
   TypeMask best(var type1, var type2, [element]) {
+    // TODO(polux): Handle [UnionTypeMask].
+    if (type1 != null) type1 = type1.simplify(compiler);
+    if (type2 != null) type2 = type2.simplify(compiler);
     final result = _best(type1, type2);
     // Tests type1 and type2 for equality modulo normalization of native types.
     // Only called when DUMP_SURPRISING_RESULTS is true.
diff --git a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
new file mode 100644
index 0000000..82865d5
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
@@ -0,0 +1,259 @@
+// 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 types;
+
+class UnionTypeMask implements TypeMask {
+  final Iterable<FlatTypeMask> disjointMasks;
+
+  static const int MAX_UNION_LENGTH = 4;
+
+  UnionTypeMask._(this.disjointMasks);
+
+  static TypeMask unionOf(Iterable<TypeMask> masks, Compiler compiler) {
+    List<FlatTypeMask> disjoint = <FlatTypeMask>[];
+    unionOfHelper(masks, disjoint, compiler);
+    if (disjoint.isEmpty) return new TypeMask.nonNullEmpty();
+    if (disjoint.length > MAX_UNION_LENGTH) return flatten(disjoint, compiler);
+    if (disjoint.length == 1) return disjoint[0];
+    return new UnionTypeMask._(disjoint);
+  }
+
+  static void unionOfHelper(Iterable<TypeMask> masks,
+                            List<FlatTypeMask> disjoint,
+                            Compiler compiler) {
+    for (TypeMask mask in masks) {
+      if (mask.isUnion) {
+        UnionTypeMask union = mask;
+        unionOfHelper(union.disjointMasks, disjoint, compiler);
+      } else if (mask.isEmpty && !mask.isNullable) {
+        continue;
+      } else {
+        FlatTypeMask flatMask = mask;
+        assert(flatMask.base == null
+               || flatMask.base.element != compiler.dynamicClass);
+        int inListIndex = -1;
+        bool covered = false;
+
+        // Iterate over [disjoint] to find out if one of the mask
+        // already covers [mask].
+        for (int i = 0; i < disjoint.length; i++) {
+          FlatTypeMask current = disjoint[i];
+          if (current == null) continue;
+          TypeMask newMask = mask.union(current, compiler);
+          // If we have found a disjoint union, continue iterating.
+          if (newMask.isUnion) continue;
+          covered = true;
+          // We found a mask that is either equal to [mask] or is a
+          // supertype of [mask].
+          if (current == newMask) break;
+
+          // [mask] is a supertype of [current], replace the [disjoint]
+          // list with [newMask] instead of [current]. Note that
+          // [newMask] may contain different information than [mask],
+          // like nullability.
+          disjoint[i] = newMask;
+          mask = newMask;
+
+          if (inListIndex != -1) {
+            // If the mask was already covered, we remove the previous
+            // place where it was inserted. This new mask subsumes the
+            // previously covered one.
+            disjoint.removeAt(inListIndex);
+            i--;
+          }
+          // Record where the mask was inserted.
+          inListIndex = i;
+        }
+        // If none of the masks in [disjoint] covers [mask], we just
+        // add [mask] to the list.
+        if (!covered) disjoint.add(mask);
+      }
+    }
+  }
+
+  static TypeMask flatten(List<FlatTypeMask> masks, Compiler compiler) {
+    assert(masks.length > 1);
+    // If either type mask is a subtype type mask, we cannot use a
+    // subclass type mask to represent their union.
+    bool useSubclass = masks.every((e) => !e.isSubtype);
+    bool isNullable = masks.any((e) => e.isNullable);
+
+    // Compute the common supertypes of the two types.
+    ClassElement firstElement = masks[0].base.element;
+    ClassElement secondElement = masks[1].base.element;
+    Iterable<ClassElement> candidates =
+        compiler.world.commonSupertypesOf(firstElement, secondElement);
+    bool unseenType = false;
+    for (int i = 2; i < masks.length; i++) {
+      ClassElement element = masks[i].base.element;
+      Set<ClassElement> supertypes = compiler.world.supertypesOf(element);
+      if (supertypes == null) {
+        unseenType = true;
+        break;
+      }
+      candidates = candidates.where((e) => supertypes.contains(e));
+    }
+
+    if (candidates.isEmpty || unseenType) {
+      // TODO(kasperl): Get rid of this check. It can only happen when
+      // at least one of the two base types is 'unseen'.
+      return new TypeMask(compiler.objectClass.rawType,
+                          FlatTypeMask.SUBCLASS,
+                          isNullable);
+    }
+    // Compute the best candidate and its kind.
+    ClassElement bestElement;
+    int bestKind;
+    int bestSize;
+    for (ClassElement candidate in candidates) {
+      Set<ClassElement> subclasses = useSubclass
+          ? compiler.world.subclassesOf(candidate)
+          : null;
+      int size;
+      int kind;
+      if (subclasses != null
+          && masks.every((t) => subclasses.contains(t.base.element))) {
+        // If both [this] and [other] are subclasses of the supertype,
+        // then we prefer to construct a subclass type mask because it
+        // will always be at least as small as the corresponding
+        // subtype type mask.
+        kind = FlatTypeMask.SUBCLASS;
+        size = subclasses.length;
+        assert(size <= compiler.world.subtypesOf(candidate).length);
+      } else {
+        kind = FlatTypeMask.SUBTYPE;
+        size = compiler.world.subtypesOf(candidate).length;
+      }
+      // Update the best candidate if the new one is better.
+      if (bestElement == null || size < bestSize) {
+        bestElement = candidate;
+        bestSize = size;
+        bestKind = kind;
+      }
+    }
+    if (bestElement == compiler.objectClass) bestKind = FlatTypeMask.SUBCLASS;
+    return new TypeMask(bestElement.computeType(compiler),
+                        bestKind,
+                        isNullable);
+  }
+
+  TypeMask union(var other, Compiler compiler) {
+    if (!other.isUnion && disjointMasks.contains(other)) return this;
+
+    List<FlatTypeMask> newList =
+        new List<FlatTypeMask>.from(disjointMasks);
+    if (!other.isUnion) {
+      newList.add(other);
+    } else {
+      assert(other is UnionTypeMask);
+      newList.addAll(other.disjointMasks);
+    }
+    return new TypeMask.unionOf(newList, compiler);
+  }
+
+  TypeMask intersection(var other, Compiler compiler) {
+    if (!other.isUnion && disjointMasks.contains(other)) return other;
+
+    List<TypeMask> intersections = <TypeMask>[];
+    for (TypeMask current in disjointMasks) {
+      if (other.isUnion) {
+        for (FlatTypeMask flatOther in other.disjointMasks) {
+          intersections.add(current.intersection(flatOther, compiler)); 
+        }
+      } else {
+        intersections.add(current.intersection(other, compiler));
+      }
+    }
+    return new TypeMask.unionOf(intersections, compiler);
+  }
+
+  TypeMask nullable() {
+    if (isNullable) return this;
+    List<FlatTypeMask> newList = new List<FlatTypeMask>.from(disjointMasks);
+    newList[0] = newList[0].nullable();
+    return new UnionTypeMask._(newList);
+  }
+
+  TypeMask nonNullable() {
+    if (!isNullable) return this;
+    Iterable<FlatTypeMask> newIterable =
+        disjointMasks.map((e) => e.nonNullable());
+    return new UnionTypeMask._(newIterable);
+  }
+
+  TypeMask simplify(Compiler compiler) => flatten(disjointMasks, compiler);
+
+  bool get isEmpty => false;
+  bool get isNullable => disjointMasks.any((e) => e.isNullable);
+  bool get isExact => false;
+  bool get isUnion => true;
+
+  bool containsOnlyInt(Compiler compiler) => false;
+  bool containsOnlyDouble(Compiler compiler) => false;
+  bool containsOnlyNum(Compiler compiler) {
+    return disjointMasks.every((mask) {
+      return mask.containsOnlyInt(compiler)
+          || mask.containsOnlyDouble(compiler)
+          || mask.containsOnlyNum(compiler);
+    });
+  }
+  bool containsOnlyNull(Compiler compiler) => false;
+  bool containsOnlyBool(Compiler compiler) => false;
+  bool containsOnlyString(Compiler compiler) => false;
+  bool containsOnly(ClassElement element) => false;
+  bool satisfies(ClassElement cls, Compiler compiler) {
+    return disjointMasks.every((mask) => mask.satisfies(cls, compiler));
+  }
+
+  bool contains(DartType type, Compiler compiler) {
+    return disjointMasks.any((e) => e.contains(type, compiler));
+  }
+
+  bool containsAll(Compiler compiler) => false;
+
+  ClassElement singleClass(Compiler compiler) => null;
+
+  Set<ClassElement> containedClasses(Compiler compiler) {
+    Set<ClassElement> set = new Set<ClassElement>();
+    disjointMasks.forEach((e) => set.addAll(e.containedClasses(compiler)));
+    return set;
+  }
+
+  /**
+   * Returns whether a [selector] call will hit a method at runtime,
+   * and not go through [noSuchMethod].
+   */
+  bool willHit(Selector selector, Compiler compiler) {
+    return disjointMasks.every((e) => e.willHit(selector, compiler));
+  }
+
+  bool canHit(Element element, Selector selector, Compiler compiler) {
+    return disjointMasks.any((e) => e.canHit(element, selector, compiler));
+  }
+
+  Element locateSingleElement(Selector selector, Compiler compiler) {
+    Element candidate;
+    for (FlatTypeMask mask in disjointMasks) {
+      Element current = mask.locateSingleElement(selector, compiler);
+      if (current == null) {
+        return null;
+      } else if (candidate == null) {
+        candidate = current;
+      } else if (candidate != current) {
+        return null;
+      }
+    }
+    return candidate;
+  }
+
+  String toString() => 'Union of $disjointMasks';
+
+  bool operator==(other) {
+    if (identical(this, other)) return true;
+    return other is UnionTypeMask
+        && other.disjointMasks.length == disjointMasks.length
+        && other.disjointMasks.every((e) => disjointMasks.contains(e));
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart b/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
index c8ad568..268fce6 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
@@ -59,7 +59,7 @@
     ClassElement single = classes[0];
     // Return true if the single class in our list does not have a
     // single instantiated subclass.
-    Set<ClassElement> subtypes = compiler.world.subtypes[single];
+    Set<ClassElement> subtypes = compiler.world.subtypesOf(single);
     return subtypes == null
         || subtypes.every((ClassElement each) => !each.isSubclassOf(single));
   }
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 7dcebd8..c609c17 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -28,6 +28,10 @@
       "no named argument '#{argumentName}' found on method");
   static const METHOD_NOT_FOUND = const MessageKind(
       'no method named #{memberName} in class #{className}');
+  static const OPERATOR_NOT_FOUND = const MessageKind(
+      'no operator #{memberName} in class #{className}');
+  static const PROPERTY_NOT_FOUND = const MessageKind(
+      'no property named #{memberName} in class #{className}');
   static const NOT_CALLABLE = const MessageKind(
       "'#{elementName}' is not callable");
   static const MEMBER_NOT_STATIC = const MessageKind(
@@ -35,6 +39,9 @@
   static const NO_INSTANCE_AVAILABLE = const MessageKind(
       '#{name} is only available in instance methods');
 
+  static const THIS_IS_THE_METHOD = const MessageKind(
+      "This is the method declaration.");
+
   static const UNREACHABLE_CODE = const MessageKind(
       'unreachable code');
   static const MISSING_RETURN = const MessageKind(
diff --git a/sdk/lib/_internal/compiler/implementation/world.dart b/sdk/lib/_internal/compiler/implementation/world.dart
index f0bd537..122bd9e 100644
--- a/sdk/lib/_internal/compiler/implementation/world.dart
+++ b/sdk/lib/_internal/compiler/implementation/world.dart
@@ -6,32 +6,54 @@
 
 class World {
   final Compiler compiler;
-  final Map<ClassElement, Set<MixinApplicationElement>> mixinUses;
-  final Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses;
   final FullFunctionSet allFunctions;
   final Set<Element> functionsCalledInLoop = new Set<Element>();
   final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>();
 
-  // We keep track of subtype and subclass relationships in four
-  // distinct sets to make class hierarchy analysis faster.
-  final Map<ClassElement, Set<ClassElement>> subclasses =
-      new Map<ClassElement, Set<ClassElement>>();
-  final Map<ClassElement, Set<ClassElement>> superclasses =
-      new Map<ClassElement, Set<ClassElement>>();
-  final Map<ClassElement, Set<ClassElement>> subtypes =
-      new Map<ClassElement, Set<ClassElement>>();
-  final Map<ClassElement, Set<ClassElement>> supertypes =
+  final Map<ClassElement, Set<MixinApplicationElement>> mixinUses =
+      new Map<ClassElement, Set<MixinApplicationElement>>();
+
+  final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses =
       new Map<ClassElement, Set<ClassElement>>();
 
+  // We keep track of subtype and subclass relationships in four
+  // distinct sets to make class hierarchy analysis faster.
+  final Map<ClassElement, Set<ClassElement>> _subclasses =
+      new Map<ClassElement, Set<ClassElement>>();
+  final Map<ClassElement, Set<ClassElement>> _superclasses =
+      new Map<ClassElement, Set<ClassElement>>();
+  final Map<ClassElement, Set<ClassElement>> _subtypes =
+      new Map<ClassElement, Set<ClassElement>>();
+  final Map<ClassElement, Set<ClassElement>> _supertypes =
+      new Map<ClassElement, Set<ClassElement>>();
+
+  Set<ClassElement> subclassesOf(ClassElement cls) {
+    return _subclasses[cls.declaration];
+  }
+
+  Set<ClassElement> subtypesOf(ClassElement cls) {
+    return _subtypes[cls.declaration];
+  }
+
+  Set<ClassElement> superclassesOf(ClassElement cls) {
+    return _superclasses[cls.declaration];
+  }
+
+  Set<ClassElement> supertypesOf(ClassElement cls) {
+    return _supertypes[cls.declaration];
+  }
+
+  Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) {
+    return _typesImplementedBySubclasses[cls];
+  }
+
   World(Compiler compiler)
-      : mixinUses = new Map<ClassElement, Set<MixinApplicationElement>>(),
-        typesImplementedBySubclasses =
-            new Map<ClassElement, Set<ClassElement>>(),
-        allFunctions = new FullFunctionSet(compiler),
+      : allFunctions = new FullFunctionSet(compiler),
         this.compiler = compiler;
 
   void populate() {
     void addSubtypes(ClassElement cls) {
+      assert(cls.isDeclaration);
       if (cls.resolutionState != STATE_DONE) {
         compiler.internalErrorOnElement(
             cls, 'Class "${cls.name.slowToString()}" is not resolved.');
@@ -39,9 +61,9 @@
 
       for (DartType type in cls.allSupertypes) {
         Set<Element> supertypesOfClass =
-            supertypes.putIfAbsent(cls, () => new Set<ClassElement>());
+            _supertypes.putIfAbsent(cls, () => new Set<ClassElement>());
         Set<Element> subtypesOfSupertype =
-            subtypes.putIfAbsent(type.element, () => new Set<ClassElement>());
+            _subtypes.putIfAbsent(type.element, () => new Set<ClassElement>());
         supertypesOfClass.add(type.element);
         subtypesOfSupertype.add(cls);
       }
@@ -51,14 +73,14 @@
       DartType type = cls.supertype;
       while (type != null) {
         Set<Element> superclassesOfClass =
-            superclasses.putIfAbsent(cls, () => new Set<ClassElement>());
+            _superclasses.putIfAbsent(cls, () => new Set<ClassElement>());
         Set<Element> subclassesOfSuperclass =
-            subclasses.putIfAbsent(type.element, () => new Set<ClassElement>());
+            _subclasses.putIfAbsent(type.element, () => new Set<ClassElement>());
         superclassesOfClass.add(type.element);
         subclassesOfSuperclass.add(cls);
 
         Set<Element> typesImplementedBySubclassesOfCls =
-            typesImplementedBySubclasses.putIfAbsent(
+            _typesImplementedBySubclasses.putIfAbsent(
                 type.element, () => new Set<ClassElement>());
         for (DartType current in cls.allSupertypes) {
           typesImplementedBySubclassesOfCls.add(current.element);
@@ -76,9 +98,9 @@
   }
 
   Iterable<ClassElement> commonSupertypesOf(ClassElement x, ClassElement y) {
-    Set<ClassElement> xSet = supertypes[x];
+    Set<ClassElement> xSet = supertypesOf(x);
     if (xSet == null) return const <ClassElement>[];
-    Set<ClassElement> ySet = supertypes[y];
+    Set<ClassElement> ySet = supertypesOf(y);
     if (ySet == null) return const <ClassElement>[];
     Set<ClassElement> smallSet, largeSet;
     if (xSet.length <= ySet.length) {
@@ -93,6 +115,8 @@
 
   void registerMixinUse(MixinApplicationElement mixinApplication,
                         ClassElement mixin) {
+    // We don't support patch classes as mixin.
+    assert(mixin.isDeclaration);
     Set<MixinApplicationElement> users =
         mixinUses.putIfAbsent(mixin, () =>
                               new Set<MixinApplicationElement>());
@@ -105,12 +129,12 @@
   }
 
   bool hasAnySubclass(ClassElement cls) {
-    Set<ClassElement> classes = subclasses[cls];
+    Set<ClassElement> classes = subclassesOf(cls);
     return classes != null && !classes.isEmpty;
   }
 
   bool hasAnySubtype(ClassElement cls) {
-    Set<ClassElement> classes = subtypes[cls];
+    Set<ClassElement> classes = subtypesOf(cls);
     return classes != null && !classes.isEmpty;
   }
 
@@ -124,7 +148,7 @@
 
   // Returns whether a subclass of [superclass] implements [type].
   bool hasAnySubclassThatImplements(ClassElement superclass, DartType type) {
-    Set<ClassElement> subclasses = typesImplementedBySubclasses[superclass];
+    Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass);
     if (subclasses == null) return false;
     return subclasses.contains(type.element);
   }
@@ -182,6 +206,13 @@
   }
 
   SideEffects getSideEffectsOfElement(Element element) {
+    // The type inferrer (where the side effects are being computed),
+    // does not see generative constructor bodies because they are
+    // created by the backend. Also, it does not make any distinction
+    // between a constructor and its body for side effects. This
+    // implies that currently, the side effects of a constructor body
+    // contain the side effects of the initializers.
+    assert(!element.isGenerativeConstructorBody());
     return sideEffects.putIfAbsent(element.declaration, () {
       return new SideEffects();
     });
diff --git a/sdk/lib/_internal/compiler/samples/compile_loop/compile_loop.dart b/sdk/lib/_internal/compiler/samples/compile_loop/compile_loop.dart
new file mode 100644
index 0000000..cb0e64b
--- /dev/null
+++ b/sdk/lib/_internal/compiler/samples/compile_loop/compile_loop.dart
@@ -0,0 +1,77 @@
+// 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 sample demonstrates how to run the compiler in a loop reading
+// all sources from memory, instead of using dart:io.
+library sample.compile_loop;
+
+import 'dart:async';
+import 'dart:uri';
+
+import '../../compiler.dart' as compiler;
+
+// If this file is missing, generate it using ../jsonify/jsonify.dart.
+import 'sdk.dart';
+
+Future<String> compile(source) {
+  Future<String> inputProvider(Uri uri) {
+    if (uri.scheme == 'sdk') {
+      var value = SDK_SOURCES['$uri'];
+      if (value == null) {
+        // TODO(ahe): Use new Future.error.
+        throw new Exception('Error: Cannot read: $uri');
+      }
+      return new Future.value(value);
+    } else if ('$uri' == 'memory:/main.dart') {
+      return new Future.value(source);
+    }
+    // TODO(ahe): Use new Future.error.
+    throw new Exception('Error: Cannot read: $uri');
+  }
+  void handler(Uri uri, int begin, int end,
+               String message, compiler.Diagnostic kind) {
+    // TODO(ahe): Remove dart:io import from
+    // ../../implementation/source_file_provider.dart and use
+    // FormattingDiagnosticHandler instead.
+    print({ 'uri': '$uri',
+            'begin': begin,
+            'end': end,
+            'message': message,
+            'kind': kind.name });
+    if (kind == compiler.Diagnostic.ERROR) {
+      throw new Exception('Unexpected error occurred.');
+    }
+  }
+  return compiler.compile(
+      new Uri('memory:/main.dart'),
+      Uri.parse('sdk:/sdk/'),
+      null,
+      inputProvider,
+      handler,
+      []);
+}
+
+int iterations = 10;
+
+main() {
+  compile(EXAMPLE_HELLO_HTML).then((jsResult) {
+    if (jsResult == null) throw 'Compilation failed';
+    if (--iterations > 0) main();
+  });
+}
+
+const String EXAMPLE_HELLO_HTML = r'''
+// Go ahead and modify this example.
+
+import "dart:html";
+
+var greeting = "Hello, World!";
+
+// Displays a greeting.
+void main() {
+  // This example uses HTML to display the greeting and it will appear
+  // in a nested HTML frame (an iframe).
+  document.body.append(new HeadingElement.h1()..appendText(greeting));
+}
+''';
diff --git a/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart b/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
new file mode 100644
index 0000000..891f505
--- /dev/null
+++ b/sdk/lib/_internal/compiler/samples/jsonify/jsonify.dart
@@ -0,0 +1,99 @@
+// 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';
+import 'dart:json';
+import 'dart:uri';
+
+// TODO(ahe): Should be dart:mirrors.
+import '../../implementation/mirrors/mirrors.dart';
+
+import '../../../libraries.dart'
+    show LIBRARIES, LibraryInfo;
+
+import '../../implementation/mirrors/dart2js_mirror.dart'
+    show analyze, BackDoor;
+
+import '../../implementation/filenames.dart';
+import '../../implementation/source_file.dart';
+import '../../implementation/source_file_provider.dart';
+import '../../implementation/util/uri_extras.dart';
+
+const DART2JS = '../../implementation/dart2js.dart';
+const DART2JS_MIRROR = '../../implementation/mirrors/dart2js_mirror.dart';
+const SDK_ROOT = '../../../../../';
+
+bool isPublicDart2jsLibrary(String name) {
+  return !name.startsWith('_') && LIBRARIES[name].isDart2jsLibrary;
+}
+
+var handler;
+RandomAccessFile output;
+Uri outputUri;
+Uri sdkRoot;
+
+main() {
+  mainWithOptions(new Options());
+}
+
+mainWithOptions(Options options) {
+  handler = new FormattingDiagnosticHandler()
+      ..throwOnError = true;
+
+  outputUri =
+      handler.provider.cwd.resolve(nativeToUriPath(options.arguments.first));
+  output = new File(options.arguments.first).openSync(mode: FileMode.WRITE);
+
+  Uri myLocation =
+      handler.provider.cwd.resolve(nativeToUriPath(options.script));
+
+  sdkRoot = myLocation.resolve(SDK_ROOT).resolve('../');
+
+  // Get the names of public dart2js libraries.
+  Iterable<String> names = LIBRARIES.keys.where(isPublicDart2jsLibrary);
+
+  // Turn the names into uris by prepending dart: to them.
+  List<Uri> uris = names.map((String name) => Uri.parse('dart:$name')).toList();
+
+  analyze(uris, myLocation.resolve(SDK_ROOT), null, handler.provider, handler)
+      .then(jsonify);
+}
+
+jsonify(MirrorSystem mirrors) {
+  var map = {};
+
+  mirrors.libraries.forEach((_, LibraryMirror library) {
+    BackDoor.compilationUnitsOf(library).forEach((compilationUnit) {
+      Uri uri = compilationUnit.uri;
+      String filename = relativize(sdkRoot, uri, false);
+      SourceFile file = handler.provider.sourceFiles['$uri'];
+      map['sdk:/$filename'] = file.text;
+    });
+  });
+
+  LIBRARIES.forEach((name, info) {
+    var patch = info.dart2jsPatchPath;
+    if (patch != null) {
+      Uri uri = sdkRoot.resolve('sdk/lib/$patch');
+      String filename = relativize(sdkRoot, uri, false);
+      SourceFile file = handler.provider.sourceFiles['$uri'];
+      map['sdk:/$filename'] = file.text;
+    }
+  });
+
+  output.writeStringSync('''
+// 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.
+
+// DO NOT EDIT.
+// This file is generated by jsonify.dart.
+
+library dart.sdk_sources;
+
+const Map<String, String> SDK_SOURCES = const <String, String>''');
+  output.writeStringSync(stringify(map).replaceAll(r'$', r'\$'));
+  output.writeStringSync(';\n');
+  output.closeSync();
+}
diff --git a/sdk/lib/_internal/pub/lib/src/entrypoint.dart b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
index edfffba..a10a0c1 100644
--- a/sdk/lib/_internal/pub/lib/src/entrypoint.dart
+++ b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
@@ -63,15 +63,17 @@
   /// using the `package:` scheme.
   ///
   /// This will automatically install the package to the system-wide cache as
-  /// well if it requires network access to retrieve (specifically, if
-  /// `id.source.shouldCache` is true).
+  /// well if it requires network access to retrieve (specifically, if the
+  /// package's source has [shouldCache] as `true`).
   ///
   /// See also [installDependencies].
   Future<PackageId> install(PackageId id) {
-    var pendingOrCompleted = _installs[id];
-    if (pendingOrCompleted != null) return pendingOrCompleted;
+    var pending = _installs[id];
+    if (pending != null) return pending;
 
     var packageDir = path.join(packagesDir, id.name);
+    var source;
+
     var future = new Future.sync(() {
       ensureDir(path.dirname(packageDir));
 
@@ -82,16 +84,18 @@
         deleteEntry(packageDir);
       }
 
-      if (id.source.shouldCache) {
+      source = cache.sources[id.source];
+
+      if (source.shouldCache) {
         return cache.install(id).then(
             (pkg) => createPackageSymlink(id.name, pkg.dir, packageDir));
       } else {
-        return id.source.install(id, packageDir).then((found) {
+        return source.install(id, packageDir).then((found) {
           if (found) return null;
-          fail('Package ${id.name} not found in source "${id.source.name}".');
+          fail('Package ${id.name} not found in source "${id.source}".');
         });
       }
-    }).then((_) => id.resolved);
+    }).then((_) => source.resolveId(id));
 
     _installs[id] = future;
 
diff --git a/sdk/lib/_internal/pub/lib/src/git_source.dart b/sdk/lib/_internal/pub/lib/src/git_source.dart
index c98616d..bccae27 100644
--- a/sdk/lib/_internal/pub/lib/src/git_source.dart
+++ b/sdk/lib/_internal/pub/lib/src/git_source.dart
@@ -112,12 +112,12 @@
     return _revisionAt(id).then((revision) {
       var description = {'url': _getUrl(id), 'ref': _getRef(id)};
       description['resolved-ref'] = revision;
-      return new PackageId(id.name, this, id.version, description);
+      return new PackageId(id.name, name, id.version, description);
     });
   }
 
   // TODO(keertip): Implement getCachedPackages().
-  
+
   /// Ensure that the canonical clone of the repository referred to by [id] (the
   /// one in `<system cache>/git/cache`) exists and is up-to-date. Returns a
   /// future that completes once this is finished and throws an exception if it
diff --git a/sdk/lib/_internal/pub/lib/src/hosted_source.dart b/sdk/lib/_internal/pub/lib/src/hosted_source.dart
index 17b1839..62503fe 100644
--- a/sdk/lib/_internal/pub/lib/src/hosted_source.dart
+++ b/sdk/lib/_internal/pub/lib/src/hosted_source.dart
@@ -48,7 +48,7 @@
 
   /// Downloads and parses the pubspec for a specific version of a package that
   /// is available from the site.
-  Future<Pubspec> describe(PackageId id) {
+  Future<Pubspec> describeUncached(PackageId id) {
     // Request it from the server.
     var url = _makeVersionUrl(id, (server, package, version) =>
         "$server/packages/$package/versions/$version.yaml");
@@ -191,9 +191,9 @@
     throw new UnsupportedError("Cannot install packages when offline.");
   }
 
-  Future<Pubspec> describe(PackageId id) {
+  Future<Pubspec> describeUncached(PackageId id) {
     // [getVersions()] will only return packages that are already cached.
-    // SystemCache should only call [describe()] on a package after it has
+    // Source should only call [describeUncached()] on a package after it has
     // failed to find it in the cache, so this code should not be reached.
     throw new UnsupportedError("Cannot describe packages when offline.");
   }
diff --git a/sdk/lib/_internal/pub/lib/src/lock_file.dart b/sdk/lib/_internal/pub/lib/src/lock_file.dart
index 1e85a4d..316e8b5 100644
--- a/sdk/lib/_internal/pub/lib/src/lock_file.dart
+++ b/sdk/lib/_internal/pub/lib/src/lock_file.dart
@@ -58,21 +58,20 @@
           throw new FormatException('Package $name is missing a source.');
         }
         var sourceName = spec['source'];
-        if (!sources.contains(sourceName)) {
-          throw new FormatException(
-              'Could not find a source named $sourceName.');
-        }
-        var source = sources[sourceName];
 
-        // Parse the description.
         if (!spec.containsKey('description')) {
           throw new FormatException('Package $name is missing a description.');
         }
         var description = spec['description'];
-        description = source.parseDescription(filePath, description,
-            fromLockFile: true);
 
-        var id = new PackageId(name, source, version, description);
+        // Parse the description if we know the source.
+        if (sources.contains(sourceName)) {
+          var source = sources[sourceName];
+          description = source.parseDescription(filePath, description,
+              fromLockFile: true);
+        }
+
+        var id = new PackageId(name, sourceName, version, description);
 
         // Validate the name.
         if (name != id.name) {
@@ -97,7 +96,7 @@
     sortedKeys.forEach((name) {
       packagesObj[name] = {
         'version': packages[name].version.toString(),
-        'source': packages[name].source.name,
+        'source': packages[name].source,
         'description': packages[name].description
       };
     });
diff --git a/sdk/lib/_internal/pub/lib/src/package.dart b/sdk/lib/_internal/pub/lib/src/package.dart
index 62a2a98..a2a1b12 100644
--- a/sdk/lib/_internal/pub/lib/src/package.dart
+++ b/sdk/lib/_internal/pub/lib/src/package.dart
@@ -10,7 +10,6 @@
 
 import 'io.dart';
 import 'pubspec.dart';
-import 'source.dart';
 import 'source_registry.dart';
 import 'version.dart';
 
@@ -87,9 +86,9 @@
   /// The name of the package being identified.
   final String name;
 
-  /// The [Source] used to look up this package given its [description]. If
-  /// this is a root package, this will be `null`.
-  final Source source;
+  /// The name of the [Source] used to look up this package given its
+  /// [description]. If this is a root package, this will be `null`.
+  final String source;
 
   /// The metadata used by the package's [source] to identify and locate it. It
   /// contains whatever [Source]-specific data it needs to be able to install
@@ -100,13 +99,8 @@
   /// Whether this package is the root package.
   bool get isRoot => source == null;
 
-  /// Gets the directory where this package is or would be found in the
-  /// [SystemCache].
-  Future<String> get systemCacheDirectory => source.systemCacheDirectory(this);
-
   String toString() {
     if (isRoot) return "$name (root)";
-    if (source.isDefault) return name;
     return "$name from $source";
   }
 
@@ -117,16 +111,11 @@
   /// Returns a [PackageId] for this package with the given concrete version.
   PackageId atVersion(Version version) =>
     new PackageId(name, source, version, description);
-
-  /// Returns `true` if this package's description matches [other]'s.
-  bool descriptionEquals(PackageDep other) {
-    return source.descriptionsEqual(description, other.description);
-  }
 }
 
 /// A reference to a [Package], but not any particular version(s) of it.
 class PackageRef extends _PackageName {
-  PackageRef(String name, Source source, description)
+  PackageRef(String name, String source, description)
       : super(name, source, description);
 
   int get hashCode => name.hashCode ^ source.hashCode;
@@ -138,18 +127,6 @@
            other.name == name &&
            other.source == source;
   }
-
-  /// Gets the list of ids of all versions of the package that are described by
-  /// this reference.
-  Future<List<PackageId>> getVersions() {
-    if (isRoot) {
-      throw new StateError("Cannot get versions for the root package.");
-    }
-
-    return source.getVersions(name, description).then((versions) {
-      return versions.map((version) => atVersion(version)).toList();
-    });
-  }
 }
 
 /// A reference to a specific version of a package. A package ID contains
@@ -163,7 +140,7 @@
   /// The package's version.
   final Version version;
 
-  PackageId(String name, Source source, this.version, description)
+  PackageId(String name, String source, this.version, description)
       : super(name, source, description);
 
   /// Creates an ID for the given root package.
@@ -184,15 +161,8 @@
 
   String toString() {
     if (isRoot) return "$name $version (root)";
-    if (source.isDefault) return "$name $version";
     return "$name $version from $source";
   }
-
-  /// Returns the pubspec for this package.
-  Future<Pubspec> describe() => source.systemCache.describe(this);
-
-  /// Returns a future that completes to the resolved [PackageId] for this id.
-  Future<PackageId> get resolved => source.resolveId(this);
 }
 
 /// A reference to a constrained range of versions of one package.
@@ -200,7 +170,7 @@
   /// The allowed package versions.
   final VersionConstraint constraint;
 
-  PackageDep(String name, Source source, this.constraint, description)
+  PackageDep(String name, String source, this.constraint, description)
       : super(name, source, description);
 
   String toString() {
diff --git a/sdk/lib/_internal/pub/lib/src/path_source.dart b/sdk/lib/_internal/pub/lib/src/path_source.dart
index 2b66e3b..5972050 100644
--- a/sdk/lib/_internal/pub/lib/src/path_source.dart
+++ b/sdk/lib/_internal/pub/lib/src/path_source.dart
@@ -23,7 +23,7 @@
   final name = 'path';
   final shouldCache = false;
 
-  Future<Pubspec> describe(PackageId id) {
+  Future<Pubspec> describeUncached(PackageId id) {
     return new Future.sync(() {
       _validatePath(id.name, id.description);
       return new Pubspec.load(id.name, id.description["path"],
diff --git a/sdk/lib/_internal/pub/lib/src/pubspec.dart b/sdk/lib/_internal/pub/lib/src/pubspec.dart
index 69dc880..e01cab1 100644
--- a/sdk/lib/_internal/pub/lib/src/pubspec.dart
+++ b/sdk/lib/_internal/pub/lib/src/pubspec.dart
@@ -214,11 +214,9 @@
   }
 }
 
-/**
- * Evaluates whether the given [url] for [field] is valid.
- *
- * Throws [FormatException] on an invalid url.
- */
+/// Evaluates whether the given [url] for [field] is valid.
+///
+/// Throws [FormatException] on an invalid url.
 void _validateFieldUrl(url, String field) {
   if (url is! String) {
     throw new FormatException(
@@ -247,14 +245,16 @@
   }
 
   yaml.forEach((name, spec) {
-    var description, source;
+    var description;
+    var sourceName;
+
     var versionConstraint = new VersionRange();
     if (spec == null) {
       description = name;
-      source = sources.defaultSource;
+      sourceName = sources.defaultSource.name;
     } else if (spec is String) {
       description = name;
-      source = sources.defaultSource;
+      sourceName = sources.defaultSource.name;
       versionConstraint = new VersionConstraint.parse(spec);
     } else if (spec is Map) {
       if (spec.containsKey('version')) {
@@ -267,24 +267,27 @@
             'Dependency $name may only have one source: $sourceNames.');
       }
 
-      var sourceName = only(sourceNames);
+      sourceName = only(sourceNames);
       if (sourceName is! String) {
         throw new FormatException(
             'Source name $sourceName should be a string.');
       }
 
-      source = sources[sourceName];
       description = spec[sourceName];
     } else {
       throw new FormatException(
           'Dependency specification $spec should be a string or a mapping.');
     }
 
-    description = source.parseDescription(pubspecPath, description,
-        fromLockFile: false);
+    // If we have a valid source, use it to process the description. Allow
+    // unknown sources so pub doesn't choke on old pubspecs.
+    if (sources.contains(sourceName)) {
+      description = sources[sourceName].parseDescription(
+          pubspecPath, description, fromLockFile: false);
+    }
 
     dependencies.add(new PackageDep(
-        name, source, versionConstraint, description));
+        name, sourceName, versionConstraint, description));
   });
 
   return dependencies;
diff --git a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
index 97d35da..1338b63 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
@@ -387,6 +387,14 @@
       // Include dev dependencies of the root package.
       if (id.isRoot) deps.addAll(pubspec.devDependencies);
 
+      // Make sure the package doesn't have any bad dependencies.
+      for (var dep in deps) {
+        if (!dep.isRoot && !_solver.sources.contains(dep.source)) {
+          throw new UnknownSourceException(id.name,
+              [new Dependency(id.name, dep)]);
+        }
+      }
+
       // Given a package dep, returns a future that completes to a pair of the
       // dep and the number of versions available for it.
       getNumVersions(PackageDep dep) {
@@ -433,8 +441,8 @@
     });
   }
 
-  /// Traverses the references that [depender] depends on, stored in [refs].
-  /// Desctructively modifies [refs]. Completes to a list of packages if the
+  /// Traverses the references that [depender] depends on, stored in [deps].
+  /// Desctructively modifies [deps]. Completes to a list of packages if the
   /// traversal is complete. Completes it to an error if a failure occurred.
   /// Otherwise, recurses.
   Future<List<PackageId>> _traverseDeps(String depender,
@@ -465,7 +473,7 @@
   }
 
   /// Ensures that dependency [dep] from [depender] is consistent with the
-  /// other dependencies on the same package. Throws a [SolverFailure]
+  /// other dependencies on the same package. Throws a [SolveFailure]
   /// exception if not. Only validates sources and descriptions, not the
   /// version.
   void _validateDependency(PackageDep dep, String depender) {
@@ -474,7 +482,7 @@
     if (required == null) return;
 
     // Make sure all of the existing sources match the new reference.
-    if (required.dep.source.name != dep.source.name) {
+    if (required.dep.source != dep.source) {
       _solver.logSolve('source mismatch on ${dep.name}: ${required.dep.source} '
                        '!= ${dep.source}');
       throw new SourceMismatchException(dep.name,
@@ -482,7 +490,8 @@
     }
 
     // Make sure all of the existing descriptions match the new reference.
-    if (!dep.descriptionEquals(required.dep)) {
+    var source = _solver.sources[dep.source];
+    if (!source.descriptionsEqual(dep.description, required.dep.description)) {
       _solver.logSolve('description mismatch on ${dep.name}: '
                        '${required.dep.description} != ${dep.description}');
       throw new DescriptionMismatchException(dep.name,
@@ -492,7 +501,7 @@
 
   /// Adds the version constraint that [depender] places on [dep] to the
   /// overall constraint that all shared dependencies place on [dep]. Throws a
-  /// [SolverFailure] if that results in an unsolvable constraints.
+  /// [SolveFailure] if that results in an unsolvable constraints.
   ///
   /// Returns the combined [VersionConstraint] that all dependers place on the
   /// package.
@@ -517,7 +526,7 @@
 
   /// Validates the currently selected package against the new dependency that
   /// [dep] and [constraint] place on it. Returns `null` if there is no
-  /// currently selected package, throws a [SolverFailure] if the new reference
+  /// currently selected package, throws a [SolveFailure] if the new reference
   /// it not does not allow the previously selected version, or returns the
   /// selected package if successful.
   PackageId _validateSelected(PackageDep dep, VersionConstraint constraint) {
@@ -538,7 +547,7 @@
   /// the solver state so that we can backtrack from this decision if it turns
   /// out wrong, but continues traversing with the new selection.
   ///
-  /// Returns a future that completes with a [SolverFailure] if a version
+  /// Returns a future that completes with a [SolveFailure] if a version
   /// could not be selected or that completes successfully if a package was
   /// selected and traversing should continue.
   Future _selectPackage(PackageDep dep, VersionConstraint constraint) {
@@ -608,8 +617,11 @@
 
     var required = _getRequired(name);
     if (required != null) {
-      if (package.source.name != required.dep.source.name) return null;
-      if (!package.descriptionEquals(required.dep)) return null;
+      if (package.source != required.dep.source) return null;
+
+      var source = _solver.sources[package.source];
+      if (!source.descriptionsEqual(
+          package.description, required.dep.description)) return null;
     }
 
     return package;
@@ -617,7 +629,7 @@
 }
 
 /// Ensures that if [pubspec] has an SDK constraint, then it is compatible
-/// with the current SDK. Throws a [SolverFailure] if not.
+/// with the current SDK. Throws a [SolveFailure] if not.
 void _validateSdkConstraint(Pubspec pubspec) {
   // If the user is running a continouous build of the SDK, just disable SDK
   // constraint checking entirely. The actual version number you get is
diff --git a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
index 885acdc..1ae8d3e 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
@@ -14,6 +14,7 @@
 import '../source.dart';
 import '../source_registry.dart';
 import '../version.dart';
+import '../utils.dart';
 import 'backtracking_solver.dart';
 
 /// Attempts to select the best concrete versions for all of the transitive
@@ -70,7 +71,11 @@
 /// Used to avoid requesting the same pubspec from the server repeatedly.
 class PubspecCache {
   final SourceRegistry _sources;
+
+  /// The already-requested cached version lists.
   final _versions = new Map<PackageRef, List<PackageId>>();
+
+  /// The already-requested cached pubspecs.
   final _pubspecs = new Map<PackageId, Pubspec>();
 
   /// The number of times a version list was requested and it wasn't cached and
@@ -105,10 +110,9 @@
     }
 
     pubspecCacheMisses++;
-    return id.describe().then((pubspec) {
-      log.solver('requested $id pubspec');
 
-      // Cache it.
+    var source = _sources[id.source];
+    return source.describe(id).then((pubspec) {
       _pubspecs[id] = pubspec;
       return pubspec;
     });
@@ -120,6 +124,10 @@
 
   /// Gets the list of versions for [package] in descending order.
   Future<List<PackageId>> getVersions(PackageRef package) {
+    if (package.isRoot) {
+      throw new StateError("Cannot get versions for root package $package.");
+    }
+
     // See if we have it cached.
     var versions = _versions[package];
     if (versions != null) {
@@ -128,11 +136,14 @@
     }
 
     versionCacheMisses++;
-    return package.getVersions().then((ids) {
-      // Sort by descending version so we try newer versions first.
-      ids.sort((a, b) => b.version.compareTo(a.version));
 
-      log.solver('requested $package version list');
+    var source = _sources[package.source];
+    return source.getVersions(package.name, package.description)
+        .then((versions) {
+      // Sort by descending version so we try newer versions first.
+      versions.sort((a, b) => b.compareTo(a));
+
+      var ids = versions.map((version) => package.atVersion(version)).toList();
       _versions[package] = ids;
       return ids;
     });
@@ -153,7 +164,7 @@
 }
 
 /// Base class for all failures that can occur while trying to resolve versions.
-class SolveFailure implements Exception {
+abstract class SolveFailure implements ApplicationException {
   /// The name of the package whose version could not be solved. Will be `null`
   /// if the failure is not specific to one package.
   final String package;
@@ -270,7 +281,6 @@
 /// Exception thrown when two packages with the same name but different sources
 /// are depended upon.
 class SourceMismatchException extends SolveFailure {
-
   SourceMismatchException(String package, Iterable<Dependency> dependencies)
       : super(package, dependencies);
 
@@ -280,6 +290,18 @@
       "depends on it from source ${dep.source}";
 }
 
+/// Exception thrown when a dependency on an unknown source name is found.
+class UnknownSourceException extends SolveFailure {
+  UnknownSourceException(String package, Iterable<Dependency> dependencies)
+      : super(package, dependencies);
+
+  String toString() {
+    var dep = only(dependencies);
+    return "Package '${dep.depender}' depends on '${dep.dep.name}' from "
+           "unknown source '${dep.dep.source}'.";
+  }
+}
+
 /// Exception thrown when two packages with the same name and source but
 /// different descriptions are depended upon.
 class DescriptionMismatchException extends SolveFailure {
diff --git a/sdk/lib/_internal/pub/lib/src/source.dart b/sdk/lib/_internal/pub/lib/src/source.dart
index 2486e78..f72f173 100644
--- a/sdk/lib/_internal/pub/lib/src/source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source.dart
@@ -68,20 +68,54 @@
   /// By default, this assumes that each description has a single version and
   /// uses [describe] to get that version.
   Future<List<Version>> getVersions(String name, description) {
-    return describe(new PackageId(name, this, Version.none, description))
-      .then((pubspec) => [pubspec.version]);
+    var id = new PackageId(name, this.name, Version.none, description);
+    return describeUncached(id).then((pubspec) => [pubspec.version]);
   }
 
   /// Loads the (possibly remote) pubspec for the package version identified by
   /// [id]. This may be called for packages that have not yet been installed
   /// during the version resolution process.
   ///
+  /// If the package has been installed to the system cache, the cached pubspec
+  /// will be used. Otherwise, it delegates to host-specific lookup behavior.
+  ///
   /// For cached sources, by default this uses [installToSystemCache] to get the
   /// pubspec. There is no default implementation for non-cached sources; they
   /// must implement it manually.
   Future<Pubspec> describe(PackageId id) {
+    if (id.isRoot) throw new ArgumentError("Cannot describe the root package.");
+    if (id.source != name) {
+      throw new ArgumentError("Package $id does not use source $name.");
+    }
+
+    // Try to get it from the system cache first.
+    if (shouldCache) {
+      return systemCacheDirectory(id).then((packageDir) {
+        if (!fileExists(path.join(packageDir, "pubspec.yaml"))) {
+          return describeUncached(id);
+        }
+
+        return new Pubspec.load(id.name, packageDir, _systemCache.sources);
+      });
+    }
+
+    // Not cached, so get it from the source.
+    return describeUncached(id);
+  }
+
+  /// Loads the pubspec for the package version identified by [id] which is not
+  /// already in the system cache.
+  ///
+  /// For cached sources, by default this uses [installToSystemCache] to get
+  /// the pubspec. There is no default implementation for non-cached sources;
+  /// they must implement it manually.
+  ///
+  /// This method is effectively protected. Derived classes may override it,
+  /// but external code should not call it. Call [describe()] instead.
+  Future<Pubspec> describeUncached(PackageId id) {
     if (!shouldCache) {
-      throw new UnimplementedError("Source $name must implement describe(id).");
+      throw new UnimplementedError(
+          "Source $name must implement describeUncached(id).");
     }
     return installToSystemCache(id).then((package) => package.pubspec);
   }
diff --git a/sdk/lib/_internal/pub/lib/src/system_cache.dart b/sdk/lib/_internal/pub/lib/src/system_cache.dart
index 567803b..63de5dc 100644
--- a/sdk/lib/_internal/pub/lib/src/system_cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/system_cache.dart
@@ -70,41 +70,25 @@
     sources.register(source);
   }
 
-  /// Gets the package identified by [id]. If the package is already cached,
-  /// reads it from the cache. Otherwise, requests it from the source.
-  Future<Pubspec> describe(PackageId id) {
-    if (id.isRoot) throw new ArgumentError("Cannot describe the root package.");
-
-    // Try to get it from the system cache first.
-    if (id.source.shouldCache) {
-      return id.systemCacheDirectory.then((packageDir) {
-        if (!fileExists(path.join(packageDir, "pubspec.yaml"))) {
-          return id.source.describe(id);
-        }
-
-        return new Pubspec.load(id.name, packageDir, sources);
-      });
-    }
-
-    // Not cached, so get it from the source.
-    return id.source.describe(id);
-  }
-
   /// Ensures that the package identified by [id] is installed to the cache,
   /// loads it, and returns it.
   ///
-  /// It is an error to try installing a package from a source with `shouldCache
-  /// == false` to the system cache.
+  /// It is an error to try installing a package from a source with
+  /// `shouldCache == false` to the system cache.
   Future<Package> install(PackageId id) {
-    if (!id.source.shouldCache) {
+    var source = sources[id.source];
+
+    if (!source.shouldCache) {
       throw new ArgumentError("Package $id is not cacheable.");
     }
 
     var pending = _pendingInstalls[id];
     if (pending != null) return pending;
 
-    var future = id.source.installToSystemCache(id)
-        .whenComplete(() { _pendingInstalls.remove(id); });
+    var future = source.installToSystemCache(id).whenComplete(() {
+      _pendingInstalls.remove(id);
+    });
+
     _pendingInstalls[id] = future;
     return future;
   }
diff --git a/sdk/lib/_internal/pub/lib/src/validator/dependency.dart b/sdk/lib/_internal/pub/lib/src/validator/dependency.dart
index c147f7b..a1a8f99 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/dependency.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/dependency.dart
@@ -22,7 +22,7 @@
 
   Future validate() {
     return Future.forEach(entrypoint.root.pubspec.dependencies, (dependency) {
-      if (dependency.source is! HostedSource) {
+      if (dependency.source != "hosted") {
         return _warnAboutSource(dependency);
       }
 
@@ -59,11 +59,11 @@
 
       // Path sources are errors. Other sources are just warnings.
       var messages = warnings;
-      if (dep.source is PathSource) {
+      if (dep.source == "path") {
         messages = errors;
       }
 
-      messages.add('Don\'t depend on "${dep.name}" from the ${dep.source.name} '
+      messages.add('Don\'t depend on "${dep.name}" from the ${dep.source} '
               'source. Use the hosted source instead. For example:\n'
           '\n'
           'dependencies:\n'
diff --git a/sdk/lib/_internal/pub/lib/src/validator/license.dart b/sdk/lib/_internal/pub/lib/src/validator/license.dart
index 50d1bfe..16b202f 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/license.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/license.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library pubspec_field_validator;
+library license_validator;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/test/install/unknown_source_test.dart b/sdk/lib/_internal/pub/test/install/unknown_source_test.dart
new file mode 100644
index 0000000..e8250c5
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/install/unknown_source_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS d.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 d.file.
+
+library pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('fails gracefully on a dependency from an unknown source', () {
+    d.appDir([{"bad": "foo"}]).create();
+
+    schedulePub(args: ['install'],
+        error: new RegExp("Package 'myapp' depends on 'foo' from unknown "
+                          "source 'bad'.\$"),
+        exitCode: 1);
+  });
+
+  integration('fails gracefully on transitive dependency from an unknown '
+              'source', () {
+    d.dir('foo', [
+      d.libDir('foo', 'foo 0.0.1'),
+      d.libPubspec('foo', '0.0.1', deps: [{"bad": "bar"}])
+    ]).create();
+
+    d.appDir([{"path": "../foo"}]).create();
+
+    schedulePub(args: ['install'],
+        error: new RegExp("Package 'foo' depends on 'bar' from unknown "
+                          "source 'bad'.\$"),
+        exitCode: 1);
+  });
+
+  integration('ignores unknown source in lockfile', () {
+    d.dir('foo', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '0.0.1')
+    ]).create();
+
+    // Depend on "foo" from a valid source.
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "foo": {"path": "../foo"}
+        }
+      })
+    ]).create();
+
+    // But lock it to a bad one.
+    d.dir(appPath, [
+      d.file("pubspec.lock", json.stringify({
+        'packages': {
+          'foo': {
+            'version': '0.0.0',
+            'source': 'bad',
+            'description': {
+              'name': 'foo'
+            }
+          }
+        }
+      }))
+    ]).create();
+
+    schedulePub(args: ['install'],
+        output: new RegExp(r"Dependencies installed!$"));
+
+    // Should update to the new one.
+    d.dir(packagesPath, [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/lock_file_test.dart b/sdk/lib/_internal/pub/test/lock_file_test.dart
index 0f7fe53..8b05d9d 100644
--- a/sdk/lib/_internal/pub/test/lock_file_test.dart
+++ b/sdk/lib/_internal/pub/test/lock_file_test.dart
@@ -13,6 +13,7 @@
 import '../lib/src/source_registry.dart';
 import '../lib/src/utils.dart';
 import '../lib/src/version.dart';
+import 'test_pub.dart';
 
 class MockSource extends Source {
   final String name = 'mock';
@@ -31,6 +32,8 @@
 }
 
 main() {
+  initConfig();
+
   var sources = new SourceRegistry();
   var mockSource = new MockSource();
   sources.register(mockSource);
@@ -65,16 +68,28 @@
         var bar = lockFile.packages['bar'];
         expect(bar.name, equals('bar'));
         expect(bar.version, equals(new Version(1, 2, 3)));
-        expect(bar.source, equals(mockSource));
+        expect(bar.source, equals(mockSource.name));
         expect(bar.description, equals('bar desc'));
 
         var foo = lockFile.packages['foo'];
         expect(foo.name, equals('foo'));
         expect(foo.version, equals(new Version(2, 3, 4)));
-        expect(foo.source, equals(mockSource));
+        expect(foo.source, equals(mockSource.name));
         expect(foo.description, equals('foo desc'));
       });
 
+      test("allows an unknown source", () {
+        var lockFile = new LockFile.parse('''
+packages:
+  foo:
+    source: bad
+    version: 1.2.3
+    description: foo desc
+''', sources);
+        var foo = lockFile.packages['foo'];
+        expect(foo.source, equals('bad'));
+      });
+
       test("throws if the version is missing", () {
         expect(() {
           new LockFile.parse('''
@@ -109,18 +124,6 @@
         }, throwsFormatException);
       });
 
-      test("throws if the source is unknown", () {
-        expect(() {
-          new LockFile.parse('''
-packages:
-  foo:
-    version: 1.2.3
-    source: notreal
-    description: foo desc
-''', sources);
-        }, throwsFormatException);
-      });
-
       test("throws if the description is missing", () {
         expect(() {
           new LockFile.parse('''
@@ -166,9 +169,9 @@
 
       test('dumps the lockfile to YAML', () {
         lockfile.packages['foo'] = new PackageId(
-            'foo', mockSource, new Version.parse('1.2.3'), 'foo desc');
+            'foo', mockSource.name, new Version.parse('1.2.3'), 'foo desc');
         lockfile.packages['bar'] = new PackageId(
-            'bar', mockSource, new Version.parse('3.2.1'), 'bar desc');
+            'bar', mockSource.name, new Version.parse('3.2.1'), 'bar desc');
 
         expect(loadYaml(lockfile.serialize()), equals({
           'packages': {
@@ -189,7 +192,7 @@
       test('lockfile is alphabetized by package name', () {
         var testNames = ['baz', 'Qwe', 'Q', 'B', 'Bar', 'bar', 'foo'];
         testNames.forEach((name) {
-          lockfile.packages[name] = new PackageId(name, mockSource,
+          lockfile.packages[name] = new PackageId(name, mockSource.name,
             new Version.parse('5.5.5'), '$name desc');
         });
 
diff --git a/sdk/lib/_internal/pub/test/pub_cache_test.dart b/sdk/lib/_internal/pub/test/pub_cache_test.dart
index 6166514..cb38da7 100644
--- a/sdk/lib/_internal/pub/test/pub_cache_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_cache_test.dart
@@ -15,9 +15,9 @@
 
 main() {
   initConfig();
-  
+
   integration('running pub cache displays error message', () {
-    schedulePub(args: ['cache'], 
+    schedulePub(args: ['cache'],
         output: '''
           Inspect the system cache.
 
@@ -26,9 +26,9 @@
         error: 'The cache command expects one argument.',
         exitCode: 64);
   });
-  
+
   integration('running pub cache foo displays error message', () {
-    schedulePub(args: ['cache' ,'foo'], 
+    schedulePub(args: ['cache' ,'foo'],
         output: '''
           Inspect the system cache.
 
@@ -37,12 +37,12 @@
         error: 'Unknown cache command "foo".',
         exitCode: 64);
   });
-  
-  integration('running pub cache list when there is no cache', () {      
+
+  integration('running pub cache list when there is no cache', () {
     schedulePub(args: ['cache', 'list'], output: '{"packages":{}}');
   });
-  
-  integration('running pub cache list on empty cache', () {      
+
+  integration('running pub cache list on empty cache', () {
     // Set up a cache.
     d.dir(cachePath, [
       d.dir('hosted', [
@@ -50,10 +50,10 @@
         ])
       ])
     ]).create();
-    
+
     schedulePub(args: ['cache', 'list'], output: '{"packages":{}}');
   });
-  
+
   integration('running pub cache list', () {
     // Set up a cache.
     d.dir(cachePath, [
@@ -69,11 +69,28 @@
         ])
       ])
     ]).create();
-    
-    schedulePub(args: ['cache', 'list'], output: 
+
+    schedulePub(args: ['cache', 'list'], output:
       new RegExp(r'\{"packages":\{"bar":\{"version":"2\.0\.0","location":'
           r'"[^"]+bar-2\.0\.0"\},"foo":\{"version":"1\.2\.3","location":'
           r'"[^"]+foo-1\.2\.3"\}\}\}$'));
   });
-  
+
+  integration('includes packages containing deps with bad sources', () {
+    // Set up a cache.
+    d.dir(cachePath, [
+      d.dir('hosted', [
+         d.dir('pub.dartlang.org', [
+          d.dir("foo-1.2.3", [
+            d.libPubspec("foo", "1.2.3", deps: [{"bad": "bar"}]),
+            d.libDir("foo")
+          ])
+        ])
+      ])
+    ]).create();
+
+    schedulePub(args: ['cache', 'list'], output:
+      new RegExp(r'\{"packages":\{"foo":\{"version":"1\.2\.3","location":'
+          r'"[^"]+foo-1\.2\.3"\}\}\}$'));
+  });
 }
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/test/pubspec_test.dart b/sdk/lib/_internal/pub/test/pubspec_test.dart
index 19f62d4..45413db 100644
--- a/sdk/lib/_internal/pub/test/pubspec_test.dart
+++ b/sdk/lib/_internal/pub/test/pubspec_test.dart
@@ -81,6 +81,18 @@
       expect(pubspec.devDependencies, isEmpty);
     });
 
+    test("allows an unknown source", () {
+      var pubspec = new Pubspec.parse(null, '''
+dependencies:
+  foo:
+    unknown: blah
+''', sources);
+
+      var foo = pubspec.dependencies[0];
+      expect(foo.name, equals('foo'));
+      expect(foo.source, equals('unknown'));
+    });
+
     test("throws if a package is in dependencies and dev_dependencies", () {
       expectFormatError('''
 dependencies:
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index 8d417ed..37bf6d0 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -545,20 +545,6 @@
     for (var dependency in resolvedDependencies) {
       var keys = dependency.keys.where((key) => key != "version");
       var sourceName = only(keys);
-      var source;
-      switch (sourceName) {
-      case "git":
-        source = new GitSource();
-        break;
-      case "hosted":
-        source = new HostedSource();
-        break;
-      case "path":
-        source = new PathSource();
-        break;
-      default:
-        throw new Exception('Unknown source "$sourceName"');
-      }
 
       result[_packageName(sourceName, dependency[sourceName])] = dependency;
     }
diff --git a/sdk/lib/_internal/pub/test/update/unknown_source_test.dart b/sdk/lib/_internal/pub/test/update/unknown_source_test.dart
new file mode 100644
index 0000000..92dfe1f
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/update/unknown_source_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS d.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 d.file.
+
+library pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('fails gracefully on a dependency from an unknown source', () {
+    d.appDir([{"bad": "foo"}]).create();
+
+    schedulePub(args: ['update'],
+        error: new RegExp("Package 'myapp' depends on 'foo' from unknown "
+                          "source 'bad'.\$"),
+        exitCode: 1);
+  });
+
+  integration('fails gracefully on transitive dependency from an unknown '
+              'source', () {
+    d.dir('foo', [
+      d.libDir('foo', 'foo 0.0.1'),
+      d.libPubspec('foo', '0.0.1', deps: [{"bad": "bar"}])
+    ]).create();
+
+    d.appDir([{"path": "../foo"}]).create();
+
+    schedulePub(args: ['update'],
+        error: new RegExp("Package 'foo' depends on 'bar' from unknown "
+                          "source 'bad'.\$"),
+        exitCode: 1);
+  });
+
+  integration('ignores unknown source in lockfile', () {
+    d.dir('foo', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '0.0.1')
+    ]).create();
+
+    // Depend on "foo" from a valid source.
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "foo": {"path": "../foo"}
+        }
+      })
+    ]).create();
+
+    // But lock it to a bad one.
+    d.dir(appPath, [
+      d.file("pubspec.lock", json.stringify({
+        'packages': {
+          'foo': {
+            'version': '0.0.0',
+            'source': 'bad',
+            'description': {
+              'name': 'foo'
+            }
+          }
+        }
+      }))
+    ]).create();
+
+    schedulePub(args: ['update'],
+        output: new RegExp(r"Dependencies updated!$"));
+
+    // Should update to the new one.
+    d.dir(packagesPath, [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
+      ])
+    ]).validate();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/version_solver_test.dart b/sdk/lib/_internal/pub/test/version_solver_test.dart
index 35af3ac..47d7198 100644
--- a/sdk/lib/_internal/pub/test/version_solver_test.dart
+++ b/sdk/lib/_internal/pub/test/version_solver_test.dart
@@ -40,6 +40,7 @@
   group('root dependency', rootDependency);
   group('dev dependency', devDependency);
   group('unsolvable', unsolvable);
+  group('bad source', badSource);
   group('backtracking', backtracking);
   group('SDK constraint', sdkConstraint);
 }
@@ -404,6 +405,55 @@
   }, error: couldNotSolve, maxTries: 4);
 }
 
+badSource() {
+  testResolve('fail if the root package has a bad source in dep', {
+    'myapp 0.0.0': {
+      'foo from bad': 'any'
+    },
+  }, error: unknownSource('myapp', 'foo', 'bad'));
+
+  testResolve('fail if the root package has a bad source in dev dep', {
+    'myapp 0.0.0': {
+      '(dev) foo from bad': 'any'
+    },
+  }, error: unknownSource('myapp', 'foo', 'bad'));
+
+  testResolve('fail if all versions have bad source in dep', {
+    'myapp 0.0.0': {
+      'foo': 'any'
+    },
+    'foo 1.0.0': {
+      'bar from bad': 'any'
+    },
+    'foo 1.0.1': {
+      'baz from bad': 'any'
+    },
+    'foo 1.0.3': {
+      'bang from bad': 'any'
+    },
+  }, error: unknownSource('foo', 'bar', 'bad'), maxTries: 3);
+
+  testResolve('ignore versions with bad source in dep', {
+    'myapp 1.0.0': {
+      'foo': 'any'
+    },
+    'foo 1.0.0': {
+      'bar': 'any'
+    },
+    'foo 1.0.1': {
+      'bar from bad': 'any'
+    },
+    'foo 1.0.3': {
+      'bar from bad': 'any'
+    },
+    'bar 1.0.0': {}
+  }, result: {
+    'myapp from root': '1.0.0',
+    'foo': '1.0.0',
+    'bar': '1.0.0'
+  }, maxTries: 3);
+}
+
 backtracking() {
   testResolve('circular dependency on older version', {
     'myapp 0.0.0': {
@@ -775,7 +825,7 @@
           // remote server.
           root = package;
         } else {
-          source.addPackage(name, package);
+          cache.sources[source].addPackage(name, package);
         }
       });
     });
@@ -797,7 +847,7 @@
       lockfile.forEach((name, version) {
         version = new Version.parse(version);
         realLockFile.packages[name] =
-          new PackageId(name, source1, version, name);
+            new PackageId(name, source1.name, version, name);
       });
     }
 
@@ -856,6 +906,11 @@
       SourceMismatchException);
 }
 
+unknownSource(String depender, String dependency, String source) {
+  return (maxTries) => new SolveFailMatcher([depender, dependency, source],
+      maxTries, UnknownSourceException);
+}
+
 class SolveSuccessMatcher implements Matcher {
   /// The expected concrete package selections.
   final Map<String, PackageId> _expected;
@@ -877,7 +932,7 @@
                                MatchState state, bool verbose) {
     if (!result.succeeded) {
       description.add('Solver failed with:\n${result.error}');
-      return;
+      return null;
     }
 
     description.add('Resolved:\n${_listPackages(result.packages)}\n');
@@ -1033,6 +1088,7 @@
         throw new Exception('MockSource does not have a package matching '
             '"$description".');
       }
+
       return _packages[description].keys.toList();
     });
   }
@@ -1098,7 +1154,7 @@
 }
 
 void parseSource(String description,
-    callback(bool isDev, String name, Source source)) {
+    callback(bool isDev, String name, String source)) {
   var isDev = false;
 
   if (description.startsWith("(dev) ")) {
@@ -1107,18 +1163,12 @@
   }
 
   var name = description;
-  var source = source1;
-
-  var sourceNames = {
-    'mock1': source1,
-    'mock2': source2,
-    'root': null
-  };
-
+  var source = "mock1";
   var match = new RegExp(r"(.*) from (.*)").firstMatch(description);
   if (match != null) {
     name = match[1];
-    source = sourceNames[match[2]];
+    source = match[2];
+    if (source == "root") source = null;
   }
 
   callback(isDev, name, source);
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 3e7dbdc..6ff3ee2 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -50,11 +50,6 @@
   final _StreamImpl<T> stream;
 
   /**
-   *
-   * If the stream is canceled before the controller needs new data the
-   * [onResume] call might not be executed.
-      : stream = new _MultiControllerStream<T>(
-            onListen, onPause, onResume, onCancel);
    * A controller with a [stream] that supports only one single subscriber.
    *
    * The controller will buffer all incoming events until the subscriber is
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 9a0bf6f..ef6239a 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -39,7 +39,7 @@
   Iterator<E> get iterator;
 
   /**
-   * Returns a lazy [Iterable] where each element [:e:] of [this] is replaced
+   * Returns a lazy [Iterable] where each element [:e:] of `this` is replaced
    * by the result of [:f(e):].
    *
    * This method returns a view of the mapped elements. As long as the
@@ -112,7 +112,7 @@
 
   /**
    * Returns true if every elements of this collection satisify the
-   * predicate [f]. Returns false otherwise.
+   * predicate [f]. Returns `false` otherwise.
    */
   bool every(bool f(E element));
 
@@ -164,7 +164,7 @@
   /**
    * Returns an [Iterable] with at most [n] elements.
    *
-   * The returned [Iterable] may contain fewer than [n] elements, if [this]
+   * The returned [Iterable] may contain fewer than [n] elements, if `this`
    * contains fewer than [n] elements.
    */
   Iterable<E> take(int n);
@@ -173,9 +173,10 @@
    * Returns an [Iterable] that stops once [test] is not satisfied anymore.
    *
    * The filtering happens lazily. Every new [Iterator] of the returned
-   * [Iterable] will start iterating over the elements of [this].
-   * When the iterator encounters an element [:e:] that does not satisfy [test],
-   * it discards [:e:] and moves into the finished state. That is, it will not
+   * [Iterable] will start iterating over the elements of `this`.
+   *
+   * When the iterator encounters an element `e` that does not satisfy [test],
+   * it discards `e` and moves into the finished state. That is, it will not
    * ask or provide any more elements.
    */
   Iterable<E> takeWhile(bool test(E value));
@@ -183,7 +184,7 @@
   /**
    * Returns an [Iterable] that skips the first [n] elements.
    *
-   * If [this] has fewer than [n] elements, then the resulting [Iterable] will
+   * If `this` has fewer than [n] elements, then the resulting [Iterable] will
    * be empty.
    */
   Iterable<E> skip(int n);
@@ -192,17 +193,20 @@
    * Returns an [Iterable] that skips elements while [test] is satisfied.
    *
    * The filtering happens lazily. Every new [Iterator] of the returned
-   * [Iterable] will iterate over all elements of [this].
+   * [Iterable] will iterate over all elements of `this`.
+   *
    * As long as the iterator's elements do not satisfy [test] they are
    * discarded. Once an element satisfies the [test] the iterator stops testing
-   * and uses every element unconditionally.
+   * and uses every element unconditionally. That is, the elements of the
+   * returned [Iterable] are the elements of `this` starting from the first
+   * element that doesn't satisfy [test].
    */
   Iterable<E> skipWhile(bool test(E value));
 
   /**
    * Returns the first element.
    *
-   * If [this] is empty throws a [StateError]. Otherwise this method is
+   * If `this` is empty throws a [StateError]. Otherwise this method is
    * equivalent to [:this.elementAt(0):]
    */
   E get first;
@@ -210,14 +214,14 @@
   /**
    * Returns the last element.
    *
-   * If [this] is empty throws a [StateError].
+   * If `this` is empty throws a [StateError].
    */
   E get last;
 
   /**
-   * Returns the single element in [this].
+   * Returns the single element in `this`.
    *
-   * If [this] is empty or has more than one element throws a [StateError].
+   * If `this` is empty or has more than one element throws a [StateError].
    */
   E get single;
 
@@ -234,7 +238,7 @@
    * Returns the last element that satisfies the given predicate [f].
    *
    * If none matches, the result of invoking the [orElse] function is
-   * returned. By default, when [orElse] is [:null:], a [StateError] is
+   * returned. By default, when [orElse] is `null`, a [StateError] is
    * thrown.
    */
   E lastWhere(bool test(E value), {E orElse()});
@@ -248,12 +252,11 @@
   /**
    * Returns the [index]th element.
    *
-   * If [this] [Iterable] has fewer than [index] elements throws a
-   * [RangeError].
+   * If `this` has fewer than [index] elements throws a [RangeError].
    *
-   * Note: if [this] does not have a deterministic iteration order then the
+   * Note: if `this` does not have a deterministic iteration order then the
    * function may simply return any element without any iteration if there are
-   * at least [index] elements in [this].
+   * at least [index] elements in `this`.
    */
   E elementAt(int index);
 }
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index 59a1563..672c8b8 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -21,18 +21,18 @@
  *
  * Example:
  *
- *    var fixedLengthList = new List(5);
- *    fixedLengthList.length = 0;  // throws.
- *    fixedLengthList.add(499);  // throws
- *    fixedLengthList[0] = 87;
- *    var growableList = [1, 2];
- *    growableList.length = 0;
- *    growableList.add(499);
- *    growableList[0] = 87;
- *    var unmodifiableList = const [1, 2];
- *    unmodifiableList.length = 0;  // throws.
- *    unmodifiableList.add(499);  // throws
- *    unmodifiableList[0] = 87;  // throws.
+ *     var fixedLengthList = new List(5);
+ *     fixedLengthList.length = 0;  // throws.
+ *     fixedLengthList.add(499);  // throws
+ *     fixedLengthList[0] = 87;
+ *     var growableList = [1, 2];
+ *     growableList.length = 0;
+ *     growableList.add(499);
+ *     growableList[0] = 87;
+ *     var unmodifiableList = const [1, 2];
+ *     unmodifiableList.length = 0;  // throws.
+ *     unmodifiableList.add(499);  // throws
+ *     unmodifiableList[0] = 87;  // throws.
  *
  * Lists are [Iterable].
  * List iteration iterates over values in index order.
@@ -94,7 +94,7 @@
    * for each index in the range `0` .. `[length] - 1`
    * in increasing order.
    *
-   * The created length's length is fixed unless [growable] is true.
+   * The created list's length is fixed unless [growable] is true.
    */
   factory List.generate(int length, E generator(int index),
                        { bool growable: true }) {
@@ -118,6 +118,7 @@
 
   /**
    * Sets the entry at the given [index] in the list to [value].
+   *
    * Throws an [RangeError] if [index] is out of bounds.
    */
   void operator []=(int index, E value);
@@ -131,20 +132,23 @@
 
   /**
    * Changes the length of the list. If [newLength] is greater than
-   * the current [length], entries are initialized to [:null:]. Throws
-   * an [UnsupportedError] if the list is not extendable.
+   * the current [length], entries are initialized to [:null:].
+   *
+   * Throws an [UnsupportedError] if the list is not extendable.
    */
   void set length(int newLength);
 
   /**
    * Adds [value] at the end of the list, extending the length by
-   * one. Throws an [UnsupportedError] if the list is not
-   * extendable.
+   * one.
+   *
+   * Throws an [UnsupportedError] if the list is not extendable.
    */
   void add(E value);
 
   /**
    * Appends all elements of the [iterable] to the end of this list.
+   *
    * Extends the length of the list by the number of elements in [iterable].
    * Throws an [UnsupportedError] if this list is not extensible.
    */
@@ -159,6 +163,7 @@
    * Sorts the list according to the order specified by the [compare] function.
    *
    * The [compare] function must act as a [Comparator].
+   *
    * The default [List] implementations use [Comparable.compare] if
    * [compare] is omitted.
    */
@@ -178,9 +183,12 @@
    * Returns the last index of [element] in the list.
    *
    * Searches the list backwards from index [start] (inclusive) to 0.
+   *
    * The first time an element [:e:] is encountered so that [:e == element:],
    * the index of [:e:] is returned.
-   * If start is not provided, it defaults to [:this.length - 1:] .
+   *
+   * If start is not provided, it defaults to [:this.length - 1:].
+   *
    * Returns -1 if [element] is not found.
    */
   int lastIndexOf(E element, [int start]);
@@ -189,6 +197,7 @@
    * Removes all elements in the list.
    *
    * The length of the list becomes zero.
+   *
    * Throws an [UnsupportedError], and retains all elements, if the
    * length of the list cannot be changed.
    */
@@ -220,7 +229,7 @@
    * Overwrites elements of `this` with the elemenst of [iterable] starting
    * at position [index] in the list.
    *
-   * This operation does not increase the length of the list.
+   * This operation does not increase the length of `this`.
    *
    * It is an error if the [index] does not point inside the list or at the
    * position after the last element.
@@ -239,14 +248,18 @@
   /**
    * Removes the element at position [index] from the list.
    *
-   * This reduces the length of the list by one and moves all later elements
+   * This reduces the length of `this` by one and moves all later elements
    * down by one position.
+   *
    * Returns the removed element.
+   *
    * Throws an [ArgumentError] if [index] is not an [int].
+   *
    * Throws an [RangeError] if the [index] does not point inside
    * the list.
+   *
    * Throws an [UnsupportedError], and doesn't remove the element,
-   * if the length of the list cannot be changed.
+   * if the length of `this` cannot be changed.
    */
   E removeAt(int index);
 
@@ -274,9 +287,9 @@
   /**
    * Returns a new list containing the elements from [start] to [end].
    *
-   * If [end] is omitted, the [length] of the list is used.
+   * If [end] is omitted, the [length] of `this` is used.
    *
-   * It is an error if [start] or [end] are not list indices for this list,
+   * It is an error if [start] or [end] are not indices into `this`,
    * or if [end] is before [start].
    */
   List<E> sublist(int start, [int end]);
@@ -304,17 +317,24 @@
   Iterable<E> getRange(int start, int end);
 
   /**
-   * Copies the elements of [iterable], skipping the [skipCount] first elements
+   * Copies the elements of [iterable], skipping the [skipCount] first elements,
    * into the range [start] to [end] exclusive of `this`.
    *
-   * If [start] equals [end] and represent a legal range, this method has
-   * no effect.
+   * If [start] equals [end] and [start]..[end] represents a legal range, this
+   * method has no effect.
    *
    * It is an error if [start]..[end] is not a valid range pointing into the
    * `this`.
    *
    * It is an error if the [iterable] does not have enough elements after
    * skipping [skipCount] elements.
+   *
+   * Example:
+   *
+   *     var list = [1, 2, 3, 4];
+   *     var list2 = [5, 6, 7, 8, 9];
+   *     list.setRange(1, 3, list2, 3);
+   *     print(list);  // => [1, 8, 9, 4]
    */
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]);
 
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index ebcfe10..7db20f3 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -145,13 +145,31 @@
   String substring(int startIndex, [int endIndex]);
 
   /**
-   * Removes leading and trailing whitespace from a string. If the string
-   * contains leading or trailing whitespace a new string with no leading and
-   * no trailing whitespace is returned. Otherwise, the string itself is
-   * returned.  Whitespace is defined as every Unicode character in the Zs, Zl
-   * and Zp categories (this includes no-break space), the spacing control
-   * characters from 9 to 13 (tab, lf, vtab, ff and cr), and 0xfeff the BOM
-   * character.
+   * Removes leading and trailing whitespace from a string.
+   *
+   * If the string contains leading or trailing whitespace a new string with no
+   * leading and no trailing whitespace is returned. Otherwise, the string
+   * itself is returned.
+   *
+   * Whitespace is defined by the Unicode White_Space property (as defined in
+   * version 6.2 or later) and the BOM character, 0xFEFF.
+   *
+   * Here is the list of trimmed characters (following version 6.2):
+   *
+   *     0009..000D    ; White_Space # Cc   <control-0009>..<control-000D>
+   *     0020          ; White_Space # Zs   SPACE
+   *     0085          ; White_Space # Cc   <control-0085>
+   *     00A0          ; White_Space # Zs   NO-BREAK SPACE
+   *     1680          ; White_Space # Zs   OGHAM SPACE MARK
+   *     180E          ; White_Space # Zs   MONGOLIAN VOWEL SEPARATOR
+   *     2000..200A    ; White_Space # Zs   EN QUAD..HAIR SPACE
+   *     2028          ; White_Space # Zl   LINE SEPARATOR
+   *     2029          ; White_Space # Zp   PARAGRAPH SEPARATOR
+   *     202F          ; White_Space # Zs   NARROW NO-BREAK SPACE
+   *     205F          ; White_Space # Zs   MEDIUM MATHEMATICAL SPACE
+   *     3000          ; White_Space # Zs   IDEOGRAPHIC SPACE
+   *
+   *     FEFF          ; BOM                ZERO WIDTH NO_BREAK SPACE
    */
   String trim();
 
diff --git a/sdk/lib/crypto/sha1.dart b/sdk/lib/crypto/sha1.dart
index 83e9217..8ee28ce 100644
--- a/sdk/lib/crypto/sha1.dart
+++ b/sdk/lib/crypto/sha1.dart
@@ -38,15 +38,15 @@
         var n = _w[i - 3] ^ _w[i - 8] ^ _w[i - 14] ^ _w[i - 16];
         _w[i] = _rotl32(n, 1);
       }
-      var t = _rotl32(a, 5) + e + _w[i];
+      var t = _add32(_add32(_rotl32(a, 5), e), _w[i]);
       if (i < 20) {
-        t = t + ((b & c) | (~b & d)) + 0x5A827999;
+        t = _add32(_add32(t, (b & c) | (~b & d)), 0x5A827999);
       } else if (i < 40) {
-        t = t + (b ^ c ^ d) + 0x6ED9EBA1;
+        t = _add32(_add32(t, (b ^ c ^ d)), 0x6ED9EBA1);
       } else if (i < 60) {
-        t = t + ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC;
+        t = _add32(_add32(t, (b & c) | (b & d) | (c & d)), 0x8F1BBCDC);
       } else {
-        t = t + (b ^ c ^ d) + 0xCA62C1D6;
+        t = _add32(_add32(t, b ^ c ^ d), 0xCA62C1D6);
       }
 
       e = d;
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index fc77a39..3bb3ec2 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -65,7 +65,7 @@
   return JS('var', r'ReceivePortSync.dispatchCall(#, #)', id, message);
 }
 
-spawnDomFunction(f) => IsolateNatives.spawnDomFunction(f);
+spawnDomFunction(Function f) => IsolateNatives.spawnDomFunction(f);
 // 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.
@@ -1535,7 +1535,7 @@
       '#.lineDashOffset || #.webkitLineDashOffset', this, this);
 
   @DomName('CanvasRenderingContext2D.lineDashOffset')
-  void set lineDashOffset(num value) => JS('void', 
+  void set lineDashOffset(num value) => JS('void',
       'typeof #.lineDashOffset != "undefined" ? #.lineDashOffset = # : '
       '#.webkitLineDashOffset = #', this, this, value, this, value);
 }
@@ -1662,7 +1662,7 @@
 @DomName('Console')
 class Console {
 
-  static Console safeConsole = new Console();
+  static Console _safeConsole = new Console();
 
   bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
 
@@ -1735,8 +1735,8 @@
       JS('void', 'console.time(#)', title) : null;
 
   @DomName('Console.timeEnd')
-  void timeEnd(String timerName) => _isConsoleDefined ?
-      JS('void', 'console.timeEnd(#)', timerName) : null;
+  void timeEnd(String title) => _isConsoleDefined ?
+      JS('void', 'console.timeEnd(#)', title) : null;
 
   @DomName('Console.timeStamp')
   void timeStamp(Object arg) => _isConsoleDefined ?
@@ -6110,6 +6110,10 @@
   @DocsEditable
   static const EventStreamProvider<Event> readyStateChangeEvent = const EventStreamProvider<Event>('readystatechange');
 
+  @DomName('Document.securitypolicyviolationEvent')
+  @DocsEditable
+  static const EventStreamProvider<SecurityPolicyViolationEvent> securityPolicyViolationEvent = const EventStreamProvider<SecurityPolicyViolationEvent>('securitypolicyviolation');
+
   @DomName('Document.selectionchangeEvent')
   @DocsEditable
   static const EventStreamProvider<Event> selectionChangeEvent = const EventStreamProvider<Event>('selectionchange');
@@ -6634,6 +6638,10 @@
   @DocsEditable
   Stream<Event> get onSearch => Element.searchEvent.forTarget(this);
 
+  @DomName('Document.onsecuritypolicyviolation')
+  @DocsEditable
+  Stream<SecurityPolicyViolationEvent> get onSecurityPolicyViolation => securityPolicyViolationEvent.forTarget(this);
+
   @DomName('Document.onselect')
   @DocsEditable
   Stream<Event> get onSelect => Element.selectEvent.forTarget(this);
@@ -7590,11 +7598,11 @@
    * * [insertAdjacentText]
    * * [insertAdjacentElement]
    */
-  void insertAdjacentHtml(String where, String text) {
+  void insertAdjacentHtml(String where, String html) {
     if (JS('bool', '!!#.insertAdjacentHtml', this)) {
-      _insertAdjacentHtml(where, text);
+      _insertAdjacentHtml(where, html);
     } else {
-      _insertAdjacentNode(where, new DocumentFragment.html(text));
+      _insertAdjacentNode(where, new DocumentFragment.html(html));
     }
   }
 
@@ -7660,7 +7668,7 @@
     throw new UnsupportedError("Not supported on this platform");
   }
 
-  @Creates('Null')
+  @Creates('Null') // Set from Dart code; does not instantiate a native type.
   Map<String, StreamSubscription> _attributeBindings;
 
   // TODO(jmesserly): I'm concerned about adding these to every element.
@@ -10039,7 +10047,19 @@
 
   @DomName('FontLoader.loadEvent')
   @DocsEditable
-  static const EventStreamProvider<Event> loadEvent = const EventStreamProvider<Event>('load');
+  static const EventStreamProvider<CssFontFaceLoadEvent> loadEvent = const EventStreamProvider<CssFontFaceLoadEvent>('load');
+
+  @DomName('FontLoader.loadingEvent')
+  @DocsEditable
+  static const EventStreamProvider<CssFontFaceLoadEvent> loadingEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loading');
+
+  @DomName('FontLoader.loadingdoneEvent')
+  @DocsEditable
+  static const EventStreamProvider<CssFontFaceLoadEvent> loadingDoneEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loadingdone');
+
+  @DomName('FontLoader.loadstartEvent')
+  @DocsEditable
+  static const EventStreamProvider<CssFontFaceLoadEvent> loadStartEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loadstart');
 
   @DomName('FontLoader.loading')
   @DocsEditable
@@ -10085,7 +10105,19 @@
 
   @DomName('FontLoader.onload')
   @DocsEditable
-  Stream<Event> get onLoad => loadEvent.forTarget(this);
+  Stream<CssFontFaceLoadEvent> get onLoad => loadEvent.forTarget(this);
+
+  @DomName('FontLoader.onloading')
+  @DocsEditable
+  Stream<CssFontFaceLoadEvent> get onLoading => loadingEvent.forTarget(this);
+
+  @DomName('FontLoader.onloadingdone')
+  @DocsEditable
+  Stream<CssFontFaceLoadEvent> get onLoadingDone => loadingDoneEvent.forTarget(this);
+
+  @DomName('FontLoader.onloadstart')
+  @DocsEditable
+  Stream<CssFontFaceLoadEvent> get onLoadStart => loadStartEvent.forTarget(this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -10127,6 +10159,14 @@
 @DomName('HTMLFormElement')
 class FormElement extends Element native "HTMLFormElement" {
 
+  @DomName('HTMLFormElement.autocompleteEvent')
+  @DocsEditable
+  static const EventStreamProvider<Event> autocompleteEvent = const EventStreamProvider<Event>('autocomplete');
+
+  @DomName('HTMLFormElement.autocompleteerrorEvent')
+  @DocsEditable
+  static const EventStreamProvider<AutocompleteErrorEvent> autocompleteErrorEvent = const EventStreamProvider<AutocompleteErrorEvent>('autocompleteerror');
+
   @DomName('HTMLFormElement.HTMLFormElement')
   @DocsEditable
   factory FormElement() => document.$dom_createElement("form");
@@ -10186,6 +10226,14 @@
   @DomName('HTMLFormElement.submit')
   @DocsEditable
   void submit() native;
+
+  @DomName('HTMLFormElement.onautocomplete')
+  @DocsEditable
+  Stream<Event> get onAutocomplete => autocompleteEvent.forTarget(this);
+
+  @DomName('HTMLFormElement.onautocompleteerror')
+  @DocsEditable
+  Stream<AutocompleteErrorEvent> get onAutocompleteError => autocompleteErrorEvent.forTarget(this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -11372,39 +11420,6 @@
 
 
 @DocsEditable
-@DomName('XMLHttpRequestException')
-class HttpRequestException native "XMLHttpRequestException" {
-
-  @DomName('XMLHttpRequestException.ABORT_ERR')
-  @DocsEditable
-  static const int ABORT_ERR = 102;
-
-  @DomName('XMLHttpRequestException.NETWORK_ERR')
-  @DocsEditable
-  static const int NETWORK_ERR = 101;
-
-  @DomName('XMLHttpRequestException.code')
-  @DocsEditable
-  final int code;
-
-  @DomName('XMLHttpRequestException.message')
-  @DocsEditable
-  final String message;
-
-  @DomName('XMLHttpRequestException.name')
-  @DocsEditable
-  final String name;
-
-  @DomName('XMLHttpRequestException.toString')
-  @DocsEditable
-  String toString() native;
-}
-// 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.
-
-
-@DocsEditable
 @DomName('XMLHttpRequestProgressEvent')
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -14253,6 +14268,15 @@
 
 
 @DocsEditable
+@DomName('MIDIInput')
+class MidiInput extends MidiPort implements EventTarget native "MIDIInput" {
+}
+// 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.
+
+
+@DocsEditable
 @DomName('MIDIMessageEvent')
 class MidiMessageEvent extends Event native "MIDIMessageEvent" {
 
@@ -14273,6 +14297,10 @@
 @DomName('MIDIPort')
 class MidiPort extends EventTarget native "MIDIPort" {
 
+  @DomName('MIDIPort.disconnectEvent')
+  @DocsEditable
+  static const EventStreamProvider<MidiConnectionEvent> disconnectEvent = const EventStreamProvider<MidiConnectionEvent>('disconnect');
+
   @DomName('MIDIPort.id')
   @DocsEditable
   final String id;
@@ -14306,6 +14334,10 @@
   @DomName('MIDIPort.removeEventListener')
   @DocsEditable
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
+
+  @DomName('MIDIPort.ondisconnect')
+  @DocsEditable
+  Stream<MidiConnectionEvent> get onDisconnect => disconnectEvent.forTarget(this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -14568,13 +14600,12 @@
       return new Point(x, y);
     } else {
       // Firefox does not support offsetX.
-      var target = this.target;
-      if (!(target is Element)) {
+      if (!(this.target is Element)) {
         throw new UnsupportedError(
             'offsetX is only supported on elements');
       }
-      return (this.client -
-          this.target.getBoundingClientRect().topLeft).toInt();
+      Element target = this.target;
+      return (this.client - target.getBoundingClientRect().topLeft).toInt();
     }
   }
 
@@ -15127,11 +15158,12 @@
 
   void addAll(Iterable<Node> iterable) {
     if (iterable is _ChildNodeListLazy) {
-      if (!identical(iterable._this, _this)) {
+      _ChildNodeListLazy otherList = iterable;
+      if (!identical(otherList._this, _this)) {
         // Optimized route for copying between nodes.
-        for (var i = 0, len = iterable.length; i < len; ++i) {
+        for (var i = 0, len = otherList.length; i < len; ++i) {
           // Should use $dom_firstChild, Bug 8886.
-          _this.append(iterable[0]);
+          _this.append(otherList[0]);
         }
       }
       return;
@@ -16287,6 +16319,13 @@
 @SupportedBrowser(SupportedBrowser.IE)
 class Performance extends EventTarget native "Performance" {
 
+  @DomName('Performance.webkitresourcetimingbufferfullEvent')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  static const EventStreamProvider<Event> resourceTimingBufferFullEvent = const EventStreamProvider<Event>('webkitresourcetimingbufferfull');
+
   /// Checks if this type is supported on the current platform.
   static bool get supported => JS('bool', '!!(window.performance)');
 
@@ -16349,6 +16388,10 @@
   @SupportedBrowser(SupportedBrowser.SAFARI)
   @Experimental
   void setResourceTimingBufferSize(int maxSize) native;
+
+  @DomName('Performance.onwebkitresourcetimingbufferfull')
+  @DocsEditable
+  Stream<Event> get onResourceTimingBufferFull => resourceTimingBufferFullEvent.forTarget(this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -17063,39 +17106,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.
 
-
-@DocsEditable
-@DomName('RangeException')
-class RangeException native "RangeException" {
-
-  @DomName('RangeException.BAD_BOUNDARYPOINTS_ERR')
-  @DocsEditable
-  static const int BAD_BOUNDARYPOINTS_ERR = 1;
-
-  @DomName('RangeException.INVALID_NODE_TYPE_ERR')
-  @DocsEditable
-  static const int INVALID_NODE_TYPE_ERR = 2;
-
-  @DomName('RangeException.code')
-  @DocsEditable
-  final int code;
-
-  @DomName('RangeException.message')
-  @DocsEditable
-  final String message;
-
-  @DomName('RangeException.name')
-  @DocsEditable
-  final String name;
-
-  @DomName('RangeException.toString')
-  @DocsEditable
-  String toString() native;
-}
-// 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.
 
 
@@ -18881,14 +18891,34 @@
 @DomName('SpeechSynthesisUtterance')
 class SpeechSynthesisUtterance extends EventTarget native "SpeechSynthesisUtterance" {
 
+  @DomName('SpeechSynthesisUtterance.boundaryEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> boundaryEvent = const EventStreamProvider<SpeechSynthesisEvent>('boundary');
+
+  @DomName('SpeechSynthesisUtterance.endEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> endEvent = const EventStreamProvider<SpeechSynthesisEvent>('end');
+
   @DomName('SpeechSynthesisUtterance.errorEvent')
   @DocsEditable
   static const EventStreamProvider<Event> errorEvent = const EventStreamProvider<Event>('error');
 
+  @DomName('SpeechSynthesisUtterance.markEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> markEvent = const EventStreamProvider<SpeechSynthesisEvent>('mark');
+
   @DomName('SpeechSynthesisUtterance.pauseEvent')
   @DocsEditable
   static const EventStreamProvider<Event> pauseEvent = const EventStreamProvider<Event>('pause');
 
+  @DomName('SpeechSynthesisUtterance.resumeEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> resumeEvent = const EventStreamProvider<SpeechSynthesisEvent>('resume');
+
+  @DomName('SpeechSynthesisUtterance.startEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> startEvent = const EventStreamProvider<SpeechSynthesisEvent>('start');
+
   @DomName('SpeechSynthesisUtterance.SpeechSynthesisUtterance')
   @DocsEditable
   factory SpeechSynthesisUtterance([String text]) {
@@ -18924,13 +18954,33 @@
   @DocsEditable
   num volume;
 
+  @DomName('SpeechSynthesisUtterance.onboundary')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onBoundary => boundaryEvent.forTarget(this);
+
+  @DomName('SpeechSynthesisUtterance.onend')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onEnd => endEvent.forTarget(this);
+
   @DomName('SpeechSynthesisUtterance.onerror')
   @DocsEditable
   Stream<Event> get onError => errorEvent.forTarget(this);
 
+  @DomName('SpeechSynthesisUtterance.onmark')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onMark => markEvent.forTarget(this);
+
   @DomName('SpeechSynthesisUtterance.onpause')
   @DocsEditable
   Stream<Event> get onPause => pauseEvent.forTarget(this);
+
+  @DomName('SpeechSynthesisUtterance.onresume')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onResume => resumeEvent.forTarget(this);
+
+  @DomName('SpeechSynthesisUtterance.onstart')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onStart => startEvent.forTarget(this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -20822,9 +20872,9 @@
          '(self.URL || self.webkitURL).createObjectURL(#)',
          blob_OR_source_OR_stream);
 
-  static void revokeObjectUrl(String objectUrl) =>
+  static void revokeObjectUrl(String url) =>
       JS('void',
-         '(self.URL || self.webkitURL).revokeObjectURL(#)', objectUrl);
+         '(self.URL || self.webkitURL).revokeObjectURL(#)', url);
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -21535,7 +21585,7 @@
     return _requestAnimationFrame(callback);
   }
 
-  void cancelAnimationFrame(id) {
+  void cancelAnimationFrame(int id) {
     _ensureRequestAnimationFrame();
     _cancelAnimationFrame(id);
   }
@@ -21588,7 +21638,7 @@
          this, this, this);
 
   @DomName('Window.console')
-  Console get console => Console.safeConsole;
+  Console get console => Console._safeConsole;
 
   /// Checks if _setImmediate is supported.
   static bool get _supportsSetImmediate =>
@@ -24450,16 +24500,16 @@
     }
   }
 
-  bool get _paused => _pauseCount > 0;
+  bool get isPaused => _pauseCount > 0;
 
   void resume() {
-    if (_canceled || !_paused) return;
+    if (_canceled || !isPaused) return;
     --_pauseCount;
     _tryResume();
   }
 
   void _tryResume() {
-    if (_onData != null && !_paused) {
+    if (_onData != null && !isPaused) {
       _target.$dom_addEventListener(_eventType, _onData, _useCapture);
     }
   }
@@ -24583,7 +24633,7 @@
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
-  void remove(Object object) {
+  bool remove(Object object) {
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
@@ -24595,7 +24645,7 @@
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
-  void setRange(int start, int end, Iterable<E> iterable, [int skipCount]) {
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     throw new UnsupportedError("Cannot setRange on immutable List.");
   }
 
@@ -26667,7 +26717,7 @@
   }
 
   // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(Document doc) {
+  static Document _getTemplateContentsOwner(HtmlDocument doc) {
     if (doc.window == null) {
       return doc;
     }
@@ -26745,7 +26795,7 @@
     // template.
     // TODO(jmesserly): node is DocumentFragment or Element
     var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-    if (node is Element && node.isTemplate) bootstrap(node);
+    if (node is Element && (node as Element).isTemplate) bootstrap(node);
 
     descendents.forEach(bootstrap);
   }
@@ -26899,7 +26949,7 @@
 
   static void _removeChild(Node parent, Node child) {
     child._templateInstance = null;
-    if (child is Element && child.isTemplate) {
+    if (child is Element && (child as Element).isTemplate) {
       // Make sure we stop observing when we remove an element.
       var templateIterator = child._templateIterator;
       if (templateIterator != null) {
@@ -27734,7 +27784,7 @@
 
   void add(E element) { _list.add(element); }
 
-  void remove(Object element) { _list.remove(element); }
+  bool remove(Object element) => _list.remove(element);
 
   void clear() { _list.clear(); }
 
@@ -27869,8 +27919,14 @@
   // Assume it's a Window if it contains the setInterval property.  It may be
   // from a different frame - without a patched prototype - so we cannot
   // rely on Dart type checking.
-  if (JS('bool', r'"setInterval" in #', e))
-    return _DOMWindowCrossFrame._createSafe(e);
+  if (JS('bool', r'"setInterval" in #', e)) {
+    var window = _DOMWindowCrossFrame._createSafe(e);
+    // If it's a native window.
+    if (window is EventTarget) {
+      return window;
+    }
+    return null;
+  }
   else
     return e;
 }
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 6c139d5..0a9d8af 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -1435,7 +1435,7 @@
   @DocsEditable
   CanvasGradient createRadialGradient(num x0, num y0, num r0, num x1, num y1, num r1) native "CanvasRenderingContext2D_createRadialGradient_Callback";
 
-  void $dom_drawImage(canvas_OR_image_OR_video, num sx_OR_x, num sy_OR_y, [num sw_OR_width, num height_OR_sh, num dx, num dy, num dw, num dh]) {
+  void _drawImage(canvas_OR_image_OR_video, num sx_OR_x, num sy_OR_y, [num sw_OR_width, num height_OR_sh, num dx, num dy, num dw, num dh]) {
     if ((canvas_OR_image_OR_video is ImageElement || canvas_OR_image_OR_video == null) && (sx_OR_x is num || sx_OR_x == null) && (sy_OR_y is num || sy_OR_y == null) && !?sw_OR_width && !?height_OR_sh && !?dx && !?dy && !?dw && !?dh) {
       _drawImage_1(canvas_OR_image_OR_video, sx_OR_x, sy_OR_y);
       return;
@@ -1758,13 +1758,13 @@
   void drawImageToRect(CanvasImageSource source, Rect destRect,
       {Rect sourceRect}) {
     if (sourceRect == null) {
-      $dom_drawImage(source,
+      _drawImage(source,
           destRect.left,
           destRect.top,
           destRect.width,
           destRect.height);
     } else {
-      $dom_drawImage(source,
+      _drawImage(source,
           sourceRect.left,
           sourceRect.top,
           sourceRect.width,
@@ -1807,7 +1807,7 @@
    */
   @DomName('CanvasRenderingContext2D.drawImage')
   void drawImage(CanvasImageSource source, num destX, num destY) {
-    $dom_drawImage(source, destX, destY);
+    _drawImage(source, destX, destY);
   }
 
   /**
@@ -1839,7 +1839,7 @@
   @DomName('CanvasRenderingContext2D.drawImage')
   void drawImageScaled(CanvasImageSource source,
       num destX, num destY, num destWidth, num destHeight) {
-    $dom_drawImage(source, destX, destY, destWidth, destHeight);
+    _drawImage(source, destX, destY, destWidth, destHeight);
   }
 
   /**
@@ -1875,7 +1875,7 @@
   void drawImageScaledFromSource(CanvasImageSource source,
       num sourceX, num sourceY, num sourceWidth, num sourceHeight,
       num destX, num destY, num destWidth, num destHeight) {
-    $dom_drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight,
+    _drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight,
         destX, destY, destWidth, destHeight);
   }
 
@@ -6572,6 +6572,10 @@
   @DocsEditable
   static const EventStreamProvider<Event> readyStateChangeEvent = const EventStreamProvider<Event>('readystatechange');
 
+  @DomName('Document.securitypolicyviolationEvent')
+  @DocsEditable
+  static const EventStreamProvider<SecurityPolicyViolationEvent> securityPolicyViolationEvent = const EventStreamProvider<SecurityPolicyViolationEvent>('securitypolicyviolation');
+
   @DomName('Document.selectionchangeEvent')
   @DocsEditable
   static const EventStreamProvider<Event> selectionChangeEvent = const EventStreamProvider<Event>('selectionchange');
@@ -7062,6 +7066,10 @@
   @DocsEditable
   Stream<Event> get onSearch => Element.searchEvent.forTarget(this);
 
+  @DomName('Document.onsecuritypolicyviolation')
+  @DocsEditable
+  Stream<SecurityPolicyViolationEvent> get onSecurityPolicyViolation => securityPolicyViolationEvent.forTarget(this);
+
   @DomName('Document.onselect')
   @DocsEditable
   Stream<Event> get onSelect => Element.selectEvent.forTarget(this);
@@ -7975,7 +7983,6 @@
   }
 
 
-  @Creates('Null')
   Map<String, StreamSubscription> _attributeBindings;
 
   // TODO(jmesserly): I'm concerned about adding these to every element.
@@ -10425,7 +10432,19 @@
 
   @DomName('FontLoader.loadEvent')
   @DocsEditable
-  static const EventStreamProvider<Event> loadEvent = const EventStreamProvider<Event>('load');
+  static const EventStreamProvider<CssFontFaceLoadEvent> loadEvent = const EventStreamProvider<CssFontFaceLoadEvent>('load');
+
+  @DomName('FontLoader.loadingEvent')
+  @DocsEditable
+  static const EventStreamProvider<CssFontFaceLoadEvent> loadingEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loading');
+
+  @DomName('FontLoader.loadingdoneEvent')
+  @DocsEditable
+  static const EventStreamProvider<CssFontFaceLoadEvent> loadingDoneEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loadingdone');
+
+  @DomName('FontLoader.loadstartEvent')
+  @DocsEditable
+  static const EventStreamProvider<CssFontFaceLoadEvent> loadStartEvent = const EventStreamProvider<CssFontFaceLoadEvent>('loadstart');
 
   @DomName('FontLoader.loading')
   @DocsEditable
@@ -10461,7 +10480,19 @@
 
   @DomName('FontLoader.onload')
   @DocsEditable
-  Stream<Event> get onLoad => loadEvent.forTarget(this);
+  Stream<CssFontFaceLoadEvent> get onLoad => loadEvent.forTarget(this);
+
+  @DomName('FontLoader.onloading')
+  @DocsEditable
+  Stream<CssFontFaceLoadEvent> get onLoading => loadingEvent.forTarget(this);
+
+  @DomName('FontLoader.onloadingdone')
+  @DocsEditable
+  Stream<CssFontFaceLoadEvent> get onLoadingDone => loadingDoneEvent.forTarget(this);
+
+  @DomName('FontLoader.onloadstart')
+  @DocsEditable
+  Stream<CssFontFaceLoadEvent> get onLoadStart => loadStartEvent.forTarget(this);
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -10504,6 +10535,14 @@
 class FormElement extends _Element_Merged {
   FormElement.internal() : super.internal();
 
+  @DomName('HTMLFormElement.autocompleteEvent')
+  @DocsEditable
+  static const EventStreamProvider<Event> autocompleteEvent = const EventStreamProvider<Event>('autocomplete');
+
+  @DomName('HTMLFormElement.autocompleteerrorEvent')
+  @DocsEditable
+  static const EventStreamProvider<AutocompleteErrorEvent> autocompleteErrorEvent = const EventStreamProvider<AutocompleteErrorEvent>('autocompleteerror');
+
   @DomName('HTMLFormElement.HTMLFormElement')
   @DocsEditable
   factory FormElement() => document.$dom_createElement("form");
@@ -10600,6 +10639,14 @@
   @DocsEditable
   void submit() native "HTMLFormElement_submit_Callback";
 
+  @DomName('HTMLFormElement.onautocomplete')
+  @DocsEditable
+  Stream<Event> get onAutocomplete => autocompleteEvent.forTarget(this);
+
+  @DomName('HTMLFormElement.onautocompleteerror')
+  @DocsEditable
+  Stream<AutocompleteErrorEvent> get onAutocompleteError => autocompleteErrorEvent.forTarget(this);
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -11815,43 +11862,6 @@
 
 
 @DocsEditable
-@DomName('XMLHttpRequestException')
-class HttpRequestException extends NativeFieldWrapperClass1 {
-  HttpRequestException.internal();
-
-  @DomName('XMLHttpRequestException.ABORT_ERR')
-  @DocsEditable
-  static const int ABORT_ERR = 102;
-
-  @DomName('XMLHttpRequestException.NETWORK_ERR')
-  @DocsEditable
-  static const int NETWORK_ERR = 101;
-
-  @DomName('XMLHttpRequestException.code')
-  @DocsEditable
-  int get code native "XMLHttpRequestException_code_Getter";
-
-  @DomName('XMLHttpRequestException.message')
-  @DocsEditable
-  String get message native "XMLHttpRequestException_message_Getter";
-
-  @DomName('XMLHttpRequestException.name')
-  @DocsEditable
-  String get name native "XMLHttpRequestException_name_Getter";
-
-  @DomName('XMLHttpRequestException.toString')
-  @DocsEditable
-  String toString() native "XMLHttpRequestException_toString_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('XMLHttpRequestProgressEvent')
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -15267,6 +15277,19 @@
 
 
 @DocsEditable
+@DomName('MIDIInput')
+class MidiInput extends MidiPort implements EventTarget {
+  MidiInput.internal() : super.internal();
+
+}
+// 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('MIDIMessageEvent')
 class MidiMessageEvent extends Event {
   MidiMessageEvent.internal() : super.internal();
@@ -15292,6 +15315,10 @@
 class MidiPort extends EventTarget {
   MidiPort.internal() : super.internal();
 
+  @DomName('MIDIPort.disconnectEvent')
+  @DocsEditable
+  static const EventStreamProvider<MidiConnectionEvent> disconnectEvent = const EventStreamProvider<MidiConnectionEvent>('disconnect');
+
   @DomName('MIDIPort.id')
   @DocsEditable
   String get id native "MIDIPort_id_Getter";
@@ -15324,6 +15351,10 @@
   @DocsEditable
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "MIDIPort_removeEventListener_Callback";
 
+  @DomName('MIDIPort.ondisconnect')
+  @DocsEditable
+  Stream<MidiConnectionEvent> get onDisconnect => disconnectEvent.forTarget(this);
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -16123,11 +16154,12 @@
 
   void addAll(Iterable<Node> iterable) {
     if (iterable is _ChildNodeListLazy) {
-      if (!identical(iterable._this, _this)) {
+      _ChildNodeListLazy otherList = iterable;
+      if (!identical(otherList._this, _this)) {
         // Optimized route for copying between nodes.
-        for (var i = 0, len = iterable.length; i < len; ++i) {
+        for (var i = 0, len = otherList.length; i < len; ++i) {
           // Should use $dom_firstChild, Bug 8886.
-          _this.append(iterable[0]);
+          _this.append(otherList[0]);
         }
       }
       return;
@@ -17409,6 +17441,13 @@
 class Performance extends EventTarget {
   Performance.internal() : super.internal();
 
+  @DomName('Performance.webkitresourcetimingbufferfullEvent')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  static const EventStreamProvider<Event> resourceTimingBufferFullEvent = const EventStreamProvider<Event>('webkitresourcetimingbufferfull');
+
   /// Checks if this type is supported on the current platform.
   static bool get supported => true;
 
@@ -17470,6 +17509,10 @@
   @Experimental
   void setResourceTimingBufferSize(int maxSize) native "Performance_webkitSetResourceTimingBufferSize_Callback";
 
+  @DomName('Performance.onwebkitresourcetimingbufferfull')
+  @DocsEditable
+  Stream<Event> get onResourceTimingBufferFull => resourceTimingBufferFullEvent.forTarget(this);
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -18260,43 +18303,6 @@
 // WARNING: Do not edit - generated code.
 
 
-@DocsEditable
-@DomName('RangeException')
-class RangeException extends NativeFieldWrapperClass1 {
-  RangeException.internal();
-
-  @DomName('RangeException.BAD_BOUNDARYPOINTS_ERR')
-  @DocsEditable
-  static const int BAD_BOUNDARYPOINTS_ERR = 1;
-
-  @DomName('RangeException.INVALID_NODE_TYPE_ERR')
-  @DocsEditable
-  static const int INVALID_NODE_TYPE_ERR = 2;
-
-  @DomName('RangeException.code')
-  @DocsEditable
-  int get code native "RangeException_code_Getter";
-
-  @DomName('RangeException.message')
-  @DocsEditable
-  String get message native "RangeException_message_Getter";
-
-  @DomName('RangeException.name')
-  @DocsEditable
-  String get name native "RangeException_name_Getter";
-
-  @DomName('RangeException.toString')
-  @DocsEditable
-  String toString() native "RangeException_toString_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.
-
-
 typedef void RequestAnimationFrameCallback(num highResTime);
 // 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
@@ -20286,14 +20292,34 @@
 class SpeechSynthesisUtterance extends EventTarget {
   SpeechSynthesisUtterance.internal() : super.internal();
 
+  @DomName('SpeechSynthesisUtterance.boundaryEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> boundaryEvent = const EventStreamProvider<SpeechSynthesisEvent>('boundary');
+
+  @DomName('SpeechSynthesisUtterance.endEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> endEvent = const EventStreamProvider<SpeechSynthesisEvent>('end');
+
   @DomName('SpeechSynthesisUtterance.errorEvent')
   @DocsEditable
   static const EventStreamProvider<Event> errorEvent = const EventStreamProvider<Event>('error');
 
+  @DomName('SpeechSynthesisUtterance.markEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> markEvent = const EventStreamProvider<SpeechSynthesisEvent>('mark');
+
   @DomName('SpeechSynthesisUtterance.pauseEvent')
   @DocsEditable
   static const EventStreamProvider<Event> pauseEvent = const EventStreamProvider<Event>('pause');
 
+  @DomName('SpeechSynthesisUtterance.resumeEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> resumeEvent = const EventStreamProvider<SpeechSynthesisEvent>('resume');
+
+  @DomName('SpeechSynthesisUtterance.startEvent')
+  @DocsEditable
+  static const EventStreamProvider<SpeechSynthesisEvent> startEvent = const EventStreamProvider<SpeechSynthesisEvent>('start');
+
   @DomName('SpeechSynthesisUtterance.SpeechSynthesisUtterance')
   @DocsEditable
   factory SpeechSynthesisUtterance([String text]) {
@@ -20351,14 +20377,34 @@
   @DocsEditable
   void set volume(num value) native "SpeechSynthesisUtterance_volume_Setter";
 
+  @DomName('SpeechSynthesisUtterance.onboundary')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onBoundary => boundaryEvent.forTarget(this);
+
+  @DomName('SpeechSynthesisUtterance.onend')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onEnd => endEvent.forTarget(this);
+
   @DomName('SpeechSynthesisUtterance.onerror')
   @DocsEditable
   Stream<Event> get onError => errorEvent.forTarget(this);
 
+  @DomName('SpeechSynthesisUtterance.onmark')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onMark => markEvent.forTarget(this);
+
   @DomName('SpeechSynthesisUtterance.onpause')
   @DocsEditable
   Stream<Event> get onPause => pauseEvent.forTarget(this);
 
+  @DomName('SpeechSynthesisUtterance.onresume')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onResume => resumeEvent.forTarget(this);
+
+  @DomName('SpeechSynthesisUtterance.onstart')
+  @DocsEditable
+  Stream<SpeechSynthesisEvent> get onStart => startEvent.forTarget(this);
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -22936,11 +22982,11 @@
 
   @DomName('WheelEvent.wheelDeltaX')
   @DocsEditable
-  int get $dom_wheelDeltaX native "WheelEvent_wheelDeltaX_Getter";
+  int get _wheelDeltaX native "WheelEvent_wheelDeltaX_Getter";
 
   @DomName('WheelEvent.wheelDeltaY')
   @DocsEditable
-  int get $dom_wheelDeltaY native "WheelEvent_wheelDeltaY_Getter";
+  int get _wheelDeltaY native "WheelEvent_wheelDeltaY_Getter";
 
   @DomName('WheelEvent.initWebKitWheelEvent')
   @DocsEditable
@@ -22956,7 +23002,7 @@
    * * [WheelEvent.deltaX](http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-WheelEvent-deltaX) from the W3C.
    */
   @DomName('WheelEvent.deltaX')
-  num get deltaX => -$dom_wheelDeltaX;
+  num get deltaX => -_wheelDeltaX;
 
   /**
    * The amount that is expected to scroll vertically, in units determined by
@@ -22967,7 +23013,7 @@
    * * [WheelEvent.deltaY](http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-WheelEvent-deltaY) from the W3C.
    */
   @DomName('WheelEvent.deltaY')
-  num get deltaY => -$dom_wheelDeltaY;
+  num get deltaY => -_wheelDeltaY;
 }
 // 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
@@ -26243,16 +26289,16 @@
     }
   }
 
-  bool get _paused => _pauseCount > 0;
+  bool get isPaused => _pauseCount > 0;
 
   void resume() {
-    if (_canceled || !_paused) return;
+    if (_canceled || !isPaused) return;
     --_pauseCount;
     _tryResume();
   }
 
   void _tryResume() {
-    if (_onData != null && !_paused) {
+    if (_onData != null && !isPaused) {
       _target.$dom_addEventListener(_eventType, _onData, _useCapture);
     }
   }
@@ -26376,7 +26422,7 @@
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
-  void remove(Object object) {
+  bool remove(Object object) {
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
@@ -26388,7 +26434,7 @@
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
-  void setRange(int start, int end, Iterable<E> iterable, [int skipCount]) {
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     throw new UnsupportedError("Cannot setRange on immutable List.");
   }
 
@@ -28460,7 +28506,7 @@
   }
 
   // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(Document doc) {
+  static Document _getTemplateContentsOwner(HtmlDocument doc) {
     if (doc.window == null) {
       return doc;
     }
@@ -28538,7 +28584,7 @@
     // template.
     // TODO(jmesserly): node is DocumentFragment or Element
     var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-    if (node is Element && node.isTemplate) bootstrap(node);
+    if (node is Element && (node as Element).isTemplate) bootstrap(node);
 
     descendents.forEach(bootstrap);
   }
@@ -28692,7 +28738,7 @@
 
   static void _removeChild(Node parent, Node child) {
     child._templateInstance = null;
-    if (child is Element && child.isTemplate) {
+    if (child is Element && (child as Element).isTemplate) {
       // Make sure we stop observing when we remove an element.
       var templateIterator = child._templateIterator;
       if (templateIterator != null) {
@@ -28945,7 +28991,7 @@
 
   void add(E element) { _list.add(element); }
 
-  void remove(Object element) { _list.remove(element); }
+  bool remove(Object element) => _list.remove(element);
 
   void clear() { _list.clear(); }
 
@@ -29141,6 +29187,8 @@
 
   /** True if the altGraphKey is pressed during this event. */
   bool get altGraphKey => _parent.altGraphKey;
+  /** Accessor to the clipboardData available for this event. */
+  DataTransfer get clipboardData => _parent.clipboardData;
   /** True if the ctrl key is pressed during this event. */
   bool get ctrlKey => _parent.ctrlKey;
   int get detail => _parent.detail;
diff --git a/sdk/lib/io/base64.dart b/sdk/lib/io/base64.dart
deleted file mode 100644
index 1469c8d..0000000
--- a/sdk/lib/io/base64.dart
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.io;
-
-class _Base64 {
-  static const List<String> _encodingTable = const [
-      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
-      'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
-      'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
-      't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
-      '8', '9', '+', '/'];
-
-  /**
-   * Base64 transfer encoding for MIME (RFC 2045)
-   */
-  static String _encode(List<int> data) {
-    List<String> characters = new List<String>();
-    int i;
-    for (i = 0; i + 3 <= data.length; i += 3) {
-      int value = 0;
-      value |= data[i + 2];
-      value |= data[i + 1] << 8;
-      value |= data[i] << 16;
-      for (int j = 0; j < 4; j++) {
-        int index = (value >> ((3 - j) * 6)) & ((1 << 6) - 1);
-        characters.add(_encodingTable[index]);
-      }
-    }
-    // Remainders.
-    if (i + 2 == data.length) {
-      int value = 0;
-      value |= data[i + 1] << 8;
-      value |= data[i] << 16;
-      for (int j = 0; j < 3; j++) {
-        int index = (value >> ((3 - j) * 6)) & ((1 << 6) - 1);
-        characters.add(_encodingTable[index]);
-      }
-      characters.add("=");
-    } else if (i + 1 == data.length) {
-      int value = 0;
-      value |= data[i] << 16;
-      for (int j = 0; j < 2; j++) {
-        int index = (value >> ((3 - j) * 6)) & ((1 << 6) - 1);
-        characters.add(_encodingTable[index]);
-      }
-      characters.add("=");
-      characters.add("=");
-    }
-    StringBuffer output = new StringBuffer();
-    for (i = 0; i < characters.length; i++) {
-      if (i > 0 && i % 76 == 0) {
-        output.write("\r\n");
-      }
-      output.write(characters[i]);
-    }
-    return output.toString();
-  }
-
-
-  /**
-   * Base64 transfer decoding for MIME (RFC 2045).
-   */
-  static List<int> _decode(String data) {
-    List<int> result = new List<int>();
-    int padCount = 0;
-    int charCount = 0;
-    int value = 0;
-    for (int i = 0; i < data.length; i++) {
-      int char = data.codeUnitAt(i);
-      if (65 <= char && char <= 90) {  // "A" - "Z".
-        value = (value << 6) | char - 65;
-        charCount++;
-      } else if (97 <= char && char <= 122) { // "a" - "z".
-        value = (value << 6) | char - 97 + 26;
-        charCount++;
-      } else if (48 <= char && char <= 57) {  // "0" - "9".
-        value = (value << 6) | char - 48 + 52;
-        charCount++;
-      } else if (char == 43) {  // "+".
-        value = (value << 6) | 62;
-        charCount++;
-      } else if (char == 47) {  // "/".
-        value = (value << 6) | 63;
-        charCount++;
-      } else if (char == 61) {  // "=".
-        value = (value << 6);
-        charCount++;
-        padCount++;
-      }
-      if (charCount == 4) {
-        result.add((value & 0xFF0000) >> 16);
-        if (padCount < 2) {
-          result.add((value & 0xFF00) >> 8);
-        }
-        if (padCount == 0) {
-          result.add(value & 0xFF);
-        }
-        charCount = 0;
-        value = 0;
-      }
-    }
-    return result;
-  }
-}
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 20110af..eb3dcd7 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -180,14 +180,19 @@
   String fullPathSync();
 
   /**
-   * Create a new independent [Stream](../dart_async/Stream.html) for the
-   * contents of this file.
+   * Create a new independent [Stream] for the contents of this file.
+   *
+   * If [start] is present, the file will be read from byte-offset [start].
+   * Otherwise from the beginning (index 0).
+   *
+   * If [end] is present, only up to byte-index [end] will be read. Otherwise,
+   * until end of file.
    *
    * In order to make sure that system resources are freed, the stream
    * must be read to completion or the subscription on the stream must
    * be cancelled.
    */
-  Stream<List<int>> openRead();
+  Stream<List<int>> openRead([int start, int end]);
 
   /**
    * Creates a new independent [IOSink] for the file. The
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 15fbded..fb6b272 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -16,6 +16,7 @@
   String _path;
   RandomAccessFile _openedFile;
   int _position;
+  int _end;
 
   // Has the stream been paused or unsubscribed?
   bool _paused = false;
@@ -27,7 +28,7 @@
   // Block read but not yet send because stream is paused.
   List<int> _currentBlock;
 
-  _FileStream(String this._path) : _position = 0 {
+  _FileStream(String this._path, this._position, this._end) {
     _setupController();
   }
 
@@ -71,7 +72,19 @@
     // Don't start a new read if one is already in progress.
     if (_readInProgress) return;
     _readInProgress = true;
-    _openedFile.read(_BLOCK_SIZE)
+    int readBytes = _BLOCK_SIZE;
+    if (_end != null) {
+      readBytes = min(readBytes, _end - _position);
+      if (readBytes < 0) {
+        if (!_unsubscribed) {
+          _controller.addError(new RangeError("Bad end position: $_end"));
+          _closeFile().then((_) { _controller.close(); });
+          _unsubscribed = true;
+        }
+        return;
+      }
+    }
+    _openedFile.read(readBytes)
       .then((block) {
         _readInProgress = false;
         if (block.length == 0) {
@@ -99,6 +112,13 @@
   }
 
   void _start() {
+    if (_position == null) {
+      _position = 0;
+    } else if (_position < 0) {
+      _controller.addError(new RangeError("Bad start position: $_position"));
+      _controller.close();
+      return;
+    }
     Future<RandomAccessFile> openFuture;
     if (_path != null) {
       openFuture = new File(_path).open(mode: FileMode.READ);
@@ -108,8 +128,11 @@
     openFuture
       .then((RandomAccessFile opened) {
         _openedFile = opened;
-        _readBlock();
+        if (_position > 0) {
+          return opened.setPosition(_position);
+        }
       })
+      .then((_) => _readBlock())
       .catchError((e) {
         _controller.addError(e);
         _controller.close();
@@ -315,14 +338,10 @@
 
   Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) {
     _ensureFileService();
-    Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
     if (mode != FileMode.READ &&
         mode != FileMode.WRITE &&
         mode != FileMode.APPEND) {
-      Timer.run(() {
-        completer.completeError(new ArgumentError());
-      });
-      return completer.future;
+      return new Future.error(new ArgumentError());
     }
     List request = new List(3);
     request[0] = _OPEN_REQUEST;
@@ -430,8 +449,8 @@
     return result;
   }
 
-  Stream<List<int>> openRead() {
-    return new _FileStream(_path);
+  Stream<List<int>> openRead([int start, int end]) {
+    return new _FileStream(_path, start, end);
   }
 
   IOSink openWrite({FileMode mode: FileMode.WRITE,
@@ -500,7 +519,6 @@
 
   Future<List<String>> readAsLines({Encoding encoding: Encoding.UTF_8}) {
     _ensureFileService();
-    Completer<List<String>> completer = new Completer<List<String>>();
     return readAsBytes().then((bytes) {
       return _decodeLines(bytes, encoding);
     });
@@ -534,9 +552,7 @@
     try {
       return writeAsBytes(_encodeString(contents, encoding), mode: mode);
     } catch (e) {
-      var completer = new Completer();
-      Timer.run(() => completer.completeError(e));
-      return completer.future;
+      return new Future.error(e);
     }
   }
 
@@ -572,8 +588,7 @@
   _RandomAccessFile(int this._id, String this._path);
 
   Future<RandomAccessFile> close() {
-    Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     _ensureFileService();
     List request = new List(2);
     request[0] = _CLOSE_REQUEST;
@@ -604,8 +619,7 @@
 
   Future<int> readByte() {
     _ensureFileService();
-    Completer<int> completer = new Completer<int>();
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     List request = new List(2);
     request[0] = _READ_BYTE_REQUEST;
     request[1] = _id;
@@ -631,18 +645,11 @@
 
   Future<List<int>> read(int bytes) {
     _ensureFileService();
-    Completer<List<int>> completer = new Completer<List<int>>();
     if (bytes is !int) {
-      // Complete asynchronously so the user has a chance to setup
-      // handlers without getting exceptions when registering the
-      // then handler.
-      Timer.run(() {
-        completer.completeError(new FileIOException(
-            "Invalid arguments to read for file '$_path'"));
-      });
-      return completer.future;
-    };
-    if (closed) return _completeWithClosedException(completer);
+      return new Future.error(new FileIOException(
+          "Invalid arguments to read for file '$_path'"));
+    }
+    if (closed) return _closedException();
     List request = new List(3);
     request[0] = _READ_REQUEST;
     request[1] = _id;
@@ -680,8 +687,7 @@
       return new Future.error(new FileIOException(
           "Invalid arguments to readInto for file '$_path'"));
     };
-    Completer<int> completer = new Completer<int>();
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     List request = new List(3);
     if (start == null) start = 0;
     if (end == null) end = buffer.length;
@@ -732,18 +738,11 @@
 
   Future<RandomAccessFile> writeByte(int value) {
     _ensureFileService();
-    Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
     if (value is !int) {
-      // Complete asynchronously so the user has a chance to setup
-      // handlers without getting exceptions when registering the
-      // then handler.
-      Timer.run(() {
-          completer.completeError(new FileIOException(
-              "Invalid argument to writeByte for file '$_path'"));
-      });
-      return completer.future;
+      return new Future.error(new FileIOException(
+          "Invalid argument to writeByte for file '$_path'"));
     }
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     List request = new List(3);
     request[0] = _WRITE_BYTE_REQUEST;
     request[1] = _id;
@@ -781,9 +780,8 @@
       return new Future.error(new FileIOException(
           "Invalid arguments to writeFrom for file '$_path'"));
     }
-    Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
 
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
 
     _BufferAndStart result;
     try {
@@ -835,12 +833,8 @@
   Future<RandomAccessFile> writeString(String string,
                                        {Encoding encoding: Encoding.UTF_8}) {
     if (encoding is! Encoding) {
-      var completer = new Completer();
-      Timer.run(() {
-        completer.completeError(new FileIOException(
-            "Invalid encoding in writeString: $encoding"));
-      });
-      return completer.future;
+      return new Future.error(new FileIOException(
+          "Invalid encoding in writeString: $encoding"));
     }
     var data = _encodeString(string, encoding);
     return writeFrom(data, 0, data.length);
@@ -857,8 +851,7 @@
 
   Future<int> position() {
     _ensureFileService();
-    Completer<int> completer = new Completer<int>();
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     List request = new List(2);
     request[0] = _POSITION_REQUEST;
     request[1] = _id;
@@ -884,8 +877,7 @@
 
   Future<RandomAccessFile> setPosition(int position) {
     _ensureFileService();
-    Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     List request = new List(3);
     request[0] = _SET_POSITION_REQUEST;
     request[1] = _id;
@@ -911,8 +903,7 @@
 
   Future<RandomAccessFile> truncate(int length) {
     _ensureFileService();
-    Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     List request = new List(3);
     request[0] = _TRUNCATE_REQUEST;
     request[1] = _id;
@@ -938,8 +929,7 @@
 
   Future<int> length() {
     _ensureFileService();
-    Completer<int> completer = new Completer<int>();
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     List request = new List(2);
     request[0] = _LENGTH_REQUEST;
     request[1] = _id;
@@ -965,8 +955,7 @@
 
   Future<RandomAccessFile> flush() {
     _ensureFileService();
-    Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
-    if (closed) return _completeWithClosedException(completer);
+    if (closed) return _closedException();
     List request = new List(2);
     request[0] = _FLUSH_REQUEST;
     request[1] = _id;
@@ -1005,12 +994,8 @@
     }
   }
 
-  Future _completeWithClosedException(Completer completer) {
-    Timer.run(() {
-      completer.completeError(
-          new FileIOException("File closed '$_path'"));
-    });
-    return completer.future;
+  Future _closedException() {
+    return new Future.error(new FileIOException("File closed '$_path'"));
   }
 
   final String _path;
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 47be232..5dc5738 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -873,6 +873,12 @@
   static const int DEFAULT_HTTP_PORT = 80;
   static const int DEFAULT_HTTPS_PORT = 443;
 
+  /**
+   * Get and set the idle timeout of non-active persistent (keep-alive)
+   * connections. The default value is 15 seconds.
+   */
+  Duration idleTimeout;
+
   factory HttpClient() => new _HttpClient();
 
   /**
diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
index 8153850..cabdfb0 100644
--- a/sdk/lib/io/http_headers.dart
+++ b/sdk/lib/io/http_headers.dart
@@ -23,7 +23,7 @@
     return values[0];
   }
 
-  void add(String name, Object value) {
+  void add(String name, value) {
     _checkMutable();
     if (value is List) {
       for (int i = 0; i < value.length; i++) {
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 73acb00..c749ceb 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -47,9 +47,9 @@
   // Is completed once all data have been received.
   Future get dataDone => _dataCompleter.future;
 
-  void close() {
+  void close(bool closing) {
     fullBodyRead = true;
-    _dataCompleter.complete();
+    _dataCompleter.complete(closing);
   }
 }
 
@@ -580,13 +580,12 @@
 
   bool _done([error]) {
     if (_completer == null) return false;
-    var tmp = _completer;
-    _completer = null;
     if (error != null) {
-      tmp.completeError(error);
+      _completer.completeError(error);
     } else {
-      tmp.complete(_outbound);
+      _completer.complete(_outbound);
     }
+    _completer = null;
     return true;
   }
 
@@ -1071,6 +1070,7 @@
   StreamSubscription _subscription;
   final _HttpClient _httpClient;
   bool _dispose = false;
+  Timer _idleTimer;
   bool closed = false;
 
   Completer<_HttpIncoming> _nextResponseCompleter;
@@ -1285,6 +1285,22 @@
     return isSecure ? "ssh:$host:$port" : "$host:$port";
   }
 
+  void stopTimer() {
+    if (_idleTimer != null) {
+      _idleTimer.cancel();
+      _idleTimer = null;
+    }
+  }
+
+  void startTimer() {
+    assert(_idleTimer == null);
+    _idleTimer = new Timer(
+        _httpClient.idleTimeout,
+        () {
+          _idleTimer = null;
+          close();
+        });
+  }
 }
 
 class _ConnnectionInfo {
@@ -1296,7 +1312,6 @@
 
 class _HttpClient implements HttpClient {
   // TODO(ajohnsen): Use eviction timeout.
-  static const int DEFAULT_EVICTION_TIMEOUT = 60000;
   bool _closing = false;
 
   final Map<String, Set<_HttpClientConnection>> _idleConnections
@@ -1308,6 +1323,21 @@
   Function _authenticate;
   Function _authenticateProxy;
   Function _findProxy = HttpClient.findProxyFromEnvironment;
+  Duration _idleTimeout = const Duration(seconds: 15);
+
+  Timer _noActiveTimer;
+
+  Duration get idleTimeout => _idleTimeout;
+
+  void set idleTimeout(Duration timeout) {
+    _idleTimeout = timeout;
+    _idleConnections.values.forEach(
+        (l) => l.forEach((c) {
+          // Reset timer. This is fine, as it's not happening often.
+          c.stopTimer();
+          c.startTimer();
+        }));
+  }
 
   Future<HttpClientRequest> open(String method,
                                  String host,
@@ -1485,15 +1515,17 @@
       connection.close();
       return;
     }
-    // TODO(ajohnsen): Listen for socket close events.
     if (!_idleConnections.containsKey(connection.key)) {
       _idleConnections[connection.key] = new LinkedHashSet();
     }
     _idleConnections[connection.key].add(connection);
+    connection.startTimer();
+    _updateTimers();
   }
 
   // Remove a closed connnection from the active set.
   void _connectionClosed(_HttpClientConnection connection) {
+    connection.stopTimer();
     _activeConnections.remove(connection);
     if (_idleConnections.containsKey(connection.key)) {
       _idleConnections[connection.key].remove(connection);
@@ -1501,6 +1533,24 @@
         _idleConnections.remove(connection.key);
       }
     }
+    _updateTimers();
+  }
+
+  void _updateTimers() {
+    if (_activeConnections.isEmpty) {
+      if (!_idleConnections.isEmpty && _noActiveTimer == null) {
+        _noActiveTimer = new Timer(const Duration(milliseconds: 100), () {
+          _noActiveTimer = null;
+          if (_activeConnections.isEmpty) {
+            close();
+            _closing = false;
+          }
+        });
+      }
+    } else if (_noActiveTimer != null) {
+      _noActiveTimer.cancel();
+      _noActiveTimer = null;
+    }
   }
 
   // Get a new _HttpClientConnection, either from the idle pool or created from
@@ -1523,7 +1573,9 @@
         if (_idleConnections[key].isEmpty) {
           _idleConnections.remove(key);
         }
+        connection.stopTimer();
         _activeConnections.add(connection);
+        _updateTimers();
         return new Future.value(new _ConnnectionInfo(connection, proxy));
       }
       return (isSecure && proxy.isDirect
@@ -1668,6 +1720,10 @@
     _socket.pipe(_httpParser);
     _subscription = _httpParser.listen(
         (incoming) {
+          // If the incoming was closed, close the connection.
+          incoming.dataDone.then((closing) {
+            if (closing) destroy();
+          });
           // Only handle one incoming request at the time. Keep the
           // stream paused until the request has been send.
           _subscription.pause();
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index af937e9..58622cf 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -105,8 +105,7 @@
   Completer resumeCompleter;
 
   _HttpDetachedIncoming(StreamSubscription this.subscription,
-                        List<int> this.carryOverData,
-                        Completer oldResumeCompleter) {
+                        List<int> this.carryOverData) {
     controller = new StreamController<List<int>>(
         onListen: resume,
         onPause: pause,
@@ -118,7 +117,6 @@
       controller.close();
     } else {
       pause();
-      if (oldResumeCompleter != null) oldResumeCompleter.complete();
       subscription.resume();
       subscription.onData(controller.add);
       subscription.onDone(controller.close);
@@ -729,7 +727,7 @@
               new HttpParserException(
                   "Connection closed while receiving data"));
       }
-      _closeIncoming();
+      _closeIncoming(true);
       _controller.close();
       return;
     }
@@ -792,11 +790,8 @@
   void set responseToMethod(String method) { _responseToMethod = method; }
 
   _HttpDetachedIncoming detachIncoming() {
-    var completer = _pauseCompleter;
-    _pauseCompleter = null;
     return new _HttpDetachedIncoming(_socketSubscription,
-                                     readUnparsedData(),
-                                     completer);
+                                     readUnparsedData());
   }
 
   List<int> readUnparsedData() {
@@ -909,7 +904,7 @@
           if (_socketSubscription != null) {
             _socketSubscription.cancel();
           }
-          _closeIncoming();
+          _closeIncoming(true);
           _controller.close();
         });
     incoming = _incoming = new _HttpIncoming(
@@ -918,11 +913,11 @@
     _pauseStateChanged();
   }
 
-  void _closeIncoming() {
+  void _closeIncoming([bool closing = false]) {
     // Ignore multiple close (can happend in re-entrance).
     if (_incoming == null) return;
     var tmp = _incoming;
-    tmp.close();
+    tmp.close(closing);
     _incoming = null;
     if (_bodyController != null) {
       _bodyController.close();
@@ -993,7 +988,6 @@
   StreamSubscription _socketSubscription;
   bool _paused = true;
   bool _bodyPaused = false;
-  Completer _pauseCompleter;
   StreamController<_HttpIncoming> _controller;
   StreamController<List<int>> _bodyController;
 }
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index fee6a12..c44f6ba 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -25,7 +25,6 @@
 import 'dart:utf';
 import 'dart:typed_data';
 
-part 'base64.dart';
 part 'buffer_list.dart';
 part 'common.dart';
 part 'data_transformer.dart';
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index c6a82f0..8e8b71f 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -116,13 +116,12 @@
 
   void _completeDone({value, error}) {
     if (_doneCompleter == null) return;
-    var tmp = _doneCompleter;
-    _doneCompleter = null;
     if (error == null) {
-      tmp.complete(value);
+      _doneCompleter.complete(value);
     } else {
-      tmp.completeError(error);
+      _doneCompleter.completeError(error);
     }
+    _doneCompleter = null;
   }
 
   StreamController<T> get _controller {
@@ -140,10 +139,9 @@
               (_) {
                 if (_isBound) {
                   // A new stream takes over - forward values to that stream.
-                  var completer = _controllerCompleter;
+                  _controllerCompleter.complete();
                   _controllerCompleter = null;
                   _controllerInstance = null;
-                  completer.complete();
                 } else {
                   // No new stream, .close was called. Close _target.
                   _closeTarget();
@@ -152,10 +150,9 @@
               onError: (error) {
                 if (_isBound) {
                   // A new stream takes over - forward errors to that stream.
-                  var completer = _controllerCompleter;
+                  _controllerCompleter.completeError(error);
                   _controllerCompleter = null;
                   _controllerInstance = null;
-                  completer.completeError(error);
                 } else {
                   // No new stream. No need to close target, as it have already
                   // failed.
diff --git a/sdk/lib/io/iolib_sources.gypi b/sdk/lib/io/iolib_sources.gypi
index 2eab1d9..5225dc1 100644
--- a/sdk/lib/io/iolib_sources.gypi
+++ b/sdk/lib/io/iolib_sources.gypi
@@ -4,7 +4,6 @@
 
 {
   'sources': [
-    'base64.dart',
     'buffer_list.dart',
     'common.dart',
     'data_transformer.dart',
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index c1a060a..6e9b1cd 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -100,6 +100,57 @@
                                             [ProcessOptions options]);
 
   /**
+   * Starts a process in the system shell and runs it non-interactively to
+   * completion.
+   *
+   * On Linux and Mac OS, [:/bin/sh:] is used to execute the [executable].
+   * On Windows, [:%WINDIR%\system32\cmd.exe:] is used.
+   *
+   * An optional [ProcessOptions] object can be passed to specify
+   * options other than the executable and the arguments.
+   *
+   * Returns a [:Future<ProcessResult>:] that completes with the
+   * result of running the process, i.e., exit code, standard out and
+   * standard in.
+   */
+  static Future<ProcessResult> runShell(String executable,
+                                        List<String> arguments,
+                                        [ProcessOptions options])
+      => run(_getShellCommand(),
+             _getShellArguments(executable, arguments),
+             options);
+
+  static String _getShellCommand() {
+    if (Platform.operatingSystem == 'windows') {
+      return 'cmd.exe';
+    }
+    return '/bin/sh';
+  }
+
+  static List<String> _getShellArguments(String executable,
+                                         List<String> arguments) {
+    List<String> shellArguments = [];
+    if (Platform.operatingSystem == 'windows') {
+      shellArguments.add('/c');
+      shellArguments.add(executable);
+      for (var arg in arguments) {
+        arg = arg.replaceAll('"', r'\"');
+        shellArguments.add(arg);
+      }
+    } else {
+      var commandLine = new StringBuffer();
+      commandLine.write(executable);
+      shellArguments.add("-c");
+      for (var arg in arguments) {
+        arg = arg.replaceAll("'", "'\"'\"'");
+        commandLine.write(" '$arg'");
+      }
+      shellArguments.add(commandLine.toString());
+    }
+    return shellArguments;
+  }
+
+  /**
    * Returns the standard output stream of the process as a [:Stream:].
    *
    * Throws an [UnsupportedError] if the process is
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 74df425..3cef0ad 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -408,7 +408,7 @@
     String key = request.headers.value("Sec-WebSocket-Key");
     SHA1 sha1 = new SHA1();
     sha1.add("$key$_webSocketGUID".codeUnits);
-    String accept = _Base64._encode(sha1.close());
+    String accept = CryptoUtils.bytesToBase64(sha1.close());
     response.headers.add("Sec-WebSocket-Accept", accept);
     response.headers.contentLength = 0;
     return response.detachSocket()
@@ -585,13 +585,12 @@
 
   bool _done([error]) {
     if (_completer == null) return false;
-    var tmp = _completer;
-    _completer = null;
     if (error != null) {
-      tmp.completeError(error);
+      _completer.completeError(error);
     } else {
-      tmp.complete(webSocket);
+      _completer.complete(webSocket);
     }
+    _completer = null;
     return true;
   }
 
@@ -659,7 +658,7 @@
     for (int i = 0; i < 16; i++) {
       nonceData[i] = random.nextInt(256);
     }
-    String nonce = _Base64._encode(nonceData);
+    String nonce = CryptoUtils.bytesToBase64(nonceData);
 
     uri = new Uri.fromComponents(scheme: uri.scheme == "wss" ? "https" : "http",
                                  userInfo: uri.userInfo,
@@ -700,7 +699,7 @@
         SHA1 sha1 = new SHA1();
         sha1.add("$nonce$_webSocketGUID".codeUnits);
         List<int> expectedAccept = sha1.close();
-        List<int> receivedAccept = _Base64._decode(accept);
+        List<int> receivedAccept = CryptoUtils.base64StringToBytes(accept);
         if (expectedAccept.length != receivedAccept.length) {
           error("Reasponse header 'Sec-WebSocket-Accept' is the wrong length");
         }
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index ae4f720..564670f 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -5365,7 +5365,7 @@
     return _cssClassSet;
   }
 
-  List<Element> get children => new FilteredElementList(this);
+  List<Element> get children => new FilteredElementList<Element>(this);
 
   void set children(List<Element> value) {
     final children = this.children;
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index bb2ad9b..d8d92c2 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -6110,7 +6110,7 @@
     return _cssClassSet;
   }
 
-  List<Element> get children => new FilteredElementList(this);
+  List<Element> get children => new FilteredElementList<Element>(this);
 
   void set children(List<Element> value) {
     final children = this.children;
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 814b54d..2a350af 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -3,16 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dartanalyzer ]
-Language/03_Overview/1_Scoping_A01_t46: fail
-Language/03_Overview/1_Scoping_A02_t07: fail
-Language/03_Overview/1_Scoping_A02_t11: fail
-Language/03_Overview/1_Scoping_A02_t12: fail
-Language/03_Overview/1_Scoping_A02_t16: fail
-Language/03_Overview/1_Scoping_A02_t28: fail
-Language/05_Variables/05_Variables_A01_t09: fail
-Language/05_Variables/05_Variables_A01_t11: fail
 Language/05_Variables/05_Variables_A05_t04: fail
-Language/06_Functions/06_Functions_A01_t10: fail
 Language/06_Functions/06_Functions_A01_t31: fail
 Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t06: fail
 Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t07: fail
@@ -20,11 +11,7 @@
 Language/06_Functions/2_Formal_Parameters_A01_t02: fail
 Language/06_Functions/2_Formal_Parameters_A01_t09: fail
 Language/06_Functions/2_Formal_Parameters_A02_t02: fail
-Language/07_Classes/07_Classes_A02_t02: fail
-Language/07_Classes/07_Classes_A02_t04: fail
-Language/07_Classes/07_Classes_A03_t02: fail
-Language/07_Classes/07_Classes_A03_t07: fail
-Language/07_Classes/07_Classes_A03_t08: fail
+Language/07_Classes/07_Classes_A01_t20: fail
 Language/07_Classes/07_Classes_A09_t01: fail
 Language/07_Classes/07_Classes_A09_t02: fail
 Language/07_Classes/07_Classes_A09_t03: fail
@@ -37,19 +24,15 @@
 Language/07_Classes/3_Setters_A03_t04: fail
 Language/07_Classes/3_Setters_A03_t06: fail
 Language/07_Classes/3_Setters_A03_t08: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t04: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t06: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A03_t11: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A11_t04: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A11_t06: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A11_t07: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A11_t09: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t01: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t04: fail
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A15_t07: fail
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A03_t02: fail
+Language/07_Classes/6_Constructors/2_Factories_A06_t01: fail
+Language/07_Classes/6_Constructors/2_Factories_A06_t02: fail
+Language/07_Classes/6_Constructors/2_Factories_A06_t04: fail
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: fail
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: fail
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: fail
@@ -60,6 +43,7 @@
 Language/08_Interfaces/5_Superinterfaces_A01_t03: fail
 Language/08_Interfaces/5_Superinterfaces_A01_t04: fail
 Language/08_Interfaces/5_Superinterfaces_A04_t03: fail
+Language/09_Generics/09_Generics_A04_t07: fail
 Language/11_Expressions/01_Constants_A01_t01: fail
 Language/11_Expressions/01_Constants_A08_t02: fail
 Language/11_Expressions/01_Constants_A09_t02: fail
@@ -78,20 +62,12 @@
 Language/11_Expressions/03_Numbers_A01_t04: fail
 Language/11_Expressions/03_Numbers_A01_t08: fail
 Language/11_Expressions/03_Numbers_A01_t10: fail
-Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t03: fail
-Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t09: fail
-Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t11: fail
-Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t14: fail
-Language/11_Expressions/05_Strings/1_String_Interpolation_A01_t15: fail
-Language/11_Expressions/05_Strings_A02_t34: fail
-Language/11_Expressions/05_Strings_A02_t36: fail
-Language/11_Expressions/05_Strings_A02_t42: fail
-Language/11_Expressions/05_Strings_A02_t44: fail
+Language/11_Expressions/05_Strings/1_String_Interpolation_A03_t01: fail
+Language/11_Expressions/05_Strings/1_String_Interpolation_A04_t01: fail
 Language/11_Expressions/05_Strings_A02_t46: fail
 Language/11_Expressions/05_Strings_A02_t48: fail
-Language/11_Expressions/06_Lists_A01_t03: fail
-Language/11_Expressions/06_Lists_A01_t04: fail
 Language/11_Expressions/06_Lists_A03_t01: fail
+Language/11_Expressions/06_Lists_A06_t01: fail
 Language/11_Expressions/07_Maps_A02_t02: fail
 Language/11_Expressions/08_Throw_A06_t01: fail
 Language/11_Expressions/08_Throw_A06_t02: fail
@@ -99,110 +75,41 @@
 Language/11_Expressions/08_Throw_A06_t04: fail
 Language/11_Expressions/08_Throw_A06_t05: fail
 Language/11_Expressions/08_Throw_A06_t06: fail
-Language/11_Expressions/11_Instance_Creation/1_New_A01_t04: fail
+Language/11_Expressions/11_Instance_Creation/1_New_A13_t02: fail
 Language/11_Expressions/11_Instance_Creation/2_Const_A06_t01: fail
 Language/11_Expressions/11_Instance_Creation/2_Const_A06_t02: fail
 Language/11_Expressions/11_Instance_Creation/2_Const_A10_t01: fail
 Language/11_Expressions/11_Instance_Creation_A05_t02: fail
-Language/11_Expressions/14_Function_Invocation/1_Actual_Argument_List_Evaluation_A01_t05: fail
+Language/11_Expressions/14_Function_Invocation/1_Actual_Argument_List_Evaluation_A02_t01: fail
 Language/11_Expressions/14_Function_Invocation/2_Binding_Actuals_to_Formals_A04_t01: fail
-Language/11_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t10: fail
-Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A01_t05: fail
-Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A01_t05: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A01_t05: fail
-Language/11_Expressions/19_Conditional_A01_t05: fail
-Language/11_Expressions/19_Conditional_A01_t06: fail
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t04: fail
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t05: fail
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t06: fail
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t07: fail
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t08: fail
-Language/11_Expressions/20_Logical_Boolean_Expressions_A01_t09: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t03: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t04: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t05: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t06: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t07: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t08: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t09: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t10: fail
-Language/11_Expressions/21_Bitwise_Expressions_A01_t11: fail
-Language/11_Expressions/22_Equality_A01_t03: fail
-Language/11_Expressions/22_Equality_A01_t04: fail
-Language/11_Expressions/22_Equality_A01_t07: fail
-Language/11_Expressions/22_Equality_A01_t08: fail
-Language/11_Expressions/22_Equality_A01_t11: fail
-Language/11_Expressions/22_Equality_A01_t12: fail
+Language/11_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t05: fail
+Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A02_t01: fail
+Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A05_t01: fail
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A04_t01: fail
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A08_t01: fail
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t01: fail
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t07: fail
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t05: fail
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A06_t02: fail
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t04: fail
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t01: fail
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t02: fail
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t03: fail
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t04: fail
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A08_t02: fail
 Language/11_Expressions/22_Equality_A01_t15: fail
 Language/11_Expressions/22_Equality_A01_t16: fail
-Language/11_Expressions/23_Relational_Expressions_A01_t03: fail
-Language/11_Expressions/23_Relational_Expressions_A01_t04: fail
-Language/11_Expressions/23_Relational_Expressions_A01_t05: fail
-Language/11_Expressions/23_Relational_Expressions_A01_t06: fail
-Language/11_Expressions/23_Relational_Expressions_A01_t07: fail
-Language/11_Expressions/23_Relational_Expressions_A01_t08: fail
-Language/11_Expressions/23_Relational_Expressions_A01_t09: fail
-Language/11_Expressions/24_Shift_A01_t02: fail
-Language/11_Expressions/24_Shift_A01_t03: fail
-Language/11_Expressions/24_Shift_A01_t04: fail
-Language/11_Expressions/24_Shift_A01_t05: fail
-Language/11_Expressions/24_Shift_A01_t06: fail
-Language/11_Expressions/24_Shift_A01_t07: fail
-Language/11_Expressions/25_Additive_Expressions_A01_t02: fail
-Language/11_Expressions/25_Additive_Expressions_A01_t03: fail
-Language/11_Expressions/25_Additive_Expressions_A01_t06: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t02: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t03: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t04: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t05: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t06: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t07: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t08: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t18: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t19: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t20: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t21: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t22: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t23: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t24: fail
-Language/11_Expressions/26_Multiplicative_Expressions_A01_t25: fail
-Language/11_Expressions/27_Unary_Expressions_A01_t08: fail
 Language/11_Expressions/28_Postfix_Expressions_A01_t06: fail
-Language/11_Expressions/28_Postfix_Expressions_A01_t09: fail
-Language/11_Expressions/28_Postfix_Expressions_A01_t10: fail
-Language/11_Expressions/28_Postfix_Expressions_A01_t11: fail
-Language/11_Expressions/29_Assignable_Expressions_A01_t10: fail
-Language/11_Expressions/29_Assignable_Expressions_A01_t11: fail
-Language/11_Expressions/29_Assignable_Expressions_A01_t12: fail
-Language/11_Expressions/29_Assignable_Expressions_A01_t13: fail
-Language/11_Expressions/29_Assignable_Expressions_A01_t15: fail
-Language/11_Expressions/29_Assignable_Expressions_A01_t16: fail
 Language/11_Expressions/30_Identifier_Reference_A01_t07: fail
 Language/11_Expressions/30_Identifier_Reference_A01_t08: fail
-Language/11_Expressions/31_Type_Test_A05_t01: fail
-Language/11_Expressions/31_Type_Test_A05_t02: fail
-Language/11_Expressions/31_Type_Test_A05_t03: fail
-Language/11_Expressions/32_Type_Cast_A04_t01: fail
-Language/11_Expressions/32_Type_Cast_A04_t02: fail
 Language/11_Expressions/33_Argument_Definition_Test_A01_t14: fail
 Language/11_Expressions/33_Argument_Definition_Test_A01_t18: fail
 Language/12_Statements/02_Expression_Statements_A01_t06: fail
-Language/12_Statements/02_Expression_Statements_A01_t12: fail
-Language/12_Statements/04_Local_Function_Declaration_A01_t01: fail
-Language/12_Statements/04_Local_Function_Declaration_A02_t02: fail
-Language/12_Statements/05_If_A01_t01: fail
-Language/12_Statements/06_For_A01_t10: fail
-Language/12_Statements/07_While_A01_t04: fail
-Language/12_Statements/08_Do_A01_t07: fail
-Language/12_Statements/09_Switch_A01_t06: fail
 Language/12_Statements/09_Switch_A04_t01: fail
-Language/12_Statements/15_Assert_A01_t03: fail
 Language/13_Libraries_and_Scripts/13_Libraries_and_Scripts_A03_t17: fail
 Language/13_Libraries_and_Scripts/1_Imports_A01_t46: fail
-Language/13_Libraries_and_Scripts/1_Imports_A02_t12: fail
-Language/13_Libraries_and_Scripts/1_Imports_A02_t15: fail
 Language/13_Libraries_and_Scripts/1_Imports_A04_t03: fail
-Language/13_Libraries_and_Scripts/1_Imports_A05_t01: fail # co19 issue 411
+Language/13_Libraries_and_Scripts/1_Imports_A05_t01: fail
 Language/13_Libraries_and_Scripts/2_Exports_A05_t01: fail
 Language/13_Libraries_and_Scripts/5_URIs_A01_t24: fail
 Language/13_Libraries_and_Scripts/5_URIs_A01_t25: fail
@@ -210,15 +117,82 @@
 Language/14_Types/3_Type_Declarations/1_Typedef_A07_t02: fail
 Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: fail
 Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: fail
+Language/14_Types/4_Interface_Types_A10_t03: fail
+Language/14_Types/4_Interface_Types_A10_t04: fail
+Language/14_Types/4_Interface_Types_A10_t09: fail
 Language/15_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: fail
+Language/15_Reference/1_Lexical_Rules_A01_t10: fail
 Language/15_Reference/1_Lexical_Rules_A02_t06: fail
+LibTest/core/AssertionError/column_A01_t02: fail
+LibTest/core/AssertionError/failedAssertion_A01_t01: fail
+LibTest/core/AssertionError/line_A01_t02: fail
+LibTest/core/AssertionError/url_A01_t01: fail
+LibTest/core/Iterable/where_A01_t07: fail
+LibTest/core/List/List.fixedLength_A01_t01: fail
+LibTest/core/List/List_A01_t02: fail
+LibTest/core/List/addLast_A01_t01: fail
+LibTest/core/List/addLast_A01_t03: fail
+LibTest/core/List/addLast_A02_t01: fail
+LibTest/core/List/every_A01_t01: fail
+LibTest/core/List/insertRange_A01_t01: fail
+LibTest/core/List/insertRange_A02_t01: fail
+LibTest/core/List/insertRange_A03_t01: fail
+LibTest/core/List/insertRange_A04_t01: fail
+LibTest/core/List/insertRange_A05_t01: fail
+LibTest/core/List/insertRange_A06_t01: fail
+LibTest/core/List/insertRange_A07_t01: fail
+LibTest/core/List/insertRange_A08_t01: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A03_t02: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A04_t01: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A07_t01: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A08_t01: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A08_t02: fail
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A09_t01: fail
+LibTest/core/Set/isSubsetOf_A01_t01: fail
+LibTest/core/Set/isSubsetOf_A01_t02: fail
+LibTest/core/String/String_class_A01_t01: fail
+LibTest/core/String/charCodeAt_A01_t01: fail
+LibTest/core/String/charCodeAt_A02_t01: fail
+LibTest/core/String/charCodeAt_A03_t01: fail
+LibTest/core/String/charCodes_A01_t01: fail
+LibTest/core/String/concat_A01_t01: fail
+LibTest/core/String/concat_A02_t01: fail
+LibTest/core/String/hashCode_A01_t01: fail
+LibTest/core/String/splitChars_A01_t01: fail
+LibTest/core/StringBuffer/addAll_A01_t01: fail
+LibTest/core/StringBuffer/addAll_A01_t02: fail
+LibTest/core/StringBuffer/addAll_A03_t01: fail
+LibTest/core/StringBuffer/add_A01_t01: fail
+LibTest/core/StringBuffer/add_A01_t02: fail
+LibTest/core/StringBuffer/isEmpty_A01_t01: fail
+LibTest/core/StringBuffer/toString_A01_t01: fail
 LibTest/core/double/ceil_A01_t05: fail
 LibTest/core/double/floor_A01_t05: fail
+LibTest/core/int/operator_division_A01_t01: fail
+
+# fails locally, passes on bot
+Language/13_Libraries_and_Scripts/3_Parts_A02_t03: skip
 
 # co19 issue #412, using 'null' as operand
-Language/11_Expressions/01_Constants_A11_t01: fail
-Language/11_Expressions/01_Constants_A12_t01: fail
-Language/11_Expressions/01_Constants_A13_t06: fail
+Language/11_Expressions/01_Constants_A11_t01: fail, OK
+Language/11_Expressions/01_Constants_A12_t01: fail, OK
+Language/11_Expressions/01_Constants_A13_t06: fail, OK
+
+# co19 issue #414, extra @compile-error
+Language/03_Overview/1_Scoping_A02_t28: fail, OK
+
+# co19 issue #416, function name is declared the parameter scope
+Language/03_Overview/1_Scoping_A02_t07: fail, OK
+Language/12_Statements/04_Local_Function_Declaration_A01_t01: fail, OK
+
+# co19 issue $417, 'if', 'while' and 'do-while' don't create scope
+Language/03_Overview/1_Scoping_A02_t11: fail, OK
+Language/03_Overview/1_Scoping_A02_t12: fail, OK
+Language/03_Overview/1_Scoping_A02_t16: fail, OK
+
 
 
 [ $runtime == drt && $compiler == none ]
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 861ba7a..ecc143f 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -230,10 +230,6 @@
 [ $compiler == dart2js && $checked ]
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t03: Fail # TODO(ahe): Please triage this failure.
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t04: Fail # TODO(ahe): Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A06_t01: Fail # TODO(ahe): Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A06_t02: Fail # TODO(ahe): Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A06_t03: Fail # TODO(ahe): Please triage this failure.
-Language/07_Classes/6_Constructors/2_Factories_A06_t04: Fail # TODO(ahe): Please triage this failure.
 Language/09_Generics/09_Generics_A03_t01: Fail # TODO(ahe): Please triage this failure.
 Language/09_Generics/09_Generics_A04_t06: Fail # TODO(ahe): Please triage this failure.
 Language/11_Expressions/03_Numbers_A05_t02: Fail # TODO(ahe): Please triage this failure.
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index 93ae53c..1cc88e4 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -27,8 +27,13 @@
 // TODO(johnniwinther): Support canonical URIs as keys and message kinds as
 // values.
 const Map<String,List<String>> WHITE_LIST = const {
-  'html_dart2js.dart': const ['Warning: Using "new Symbol"', // Issue 10565.
-                              'Warning: unreachable code'], // Issue 10617.
+  'html_dart2js.dart':
+      const ['Warning: Using "new Symbol"', // Issue 10565.
+             'Warning: unreachable code', // Issue 10617.
+             // Issue 10688:
+             'Warning: no property named',
+             "Warning: 'UnsupportedError' is not callable",
+             "Warning: no operator [] in class Iterable"],
 };
 
 class CollectingDiagnosticHandler extends FormattingDiagnosticHandler {
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
index 28d2995..8ff09c7 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -222,7 +222,7 @@
       int index = 0;
       signature.forEachParameter((Element element) {
         Expect.equals(expectedTypes[index++],
-                      inferrer.internal.typeOf[element]);
+            inferrer.internal.typeOf[element].simplify(inferrer.compiler));
       });
       Expect.equals(index, expectedTypes.length);
   });
@@ -245,14 +245,14 @@
   runTest(TEST_5, (inferrer) => [inferrer.numType]);
   runTest(TEST_6, (inferrer) => [inferrer.numType]);
   runTest(TEST_7a, (inferrer) => [subclassOfInterceptor(inferrer)]);
-  runTest(TEST_7b, (inferrer) => [inferrer.dynamicType]);
+  runTest(TEST_7b, (inferrer) => [inferrer.dynamicType.nonNullable()]);
 
   // In the following tests, we can't infer the right types because we
   // have recursive calls with the same parameters. We should build a
   // constraint system for those, to find the types.
   runTest(TEST_8, (inferrer) => [inferrer.dynamicType,
                                  subclassOfInterceptor(inferrer),
-                                 inferrer.dynamicType]);
+                                 inferrer.dynamicType.nonNullable()]);
   runTest(TEST_9, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
   runTest(TEST_10, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
   runTest(TEST_11, (inferrer) => [subclassOfInterceptor(inferrer),
diff --git a/tests/compiler/dart2js/call_site_type_inferer_static_test.dart b/tests/compiler/dart2js/call_site_type_inferer_static_test.dart
index 2081157..5a77227 100644
--- a/tests/compiler/dart2js/call_site_type_inferer_static_test.dart
+++ b/tests/compiler/dart2js/call_site_type_inferer_static_test.dart
@@ -84,8 +84,9 @@
       HTypeList types = compiler.backend.optimisticParameterTypes(x, null);
       if (expectedTypes != null) {
         Expect.isFalse(types.allUnknown);
-        Expect.listEquals(expectedTypes.map((f) => f(compiler)).toList(),
-                          types.types);
+        Expect.listEquals(
+            expectedTypes.map((f) => f(compiler)).toList(),
+            types.types.map((e) => e.simplify(compiler)).toList());
       } else {
         Expect.isTrue(types.allUnknown);
       }
diff --git a/tests/compiler/dart2js/call_site_type_inferer_test.dart b/tests/compiler/dart2js/call_site_type_inferer_test.dart
index 4a04eff..bad589f 100644
--- a/tests/compiler/dart2js/call_site_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_type_inferer_test.dart
@@ -228,7 +228,8 @@
             .toList();
         Expect.isFalse(types.allUnknown);
         Expect.equals(expectedTypes.length, types.types.length);
-        Expect.listEquals(expectedTypes, types.types);
+        Expect.listEquals(expectedTypes,
+            types.types.map((t) => t.simplify(compiler)).toList());
       } else {
         Expect.isTrue(types.allUnknown);
       }
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index 619f3bf..334d825 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -1255,8 +1255,9 @@
   Expect.equals(convert(singleton(a).union(singleton(b)).union(nullSingleton)),
                 new TypeMask.subclass(a.rawType));
 
-  Expect.equals(convert(singleton(b).union(singleton(d))),
-                new TypeMask.nonNullSubtype(a.rawType));
+  Expect.equals(
+      convert(singleton(b).union(singleton(d))).simplify(result.compiler),
+      new TypeMask.nonNullSubtype(a.rawType));
 }
 
 testSelectors() {
@@ -1302,7 +1303,7 @@
   Selector foo = new Selector.call(buildSourceString("foo"), null, 0);
 
   Expect.equals(
-      inferredType(foo),
+      inferredType(foo).simplify(result.compiler),
       new TypeMask.nonNullSubclass(abc.rawType));
   Expect.equals(
       inferredType(new TypedSelector.subclass(x.rawType, foo)),
@@ -1314,7 +1315,8 @@
       inferredType(new TypedSelector.subclass(z.rawType, foo)),
       new TypeMask.nonNullExact(a.rawType));
   Expect.equals(
-      inferredType(new TypedSelector.subclass(xy.rawType, foo)),
+      inferredType(new TypedSelector.subclass(
+          xy.rawType, foo)).simplify(result.compiler),
       new TypeMask.nonNullSubclass(bc.rawType));
 
   Selector bar = new Selector.call(buildSourceString("bar"), null, 0);
diff --git a/tests/compiler/dart2js/field_type_inferer_test.dart b/tests/compiler/dart2js/field_type_inferer_test.dart
index 901b06e..59db184 100644
--- a/tests/compiler/dart2js/field_type_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_inferer_test.dart
@@ -344,7 +344,8 @@
       name,
       disableInlining,
       (backend, field) {
-        HType inferredType = backend.optimisticFieldType(field);
+        HType inferredType =
+            backend.optimisticFieldType(field).simplify(backend.compiler);
         if (type is Function) type = type(backend.compiler);
         Expect.equals(type, inferredType);
     });
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 5a2f27b..7422b80 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -450,7 +450,8 @@
       disableInlining,
       (inferrer, field) {
         TypeMask type = f(inferrer);
-        TypeMask inferredType = inferrer.internal.typeOf[field];
+        TypeMask inferredType =
+            inferrer.internal.typeOf[field].simplify(inferrer.compiler);
         Expect.equals(type, inferredType, name);
     });
   });
@@ -478,11 +479,10 @@
   // code at the declaration site of the fields does not matter.
   runTest(TEST_5, {'f1': subclassOfInterceptor,
                    'f2': subclassOfInterceptor});
-  // TODO(9415). These tests seem flaky.
-  //runTest(TEST_6, {'f1': subclassOfInterceptor,
-  //                 'f2': subclassOfInterceptor});
-  //runTest(TEST_7, {'f1': subclassOfInterceptor,
-  //                 'f2': subclassOfInterceptor});
+  runTest(TEST_6, {'f1': subclassOfInterceptor,
+                   'f2': subclassOfInterceptor});
+  runTest(TEST_7, {'f1': subclassOfInterceptor,
+                   'f2': subclassOfInterceptor});
 
   runTest(TEST_8, {'f': (inferrer) => inferrer.stringType.nullable()});
   runTest(TEST_9, {'f': (inferrer) => inferrer.stringType.nullable()});
diff --git a/tests/compiler/dart2js/generate_at_use_site_test.dart b/tests/compiler/dart2js/generate_at_use_site_test.dart
index d0955cb..8204f6a 100644
--- a/tests/compiler/dart2js/generate_at_use_site_test.dart
+++ b/tests/compiler/dart2js/generate_at_use_site_test.dart
@@ -22,8 +22,23 @@
 }
 """;
 
+const String BAR = r"""
+bar() {
+  var isLeaf = (bar() != null) && bar();
+  // Because we're using a local variable, the graph gets an empty
+  // block between the [isLeaf] phi and the next instruction that uses
+  // it. The optimizer must take that new block into account in order
+  // to have the phi be generate at use uste.
+  if (isLeaf) return null;
+  return true;
+}
+""";
+
 main() {
   // Make sure we don't introduce a new variable.
   RegExp regexp = new RegExp("var $anyIdentifier =");
   compileAndDoNotMatch(FIB, 'fib', regexp);
+
+  regexp = new RegExp("isLeaf");
+  compileAndDoNotMatch(BAR, 'bar', regexp);
 }
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 8e95867..9129573 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -173,6 +173,7 @@
   class _WorkerBase {}''';
 
 class MockCompiler extends Compiler {
+  api.DiagnosticHandler diagnosticHandler;
   List<WarningMessage> warnings;
   List<WarningMessage> errors;
   final Map<String, SourceFile> sourceFiles;
@@ -256,6 +257,8 @@
   void reportWarning(Node node, var message) {
     if (message is! Message) message = message.message;
     warnings.add(new WarningMessage(node, message));
+    reportDiagnostic(spanFromNode(node),
+        'Warning: $message', api.Diagnostic.WARNING);
   }
 
   void reportError(Node node, var message) {
@@ -265,6 +268,8 @@
     }
     if (message is! Message) message = message.message;
     errors.add(new WarningMessage(node, message));
+    reportDiagnostic(spanFromNode(node),
+        'Error: $message', api.Diagnostic.ERROR);
   }
 
   void reportMessage(SourceSpan span, var message, api.Diagnostic kind) {
@@ -274,10 +279,17 @@
     } else {
       warnings.add(diagnostic);
     }
+    reportDiagnostic(span, "$message", kind);
   }
 
-  void reportDiagnostic(SourceSpan span, String message, var kind) {
-    print(message);
+  void reportDiagnostic(SourceSpan span, String message, api.Diagnostic kind) {
+    if (diagnosticHandler != null) {
+      if (span != null) {
+        diagnosticHandler(span.uri, span.begin, span.end, message, kind);
+      } else {
+        diagnosticHandler(null, null, null, message, kind);
+      }
+    }
   }
 
   bool get compilationFailed => !errors.isEmpty;
@@ -319,7 +331,7 @@
 
   parseScript(String text, [LibraryElement library]) {
     if (library == null) library = mainApp;
-    parseUnit(text, this, library);
+    parseUnit(text, this, library, registerSource);
   }
 
   void scanBuiltinLibraries() {
diff --git a/tests/compiler/dart2js/parser_helper.dart b/tests/compiler/dart2js/parser_helper.dart
index ec96f0e..3ba38e9 100644
--- a/tests/compiler/dart2js/parser_helper.dart
+++ b/tests/compiler/dart2js/parser_helper.dart
@@ -78,10 +78,17 @@
       : super('<string>', text);
 }
 
+var sourceCounter = 0;
+
 Link<Element> parseUnit(String text, Compiler compiler,
-                        LibraryElement library) {
+                        LibraryElement library,
+                        [void registerSource(Uri uri, String source)]) {
   Token tokens = scan(text);
-  Uri uri = new Uri.fromComponents(scheme: "source");
+  Uri uri =
+      new Uri.fromComponents(scheme: "source", path: '${++sourceCounter}');
+  if (registerSource != null) {
+    registerSource(uri, text);
+  }
   var script = new Script(uri, new MockFile(text));
   var unit = new CompilationUnitElementX(script, library);
   int id = 0;
diff --git a/tests/compiler/dart2js/return_type_inferer_test.dart b/tests/compiler/dart2js/return_type_inferer_test.dart
index 7f50c98..30b854d 100644
--- a/tests/compiler/dart2js/return_type_inferer_test.dart
+++ b/tests/compiler/dart2js/return_type_inferer_test.dart
@@ -72,7 +72,7 @@
       var backend = compiler.backend;
       HType type =
           backend.optimisticReturnTypesWithRecompilationOnTypeChange(null, x);
-      Expect.equals(findExpectedType(compiler), type);
+      Expect.equals(findExpectedType(compiler), type.simplify(compiler));
   });
 }
 
diff --git a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
index 14ef2d3..40c01a5 100644
--- a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
@@ -62,7 +62,8 @@
 
   checkReturn(String name, type) {
     var element = findElement(compiler, name);
-    Expect.equals(type, typesInferrer.internal.returnTypeOf[element]);
+    Expect.equals(type,
+        typesInferrer.internal.returnTypeOf[element].simplify(compiler));
   }
 
   var subclassOfInterceptor =
@@ -71,7 +72,7 @@
   checkReturn('returnDyn1', subclassOfInterceptor);
   checkReturn('returnDyn2', subclassOfInterceptor);
   checkReturn('returnDyn3', subclassOfInterceptor);
-  checkReturn('returnDyn4', typesInferrer.dynamicType);
-  checkReturn('returnDyn5', typesInferrer.dynamicType);
-  checkReturn('returnDyn6', typesInferrer.dynamicType);
+  checkReturn('returnDyn4', typesInferrer.dynamicType.nonNullable());
+  checkReturn('returnDyn5', typesInferrer.dynamicType.nonNullable());
+  checkReturn('returnDyn6', typesInferrer.dynamicType.nonNullable());
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
index cf1b4aa..b43693e 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
@@ -31,7 +31,8 @@
   checkFieldTypeInClass(String className, String fieldName, type) {
     var cls = findElement(compiler, className);
     var element = cls.lookupLocalMember(buildSourceString(fieldName));
-    Expect.equals(type, typesInferrer.internal.typeOf[element]);
+    Expect.equals(type,
+        typesInferrer.internal.typeOf[element].simplify(compiler));
   }
 
   checkFieldTypeInClass('A', 'dynamicField',
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 2e24c53..2e3cc4c 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -34,12 +34,14 @@
   checkFieldTypeInClass(String className, String fieldName, type) {
     var cls = findElement(compiler, className);
     var element = cls.lookupLocalMember(buildSourceString(fieldName));
-    Expect.equals(type, typesInferrer.internal.typeOf[element]);
+    Expect.equals(type,
+        typesInferrer.internal.typeOf[element].simplify(compiler));
   }
 
   checkFieldTypeInClass('A', 'intField', typesInferrer.intType);
   checkFieldTypeInClass('A', 'giveUpField1',
       findTypeMask(compiler, 'Interceptor', 'nonNullSubclass'));
-  checkFieldTypeInClass('A', 'giveUpField2', typesInferrer.dynamicType);
+  checkFieldTypeInClass('A', 'giveUpField2',
+      typesInferrer.dynamicType.nonNullable());
   checkFieldTypeInClass('A', 'fieldParameter', typesInferrer.intType);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
index 5297520..91fb20d 100644
--- a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
@@ -71,7 +71,7 @@
 test8() => new C().bar();
 test9() => (a ? new B() : new C()).bar();
 
-// Can hit A.noSuchMethod, D.noSuchMethod and Object.noSuchMethod.
+// Can hit A.noSuchMethod and D.noSuchMethod.
 test10() => (a ? new B() : new D()).bar();
 
 // Can hit D.noSuchMethod.
@@ -101,15 +101,18 @@
 
   checkReturn(String name, type) {
     var element = findElement(compiler, name);
-    Expect.equals(type, typesInferrer.internal.returnTypeOf[element], name);
+    Expect.equals(
+        type,
+        typesInferrer.internal.returnTypeOf[element].simplify(compiler),
+        name);
   }
 
   checkReturn('test1', typesInferrer.intType);
   checkReturn('test2', typesInferrer.dynamicType);
   checkReturn('test3', typesInferrer.intType);
   checkReturn('test4', typesInferrer.mapType);
-  checkReturn('test5', typesInferrer.dynamicType);
-  checkReturn('test6', typesInferrer.dynamicType);
+  checkReturn('test5', typesInferrer.dynamicType.nonNullable());
+  checkReturn('test6', typesInferrer.dynamicType.nonNullable());
 
   compiler = compilerFor(TEST2, uri);
   compiler.runCompiler(uri);
@@ -129,6 +132,6 @@
   checkReturn('test7', typesInferrer.intType);
   checkReturn('test8', typesInferrer.intType);
   checkReturn('test9', typesInferrer.intType);
-  checkReturn('test10', typesInferrer.numType.nullable());
+  checkReturn('test10', typesInferrer.numType);
   checkReturn('test11', typesInferrer.doubleType);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
index a879e29..3c9aaa1 100644
--- a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
@@ -69,7 +69,8 @@
   checkReturnInClass(String className, String methodName, type) {
     var cls = findElement(compiler, className);
     var element = cls.lookupLocalMember(buildSourceString(methodName));
-    Expect.equals(type, typesInferrer.internal.returnTypeOf[element]);
+    Expect.equals(type,
+        typesInferrer.internal.returnTypeOf[element].simplify(compiler));
   }
 
   var subclassOfInterceptor =
diff --git a/tests/compiler/dart2js/simple_inferrer_relations_test.dart b/tests/compiler/dart2js/simple_inferrer_relations_test.dart
index 1488c10..4b3af4a 100644
--- a/tests/compiler/dart2js/simple_inferrer_relations_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_relations_test.dart
@@ -52,7 +52,7 @@
 
 void main() {
   String generated = compileAll(TEST);
-  if (!generated.contains(r'if ($.$eq(c, d))')) {
+  if (generated.contains(r'=== true')) {
     print(generated);
     Expect.fail("missing elision of '=== true'");
   }
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 485896c..cc15222 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -236,6 +236,24 @@
   return topLevelGetter() as Foo;
 }
 
+testDeadCode() {
+  return 42;
+  return 'foo';
+}
+
+testLabeledIf(a) {
+  var c;
+  L1: if (a > 1) {
+    if (a == 2) {
+      break L1;
+    }
+    c = 42;
+  } else {
+    c = 38;
+  }
+  return c;
+}
+
 testSwitch1() {
   var a = null;
   switch (topLevelGetter) {
@@ -266,8 +284,57 @@
   return b;
 }
 
+testContinue1() {
+  var a = 42;
+  var b;
+  while (true) {
+    b = a + 54;
+    if (b == 42) continue;
+    a = 'foo';
+  }
+  return b;
+}
+
+testBreak1() {
+  var a = 42;
+  var b;
+  while (true) {
+    b = a + 54;
+    if (b == 42) break;
+    b = 'foo';
+  }
+  return b;
+}
+
+testContinue2() {
+  var a = 42;
+  var b;
+  while (true) {
+    b = a + 54;
+    if (b == 42) {
+      b = 'foo';
+      continue;
+    }
+  }
+  return b;
+}
+
+testBreak2() {
+  var a = 42;
+  var b;
+  while (true) {
+    b = a + 54;
+    if (b == 42) {
+      a = 'foo';
+      break;
+    }
+  }
+  return b;
+}
+
 get topLevelGetter => 42;
 returnDynamic() => topLevelGetter(42);
+returnTopLevelGetter() => topLevelGetter;
 
 class A {
   factory A() = A.generative;
@@ -296,6 +363,7 @@
   returnInt6() => super.myField += 4;
   returnInt7() => ++super[0];
   returnInt8() => super[0] += 54;
+  returnInt9() => super.myField;
 }
 
 main() {
@@ -337,9 +405,16 @@
   returnAsString();
   returnIntAsNum();
   returnAsTypedef();
+  returnTopLevelGetter();
+  testDeadCode();
+  testLabeledIf();
   testSwitch1();
   testSwitch2();
   testSwitch3();
+  testContinue1();
+  testBreak1();
+  testContinue2();
+  testBreak2();
   new A() == null;
   new A()..returnInt1()
          ..returnInt2()
@@ -355,7 +430,8 @@
          ..returnInt5()
          ..returnInt6()
          ..returnInt7()
-         ..returnInt8();
+         ..returnInt8()
+         ..returnInt9();
 }
 """;
 
@@ -367,7 +443,10 @@
 
   checkReturn(String name, type) {
     var element = findElement(compiler, name);
-    Expect.equals(type, typesInferrer.internal.returnTypeOf[element], name);
+    Expect.equals(
+        type,
+        typesInferrer.internal.returnTypeOf[element].simplify(compiler),
+        name);
   }
   var interceptorType =
       findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
@@ -412,15 +491,23 @@
       new TypeMask.subtype(compiler.stringClass.computeType(compiler)));
   checkReturn('returnIntAsNum', typesInferrer.intType);
   checkReturn('returnAsTypedef', typesInferrer.functionType.nullable());
-  checkReturn('testSwitch1',
-    typesInferrer.intType.union(typesInferrer.doubleType, compiler).nullable());
+  checkReturn('returnTopLevelGetter', typesInferrer.intType);
+  checkReturn('testDeadCode', typesInferrer.intType);
+  checkReturn('testLabeledIf', typesInferrer.intType.nullable());
+  checkReturn('testSwitch1', typesInferrer.intType
+      .union(typesInferrer.doubleType, compiler).nullable().simplify(compiler));
   checkReturn('testSwitch2', typesInferrer.intType);
   checkReturn('testSwitch3', interceptorType.nullable());
+  checkReturn('testContinue1', interceptorType.nullable());
+  checkReturn('testBreak1', interceptorType.nullable());
+  checkReturn('testContinue2', interceptorType.nullable());
+  checkReturn('testBreak2', typesInferrer.intType.nullable());
 
   checkReturnInClass(String className, String methodName, type) {
     var cls = findElement(compiler, className);
     var element = cls.lookupLocalMember(buildSourceString(methodName));
-    Expect.equals(type, typesInferrer.internal.returnTypeOf[element]);
+    Expect.equals(type,
+        typesInferrer.internal.returnTypeOf[element].simplify(compiler));
   }
 
   checkReturnInClass('A', 'returnInt1', typesInferrer.intType);
@@ -439,6 +526,7 @@
   checkReturnInClass('B', 'returnInt6', typesInferrer.intType);
   checkReturnInClass('B', 'returnInt7', typesInferrer.intType);
   checkReturnInClass('B', 'returnInt8', typesInferrer.intType);
+  checkReturnInClass('B', 'returnInt9', typesInferrer.intType);
 
   checkFactoryConstructor(String className) {
     var cls = findElement(compiler, className);
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
index a080d4d..2b6ebef 100644
--- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -161,7 +161,8 @@
 
   checkReturn(String name, type) {
     var element = findElement(compiler, name);
-    Expect.equals(type, typesInferrer.internal.returnTypeOf[element]);
+    Expect.equals(type,
+        typesInferrer.internal.returnTypeOf[element].simplify(compiler));
   }
 
   checkReturn('returnInt1', typesInferrer.intType);
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 1381be8..6b813b0 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -3,14 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "package:expect/expect.dart";
+import '../../../sdk/lib/_internal/compiler/compiler.dart' as api;
 import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/tree/tree.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/util/util.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';
 import 'mock_compiler.dart';
 import 'parser_helper.dart';
 
 import '../../../sdk/lib/_internal/compiler/implementation/elements/modelx.dart'
-    show ElementX;
+    show ElementX, CompilationUnitElementX;
 
 import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
     hide SourceString;
@@ -38,7 +40,8 @@
                 // testNewExpression,
                 testConditionalExpression,
                 testIfStatement,
-                testThis];
+                testThis,
+                testOperatorsAssignability];
   for (Function test in tests) {
     setup();
     test();
@@ -111,19 +114,22 @@
     analyze("{ var i = 1 ${op} 2; }");
     analyze("{ var i = 1; i ${op}= 2; }");
     analyze("{ int i; var j = (i = true) ${op} 2; }",
-            MessageKind.NOT_ASSIGNABLE);
+            [MessageKind.NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
     analyze("{ int i; var j = 1 ${op} (i = true); }",
-            MessageKind.NOT_ASSIGNABLE);
+            [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
   }
   for (final op in ['-', '~']) {
     analyze("{ var i = ${op}1; }");
-    analyze("{ int i; var j = ${op}(i = true); }", MessageKind.NOT_ASSIGNABLE);
+    analyze("{ int i; var j = ${op}(i = true); }",
+        [MessageKind.NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
   }
   for (final op in ['++', '--']) {
     analyze("{ int i = 1; int j = i${op}; }");
     analyze("{ int i = 1; bool j = i${op}; }", MessageKind.NOT_ASSIGNABLE);
-    analyze("{ bool b = true; bool j = b${op}; }");
-    analyze("{ bool b = true; int j = ${op}b; }");
+    analyze("{ bool b = true; bool j = b${op}; }",
+        MessageKind.OPERATOR_NOT_FOUND);
+    analyze("{ bool b = true; int j = ${op}b; }",
+        MessageKind.OPERATOR_NOT_FOUND);
   }
   for (final op in ['||', '&&']) {
     analyze("{ bool b = (true ${op} false); }");
@@ -131,13 +137,21 @@
     analyze("{ bool b = (1 ${op} false); }", MessageKind.NOT_ASSIGNABLE);
     analyze("{ bool b = (true ${op} 2); }", MessageKind.NOT_ASSIGNABLE);
   }
-  for (final op in ['>', '<', '<=', '>=', '==', '!=']) {
+  for (final op in ['>', '<', '<=', '>=']) {
     analyze("{ bool b = 1 ${op} 2; }");
     analyze("{ int i = 1 ${op} 2; }", MessageKind.NOT_ASSIGNABLE);
     analyze("{ int i; bool b = (i = true) ${op} 2; }",
-            MessageKind.NOT_ASSIGNABLE);
+            [MessageKind.NOT_ASSIGNABLE, MessageKind.OPERATOR_NOT_FOUND]);
     analyze("{ int i; bool b = 1 ${op} (i = true); }",
-            MessageKind.NOT_ASSIGNABLE);
+            [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+  }
+  for (final op in ['==', '!=']) {
+    analyze("{ bool b = 1 ${op} 2; }");
+    analyze("{ int i = 1 ${op} 2; }", MessageKind.NOT_ASSIGNABLE);
+    analyze("{ int i; bool b = (i = true) ${op} 2; }",
+        MessageKind.NOT_ASSIGNABLE);
+    analyze("{ int i; bool b = 1 ${op} (i = true); }",
+        MessageKind.NOT_ASSIGNABLE);
   }
 }
 
@@ -495,6 +509,281 @@
   analyzeIn(foo, "{ Foo f = this; }");
 }
 
+const String CLASSES_WITH_OPERATORS = '''
+class Operators {
+  Operators operator +(Operators other) => this;
+  Operators operator -(Operators other) => this;
+  Operators operator -() => this;
+  Operators operator *(Operators other) => this;
+  Operators operator /(Operators other) => this;
+  Operators operator %(Operators other) => this;
+  Operators operator ~/(Operators other) => this;
+
+  Operators operator &(Operators other) => this;
+  Operators operator |(Operators other) => this;
+  Operators operator ^(Operators other) => this;
+
+  Operators operator ~() => this;
+
+  Operators operator <(Operators other) => true;
+  Operators operator >(Operators other) => false;
+  Operators operator <=(Operators other) => this;
+  Operators operator >=(Operators other) => this;
+
+  Operators operator <<(Operators other) => this;
+  Operators operator >>(Operators other) => this;
+
+  bool operator ==(Operators other) => true;
+
+  Operators operator [](Operators key) => this;
+  void operator []=(Operators key, Operators value) {}
+}
+
+class MismatchA {
+  int operator+(MismatchA other) => 0;
+  MismatchA operator-(int other) => this;
+
+  MismatchA operator[](int key) => this;
+  void operator[]=(int key, MismatchA value) {}
+}
+
+class MismatchB {
+  MismatchB operator+(MismatchB other) => this;
+
+  MismatchB operator[](int key) => this;
+  void operator[]=(String key, MismatchB value) {}
+}
+
+class MismatchC {
+  MismatchC operator+(MismatchC other) => this;
+
+  MismatchC operator[](int key) => this;
+  void operator[]=(int key, String value) {}
+}
+''';
+
+testOperatorsAssignability() {
+  compiler.parseScript(CLASSES_WITH_OPERATORS);
+
+  // Tests against Operators.
+
+  String header = """{
+      bool z;
+      Operators a;
+      Operators b;
+      Operators c;
+      """;
+
+  check(String text, [expectedWarnings]) {
+    analyze('$header $text }', expectedWarnings);
+  }
+
+  // Positive tests on operators.
+
+  check('c = a + b;');
+  check('c = a - b;');
+  check('c = -a;');
+  check('c = a * b;');
+  check('c = a / b;');
+  check('c = a % b;');
+  check('c = a ~/ b;');
+
+  check('c = a & b;');
+  check('c = a | b;');
+  check('c = a ^ b;');
+
+  check('c = ~a;');
+
+  check('c = a < b;');
+  check('c = a > b;');
+  check('c = a <= b;');
+  check('c = a >= b;');
+
+  check('c = a << b;');
+  check('c = a >> b;');
+
+  check('c = a[b];');
+
+  check('a[b] = c;');
+  check('a[b] += c;');
+  check('a[b] -= c;');
+  check('a[b] *= c;');
+  check('a[b] /= c;');
+  check('a[b] %= c;');
+  check('a[b] ~/= c;');
+  check('a[b] <<= c;');
+  check('a[b] >>= c;');
+  check('a[b] &= c;');
+  check('a[b] |= c;');
+  check('a[b] ^= c;');
+
+  check('a += b;');
+  check('a -= b;');
+  check('a *= b;');
+  check('a /= b;');
+  check('a %= b;');
+  check('a ~/= b;');
+
+  check('a <<= b;');
+  check('a >>= b;');
+
+  check('a &= b;');
+  check('a |= b;');
+  check('a ^= b;');
+
+  // Negative tests on operators.
+
+  // For the sake of brevity we misuse the terminology in comments:
+  //  'e1 is not assignable to e2' should be read as
+  //     'the type of e1 is not assignable to the type of e2', and
+  //  'e1 is not assignable to operator o on e2' should be read as
+  //     'the type of e1 is not assignable to the argument type of operator o
+  //      on e2'.
+
+  // `0` is not assignable to operator + on `a`.
+  check('c = a + 0;', MessageKind.NOT_ASSIGNABLE);
+  // `a + b` is not assignable to `z`.
+  check('z = a + b;', MessageKind.NOT_ASSIGNABLE);
+
+  // `-a` is not assignable to `z`.
+  check('z = -a;', MessageKind.NOT_ASSIGNABLE);
+
+  // `0` is not assignable to operator [] on `a`.
+  check('c = a[0];', MessageKind.NOT_ASSIGNABLE);
+  // `a[b]` is not assignable to `z`.
+  check('z = a[b];', MessageKind.NOT_ASSIGNABLE);
+
+  // `0` is not assignable to operator [] on `a`.
+  // Warning suppressed for `0` is not assignable to operator []= on `a`.
+  check('a[0] *= c;', MessageKind.NOT_ASSIGNABLE);
+  // `z` is not assignable to operator * on `a[0]`.
+  check('a[b] *= z;', MessageKind.NOT_ASSIGNABLE);
+
+  check('b = a++;', MessageKind.NOT_ASSIGNABLE);
+  check('b = ++a;', MessageKind.NOT_ASSIGNABLE);
+  check('b = a--;', MessageKind.NOT_ASSIGNABLE);
+  check('b = --a;', MessageKind.NOT_ASSIGNABLE);
+
+  check('c = a[b]++;', MessageKind.NOT_ASSIGNABLE);
+  check('c = ++a[b];', MessageKind.NOT_ASSIGNABLE);
+  check('c = a[b]--;', MessageKind.NOT_ASSIGNABLE);
+  check('c = --a[b];', MessageKind.NOT_ASSIGNABLE);
+
+  check('z = a == b;');
+  check('z = a != b;');
+
+  for (String o in ['&&', '||']) {
+    check('z = z $o z;');
+    check('z = a $o z;', MessageKind.NOT_ASSIGNABLE);
+    check('z = z $o b;', MessageKind.NOT_ASSIGNABLE);
+    check('z = a $o b;',
+        [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+    check('a = a $o b;',
+        [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE,
+         MessageKind.NOT_ASSIGNABLE]);
+  }
+
+  check('z = !z;');
+  check('z = !a;', MessageKind.NOT_ASSIGNABLE);
+  check('a = !z;', MessageKind.NOT_ASSIGNABLE);
+  check('a = !a;',
+      [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+
+
+  // Tests against MismatchA.
+
+  header = """{
+      MismatchA a;
+      MismatchA b;
+      MismatchA c;
+      """;
+
+  // Tests against int operator +(MismatchA other) => 0;
+
+  // `a + b` is not assignable to `c`.
+  check('c = a + b;', MessageKind.NOT_ASSIGNABLE);
+  // `a + b` is not assignable to `a`.
+  check('a += b;', MessageKind.NOT_ASSIGNABLE);
+  // `a[0] + b` is not assignable to `a[0]`.
+  check('a[0] += b;', MessageKind.NOT_ASSIGNABLE);
+
+  // 1 is not applicable to operator +.
+  check('b = a++;', MessageKind.NOT_ASSIGNABLE);
+  // 1 is not applicable to operator +.
+  // `++a` of type int is not assignable to `b`.
+  check('b = ++a;',
+      [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+
+  // 1 is not applicable to operator +.
+  check('b = a[0]++;', MessageKind.NOT_ASSIGNABLE);
+  // 1 is not applicable to operator +.
+  // `++a[0]` of type int is not assignable to `b`.
+  check('b = ++a[0];',
+      [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+
+  // Tests against: MismatchA operator -(int other) => this;
+
+  // `a - b` is not assignable to `c`.
+  check('c = a + b;', MessageKind.NOT_ASSIGNABLE);
+  // `a - b` is not assignable to `a`.
+  check('a += b;', MessageKind.NOT_ASSIGNABLE);
+  // `a[0] - b` is not assignable to `a[0]`.
+  check('a[0] += b;', MessageKind.NOT_ASSIGNABLE);
+
+  check('b = a--;');
+  check('b = --a;');
+
+  check('b = a[0]--;');
+  check('b = --a[0];');
+
+  // Tests against MismatchB.
+
+  header = """{
+      MismatchB a;
+      MismatchB b;
+      MismatchB c;
+      """;
+
+  // Tests against:
+  // MismatchB operator [](int key) => this;
+  // void operator []=(String key, MismatchB value) {}
+
+  // `0` is not applicable to operator []= on `a`.
+  check('a[0] = b;', MessageKind.NOT_ASSIGNABLE);
+
+  // `0` is not applicable to operator []= on `a`.
+  check('a[0] += b;', MessageKind.NOT_ASSIGNABLE);
+  // `""` is not applicable to operator [] on `a`.
+  check('a[""] += b;', MessageKind.NOT_ASSIGNABLE);
+  // `c` is not applicable to operator [] on `a`.
+  // `c` is not applicable to operator []= on `a`.
+  check('a[c] += b;',
+      [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+
+
+  // Tests against MismatchB.
+
+  header = """{
+      MismatchC a;
+      MismatchC b;
+      MismatchC c;
+      """;
+
+  // Tests against:
+  // MismatchC operator[](int key) => this;
+  // void operator[]=(int key, String value) {}
+
+  // `b` is not assignable to `a[0]`.
+  check('a[0] += b;', MessageKind.NOT_ASSIGNABLE);
+  // `0` is not applicable to operator + on `a[0]`.
+  check('a[0] += "";',
+      [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+  // `true` is not applicable to operator + on `a[0]`.
+  // `true` is not assignable to `a[0]`.
+  check('a[0] += true;',
+      [MessageKind.NOT_ASSIGNABLE, MessageKind.NOT_ASSIGNABLE]);
+}
+
 const CLASS_WITH_METHODS = '''
 class ClassWithMethods {
   untypedNoArgumentMethod() {}
@@ -531,8 +820,45 @@
 Node parseExpression(String text) =>
   parseBodyCode(text, (parser, token) => parser.parseExpression(token));
 
+const String NUM_SOURCE = '''
+abstract class num {
+  num operator +(num other);
+  num operator -(num other);
+  num operator *(num other);
+  num operator %(num other);
+  double operator /(num other);
+  int operator ~/(num other);
+  num operator -();
+  bool operator <(num other);
+  bool operator <=(num other);
+  bool operator >(num other);
+  bool operator >=(num other);
+}
+''';
+
+const String INT_SOURCE = '''
+abstract class int extends num {
+  int operator &(int other);
+  int operator |(int other);
+  int operator ^(int other);
+  int operator ~();
+  int operator <<(int shiftAmount);
+  int operator >>(int shiftAmount);
+  int operator -();
+}
+''';
+
 void setup() {
-  compiler = new MockCompiler();
+  RegExp classNum = new RegExp(r'abstract class num {}');
+  Expect.isTrue(DEFAULT_CORELIB.contains(classNum));
+  RegExp classInt = new RegExp(r'abstract class int extends num { }');
+  Expect.isTrue(DEFAULT_CORELIB.contains(classInt));
+
+  String CORE_SOURCE = DEFAULT_CORELIB
+      .replaceAll(classNum, NUM_SOURCE)
+      .replaceAll(classInt, INT_SOURCE);
+
+  compiler = new MockCompiler(coreSource: CORE_SOURCE);
   types = compiler.types;
   voidType = compiler.types.voidType;
   intType = compiler.intClass.computeType(compiler);
@@ -570,23 +896,56 @@
   }
 }
 
+api.DiagnosticHandler createHandler(String text) {
+  return (uri, int begin, int end, String message, kind) {
+    SourceFile sourceFile;
+    if (uri == null) {
+      sourceFile = new SourceFile('analysis', text);
+    } else {
+      sourceFile = compiler.sourceFiles[uri.toString()];
+    }
+    if (sourceFile != null) {
+      print(sourceFile.getLocationMessage(message, begin, end, true, (x) => x));
+    } else {
+      print(message);
+    }
+  };
+}
+
 analyze(String text, [expectedWarnings]) {
   if (expectedWarnings == null) expectedWarnings = [];
   if (expectedWarnings is !List) expectedWarnings = [expectedWarnings];
 
+  compiler.diagnosticHandler = createHandler(text);
+
   Token tokens = scan(text);
   NodeListener listener = new NodeListener(compiler, null);
   Parser parser = new Parser(listener);
   parser.parseStatement(tokens);
   Node node = listener.popNode();
+  Element compilationUnit =
+    new CompilationUnitElementX(new Script(null, null), compiler.mainApp);
   Element function = new ElementX(
-      buildSourceString(''), ElementKind.FUNCTION, compiler.mainApp);
+      buildSourceString(''), ElementKind.FUNCTION, compilationUnit);
   TreeElements elements = compiler.resolveNodeStatement(node, function);
   TypeCheckerVisitor checker = new TypeCheckerVisitor(compiler, elements,
                                                                 types);
   compiler.clearWarnings();
   checker.analyze(node);
   compareWarningKinds(text, expectedWarnings, compiler.warnings);
+  compiler.diagnosticHandler = null;
+}
+
+void generateOutput(String text) {
+  for (WarningMessage message in compiler.warnings) {
+    var beginToken = message.node.getBeginToken();
+    var endToken = message.node.getEndToken();
+    int begin = beginToken.charOffset;
+    int end = endToken.charOffset + endToken.slowCharCount;
+    SourceFile sourceFile = new SourceFile('analysis', text);
+    print(sourceFile.getLocationMessage(message.message.toString(),
+                                        begin, end, true, (str) => str));
+  }
 }
 
 analyzeIn(ClassElement classElement, String text, [expectedWarnings]) {
@@ -603,7 +962,7 @@
   TypeCheckerVisitor checker = new TypeCheckerVisitor(compiler, elements,
                                                                 types);
   compiler.clearWarnings();
-  checker.currentClass = classElement;
   checker.analyze(node);
+  generateOutput(text);
   compareWarningKinds(text, expectedWarnings, compiler.warnings);
 }
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index 8a23071..3fea40e 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -96,7 +96,8 @@
 }
 
 void testUnion(MockCompiler compiler) {
-  RuleSet ruleSet = new RuleSet('union', (t1, t2) => t1.union(t2, compiler));
+  RuleSet ruleSet = new RuleSet('union',
+      (t1, t2) => t1.union(t2, compiler).simplify(compiler));
   rule(type1, type2, result) => ruleSet.rule(type1, type2, result);
   check(type1, type2, predicate) => ruleSet.check(type1, type2, predicate);
 
diff --git a/tests/compiler/dart2js_extra/factory_test.dart b/tests/compiler/dart2js_extra/factory_test.dart
deleted file mode 100644
index 0d3e59b..0000000
--- a/tests/compiler/dart2js_extra/factory_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-
-class A {
-  factory A() {
-    return 1;
-  }
-}
-
-main() {
-  Expect.equals(1, new A());
-}
diff --git a/tests/compiler/dart2js_extra/type_error_message_test.dart b/tests/compiler/dart2js_extra/type_error_message_test.dart
new file mode 100644
index 0000000..220550b
--- /dev/null
+++ b/tests/compiler/dart2js_extra/type_error_message_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.
+
+import 'package:expect/expect.dart';
+
+class C<T, S> {}
+
+bool inCheckedMode() {
+  try {
+    int i = 'hest';
+  } catch (e) {
+    return true;
+  }
+  return false;
+}
+
+main() {
+  if (inCheckedMode()) {
+    bool caught = false;
+    try {
+      C<String, String> x = new C<C<int, String>, String>();
+    } catch (e) {
+      String expected = 'C<C<int, String>, String>';
+      Expect.isTrue(e.toString().contains(expected),
+                    'Expected "$expected" in the message');
+      caught = true;
+    }
+    Expect.isTrue(caught);
+  }
+}
diff --git a/tests/compiler/dart2js_native/native_exception2_test.dart b/tests/compiler/dart2js_native/native_exception2_test.dart
new file mode 100644
index 0000000..6f26332
--- /dev/null
+++ b/tests/compiler/dart2js_native/native_exception2_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.
+
+// Similar to native_exception_test.dart but also defines a native
+// class.  This exercises a different code path in emitter.dart.
+
+library native_exception2_test;
+
+import 'native_exception_test.dart' as other;
+
+class NativeClass native "NativeClass" {
+}
+
+makeNativeClass() native;
+
+setup() native """
+function NativeClass() {}
+makeNativeClass = function() { return new NativeClass; }
+""";
+
+main() {
+  setup();
+  other.main();
+}
diff --git a/tests/compiler/dart2js_native/native_exception_test.dart b/tests/compiler/dart2js_native/native_exception_test.dart
new file mode 100644
index 0000000..9b1d346
--- /dev/null
+++ b/tests/compiler/dart2js_native/native_exception_test.dart
@@ -0,0 +1,34 @@
+// 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 dart2js can handle unexpected exception types.
+
+library native_exception_test;
+
+import 'dart:_foreign_helper' show JS;
+
+import "package:expect/expect.dart";
+
+main() {
+  var previous;
+  check(e) {
+    print('$e');
+    Expect.equals(e, e);
+    Expect.notEquals(e, new Object());
+    Expect.notEquals(e, previous);
+    previous = e;
+    return '$e' != '[object Object]';
+  }
+  Expect.throws(() { JS('void', 'noGlobalVariableWithThisName'); }, check);
+  Expect.throws(() { JS('void', 'throw 3'); }, check);
+  Expect.throws(
+      () {
+        JS('bool', 'Object.prototype.hasOwnProperty.call(undefined, "foo")');
+      },
+      check);
+  Expect.throws(() { JS('void', 'throw new ReferenceError()'); }, check);
+  Expect.throws(() { JS('void', 'throw void 0'); }, check);
+  Expect.throws(() { JS('void', 'throw "a string"'); }, check);
+  Expect.throws(() { JS('void', 'throw null'); }, check);
+}
diff --git a/tests/corelib/string_trim2_test.dart b/tests/corelib/string_trim2_test.dart
new file mode 100644
index 0000000..0f0ccab
--- /dev/null
+++ b/tests/corelib/string_trim2_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// TODO(floitsch): Test 0x85 when dart2js supports it.
+const WHITESPACE = const [
+  9,
+  10,
+  11,
+  12,
+  13,
+  0x20,
+  0xA0,
+  0x1680,
+  0x180E,
+  0x2000,
+  0x2001,
+  0x2002,
+  0x2003,
+  0x2004,
+  0x2005,
+  0x2006,
+  0x2007,
+  0x2008,
+  0x2009,
+  0x200A,
+  0x202F,
+  0x205F,
+  0x3000,
+  0x2028,
+  0x2029,
+  0xFEFF,
+];
+
+main() {
+  for (var ws in WHITESPACE) {
+    Expect.equals("", new String.fromCharCode(ws).trim());
+  }
+  Expect.equals("", new String.fromCharCodes(WHITESPACE).trim());
+  for (var ws in WHITESPACE) {
+    var c = new String.fromCharCode(ws);
+    Expect.equals("a", ("a" + c).trim());
+    Expect.equals("a", (c + "a").trim());
+    Expect.equals("a", (c + c + "a" + c + c).trim());
+  }
+}
diff --git a/tests/html/html.status b/tests/html/html.status
index 409328c..255b99c 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -4,7 +4,6 @@
 
 window_open_test: Skip # http://dartbug.com/5151
 async_window_test: Skip #TODO(gram): investigating
-svg_test: Skip #TODO(vsm): investigating
 
 event_test: Skip  # Issue 1996
 custom_elements_test: Skip # Not yet implemented.
@@ -13,6 +12,7 @@
 [ $compiler == none && ($runtime == drt || $runtime == dartium) ]
 # postMessage in dartium always transfers the typed array buffer, never a view
 postmessage_structured_test/typed_arrays: Fail
+custom_element_bindings_test: Fail # To investigate.
 
 [ $compiler == none && $runtime == drt && $system == windows ]
 worker_test/functional: Pass, Crash # Issue 9929.
@@ -28,9 +28,6 @@
 [ $compiler == dart2js && ( $runtime == ie9 || $runtime == ie10 ) ]
 worker_api_test: Fail # IE does not support URL.createObjectURL in web workers.
 
-[ $compiler == dart2js && ( $runtime == ff ) ]
-worker_api_test: Fail # Requires Firefox 21.
-
 [ $compiler == dart2js && $runtime == safari ]
 url_test: Fail # Issue 10096
 
@@ -187,7 +184,6 @@
 rtc_test/supported: Fail
 shadow_dom_test/supported: Fail
 speechrecognition_test/supported: Fail
-svg_test/supported_externalResourcesRequired: Fail
 svgelement_test/supported_altGlyph: Fail
 svgelement_test/supported_animate: Fail
 svgelement_test/supported_animateMotion: Fail
@@ -265,6 +261,9 @@
 speechrecognition_test/supported: Fail
 touchevent_test/supported: Fail
 
+[ $runtime == ie9 && $checked ]
+element_types_test/constructors: Fail # Issue 10796
+
 [ $runtime == opera ]
 blob_constructor_test: Fail
 canvas_test: Fail
@@ -306,8 +305,6 @@
 notifications_test/supported: Fail
 performance_api_test/supported: Fail
 speechrecognition_test/supported: Fail
-svg_test/supported_externalResourcesRequired: Fail
-svg_test/supported_langSpace: Fail
 websql_test/supported: Fail
 
 [ $runtime == ff ]
@@ -320,7 +317,6 @@
 # All changes should be accompanied by platform support annotation changes.
 audiobuffersourcenode_test/supported: Fail
 audiocontext_test/supported: Fail
-crypto_test/supported: Fail
 css_test/supportsPointConversions: Fail
 document_test/supports_cssCanvasContext: Fail
 element_types_test/supported_content: Fail
@@ -346,8 +342,6 @@
 rtc_test/supported: Fail # Release build does not enable by default.
 shadow_dom_test/supported: Fail
 speechrecognition_test/supported: Fail
-svg_test/supported_externalResourcesRequired: Fail
-svg_test/supported_langSpace: Fail
 touchevent_test/supported: Fail
 websql_test/supported: Fail
 xhr_test/supported_HttpRequestProgressEvent: Fail
diff --git a/tests/html/svg_test.dart b/tests/html/svg_test.dart
index 156f379..db31807 100644
--- a/tests/html/svg_test.dart
+++ b/tests/html/svg_test.dart
@@ -68,15 +68,6 @@
     var isSvgSvgElement =
         predicate((x) => x is svg.SvgSvgElement, 'is a SvgSvgElement');
     var isNode = predicate((x) => x is Node, 'is a Node');
-    var isSvgTests = predicate((x) => x is svg.Tests, 'is a svg.Tests');
-    var isSvgLangSpace = predicate((x) => x is svg.LangSpace, 'is a svg.LangSpace');
-    var isSvgExternalResourcesRequired =
-        predicate((x) => x is svg.ExternalResourcesRequired,
-            'is a svg.ExternalResourcesRequired');
-    var isSvgTransformable =
-        predicate((x) => x is svg.Transformable, 'is a svg.Transformable');
-    var isSvgLocatable =
-        predicate((x) => x is svg.Locatable, 'is a svg.Locatable');
     var isSvgNumber = predicate((x) => x is svg.Number, 'is a svg.Number');
     var isSvgRect = predicate((x) => x is svg.Rect, 'is a svg.Rect');
 
@@ -89,13 +80,6 @@
         expect(r, isElement);
         expect(r, isNode);
 
-        // Other implemented interfaces.
-        expect(r, isSvgTests);
-        expect(r, isSvgLangSpace);
-        expect(r, isSvgExternalResourcesRequired);
-        expect(r, isSvgTransformable);
-        expect(r, isSvgLocatable);
-
         // Interfaces not implemented.
         expect(r, isNot(isSvgNumber));
         expect(r, isNot(isSvgRect));
@@ -116,24 +100,6 @@
     return element;
   }
 
-  group('supported_externalResourcesRequired', () {
-    test('supported', () {
-      var div = insertTestDiv();
-      var r = document.query('#rect1');
-      expect(svg.ExternalResourcesRequired.supported(r), true);
-      div.remove();
-    });
-  });
-
-  group('supported_langSpace', () {
-    test('supported', () {
-      var div = insertTestDiv();
-      var r = document.query('#rect1');
-      expect(svg.LangSpace.supported(r), true);
-      div.remove();
-    });
-  });
-
   group('svgBehavioral', () {
 
     // Test that SVG elements have the operations advertised through all the IDL
@@ -154,47 +120,6 @@
     var isCssStyleDeclaration =
         predicate((x) => x is CssStyleDeclaration, 'is a CssStyleDeclaration');
 
-    /// Verifies that [e] supports the operations on the svg.Tests interface.
-    checkSvgTests(e) {
-      // Just check that the operations seem to exist.
-      var rx = e.requiredExtensions;
-      expect(rx, isStringList);
-      var rf = e.requiredFeatures;
-      expect(rf, isStringList);
-      var sl = e.systemLanguage;
-      expect(sl, isStringList);
-
-      bool hasDoDo = e.hasExtension("DoDo");
-      expect(hasDoDo, isFalse);
-    }
-
-    /// Verifies that [e] supports the operations on the svg.Locatable interface.
-    checkSvgLocatable(e) {
-      var v1 = e.farthestViewportElement;
-      var v2 = e.nearestViewportElement;
-      expect(v1, same(v2));
-
-      var bbox = e.getBBox();
-      expect(bbox, isSvgRect);
-
-      var ctm = e.getCtm();
-      expect(ctm, isSvgMatrix);
-
-      var sctm = e.getScreenCtm();
-      expect(sctm, isSvgMatrix);
-
-      var xf2e = e.getTransformToElement(e);
-      expect(xf2e, isSvgMatrix);
-    }
-
-    /**
-     * Verifies that [e] supports the operations on the svg.Transformable
-     * interface.
-     */
-    checkSvgTransformable(e) {
-      var trans = e.transform;
-      expect(trans, isSvgAnimatedTransformList);
-    }
 
     testRect(name, checker) {
       test(name, () {
@@ -204,43 +129,6 @@
         div.remove();
       });
     }
-
-    /**
-     * Verifies that [e] supports the operations on the svg.LangSpace interface.
-     */
-    checkSvgLangSpace(e) {
-      if (svg.LangSpace.supported(e)) {
-        // Just check that the attributes seem to exist.
-        var lang = e.xmllang;
-        e.xmllang = lang;
-
-        String space = e.xmlspace;
-        e.xmlspace = space;
-
-        expect(lang, isString);
-        expect(space, isString);
-      }
-    }
-
-    /**
-     * Verifies that [e] supports the operations on the
-     * svg.ExternalResourcesRequired interface.
-     */
-    checkSvgExternalResourcesRequired(e) {
-      if (svg.ExternalResourcesRequired.supported(e)) {
-        var b = e.externalResourcesRequired;
-        expect(b, isSvgAnimatedBoolean);
-        expect(b.baseVal, isFalse);
-        expect(b.animVal, isFalse);
-      }
-    }
-
-    testRect('rect_SvgTests', checkSvgTests);
-    testRect('rect_SvgLangSpace', checkSvgLangSpace);
-    testRect('rect_SvgExternalResourcesRequired',
-             checkSvgExternalResourcesRequired);
-    testRect('rect_SvgLocatable', checkSvgLocatable);
-    testRect('rect_SvgTransformable', checkSvgTransformable);
   });
 
 }
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 8b8934f..6368aad 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -40,7 +40,6 @@
 
 [ $compiler == dartanalyzer ]
 isolate2_negative_test: fail
-isolate3_negative_test: fail
 isolate_import_negative_test: fail
 isolate_negative_test: fail
 spawn_function_negative_test: fail
diff --git a/tests/language/factory_return_type_checked_test.dart b/tests/language/factory_return_type_checked_test.dart
new file mode 100644
index 0000000..dc46145
--- /dev/null
+++ b/tests/language/factory_return_type_checked_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A {
+  factory A() => 42;
+}
+
+main() {
+  bool isCheckedMode = false;
+  try {
+    String a = 42;
+  } catch (e) {
+    isCheckedMode = true;
+  }
+  if (isCheckedMode) {
+    Expect.throws(() => new A(), (e) => e is TypeError);
+  } else {
+    Expect.equals(42, new A());
+  }
+}
diff --git a/tests/language/generic_list_checked_test.dart b/tests/language/generic_list_checked_test.dart
new file mode 100644
index 0000000..fcff24b
--- /dev/null
+++ b/tests/language/generic_list_checked_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+bool inCheckedMode() {
+  try {
+    int i = 'hest';
+  } catch (e) {
+    return true;
+  }
+  return false;
+}
+
+main() {
+  if (inCheckedMode()) {
+    Expect.throws(() { List<int> t = new List<String>(); });
+  }
+}
diff --git a/tests/language/inferrer_constructor_test.dart b/tests/language/inferrer_constructor_test.dart
new file mode 100644
index 0000000..38b97da
--- /dev/null
+++ b/tests/language/inferrer_constructor_test.dart
@@ -0,0 +1,24 @@
+// 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 dart2js type inferrer detects dead code.
+
+import "package:expect/expect.dart";
+
+class A {
+  var field;
+  A(test) {
+    if (test) {
+      return;
+      field = 42;
+    } else {
+      field = 54;
+    }
+  }
+}
+
+main() {
+  var a = new A(true);
+  Expect.throws(() => a.field + 42, (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/issue10561_test.dart b/tests/language/issue10561_test.dart
new file mode 100644
index 0000000..d02e157
--- /dev/null
+++ b/tests/language/issue10561_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js that used to miscompile classes
+// extending HashMap, because HashMap is patched.
+
+import "package:expect/expect.dart";
+
+import 'dart:collection';
+
+class Foo extends HashMap {
+}
+
+main() {
+  Expect.equals(0, new Foo().length);
+}
diff --git a/tests/language/issue10721_test.dart b/tests/language/issue10721_test.dart
new file mode 100644
index 0000000..4bad7a0
--- /dev/null
+++ b/tests/language/issue10721_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+void main() {
+  Expect.equals('', useParameterInClosure(1));
+  Expect.equals(43, updateParameterInClosure(1)());
+}
+
+String useParameterInClosure(arg1, {int arg2}) {
+  if (arg1 is Map) {
+    return arg1.keys.map((key) => arg1[key]).first;
+  } else {
+    return '';
+  }
+}
+
+Function updateParameterInClosure(arg1) {
+  if (arg1 is Map) {
+    return () => arg1 = 42;
+  } else {
+    return () => arg1 = arg1 + 42;
+  }
+}
diff --git a/tests/language/issue10747_test.dart b/tests/language/issue10747_test.dart
new file mode 100644
index 0000000..fda6c49
--- /dev/null
+++ b/tests/language/issue10747_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.
+
+import "package:expect/expect.dart";
+
+class B<T> {
+}
+
+class A<T> {
+  var field;
+  A(this.field);
+  asTypeVariable() => field as T;
+  asBOfT() => field as B<T>;
+}
+
+main() {
+  Expect.equals(42, new A<int>(42).asTypeVariable());
+  Expect.throws(
+      () => new A<String>(42).asTypeVariable(),
+      (e) => e is CastError);
+
+  var b = new B<int>();
+  Expect.equals(b, new A<int>(b).asBOfT());
+  Expect.throws(
+      () => new A<String>(b).asBOfT(),
+      (e) => e is CastError);
+}
diff --git a/tests/language/issue10783_test.dart b/tests/language/issue10783_test.dart
new file mode 100644
index 0000000..c603f81
--- /dev/null
+++ b/tests/language/issue10783_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C {
+  foo(int y) { return y; }
+}
+
+main() {
+  for (var b in [[false, 'pig']]) {
+    var c;
+    if (b[0]) c = new C();
+    Expect.throws(() => print(c.foo(b[1])), (e) => e is NoSuchMethodError);
+  }
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index e7a5d61..a1fbeef 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -556,11 +556,6 @@
 [ $compiler == dartanalyzer ]
 abstract_factory_constructor_test/00: fail
 assign_instance_method_negative_test: fail
-assign_static_type_test/01: fail
-assign_static_type_test/02: fail
-assign_static_type_test/03: fail
-assign_static_type_test/04: fail
-assign_static_type_test/05: fail
 assign_static_type_test/06: fail
 bad_named_parameters2_test: fail
 bad_named_parameters_test: fail
@@ -576,21 +571,13 @@
 call_constructor_on_unresolvable_class_test/02: fail
 call_constructor_on_unresolvable_class_test/03: fail
 call_constructor_on_unresolvable_class_test/07: fail
-call_non_method_field_test/01: fail
-call_non_method_field_test/02: fail
-call_nonexistent_static_test/01: fail
-call_nonexistent_static_test/02: fail
-call_nonexistent_static_test/03: fail
 call_nonexistent_static_test/04: fail
-call_nonexistent_static_test/05: fail
 call_nonexistent_static_test/06: fail
 call_nonexistent_static_test/07: fail
-call_nonexistent_static_test/08: fail
 call_nonexistent_static_test/09: fail
 call_nonexistent_static_test/10: fail
 call_through_getter_test: fail
-callable_test/00: fail
-callable_test/01: fail
+callable_test/none: fail
 cast_test/04: fail
 cast_test/05: fail
 class_cycle_negative_test: fail
@@ -613,6 +600,7 @@
 class_literal_test/27: fail
 class_literal_test/28: fail
 class_literal_test/29: fail
+class_literal_test/none: fail
 closure_call_wrong_argument_count_negative_test: fail
 compile_time_constant10_test/none: fail
 compile_time_constant8_test: fail
@@ -623,6 +611,8 @@
 compile_time_constant_arguments_test/05: fail
 compile_time_constant_arguments_test/06: fail
 compile_time_constant_b_test: fail
+compile_time_constant_c_test/01: fail
+compile_time_constant_c_test/02: fail
 compile_time_constant_checked2_test/01: fail
 compile_time_constant_checked2_test/02: fail
 compile_time_constant_checked2_test/03: fail
@@ -635,11 +625,6 @@
 compile_time_constant_checked3_test/04: fail
 compile_time_constant_checked3_test/05: fail
 compile_time_constant_checked3_test/06: fail
-compile_time_constant_checked_test/01: fail
-compile_time_constant_checked_test/02: fail
-compile_time_constant_checked_test/03: fail
-compile_time_constant_c_test/01: fail
-compile_time_constant_c_test/02: fail
 compile_time_constant_d_test: fail
 compile_time_constant_e_test: fail
 compile_time_constant_test/02: fail
@@ -649,9 +634,6 @@
 constructor3_negative_test: fail
 constructor_call_wrong_argument_count_negative_test: fail
 constructor_negative_test: fail
-constructor_redirect2_test/02: fail
-constructor_redirect2_test/04: fail
-constructor_redirect_test/01: fail
 constructor_return_with_arrow_negative_test: fail
 constructor_return_with_init_and_arrow_negative_test: fail
 cyclic_type_variable_test/01: fail
@@ -660,33 +642,20 @@
 cyclic_type_variable_test/04: fail
 default_factory2_test/01: fail
 default_implementation2_test: fail
-duplicate_constructor_test/01: fail
 dynamic2_test/00: fail
 dynamic_field_test: fail
 export_cyclic_test: fail
 f_bounded_quantification_test/01: fail
 f_bounded_quantification_test/02: fail
-factory1_test/00: skip
-factory1_test/01: skip
 factory2_test: fail
 factory5_test/00: fail
-factory_implementation_test/00: skip
+factory_implementation_test/none: fail
 factory_redirection2_test/01: fail
 factory_redirection_test/07: fail
-factory_redirection_test/08: skip
-factory_redirection_test/09: skip
-factory_redirection_test/10: skip
-factory_redirection_test/11: skip
-factory_redirection_test/12: skip
-factory_redirection_test/13: skip
-factory_redirection_test/14: skip
 fauxverride_test/03: fail
 fauxverride_test/05: fail
 field_method4_negative_test: fail
 field_override_test/01: fail
-field_override_test/02: fail
-field_type_check_test/01: fail
-field_type_check2_test/01: skip
 final_for_in_variable_test/01: fail
 final_param_negative_test: fail
 final_var_negative_test: fail
@@ -704,10 +673,7 @@
 getter_no_setter_test/00: fail
 getter_no_setter_test/01: fail
 getters_setters2_test/01: fail
-getters_setters2_test/02: fail
-getters_setters2_test/03: skip
 getters_setters_type_test/01: fail
-implicit_scope_test: fail
 implicit_this_test/01: fail
 implicit_this_test/04: fail
 implicit_this_test/none: fail
@@ -725,14 +691,12 @@
 interface_test/00: fail
 internal_library_test/01: fail
 is_not_class2_negative_test: fail
-issue1363_test: fail
 library_juxtaposition_test: fail
 licm_test: fail
 list_literal1_negative_test: fail
 list_literal_syntax_test/01: fail
 list_literal_syntax_test/02: fail
 list_literal_syntax_test/03: fail
-list_literal_syntax_test/05: fail
 map_literal1_negative_test: fail
 map_literal3_test: fail
 method_override2_test/03: fail
@@ -754,11 +718,10 @@
 named_parameters_aggregated_test/03: fail
 named_parameters_aggregated_test/04: fail
 named_parameters_aggregated_test/05: fail
-named_parameters_type_test: fail
-nested_switch_label_test: fail
 new_expression_type_args_test/00: fail
 new_expression_type_args_test/01: fail
 new_expression_type_args_test/02: fail
+nested_switch_label_test: fail
 no_such_method_negative_test: fail
 non_const_super_negative_test: fail
 number_identifier_negative_test: fail
@@ -771,8 +734,6 @@
 override_field_test/03: fail
 override_method_with_field_test/01: fail
 override_method_with_field_test/02: fail
-parameter_initializer5_negative_test: fail
-positional_parameters_type_test: fail
 prefix10_negative_test: fail
 prefix11_negative_test: fail
 prefix12_negative_test: fail
@@ -798,42 +759,12 @@
 static_call_wrong_argument_count_negative_test: fail
 static_field3_test/01: fail
 static_field3_test/02: fail
-static_field3_test/03: fail
 static_field3_test/04: fail
 static_field_test/01: fail
 static_field_test/02: fail
 static_field_test/03: fail
-static_field_test/04: fail
 static_final_field2_negative_test: fail
 static_final_field_negative_test: fail
-string_interpolate1_negative_test: fail
-string_interpolate2_negative_test: fail
-string_interpolation2_negative_test: fail
-string_interpolation3_negative_test: fail
-string_interpolation4_negative_test: fail
-string_interpolation5_negative_test: fail
-string_interpolation6_negative_test: fail
-string_interpolation9_test/10: fail
-string_interpolation9_test/11: fail
-string_interpolation9_test/12: fail
-string_interpolation9_test/13: fail
-string_interpolation9_test/14: fail
-string_interpolation9_test/15: fail
-string_interpolation9_test/16: fail
-string_interpolation9_test/17: fail
-string_interpolation9_test/18: fail
-string_interpolation9_test/19: fail
-string_interpolation9_test/1: fail
-string_interpolation9_test/20: fail
-string_interpolation9_test/2: fail
-string_interpolation9_test/3: fail
-string_interpolation9_test/4: fail
-string_interpolation9_test/5: fail
-string_interpolation9_test/6: fail
-string_interpolation9_test/7: fail
-string_interpolation9_test/8: fail
-string_interpolation9_test/9: fail
-string_interpolation_test/01: fail
 super_operator_index_test/01: fail
 super_operator_index_test/02: fail
 super_operator_index_test/03: fail
@@ -865,26 +796,16 @@
 type_variable_bounds2_test/02: fail
 type_variable_bounds2_test/03: fail
 type_variable_bounds2_test/04: fail
-type_variable_bounds2_test/05: skip
 type_variable_bounds2_test/06: fail
-type_variable_bounds3_test/00: skip
 type_variable_bounds_test/00: fail
 type_variable_bounds_test/01: fail
 type_variable_bounds_test/02: fail
 type_variable_bounds_test/03: fail
 type_variable_bounds_test/04: fail
-type_variable_bounds_test/05: fail
 type_variable_bounds_test/06: fail
 type_variable_bounds_test/07: fail
 type_variable_bounds_test/09: fail
-type_variable_bounds_test/10: fail
 type_variable_identifier_expression_negative_test: fail
-type_variable_scope_test/00: skip
-type_variable_scope_test/01: skip
-type_variable_scope_test/02: skip
-type_variable_scope_test/03: skip
-type_variable_scope_test/04: skip
-type_variable_scope_test/05: skip
 type_variable_static_context_negative_test: fail
 typed_equality_test: fail
 unary2_test: fail
@@ -892,15 +813,13 @@
 unresolved_in_factory_negative_test: fail
 unresolved_top_level_method_negative_test: fail
 unresolved_top_level_var_negative_test: fail
-unsigned_right_shift_test/01: fail
-unsigned_right_shift_test/02: fail
-wrong_number_type_arguments_test/00: fail
-wrong_number_type_arguments_test/02: fail
 
 # test issue 10683, It is a compile-time error if e refers to the name v or the name v=.
 block_scope_test: fail
 lazy_static3_test: fail
 
+# test issue 10752, there are 'implicit' scopes for 'if', 'while' and 'do-while'
+implicit_scope_test: fail, OK
 
 [ $arch == arm ]
 *: Skip
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 1dfd21f..541b3c9 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -44,7 +44,6 @@
 prefix16_test: Fail # dartbug.com/7354
 default_factory2_test/01: Pass # For the wrong reasons.
 type_variable_scope_test/none: Fail
-factory_implementation_test/00: Fail
 redirecting_factory_infinite_steps_test/01: Fail
 type_variable_bounds_test/01: Fail
 type_variable_bounds_test/02: Fail
@@ -58,8 +57,6 @@
 f_bounded_quantification_test/01: Fail
 f_bounded_quantification_test/02: Fail
 closure_type_test: Fail # does not detect type error in checked mode.
-factory1_test/00: Fail
-factory1_test/01: Fail
 type_annotation_test/09: Fail # Named constructors interpreted as a type.
 prefix15_test: Fail # Issue 5022
 local_function2_test: Fail # Issue 5022
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 26e406b..097a374 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -25,6 +25,9 @@
 [ $compiler == dart2js && $checked ]
 async/stream_event_transform_test: Fail # Issue 7733.
 
+[ $compiler == dart2js && $unchecked && ($runtime == d8 || $runtime == chrome || $runtime == drt) ]
+crypto/sha1_test: Fail # V8 bug: https://code.google.com/p/v8/issues/detail?id=2692
+
 [ $compiler == dart2js && $jscl ]
 async/future_test: Fail # Timer interface not supported; dartbug.com/7728.
 async/slow_consumer2_test: Fail # Timer interface not supported; dartbug.com/7728.
diff --git a/tests/standalone/crypto/base64_test.dart b/tests/standalone/crypto/base64_test.dart
deleted file mode 100644
index 55546f0..0000000
--- a/tests/standalone/crypto/base64_test.dart
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-
-part "../../../sdk/lib/io/base64.dart";
-
-void main() {
-  String line;
-  String expected;
-
-  line =
-      "Man is distinguished, not only by his reason, but by this singular "
-      "passion from other animals, which is a lust of the mind, that by a "
-      "perseverance of delight in the continued and indefatigable generation "
-      "of knowledge, exceeds the short vehemence of any carnal pleasure.";
-  expected =
-      "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbm"
-      "x5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz\r\n"
-      "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci"
-      "BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg\r\n"
-      "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcm"
-      "FuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu\r\n"
-      "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYX"
-      "Rpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo\r\n"
-      "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm"
-      "5hbCBwbGVhc3VyZS4=";
-  Expect.equals(expected, _Base64._encode(line.codeUnits));
-  Expect.listEquals(line.codeUnits, _Base64._decode(expected));
-
-  line = "Simple string";
-  expected = "U2ltcGxlIHN0cmluZw==";
-  Expect.equals(expected, _Base64._encode(line.codeUnits));
-  Expect.listEquals(line.codeUnits, _Base64._decode(expected));
-
-  for (int i = 0; i < 256; i++) {
-    List<int> x = [i];
-    Expect.listEquals(x, _Base64._decode(_Base64._encode(x)));
-  }
-
-  for (int i = 0; i < 255; i++) {
-    List<int> x = [i, i + 1];
-    Expect.listEquals(x, _Base64._decode(_Base64._encode(x)));
-  }
-
-  for (int i = 0; i < 254; i++) {
-    List<int> x = [i, i + 1, i + 2];
-    Expect.listEquals(x, _Base64._decode(_Base64._encode(x)));
-  }
-
-  for (int i = 0; i < 253; i++) {
-    List<int> x = [i, i + 1, i + 2, i + 3];
-    Expect.listEquals(x, _Base64._decode(_Base64._encode(x)));
-  }
-
-  for (int i = 0; i < 252; i++) {
-    List<int> x = [i, i + 1, i + 2, i + 3, i + 4];
-    Expect.listEquals(x, _Base64._decode(_Base64._encode(x)));
-  }
-
-  for (int i = 0; i < 251; i++) {
-    List<int> x = [i, i + 1, i + 2, i + 3, i + 4, i + 5];
-    Expect.listEquals(x, _Base64._decode(_Base64._encode(x)));
-  }
-
-  for (int i = 0; i < 250; i++) {
-    List<int> x = [i, i + 1, i + 2, i + 3, i + 4, i + 5, i + 6];
-    Expect.listEquals(x, _Base64._decode(_Base64._encode(x)));
-  }
-}
diff --git a/tests/standalone/io/file_input_stream_test.dart b/tests/standalone/io/file_input_stream_test.dart
index 93c9deb..d57c014 100644
--- a/tests/standalone/io/file_input_stream_test.dart
+++ b/tests/standalone/io/file_input_stream_test.dart
@@ -169,6 +169,61 @@
 }
 
 
+void testInputStreamOffset() {
+  void test(int start, int end, int expectedBytes) {
+    var keepAlive = new ReceivePort();
+    var temp = new Directory('').createTempSync();
+    var file = new File('${temp.path}/input_stream_offset.txt');
+    var originalLength = writeLongFileSync(file);
+    var streamedBytes = 0;
+    if (expectedBytes < 0) expectedBytes = originalLength + expectedBytes;
+    file.openRead(start, end).listen(
+        (d) {
+          streamedBytes += d.length;
+        },
+        onDone: () {
+          Expect.equals(expectedBytes, streamedBytes);
+          temp.delete(recursive: true).then((_) => keepAlive.close());
+        },
+        onError: (e) {
+          Expect.fail("Unexpected error");
+        });
+  }
+  test(10, 20, 10);
+  test(10, 11, 1);
+  test(10, 10, 0);
+  test(100000000, null, 0);
+  test(null, 0, 0);
+  test(null, 1, 1);
+  test(1, null, -1);
+  test(20, null, -20);
+}
+
+
+void testInputStreamBadOffset() {
+  void test(int start, int end) {
+    var keepAlive = new ReceivePort();
+    var temp = new Directory('').createTempSync();
+    var file = new File('${temp.path}/input_stream_bad_offset.txt');
+    var originalLength = writeLongFileSync(file);
+    var streamedBytes = 0;
+    file.openRead(start, end).listen(
+        (d) {
+          streamedBytes += d.length;
+        },
+        onDone: () {
+          temp.delete(recursive: true);
+        },
+        onError: (e) {
+          keepAlive.close();
+        });
+  }
+  test(-1, null);
+  test(100, 99);
+  test(null, -1);
+}
+
+
 void testStringLineTransformerEnding(String name, int length) {
   String fileName = getFilename("tests/standalone/io/$name");
   // File contains 10 lines.
@@ -198,6 +253,8 @@
   testInputStreamTruncate();
   testInputStreamDelete();
   testInputStreamAppend();
+  testInputStreamOffset();
+  testInputStreamBadOffset();
   // Check the length of these files as both are text files where one
   // is without a terminating line separator which can easily be added
   // back if accidentally opened in a text editor.
diff --git a/tests/standalone/io/http_client_timeout_test.dart b/tests/standalone/io/http_client_timeout_test.dart
new file mode 100644
index 0000000..0703abb4
--- /dev/null
+++ b/tests/standalone/io/http_client_timeout_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+
+void testOneRequest(int connections) {
+  HttpServer.bind('127.0.0.1', 0).then((server) {
+    server.listen((request) => request.response.close());
+    var client = new HttpClient();
+    var futures = [];
+    for (int i = 0; i < connections; i++) {
+      futures.add(
+          client.get('127.0.0.1', server.port, '/')
+              .then((request) => request.close())
+              .then((response) => response.fold(null, (x, y) {})));
+    }
+    Future.wait(futures).then((_) {
+      new Timer.periodic(const Duration(milliseconds: 100), (timer) {
+        if (server.connectionsInfo().total == 0) {
+          timer.cancel();
+          server.close();
+        }
+      });
+    });
+  });
+}
+
+
+void testIdleTimeout(int timeout) {
+  HttpServer.bind('127.0.0.1', 0).then((server1) {
+    HttpServer.bind('127.0.0.1', 0).then((server2) {
+      server1.listen((request) => request.pipe(request.response));
+      server2.listen((request) => request.pipe(request.response));
+
+      var client = new HttpClient();
+      client.idleTimeout = new Duration(milliseconds: timeout);
+
+      // Create a 'slow' connection..
+      Future connect(int port) {
+        return client.post('127.0.0.1', port, '/')
+            .then((request) {
+              request.write("data");
+              new Timer(const Duration(milliseconds: 250), () {
+                request.close();
+              });
+              return request.done;
+            })
+            .then((response) {
+              return response.fold(null, (x, y) {});
+            });
+      }
+
+      // Create a single, slow request, to server1.
+      connect(server1.port);
+
+      // Create a repeating connection to server2.
+      run() {
+        connect(server2.port).then((_) {
+          if (server1.connectionsInfo().total == 0) {
+            server1.close();
+            server2.close();
+            return;
+          }
+          Timer.run(run);
+        });
+      }
+      run();
+    });
+  });
+}
+
+
+main() {
+  testOneRequest(1);
+  testOneRequest(5);
+  testOneRequest(20);
+  testIdleTimeout(0);
+  testIdleTimeout(100);
+  testIdleTimeout(500);
+  testIdleTimeout(1000);
+  testIdleTimeout(2000);
+}
diff --git a/tests/standalone/io/http_close_test.dart b/tests/standalone/io/http_close_test.dart
index a4f8175..17b4e47 100644
--- a/tests/standalone/io/http_close_test.dart
+++ b/tests/standalone/io/http_close_test.dart
@@ -111,9 +111,36 @@
 }
 
 
+void testClientCloseWhileSendingRequest(int connections) {
+  HttpServer.bind("127.0.0.1", 0).then((server) {
+    int errors = 0;
+    server.listen((request) {
+      request.listen((_) {}, onError: (e) { errors++; });
+    });
+    var client = new HttpClient();
+    for (int i = 0; i < connections; i++) {
+      client.post("127.0.0.1", server.port, "/")
+          .then((request) {
+            request.contentLength = 110;
+            request.write("0123456789");
+            return request.close();
+          })
+          .catchError((_) {});
+    }
+    new Timer.periodic(const Duration(milliseconds: 100), (t) {
+      if (errors == connections && server.connectionsInfo().total == 0) {
+        t.cancel();
+        server.close();
+      }
+    });
+  });
+}
+
+
 void main() {
   testClientAndServerCloseNoListen(10);
   testClientCloseServerListen(10);
   testClientCloseSendingResponse(10);
+  testClientCloseWhileSendingRequest(10);
 }
 
diff --git a/tests/standalone/io/process_echo_util.dart b/tests/standalone/io/process_echo_util.dart
new file mode 100644
index 0000000..1cc501d
--- /dev/null
+++ b/tests/standalone/io/process_echo_util.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+void main() {
+  new Options().arguments.forEach(print);
+}
diff --git a/tests/standalone/io/process_exit_negative_test.dart b/tests/standalone/io/process_exit_negative_test.dart
index 9eede27..418977f 100644
--- a/tests/standalone/io/process_exit_negative_test.dart
+++ b/tests/standalone/io/process_exit_negative_test.dart
@@ -9,14 +9,14 @@
 import "process_test_util.dart";
 
 void main() {
-  Future<Process> fp = Process.start(getProcessTestFileName(),
-                            const ["0", "0", "0", "0"]);
+  var fp = Process.start(getProcessTestFileName(),
+                         const ["0", "0", "0", "0"]);
   fp.then((p) {
-    p.onExit = (int s) {
+    p.exitCode.then((int s) {
       print(a.toString());  // Should cause a compilation error here.
-    };
+    });
     // Drain stdout and stderr.
-    p.stdout.onData = p.stdout.read;
-    p.stderr.onData = p.stderr.read;
+    p.stdout.listen((_) {});
+    p.stderr.listen((_) {});
   });
 }
diff --git a/tests/standalone/io/process_shell_test.dart b/tests/standalone/io/process_shell_test.dart
new file mode 100644
index 0000000..add0c9f
--- /dev/null
+++ b/tests/standalone/io/process_shell_test.dart
@@ -0,0 +1,72 @@
+// 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";
+
+void testRunShell() {
+  test(args) {
+    var options = new Options();
+    var path = new Path(options.script);
+    path = path.directoryPath.join(new Path("process_echo_util.dart"));
+    Process.runShell(options.executable, [path.toString()]..addAll(args))
+        .then((result) {
+          if (Platform.operatingSystem == "windows") {
+            result = result.stdout.split("\r\n");
+          } else {
+            result = result.stdout.split("\n");
+          }
+          if (result.length - 1 != args.length) {
+            throw "wrong number of args: $args vs $result";
+          }
+          for (int i = 0; i < args.length; i++) {
+            if (args[i] != result[i]) {
+              throw "bad result at $i: '${args[i]}' vs '${result[i]}'";
+            }
+          }
+        });
+  }
+  test(["\""]);
+  test(["a b"]);
+  test(["'"]);
+  test(["'\"\"'\"'\"'"]);
+  test(["'\"\"'", "\"'\"'"]);
+  test(["'\$HOME'"]);
+  test(["'\$tmp'"]);
+}
+
+void testShell() {
+  test(args, expected) {
+    var options = new Options();
+    var path = new Path(options.script);
+    path = path.directoryPath.join(new Path("process_echo_util.dart"));
+    var command = "${options.executable} $path $args";
+    Process.runShell(command, [])
+        .then((result) {
+          if (Platform.operatingSystem == "windows") {
+            result = result.stdout.split("\r\n");
+          } else {
+            result = result.stdout.split("\n");
+          }
+          if (result.length - 1 != expected.length) {
+            throw "wrong number of args: $expected vs $result";
+          }
+          for (int i = 0; i < expected.length; i++) {
+            if (expected[i] != result[i]) {
+              throw "bad result at $i: ${expected[i]} vs ${result[i]}";
+            }
+          }
+        });
+  }
+  test("arg", ["arg"]);
+  test("arg1 arg2", ["arg1", "arg2"]);
+  if (Platform.operatingSystem != 'windows') {
+    test("arg1 arg2 > /dev/null", []);
+  }
+}
+
+void main() {
+  testRunShell();
+  testShell();
+}
+
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 58dfb16..10e39ba 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -7,6 +7,9 @@
 [ $runtime == vm && $system == macos ]
 debugger/basic_debugger_test: Pass, Crash # Issue 10488.
 
+[ $runtime == vm && $system == windows ]
+debugger/*: Skip # Issue: 10791
+
 [ $runtime == vm ]
 # Fails because checked-in dart executable is not up to date.
 io/test_runner_test: Fail
@@ -79,7 +82,6 @@
 io/process_exit_negative_test: Fail  # This is a compilation-time negative test.
 
 [ $compiler == dartanalyzer ]
-crypto/base64_test: fail
 io/file_constructor_test: fail
 io/http_date_test: fail
 io/http_headers_test: fail
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index 3ed3e17..ae44c27 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -52,8 +52,9 @@
                     var removeLast;
                     var add;
                   }
-                  class JSFixedArray {}
-                  class JSExtendableArray {}
+                  class JSMutableArray {}
+                  class JSFixedArray extends JSMutableArray {}
+                  class JSExtendableArray extends JSMutableArray {}
                   class JSString {
                     var split;
                     var concat;
diff --git a/tools/VERSION b/tools/VERSION
index e85a212..004cbc5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 5
-BUILD 9
+BUILD 10
 PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index 3cfd6e5..72cf2e6 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -219,9 +219,11 @@
     # The dart2js compiler isn't self-hosted (yet) so we run its
     # unit tests on the VM. We avoid doing this on the builders
     # that run the browser tests to cut down on the cycle time.
+    unit_test_flags = [flag for flag in flags if flag.startswith('--shard')]
+    # Run the unit tests in checked mode (the VM's checked mode).
+    unit_test_flags.append('--checked')
     TestStep("dart2js_unit", mode, system, 'none', 'vm', ['dart2js'],
-             # Run the unit tests in checked mode (the VM's checked mode).
-             ['--checked'])
+             unit_test_flags)
 
   if system.startswith('win') and runtime.startswith('ie10'):
     TestStep("dart2js", mode, system, 'dart2js', runtime, ['html'], flags)
diff --git a/tools/build.py b/tools/build.py
index 2426699..71b9247 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -108,7 +108,7 @@
       # We have not yet tweaked the v8 dart build to work with the Android
       # NDK/SDK, so don't try to build it.
       if args == []:
-        print "For android builds you must specify a target, such as 'dart'."
+        print "For android builds you must specify a target, such as 'samples'."
         return False
       if 'v8' in args:
         print "The v8 target is not supported for android builds."
@@ -166,7 +166,7 @@
 
   os.environ['ANDROID_TOOLCHAIN'] = android_toolchain
 
-  android_sdk_version = 9
+  android_sdk_version = 15
 
   android_sdk_tools = os.path.join(android_sdk_root, 'tools')
   CheckDirExists(android_sdk_tools, 'Android SDK tools')
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 22f3b28..cc9935d 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -3529,7 +3529,10 @@
       "HTMLFormElement": {},
       "acceptCharset": {},
       "action": {},
-      "autocomplete": {},
+      "autocomplete": {
+        "comment": "http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#autofilling-form-controls:-the-autocomplete-attribute",
+        "support_level": "experimental"
+      },
       "checkValidity": {},
       "elements": {},
       "encoding": {},
@@ -5295,6 +5298,10 @@
     },
     "support_level": "untriaged"
   },
+  "MIDIInput": {
+    "members": {},
+    "support_level": "untriaged"
+  },
   "MIDIMessageEvent": {
     "members": {
       "data": {
@@ -5323,6 +5330,9 @@
       "name": {
         "support_level": "untriaged"
       },
+      "ondisconnect": {
+        "support_level": "untriaged"
+      },
       "removeEventListener": {
         "support_level": "untriaged"
       },
@@ -10173,12 +10183,27 @@
       "lang": {
         "support_level": "untriaged"
       },
+      "onboundary": {
+        "support_level": "untriaged"
+      },
+      "onend": {
+        "support_level": "untriaged"
+      },
       "onerror": {
         "support_level": "untriaged"
       },
+      "onmark": {
+        "support_level": "untriaged"
+      },
       "onpause": {
         "support_level": "untriaged"
       },
+      "onresume": {
+        "support_level": "untriaged"
+      },
+      "onstart": {
+        "support_level": "untriaged"
+      },
       "pitch": {
         "support_level": "untriaged"
       },
diff --git a/tools/dom/scripts/fremontcutbuilder.py b/tools/dom/scripts/fremontcutbuilder.py
index 3b172b2..16bf69a 100755
--- a/tools/dom/scripts/fremontcutbuilder.py
+++ b/tools/dom/scripts/fremontcutbuilder.py
@@ -12,40 +12,33 @@
 
 _logger = logging.getLogger('fremontcutbuilder')
 
+# See:
+#  http://src.chromium.org/viewvc/multivm/trunk/webkit/Source/core/features.gypi
+# for ENABLE_* flags defined in Chromium / Blink.
+# We list all ENABLE flags used in IDL in one of these two lists.
 FEATURE_DISABLED = [
     'ENABLE_BATTERY_STATUS',
-    'ENABLE_CSS3_CONDITIONAL_RULES',
     'ENABLE_CSS_DEVICE_ADAPTATION',
     'ENABLE_CUSTOM_SCHEME_HANDLER',
     'ENABLE_ENCRYPTED_MEDIA_V2',
     'ENABLE_MEDIA_CAPTURE', # Only enabled on Android.
     'ENABLE_ORIENTATION_EVENTS', # Only enabled on Android.
-    'ENABLE_SPEECH_SYNTHESIS',
     'ENABLE_WEBVTT_REGIONS',
     'ENABLE_XHR_TIMEOUT',
 ]
 
 FEATURE_DEFINES = [
-    'ENABLE_CALENDAR_PICKER',
-    'ENABLE_CANVAS_PROXY',
-    'ENABLE_CSS_REGIONS',
-    'ENABLE_CUSTOM_ELEMENTS',
-    'ENABLE_DATALIST_ELEMENT',
-    'ENABLE_DIALOG_ELEMENT',
+    'ENABLE_CALENDAR_PICKER', # Not on Android
+    'ENABLE_DATALIST_ELEMENT', # Not on Android
     'ENABLE_ENCRYPTED_MEDIA',
-    'ENABLE_FONT_LOAD_EVENTS',
-    'ENABLE_GAMEPAD',
-    'ENABLE_INPUT_SPEECH',
-    'ENABLE_LEGACY_NOTIFICATIONS',
-    'ENABLE_MEDIA_STREAM',
-    'ENABLE_NAVIGATOR_CONTENT_UTILS',
-    'ENABLE_NOTIFICATIONS',
-    'ENABLE_PAGE_POPUP',
-    'ENABLE_SHARED_WORKERS',
+    'ENABLE_INPUT_SPEECH', # Not on Android
+    'ENABLE_LEGACY_NOTIFICATIONS', # Not on Android
+    'ENABLE_NAVIGATOR_CONTENT_UTILS', # Not on Android
+    'ENABLE_NOTIFICATIONS', # Not on Android
+    'ENABLE_PAGE_POPUP', # Not on Android
     'ENABLE_SVG',
     'ENABLE_SVG_FONTS',
-    'ENABLE_VIDEO',
-    'ENABLE_WEB_AUDIO',
+    'ENABLE_WEB_AUDIO', # Not on Android
     'ENABLE_WEBGL',
 ]
 
@@ -111,11 +104,13 @@
   if unused_conditionals:
     _logger.warning('There are some unused conditionals %s' %
         sorted(unused_conditionals))
+    _logger.warning('Please update fremontcutbuilder.py')
 
   unknown_conditionals = conditionals_met - known_conditionals
   if unknown_conditionals:
     _logger.warning('There are some unknown conditionals %s' %
         sorted(unknown_conditionals))
+    _logger.warning('Please update fremontcutbuilder.py')
 
   db.Save()
   return db
diff --git a/tools/dom/scripts/htmleventgenerator.py b/tools/dom/scripts/htmleventgenerator.py
index cdbade3..3ed4393 100644
--- a/tools/dom/scripts/htmleventgenerator.py
+++ b/tools/dom/scripts/htmleventgenerator.py
@@ -121,6 +121,7 @@
   'DOMApplicationCache.progress': ('progress', 'Event'),
   'DOMApplicationCache.updateready': ('updateReady', 'Event'),
   'Document.readystatechange': ('readyStateChange', 'Event'),
+  'Document.securitypolicyviolation': ('securityPolicyViolation', 'SecurityPolicyViolationEvent'),
   'Document.selectionchange': ('selectionChange', 'Event'),
   'Document.webkitpointerlockchange': ('pointerLockChange', 'Event'),
   'Document.webkitpointerlockerror': ('pointerLockError', 'Event'),
@@ -135,8 +136,14 @@
   'FileWriter.write': ('write', 'ProgressEvent'),
   'FileWriter.writeend': ('writeEnd', 'ProgressEvent'),
   'FileWriter.writestart': ('writeStart', 'ProgressEvent'),
+  'FontLoader.load': ('load', 'CssFontFaceLoadEvent'),
+  'FontLoader.loading': ('loading', 'CssFontFaceLoadEvent'),
+  'FontLoader.loadingdone': ('loadingDone', 'CssFontFaceLoadEvent'),
+  'FontLoader.loadstart': ('loadStart', 'CssFontFaceLoadEvent'),
   'HTMLBodyElement.storage': ('storage', 'StorageEvent'),
   'HTMLInputElement.webkitSpeechChange': ('speechChange', 'Event'),
+  'HTMLFormElement.autocomplete': ('autocomplete', 'Event'),
+  'HTMLFormElement.autocompleteerror': ('autocompleteError', 'AutocompleteErrorEvent'),
   'HTMLMediaElement.loadstart': ('loadStart', 'Event'),
   'HTMLMediaElement.progress': ('progress', 'Event'),
   'HTMLMediaElement.show': ('show', 'Event'),
@@ -153,10 +160,12 @@
   'MediaStream.removetrack': ('removeTrack', 'Event'),
   'MediaStreamTrack.mute': ('mute', 'Event'),
   'MediaStreamTrack.unmute': ('unmute', 'Event'),
+  'MIDIPort.disconnect': ('disconnect', 'MidiConnectionEvent'),
   'Notification.click': ('click', 'Event'),
   'Notification.close': ('close', 'Event'),
   'Notification.display': ('display', 'Event'),
   'Notification.show': ('show', 'Event'),
+  'Performance.webkitresourcetimingbufferfull': ('resourceTimingBufferFull', 'Event'),
   'RTCDTMFSender.tonechange': ('toneChange', 'RtcDtmfToneChangeEvent'),
   'RTCDataChannel.close': ('close', 'Event'),
   'RTCDataChannel.open': ('open', 'Event'),
@@ -179,6 +188,11 @@
   'SpeechRecognition.speechend': ('speechEnd', 'Event'),
   'SpeechRecognition.speechstart': ('speechStart', 'Event'),
   'SpeechRecognition.start': ('start', 'Event'),
+  'SpeechSynthesisUtterance.boundary': ('boundary', 'SpeechSynthesisEvent'),
+  'SpeechSynthesisUtterance.end': ('end', 'SpeechSynthesisEvent'),
+  'SpeechSynthesisUtterance.mark': ('mark', 'SpeechSynthesisEvent'),
+  'SpeechSynthesisUtterance.resume': ('resume', 'SpeechSynthesisEvent'),
+  'SpeechSynthesisUtterance.start': ('start', 'SpeechSynthesisEvent'),
   'TextTrack.cuechange': ('cueChange', 'Event'),
   'TextTrackCue.enter': ('enter', 'Event'),
   'TextTrackCue.exit': ('exit', 'Event'),
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index e28460c..7262ee1 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -56,7 +56,6 @@
     'SVGSVGElement': 'SvgSvgElement', # Manual to avoid name conflicts.
     'WebGLVertexArrayObjectOES': 'VertexArrayObject',
     'XMLHttpRequest': 'HttpRequest',
-    'XMLHttpRequestException': 'HttpRequestException',
     'XMLHttpRequestProgressEvent': 'HttpRequestProgressEvent',
     'XMLHttpRequestUpload': 'HttpRequestUpload',
 }, **typed_array_renames))
@@ -157,7 +156,6 @@
 # browser.
 _private_html_members = monitored.Set('htmlrenamer._private_html_members', [
   'CanvasRenderingContext2D.arc',
-  'CanvasRenderingContext2D.drawImage',
   'CompositionEvent.initCompositionEvent',
   'CustomEvent.initCustomEvent',
   'DeviceOrientationEvent.initDeviceOrientationEvent',
@@ -301,8 +299,6 @@
   'UIEvent.layerY',
   'UIEvent.pageX',
   'UIEvent.pageY',
-  'WheelEvent.wheelDeltaX',
-  'WheelEvent.wheelDeltaY',
   'WheelEvent.initWebKitWheelEvent',
   'DOMWindow.getComputedStyle',
 ])
@@ -310,6 +306,7 @@
 # Members from the standard dom that exist in the dart:html library with
 # identical functionality but with cleaner names.
 renamed_html_members = monitored.Dict('htmlrenamer.renamed_html_members', {
+    'CanvasRenderingContext2D.drawImage': '_drawImage',
     'CSSStyleDeclaration.getPropertyValue': '_getPropertyValue',
     'CSSStyleDeclaration.setProperty': '_setProperty',
     'DirectoryEntry.getDirectory': '_getDirectory',
@@ -346,6 +343,8 @@
     'StorageInfo.queryUsageAndQuota': '_queryUsageAndQuota',
     'SVGElement.className': '$dom_svgClassName',
     'SVGStopElement.offset': 'gradientOffset',
+    'WheelEvent.wheelDeltaX': '_wheelDeltaX',
+    'WheelEvent.wheelDeltaY': '_wheelDeltaY',
     #'WorkerContext.webkitRequestFileSystem': '_requestFileSystem',
     #'WorkerContext.webkitRequestFileSystemSync': '_requestFileSystemSync',
 })
diff --git a/tools/dom/scripts/idlparser.py b/tools/dom/scripts/idlparser.py
index 6583444..3142118 100755
--- a/tools/dom/scripts/idlparser.py
+++ b/tools/dom/scripts/idlparser.py
@@ -212,7 +212,7 @@
         [MAYBE(ExtAttrs), MAYBE(Static), MAYBE(Stringifier), MAYBE(_Specials),
          ReturnType, MAYBE(Id), '(', _Arguments, ')', ';'],
         # WebKit:
-        [MAYBE(ExtAttrs), MAYBE(Static), MAYBE(_AttrGetterSetter),
+        [MAYBE(ExtAttrs), MAYBE(Static), MAYBE(_Specials),
          ReturnType, MAYBE(Id), '(', _Arguments, ')', ';'],
         # FremontCut:
         [MAYBE(_Annotations), MAYBE(ExtAttrs), MAYBE(Static), MAYBE(Stringifier),
diff --git a/tools/dom/scripts/logging.conf b/tools/dom/scripts/logging.conf
index 8645a8e..6dbf12e 100644
--- a/tools/dom/scripts/logging.conf
+++ b/tools/dom/scripts/logging.conf
@@ -1,5 +1,5 @@
 [loggers]
-keys=root,pegparser,database,databasebuilder,dartgenerator,dartmetadata,snippet_manager,htmlrenamer
+keys=root,pegparser,database,databasebuilder,dartgenerator,dartmetadata,snippet_manager,htmlrenamer,fremontcutbuilder
 
 [handlers]
 keys=consoleHandler
@@ -29,6 +29,12 @@
 handlers=consoleHandler
 qualname=databasebuilder
 
+[logger_fremontcutbuilder]
+level=INFO
+propagate=0
+handlers=consoleHandler
+qualname=fremontcutbuilder
+
 [logger_snippet_manager]
 level=INFO
 propagate=0
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 0302a6c..c6463e1 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -708,8 +708,11 @@
     #
 
     ext_attrs = self._interface.ext_attrs
-    has_indexed_getter = ('IndexedGetter' in ext_attrs or
-      'CustomIndexedSetter' in ext_attrs)
+    has_indexed_getter = 'CustomIndexedGetter' in ext_attrs
+    for operation in self._interface.operations:
+      if operation.id == 'item' and 'getter' in operation.specials:
+        has_indexed_getter = True
+        break
 
     if has_indexed_getter:
       indexed_getter = ('JS("%s", "#[#]", this, index)' %
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index a81e322..c5c8219 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -336,8 +336,7 @@
 
     ext_attrs = self._interface.ext_attrs
 
-    if ('CustomToJS' in ext_attrs or
-        ('CustomToJSObject' in ext_attrs and 'TypedArray' not in ext_attrs) or
+    if ('CustomToV8' in ext_attrs or
         'PureInterface' in ext_attrs or
         'CPPPureInterface' in ext_attrs or
         self._interface_type_info.custom_to_dart()):
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 788b179..303a4e8 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -78,16 +78,16 @@
     }
   }
 
-  bool get _paused => _pauseCount > 0;
+  bool get isPaused => _pauseCount > 0;
 
   void resume() {
-    if (_canceled || !_paused) return;
+    if (_canceled || !isPaused) return;
     --_pauseCount;
     _tryResume();
   }
 
   void _tryResume() {
-    if (_onData != null && !_paused) {
+    if (_onData != null && !isPaused) {
       _target.$dom_addEventListener(_eventType, _onData, _useCapture);
     }
   }
diff --git a/tools/dom/src/ImmutableListMixin.dart b/tools/dom/src/ImmutableListMixin.dart
index df14b40..2c05c11 100644
--- a/tools/dom/src/ImmutableListMixin.dart
+++ b/tools/dom/src/ImmutableListMixin.dart
@@ -47,7 +47,7 @@
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
-  void remove(Object object) {
+  bool remove(Object object) {
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
@@ -59,7 +59,7 @@
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
-  void setRange(int start, int end, Iterable<E> iterable, [int skipCount]) {
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     throw new UnsupportedError("Cannot setRange on immutable List.");
   }
 
diff --git a/tools/dom/src/TemplateBindings.dart b/tools/dom/src/TemplateBindings.dart
index 9841aee..81cebd3 100644
--- a/tools/dom/src/TemplateBindings.dart
+++ b/tools/dom/src/TemplateBindings.dart
@@ -378,7 +378,7 @@
   }
 
   // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(Document doc) {
+  static Document _getTemplateContentsOwner(HtmlDocument doc) {
     if (doc.window == null) {
       return doc;
     }
@@ -456,7 +456,7 @@
     // template.
     // TODO(jmesserly): node is DocumentFragment or Element
     var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-    if (node is Element && node.isTemplate) bootstrap(node);
+    if (node is Element && (node as Element).isTemplate) bootstrap(node);
 
     descendents.forEach(bootstrap);
   }
@@ -610,7 +610,7 @@
 
   static void _removeChild(Node parent, Node child) {
     child._templateInstance = null;
-    if (child is Element && child.isTemplate) {
+    if (child is Element && (child as Element).isTemplate) {
       // Make sure we stop observing when we remove an element.
       var templateIterator = child._templateIterator;
       if (templateIterator != null) {
diff --git a/tools/dom/src/WrappedList.dart b/tools/dom/src/WrappedList.dart
index 3baff3e..b725b96 100644
--- a/tools/dom/src/WrappedList.dart
+++ b/tools/dom/src/WrappedList.dart
@@ -23,7 +23,7 @@
 
   void add(E element) { _list.add(element); }
 
-  void remove(Object element) { _list.remove(element); }
+  bool remove(Object element) => _list.remove(element);
 
   void clear() { _list.clear(); }
 
diff --git a/tools/dom/src/dart2js_Conversions.dart b/tools/dom/src/dart2js_Conversions.dart
index 1c51b29..86f32fb 100644
--- a/tools/dom/src/dart2js_Conversions.dart
+++ b/tools/dom/src/dart2js_Conversions.dart
@@ -32,8 +32,14 @@
   // Assume it's a Window if it contains the setInterval property.  It may be
   // from a different frame - without a patched prototype - so we cannot
   // rely on Dart type checking.
-  if (JS('bool', r'"setInterval" in #', e))
-    return _DOMWindowCrossFrame._createSafe(e);
+  if (JS('bool', r'"setInterval" in #', e)) {
+    var window = _DOMWindowCrossFrame._createSafe(e);
+    // If it's a native window.
+    if (window is EventTarget) {
+      return window;
+    }
+    return null;
+  }
   else
     return e;
 }
diff --git a/tools/dom/src/dartium_KeyEvent.dart b/tools/dom/src/dartium_KeyEvent.dart
index b627b9c..5be433b 100644
--- a/tools/dom/src/dartium_KeyEvent.dart
+++ b/tools/dom/src/dartium_KeyEvent.dart
@@ -66,6 +66,8 @@
 
   /** True if the altGraphKey is pressed during this event. */
   bool get altGraphKey => _parent.altGraphKey;
+  /** Accessor to the clipboardData available for this event. */
+  DataTransfer get clipboardData => _parent.clipboardData;
   /** True if the ctrl key is pressed during this event. */
   bool get ctrlKey => _parent.ctrlKey;
   int get detail => _parent.detail;
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 28e1d55..2a20d31 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -94,4 +94,4 @@
   return JS('var', r'ReceivePortSync.dispatchCall(#, #)', id, message);
 }
 
-spawnDomFunction(f) => IsolateNatives.spawnDomFunction(f);
+spawnDomFunction(Function f) => IsolateNatives.spawnDomFunction(f);
diff --git a/tools/dom/templates/html/dart2js/impl_Console.darttemplate b/tools/dom/templates/html/dart2js/impl_Console.darttemplate
index 25d08e1..84527d2 100644
--- a/tools/dom/templates/html/dart2js/impl_Console.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_Console.darttemplate
@@ -6,7 +6,7 @@
 
 $(ANNOTATIONS)class Console {
 
-  static Console safeConsole = new Console();
+  static Console _safeConsole = new Console();
 
   bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
 
@@ -79,8 +79,8 @@
       JS('void', 'console.time(#)', title) : null;
 
   @DomName('Console.timeEnd')
-  void timeEnd(String timerName) => _isConsoleDefined ?
-      JS('void', 'console.timeEnd(#)', timerName) : null;
+  void timeEnd(String title) => _isConsoleDefined ?
+      JS('void', 'console.timeEnd(#)', title) : null;
 
   @DomName('Console.timeStamp')
   void timeStamp(Object arg) => _isConsoleDefined ?
diff --git a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
index 9792bf1..d4e304d 100644
--- a/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_MouseEvent.darttemplate
@@ -64,13 +64,12 @@
       return new Point(x, y);
     } else {
       // Firefox does not support offsetX.
-      var target = this.target;
-      if (!(target is Element)) {
+      if (!(this.target is Element)) {
         throw new UnsupportedError(
             'offsetX is only supported on elements');
       }
-      return (this.client -
-          this.target.getBoundingClientRect().topLeft).toInt();
+      Element target = this.target;
+      return (this.client - target.getBoundingClientRect().topLeft).toInt();
     }
   }
 
diff --git a/tools/dom/templates/html/dart2js/impl_URL.darttemplate b/tools/dom/templates/html/dart2js/impl_URL.darttemplate
index 30c4161..3da9a69 100644
--- a/tools/dom/templates/html/dart2js/impl_URL.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_URL.darttemplate
@@ -11,8 +11,8 @@
          '(self.URL || self.webkitURL).createObjectURL(#)',
          blob_OR_source_OR_stream);
 
-  static void revokeObjectUrl(String objectUrl) =>
+  static void revokeObjectUrl(String url) =>
       JS('void',
-         '(self.URL || self.webkitURL).revokeObjectURL(#)', objectUrl);
+         '(self.URL || self.webkitURL).revokeObjectURL(#)', url);
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
index 1fca45d..22b56c2 100644
--- a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
@@ -112,13 +112,13 @@
     }
 $else
     if (sourceRect == null) {
-      $dom_drawImage(source,
+      _drawImage(source,
           destRect.left,
           destRect.top,
           destRect.width,
           destRect.height);
     } else {
-      $dom_drawImage(source,
+      _drawImage(source,
           sourceRect.left,
           sourceRect.top,
           sourceRect.width,
@@ -166,7 +166,7 @@
   void drawImage(CanvasImageSource source, num destX, num destY) native;
 $else
   void drawImage(CanvasImageSource source, num destX, num destY) {
-    $dom_drawImage(source, destX, destY);
+    _drawImage(source, destX, destY);
   }
 $endif
 
@@ -204,7 +204,7 @@
 $else
   void drawImageScaled(CanvasImageSource source,
       num destX, num destY, num destWidth, num destHeight) {
-    $dom_drawImage(source, destX, destY, destWidth, destHeight);
+    _drawImage(source, destX, destY, destWidth, destHeight);
   }
 $endif
 
@@ -247,7 +247,7 @@
   void drawImageScaledFromSource(CanvasImageSource source,
       num sourceX, num sourceY, num sourceWidth, num sourceHeight,
       num destX, num destY, num destWidth, num destHeight) {
-    $dom_drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight,
+    _drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight,
         destX, destY, destWidth, destHeight);
   }
 $endif
@@ -258,7 +258,7 @@
       '#.lineDashOffset || #.webkitLineDashOffset', this, this);
 
   @DomName('CanvasRenderingContext2D.lineDashOffset')
-  void set lineDashOffset(num value) => JS('void', 
+  void set lineDashOffset(num value) => JS('void',
       'typeof #.lineDashOffset != "undefined" ? #.lineDashOffset = # : '
       '#.webkitLineDashOffset = #', this, this, value, this, value);
 $else
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 261a6cd..188759e 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -564,11 +564,11 @@
    * * [insertAdjacentText]
    * * [insertAdjacentElement]
    */
-  void insertAdjacentHtml(String where, String text) {
+  void insertAdjacentHtml(String where, String html) {
     if (JS('bool', '!!#.insertAdjacentHtml', this)) {
-      _insertAdjacentHtml(where, text);
+      _insertAdjacentHtml(where, html);
     } else {
-      _insertAdjacentNode(where, new DocumentFragment.html(text));
+      _insertAdjacentNode(where, new DocumentFragment.html(html));
     }
   }
 
@@ -636,7 +636,9 @@
 $else
 $endif
 
-  @Creates('Null')
+$if DART2JS
+  @Creates('Null') // Set from Dart code; does not instantiate a native type.
+$endif
   Map<String, StreamSubscription> _attributeBindings;
 
   // TODO(jmesserly): I'm concerned about adding these to every element.
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index 04b03cd..287151f 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -57,11 +57,12 @@
 
   void addAll(Iterable<Node> iterable) {
     if (iterable is _ChildNodeListLazy) {
-      if (!identical(iterable._this, _this)) {
+      _ChildNodeListLazy otherList = iterable;
+      if (!identical(otherList._this, _this)) {
         // Optimized route for copying between nodes.
-        for (var i = 0, len = iterable.length; i < len; ++i) {
+        for (var i = 0, len = otherList.length; i < len; ++i) {
           // Should use $dom_firstChild, Bug 8886.
-          _this.append(iterable[0]);
+          _this.append(otherList[0]);
         }
       }
       return;
diff --git a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
index 8ac5997..d196fc1 100644
--- a/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_SVGElement.darttemplate
@@ -44,7 +44,7 @@
     return _cssClassSet;
   }
 
-  List<Element> get children => new FilteredElementList(this);
+  List<Element> get children => new FilteredElementList<Element>(this);
 
   void set children(List<Element> value) {
     final children = this.children;
diff --git a/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate b/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
index 1e4b239..dcad713 100644
--- a/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
+++ b/tools/dom/templates/html/impl/impl_WheelEvent.darttemplate
@@ -230,7 +230,7 @@
    * * [WheelEvent.deltaX](http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-WheelEvent-deltaX) from the W3C.
    */
   @DomName('WheelEvent.deltaX')
-  num get deltaX => -$dom_wheelDeltaX;
+  num get deltaX => -_wheelDeltaX;
 
   /**
    * The amount that is expected to scroll vertically, in units determined by
@@ -241,6 +241,6 @@
    * * [WheelEvent.deltaY](http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-WheelEvent-deltaY) from the W3C.
    */
   @DomName('WheelEvent.deltaY')
-  num get deltaY => -$dom_wheelDeltaY;
+  num get deltaY => -_wheelDeltaY;
 $endif
 }
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index f60f7d495..9c8f8ce 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -152,7 +152,7 @@
     return _requestAnimationFrame(callback);
   }
 
-  void cancelAnimationFrame(id) {
+  void cancelAnimationFrame(int id) {
     _ensureRequestAnimationFrame();
     _cancelAnimationFrame(id);
   }
@@ -205,7 +205,7 @@
          this, this, this);
 
   @DomName('Window.console')
-  Console get console => Console.safeConsole;
+  Console get console => Console._safeConsole;
 
   /// Checks if _setImmediate is supported.
   static bool get _supportsSetImmediate =>
diff --git a/tools/gyp/configurations_make.gypi b/tools/gyp/configurations_make.gypi
index abced4d..05a3bad 100644
--- a/tools/gyp/configurations_make.gypi
+++ b/tools/gyp/configurations_make.gypi
@@ -55,6 +55,7 @@
             '-Wno-psabi', # suppresses va_list warning
             '-fno-strict-overflow',
           ],
+          'ldflags': ['-static'],
         }],
         ['_toolset=="host"', {
           'cflags': ['-m32', '-msse2'],
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 4261cec..94c33bb 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -846,7 +846,7 @@
       } else if (fields[ERROR_LEVEL] == 'WARNING') {
         // We only care about testing Static type warnings
         // ignore all others
-        if (fields[ERROR_TYPE] == 'STATIC_TYPE') {
+        if (fields[ERROR_TYPE] == 'STATIC_TYPE' || fields[ERROR_TYPE] == 'STATIC_TYPE_WARNING') {
           staticWarnings.add(fields[FORMATTED_ERROR]);
         }
       }
@@ -970,6 +970,20 @@
   }
 }
 
+
+/** Modifies the --timeout=XX parameter passed to run_selenium.py */
+List<String> _modifySeleniumTimeout(List<String> arguments, int timeout) {
+  return arguments.map((argument) {
+    if (argument.startsWith('--timeout=')) {
+      return "--timeout=$timeout";
+    } else {
+      return argument;
+    }
+  }).toList();
+  return;
+}
+
+
 /**
  * A RunningProcess actually runs a test, getting the command lines from
  * its [TestCase], starting the test process (and first, a compilation
@@ -1011,8 +1025,10 @@
         _commandComplete(0);
       } else {
         var processOptions = _createProcessOptions();
+        var commandArguments = _modifySeleniumTimeout(command.arguments,
+                                                      testCase.timeout);
         Future processFuture = io.Process.start(command.executable,
-                                                command.arguments,
+                                                commandArguments,
                                                 processOptions);
         processFuture.then((io.Process process) {
           // Close stdin so that tests that try to block on input will fail.
@@ -1177,7 +1193,8 @@
             "environments for batch runner tests!");
     }
 
-    var line = _createArgumentsLine(testCase.batchTestArguments);
+    var line = _createArgumentsLine(testCase.batchTestArguments,
+                                    testCase.timeout);
     _process.stdin.write(line);
     _stdoutSubscription.resume();
     _stderrSubscription.resume();
@@ -1185,7 +1202,8 @@
                  _stderrCompleter.future]).then((_) => _reportResult());
   }
 
-  String _createArgumentsLine(List<String> arguments) {
+  String _createArgumentsLine(List<String> arguments, int timeout) {
+    arguments = _modifySeleniumTimeout(arguments, timeout);
     return arguments.join(' ').concat('\n');
   }
 
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index bd0ddbd..329d087 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -998,7 +998,8 @@
           args = [
               dartDir.append('tools/testing/run_selenium.py').toNativePath(),
               '--browser=$runtime',
-              '--timeout=${configuration["timeout"]~/2}',
+              // NOTE: This value will be overridden by the test runner
+              '--timeout=${configuration['timeout']}',
               '--out=$fullHtmlPath'];
           if (runtime == 'dartium') {
             args.add('--executable=$dartiumFilename');