Version 0.6.7.0 .

svn merge -r 25115:25191 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@25194 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/lib/src/generated/ast.dart b/pkg/analyzer_experimental/lib/src/generated/ast.dart
index 833edbb..42a3cc7 100644
--- a/pkg/analyzer_experimental/lib/src/generated/ast.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/ast.dart
@@ -15497,6 +15497,9 @@
    * @return the element that was found
    */
   ASTNode searchWithin(ASTNode node) {
+    if (node == null) {
+      return null;
+    }
     try {
       node.accept(this);
     } on NodeLocator_NodeFoundException catch (exception) {
@@ -16946,7 +16949,11 @@
   BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement.full(node.keyword, clone2(node.label), node.semicolon);
   CascadeExpression visitCascadeExpression(CascadeExpression node) => new CascadeExpression.full(clone2(node.target), clone3(node.cascadeSections));
   CatchClause visitCatchClause(CatchClause node) => new CatchClause.full(node.onKeyword, clone2(node.exceptionType), node.catchKeyword, node.leftParenthesis, clone2(node.exceptionParameter), node.comma, clone2(node.stackTraceParameter), node.rightParenthesis, clone2(node.body));
-  ClassDeclaration visitClassDeclaration(ClassDeclaration node) => new ClassDeclaration.full(clone2(node.documentationComment), clone3(node.metadata), node.abstractKeyword, node.classKeyword, clone2(node.name), clone2(node.typeParameters), clone2(node.extendsClause), clone2(node.withClause), clone2(node.implementsClause), node.leftBracket, clone3(node.members), node.rightBracket);
+  ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
+    ClassDeclaration copy = new ClassDeclaration.full(clone2(node.documentationComment), clone3(node.metadata), node.abstractKeyword, node.classKeyword, clone2(node.name), clone2(node.typeParameters), clone2(node.extendsClause), clone2(node.withClause), clone2(node.implementsClause), node.leftBracket, clone3(node.members), node.rightBracket);
+    copy.nativeClause = clone2(node.nativeClause);
+    return copy;
+  }
   ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias.full(clone2(node.documentationComment), clone3(node.metadata), node.keyword, clone2(node.name), clone2(node.typeParameters), node.equals, node.abstractKeyword, clone2(node.superclass), clone2(node.withClause), clone2(node.implementsClause), node.semicolon);
   Comment visitComment(Comment node) {
     if (node.isDocumentation) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/element.dart b/pkg/analyzer_experimental/lib/src/generated/element.dart
index d822866..6effbfe 100644
--- a/pkg/analyzer_experimental/lib/src/generated/element.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/element.dart
@@ -5719,7 +5719,7 @@
   }
   String get displayName {
     String name = this.name;
-    if (name == null) {
+    if (name == null || name.length == 0) {
       List<Type2> normalParameterTypes = this.normalParameterTypes;
       List<Type2> optionalParameterTypes = this.optionalParameterTypes;
       Map<String, Type2> namedParameterTypes = this.namedParameterTypes;
@@ -6563,11 +6563,15 @@
     if (argumentTypes.length != parameterTypes.length) {
       throw new IllegalArgumentException("argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
     }
-    if (argumentTypes.length == 0) {
+    if (argumentTypes.length == 0 || _typeArguments.length == 0) {
+      return this;
+    }
+    List<Type2> newTypeArguments = TypeImpl.substitute(_typeArguments, argumentTypes, parameterTypes);
+    if (JavaArrays.equals(newTypeArguments, _typeArguments)) {
       return this;
     }
     InterfaceTypeImpl newType = new InterfaceTypeImpl.con1(element);
-    newType.typeArguments = TypeImpl.substitute(_typeArguments, argumentTypes, parameterTypes);
+    newType.typeArguments = newTypeArguments;
     return newType;
   }
   void appendTo(JavaStringBuilder builder) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart
index 8bc9ce1..d1658b1 100644
--- a/pkg/analyzer_experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
@@ -1109,7 +1109,11 @@
       state = state._nextState;
     }
     ;
-    return CacheState.INVALID;
+    if (identical(descriptor, DartEntry.RESOLUTION_ERRORS) || identical(descriptor, DartEntry.RESOLVED_UNIT) || identical(descriptor, DartEntry.HINTS)) {
+      return CacheState.INVALID;
+    } else {
+      throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
+    }
   }
   Object getValue(DataDescriptor descriptor) {
     if (identical(descriptor, DartEntry.ELEMENT)) {
@@ -1311,9 +1315,11 @@
     }
     if (_parsedUnitState != CacheState.VALID) {
       _parsedUnit = unit;
+      _parsedUnitState = CacheState.VALID;
     }
     if (_parseErrorsState != CacheState.VALID) {
       _parseErrors = errors == null ? AnalysisError.NO_ERRORS : errors;
+      _parseErrorsState = CacheState.VALID;
     }
   }
   void setState(DataDescriptor<Object> descriptor, CacheState state) {
@@ -4964,10 +4970,12 @@
  */
 class ResolutionEraser extends GeneralizingASTVisitor<Object> {
   Object visitAssignmentExpression(AssignmentExpression node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitAssignmentExpression(node);
   }
   Object visitBinaryExpression(BinaryExpression node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitBinaryExpression(node);
   }
@@ -4980,6 +4988,7 @@
     return super.visitConstructorDeclaration(node);
   }
   Object visitConstructorName(ConstructorName node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitConstructorName(node);
   }
@@ -4997,34 +5006,42 @@
     return super.visitFunctionExpression(node);
   }
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitFunctionExpressionInvocation(node);
   }
   Object visitIndexExpression(IndexExpression node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitIndexExpression(node);
   }
   Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitInstanceCreationExpression(node);
   }
   Object visitPostfixExpression(PostfixExpression node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitPostfixExpression(node);
   }
   Object visitPrefixExpression(PrefixExpression node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitPrefixExpression(node);
   }
   Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitRedirectingConstructorInvocation(node);
   }
   Object visitSimpleIdentifier(SimpleIdentifier node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitSimpleIdentifier(node);
   }
   Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    node.staticElement = null;
     node.element = null;
     return super.visitSuperConstructorInvocation(node);
   }
diff --git a/pkg/analyzer_experimental/lib/src/generated/error.dart b/pkg/analyzer_experimental/lib/src/generated/error.dart
index 4f53646..9729ec5 100644
--- a/pkg/analyzer_experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/error.dart
@@ -2617,18 +2617,6 @@
   static final StaticWarningCode TYPE_PARAMETER_REFERENCED_BY_STATIC = new StaticWarningCode('TYPE_PARAMETER_REFERENCED_BY_STATIC', 62, "Static members cannot reference type parameters");
 
   /**
-   * 15.1 Static Types: A type <i>T</i> is malformed iff: * <i>T</i> has the form <i>id</i> or the
-   * form <i>prefix.id</i>, and in the enclosing lexical scope, the name <i>id</i> (respectively
-   * <i>prefix.id</i>) does not denote a type. * <i>T</i> denotes a type variable in the
-   * enclosing lexical scope, but occurs in the signature or body of a static member. *
-   * <i>T</i> is a parameterized type of the form <i>G&lt;S<sub>1</sub>, .., S<sub>n</sub>&gt;</i>,
-   * and <i>G</i> is malformed.
-   *
-   * Any use of a malformed type gives rise to a static warning.
-   */
-  static final StaticWarningCode TYPE_VARIABLE_IN_STATIC_SCOPE = new StaticWarningCode('TYPE_VARIABLE_IN_STATIC_SCOPE', 63, "");
-
-  /**
    * 12.15.3 Static Invocation: A static method invocation <i>i</i> has the form
    * <i>C.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>, &hellip;
    * x<sub>n+k</sub>: a<sub>n+k</sub>)</i>. It is a static warning if <i>C</i> does not denote a
@@ -2636,12 +2624,12 @@
    *
    * @param undefinedClassName the name of the undefined class
    */
-  static final StaticWarningCode UNDEFINED_CLASS = new StaticWarningCode('UNDEFINED_CLASS', 64, "Undefined class '%s'");
+  static final StaticWarningCode UNDEFINED_CLASS = new StaticWarningCode('UNDEFINED_CLASS', 63, "Undefined class '%s'");
 
   /**
    * Same as [UNDEFINED_CLASS], but to catch using "boolean" instead of "bool".
    */
-  static final StaticWarningCode UNDEFINED_CLASS_BOOLEAN = new StaticWarningCode('UNDEFINED_CLASS_BOOLEAN', 65, "Undefined class 'boolean'; did you mean 'bool'?");
+  static final StaticWarningCode UNDEFINED_CLASS_BOOLEAN = new StaticWarningCode('UNDEFINED_CLASS_BOOLEAN', 64, "Undefined class 'boolean'; did you mean 'bool'?");
 
   /**
    * 12.17 Getter Invocation: It is a static warning if there is no class <i>C</i> in the enclosing
@@ -2651,7 +2639,7 @@
    * @param getterName the name of the getter
    * @param enclosingType the name of the enclosing type where the getter is being looked for
    */
-  static final StaticWarningCode UNDEFINED_GETTER = new StaticWarningCode('UNDEFINED_GETTER', 66, "There is no such getter '%s' in '%s'");
+  static final StaticWarningCode UNDEFINED_GETTER = new StaticWarningCode('UNDEFINED_GETTER', 65, "There is no such getter '%s' in '%s'");
 
   /**
    * 12.30 Identifier Reference: It is as static warning if an identifier expression of the form
@@ -2659,7 +2647,7 @@
    * setter) or variable initializer and there is no declaration <i>d</i> with name <i>id</i> in the
    * lexical scope enclosing the expression.
    */
-  static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode('UNDEFINED_IDENTIFIER', 67, "Undefined name '%s'");
+  static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode('UNDEFINED_IDENTIFIER', 66, "Undefined name '%s'");
 
   /**
    * 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>, <i>1<=i<=l</i>,
@@ -2668,7 +2656,7 @@
    *
    * @param name the name of the requested named parameter
    */
-  static final StaticWarningCode UNDEFINED_NAMED_PARAMETER = new StaticWarningCode('UNDEFINED_NAMED_PARAMETER', 68, "The named parameter '%s' is not defined");
+  static final StaticWarningCode UNDEFINED_NAMED_PARAMETER = new StaticWarningCode('UNDEFINED_NAMED_PARAMETER', 67, "The named parameter '%s' is not defined");
 
   /**
    * 12.18 Assignment: It is as static warning if an assignment of the form <i>v = e</i> occurs
@@ -2683,7 +2671,7 @@
    * @param setterName the name of the getter
    * @param enclosingType the name of the enclosing type where the setter is being looked for
    */
-  static final StaticWarningCode UNDEFINED_SETTER = new StaticWarningCode('UNDEFINED_SETTER', 69, "There is no such setter '%s' in '%s'");
+  static final StaticWarningCode UNDEFINED_SETTER = new StaticWarningCode('UNDEFINED_SETTER', 68, "There is no such setter '%s' in '%s'");
 
   /**
    * 12.15.3 Static Invocation: It is a static warning if <i>C</i> does not declare a static method
@@ -2692,7 +2680,7 @@
    * @param methodName the name of the method
    * @param enclosingType the name of the enclosing type where the method is being looked for
    */
-  static final StaticWarningCode UNDEFINED_STATIC_METHOD_OR_GETTER = new StaticWarningCode('UNDEFINED_STATIC_METHOD_OR_GETTER', 70, "There is no such static method '%s' in '%s'");
+  static final StaticWarningCode UNDEFINED_STATIC_METHOD_OR_GETTER = new StaticWarningCode('UNDEFINED_STATIC_METHOD_OR_GETTER', 69, "There is no such static method '%s' in '%s'");
   static final List<StaticWarningCode> values = [
       AMBIGUOUS_IMPORT,
       ARGUMENT_TYPE_NOT_ASSIGNABLE,
@@ -2757,7 +2745,6 @@
       SWITCH_EXPRESSION_NOT_ASSIGNABLE,
       TYPE_TEST_NON_TYPE,
       TYPE_PARAMETER_REFERENCED_BY_STATIC,
-      TYPE_VARIABLE_IN_STATIC_SCOPE,
       UNDEFINED_CLASS,
       UNDEFINED_CLASS_BOOLEAN,
       UNDEFINED_GETTER,
diff --git a/pkg/analyzer_experimental/lib/src/generated/parser.dart b/pkg/analyzer_experimental/lib/src/generated/parser.dart
index 16b9b5a..c406289 100644
--- a/pkg/analyzer_experimental/lib/src/generated/parser.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/parser.dart
@@ -1588,7 +1588,7 @@
             return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKeyword, validateModifiersForField(modifiers), returnType);
           }
         }
-        if (isOperator(peek())) {
+        if (isOperator(_currentToken)) {
           validateModifiersForOperator(modifiers);
           return parseOperator(commentAndMetadata, modifiers.externalKeyword, returnType);
         }
@@ -1605,7 +1605,7 @@
       validateModifiersForOperator(modifiers);
       return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
     } else if (!matchesIdentifier()) {
-      if (isOperator(peek())) {
+      if (isOperator(_currentToken)) {
         validateModifiersForOperator(modifiers);
         return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
       }
@@ -1642,7 +1642,7 @@
       if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
         return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKeyword, validateModifiersForField(modifiers), type);
       }
-      if (isOperator(peek())) {
+      if (isOperator(_currentToken)) {
         validateModifiersForOperator(modifiers);
         return parseOperator(commentAndMetadata, modifiers.externalKeyword, type);
       }
diff --git a/pkg/analyzer_experimental/lib/src/generated/resolver.dart b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
index 8672e0d..3891934 100644
--- a/pkg/analyzer_experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
@@ -8012,7 +8012,7 @@
    * @param library the library being tested
    * @return `true` if the library is 'dart:html'
    */
-  bool isHtmlLibrary(LibraryElement library) => library.name == "dart.dom.html";
+  bool isHtmlLibrary(LibraryElement library) => library != null && "dart.dom.html" == library.name;
 
   /**
    * Return `true` if the given node is not a type literal.
@@ -11577,15 +11577,6 @@
               return true;
             }
           }
-          List<PropertyAccessorElement> propertyAccessorElts = superclassElement.accessors;
-          for (PropertyAccessorElement accessorElt in propertyAccessorElts) {
-            if (accessorElt.name == executableElementName && accessorElt.isStatic) {
-              _errorReporter.reportError2(StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, errorNameTarget, [
-                  executableElementName,
-                  accessorElt.enclosingElement.displayName]);
-              return true;
-            }
-          }
           List<MethodElement> methodElements = superclassElement.methods;
           for (MethodElement methodElement in methodElements) {
             if (methodElement.name == executableElementName && methodElement.isStatic) {
@@ -13376,18 +13367,26 @@
    * Check to make sure that all similarly typed accessors are of the same type (including inherited
    * accessors).
    *
-   * @param node The accessor currently being visited.
+   * @param node the accessor currently being visited
+   * @return `true` if and only if an error code is generated on the passed node
    */
-  void checkForMismatchedAccessorTypes(Declaration accessorDeclaration, String accessorTextName) {
-    PropertyAccessorElement counterpartAccessor = null;
+  bool checkForMismatchedAccessorTypes(Declaration accessorDeclaration, String accessorTextName) {
     ExecutableElement accessorElement = accessorDeclaration.element as ExecutableElement;
     if (accessorElement is! PropertyAccessorElement) {
-      return;
+      return false;
     }
+    PropertyAccessorElement counterpartAccessor = null;
     PropertyAccessorElement propertyAccessorElement = accessorElement as PropertyAccessorElement;
-    counterpartAccessor = propertyAccessorElement.correspondingSetter;
+    if (propertyAccessorElement.isGetter) {
+      counterpartAccessor = propertyAccessorElement.correspondingSetter;
+    } else {
+      counterpartAccessor = propertyAccessorElement.correspondingGetter;
+      if (counterpartAccessor != null && identical(counterpartAccessor.enclosingElement, propertyAccessorElement.enclosingElement)) {
+        return false;
+      }
+    }
     if (counterpartAccessor == null) {
-      return;
+      return false;
     }
     Type2 getterType = null;
     Type2 setterType = null;
@@ -13404,7 +13403,9 @@
           accessorTextName,
           setterType.displayName,
           getterType.displayName]);
+      return true;
     }
+    return false;
   }
 
   /**
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk.dart b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
index e93c87b..364d40a 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
@@ -332,9 +332,8 @@
    * Return the source representing the library with the given `dart:` URI, or `null` if
    * the given URI does not denote a library in this SDK.
    *
-   * @param contentCache the content cache used to access the contents of the mapped source
    * @param dartUri the URI of the library to be returned
    * @return the source representing the specified library
    */
-  Source mapDartUri(ContentCache contentCache, String dartUri);
+  Source mapDartUri(String dartUri);
 }
\ No newline at end of file
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
index 3ea00d4..143b072 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
@@ -316,12 +316,12 @@
    * @return `true` if the Dartium binary is available
    */
   bool get isDartiumInstalled => dartiumExecutable != null;
-  Source mapDartUri(ContentCache contentCache, String dartUri) {
+  Source mapDartUri(String dartUri) {
     SdkLibrary library = getSdkLibrary(dartUri);
     if (library == null) {
       return null;
     }
-    return new FileBasedSource.con2(contentCache, new JavaFile.relative(libraryDirectory, library.path), UriKind.DART_URI);
+    return new FileBasedSource.con2(_analysisContext.sourceFactory.contentCache, new JavaFile.relative(libraryDirectory, library.path), UriKind.DART_URI);
   }
 
   /**
diff --git a/pkg/analyzer_experimental/lib/src/generated/source.dart b/pkg/analyzer_experimental/lib/src/generated/source.dart
index 560625c..e6463ff 100644
--- a/pkg/analyzer_experimental/lib/src/generated/source.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/source.dart
@@ -737,7 +737,7 @@
     if (!isDartUri(uri)) {
       return null;
     }
-    return _sdk.mapDartUri(contentCache, uri.toString());
+    return _sdk.mapDartUri(uri.toString());
   }
 }
 /**
diff --git a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
index d92be2b0..c778711 100644
--- a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
@@ -51,7 +51,6 @@
     message = 'an analysis error occured during format';
 
   String toString() => 'FormatterException: $message';
-
 }
 
 /// Specifies the kind of code snippet to format.
@@ -87,6 +86,8 @@
   final FormatterOptions options;
   final errors = <AnalysisError>[];
 
+  LineInfo lineInfo;
+
   CodeFormatterImpl(this.options);
 
   String format(CodeKind kind, String source, {int offset, int end,
@@ -98,7 +99,7 @@
     var node = parse(kind, start);
     checkForErrors();
 
-    var formatter = new SourceVisitor(options);
+    var formatter = new SourceVisitor(options, lineInfo);
     node.accept(formatter);
 
     return formatter.writer.toString();
@@ -130,7 +131,9 @@
 
   Token tokenize(String source) {
     var scanner = new StringScanner(null, source, this);
-    return scanner.tokenize();
+    var token = scanner.tokenize();
+    lineInfo = new LineInfo(scanner.lineStarts);
+    return token;
   }
 
 }
@@ -143,9 +146,11 @@
   /// The writer to which the source is to be written.
   SourceWriter writer;
 
+  LineInfo lineInfo;
+
   /// Initialize a newly created visitor to write source code representing
   /// the visited nodes to the given [writer].
-  SourceVisitor(FormatterOptions options) :
+  SourceVisitor(FormatterOptions options, this.lineInfo) :
       writer = new SourceWriter(indentCount: options.initialIndentationLevel,
                                 lineSeparator: options.lineSeparator);
 
@@ -293,7 +298,10 @@
     var prefix = scriptTag == null ? '' : ' ';
     visitPrefixedList(prefix, directives, ' ');
     prefix = scriptTag == null && directives.isEmpty ? '' : ' ';
-    visitPrefixedList(prefix, node.declarations, ' ');
+    visitPrefixedListWithBlanks(prefix, node.declarations);
+
+    //TODO(pquitslund): move this?
+    writer.newline();
   }
 
   visitConditionalExpression(ConditionalExpression node) {
@@ -646,6 +654,11 @@
     visitPrefixed(' ', node.expression);
   }
 
+  visitNativeClause(NativeClause node) {
+    writer.print('native ');
+    visit(node.name);
+  }
+
   visitNativeFunctionBody(NativeFunctionBody node) {
     writer.print('native ');
     visit(node.stringLiteral);
@@ -942,4 +955,29 @@
     }
   }
 
+  /// Print a list of [nodes], preserving blank lines between nodes.
+  visitPrefixedListWithBlanks(String prefix,
+      NodeList<ASTNode> nodes) {
+    if (nodes != null) {
+      var size = nodes.length;
+      if (size > 0) {
+        writer.print(prefix);
+        for (var i = 0; i < size; i++) {
+          if (i > 0) {
+            // Emit blanks lines
+            var lastLine =
+                lineInfo.getLocation(nodes[i-1].endToken.offset).lineNumber;
+            var currentLine =
+                lineInfo.getLocation(nodes[i].beginToken.offset).lineNumber;
+            var blanks = currentLine - lastLine;
+            for (var i = 0; i < blanks; i++) {
+              writer.newline();
+            }
+          }
+          nodes[i].accept(this);
+        }
+      }
+    }
+  }
+
 }
\ No newline at end of file
diff --git a/pkg/analyzer_experimental/test/generated/ast_test.dart b/pkg/analyzer_experimental/test/generated/ast_test.dart
index 5163120..ba2c406 100644
--- a/pkg/analyzer_experimental/test/generated/ast_test.dart
+++ b/pkg/analyzer_experimental/test/generated/ast_test.dart
@@ -16,26 +16,30 @@
 import 'test_support.dart';
 import 'scanner_test.dart' show TokenFactory;
 class NodeLocatorTest extends ParserTestCase {
-  void test_offset() {
+  void test_range() {
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit("library myLib;", []);
+    assertLocate2(unit, 4, 10, LibraryDirective);
+  }
+  void test_searchWithin_null() {
+    NodeLocator locator = new NodeLocator.con2(0, 0);
+    JUnitTestCase.assertNull(locator.searchWithin(null));
+  }
+  void test_searchWithin_offset() {
     CompilationUnit unit = ParserTestCase.parseCompilationUnit("library myLib;", []);
     assertLocate(unit, 10, SimpleIdentifier);
   }
-  void test_offsetAfterNode() {
+  void test_searchWithin_offsetAfterNode() {
     CompilationUnit unit = ParserTestCase.parseCompilationUnit(EngineTestCase.createSource(["class A {}", "class B {}"]), []);
     NodeLocator locator = new NodeLocator.con2(1024, 1024);
     ASTNode node = locator.searchWithin(unit.declarations[0]);
     JUnitTestCase.assertNull(node);
   }
-  void test_offsetBeforeNode() {
+  void test_searchWithin_offsetBeforeNode() {
     CompilationUnit unit = ParserTestCase.parseCompilationUnit(EngineTestCase.createSource(["class A {}", "class B {}"]), []);
     NodeLocator locator = new NodeLocator.con2(0, 0);
     ASTNode node = locator.searchWithin(unit.declarations[1]);
     JUnitTestCase.assertNull(node);
   }
-  void test_range() {
-    CompilationUnit unit = ParserTestCase.parseCompilationUnit("library myLib;", []);
-    assertLocate2(unit, 4, 10, LibraryDirective);
-  }
   void assertLocate(CompilationUnit unit, int offset, Type expectedClass) {
     assertLocate2(unit, offset, offset, expectedClass);
   }
@@ -43,28 +47,33 @@
     NodeLocator locator = new NodeLocator.con2(start, end);
     ASTNode node = locator.searchWithin(unit);
     JUnitTestCase.assertNotNull(node);
+    JUnitTestCase.assertSame(node, locator.foundNode);
     JUnitTestCase.assertTrueMsg("Node starts after range", node.offset <= start);
     JUnitTestCase.assertTrueMsg("Node ends before range", node.offset + node.length > end);
     EngineTestCase.assertInstanceOf(expectedClass, node);
   }
   static dartSuite() {
     _ut.group('NodeLocatorTest', () {
-      _ut.test('test_offset', () {
-        final __test = new NodeLocatorTest();
-        runJUnitTest(__test, __test.test_offset);
-      });
-      _ut.test('test_offsetAfterNode', () {
-        final __test = new NodeLocatorTest();
-        runJUnitTest(__test, __test.test_offsetAfterNode);
-      });
-      _ut.test('test_offsetBeforeNode', () {
-        final __test = new NodeLocatorTest();
-        runJUnitTest(__test, __test.test_offsetBeforeNode);
-      });
       _ut.test('test_range', () {
         final __test = new NodeLocatorTest();
         runJUnitTest(__test, __test.test_range);
       });
+      _ut.test('test_searchWithin_null', () {
+        final __test = new NodeLocatorTest();
+        runJUnitTest(__test, __test.test_searchWithin_null);
+      });
+      _ut.test('test_searchWithin_offset', () {
+        final __test = new NodeLocatorTest();
+        runJUnitTest(__test, __test.test_searchWithin_offset);
+      });
+      _ut.test('test_searchWithin_offsetAfterNode', () {
+        final __test = new NodeLocatorTest();
+        runJUnitTest(__test, __test.test_searchWithin_offsetAfterNode);
+      });
+      _ut.test('test_searchWithin_offsetBeforeNode', () {
+        final __test = new NodeLocatorTest();
+        runJUnitTest(__test, __test.test_searchWithin_offsetBeforeNode);
+      });
     });
   }
 }
@@ -350,6 +359,7 @@
   static NamedExpression namedExpression(Label label, Expression expression) => new NamedExpression.full(label, expression);
   static NamedExpression namedExpression2(String label, Expression expression) => namedExpression(label2(label), expression);
   static DefaultFormalParameter namedFormalParameter(NormalFormalParameter parameter, Expression expression) => new DefaultFormalParameter.full(parameter, ParameterKind.NAMED, expression == null ? null : TokenFactory.token3(TokenType.COLON), expression);
+  static NativeClause nativeClause(String nativeCode) => new NativeClause.full(TokenFactory.token2("native"), string2(nativeCode));
   static NativeFunctionBody nativeFunctionBody(String nativeMethodName) => new NativeFunctionBody.full(TokenFactory.token2("native"), string2(nativeMethodName), TokenFactory.token3(TokenType.SEMICOLON));
   static NullLiteral nullLiteral() => new NullLiteral.full(TokenFactory.token(Keyword.NULL));
   static ParenthesizedExpression parenthesizedExpression(Expression expression) => new ParenthesizedExpression.full(TokenFactory.token3(TokenType.OPEN_PAREN), expression, TokenFactory.token3(TokenType.CLOSE_PAREN));
@@ -364,6 +374,7 @@
   static PropertyAccess propertyAccess2(Expression target, String propertyName) => new PropertyAccess.full(target, TokenFactory.token3(TokenType.PERIOD), identifier3(propertyName));
   static RedirectingConstructorInvocation redirectingConstructorInvocation(List<Expression> arguments) => redirectingConstructorInvocation2(null, arguments);
   static RedirectingConstructorInvocation redirectingConstructorInvocation2(String constructorName, List<Expression> arguments) => new RedirectingConstructorInvocation.full(TokenFactory.token(Keyword.THIS), constructorName == null ? null : TokenFactory.token3(TokenType.PERIOD), constructorName == null ? null : identifier3(constructorName), argumentList(arguments));
+  static RethrowExpression rethrowExpression() => new RethrowExpression.full(TokenFactory.token(Keyword.RETHROW));
   static ReturnStatement returnStatement() => returnStatement2(null);
   static ReturnStatement returnStatement2(Expression expression) => new ReturnStatement.full(TokenFactory.token(Keyword.RETURN), expression, TokenFactory.token3(TokenType.SEMICOLON));
   static ScriptTag scriptTag(String scriptTag2) => new ScriptTag.full(TokenFactory.token2(scriptTag2));
@@ -1872,6 +1883,9 @@
   void test_visitNamedFormalParameter() {
     assertSource("var a : 0", ASTFactory.namedFormalParameter(ASTFactory.simpleFormalParameter(Keyword.VAR, "a"), ASTFactory.integer(0)));
   }
+  void test_visitNativeClause() {
+    assertSource("native 'code'", ASTFactory.nativeClause("code"));
+  }
   void test_visitNativeFunctionBody() {
     assertSource("native 'str';", ASTFactory.nativeFunctionBody("str"));
   }
@@ -1908,6 +1922,9 @@
   void test_visitRedirectingConstructorInvocation_unnamed() {
     assertSource("this()", ASTFactory.redirectingConstructorInvocation([]));
   }
+  void test_visitRethrowExpression() {
+    assertSource("rethrow", ASTFactory.rethrowExpression());
+  }
   void test_visitReturnStatement_expression() {
     assertSource("return a;", ASTFactory.returnStatement2(ASTFactory.identifier3("a")));
   }
@@ -2828,6 +2845,10 @@
         final __test = new ToSourceVisitorTest();
         runJUnitTest(__test, __test.test_visitNamedFormalParameter);
       });
+      _ut.test('test_visitNativeClause', () {
+        final __test = new ToSourceVisitorTest();
+        runJUnitTest(__test, __test.test_visitNativeClause);
+      });
       _ut.test('test_visitNativeFunctionBody', () {
         final __test = new ToSourceVisitorTest();
         runJUnitTest(__test, __test.test_visitNativeFunctionBody);
@@ -2876,6 +2897,10 @@
         final __test = new ToSourceVisitorTest();
         runJUnitTest(__test, __test.test_visitRedirectingConstructorInvocation_unnamed);
       });
+      _ut.test('test_visitRethrowExpression', () {
+        final __test = new ToSourceVisitorTest();
+        runJUnitTest(__test, __test.test_visitRethrowExpression);
+      });
       _ut.test('test_visitReturnStatement_expression', () {
         final __test = new ToSourceVisitorTest();
         runJUnitTest(__test, __test.test_visitReturnStatement_expression);
diff --git a/pkg/analyzer_experimental/test/generated/element_test.dart b/pkg/analyzer_experimental/test/generated/element_test.dart
index 7cd1a48..23b15b9 100644
--- a/pkg/analyzer_experimental/test/generated/element_test.dart
+++ b/pkg/analyzer_experimental/test/generated/element_test.dart
@@ -341,6 +341,19 @@
   void test_creation() {
     JUnitTestCase.assertNotNull(new InterfaceTypeImpl.con1(ElementFactory.classElement2("A", [])));
   }
+  void test_getAccessors() {
+    ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
+    PropertyAccessorElement getterG = ElementFactory.getterElement("g", false, null);
+    PropertyAccessorElement getterH = ElementFactory.getterElement("h", false, null);
+    typeElement.accessors = <PropertyAccessorElement> [getterG, getterH];
+    InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
+    JUnitTestCase.assertEquals(2, type.accessors.length);
+  }
+  void test_getAccessors_empty() {
+    ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
+    InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
+    JUnitTestCase.assertEquals(0, type.accessors.length);
+  }
   void test_getElement() {
     ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
     InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
@@ -623,6 +636,19 @@
     InterfaceType typeA = classA.type;
     JUnitTestCase.assertNull(typeA.getMethod("m"));
   }
+  void test_getMethods() {
+    ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
+    MethodElementImpl methodOne = ElementFactory.methodElement("one", null, []);
+    MethodElementImpl methodTwo = ElementFactory.methodElement("two", null, []);
+    typeElement.methods = <MethodElement> [methodOne, methodTwo];
+    InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
+    JUnitTestCase.assertEquals(2, type.methods.length);
+  }
+  void test_getMethods_empty() {
+    ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
+    InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
+    JUnitTestCase.assertEquals(0, type.methods.length);
+  }
   void test_getMixins_nonParameterized() {
     ClassElementImpl classA = ElementFactory.classElement2("A", []);
     InterfaceType typeA = classA.type;
@@ -710,6 +736,11 @@
     InterfaceType type = ElementFactory.classElement2("A", []).type;
     EngineTestCase.assertLength(0, type.typeArguments);
   }
+  void test_hashCode() {
+    ClassElement classA = ElementFactory.classElement2("A", []);
+    InterfaceType typeA = classA.type;
+    JUnitTestCase.assertFalse(0 == typeA.hashCode);
+  }
   void test_isDirectSupertypeOf_extends() {
     ClassElement classA = ElementFactory.classElement2("A", []);
     ClassElement classB = ElementFactory.classElement("B", classA.type, []);
@@ -1143,6 +1174,16 @@
     EngineTestCase.assertLength(1, resultArguments);
     JUnitTestCase.assertEquals(argumentType, resultArguments[0]);
   }
+  void test_substitute_exception() {
+    try {
+      ClassElementImpl classA = ElementFactory.classElement2("A", []);
+      InterfaceTypeImpl type = new InterfaceTypeImpl.con1(classA);
+      InterfaceType argumentType = ElementFactory.classElement2("B", []).type;
+      type.substitute2(<Type2> [argumentType], <Type2> []);
+      JUnitTestCase.fail("Expected to encounter exception, argument and parameter type array lengths not equal.");
+    } catch (e) {
+    }
+  }
   void test_substitute_notEqual() {
     ClassElementImpl classA = ElementFactory.classElement2("A", []);
     TypeVariableElementImpl parameterElement = new TypeVariableElementImpl(ASTFactory.identifier3("E"));
@@ -1207,6 +1248,14 @@
         final __test = new InterfaceTypeImplTest();
         runJUnitTest(__test, __test.test_creation);
       });
+      _ut.test('test_getAccessors', () {
+        final __test = new InterfaceTypeImplTest();
+        runJUnitTest(__test, __test.test_getAccessors);
+      });
+      _ut.test('test_getAccessors_empty', () {
+        final __test = new InterfaceTypeImplTest();
+        runJUnitTest(__test, __test.test_getAccessors_empty);
+      });
       _ut.test('test_getElement', () {
         final __test = new InterfaceTypeImplTest();
         runJUnitTest(__test, __test.test_getElement);
@@ -1315,6 +1364,14 @@
         final __test = new InterfaceTypeImplTest();
         runJUnitTest(__test, __test.test_getMethod_unimplemented);
       });
+      _ut.test('test_getMethods', () {
+        final __test = new InterfaceTypeImplTest();
+        runJUnitTest(__test, __test.test_getMethods);
+      });
+      _ut.test('test_getMethods_empty', () {
+        final __test = new InterfaceTypeImplTest();
+        runJUnitTest(__test, __test.test_getMethods_empty);
+      });
       _ut.test('test_getMixins_nonParameterized', () {
         final __test = new InterfaceTypeImplTest();
         runJUnitTest(__test, __test.test_getMixins_nonParameterized);
@@ -1347,6 +1404,10 @@
         final __test = new InterfaceTypeImplTest();
         runJUnitTest(__test, __test.test_getTypeArguments_empty);
       });
+      _ut.test('test_hashCode', () {
+        final __test = new InterfaceTypeImplTest();
+        runJUnitTest(__test, __test.test_hashCode);
+      });
       _ut.test('test_isDirectSupertypeOf_extends', () {
         final __test = new InterfaceTypeImplTest();
         runJUnitTest(__test, __test.test_isDirectSupertypeOf_extends);
@@ -1527,6 +1588,10 @@
         final __test = new InterfaceTypeImplTest();
         runJUnitTest(__test, __test.test_substitute_equal);
       });
+      _ut.test('test_substitute_exception', () {
+        final __test = new InterfaceTypeImplTest();
+        runJUnitTest(__test, __test.test_substitute_exception);
+      });
       _ut.test('test_substitute_notEqual', () {
         final __test = new InterfaceTypeImplTest();
         runJUnitTest(__test, __test.test_substitute_notEqual);
@@ -2194,8 +2259,21 @@
     ((library.definingCompilationUnit as CompilationUnitElementImpl)).types = <ClassElement> [classElement];
     JUnitTestCase.assertTrue(classElement.isAccessibleIn(library));
   }
+  void test_SORT_BY_OFFSET() {
+    ClassElementImpl classElementA = ElementFactory.classElement2("A", []);
+    classElementA.nameOffset = 1;
+    ClassElementImpl classElementB = ElementFactory.classElement2("B", []);
+    classElementB.nameOffset = 2;
+    JUnitTestCase.assertEquals(0, Element.SORT_BY_OFFSET(classElementA, classElementA));
+    JUnitTestCase.assertTrue(Element.SORT_BY_OFFSET(classElementA, classElementB) < 0);
+    JUnitTestCase.assertTrue(Element.SORT_BY_OFFSET(classElementB, classElementA) > 0);
+  }
   static dartSuite() {
     _ut.group('ElementImplTest', () {
+      _ut.test('test_SORT_BY_OFFSET', () {
+        final __test = new ElementImplTest();
+        runJUnitTest(__test, __test.test_SORT_BY_OFFSET);
+      });
       _ut.test('test_equals', () {
         final __test = new ElementImplTest();
         runJUnitTest(__test, __test.test_equals);
@@ -2261,7 +2339,7 @@
   }
   void test_isSubtypeOf_baseCase_classFunction() {
     ClassElementImpl functionElement = ElementFactory.classElement2("Function", []);
-    InterfaceTypeImpl functionType = new InterfaceTypeImpl_19(functionElement);
+    InterfaceTypeImpl functionType = new InterfaceTypeImpl_20(functionElement);
     FunctionType f = ElementFactory.functionElement("f").type;
     JUnitTestCase.assertTrue(f.isSubtypeOf(functionType));
   }
@@ -2721,8 +2799,8 @@
     });
   }
 }
-class InterfaceTypeImpl_19 extends InterfaceTypeImpl {
-  InterfaceTypeImpl_19(ClassElement arg0) : super.con1(arg0);
+class InterfaceTypeImpl_20 extends InterfaceTypeImpl {
+  InterfaceTypeImpl_20(ClassElement arg0) : super.con1(arg0);
   bool get isDartCoreFunction => true;
 }
 main() {
diff --git a/pkg/analyzer_experimental/test/generated/parser_test.dart b/pkg/analyzer_experimental/test/generated/parser_test.dart
index abe510f..2cb648e 100644
--- a/pkg/analyzer_experimental/test/generated/parser_test.dart
+++ b/pkg/analyzer_experimental/test/generated/parser_test.dart
@@ -3757,7 +3757,7 @@
    * @throws Exception if the method could not be invoked or throws an exception
    */
   String computeStringValue(String lexeme) {
-    AnalysisErrorListener listener = new AnalysisErrorListener_20();
+    AnalysisErrorListener listener = new AnalysisErrorListener_21();
     Parser parser = new Parser(null, listener);
     return invokeParserMethodImpl(parser, "computeStringValue", <Object> [lexeme], null) as String;
   }
@@ -5965,7 +5965,7 @@
     });
   }
 }
-class AnalysisErrorListener_20 implements AnalysisErrorListener {
+class AnalysisErrorListener_21 implements AnalysisErrorListener {
   void onError(AnalysisError event) {
     JUnitTestCase.fail("Unexpected compilation error: ${event.message} (${event.offset}, ${event.length})");
   }
@@ -7585,12 +7585,6 @@
   void fail_varAndType_parameter() {
     ParserTestCase.parse5("parseFormalParameterList", "(var int x)", [ParserErrorCode.VAR_AND_TYPE]);
   }
-  void fail_voidVariable_initializer() {
-    ParserTestCase.parseStatement("void x = 0;", [ParserErrorCode.VOID_VARIABLE]);
-  }
-  void fail_voidVariable_noInitializer() {
-    ParserTestCase.parseStatement("void x;", [ParserErrorCode.VOID_VARIABLE]);
-  }
   void test_abstractClassMember_constructor() {
     ParserTestCase.parse4("parseClassMember", <Object> ["C"], "abstract C.c();", [ParserErrorCode.ABSTRACT_CLASS_MEMBER]);
   }
@@ -7772,6 +7766,15 @@
   void test_expectedToken_commaMissingInArgumentList() {
     ParserTestCase.parse5("parseArgumentList", "(x, y z)", [ParserErrorCode.EXPECTED_TOKEN]);
   }
+  void test_expectedToken_parseStatement_afterVoid() {
+    ParserTestCase.parseStatement("void}", [
+        ParserErrorCode.EXPECTED_TOKEN,
+        ParserErrorCode.MISSING_IDENTIFIER]);
+  }
+  void test_expectedToken_semicolonAfterTypedef() {
+    Token token = TokenFactory.token(Keyword.TYPEDEF);
+    ParserTestCase.parse4("parseClassTypeAlias", <Object> [emptyCommentAndMetadata(), token], "A = B", [ParserErrorCode.EXPECTED_TOKEN]);
+  }
   void test_expectedToken_semicolonMissingAfterExpression() {
     ParserTestCase.parseStatement("x", [ParserErrorCode.EXPECTED_TOKEN]);
   }
@@ -8027,6 +8030,11 @@
   void test_missingIdentifier_afterOperator() {
     ParserTestCase.parse5("parseMultiplicativeExpression", "1 *", [ParserErrorCode.MISSING_IDENTIFIER]);
   }
+  void test_missingIdentifier_beforeClosingCurly() {
+    ParserTestCase.parse4("parseClassMember", <Object> ["C"], "int}", [
+        ParserErrorCode.MISSING_IDENTIFIER,
+        ParserErrorCode.EXPECTED_TOKEN]);
+  }
   void test_missingIdentifier_functionDeclaration_returnTypeWithoutName() {
     ParserTestCase.parse5("parseFunctionDeclarationStatement", "A<T> () {}", [ParserErrorCode.MISSING_IDENTIFIER]);
   }
@@ -8043,6 +8051,15 @@
   void test_missingKeywordOperator() {
     ParserTestCase.parse4("parseOperator", <Object> [emptyCommentAndMetadata(), null, null], "+(x) {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
   }
+  void test_missingKeywordOperator_parseClassMember() {
+    ParserTestCase.parse4("parseClassMember", <Object> ["C"], "+() {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
+  }
+  void test_missingKeywordOperator_parseClassMember_afterTypeName() {
+    ParserTestCase.parse4("parseClassMember", <Object> ["C"], "int +() {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
+  }
+  void test_missingKeywordOperator_parseClassMember_afterVoid() {
+    ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void +() {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
+  }
   void test_missingNameInLibraryDirective() {
     CompilationUnit unit = ParserTestCase.parseCompilationUnit("library;", [ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE]);
     JUnitTestCase.assertNotNull(unit);
@@ -8051,6 +8068,12 @@
     CompilationUnit unit = ParserTestCase.parseCompilationUnit("part of;", [ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE]);
     JUnitTestCase.assertNotNull(unit);
   }
+  void test_missingStatement() {
+    ParserTestCase.parseStatement("is", [ParserErrorCode.MISSING_STATEMENT]);
+  }
+  void test_missingStatement_afterVoid() {
+    ParserTestCase.parseStatement("void;", [ParserErrorCode.MISSING_STATEMENT]);
+  }
   void test_missingTerminatorForParameterGroup_named() {
     ParserTestCase.parse5("parseFormalParameterList", "(a, {b: 0)", [ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP]);
   }
@@ -8075,6 +8098,12 @@
   void test_mixedParameterGroups_positionalNamed() {
     ParserTestCase.parse5("parseFormalParameterList", "(a, [b], {c})", [ParserErrorCode.MIXED_PARAMETER_GROUPS]);
   }
+  void test_multipleExtendsClauses() {
+    ParserTestCase.parseCompilationUnit("class A extends B extends C {}", [ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES]);
+  }
+  void test_multipleImplementsClauses() {
+    ParserTestCase.parseCompilationUnit("class A implements B implements C {}", [ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES]);
+  }
   void test_multipleLibraryDirectives() {
     ParserTestCase.parseCompilationUnit("library l; library m;", [ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES]);
   }
@@ -8090,6 +8119,9 @@
   void test_multipleVariablesInForEach() {
     ParserTestCase.parse5("parseForStatement", "for (int a, b in foo) {}", [ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH]);
   }
+  void test_multipleWithClauses() {
+    ParserTestCase.parseCompilationUnit("class A extends B with C with D {}", [ParserErrorCode.MULTIPLE_WITH_CLAUSES]);
+  }
   void test_namedParameterOutsideGroup() {
     ParserTestCase.parse5("parseFormalParameterList", "(a, b : 0)", [ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP]);
   }
@@ -8122,6 +8154,12 @@
   void test_optionalAfterNormalParameters_positional() {
     ParserTestCase.parseCompilationUnit("f([a], b) {}", [ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS]);
   }
+  void test_parseCascadeSection_missingIdentifier() {
+    MethodInvocation methodInvocation = ParserTestCase.parse5("parseCascadeSection", "..()", [ParserErrorCode.MISSING_IDENTIFIER]);
+    JUnitTestCase.assertNull(methodInvocation.target);
+    JUnitTestCase.assertEquals("", methodInvocation.methodName.name);
+    EngineTestCase.assertSize(0, methodInvocation.argumentList.arguments);
+  }
   void test_positionalAfterNamedArgument() {
     ParserTestCase.parse5("parseArgumentList", "(x: 1, 2)", [ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT]);
   }
@@ -8227,15 +8265,37 @@
   void test_varTypedef() {
     ParserTestCase.parseCompilationUnit("var typedef F();", [ParserErrorCode.VAR_TYPEDEF]);
   }
-  void test_voidField_initializer() {
-    ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void x = 0;", [ParserErrorCode.VOID_VARIABLE]);
-  }
-  void test_voidField_noInitializer() {
-    ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void x;", [ParserErrorCode.VOID_VARIABLE]);
-  }
   void test_voidParameter() {
     ParserTestCase.parse5("parseNormalFormalParameter", "void a)", [ParserErrorCode.VOID_PARAMETER]);
   }
+  void test_voidVariable_parseClassMember_initializer() {
+    ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void x = 0;", [ParserErrorCode.VOID_VARIABLE]);
+  }
+  void test_voidVariable_parseClassMember_noInitializer() {
+    ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void x;", [ParserErrorCode.VOID_VARIABLE]);
+  }
+  void test_voidVariable_parseCompilationUnit_initializer() {
+    ParserTestCase.parseCompilationUnit("void x = 0;", [ParserErrorCode.VOID_VARIABLE]);
+  }
+  void test_voidVariable_parseCompilationUnit_noInitializer() {
+    ParserTestCase.parseCompilationUnit("void x;", [ParserErrorCode.VOID_VARIABLE]);
+  }
+  void test_voidVariable_parseCompilationUnitMember_initializer() {
+    ParserTestCase.parse4("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "void a = 0;", [ParserErrorCode.VOID_VARIABLE]);
+  }
+  void test_voidVariable_parseCompilationUnitMember_noInitializer() {
+    ParserTestCase.parse4("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "void a;", [ParserErrorCode.VOID_VARIABLE]);
+  }
+  void test_voidVariable_statement_initializer() {
+    ParserTestCase.parseStatement("void x = 0;", [
+        ParserErrorCode.VOID_VARIABLE,
+        ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE]);
+  }
+  void test_voidVariable_statement_noInitializer() {
+    ParserTestCase.parseStatement("void x;", [
+        ParserErrorCode.VOID_VARIABLE,
+        ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE]);
+  }
   void test_withBeforeExtends() {
     ParserTestCase.parseCompilationUnit("class A with B extends C {}", [ParserErrorCode.WITH_BEFORE_EXTENDS]);
   }
@@ -8492,6 +8552,14 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_expectedToken_commaMissingInArgumentList);
       });
+      _ut.test('test_expectedToken_parseStatement_afterVoid', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_expectedToken_parseStatement_afterVoid);
+      });
+      _ut.test('test_expectedToken_semicolonAfterTypedef', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_expectedToken_semicolonAfterTypedef);
+      });
       _ut.test('test_expectedToken_semicolonMissingAfterExpression', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_expectedToken_semicolonMissingAfterExpression);
@@ -8820,6 +8888,10 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_missingIdentifier_afterOperator);
       });
+      _ut.test('test_missingIdentifier_beforeClosingCurly', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_missingIdentifier_beforeClosingCurly);
+      });
       _ut.test('test_missingIdentifier_functionDeclaration_returnTypeWithoutName', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_missingIdentifier_functionDeclaration_returnTypeWithoutName);
@@ -8840,6 +8912,18 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_missingKeywordOperator);
       });
+      _ut.test('test_missingKeywordOperator_parseClassMember', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_missingKeywordOperator_parseClassMember);
+      });
+      _ut.test('test_missingKeywordOperator_parseClassMember_afterTypeName', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_missingKeywordOperator_parseClassMember_afterTypeName);
+      });
+      _ut.test('test_missingKeywordOperator_parseClassMember_afterVoid', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_missingKeywordOperator_parseClassMember_afterVoid);
+      });
       _ut.test('test_missingNameInLibraryDirective', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_missingNameInLibraryDirective);
@@ -8848,6 +8932,14 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_missingNameInPartOfDirective);
       });
+      _ut.test('test_missingStatement', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_missingStatement);
+      });
+      _ut.test('test_missingStatement_afterVoid', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_missingStatement_afterVoid);
+      });
       _ut.test('test_missingTerminatorForParameterGroup_named', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_missingTerminatorForParameterGroup_named);
@@ -8880,6 +8972,14 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_mixedParameterGroups_positionalNamed);
       });
+      _ut.test('test_multipleExtendsClauses', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_multipleExtendsClauses);
+      });
+      _ut.test('test_multipleImplementsClauses', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_multipleImplementsClauses);
+      });
       _ut.test('test_multipleLibraryDirectives', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_multipleLibraryDirectives);
@@ -8900,6 +9000,10 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_multipleVariablesInForEach);
       });
+      _ut.test('test_multipleWithClauses', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_multipleWithClauses);
+      });
       _ut.test('test_namedParameterOutsideGroup', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_namedParameterOutsideGroup);
@@ -8940,6 +9044,10 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_optionalAfterNormalParameters_positional);
       });
+      _ut.test('test_parseCascadeSection_missingIdentifier', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_parseCascadeSection_missingIdentifier);
+      });
       _ut.test('test_positionalAfterNamedArgument', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_positionalAfterNamedArgument);
@@ -9072,18 +9180,42 @@
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_varTypedef);
       });
-      _ut.test('test_voidField_initializer', () {
-        final __test = new ErrorParserTest();
-        runJUnitTest(__test, __test.test_voidField_initializer);
-      });
-      _ut.test('test_voidField_noInitializer', () {
-        final __test = new ErrorParserTest();
-        runJUnitTest(__test, __test.test_voidField_noInitializer);
-      });
       _ut.test('test_voidParameter', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_voidParameter);
       });
+      _ut.test('test_voidVariable_parseClassMember_initializer', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_voidVariable_parseClassMember_initializer);
+      });
+      _ut.test('test_voidVariable_parseClassMember_noInitializer', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_voidVariable_parseClassMember_noInitializer);
+      });
+      _ut.test('test_voidVariable_parseCompilationUnitMember_initializer', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_voidVariable_parseCompilationUnitMember_initializer);
+      });
+      _ut.test('test_voidVariable_parseCompilationUnitMember_noInitializer', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_voidVariable_parseCompilationUnitMember_noInitializer);
+      });
+      _ut.test('test_voidVariable_parseCompilationUnit_initializer', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_voidVariable_parseCompilationUnit_initializer);
+      });
+      _ut.test('test_voidVariable_parseCompilationUnit_noInitializer', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_voidVariable_parseCompilationUnit_noInitializer);
+      });
+      _ut.test('test_voidVariable_statement_initializer', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_voidVariable_statement_initializer);
+      });
+      _ut.test('test_voidVariable_statement_noInitializer', () {
+        final __test = new ErrorParserTest();
+        runJUnitTest(__test, __test.test_voidVariable_statement_noInitializer);
+      });
       _ut.test('test_withBeforeExtends', () {
         final __test = new ErrorParserTest();
         runJUnitTest(__test, __test.test_withBeforeExtends);
diff --git a/pkg/analyzer_experimental/test/generated/resolver_test.dart b/pkg/analyzer_experimental/test/generated/resolver_test.dart
index 89d8c51..6087c87 100644
--- a/pkg/analyzer_experimental/test/generated/resolver_test.dart
+++ b/pkg/analyzer_experimental/test/generated/resolver_test.dart
@@ -2142,13 +2142,7 @@
     assertNoErrors();
     verify([source]);
   }
-  void test_nonBoolExpression_assert_bool() {
-    Source source = addSource(EngineTestCase.createSource(["f() {", "  assert(true);", "}"]));
-    resolve(source);
-    assertNoErrors();
-    verify([source]);
-  }
-  void test_nonBoolExpression_assert_functionType() {
+  void test_nonBoolExpression_functionType() {
     Source source = addSource(EngineTestCase.createSource([
         "bool makeAssertion() => true;",
         "f() {",
@@ -2158,6 +2152,12 @@
     assertNoErrors();
     verify([source]);
   }
+  void test_nonBoolExpression_interfaceType() {
+    Source source = addSource(EngineTestCase.createSource(["f() {", "  assert(true);", "}"]));
+    resolve(source);
+    assertNoErrors();
+    verify([source]);
+  }
   void test_nonConstantDefaultValue_function_named() {
     Source source = addSource(EngineTestCase.createSource(["f({x : 2 + 3}) {}"]));
     resolve(source);
@@ -3527,13 +3527,13 @@
         final __test = new NonErrorResolverTest();
         runJUnitTest(__test, __test.test_newWithUndefinedConstructorDefault);
       });
-      _ut.test('test_nonBoolExpression_assert_bool', () {
+      _ut.test('test_nonBoolExpression_functionType', () {
         final __test = new NonErrorResolverTest();
-        runJUnitTest(__test, __test.test_nonBoolExpression_assert_bool);
+        runJUnitTest(__test, __test.test_nonBoolExpression_functionType);
       });
-      _ut.test('test_nonBoolExpression_assert_functionType', () {
+      _ut.test('test_nonBoolExpression_interfaceType', () {
         final __test = new NonErrorResolverTest();
-        runJUnitTest(__test, __test.test_nonBoolExpression_assert_functionType);
+        runJUnitTest(__test, __test.test_nonBoolExpression_interfaceType);
       });
       _ut.test('test_nonConstCaseExpression', () {
         final __test = new NonErrorResolverTest();
@@ -4001,6 +4001,19 @@
     assertErrors([StaticTypeWarningCode.INACCESSIBLE_SETTER]);
     verify([source]);
   }
+  void fail_invocationOfNonFunction_staticInSuperclass() {
+    Source source = addSource(EngineTestCase.createSource([
+        "class A {",
+        "  static void a() {}",
+        "}",
+        "",
+        "class B extends A {",
+        "  void b() { a(); }",
+        "}"]));
+    resolve(source);
+    assertErrors([StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
+    verify([source]);
+  }
   void test_inconsistentMethodInheritance_paramCount() {
     Source source = addSource(EngineTestCase.createSource([
         "abstract class A {",
@@ -4173,7 +4186,17 @@
     assertErrors([StaticTypeWarningCode.NON_BOOL_CONDITION]);
     verify([source]);
   }
-  void test_nonBoolExpression() {
+  void test_nonBoolExpression_functionType() {
+    Source source = addSource(EngineTestCase.createSource([
+        "int makeAssertion() => 1;",
+        "f() {",
+        "  assert(makeAssertion);",
+        "}"]));
+    resolve(source);
+    assertErrors([StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
+    verify([source]);
+  }
+  void test_nonBoolExpression_interfaceType() {
     Source source = addSource(EngineTestCase.createSource(["f() {", "  assert(0);", "}"]));
     resolve(source);
     assertErrors([StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
@@ -4624,9 +4647,13 @@
         final __test = new StaticTypeWarningCodeTest();
         runJUnitTest(__test, __test.test_nonBoolCondition_while);
       });
-      _ut.test('test_nonBoolExpression', () {
+      _ut.test('test_nonBoolExpression_functionType', () {
         final __test = new StaticTypeWarningCodeTest();
-        runJUnitTest(__test, __test.test_nonBoolExpression);
+        runJUnitTest(__test, __test.test_nonBoolExpression_functionType);
+      });
+      _ut.test('test_nonBoolExpression_interfaceType', () {
+        final __test = new StaticTypeWarningCodeTest();
+        runJUnitTest(__test, __test.test_nonBoolExpression_interfaceType);
       });
       _ut.test('test_nonTypeAsTypeArgument_notAType', () {
         final __test = new StaticTypeWarningCodeTest();
@@ -7455,7 +7482,13 @@
     assertErrors([CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD]);
     verify([source]);
   }
-  void test_initializingFormalForNonExistantField_static() {
+  void test_initializingFormalForNonExistantField_synthetic() {
+    Source source = addSource(EngineTestCase.createSource(["class A {", "  int get x => 1;", "  A(this.x) {}", "}"]));
+    resolve(source);
+    assertErrors([CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD]);
+    verify([source]);
+  }
+  void test_initializingFormalForStaticField() {
     Source source = addSource(EngineTestCase.createSource(["class A {", "  static int x;", "  A([this.x]) {}", "}"]));
     resolve(source);
     assertErrors([CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD]);
@@ -9387,9 +9420,13 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_initializingFormalForNonExistantField_optional);
       });
-      _ut.test('test_initializingFormalForNonExistantField_static', () {
+      _ut.test('test_initializingFormalForNonExistantField_synthetic', () {
         final __test = new CompileTimeErrorCodeTest();
-        runJUnitTest(__test, __test.test_initializingFormalForNonExistantField_static);
+        runJUnitTest(__test, __test.test_initializingFormalForNonExistantField_synthetic);
+      });
+      _ut.test('test_initializingFormalForStaticField', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_initializingFormalForStaticField);
       });
       _ut.test('test_instanceMemberAccessFromStatic_field', () {
         final __test = new CompileTimeErrorCodeTest();
@@ -10046,6 +10083,12 @@
   List<Expression> _unresolvedExpressions = new List<Expression>();
 
   /**
+   * A list containing all of the AST Expression nodes for which a propagated type was computed but
+   * where that type was not more specific than the static type.
+   */
+  List<Expression> _invalidlyPropagatedExpressions = new List<Expression>();
+
+  /**
    * A list containing all of the AST TypeName nodes that were not resolved.
    */
   List<TypeName> _unresolvedTypes = new List<TypeName>();
@@ -10056,6 +10099,11 @@
   int _resolvedExpressionCount = 0;
 
   /**
+   * Counter for the number of Expression nodes visited that have propagated type information.
+   */
+  int _propagatedExpressionCount = 0;
+
+  /**
    * Counter for the number of TypeName nodes visited that are resolved.
    */
   int _resolvedTypeCount = 0;
@@ -10065,20 +10113,14 @@
    */
   void assertResolved() {
     if (!_unresolvedExpressions.isEmpty || !_unresolvedTypes.isEmpty) {
-      int unresolvedExpressionCount = _unresolvedExpressions.length;
-      int unresolvedTypeCount = _unresolvedTypes.length;
       PrintStringWriter writer = new PrintStringWriter();
-      writer.print("Failed to associate types with nodes: ");
-      writer.print(unresolvedExpressionCount);
-      writer.print("/");
-      writer.print(_resolvedExpressionCount + unresolvedExpressionCount);
-      writer.print(" Expressions and ");
-      writer.print(unresolvedTypeCount);
-      writer.print("/");
-      writer.print(_resolvedTypeCount + unresolvedTypeCount);
-      writer.println(" TypeNames.");
+      int unresolvedTypeCount = _unresolvedTypes.length;
       if (unresolvedTypeCount > 0) {
-        writer.println("TypeNames:");
+        writer.print("Failed to resolve ");
+        writer.print(unresolvedTypeCount);
+        writer.print(" of ");
+        writer.print(_resolvedTypeCount + unresolvedTypeCount);
+        writer.println(" type names:");
         for (TypeName identifier in _unresolvedTypes) {
           writer.print("  ");
           writer.print(identifier.toString());
@@ -10089,15 +10131,42 @@
           writer.println(")");
         }
       }
+      int unresolvedExpressionCount = _unresolvedExpressions.length;
       if (unresolvedExpressionCount > 0) {
-        writer.println("Expressions:");
-        for (Expression identifier in _unresolvedExpressions) {
+        writer.println("Failed to resolve ");
+        writer.print(unresolvedExpressionCount);
+        writer.print(" of ");
+        writer.print(_resolvedExpressionCount + unresolvedExpressionCount);
+        writer.println(" expressions:");
+        for (Expression expression in _unresolvedExpressions) {
           writer.print("  ");
-          writer.print(identifier.toString());
+          writer.print(expression.toString());
           writer.print(" (");
-          writer.print(getFileName(identifier));
+          writer.print(getFileName(expression));
           writer.print(" : ");
-          writer.print(identifier.offset);
+          writer.print(expression.offset);
+          writer.println(")");
+        }
+      }
+      int invalidlyPropagatedExpressionCount = _invalidlyPropagatedExpressions.length;
+      if (invalidlyPropagatedExpressionCount > 0) {
+        writer.println("Incorrectly propagated ");
+        writer.print(invalidlyPropagatedExpressionCount);
+        writer.print(" of ");
+        writer.print(_propagatedExpressionCount);
+        writer.println(" expressions:");
+        for (Expression expression in _invalidlyPropagatedExpressions) {
+          writer.print("  ");
+          writer.print(expression.toString());
+          writer.print(" [");
+          writer.print(expression.staticType.displayName);
+          writer.print(", ");
+          writer.print(expression.propagatedType.displayName);
+          writer.println("]");
+          writer.print("    ");
+          writer.print(getFileName(expression));
+          writer.print(" : ");
+          writer.print(expression.offset);
           writer.println(")");
         }
       }
@@ -10110,10 +10179,18 @@
   Object visitExportDirective(ExportDirective node) => null;
   Object visitExpression(Expression node) {
     node.visitChildren(this);
-    if (node.staticType == null) {
+    Type2 staticType = node.staticType;
+    if (staticType == null) {
       _unresolvedExpressions.add(node);
     } else {
       _resolvedExpressionCount++;
+      Type2 propagatedType = node.propagatedType;
+      if (propagatedType != null) {
+        _propagatedExpressionCount++;
+        if (!propagatedType.isMoreSpecificThan(staticType)) {
+          _invalidlyPropagatedExpressions.add(node);
+        }
+      }
     }
     return null;
   }
@@ -13945,8 +14022,13 @@
     if (!node.operator.isUserDefinableOperator) {
       return null;
     }
+    Type2 operandType = node.leftOperand.staticType;
+    if (operandType == null || operandType.isDynamic) {
+      return null;
+    }
     return checkResolved2(node, node.element, MethodElement);
   }
+  Object visitCommentReference(CommentReference node) => null;
   Object visitCompilationUnit(CompilationUnit node) {
     node.visitChildren(this);
     return checkResolved2(node, node.element, CompilationUnitElement);
@@ -13961,7 +14043,7 @@
   }
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     node.visitChildren(this);
-    return checkResolved2(node, node.element, FunctionElement);
+    return null;
   }
   Object visitImportDirective(ImportDirective node) {
     checkResolved2(node, node.element, ImportElement);
@@ -13973,9 +14055,14 @@
   }
   Object visitIndexExpression(IndexExpression node) {
     node.visitChildren(this);
+    Type2 targetType = node.realTarget.staticType;
+    if (targetType == null || targetType.isDynamic) {
+      return null;
+    }
     return checkResolved2(node, node.element, MethodElement);
   }
   Object visitLibraryDirective(LibraryDirective node) => checkResolved2(node, node.element, LibraryElement);
+  Object visitNamedExpression(NamedExpression node) => node.expression.accept(this);
   Object visitPartDirective(PartDirective node) => checkResolved2(node, node.element, CompilationUnitElement);
   Object visitPartOfDirective(PartOfDirective node) => checkResolved2(node, node.element, LibraryElement);
   Object visitPostfixExpression(PostfixExpression node) {
@@ -13983,27 +14070,61 @@
     if (!node.operator.isUserDefinableOperator) {
       return null;
     }
+    Type2 operandType = node.operand.staticType;
+    if (operandType == null || operandType.isDynamic) {
+      return null;
+    }
     return checkResolved2(node, node.element, MethodElement);
   }
+  Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+    SimpleIdentifier prefix = node.prefix;
+    prefix.accept(this);
+    Type2 prefixType = prefix.staticType;
+    if (prefixType == null || prefixType.isDynamic) {
+      return null;
+    }
+    return checkResolved(node, node.element);
+  }
   Object visitPrefixExpression(PrefixExpression node) {
     node.visitChildren(this);
     if (!node.operator.isUserDefinableOperator) {
       return null;
     }
+    Type2 operandType = node.operand.staticType;
+    if (operandType == null || operandType.isDynamic) {
+      return null;
+    }
     return checkResolved2(node, node.element, MethodElement);
   }
+  Object visitPropertyAccess(PropertyAccess node) {
+    Expression target = node.realTarget;
+    target.accept(this);
+    Type2 targetType = target.staticType;
+    if (targetType == null || targetType.isDynamic) {
+      return null;
+    }
+    return node.propertyName.accept(this);
+  }
   Object visitSimpleIdentifier(SimpleIdentifier node) {
     if (node.name == "void") {
       return null;
     }
+    ASTNode parent = node.parent;
+    if (parent is MethodInvocation) {
+      MethodInvocation invocation = (parent as MethodInvocation);
+      if (identical(invocation.methodName, node)) {
+        Expression target = invocation.realTarget;
+        Type2 targetType = target == null ? null : target.staticType;
+        if (targetType == null || targetType.isDynamic) {
+          return null;
+        }
+      }
+    }
     return checkResolved(node, node.element);
   }
   Object checkResolved(ASTNode node, Element element) => checkResolved2(node, element, null);
   Object checkResolved2(ASTNode node, Element element, Type expectedClass) {
     if (element == null) {
-      if (node.parent is CommentReference) {
-        return null;
-      }
       if (_knownExceptions == null || !_knownExceptions.contains(node)) {
         _unresolvedNodes.add(node);
       }
@@ -15187,7 +15308,7 @@
   void test_define_duplicate() {
     LibraryElement definingLibrary2 = createTestLibrary();
     GatheringErrorListener errorListener2 = new GatheringErrorListener();
-    Scope rootScope = new Scope_17(definingLibrary2, errorListener2);
+    Scope rootScope = new Scope_18(definingLibrary2, errorListener2);
     EnclosedScope scope = new EnclosedScope(rootScope);
     VariableElement element1 = ElementFactory.localVariableElement(ASTFactory.identifier3("v1"));
     VariableElement element2 = ElementFactory.localVariableElement(ASTFactory.identifier3("v1"));
@@ -15198,7 +15319,7 @@
   void test_define_normal() {
     LibraryElement definingLibrary3 = createTestLibrary();
     GatheringErrorListener errorListener3 = new GatheringErrorListener();
-    Scope rootScope = new Scope_18(definingLibrary3, errorListener3);
+    Scope rootScope = new Scope_19(definingLibrary3, errorListener3);
     EnclosedScope outerScope = new EnclosedScope(rootScope);
     EnclosedScope innerScope = new EnclosedScope(outerScope);
     VariableElement element1 = ElementFactory.localVariableElement(ASTFactory.identifier3("v1"));
@@ -15220,18 +15341,18 @@
     });
   }
 }
-class Scope_17 extends Scope {
+class Scope_18 extends Scope {
   LibraryElement definingLibrary2;
   GatheringErrorListener errorListener2;
-  Scope_17(this.definingLibrary2, this.errorListener2) : super();
+  Scope_18(this.definingLibrary2, this.errorListener2) : super();
   LibraryElement get definingLibrary => definingLibrary2;
   AnalysisErrorListener get errorListener => errorListener2;
   Element lookup3(Identifier identifier, String name, LibraryElement referencingLibrary) => null;
 }
-class Scope_18 extends Scope {
+class Scope_19 extends Scope {
   LibraryElement definingLibrary3;
   GatheringErrorListener errorListener3;
-  Scope_18(this.definingLibrary3, this.errorListener3) : super();
+  Scope_19(this.definingLibrary3, this.errorListener3) : super();
   LibraryElement get definingLibrary => definingLibrary3;
   AnalysisErrorListener get errorListener => errorListener3;
   Element lookup3(Identifier identifier, String name, LibraryElement referencingLibrary) => null;
diff --git a/pkg/analyzer_experimental/test/services/formatter_test.dart b/pkg/analyzer_experimental/test/services/formatter_test.dart
index 145aef6..41e5379 100644
--- a/pkg/analyzer_experimental/test/services/formatter_test.dart
+++ b/pkg/analyzer_experimental/test/services/formatter_test.dart
@@ -26,7 +26,7 @@
           'class A  {\n'
           '}',
           'class A {\n'
-          '}'
+          '}\n'
         );
     });
 
@@ -35,7 +35,7 @@
           'class      A  {  \n'
           '}',
           'class A {\n'
-          '}'
+          '}\n'
         );
     });
 
@@ -44,7 +44,7 @@
           'class A {\n'
           '  }',
           'class A {\n'
-          '}'
+          '}\n'
         );
     });
 
@@ -53,7 +53,7 @@
           ' class A {\n'
           '}',
           'class A {\n'
-          '}'
+          '}\n'
         );
     });
 
@@ -66,7 +66,7 @@
           'class A {\n'
           '  void x() {\n'
           '  }\n'
-          '}'
+          '}\n'
         );
     });
 
@@ -79,7 +79,7 @@
           '  static bool x() {\n'
           '    return true;\n'
           '  }\n'
-          '}'
+          '}\n'
         );
     });
 
@@ -90,7 +90,7 @@
           '   }',
           'class A {\n'
           '  int x() => 42 + 3;\n'
-          '}'
+          '}\n'
         );
     });
 
@@ -110,10 +110,37 @@
           '      return false;\n'
           '    }\n'
           '  }\n'
-          '}'
+          '}\n'
         );
     });
 
+    test('CU (multiple members)', () {
+      expectCUFormatsTo(
+          'class A {\n'
+          '}\n'
+          'class B {\n'
+          '}\n',
+          'class A {\n'
+          '}\n'
+          'class B {\n'
+          '}\n'
+        );
+    });
+
+    test('CU (multiple members w/blanks)', () {
+      expectCUFormatsTo(
+          'class A {\n'
+          '}\n\n'
+          'class B {\n'
+          '}\n',
+          'class A {\n'
+          '}\n\n'
+          'class B {\n'
+          '}\n'
+        );
+    });
+    
+
     test('stmt', () {
       expectStmtFormatsTo(
          'if (true){\n'
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
index b4efbc7..e16f94b 100644
--- a/pkg/barback/lib/src/phase.dart
+++ b/pkg/barback/lib/src/phase.dart
@@ -141,11 +141,21 @@
   ///
   /// Passes their outputs to the next phase.
   Future _processTransforms() {
-    var dirtyTransforms = _transforms.where((transform) => transform.isDirty);
+    // Convert this to a list so we can safely modify _transforms while
+    // iterating over it.
+    var dirtyTransforms = _transforms.where((transform) => transform.isDirty)
+        .toList();
     if (dirtyTransforms.isEmpty) return null;
 
-    return Future.wait(dirtyTransforms.map((transform) => transform.apply()))
-        .then((transformOutputs) {
+    return Future.wait(dirtyTransforms.map((transform) {
+      if (inputs.containsKey(transform.primary.id)) return transform.apply();
+
+      // If the primary input for the transform has been removed, get rid of it
+      // and all its outputs.
+      _transforms.remove(transform);
+      return new Future.value(
+          new TransformOutputs(new AssetSet(), transform.outputs));
+    })).then((transformOutputs) {
       // Collect all of the outputs. Since the transforms are run in parallel,
       // we have to be careful here to ensure that the result is deterministic
       // and not influenced by the order that transforms complete.
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index b17c9a5..84e42c0 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -43,6 +43,7 @@
   /// The outputs created by this transform the last time it was run.
   ///
   /// Used to tell if an output was removed in a later run.
+  Set<AssetId> get outputs => _outputs;
   var _outputs = new Set<AssetId>();
 
   TransformNode(this.phase, this._transformer, this.primary);
diff --git a/pkg/barback/test/package_graph/source_test.dart b/pkg/barback/test/package_graph/source_test.dart
index 0367d88..0185679 100644
--- a/pkg/barback/test/package_graph/source_test.dart
+++ b/pkg/barback/test/package_graph/source_test.dart
@@ -17,6 +17,7 @@
     initGraph(["app|foo.txt"]);
     updateSources(["app|foo.txt"]);
     expectAsset("app|foo.txt");
+    buildShouldSucceed();
   });
 
   test("doesn't get an unknown source", () {
@@ -49,6 +50,7 @@
 
     updateSources(["app|foo.txt"]);
     expectAsset("app|foo.txt");
+    buildShouldSucceed();
   });
 
   test("doesn't get a removed source", () {
@@ -56,12 +58,14 @@
 
     updateSources(["app|foo.txt"]);
     expectAsset("app|foo.txt");
+    buildShouldSucceed();
 
     schedule(() {
       removeSources(["app|foo.txt"]);
     });
 
     expectNoAsset("app|foo.txt");
+    buildShouldSucceed();
   });
 
   test("collapses redundant updates", () {
@@ -77,6 +81,7 @@
     });
 
     expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
 
     schedule(() {
       expect(transformer.numRuns, equals(1));
@@ -92,6 +97,7 @@
     });
 
     expectNoAsset("app|foo.txt");
+    buildShouldSucceed();
   });
 
   test("an update cancels out a removal", () {
@@ -103,6 +109,7 @@
     });
 
     expectAsset("app|foo.txt");
+    buildShouldSucceed();
   });
 
   test("restarts a build if a source is updated while sources are loading", () {
diff --git a/pkg/barback/test/package_graph/transform_test.dart b/pkg/barback/test/package_graph/transform_test.dart
index ceabe21..bcb7c33 100644
--- a/pkg/barback/test/package_graph/transform_test.dart
+++ b/pkg/barback/test/package_graph/transform_test.dart
@@ -19,6 +19,7 @@
     ]});
     updateSources(["app|foo.blub"]);
     expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
   });
 
   test("gets a transformed asset with the same path", () {
@@ -27,6 +28,7 @@
     ]});
     updateSources(["app|foo.blub"]);
     expectAsset("app|foo.blub", "foo.blub");
+    buildShouldSucceed();
   });
 
   test("doesn't find an output from a later phase", () {
@@ -36,6 +38,7 @@
     ]});
     updateSources(["app|foo.a"]);
     expectNoAsset("app|foo.c");
+    buildShouldSucceed();
   });
 
   test("doesn't find an output from the same phase", () {
@@ -48,6 +51,7 @@
     updateSources(["app|foo.a"]);
     expectAsset("app|foo.b", "foo.b");
     expectNoAsset("app|foo.c");
+    buildShouldSucceed();
   });
 
   test("finds the latest output before the transformer's phase", () {
@@ -61,6 +65,7 @@
     ]});
     updateSources(["app|foo.blub"]);
     expectAsset("app|foo.done", "foo.blub.done");
+    buildShouldSucceed();
   });
 
   test("applies multiple transformations to an asset", () {
@@ -78,6 +83,7 @@
     ]});
     updateSources(["app|foo.a"]);
     expectAsset("app|foo.k", "foo.b.c.d.e.f.g.h.i.j.k");
+    buildShouldSucceed();
   });
 
   test("only runs a transform once for all of its outputs", () {
@@ -87,6 +93,7 @@
     expectAsset("app|foo.a", "foo.a");
     expectAsset("app|foo.b", "foo.b");
     expectAsset("app|foo.c", "foo.c");
+    buildShouldSucceed();
     schedule(() {
       expect(transformer.numRuns, equals(1));
     });
@@ -118,6 +125,7 @@
 
     expectAsset("app|foo.a", "foo.a");
     expectAsset("app|foo.b", "foo.b");
+    buildShouldSucceed();
   });
 
   test("does not reapply transform when inputs are not modified", () {
@@ -127,6 +135,7 @@
     expectAsset("app|foo.blab", "foo.blab");
     expectAsset("app|foo.blab", "foo.blab");
     expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
 
     schedule(() {
       expect(transformer.numRuns, equals(1));
@@ -142,18 +151,21 @@
     });
 
     expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
 
     schedule(() {
       updateSources(["app|foo.blub"]);
     });
 
     expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
 
     schedule(() {
       updateSources(["app|foo.blub"]);
     });
 
     expectAsset("app|foo.blab", "foo.blab");
+    buildShouldSucceed();
 
     schedule(() {
       expect(transformer.numRuns, equals(3));
@@ -171,6 +183,7 @@
     updateSources(["app|a.txt", "app|a.inc", "app|b.inc"]);
 
     expectAsset("app|a.out", "ab");
+    buildShouldSucceed();
 
     // Remove the dependency on the non-primary input.
     schedule(() {
@@ -180,6 +193,7 @@
 
     // Process it again.
     expectAsset("app|a.out", "a");
+    buildShouldSucceed();
 
     // Now touch the removed input. It should not trigger another build.
     schedule(() {
@@ -187,6 +201,7 @@
     });
 
     expectAsset("app|a.out", "a");
+    buildShouldSucceed();
 
     schedule(() {
       expect(transformer.numRuns, equals(2));
@@ -202,6 +217,7 @@
 
     expectAsset("app|a.out", "spread txt");
     expectAsset("app|b.out", "spread txt");
+    buildShouldSucceed();
   });
 
   test("does not rebuild transforms that don't use modified source", () {
@@ -219,6 +235,7 @@
 
     expectAsset("app|foo.aaa", "foo.aa.aaa");
     expectAsset("app|foo.bbb", "foo.bb.bbb");
+    buildShouldSucceed();
 
     schedule(() {
       updateSources(["app|foo.a"]);
@@ -226,6 +243,7 @@
 
     expectAsset("app|foo.aaa", "foo.aa.aaa");
     expectAsset("app|foo.bbb", "foo.bb.bbb");
+    buildShouldSucceed();
 
     schedule(() {
       expect(aa.numRuns, equals(2));
@@ -241,12 +259,14 @@
 
     updateSources(["app|foo.txt"]);
     expectAsset("app|foo.out", "foo.out");
+    buildShouldSucceed();
 
     schedule(() {
       removeSources(["app|foo.txt"]);
     });
 
     expectNoAsset("app|foo.out");
+    buildShouldSucceed();
   });
 
   test("reapplies a transform when a non-primary input changes", () {
@@ -257,6 +277,7 @@
 
     updateSources(["app|a.txt", "app|a.inc"]);
     expectAsset("app|a.out", "a");
+    buildShouldSucceed();
 
     schedule(() {
       modifyAsset("app|a.inc", "after");
@@ -264,6 +285,7 @@
     });
 
     expectAsset("app|a.out", "after");
+    buildShouldSucceed();
   });
 
   test("restarts processing if a change occurs during processing", () {
@@ -289,6 +311,7 @@
     });
 
     expectAsset("app|foo.out", "foo.out");
+    buildShouldSucceed();
 
     schedule(() {
       expect(transformer.numRuns, equals(2));
@@ -309,6 +332,7 @@
     expectAsset("app|a.out", "spread a");
     expectAsset("app|b.out", "spread b");
     expectAsset("app|shared.out", "spread a");
+    buildShouldSucceed();
 
     // Now switch their contents so that "shared.out" will be output by "b.b"'s
     // transformer.
@@ -321,6 +345,7 @@
     expectAsset("app|a.out", "spread a");
     expectAsset("app|b.out", "spread b");
     expectAsset("app|shared.out", "spread b");
+    buildShouldSucceed();
   });
 
   test("restarts before finishing later phases when a change occurs", () {
@@ -349,6 +374,7 @@
 
     expectAsset("app|foo.out", "foo.int.out");
     expectAsset("app|bar.out", "bar.int.out");
+    buildShouldSucceed();
 
     schedule(() {
       // Should only have run each transform once for each primary.
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index f88df54..5d0b391 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -50,6 +50,9 @@
 /// Resolves reference links in doc comments.
 markdown.Resolver linkResolver;
 
+/// Index of all the qualified names documented. 
+Set<String> qualifiedNameIndex = new Set<String>();
+
 /**
  * Docgen constructor initializes the link resolver for markdown parsing.
  * Also initializes the command line arguments.
@@ -217,6 +220,9 @@
   // to read in.
   _writeToFile(listDir('docs').join('\n').replaceAll('docs/', ''),
       'library_list.txt');
+  // Outputs all the qualified names documented. This will help generate search
+  // results. 
+  _writeToFile(qualifiedNameIndex.join('\n'), 'index.txt');
 }
 
 Library generateLibrary(dart2js.Dart2JsLibraryMirror library,
@@ -302,7 +308,7 @@
       _currentMember = mirror;
       data[mirrorName] = new Variable(mirrorName, mirror.isFinal, 
           mirror.isStatic, mirror.type.qualifiedName, _getComment(mirror), 
-          _getAnnotations(mirror));
+          _getAnnotations(mirror), mirror.qualifiedName);
     }
   });
   return data;
@@ -324,7 +330,8 @@
     if (includePrivate || !mirror.isPrivate) {
       var method = new Method(mirrorName, mirror.isStatic, 
           mirror.returnType.qualifiedName, _getComment(mirror), 
-          _getParameters(mirror.parameters), _getAnnotations(mirror));
+          _getParameters(mirror.parameters), _getAnnotations(mirror),
+          mirror.qualifiedName);
       _currentMember = mirror;
       if (mirror.isSetter) {
         setters[mirrorName] = method;
@@ -337,15 +344,17 @@
       } else if (mirror.isRegularMethod) {
          methods[mirrorName] = method;
       } else {
-        throw new StateError('${mirror.qualifiedName} - no method type match');
+        throw new ArgumentError('$mirrorName - no method type match');
       }
     }
   });
-  return {'setters' : setters,
-          'getters' : getters,
-          'constructors' : constructors,
-          'operators' : operators,
-          'methods' : methods};
+  return {
+    'setters': setters,
+    'getters': getters,
+    'constructors': constructors,
+    'operators': operators,
+    'methods': methods
+  };
 } 
 
 /**
@@ -353,22 +362,43 @@
  */
 Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap,
     bool includePrivate) {
-  var data = {};
+  
+  var abstractClasses = {};
+  var classes = {};
+  var typedefs = {};
+  var errors = {};
+  
   mirrorMap.forEach((String mirrorName, ClassMirror mirror) {
     if (includePrivate || !mirror.isPrivate) {
-      _currentClass = mirror;
       var superclass = (mirror.superclass != null) ?
           mirror.superclass.qualifiedName : '';
       var interfaces =
           mirror.superinterfaces.map((interface) => interface.qualifiedName);
-      data[mirrorName] = new Class(mirrorName, superclass, mirror.isAbstract, 
-          mirror.isTypedef, _getComment(mirror), interfaces.toList(),
-          _getVariables(mirror.variables, includePrivate),
+      var clazz = new Class(mirrorName, superclass, _getComment(mirror), 
+          interfaces.toList(), _getVariables(mirror.variables, includePrivate),
           _getMethods(mirror.methods, includePrivate),
-          _getAnnotations(mirror));
+          _getAnnotations(mirror), mirror.qualifiedName);
+      _currentClass = mirror;
+      
+      if (isError(mirror.qualifiedName)) {
+        errors[mirrorName] = clazz;
+      } else if (mirror.isTypedef) {
+        typedefs[mirrorName] = clazz;
+      } else if (mirror.isAbstract) {
+        abstractClasses[mirrorName] = clazz;
+      } else if (mirror.isClass) {
+        classes[mirrorName] = clazz;
+      } else {
+        throw new ArgumentError('$mirrorName - no class type match. ');
+      }
     }
   });
-  return data;
+  return {
+    'abstract': abstractClasses, 
+    'class': classes,
+    'typedef': typedefs,
+    'error': errors
+  };
 }
 
 /**
@@ -417,10 +447,24 @@
   return outputMap;
 }
 
+bool isError(String qualifiedName) {
+  return qualifiedName.toLowerCase().contains('error') || 
+      qualifiedName.toLowerCase().contains('exception');
+}
+
+/**
+ * A class representing all programming constructs, like library or class. 
+ */
+class Indexable {
+  Indexable(String qualifiedName) {
+    qualifiedNameIndex.add(qualifiedName);
+  }
+}
+
 /**
  * A class containing contents of a Dart library.
  */
-class Library {
+class Library extends Indexable {
 
   /// Documentation comment with converted markdown.
   String comment;
@@ -436,8 +480,10 @@
 
   String name;
 
-  Library(this.name, this.comment, this.variables,
-      this.functions, this.classes);
+  Library(name, this.comment, this.variables,
+      this.functions, this.classes) : super(name) {
+    this.name = name; 
+  }
 
   /// Generates a map describing the [Library] object.
   Map toMap() {
@@ -455,7 +501,7 @@
  * A class containing contents of a Dart class.
  */
 // TODO(tmandel): Figure out how to do typedefs (what is needed)
-class Class {
+class Class extends Indexable {
 
   /// Documentation comment with converted markdown.
   String comment;
@@ -471,15 +517,13 @@
   
   String name;
   String superclass;
-  bool isAbstract;
-  bool isTypedef;
 
   /// List of the meta annotations on the class.
   List<String> annotations;
   
-  Class(this.name, this.superclass, this.isAbstract, this.isTypedef, 
-      this.comment, this.interfaces, this.variables, this.methods, 
-      this.annotations);
+  Class(this.name, this.superclass, this.comment, this.interfaces, 
+      this.variables, this.methods, this.annotations, 
+      String qualifiedName) : super(qualifiedName) {}
 
   /// Generates a map describing the [Class] object.
   Map toMap() {
@@ -487,8 +531,6 @@
     classMap['name'] = name;
     classMap['comment'] = comment;
     classMap['superclass'] = superclass;
-    classMap['abstract'] = isAbstract.toString();
-    classMap['typedef'] = isTypedef.toString();
     classMap['implements'] = new List.from(interfaces);
     classMap['variables'] = recurseMap(variables);
     classMap['methods'] = recurseMap(methods);
@@ -500,7 +542,7 @@
 /**
  * A class containing properties of a Dart variable.
  */
-class Variable {
+class Variable extends Indexable {
 
   /// Documentation comment with converted markdown.
   String comment;
@@ -514,7 +556,7 @@
   List<String> annotations;
   
   Variable(this.name, this.isFinal, this.isStatic, this.type, this.comment, 
-      this.annotations);
+      this.annotations, String qualifiedName) : super(qualifiedName);
   
   /// Generates a map describing the [Variable] object.
   Map toMap() {
@@ -532,7 +574,7 @@
 /**
  * A class containing properties of a Dart method.
  */
-class Method {
+class Method extends Indexable {
 
   /// Documentation comment with converted markdown.
   String comment;
@@ -548,7 +590,8 @@
   List<String> annotations;
   
   Method(this.name, this.isStatic, this.returnType, this.comment, 
-      this.parameters, this.annotations);
+      this.parameters, this.annotations, String qualifiedName) 
+      : super(qualifiedName);
   
   /// Generates a map describing the [Method] object.
   Map toMap() {
diff --git a/pkg/docgen/test/single_library_test.dart b/pkg/docgen/test/single_library_test.dart
index f00ddc4..6ff1539 100644
--- a/pkg/docgen/test/single_library_test.dart
+++ b/pkg/docgen/test/single_library_test.dart
@@ -54,7 +54,11 @@
               includePrivate: true);
           expect(library is Library, isTrue);
           
-          var classes = library.classes.values;
+          var classTypes = library.classes.values;
+          expect(classTypes.every((e) => e is Map), isTrue);
+          
+          var classes = [];
+          classTypes.forEach((e) => classes.addAll(e.values));
           expect(classes.every((e) => e is Class), isTrue);
           
           var classMethodTypes = [];
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index 02eb213..6c8a6f4 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -20,7 +20,7 @@
    * The minimum positive value attainable by an [int32], namely
    * -2147483648.
    */
-  static int32 MIN_VALUE = const int32._internal(0x80000000);
+  static int32 MIN_VALUE = const int32._internal(-0x80000000);
 
   /**
    * An [int32] constant equal to 0.
diff --git a/pkg/fixnum/pubspec.yaml b/pkg/fixnum/pubspec.yaml
index bdb079c..c582394 100644
--- a/pkg/fixnum/pubspec.yaml
+++ b/pkg/fixnum/pubspec.yaml
@@ -1,5 +1,6 @@
 name: fixnum
-author: "Dart Team <misc@dartlang.org>"
+author: Dart Team <misc@dartlang.org>
+description: Library for 32- and 64-bit fixed size integers.
 homepage: http://www.dartlang.org
-description: >
-  Library for 32- and 64-bit fixed size integers.
+dev_dependencies:
+  unittest: any
diff --git a/pkg/fixnum/test/int_32_test.dart b/pkg/fixnum/test/int_32_test.dart
index 407f2a0..77a6b27 100644
--- a/pkg/fixnum/test/int_32_test.dart
+++ b/pkg/fixnum/test/int_32_test.dart
@@ -3,157 +3,234 @@
 // BSD-style license that can be found in the LICENSE file.
 
 library int32test;
-import "package:expect/expect.dart";
 import 'package:fixnum/fixnum.dart';
+import 'package:unittest/unittest.dart';
 
 void main() {
-  Expect.equals("0", new int32.fromInt(0).toString());
-  Expect.equals("1", new int32.fromInt(1).toString());
-  Expect.equals("-1", new int32.fromInt(-1).toString());
-  Expect.equals("1000", new int32.fromInt(1000).toString());
-  Expect.equals("-1000", new int32.fromInt(-1000).toString());
-  Expect.equals("2147483647", new int32.fromInt(2147483647).toString());
-  Expect.equals("-2147483648", new int32.fromInt(2147483648).toString());
-  Expect.equals("-2147483647", new int32.fromInt(2147483649).toString());
-  Expect.equals("-2147483646", new int32.fromInt(2147483650).toString());
-  Expect.equals("-2147483648", new int32.fromInt(-2147483648).toString());
-  Expect.equals("2147483647", new int32.fromInt(-2147483649).toString());
-  Expect.equals("2147483646",  new int32.fromInt(-2147483650).toString());
+  group("arithmetic operators", () {
+    int32 n1 = new int32.fromInt(1234);
+    int32 n2 = new int32.fromInt(9876);
+    int32 n3 = new int32.fromInt(-1234);
+    int32 n4 = new int32.fromInt(-9876);
+    int32 n5 = new int32.fromInt(0x12345678);
+    int32 n6 = new int32.fromInt(0x22222222);
 
-  Expect.equals("-1", new int32.fromInt(-1).toHexString());
-  Expect.equals("-1", (new int32.fromInt(-1) >> 8).toHexString());
-  Expect.equals("-100", (new int32.fromInt(-1) << 8).toHexString());
-  Expect.equals("ffffff",
-      new int32.fromInt(-1).shiftRightUnsigned(8).toHexString());
+    test("+", () {
+      expect(n1 + n2, new int32.fromInt(11110));
+      expect(n3 + n2, new int32.fromInt(8642));
+      expect(n3 + n4, new int32.fromInt(-11110));
+      expect(int32.MAX_VALUE + 1, int32.MIN_VALUE);
+      expect(() => new int32.fromInt(17) + null, throws);
+    });
 
-  Expect.equals("123456789", new int32.fromInt(123456789).toString());
-  Expect.equals("75bcd15", new int32.fromInt(123456789).toHexString());
-  Expect.equals("223101104124", new int32.fromInt(123456789).toRadixString(5));
+    test("-", () {
+      expect(n1 - n2, new int32.fromInt(-8642));
+      expect(n3 - n2, new int32.fromInt(-11110));
+      expect(n3 - n4, new int32.fromInt(8642));
+      expect(int32.MIN_VALUE - 1, int32.MAX_VALUE);
+      expect(() => new int32.fromInt(17) - null, throws);
+    });
 
-  try {
-    new int32.fromInt(17) >> -1;
-    Expect.fail("x >> -1 should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
+    test("unary -", () {
+      expect(-n1, new int32.fromInt(-1234));
+      expect(-int32.ZERO, int32.ZERO);
+    });
 
-  try {
-    new int32.fromInt(17) << -1;
-    Expect.fail("x >> -1 should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
+    test("*", () {
+      expect(n1 * n2, new int32.fromInt(12186984));
+      expect(n2 * n3, new int32.fromInt(-12186984));
+      expect(n3 * n3, new int32.fromInt(1522756));
+      expect(n3 * n2, new int32.fromInt(-12186984));
+      expect(new int32.fromInt(0x12345678) * new int32.fromInt(0x22222222),
+          new int32.fromInt(-899716112));
+      expect((new int32.fromInt(123456789) * new int32.fromInt(987654321)),
+          new int32.fromInt(-67153019));
+      expect(new int32.fromInt(0x12345678) * new int64.fromInt(0x22222222),
+          new int64.fromInts(0x026D60DC, 0xCA5F6BF0));
+      expect((new int32.fromInt(123456789) * 987654321),
+          new int32.fromInt(-67153019));
+      expect(() => new int32.fromInt(17) * null, throws);
+    });
 
-  try {
-    new int32.fromInt(17).shiftRightUnsigned(-1);
-    Expect.fail("x >> -1 should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
+    test("~/", () {
+      expect(new int32.fromInt(829893893) ~/ new int32.fromInt(1919),
+          new int32.fromInt(432461));
+      expect(new int32.fromInt(0x12345678) ~/ new int32.fromInt(0x22),
+          new int32.fromInt(0x12345678 ~/ 0x22));
+      expect(new int32.fromInt(829893893) ~/ new int64.fromInt(1919),
+          new int32.fromInt(432461));
+      expect(new int32.fromInt(0x12345678) ~/ new int64.fromInt(0x22),
+          new int32.fromInt(0x12345678 ~/ 0x22));
+      expect(new int32.fromInt(829893893) ~/ 1919, new int32.fromInt(432461));
+      expect(() => new int32.fromInt(17) ~/ int32.ZERO, throws);
+      expect(() => new int32.fromInt(17) ~/ null, throws);
+    });
 
-  // wraparound
-  Expect.equals("-67153019", (new int32.fromInt(123456789) *
-      new int32.fromInt(987654321)).toString());
-  Expect.equals("121932631112635269", (new int64.fromInt(123456789) *
-      new int32.fromInt(987654321)).toString());
-  Expect.equals("121932631112635269", (new int32.fromInt(123456789) *
-      new int64.fromInt(987654321)).toString());
-  Expect.equals("121932631112635269", (new int64.fromInt(123456789) *
-      new int64.fromInt(987654321)).toString());
+    test("%", () {
+      expect(new int32.fromInt(0x12345678) % new int32.fromInt(0x22),
+          new int32.fromInt(0x12345678 % 0x22));
+      expect(new int32.fromInt(0x12345678) % new int64.fromInt(0x22),
+          new int32.fromInt(0x12345678 % 0x22));
+      expect(() => new int32.fromInt(17) % null, throws);
+    });
 
-  Expect.equals("432461",
-      (new int32.fromInt(829893893) ~/ new int32.fromInt(1919)).toString());
-  Expect.equals("432461",
-      (new int32.fromInt(829893893) ~/ new int64.fromInt(1919)).toString());
-  Expect.equals("432461",
-      (new int64.fromInt(829893893) ~/ new int32.fromInt(1919)).toString());
-  Expect.equals("432461",
-      (new int64.fromInt(829893893) ~/ new int64.fromInt(1919)).toString());
-  Expect.equals("432461",
-      (new int32.fromInt(829893893) ~/ 1919).toString());
-  Expect.equals("432461",
-      (new int64.fromInt(829893893) ~/ 1919).toString());
+    test("remainder", () {
+      expect(new int32.fromInt(0x12345678).remainder(new int32.fromInt(0x22)),
+          new int32.fromInt(0x12345678.remainder(0x22)));
+      expect(new int32.fromInt(0x12345678).remainder(new int32.fromInt(-0x22)),
+          new int32.fromInt(0x12345678.remainder(-0x22)));
+      expect(new int32.fromInt(-0x12345678).remainder(new int32.fromInt(-0x22)),
+          new int32.fromInt(-0x12345678.remainder(-0x22)));
+      expect(new int32.fromInt(-0x12345678).remainder(new int32.fromInt(0x22)),
+          new int32.fromInt(-0x12345678.remainder(0x22)));
+      expect(new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
+          new int32.fromInt(0x12345678.remainder(0x22)));
+      expect(() => new int32.fromInt(17).remainder(null), throws);
+    });
+  });
 
-  Expect.isTrue(new int32.fromInt(12345) == 12345);
-  Expect.isTrue(new int32.fromInt(12345) == new int32.fromInt(12345));
-  Expect.isTrue(new int64.fromInt(12345) == new int32.fromInt(12345));
+  group("comparison operators", () {
+    test("<", () {
+      expect(new int32.fromInt(17) < new int32.fromInt(18), true);
+      expect(new int32.fromInt(17) < new int32.fromInt(17), false);
+      expect(new int32.fromInt(17) < new int32.fromInt(16), false);
+      expect(int32.MIN_VALUE < int32.MAX_VALUE, true);
+      expect(int32.MAX_VALUE < int32.MIN_VALUE, false);
+      expect(() => new int32.fromInt(17) < null, throws);
+    });
 
-  Expect.equals(new int32.fromInt(~0x12345678),
-      ~(new int32.fromInt(0x12345678)));
-  Expect.equals(new int64.fromInt(-0x12345678),
-      -(new int32.fromInt(0x12345678)));
+    test("<=", () {
+      expect(new int32.fromInt(17) <= new int32.fromInt(18), true);
+      expect(new int32.fromInt(17) <= new int32.fromInt(17), true);
+      expect(new int32.fromInt(17) <= new int32.fromInt(16), false);
+      expect(int32.MIN_VALUE <= int32.MAX_VALUE, true);
+      expect(int32.MAX_VALUE <= int32.MIN_VALUE, false);
+      expect(() => new int32.fromInt(17) <= null, throws);
+    });
 
-  Expect.equals(new int32.fromInt(0x12345678 & 0x22222222),
-      new int32.fromInt(0x12345678) & new int32.fromInt(0x22222222));
-  Expect.equals(new int64.fromInt(0x12345678 & 0x22222222),
-      new int32.fromInt(0x12345678) & new int64.fromInt(0x22222222));
-  Expect.equals(new int32.fromInt(0x12345678 | 0x22222222),
-      new int32.fromInt(0x12345678) | new int32.fromInt(0x22222222));
-  Expect.equals(new int64.fromInt(0x12345678 | 0x22222222),
-      new int32.fromInt(0x12345678) | new int64.fromInt(0x22222222));
-  Expect.equals(new int32.fromInt(0x12345678 ^ 0x22222222),
-      new int32.fromInt(0x12345678) ^ new int32.fromInt(0x22222222));
-  Expect.equals(new int64.fromInt(0x12345678 ^ 0x22222222),
-      new int32.fromInt(0x12345678) ^ new int64.fromInt(0x22222222));
+    test("==", () {
+      expect(new int32.fromInt(17) == new int32.fromInt(18), false);
+      expect(new int32.fromInt(17) == new int32.fromInt(17), true);
+      expect(new int32.fromInt(17) == new int32.fromInt(16), false);
+      expect(int32.MIN_VALUE == int32.MAX_VALUE, false);
+      expect(new int32.fromInt(17) == null, false);
+    });
 
-  Expect.equals(new int32.fromInt(0x12345678 + 0x22222222),
-      new int32.fromInt(0x12345678) + new int32.fromInt(0x22222222));
-  Expect.equals(new int64.fromInt(0x12345678 + 0x22222222),
-     new int32.fromInt(0x12345678) + new int64.fromInt(0x22222222));
-  Expect.equals(new int32.fromInt(0x12345678 - 0x22222222),
-     new int32.fromInt(0x12345678) - new int32.fromInt(0x22222222));
-  Expect.equals(new int64.fromInt(0x12345678 - 0x22222222),
-     new int32.fromInt(0x12345678) - new int64.fromInt(0x22222222));
-  Expect.equals(new int32.fromInt(-899716112),
-      new int32.fromInt(0x12345678) * new int32.fromInt(0x22222222));
-  Expect.equals(new int64.fromInts(0x026D60DC, 0xCA5F6BF0),
-      new int32.fromInt(0x12345678) * new int64.fromInt(0x22222222));
-  Expect.equals(new int32.fromInt(0x12345678 % 0x22),
-      new int32.fromInt(0x12345678) % new int32.fromInt(0x22));
-  Expect.equals(new int32.fromInt(0x12345678 % 0x22),
-      new int32.fromInt(0x12345678) % new int64.fromInt(0x22));
-  Expect.equals(new int32.fromInt(0x12345678.remainder(0x22)),
-      new int32.fromInt(0x12345678).remainder(new int32.fromInt(0x22)));
-  Expect.equals(new int32.fromInt(0x12345678.remainder(-0x22)),
-      new int32.fromInt(0x12345678).remainder(new int32.fromInt(-0x22)));
-  Expect.equals(new int32.fromInt(-0x12345678.remainder(-0x22)),
-      new int32.fromInt(-0x12345678).remainder(new int32.fromInt(-0x22)));
-  Expect.equals(new int32.fromInt(-0x12345678.remainder(0x22)),
-      new int32.fromInt(-0x12345678).remainder(new int32.fromInt(0x22)));
-  Expect.equals(new int32.fromInt(0x12345678.remainder(0x22)),
-      new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)));
-  Expect.equals(new int32.fromInt(0x12345678 ~/ 0x22),
-      new int32.fromInt(0x12345678) ~/ new int32.fromInt(0x22));
-  Expect.equals(new int32.fromInt(0x12345678 ~/ 0x22),
-      new int32.fromInt(0x12345678) ~/ new int64.fromInt(0x22));
+    test(">=", () {
+      expect(new int32.fromInt(17) >= new int32.fromInt(18), false);
+      expect(new int32.fromInt(17) >= new int32.fromInt(17), true);
+      expect(new int32.fromInt(17) >= new int32.fromInt(16), true);
+      expect(int32.MIN_VALUE >= int32.MAX_VALUE, false);
+      expect(int32.MAX_VALUE >= int32.MIN_VALUE, true);
+      expect(() => new int32.fromInt(17) >= null, throws);
+    });
 
-  Expect.equals(new int32.fromInt(0x12345678 >> 7),
-      new int32.fromInt(0x12345678) >> 7);
-  Expect.equals(new int32.fromInt(0x12345678 << 7),
-      new int32.fromInt(0x12345678) << 7);
-  Expect.equals(new int32.fromInt(0x12345678 >> 7),
-      new int32.fromInt(0x12345678).shiftRightUnsigned(7));
+    test(">", () {
+      expect(new int32.fromInt(17) > new int32.fromInt(18), false);
+      expect(new int32.fromInt(17) > new int32.fromInt(17), false);
+      expect(new int32.fromInt(17) > new int32.fromInt(16), true);
+      expect(int32.MIN_VALUE > int32.MAX_VALUE, false);
+      expect(int32.MAX_VALUE > int32.MIN_VALUE, true);
+      expect(() => new int32.fromInt(17) > null, throws);
+    });
+  });
 
-  try {
-    new int32.fromInt(17) < null;
-    Expect.fail("x < null should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
+  group("bitwise operators", () {
+    test("&", () {
+      expect(new int32.fromInt(0x12345678) & new int32.fromInt(0x22222222),
+          new int32.fromInt(0x12345678 & 0x22222222));
+      expect(new int32.fromInt(0x12345678) & new int64.fromInt(0x22222222),
+          new int64.fromInt(0x12345678 & 0x22222222));
+      expect(() => new int32.fromInt(17) & null, throwsArgumentError);
+    });
 
-  try {
-    new int32.fromInt(17) <= null;
-    Expect.fail("x <= null should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
+    test("|", () {
+      expect(new int32.fromInt(0x12345678) | new int32.fromInt(0x22222222),
+          new int32.fromInt(0x12345678 | 0x22222222));
+      expect(new int32.fromInt(0x12345678) | new int64.fromInt(0x22222222),
+          new int64.fromInt(0x12345678 | 0x22222222));
+      expect(() => new int32.fromInt(17) | null, throws);
+    });
 
-  try {
-    new int32.fromInt(17) > null;
-    Expect.fail("x > null should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
+    test("^", () {
+      expect(new int32.fromInt(0x12345678) ^ new int32.fromInt(0x22222222),
+          new int32.fromInt(0x12345678 ^ 0x22222222));
+      expect(new int32.fromInt(0x12345678) ^ new int64.fromInt(0x22222222),
+          new int64.fromInt(0x12345678 ^ 0x22222222));
+      expect(() => new int32.fromInt(17) ^ null, throws);
+    });
 
-  try {
-    new int32.fromInt(17) < null;
-    Expect.fail("x >= null should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
+    test("~", () {
+      expect(~(new int32.fromInt(0x12345678)), new int32.fromInt(~0x12345678));
+      expect(-(new int32.fromInt(0x12345678)), new int64.fromInt(-0x12345678));
+    });
+  });
 
-  Expect.isFalse(new int32.fromInt(17) == null);
+  group("bitshift operators", () {
+    test("<<", () {
+      expect(new int32.fromInt(0x12345678) << 7,
+          new int32.fromInt(0x12345678 << 7));
+      expect(() => new int32.fromInt(17) << -1, throwsArgumentError);
+      expect(() => new int32.fromInt(17) << null, throws);
+    });
+
+    test(">>", () {
+      expect(new int32.fromInt(0x12345678) >> 7,
+          new int32.fromInt(0x12345678 >> 7));
+      expect(() => new int32.fromInt(17) >> -1, throwsArgumentError);
+      expect(() => new int32.fromInt(17) >> null, throws);
+    });
+
+    test("shiftRightUnsigned", () {
+      expect(new int32.fromInt(0x12345678).shiftRightUnsigned(7),
+          new int32.fromInt(0x12345678 >> 7));
+      expect(() => (new int32.fromInt(17).shiftRightUnsigned(-1)),
+          throwsArgumentError);
+      expect(() => (new int32.fromInt(17).shiftRightUnsigned(null)), throws);
+    });
+  });
+
+  group("type conversions", () {
+    expect(new int32.fromInt(17).toInt(), 17);
+    expect(new int32.fromInt(-17).toInt(), -17);
+    expect(new int32.fromInt(17).toInt32(), new int32.fromInt(17));
+    expect(new int32.fromInt(-17).toInt32(), new int32.fromInt(-17));
+    expect(new int32.fromInt(17).toInt64(), new int64.fromInt(17));
+    expect(new int32.fromInt(-17).toInt64(), new int64.fromInt(-17));
+  });
+
+  group("string representation", () {
+    test("toString", () {
+      expect(new int32.fromInt(0).toString(), "0");
+      expect(new int32.fromInt(1).toString(), "1");
+      expect(new int32.fromInt(-1).toString(), "-1");
+      expect(new int32.fromInt(1000).toString(), "1000");
+      expect(new int32.fromInt(-1000).toString(), "-1000");
+      expect(new int32.fromInt(123456789).toString(), "123456789");
+      expect(new int32.fromInt(2147483647).toString(), "2147483647");
+      expect(new int32.fromInt(2147483648).toString(), "-2147483648");
+      expect(new int32.fromInt(2147483649).toString(), "-2147483647");
+      expect(new int32.fromInt(2147483650).toString(), "-2147483646");
+      expect(new int32.fromInt(-2147483648).toString(), "-2147483648");
+      expect(new int32.fromInt(-2147483649).toString(), "2147483647");
+      expect(new int32.fromInt(-2147483650).toString(), "2147483646");
+    });
+  });
+
+  group("toHexString", () {
+    test("returns hexadecimal string representation", () {
+      expect(new int32.fromInt(-1).toHexString(), "-1");
+      expect((new int32.fromInt(-1) >> 8).toHexString(), "-1");
+      expect((new int32.fromInt(-1) << 8).toHexString(), "-100");
+      expect(new int32.fromInt(123456789).toHexString(), "75bcd15");
+      expect(new int32.fromInt(-1).shiftRightUnsigned(8).toHexString(),
+          "ffffff");
+    });
+  });
+
+  group("toRadixString", () {
+    test("returns base n string representation", () {
+      expect(new int32.fromInt(123456789).toRadixString(5), "223101104124");
+    });
+  });
 }
diff --git a/pkg/fixnum/test/int_64_test.dart b/pkg/fixnum/test/int_64_test.dart
index 8aa3e5b..fddb409 100644
--- a/pkg/fixnum/test/int_64_test.dart
+++ b/pkg/fixnum/test/int_64_test.dart
@@ -3,605 +3,581 @@
 // BSD-style license that can be found in the LICENSE file.
 
 library int64test;
-import "package:expect/expect.dart";
 import 'package:fixnum/fixnum.dart';
+import 'package:unittest/unittest.dart';
 
 void main() {
-  testAdditive();
-  testBitOps();
-  testComparisons();
-  testConversions();
-  testDiv();
-  testFactorial();
-  testMinMax();
-  testMod();
-  testMultiplicative();
-  testNegate();
-  testShift();
-  testToHexString();
-  testToString();
-}
-
-void testAdditive() {
-  {
+  group("arithmetic operators", () {
     int64 n1 = new int64.fromInt(1234);
     int64 n2 = new int64.fromInt(9876);
-    Expect.equals(new int64.fromInt(11110), n1 + n2);
-    Expect.equals(new int64.fromInt(-8642), n1 - n2);
-  }
+    int64 n3 = new int64.fromInt(-1234);
+    int64 n4 = new int64.fromInt(-9876);
+    int64 n5 = new int64.fromInts(0x12345678, 0xabcdabcd);
+    int64 n6 = new int64.fromInts(0x77773333, 0x22224444);
 
-  {
-    int64 n1 = new int64.fromInt(-1234);
-    int64 n2 = new int64.fromInt(9876);
-    Expect.equals(new int64.fromInt(8642), n1 + n2);
-    Expect.equals(new int64.fromInt(-11110), n1 - n2);
-  }
+    test("+", () {
+      expect(n1 + n2, new int64.fromInt(11110));
+      expect(n3 + n2, new int64.fromInt(8642));
+      expect(n3 + n4, new int64.fromInt(-11110));
+      expect(n5 + n6, new int64.fromInts(0x89ab89ab, 0xcdeff011));
+      expect(int64.MAX_VALUE + 1, int64.MIN_VALUE);
+    });
 
-  {
-    int64 n1 = new int64.fromInt(-1234);
-    int64 n2 = new int64.fromInt(-9876);
-    Expect.equals(new int64.fromInt(-11110), n1 + n2);
-    Expect.equals(new int64.fromInt(8642), n1 - n2);
-  }
+    test("-", () {
+      expect(n1 - n2, new int64.fromInt(-8642));
+      expect(n3 - n2, new int64.fromInt(-11110));
+      expect(n3 - n4, new int64.fromInt(8642));
+      expect(n5 - n6, new int64.fromInts(0x9abd2345, 0x89ab6789));
+      expect(int64.MIN_VALUE - 1, int64.MAX_VALUE);
+    });
 
-  {
-    int64 n1 = new int64.fromInts(0x12345678, 0xabcdabcd);
-    int64 n2 = new int64.fromInts(0x77773333, 0x22224444);
-    Expect.equals(new int64.fromInts(0x89ab89ab, 0xcdeff011), n1 + n2);
-    Expect.equals(new int64.fromInts(0x9abd2345, 0x89ab6789), n1 - n2);
-  }
-}
+    test("unary -", () {
+      expect(-n1, new int64.fromInt(-1234));
+      expect(-int64.ZERO, int64.ZERO);
+    });
 
-void testBitOps() {
-  {
+    test("*", () {
+      expect(new int64.fromInt(1111) * new int64.fromInt(3),
+          new int64.fromInt(3333));
+      expect(new int64.fromInt(1111) * new int64.fromInt(-3),
+          new int64.fromInt(-3333));
+      expect(new int64.fromInt(-1111) * new int64.fromInt(3),
+          new int64.fromInt(-3333));
+      expect(new int64.fromInt(-1111) * new int64.fromInt(-3),
+          new int64.fromInt(3333));
+      expect(new int64.fromInt(100) * new int64.fromInt(0),
+          new int64.fromInt(0));
+
+      expect(new int64.fromInts(0x12345678, 0x12345678) *
+          new int64.fromInts(0x1234, 0x12345678),
+          new int64.fromInts(0x7ff63f7c, 0x1df4d840));
+      expect(new int64.fromInts(0xf2345678, 0x12345678) *
+          new int64.fromInts(0x1234, 0x12345678),
+          new int64.fromInts(0x7ff63f7c, 0x1df4d840));
+      expect(new int64.fromInts(0xf2345678, 0x12345678) *
+          new int64.fromInts(0xffff1234, 0x12345678),
+          new int64.fromInts(0x297e3f7c, 0x1df4d840));
+
+      // RHS int32
+      expect((new int64.fromInt(123456789) * new int32.fromInt(987654321)),
+          new int64.fromInts(0x1b13114, 0xfbff5385));
+      expect((new int64.fromInt(123456789) * new int32.fromInt(987654321)),
+          new int64.fromInts(0x1b13114, 0xfbff5385));
+
+      // Wraparound
+      expect((new int64.fromInt(123456789) * new int64.fromInt(987654321)),
+          new int64.fromInts(0x1b13114, 0xfbff5385));
+
+      expect(int64.MIN_VALUE * new int64.fromInt(2), new int64.fromInt(0));
+      expect(int64.MIN_VALUE * new int64.fromInt(1), int64.MIN_VALUE);
+      expect(int64.MIN_VALUE * new int64.fromInt(-1), int64.MIN_VALUE);
+    });
+
+    test("~/", () {
+      int64 deadBeef = new int64.fromInts(0xDEADBEEF, 0xDEADBEEF);
+      int64 ten = new int64.fromInt(10);
+
+      expect(deadBeef ~/ ten, new int64.fromInts(0xfcaaf97e, 0x63115fe5));
+      expect(int64.ONE ~/ int64.TWO, int64.ZERO);
+      expect(int64.MAX_VALUE ~/ int64.TWO,
+          new int64.fromInts(0x3fffffff, 0xffffffff));
+      expect(int64.ZERO ~/ new int64.fromInt(1000), int64.ZERO);
+      expect(int64.MIN_VALUE ~/ int64.MIN_VALUE, int64.ONE);
+      expect(new int64.fromInt(1000) ~/ int64.MIN_VALUE, int64.ZERO);
+      expect(int64.MIN_VALUE ~/ new int64.fromInt(8192),
+          new int64.fromInt(-1125899906842624));
+      expect(int64.MIN_VALUE ~/ new int64.fromInt(8193),
+          new int64.fromInt(-1125762484664320));
+      expect(new int64.fromInt(-1000) ~/ new int64.fromInt(8192), int64.ZERO);
+      expect(new int64.fromInt(-1000) ~/ new int64.fromInt(8193), int64.ZERO);
+      expect(new int64.fromInt(-1000000000) ~/ new int64.fromInt(8192),
+          new int64.fromInt(-122070));
+      expect(new int64.fromInt(-1000000000) ~/ new int64.fromInt(8193),
+          new int64.fromInt(-122055));
+      expect(new int64.fromInt(1000000000) ~/ new int64.fromInt(8192),
+          new int64.fromInt(122070));
+      expect(new int64.fromInt(1000000000) ~/ new int64.fromInt(8193),
+          new int64.fromInt(122055));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000400),
+          new int64.fromInts(0x1fffff, 0xffffffff));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00040000),
+          new int64.fromInts(0x1fff, 0xffffffff));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x04000000),
+          new int64.fromInts(0x1f, 0xffffffff));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000004, 0x00000000),
+          new int64.fromInt(536870911));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000400, 0x00000000),
+          new int64.fromInt(2097151));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00040000, 0x00000000),
+          new int64.fromInt(8191));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x04000000, 0x00000000),
+          new int64.fromInt(31));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000300),
+          new int64.fromInts(0x2AAAAA, 0xAAAAAAAA));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x30000000),
+          new int64.fromInts(0x2, 0xAAAAAAAA));
+      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00300000, 0x00000000),
+          new int64.fromInt(0x2AA));
+      expect(int64.MAX_VALUE ~/ new int64.fromInt(0x123456),
+          new int64.fromInts(0x708, 0x002E9501));
+      expect(int64.MAX_VALUE % new int64.fromInt(0x123456),
+          new int64.fromInt(0x3BDA9));
+      expect(new int64.fromInt(5) ~/ new int64.fromInt(5),
+          new int64.fromInt(1));
+      expect(new int64.fromInt(1000) ~/ new int64.fromInt(3),
+          new int64.fromInt(333));
+      expect(new int64.fromInt(1000) ~/ new int64.fromInt(-3),
+          new int64.fromInt(-333));
+      expect(new int64.fromInt(-1000) ~/ new int64.fromInt(3),
+          new int64.fromInt(-333));
+      expect(new int64.fromInt(-1000) ~/ new int64.fromInt(-3),
+          new int64.fromInt(333));
+      expect(new int64.fromInt(3) ~/ new int64.fromInt(1000),
+          new int64.fromInt(0));
+      expect(new int64.fromInts( 0x12345678, 0x12345678) ~/
+          new int64.fromInts(0x0, 0x123),
+          new int64.fromInts(0x1003d0, 0xe84f5ae8));
+      expect(new int64.fromInts(0x12345678, 0x12345678) ~/
+          new int64.fromInts(0x1234, 0x12345678),
+          new int64.fromInts(0x0, 0x10003));
+      expect(new int64.fromInts(0xf2345678, 0x12345678) ~/
+          new int64.fromInts(0x1234, 0x12345678),
+          new int64.fromInts(0xffffffff, 0xffff3dfe));
+      expect(new int64.fromInts(0xf2345678, 0x12345678) ~/
+          new int64.fromInts(0xffff1234, 0x12345678),
+          new int64.fromInts(0x0, 0xeda));
+      expect(new int64.fromInt(829893893) ~/ new int32.fromInt(1919),
+          new int32.fromInt(432461));
+      expect(new int64.fromInt(829893893) ~/ new int64.fromInt(1919),
+          new int32.fromInt(432461));
+      expect(new int64.fromInt(829893893) ~/ 1919,
+          new int32.fromInt(432461));
+      expect(() => new int64.fromInt(1) ~/ new int64.fromInt(0),
+          throwsA(new isInstanceOf<IntegerDivisionByZeroException>()));
+      expect(int64.MIN_VALUE ~/ new int64.fromInt(2),
+          new int64.fromInts(0xc0000000, 0x00000000));
+      expect(int64.MIN_VALUE ~/ new int64.fromInt(1), int64.MIN_VALUE);
+      expect(int64.MIN_VALUE ~/ new int64.fromInt(-1), int64.MIN_VALUE);
+      expect(() => new int64.fromInt(17) ~/ int64.ZERO, throws);
+      expect(() => new int64.fromInt(17) ~/ null, throws);
+    });
+
+    test("%", () {
+      // Define % as Euclidean mod, with positive result for all arguments
+      expect(int64.ZERO % new int64.fromInt(1000), new int64.fromInt(0));
+      expect(int64.MIN_VALUE % int64.MIN_VALUE, new int64.fromInt(0));
+      expect(new int64.fromInt(1000) % int64.MIN_VALUE,
+          new int64.fromInt(1000));
+      expect(int64.MIN_VALUE % new int64.fromInt(8192), new int64.fromInt(0));
+      expect(int64.MIN_VALUE % new int64.fromInt(8193),
+          new int64.fromInt(6145));
+      expect(new int64.fromInt(-1000) % new int64.fromInt(8192),
+          new int64.fromInt(7192));
+      expect(new int64.fromInt(-1000) % new int64.fromInt(8193),
+          new int64.fromInt(7193));
+      expect(new int64.fromInt(-1000000000) % new int64.fromInt(8192),
+          new int64.fromInt(5632));
+      expect(new int64.fromInt(-1000000000) % new int64.fromInt(8193),
+          new int64.fromInt(4808));
+      expect(new int64.fromInt(1000000000) % new int64.fromInt(8192),
+          new int64.fromInt(2560));
+      expect(new int64.fromInt(1000000000) % new int64.fromInt(8193),
+          new int64.fromInt(3385));
+      expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00000400),
+          new int64.fromInts(0x0, 0x3ff));
+      expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00040000),
+          new int64.fromInts(0x0, 0x3ffff));
+      expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x04000000),
+          new int64.fromInts(0x0, 0x3ffffff));
+      expect(int64.MAX_VALUE % new int64.fromInts(0x00000004, 0x00000000),
+          new int64.fromInts(0x3, 0xffffffff));
+      expect(int64.MAX_VALUE % new int64.fromInts(0x00000400, 0x00000000),
+          new int64.fromInts(0x3ff, 0xffffffff));
+      expect(int64.MAX_VALUE % new int64.fromInts(0x00040000, 0x00000000),
+          new int64.fromInts(0x3ffff, 0xffffffff));
+      expect(int64.MAX_VALUE % new int64.fromInts(0x04000000, 0x00000000),
+          new int64.fromInts(0x3ffffff, 0xffffffff));
+      expect(new int64.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
+          new int64.fromInt(0x12345678.remainder(0x22)));
+      expect(new int64.fromInt(0x12345678).remainder(new int64.fromInt(-0x22)),
+          new int64.fromInt(0x12345678.remainder(-0x22)));
+      expect(new int64.fromInt(-0x12345678).remainder(new int64.fromInt(-0x22)),
+          new int64.fromInt(-0x12345678.remainder(-0x22)));
+      expect(new int64.fromInt(-0x12345678).remainder(new int64.fromInt(0x22)),
+          new int64.fromInt(-0x12345678.remainder(0x22)));
+      expect(new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
+          new int64.fromInt(0x12345678.remainder(0x22)));
+    });
+  });
+
+  group("comparison operators", () {
+    int64 largeNeg = new int64.fromInts(0x82341234, 0x0);
+    int64 largePos = new int64.fromInts(0x12341234, 0x0);
+    int64 largePosPlusOne = largePos + new int64.fromInt(1);
+
+    test("<", () {
+      expect(new int64.fromInt(10) < new int64.fromInt(11), true);
+      expect(new int64.fromInt(10) < new int64.fromInt(10), false);
+      expect(new int64.fromInt(12) < new int64.fromInt(11), false);
+      expect(new int64.fromInt(-10) < new int64.fromInt(-11), false);
+      expect(int64.MIN_VALUE < new int64.fromInt(0), true);
+      expect(largeNeg < largePos, true);
+      expect(largePos < largePosPlusOne, true);
+      expect(largePos < largePos, false);
+      expect(largePosPlusOne < largePos, false);
+      expect(int64.MIN_VALUE < int64.MAX_VALUE, true);
+      expect(int64.MAX_VALUE < int64.MIN_VALUE, false);
+      expect(() => new int64.fromInt(17) < null, throwsArgumentError);
+    });
+
+    test("<=", () {
+      expect(new int64.fromInt(10) <= new int64.fromInt(11), true);
+      expect(new int64.fromInt(10) <= new int64.fromInt(10), true);
+      expect(new int64.fromInt(12) <= new int64.fromInt(11), false);
+      expect(new int64.fromInt(-10) <= new int64.fromInt(-11), false);
+      expect(new int64.fromInt(-10) <= new int64.fromInt(-10), true);
+      expect(largeNeg <= largePos, true);
+      expect(largePos <= largeNeg, false);
+      expect(largePos <= largePosPlusOne, true);
+      expect(largePos <= largePos, true);
+      expect(largePosPlusOne <= largePos, false);
+      expect(int64.MIN_VALUE <= int64.MAX_VALUE, true);
+      expect(int64.MAX_VALUE <= int64.MIN_VALUE, false);
+      expect(() => new int64.fromInt(17) <= null, throwsArgumentError);
+    });
+
+    test("==", () {
+      expect(new int64.fromInt(10) == new int64.fromInt(11), false);
+      expect(new int64.fromInt(10) == new int64.fromInt(10), true);
+      expect(new int64.fromInt(12) == new int64.fromInt(11), false);
+      expect(new int64.fromInt(-10) == new int64.fromInt(-10), true);
+      expect(new int64.fromInt(-10) != new int64.fromInt(-10), false);
+      expect(largePos == largePos, true);
+      expect(largePos == largePosPlusOne, false);
+      expect(largePosPlusOne == largePos, false);
+      expect(int64.MIN_VALUE == int64.MAX_VALUE, false);
+      expect(new int64.fromInt(17) == null, false);
+    });
+
+    test(">=", () {
+      expect(new int64.fromInt(10) >= new int64.fromInt(11), false);
+      expect(new int64.fromInt(10) >= new int64.fromInt(10), true);
+      expect(new int64.fromInt(12) >= new int64.fromInt(11), true);
+      expect(new int64.fromInt(-10) >= new int64.fromInt(-11), true);
+      expect(new int64.fromInt(-10) >= new int64.fromInt(-10), true);
+      expect(largePos >= largeNeg, true);
+      expect(largeNeg >= largePos, false);
+      expect(largePos >= largePosPlusOne, false);
+      expect(largePos >= largePos, true);
+      expect(largePosPlusOne >= largePos, true);
+      expect(int64.MIN_VALUE >= int64.MAX_VALUE, false);
+      expect(int64.MAX_VALUE >= int64.MIN_VALUE, true);
+      expect(() => new int64.fromInt(17) >= null, throwsArgumentError);
+    });
+
+    test(">", () {
+      expect(new int64.fromInt(10) > new int64.fromInt(11), false);
+      expect(new int64.fromInt(10) > new int64.fromInt(10), false);
+      expect(new int64.fromInt(12) > new int64.fromInt(11), true);
+      expect(new int64.fromInt(-10) > new int64.fromInt(-11), true);
+      expect(new int64.fromInt(10) > new int64.fromInt(-11), true);
+      expect(new int64.fromInt(-10) > new int64.fromInt(11), false);
+      expect(largePos > largeNeg, true);
+      expect(largeNeg > largePos, false);
+      expect(largePos > largePosPlusOne, false);
+      expect(largePos > largePos, false);
+      expect(largePosPlusOne > largePos, true);
+      expect(new int64.fromInt(0) > int64.MIN_VALUE, true);
+      expect(int64.MIN_VALUE > int64.MAX_VALUE, false);
+      expect(int64.MAX_VALUE > int64.MIN_VALUE, true);
+      expect(() => new int64.fromInt(17) > null, throwsArgumentError);
+    });
+  });
+
+  group("bitwise operators", () {
     int64 n1 = new int64.fromInt(1234);
     int64 n2 = new int64.fromInt(9876);
+    int64 n3 = new int64.fromInt(-1234);
+    int64 n4 = new int64.fromInt(0x1234) << 32;
+    int64 n5 = new int64.fromInt(0x9876) << 32;
 
-    Expect.equals(new int64.fromInt(1168), n1 & n2);
-    Expect.equals(new int64.fromInt(9942), n1 | n2);
-    Expect.equals(new int64.fromInt(8774), n1 ^ n2);
-    Expect.equals(new int64.fromInt(-1235), ~n1);
-    Expect.equals(new int64.fromInt(-9877), ~n2);
-  }
+    test("&", () {
+      expect(n1 & n2, new int64.fromInt(1168));
+      expect(n3 & n2, new int64.fromInt(8708));
+      expect(n4 & n5, new int64.fromInt(0x1034) << 32);
+      expect(() => n1 & null, throws);
+    });
 
-  {
-    int64 n1 = new int64.fromInt(-1234);
-    int64 n2 = new int64.fromInt(9876);
-    Expect.equals(new int64.fromInt(8708), n1 & n2);
-    Expect.equals(new int64.fromInt(-66), n1 | n2);
-    Expect.equals(new int64.fromInt(-8774), n1 ^ n2);
-    Expect.equals(new int64.fromInt(1233), ~n1);
-    Expect.equals(new int64.fromInt(-9877), ~n2);
-  }
+    test("|", () {
+      expect(n1 | n2, new int64.fromInt(9942));
+      expect(n3 | n2, new int64.fromInt(-66));
+      expect(n4 | n5, new int64.fromInt(0x9a76) << 32);
+      expect(() => n1 | null, throws);
+    });
 
-  {
-    int64 n1 = new int64.fromInt(0x1234) << 32;
-    int64 n2 = new int64.fromInt(0x9876) << 32;
-    Expect.equals(new int64.fromInt(0x1034) << 32, n1 & n2);
-    Expect.equals(new int64.fromInt(0x9a76) << 32, n1 | n2);
-    Expect.equals(new int64.fromInt(0x8a42) << 32, n1 ^ n2);
-    Expect.equals(new int64.fromInts(0xffffedcb, 0xffffffff), ~n1);
-    Expect.equals(new int64.fromInts(0xffff6789, 0xffffffff), ~n2);
-  }
-}
+    test("^", () {
+      expect(n1 ^ n2, new int64.fromInt(8774));
+      expect(n3 ^ n2, new int64.fromInt(-8774));
+      expect(n4 ^ n5, new int64.fromInt(0x8a42) << 32);
+      expect(() => n1 ^ null, throws);
+    });
 
-void testComparisons() {
-  Expect.isTrue(new int64.fromInt(10) < new int64.fromInt(11));
-  Expect.isTrue(new int64.fromInt(10) <= new int64.fromInt(11));
-  Expect.isTrue(!(new int64.fromInt(10) == new int64.fromInt(11)));
-  Expect.isTrue(!(new int64.fromInt(10) >= new int64.fromInt(11)));
-  Expect.isTrue(!(new int64.fromInt(10) > new int64.fromInt(11)));
+    test("~", () {
+      expect(-new int64.fromInt(1), new int64.fromInt(-1));
+      expect(-new int64.fromInt(-1), new int64.fromInt(1));
+      expect(-int64.MIN_VALUE, int64.MIN_VALUE);
 
-  Expect.isTrue(!(new int64.fromInt(10) < new int64.fromInt(10)));
-  Expect.isTrue(new int64.fromInt(10) <= new int64.fromInt(10));
-  Expect.isTrue(new int64.fromInt(10) == new int64.fromInt(10));
-  Expect.isTrue(new int64.fromInt(10) >= new int64.fromInt(10));
-  Expect.isTrue(!(new int64.fromInt(10) > new int64.fromInt(10)));
+      expect(~n1, new int64.fromInt(-1235));
+      expect(~n2, new int64.fromInt(-9877));
+      expect(~n3, new int64.fromInt(1233));
+      expect(~n4, new int64.fromInts(0xffffedcb, 0xffffffff));
+      expect(~n5, new int64.fromInts(0xffff6789, 0xffffffff));
+    });
+  });
 
-  Expect.isTrue(!(new int64.fromInt(12) < new int64.fromInt(11)));
-  Expect.isTrue(!(new int64.fromInt(12) <= new int64.fromInt(11)));
-  Expect.isTrue(!(new int64.fromInt(12) == new int64.fromInt(11)));
-  Expect.isTrue(new int64.fromInt(12) >= new int64.fromInt(11));
-  Expect.isTrue(new int64.fromInt(12) > new int64.fromInt(11));
+  group("bitshift operators", () {
+    test("<<", () {
+      expect(new int64.fromInts(0x12341234, 0x45674567) << 10,
+          new int64.fromInts(0xd048d115, 0x9d159c00));
+      expect(new int64.fromInts(0x92341234, 0x45674567) << 10,
+          new int64.fromInts(0xd048d115, 0x9d159c00));
+      expect(new int64.fromInt(-1) << 5, new int64.fromInt(-32));
+      expect(new int64.fromInt(-1) << 0, new int64.fromInt(-1));
+      expect(() => new int64.fromInt(17) << -1, throwsArgumentError);
+      expect(() => new int64.fromInt(17) << null, throws);
+    });
 
-  Expect.isTrue(new int64.fromInt(-10) > new int64.fromInt(-11));
-  Expect.isTrue(new int64.fromInt(10) > new int64.fromInt(-11));
-  Expect.isTrue(!(new int64.fromInt(-10) > new int64.fromInt(11)));
-  Expect.isTrue(new int64.fromInt(-10) >= new int64.fromInt(-11));
-  Expect.isTrue(new int64.fromInt(-10) >= new int64.fromInt(-10));
-  Expect.isTrue(!(new int64.fromInt(-10) < new int64.fromInt(-11)));
-  Expect.isTrue(!(new int64.fromInt(-10) <= new int64.fromInt(-11)));
-  Expect.isTrue(new int64.fromInt(-10) <= new int64.fromInt(-10));
-  Expect.isTrue(new int64.fromInt(-10) == new int64.fromInt(-10));
-  Expect.isTrue(!(new int64.fromInt(-10) != new int64.fromInt(-10)));
+    test(">>", () {
+      expect((int64.MIN_VALUE >> 13).toString(), "-1125899906842624");
+      expect(new int64.fromInts(0x12341234, 0x45674567) >> 10,
+          new int64.fromInts(0x48d04, 0x8d1159d1));
+      expect(new int64.fromInts(0x92341234, 0x45674567) >> 10,
+          new int64.fromInts(0xffe48d04, 0x8d1159d1));
+      expect(new int64.fromInts(0xFFFFFFF, 0xFFFFFFFF) >> 34,
+          new int64.fromInt(67108863));
+      for (int n = 0; n <= 66; n++) {
+        expect(new int64.fromInt(-1) >> n, new int64.fromInt(-1));
+      }
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 8,
+          new int64.fromInts(0x00723456, 0x789abcde));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 16,
+          new int64.fromInts(0x00007234, 0x56789abc));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 24,
+          new int64.fromInts(0x00000072, 0x3456789a));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 28,
+          new int64.fromInts(0x00000007, 0x23456789));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 32,
+          new int64.fromInts(0x00000000, 0x72345678));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 36,
+          new int64.fromInts(0x00000000, 0x07234567));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 40,
+          new int64.fromInts(0x00000000, 0x00723456));
+      expect(new int64.fromInts(0x72345678, 0x9abcde00) >> 44,
+          new int64.fromInts(0x00000000, 0x00072345));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 48,
+          new int64.fromInts(0x00000000, 0x00007234));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 8,
+          new int64.fromInts(0xff923456, 0x789abcde));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 16,
+          new int64.fromInts(0xffff9234, 0x56789abc));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 24,
+          new int64.fromInts(0xffffff92, 0x3456789a));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 28,
+          new int64.fromInts(0xfffffff9, 0x23456789));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 32,
+          new int64.fromInts(0xffffffff, 0x92345678));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 36,
+          new int64.fromInts(0xffffffff, 0xf9234567));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 40,
+          new int64.fromInts(0xffffffff, 0xff923456));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 44,
+          new int64.fromInts(0xffffffff, 0xfff92345));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 48,
+          new int64.fromInts(0xffffffff, 0xffff9234));
+      expect(() => new int64.fromInt(17) >> -1, throwsArgumentError);
+      expect(() => new int64.fromInt(17) >> null, throws);
+    });
 
-  // the following three comparisons cannot be implemented by
-  // subtracting the arguments, because the subtraction causes an overflow
-  int64 largeNeg = new int64.fromInts(0x82341234, 0x0);
-  int64 largePos = new int64.fromInts(0x12341234, 0x0);
-  Expect.isTrue(largeNeg < largePos);
+    test("shiftRightUnsigned", () {
+      expect(new int64.fromInts(0x12341234, 0x45674567).shiftRightUnsigned(10),
+          new int64.fromInts(0x48d04, 0x8d1159d1));
+      expect(new int64.fromInts(0x92341234, 0x45674567).shiftRightUnsigned(10),
+          new int64.fromInts(0x248d04, 0x8d1159d1));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(8),
+          new int64.fromInts(0x00723456, 0x789abcde));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(16),
+          new int64.fromInts(0x00007234, 0x56789abc));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(24),
+          new int64.fromInts(0x00000072, 0x3456789a));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(28),
+          new int64.fromInts(0x00000007, 0x23456789));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(32),
+          new int64.fromInts(0x00000000, 0x72345678));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(36),
+          new int64.fromInts(0x00000000, 0x07234567));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(40),
+          new int64.fromInts(0x00000000, 0x00723456));
+      expect(new int64.fromInts(0x72345678, 0x9abcde00).shiftRightUnsigned(44),
+          new int64.fromInts(0x00000000, 0x00072345));
+      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(48),
+          new int64.fromInts(0x00000000, 0x00007234));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(8),
+          new int64.fromInts(0x00923456, 0x789abcde));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(16),
+          new int64.fromInts(0x00009234, 0x56789abc));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(24),
+          new int64.fromInts(0x00000092, 0x3456789a));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(28),
+          new int64.fromInts(0x00000009, 0x23456789));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(32),
+          new int64.fromInts(0x00000000, 0x92345678));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(36),
+          new int64.fromInts(0x00000000, 0x09234567));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(40),
+          new int64.fromInts(0x00000000, 0x00923456));
+      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(44),
+          new int64.fromInts(0x00000000, 0x00092345));
+      expect(new int64.fromInts(0x00000000, 0x00009234),
+          new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(48));
+      expect(() => new int64.fromInt(17).shiftRightUnsigned(-1),
+          throwsArgumentError);
+      expect(() => new int64.fromInt(17).shiftRightUnsigned(null), throws);
+    });
 
-  Expect.isTrue(int64.MIN_VALUE < new int64.fromInt(0));
-  Expect.isTrue(new int64.fromInt(0) > int64.MIN_VALUE);
+    test("overflow", () {
+      expect((new int64.fromInt(1) << 63) >> 1,
+          -new int64.fromInts(0x40000000, 0x00000000));
+      expect((new int64.fromInt(-1) << 32) << 32, new int64.fromInt(0));
+      expect(int64.MIN_VALUE << 0, int64.MIN_VALUE);
+      expect(int64.MIN_VALUE << 1, new int64.fromInt(0));
+      expect((-new int64.fromInts(8, 0)) >> 1,
+          new int64.fromInts(0xfffffffc, 0x00000000));
+      expect((-new int64.fromInts(8, 0)).shiftRightUnsigned(1),
+          new int64.fromInts(0x7ffffffc, 0x0));
+    });
+  });
 
-  int64 largePosPlusOne = largePos + new int64.fromInt(1);
+  group("type conversions", () {
+    test("toInt", () {
+      expect(new int64.fromInt(0).toInt(), 0);
+      expect(new int64.fromInt(100).toInt(), 100);
+      expect(new int64.fromInt(-100).toInt(), -100);
+      expect(new int64.fromInt(2147483647).toInt(), 2147483647);
+      expect(new int64.fromInt(2147483648).toInt(), 2147483648);
+      expect(new int64.fromInt(-2147483647).toInt(), -2147483647);
+      expect(new int64.fromInt(-2147483648).toInt(), -2147483648);
+      expect(new int64.fromInt(4503599627370495).toInt(), 4503599627370495);
+      expect(new int64.fromInt(4503599627370496).toInt(), 4503599627370496);
+      expect(new int64.fromInt(-4503599627370495).toInt(), -4503599627370495);
+      expect(new int64.fromInt(-4503599627370496).toInt(), -4503599627370496);
+    });
 
-  Expect.isTrue(largePos < largePosPlusOne);
-  Expect.isTrue(largePos <= largePosPlusOne);
-  Expect.isTrue(!(largePos == largePosPlusOne));
-  Expect.isTrue(!(largePos >= largePosPlusOne));
-  Expect.isTrue(!(largePos > largePosPlusOne));
+    test("toInt32", () {
+      expect(new int64.fromInt(0).toInt32(), new int32.fromInt(0));
+      expect(new int64.fromInt(1).toInt32(), new int32.fromInt(1));
+      expect(new int64.fromInt(-1).toInt32(), new int32.fromInt(-1));
+      expect(new int64.fromInt(2147483647).toInt32(),
+          new int32.fromInt(2147483647));
+      expect(new int64.fromInt(2147483648).toInt32(),
+          new int32.fromInt(-2147483648));
+      expect(new int64.fromInt(2147483649).toInt32(),
+          new int32.fromInt(-2147483647));
+      expect(new int64.fromInt(2147483650).toInt32(),
+          new int32.fromInt(-2147483646));
+      expect(new int64.fromInt(-2147483648).toInt32(),
+          new int32.fromInt(-2147483648));
+      expect(new int64.fromInt(-2147483649).toInt32(),
+          new int32.fromInt(2147483647));
+      expect(new int64.fromInt(-2147483650).toInt32(),
+          new int32.fromInt(2147483646));
+      expect(new int64.fromInt(-2147483651).toInt32(),
+          new int32.fromInt(2147483645));
+    });
+  });
 
-  Expect.isTrue(!(largePos < largePos));
-  Expect.isTrue(largePos <= largePos);
-  Expect.isTrue(largePos == largePos);
-  Expect.isTrue(largePos >= largePos);
-  Expect.isTrue(!(largePos > largePos));
-
-  Expect.isTrue(!(largePosPlusOne < largePos));
-  Expect.isTrue(!(largePosPlusOne <= largePos));
-  Expect.isTrue(!(largePosPlusOne == largePos));
-  Expect.isTrue(largePosPlusOne >= largePos);
-  Expect.isTrue(largePosPlusOne > largePos);
-
-  try {
-    new int64.fromInt(17) < null;
-    Expect.fail("x < null should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
-
-  try {
-    new int64.fromInt(17) <= null;
-    Expect.fail("x <= null should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
-
-  try {
-    new int64.fromInt(17) > null;
-    Expect.fail("x > null should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
-
-  try {
-    new int64.fromInt(17) < null;
-    Expect.fail("x >= null should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
-
-  Expect.isFalse(new int64.fromInt(17) == null);
-}
-
-void testConversions() {
-  Expect.equals(0, new int64.fromInt(0).toInt());
-  Expect.equals(100, new int64.fromInt(100).toInt());
-  Expect.equals(-100, new int64.fromInt(-100).toInt());
-  Expect.equals(2147483647, new int64.fromInt(2147483647).toInt());
-  Expect.equals(2147483648, new int64.fromInt(2147483648).toInt());
-  Expect.equals(-2147483647, new int64.fromInt(-2147483647).toInt());
-  Expect.equals(-2147483648, new int64.fromInt(-2147483648).toInt());
-  Expect.equals(4503599627370495, new int64.fromInt(4503599627370495).toInt());
-  Expect.equals(4503599627370496, new int64.fromInt(4503599627370496).toInt());
-  Expect.equals(-4503599627370495,
-      new int64.fromInt(-4503599627370495).toInt());
-  Expect.equals(-4503599627370496,
-      new int64.fromInt(-4503599627370496).toInt());
-
-  Expect.equals(new int32.fromInt(0), new int64.fromInt(0).toInt32());
-  Expect.equals(new int32.fromInt(1), new int64.fromInt(1).toInt32());
-  Expect.equals(new int32.fromInt(-1), new int64.fromInt(-1).toInt32());
-  Expect.equals(new int32.fromInt(2147483647),
-    new int64.fromInt(2147483647).toInt32());
-  Expect.equals(new int32.fromInt(-2147483648),
-      new int64.fromInt(2147483648).toInt32());
-  Expect.equals(new int32.fromInt(-2147483647),
-      new int64.fromInt(2147483649).toInt32());
-  Expect.equals(new int32.fromInt(-2147483646),
-      new int64.fromInt(2147483650).toInt32());
-
-  Expect.equals(new int32.fromInt(-2147483648),
-      new int64.fromInt(-2147483648).toInt32());
-  Expect.equals(new int32.fromInt(2147483647),
-      new int64.fromInt(-2147483649).toInt32());
-  Expect.equals(new int32.fromInt(2147483646),
-      new int64.fromInt(-2147483650).toInt32());
-  Expect.equals(new int32.fromInt(2147483645),
-      new int64.fromInt(-2147483651).toInt32());
-}
-
-void testDiv() {
-  int64 deadBeef = new int64.fromInts(0xDEADBEEF, 0xDEADBEEF);
-  int64 ten = new int64.fromInt(10);
-  Expect.equals(new int64.fromInts(0xfcaaf97e, 0x63115fe5), deadBeef ~/ ten);
-  Expect.equals(int64.ZERO, int64.ONE ~/ int64.TWO);
-  Expect.equals(new int64.fromInts(0x3fffffff, 0xffffffff),
-    int64.MAX_VALUE ~/ int64.TWO);
-
-  Expect.equals(int64.ZERO, int64.ZERO ~/ new int64.fromInt(1000));
-  Expect.equals(int64.ONE, int64.MIN_VALUE ~/ int64.MIN_VALUE);
-  Expect.equals(int64.ZERO, new int64.fromInt(1000) ~/ int64.MIN_VALUE);
-
-  Expect.equals("-1125899906842624",
-    (int64.MIN_VALUE ~/ new int64.fromInt(8192)).toString());
-  Expect.equals("-1125762484664320",
-    (int64.MIN_VALUE ~/ new int64.fromInt(8193)).toString());
-  Expect.equals(int64.ZERO,
-    new int64.fromInt(-1000) ~/ new int64.fromInt(8192));
-  Expect.equals(int64.ZERO,
-    new int64.fromInt(-1000) ~/ new int64.fromInt(8193));
-  Expect.equals(new int64.fromInt(-122070),
-    new int64.fromInt(-1000000000) ~/ new int64.fromInt(8192));
-  Expect.equals(new int64.fromInt(-122055),
-    new int64.fromInt(-1000000000) ~/ new int64.fromInt(8193));
-  Expect.equals(new int64.fromInt(122070),
-    new int64.fromInt(1000000000) ~/ new int64.fromInt(8192));
-  Expect.equals(new int64.fromInt(122055),
-    new int64.fromInt(1000000000) ~/ new int64.fromInt(8193));
-
-  Expect.equals(new int64.fromInts(0x1fffff, 0xffffffff),
-    int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000400));
-  Expect.equals(new int64.fromInts(0x1fff, 0xffffffff),
-    int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00040000));
-  Expect.equals(new int64.fromInts(0x1f, 0xffffffff),
-    int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x04000000));
-  Expect.equals(new int64.fromInt(536870911),
-    int64.MAX_VALUE ~/ new int64.fromInts(0x00000004, 0x00000000));
-  Expect.equals(new int64.fromInt(2097151),
-    int64.MAX_VALUE ~/ new int64.fromInts(0x00000400, 0x00000000));
-  Expect.equals(new int64.fromInt(8191),
-    int64.MAX_VALUE ~/ new int64.fromInts(0x00040000, 0x00000000));
-  Expect.equals(new int64.fromInt(31),
-    int64.MAX_VALUE ~/ new int64.fromInts(0x04000000, 0x00000000));
-
-  Expect.equals(new int64.fromInts(0x2AAAAA, 0xAAAAAAAA),
-      int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000300));
-  Expect.equals(new int64.fromInts(0x2, 0xAAAAAAAA),
-      int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x30000000));
-  Expect.equals(new int64.fromInt(0x2AA),
-      int64.MAX_VALUE ~/ new int64.fromInts(0x00300000, 0x00000000));
-
-  Expect.equals(new int64.fromInts(0x708, 0x002E9501),
-      int64.MAX_VALUE ~/ new int64.fromInt(0x123456));
-  Expect.equals(new int64.fromInt(0x3BDA9),
-      int64.MAX_VALUE % new int64.fromInt(0x123456));
-}
-
-void testFactorial() {
-
-  int64 _fact(int64 n) {
-    if (n.isZero) {
-      return new int64.fromInt(1);
-    } else {
-      return n * _fact(n - new int64.fromInt(1));
+  test("JavaScript 53-bit integer boundary", () {
+    int64 _factorial(int64 n) {
+      if (n.isZero) {
+        return new int64.fromInt(1);
+      } else {
+        return n * _factorial(n - new int64.fromInt(1));
+      }
     }
-  }
+    int64 fact18 = _factorial(new int64.fromInt(18));
+    int64 fact17 = _factorial(new int64.fromInt(17));
+    expect(fact18 ~/ fact17, new int64.fromInt(18));
+  });
 
-  int64 fact18 = _fact(new int64.fromInt(18));
-  int64 fact17 = _fact(new int64.fromInt(17));
-  Expect.equals(new int64.fromInt(18), fact18 ~/ fact17);
-}
+  test("min, max values", () {
+    expect(new int64.fromInt(1) << 63, int64.MIN_VALUE);
+    expect(-(int64.MIN_VALUE + new int64.fromInt(1)), int64.MAX_VALUE);
+  });
 
-void testMinMax() {
-  Expect.equals(int64.MIN_VALUE, new int64.fromInt(1) << 63);
-  Expect.equals(int64.MAX_VALUE, -(int64.MIN_VALUE + new int64.fromInt(1)));
-}
+  group("string representation", () {
+    test("toString", () {
+      expect(new int64.fromInt(0).toString(), "0");
+      expect(new int64.fromInt(1).toString(), "1");
+      expect(new int64.fromInt(-1).toString(), "-1");
+      expect(new int64.fromInt(-10).toString(), "-10");
+      expect(int64.MIN_VALUE.toString(), "-9223372036854775808");
+      expect(int64.MAX_VALUE.toString(), "9223372036854775807");
 
-// Define % as Euclidean mod, with positive result for all arguments
-void testMod() {
-  Expect.equals(new int64.fromInt(0), int64.ZERO % new int64.fromInt(1000));
-  Expect.equals(new int64.fromInt(0), int64.MIN_VALUE % int64.MIN_VALUE);
-  Expect.equals(new int64.fromInt(1000),
-    new int64.fromInt(1000) % int64.MIN_VALUE);
-  Expect.equals(new int64.fromInt(0),
-    int64.MIN_VALUE % new int64.fromInt(8192));
-  Expect.equals(new int64.fromInt(6145),
-    int64.MIN_VALUE % new int64.fromInt(8193));
+      int top = 922337201;
+      int bottom = 967490662;
+      int64 fullnum = (new int64.fromInt(1000000000) * new int64.fromInt(top)) +
+          new int64.fromInt(bottom);
+      expect(fullnum.toString(), "922337201967490662");
+      expect((-fullnum).toString(), "-922337201967490662");
+      expect(new int64.fromInt(123456789).toString(), "123456789");
+    });
 
-  Expect.equals(new int64.fromInt(7192),
-    new int64.fromInt(-1000) % new int64.fromInt(8192));
-  Expect.equals(new int64.fromInt(7193),
-    new int64.fromInt(-1000) % new int64.fromInt(8193));
-  Expect.equals(new int64.fromInt(5632),
-    new int64.fromInt(-1000000000) % new int64.fromInt(8192));
-  Expect.equals(new int64.fromInt(4808),
-    new int64.fromInt(-1000000000) % new int64.fromInt(8193));
-  Expect.equals(new int64.fromInt(2560),
-    new int64.fromInt(1000000000) % new int64.fromInt(8192));
-  Expect.equals(new int64.fromInt(3385),
-    new int64.fromInt(1000000000) % new int64.fromInt(8193));
+    test("toHexString", () {
+      int64 deadbeef12341234 = new int64.fromInts(0xDEADBEEF, 0x12341234);
+      expect(int64.ZERO.toHexString(), "0");
+      expect(deadbeef12341234.toHexString(), "DEADBEEF12341234");
+      expect(new int64.fromInts(0x17678A7, 0xDEF01234).toHexString(),
+          "17678A7DEF01234");
+      expect(new int64.fromInt(123456789).toHexString(), "75BCD15");
+    });
 
-  Expect.equals(new int64.fromInts(0x0, 0x3ff),
-    int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00000400));
-  Expect.equals(new int64.fromInts(0x0, 0x3ffff),
-    int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00040000));
-  Expect.equals(new int64.fromInts(0x0, 0x3ffffff),
-    int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x04000000));
-  Expect.equals(new int64.fromInts(0x3, 0xffffffff),
-    int64.MAX_VALUE % new int64.fromInts(0x00000004, 0x00000000));
-  Expect.equals(new int64.fromInts(0x3ff, 0xffffffff),
-    int64.MAX_VALUE % new int64.fromInts(0x00000400, 0x00000000));
-  Expect.equals(new int64.fromInts(0x3ffff, 0xffffffff),
-    int64.MAX_VALUE % new int64.fromInts(0x00040000, 0x00000000));
-  Expect.equals(new int64.fromInts(0x3ffffff, 0xffffffff),
-    int64.MAX_VALUE % new int64.fromInts(0x04000000, 0x00000000));
-
-  Expect.equals(new int64.fromInt(0x12345678.remainder(0x22)),
-      new int64.fromInt(0x12345678).remainder(new int64.fromInt(0x22)));
-  Expect.equals(new int64.fromInt(0x12345678.remainder(-0x22)),
-      new int64.fromInt(0x12345678).remainder(new int64.fromInt(-0x22)));
-  Expect.equals(new int64.fromInt(-0x12345678.remainder(-0x22)),
-      new int64.fromInt(-0x12345678).remainder(new int64.fromInt(-0x22)));
-  Expect.equals(new int64.fromInt(-0x12345678.remainder(0x22)),
-      new int64.fromInt(-0x12345678).remainder(new int64.fromInt(0x22)));
-  Expect.equals(new int64.fromInt(0x12345678.remainder(0x22)),
-      new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)));
-}
-
-void testMultiplicative() {
-  Expect.equals(new int64.fromInt(3333),
-    new int64.fromInt(1111) * new int64.fromInt(3));
-  Expect.equals(new int64.fromInt(-3333),
-    new int64.fromInt(1111) * new int64.fromInt(-3));
-  Expect.equals(new int64.fromInt(-3333),
-    new int64.fromInt(-1111) * new int64.fromInt(3));
-  Expect.equals(new int64.fromInt(3333),
-    new int64.fromInt(-1111) * new int64.fromInt(-3));
-  Expect.equals(new int64.fromInt(0),
-    new int64.fromInt(100) * new int64.fromInt(0));
-
-  Expect.equals(new int64.fromInts(0x7ff63f7c, 0x1df4d840),
-      new int64.fromInts(0x12345678, 0x12345678) *
-      new int64.fromInts(0x1234, 0x12345678));
-  Expect.equals(new int64.fromInts(0x7ff63f7c, 0x1df4d840),
-      new int64.fromInts(0xf2345678, 0x12345678) *
-      new int64.fromInts(0x1234, 0x12345678));
-  Expect.equals(new int64.fromInts(0x297e3f7c, 0x1df4d840),
-      new int64.fromInts(0xf2345678, 0x12345678) *
-      new int64.fromInts(0xffff1234, 0x12345678));
-
-  Expect.equals(new int64.fromInt(0), int64.MIN_VALUE * new int64.fromInt(2));
-  Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE * new int64.fromInt(1));
-  Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE * new int64.fromInt(-1));
-
-  Expect.equals(new int64.fromInt(1), new int64.fromInt(5) ~/
-      new int64.fromInt(5));
-  Expect.equals(new int64.fromInt(333), new int64.fromInt(1000) ~/
-      new int64.fromInt(3));
-  Expect.equals(new int64.fromInt(-333), new int64.fromInt(1000) ~/
-      new int64.fromInt(-3));
-  Expect.equals(new int64.fromInt(-333), new int64.fromInt(-1000) ~/
-      new int64.fromInt(3));
-  Expect.equals(new int64.fromInt(333), new int64.fromInt(-1000) ~/
-      new int64.fromInt(-3));
-  Expect.equals(new int64.fromInt(0), new int64.fromInt(3) ~/
-      new int64.fromInt(1000));
-  Expect.equals(new int64.fromInts(0x1003d0, 0xe84f5ae8), new int64.fromInts(
-      0x12345678, 0x12345678) ~/ new int64.fromInts(0x0, 0x123));
-  Expect.equals(new int64.fromInts(0x0, 0x10003), new int64.fromInts(
-      0x12345678, 0x12345678) ~/ new int64.fromInts(0x1234, 0x12345678));
-  Expect.equals(new int64.fromInts(0xffffffff, 0xffff3dfe),
-      new int64.fromInts(0xf2345678, 0x12345678) ~/
-      new int64.fromInts(0x1234, 0x12345678));
-  Expect.equals(new int64.fromInts(0x0, 0xeda), new int64.fromInts(0xf2345678,
-      0x12345678) ~/ new int64.fromInts(0xffff1234, 0x12345678));
-
-  try {
-    new int64.fromInt(1) ~/ new int64.fromInt(0);
-    Expect.fail("Expected an IntegerDivisionByZeroException");
-  } on IntegerDivisionByZeroException catch (e) {
-  }
-
-  Expect.equals(new int64.fromInts(0xc0000000, 0x00000000),
-      int64.MIN_VALUE ~/ new int64.fromInt(2));
-  Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE ~/
-      new int64.fromInt(1));
-  Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE ~/
-      new int64.fromInt(-1));
-}
-
-void testNegate() {
-  Expect.equals(new int64.fromInt(-1), -new int64.fromInt(1));
-  Expect.equals(new int64.fromInt(1), -new int64.fromInt(-1));
-  Expect.equals(int64.MIN_VALUE, -int64.MIN_VALUE);
-}
-
-void testShift() {
-  Expect.equals("-1125899906842624", (int64.MIN_VALUE >> 13).toString());
-  Expect.equals(new int64.fromInts(0xd048d115, 0x9d159c00),
-    new int64.fromInts(0x12341234, 0x45674567) << 10);
-  Expect.equals(new int64.fromInts(0x48d04, 0x8d1159d1),
-    new int64.fromInts(0x12341234, 0x45674567) >> 10);
-  Expect.equals(new int64.fromInts(0x48d04, 0x8d1159d1),
-    new int64.fromInts(0x12341234, 0x45674567).shiftRightUnsigned(10));
-  Expect.equals(new int64.fromInts(0xd048d115, 0x9d159c00),
-    new int64.fromInts(0x92341234, 0x45674567) << 10);
-  Expect.equals(new int64.fromInts(0xffe48d04, 0x8d1159d1),
-    new int64.fromInts(0x92341234, 0x45674567) >> 10);
-  Expect.equals(new int64.fromInt(67108863),
-    new int64.fromInts(0xFFFFFFF, 0xFFFFFFFF) >> 34);
-  Expect.equals(new int64.fromInts(0x248d04, 0x8d1159d1),
-    new int64.fromInts(0x92341234, 0x45674567).shiftRightUnsigned(10));
-
-  for (int n = 0; n <= 66; n++) {
-    Expect.equals(new int64.fromInt(-1), new int64.fromInt(-1) >> n);
-  }
-
-  Expect.equals(new int64.fromInt(-32), new int64.fromInt(-1) << 5);
-  Expect.equals(new int64.fromInt(-1), new int64.fromInt(-1) << 0);
-  Expect.equals(-new int64.fromInts(0x40000000, 0x00000000),
-    (new int64.fromInt(1) << 63) >> 1);
-  Expect.equals(new int64.fromInt(0), (new int64.fromInt(-1) << 32) << 32);
-  Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE << 0);
-  Expect.equals(new int64.fromInt(0), int64.MIN_VALUE << 1);
-  Expect.equals(new int64.fromInts(0xfffffffc, 0x00000000),
-    (-new int64.fromInts(8, 0)) >> 1);
-  Expect.equals(new int64.fromInts(0x7ffffffc, 0x0),
-    (-new int64.fromInts(8, 0)).shiftRightUnsigned(1));
-
-  Expect.equals(new int64.fromInts(0x00723456, 0x789abcde),
-      new int64.fromInts(0x72345678, 0x9abcdef0) >> 8);
-  Expect.equals(new int64.fromInts(0x00007234, 0x56789abc),
-      new int64.fromInts(0x72345678, 0x9abcdef0) >> 16);
-  Expect.equals(new int64.fromInts(0x00000072, 0x3456789a),
-      new int64.fromInts(0x72345678, 0x9abcdef0) >> 24);
-  Expect.equals(new int64.fromInts(0x00000007, 0x23456789),
-      new int64.fromInts(0x72345678, 0x9abcdef0) >> 28);
-  Expect.equals(new int64.fromInts(0x00000000, 0x72345678),
-      new int64.fromInts(0x72345678, 0x9abcdef0) >> 32);
-  Expect.equals(new int64.fromInts(0x00000000, 0x07234567),
-      new int64.fromInts(0x72345678, 0x9abcdef0) >> 36);
-  Expect.equals(new int64.fromInts(0x00000000, 0x00723456),
-      new int64.fromInts(0x72345678, 0x9abcdef0) >> 40);
-  Expect.equals(new int64.fromInts(0x00000000, 0x00072345),
-      new int64.fromInts(0x72345678, 0x9abcde00) >> 44);
-  Expect.equals(new int64.fromInts(0x00000000, 0x00007234),
-      new int64.fromInts(0x72345678, 0x9abcdef0) >> 48);
-
-  Expect.equals(new int64.fromInts(0x00723456, 0x789abcde),
-      new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(8));
-  Expect.equals(new int64.fromInts(0x00007234, 0x56789abc),
-      new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(16));
-  Expect.equals(new int64.fromInts(0x00000072, 0x3456789a),
-      new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(24));
-  Expect.equals(new int64.fromInts(0x00000007, 0x23456789),
-      new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(28));
-  Expect.equals(new int64.fromInts(0x00000000, 0x72345678),
-      new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(32));
-  Expect.equals(new int64.fromInts(0x00000000, 0x07234567),
-      new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(36));
-  Expect.equals(new int64.fromInts(0x00000000, 0x00723456),
-      new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(40));
-  Expect.equals(new int64.fromInts(0x00000000, 0x00072345),
-      new int64.fromInts(0x72345678, 0x9abcde00).shiftRightUnsigned(44));
-  Expect.equals(new int64.fromInts(0x00000000, 0x00007234),
-      new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(48));
-
-  Expect.equals(new int64.fromInts(0xff923456, 0x789abcde),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 8);
-  Expect.equals(new int64.fromInts(0xffff9234, 0x56789abc),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 16);
-
-  Expect.equals(new int64.fromInts(0xffffff92, 0x3456789a),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 24);
-  Expect.equals(new int64.fromInts(0xfffffff9, 0x23456789),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 28);
-  Expect.equals(new int64.fromInts(0xffffffff, 0x92345678),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 32);
-  Expect.equals(new int64.fromInts(0xffffffff, 0xf9234567),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 36);
-  Expect.equals(new int64.fromInts(0xffffffff, 0xff923456),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 40);
-  Expect.equals(new int64.fromInts(0xffffffff, 0xfff92345),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 44);
-  Expect.equals(new int64.fromInts(0xffffffff, 0xffff9234),
-      new int64.fromInts(0x92345678, 0x9abcdef0) >> 48);
-
-  Expect.equals(new int64.fromInts(0x00923456, 0x789abcde),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(8));
-  Expect.equals(new int64.fromInts(0x00009234, 0x56789abc),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(16));
-  Expect.equals(new int64.fromInts(0x00000092, 0x3456789a),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(24));
-  Expect.equals(new int64.fromInts(0x00000009, 0x23456789),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(28));
-  Expect.equals(new int64.fromInts(0x00000000, 0x92345678),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(32));
-  Expect.equals(new int64.fromInts(0x00000000, 0x09234567),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(36));
-  Expect.equals(new int64.fromInts(0x00000000, 0x00923456),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(40));
-  Expect.equals(new int64.fromInts(0x00000000, 0x00092345),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(44));
-  Expect.equals(new int64.fromInts(0x00000000, 0x00009234),
-      new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(48));
-
-  try {
-    new int64.fromInt(17) >> -1;
-    Expect.fail("x >> -1 should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
-
-  try {
-    new int64.fromInt(17) << -1;
-    Expect.fail("x >> -1 should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
-
-  try {
-    new int64.fromInt(17).shiftRightUnsigned(-1);
-    Expect.fail("x >> -1 should throw ArgumentError");
-  } on ArgumentError catch (e) {
-  }
-
-}
-
-void testToHexString() {
-  int64 deadbeef12341234 = new int64.fromInts(0xDEADBEEF, 0x12341234);
-  Expect.equals("0", int64.ZERO.toHexString());
-  Expect.equals("DEADBEEF12341234", deadbeef12341234.toHexString());
-}
-
-void testToString() {
-  Expect.equals("0", new int64.fromInt(0).toString());
-  Expect.equals("1", new int64.fromInt(1).toString());
-  Expect.equals("-1", new int64.fromInt(-1).toString());
-  Expect.equals("-10", new int64.fromInt(-10).toString());
-  Expect.equals("-9223372036854775808", int64.MIN_VALUE.toString());
-  Expect.equals("9223372036854775807", int64.MAX_VALUE.toString());
-
-  int top = 922337201;
-  int bottom = 967490662;
-  int64 fullnum = (new int64.fromInt(1000000000) * new int64.fromInt(top)) +
-      new int64.fromInt(bottom);
-
-  Expect.equals("922337201967490662", fullnum.toString());
-  Expect.equals("-922337201967490662", (-fullnum).toString());
-
-  Expect.equals("17678A7DEF01234",
-      new int64.fromInts(0x17678A7, 0xDEF01234).toHexString());
-
-  Expect.equals("123456789", new int64.fromInt(123456789).toString());
-  Expect.equals("75BCD15", new int64.fromInt(123456789).toHexString());
-  Expect.equals("223101104124", new int64.fromInt(123456789).toRadixString(5));
-
-  Expect.equals(
-        "-1000000000000000000000000000000000000000000000000000000000000000",
-      int64.MIN_VALUE.toRadixString(2));
-  Expect.equals("-2021110011022210012102010021220101220222",
-      int64.MIN_VALUE.toRadixString(3));
-  Expect.equals("-20000000000000000000000000000000",
-      int64.MIN_VALUE.toRadixString(4));
-  Expect.equals("-1104332401304422434310311213",
-      int64.MIN_VALUE.toRadixString(5));
-  Expect.equals("-1540241003031030222122212", int64.MIN_VALUE.toRadixString(6));
-  Expect.equals("-22341010611245052052301", int64.MIN_VALUE.toRadixString(7));
-  Expect.equals("-1000000000000000000000", int64.MIN_VALUE.toRadixString(8));
-  Expect.equals("-67404283172107811828", int64.MIN_VALUE.toRadixString(9));
-  Expect.equals("-9223372036854775808", int64.MIN_VALUE.toRadixString(10));
-  Expect.equals("-1728002635214590698", int64.MIN_VALUE.toRadixString(11));
-  Expect.equals("-41A792678515120368", int64.MIN_VALUE.toRadixString(12));
-  Expect.equals("-10B269549075433C38", int64.MIN_VALUE.toRadixString(13));
-  Expect.equals("-4340724C6C71DC7A8", int64.MIN_VALUE.toRadixString(14));
-  Expect.equals("-160E2AD3246366808", int64.MIN_VALUE.toRadixString(15));
-  Expect.equals("-8000000000000000", int64.MIN_VALUE.toRadixString(16));
-
-  Expect.equals(
-        "111111111111111111111111111111111111111111111111111111111111111",
-      int64.MAX_VALUE.toRadixString(2));
-  Expect.equals("2021110011022210012102010021220101220221",
-      int64.MAX_VALUE.toRadixString(3));
-  Expect.equals("13333333333333333333333333333333",
-      int64.MAX_VALUE.toRadixString(4));
-  Expect.equals("1104332401304422434310311212",
-      int64.MAX_VALUE.toRadixString(5));
-  Expect.equals("1540241003031030222122211", int64.MAX_VALUE.toRadixString(6));
-  Expect.equals("22341010611245052052300", int64.MAX_VALUE.toRadixString(7));
-  Expect.equals("777777777777777777777", int64.MAX_VALUE.toRadixString(8));
-  Expect.equals("67404283172107811827", int64.MAX_VALUE.toRadixString(9));
-  Expect.equals("9223372036854775807", int64.MAX_VALUE.toRadixString(10));
-  Expect.equals("1728002635214590697", int64.MAX_VALUE.toRadixString(11));
-  Expect.equals("41A792678515120367", int64.MAX_VALUE.toRadixString(12));
-  Expect.equals("10B269549075433C37", int64.MAX_VALUE.toRadixString(13));
-  Expect.equals("4340724C6C71DC7A7", int64.MAX_VALUE.toRadixString(14));
-  Expect.equals("160E2AD3246366807", int64.MAX_VALUE.toRadixString(15));
-  Expect.equals("7FFFFFFFFFFFFFFF", int64.MAX_VALUE.toRadixString(16));
+    test("toRadixString", () {
+      expect(new int64.fromInt(123456789).toRadixString(5), "223101104124");
+      expect(int64.MIN_VALUE.toRadixString(2),
+          "-1000000000000000000000000000000000000000000000000000000000000000");
+      expect(int64.MIN_VALUE.toRadixString(3),
+          "-2021110011022210012102010021220101220222");
+      expect(int64.MIN_VALUE.toRadixString(4),
+          "-20000000000000000000000000000000");
+      expect(int64.MIN_VALUE.toRadixString(5), "-1104332401304422434310311213");
+      expect(int64.MIN_VALUE.toRadixString(6), "-1540241003031030222122212");
+      expect(int64.MIN_VALUE.toRadixString(7), "-22341010611245052052301");
+      expect(int64.MIN_VALUE.toRadixString(8), "-1000000000000000000000");
+      expect(int64.MIN_VALUE.toRadixString(9), "-67404283172107811828");
+      expect(int64.MIN_VALUE.toRadixString(10), "-9223372036854775808");
+      expect(int64.MIN_VALUE.toRadixString(11), "-1728002635214590698");
+      expect(int64.MIN_VALUE.toRadixString(12), "-41A792678515120368");
+      expect(int64.MIN_VALUE.toRadixString(13), "-10B269549075433C38");
+      expect(int64.MIN_VALUE.toRadixString(14), "-4340724C6C71DC7A8");
+      expect(int64.MIN_VALUE.toRadixString(15), "-160E2AD3246366808");
+      expect(int64.MIN_VALUE.toRadixString(16), "-8000000000000000");
+      expect(int64.MAX_VALUE.toRadixString(2),
+          "111111111111111111111111111111111111111111111111111111111111111");
+      expect(int64.MAX_VALUE.toRadixString(3),
+          "2021110011022210012102010021220101220221");
+      expect(int64.MAX_VALUE.toRadixString(4),
+          "13333333333333333333333333333333");
+      expect(int64.MAX_VALUE.toRadixString(5), "1104332401304422434310311212");
+      expect(int64.MAX_VALUE.toRadixString(6), "1540241003031030222122211");
+      expect(int64.MAX_VALUE.toRadixString(7), "22341010611245052052300");
+      expect(int64.MAX_VALUE.toRadixString(8), "777777777777777777777");
+      expect(int64.MAX_VALUE.toRadixString(9), "67404283172107811827");
+      expect(int64.MAX_VALUE.toRadixString(10), "9223372036854775807");
+      expect(int64.MAX_VALUE.toRadixString(11), "1728002635214590697");
+      expect(int64.MAX_VALUE.toRadixString(12), "41A792678515120367");
+      expect(int64.MAX_VALUE.toRadixString(13), "10B269549075433C37");
+      expect(int64.MAX_VALUE.toRadixString(14), "4340724C6C71DC7A7");
+      expect(int64.MAX_VALUE.toRadixString(15), "160E2AD3246366807");
+      expect(int64.MAX_VALUE.toRadixString(16), "7FFFFFFFFFFFFFFF");
+    });
+  });
 }
diff --git a/pkg/fixnum/test/int_64_vm_test.dart b/pkg/fixnum/test/int_64_vm_test.dart
deleted file mode 100644
index b0a40a7..0000000
--- a/pkg/fixnum/test/int_64_vm_test.dart
+++ /dev/null
@@ -1,331 +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.
-
-// A test to compare the results of the fixnum library with the Dart VM
-
-library int64vmtest;
-
-import "package:expect/expect.dart";
-import 'dart:math' as math;
-
-part 'package:fixnum/src/int32.dart';
-part 'package:fixnum/src/int64.dart';
-part 'package:fixnum/src/intx.dart';
-
-final random = new math.Random();
-
-void main() {
-  int64VMTest test = new int64VMTest();
-  test.doTestBinary(new BinaryOp("&", (a, b) => a & b));
-  test.doTestBinary(new BinaryOp("|", (a, b) => a | b));
-  test.doTestBinary(new BinaryOp("^", (a, b) => a ^ b));
-  test.doTestBinary(new BinaryOp("+", (a, b) => a + b));
-  test.doTestBinary(new BinaryOp("-", (a, b) => a - b));
-  test.doTestBinary(new BinaryOp("*", (a, b) => a * b));
-  test.doTestUnary(new UnaryOp("-", (a) => -a));
-  test.doTestUnary(new UnaryOp("~", (a) => ~a));
-  test.doTestShift(new ShiftOp("<<", (a, n) => a << (n & 63)));
-  test.doTestShift(new ShiftOp(">>", (a, n) => a >> (n & 63)));
-  test.doTestBoolean(new BooleanOp("compareTo", (a, b) => a.compareTo(b)));
-  test.doTestBoolean(new BooleanOp("==", (a, b) => a == b));
-  test.doTestBoolean(new BooleanOp("!=", (a, b) => a != b));
-  test.doTestBoolean(new BooleanOp("<", (a, b) => a < b));
-  test.doTestBoolean(new BooleanOp("<=", (a, b) => a <= b));
-  test.doTestBoolean(new BooleanOp(">", (a, b) => a > b));
-  test.doTestBoolean(new BooleanOp(">=", (a, b) => a >= b));
-  test.doTestBinary(new BinaryOp("%", (a, b) => a % b));
-  test.doTestBinary(new BinaryOp("~/", (a, b) => a ~/ b));
-  test.doTestBinary(new BinaryOp("remainder", (a, b) => a.remainder(b)));
-}
-
-const int DISCARD = 0;
-
-int64 _randomInt64() {
-  int i = 0;
-  for (int b = 0; b < 64; b++) {
-      double rand = random.nextDouble();
-      for (int j = 0; j < DISCARD; j++) {
-        rand = random.nextDouble();
-      }
-      i = (i << 1) | ((rand > 0.5) ? 1 : 0);
-  }
-  return new int64.fromInt(i);
-}
-
-int _randomInt(int n) {
-  double rand = random.nextDouble();
-  for (int i = 0; i < DISCARD; i++) {
-    rand = random.nextDouble();
-  }
-  return (rand * n).floor();
-}
-
-class Op {
-  String name;
-  Function op;
-
-  Op(String this.name, Function this.op);
-
-  // Truncate x to a value in the range [-2^63, 2^63 - 1]
-  int trunc64(int x) {
-    int trunc = x & 0xffffffffffffffff;
-    if ((trunc & 0x8000000000000000) != 0) {
-      trunc -= 18446744073709551616; // 2^64
-    }
-    return trunc;
-  }
-}
-
-class UnaryOp extends Op {
-  UnaryOp(String name, Function op) : super(name, op);
-  int ref(int val) => trunc64(op(val));
-  int64 test(int64 val) => op(val);
-}
-
-class BinaryOp extends Op {
-  BinaryOp(String name, Function op) : super(name, op);
-  int ref(int val0, int val1) => trunc64(op(val0, val1));
-  int64 test(int64 val0, int64 val1) => op(val0, val1);
-}
-
-class BooleanOp extends Op {
-  BooleanOp(String name, Function op) : super(name, op);
-  bool ref(int val0, int val1) => op(val0, val1);
-  bool test(int64 val0, int64 val1) => op(val0, val1);
-}
-
-class ShiftOp extends Op {
-  ShiftOp(String name, Function op) : super(name, op);
-  int ref(int val0, int shift) => trunc64(op(val0, shift));
-  int64 test(int64 val0, int shift) => op(val0, shift);
-}
-
-class int64VMTest {
-  static const int BASE_VALUES = 32;
-  static const int RANDOM_TESTS = 32;
-  List<int64> TEST_VALUES;
-
-  int64VMTest() {
-    Set<int64> testSet = new Set<int64>();
-    for (int i = 0; i < BASE_VALUES; i++) {
-      testSet.add(new int64.fromInt(i));
-      testSet.add(new int64.fromInt(-i));
-
-      testSet.add(int64.MIN_VALUE + i);
-      testSet.add(int64.MAX_VALUE - i);
-
-      testSet.add(new int64.fromInt(i << int64._BITS ~/ 2));
-      testSet.add(new int64.fromInt(i << int64._BITS));
-      testSet.add(new int64.fromInt(i << (3 * int64._BITS) ~/ 2));
-      testSet.add(new int64.fromInt(i << 2 * int64._BITS));
-      testSet.add(new int64.fromInt(i << (5 * int64._BITS) ~/ 2));
-    }
-
-    int64 one = new int64.fromInt(1);
-    int64 three = new int64.fromInt(3);
-    int64 ones = int64.parseHex("1111111111111111");
-    int64 tens = int64.parseHex("1010101010101010");
-    int64 oh_ones = int64.parseHex("0101010101010101");
-    int64 digits = int64.parseHex("123456789ABCDEFF");
-    for (int i = 0; i < 16; i++) {
-      testSet.add(ones * i);
-      testSet.add(~(ones * i));
-      testSet.add(-(ones * i));
-      testSet.add(tens * i);
-      testSet.add(~(tens * i));
-      testSet.add(-(tens * i));
-      testSet.add(oh_ones * i);
-      testSet.add(~(oh_ones * i));
-      testSet.add(-(oh_ones * i));
-      testSet.add(digits * i);
-      testSet.add(~(digits * i));
-      testSet.add(-(digits * i));
-    }
-
-    for (int i = 0; i < 64; i += 4) {
-      testSet.add(one << i);
-      testSet.add(~(one << i));
-      testSet.add(digits >> i);
-      testSet.add(-(digits >> i));
-
-      // Powers of two and nearby numbers
-      testSet.add(one << i);
-      for (int j = 1; j <= 16; j++) {
-        testSet.add((one << i) + j);
-        testSet.add(-((one << i) + j));
-        testSet.add(~((one << i) + j));
-        testSet.add((one << i) - j);
-        testSet.add(-((one << i) - j));
-        testSet.add(~((one << i) - j));
-        testSet.add((three << i) + j);
-        testSet.add(-((three << i) + j));
-        testSet.add(~((three << i) + j));
-        testSet.add((three << i) - j);
-        testSet.add(-((three << i) - j));
-        testSet.add(~((three << i) - j));
-      }
-    }
-
-    for (int a = 0; a < 19; a++) {
-      // Math.pow(10, a)
-      int pow = 1;
-      for (int j = 0; j < a; j++) {
-        pow *= 10;
-      }
-      testSet.add(new int64.fromInt(pow));
-    }
-
-    TEST_VALUES = new List<int64>(testSet.length);
-    int index = 0;
-    for (int64 val in testSet) {
-      TEST_VALUES[index++] = val;
-    }
-
-    print("VALUES.length = $index");
-  }
-
-  void _doTestUnary(UnaryOp op, int64 val) {
-    int ref = op.ref(val.toInt());
-    int64 result64 = op.test(val);
-    int result = result64.toInt();
-    if (ref != result) {
-      Expect.fail("${op.name}: val = $val");
-    }
-  }
-
-  void doTestUnary(UnaryOp op) {
-    print("Testing operator ${op.name}");
-    for (int i = 0; i < TEST_VALUES.length; i++) {
-      _doTestUnary(op, TEST_VALUES[i]);
-    }
-    for (int i = 0; i < RANDOM_TESTS; i++) {
-      int64 randomLong = _randomInt64();
-      _doTestUnary(op, randomLong);
-    }
-  }
-
-  void _doTestBinary(BinaryOp op, int64 val0, int64 val1) {
-    // print("Test val0 = $val0, val1 = $val1");
-    var refException = null;
-    int ref = -1;
-    try {
-      ref = op.ref(val0.toInt(), val1.toInt());
-    } on Exception catch (e) {
-      refException = e;
-    }
-    var testException = null;
-    int result = -2;
-    int64 result64;
-    try {
-      int64 val0_save = new int64._copy(val0);
-      int64 val1_save = new int64._copy(val1);
-      result64 = op.test(val0, val1);
-      result = result64.toInt();
-      if (val0 != val0_save) {
-        print(
-            "Test altered first argument val0 = $val0, val0_save = $val0_save");
-      }
-      if (val1 != val1_save) {
-        print("Test altered second argument");
-      }
-    } on Exception catch (e) {
-      testException = e;
-    }
-    if (testException is IntegerDivisionByZeroException &&
-        refException is IntegerDivisionByZeroException) {
-    } else if (testException != null || refException != null) {
-      Expect.fail("${op.name}: val0 = $val0, val1 = $val1, "
-          "testException = $testException, refException = $refException");
-      return;
-    } else if (ref != result) {
-      if ("%" == op.name && ref < 0) {
-        // print("Dart VM bug: ${op.name}: val0 = $val0, val1 = $val1, "
-        //    "ref = $ref, result64 = $result64, result = $result");
-      } else {
-        Expect.fail("${op.name}: val0 = $val0, val1 = $val1, "
-            "ref = $ref, result64 = $result64, result = $result");
-      }
-    }
-  }
-
-  void doTestBinary(BinaryOp op) {
-    print("Testing operator ${op.name}");
-    for (int i = 0; i < TEST_VALUES.length; i++) {
-      int64 randomLong = _randomInt64();
-      _doTestBinary(op, TEST_VALUES[i], randomLong);
-      _doTestBinary(op, randomLong, TEST_VALUES[i]);
-      for (int j = 0; j < TEST_VALUES.length; j++) {
-        _doTestBinary(op, TEST_VALUES[i], TEST_VALUES[j]);
-      }
-    }
-    for (int i = 0; i < RANDOM_TESTS; i++) {
-      int64 longVal0 = _randomInt64();
-      int64 longVal1 = _randomInt64();
-      if (_randomInt(20) == 0) {
-        if (_randomInt(2) == 0) {
-          longVal1 = longVal0;
-        } else {
-          longVal1 = -longVal0;
-        }
-      }
-      _doTestBinary(op, longVal0, longVal1);
-    }
-  }
-
-  void _doTestBoolean(BooleanOp op, int64 val0, int64 val1) {
-    bool ref = op.ref(val0.toInt(), val1.toInt());
-    bool result = op.test(val0, val1);
-    if (ref != result) {
-      Expect.fail("${op.name}: val0 = $val0, val1 = $val1");
-    }
-  }
-
-  void doTestBoolean(BooleanOp op) {
-    print("Testing operator ${op.name}");
-    for (int i = 0; i < TEST_VALUES.length; i++) {
-      int64 randomLong = _randomInt64();
-      _doTestBoolean(op, TEST_VALUES[i], randomLong);
-      _doTestBoolean(op, randomLong, TEST_VALUES[i]);
-      for (int j = 0; j < TEST_VALUES.length; j++) {
-        _doTestBoolean(op, TEST_VALUES[i], TEST_VALUES[j]);
-      }
-    }
-    for (int i = 0; i < RANDOM_TESTS; i++) {
-      int64 longVal0 = _randomInt64();
-      int64 longVal1 = _randomInt64();
-      if (_randomInt(20) == 0) {
-        if (_randomInt(2) == 0) {
-          longVal1 = longVal0;
-        } else {
-          longVal1 = -longVal0;
-        }
-      }
-      _doTestBoolean(op, longVal0, longVal1);
-    }
-  }
-
-  void _doTestShift(ShiftOp op, int64 val, int shift) {
-    int ref = op.ref(val.toInt(), shift);
-    int64 result64 = op.test(val, shift);
-    int result = result64.toInt();
-    if (ref != result) {
-      Expect.fail("${op.name}: val = $val, shift = $shift");
-    }
-  }
-
-  void doTestShift(ShiftOp op) {
-    print("Testing operator ${op.name}");
-    for (int i = 0; i < TEST_VALUES.length; i++) {
-      for (int shift = -64; shift <= 64; shift++) {
-        _doTestShift(op, TEST_VALUES[i], shift);
-      }
-    }
-    for (int i = 0; i < RANDOM_TESTS; i++) {
-      int64 randomLong = _randomInt64();
-      for (int shift = -64; shift <= 64; shift++) {
-        _doTestShift(op, randomLong, shift);
-      }
-    }
-  }
-}
diff --git a/pkg/path/lib/path.dart b/pkg/path/lib/path.dart
index 25ce0e6..1d83c00 100644
--- a/pkg/path/lib/path.dart
+++ b/pkg/path/lib/path.dart
@@ -109,7 +109,7 @@
 /// Gets the part of [path] before the last separator.
 ///
 ///     path.dirname('path/to/foo.dart'); // -> 'path/to'
-///     path.dirname('path/to');          // -> 'to'
+///     path.dirname('path/to');          // -> 'path'
 ///
 /// Trailing separators are ignored.
 ///
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 0a89418..a3edba3 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -2,13 +2,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-# Run this test manually to verify that the fixnum library produces
-# the same results as native ints on a set of directed and random inputs.
-# Skip it when running automated tests because it times out.  This
-# test only makes sense on runtimes that support 64-bit integer
-# arithmetic natively, i.e., the VM.
-fixnum/test/int_64_vm_test: Skip
-
 # Don't run any test-like files that show up in packages directories. It
 # shouldn't be necessary to run "pub install" in these packages, but if you do
 # it shouldn't break the tests.
diff --git a/pkg/unittest/lib/compact_vm_config.dart b/pkg/unittest/lib/compact_vm_config.dart
index b2bbc59..97c120a 100644
--- a/pkg/unittest/lib/compact_vm_config.dart
+++ b/pkg/unittest/lib/compact_vm_config.dart
@@ -12,8 +12,10 @@
 
 import 'dart:async';
 import 'dart:io';
+import 'dart:isolate';
 
 import 'unittest.dart';
+import 'src/utils.dart';
 import 'vm_config.dart';
 
 const String _GREEN = '\u001b[32m';
@@ -23,11 +25,16 @@
 const int MAX_LINE = 80;
 
 class CompactVMConfiguration extends VMConfiguration {
+  // The VM won't shut down if a receive port is open. Use this to make sure
+  // we correctly wait for asynchronous tests.
+  ReceivePort _receivePort;
+
   DateTime _start;
   int _pass = 0;
   int _fail = 0;
 
   void onInit() {
+    _receivePort = new ReceivePort();
     // Override and don't call the superclass onInit() to avoid printing the
     // "unittest-suite-..." boilerplate.
   }
@@ -51,11 +58,11 @@
       _progressLine(_start, _pass, _fail, test.description);
       print('');
       if (test.message != '') {
-        print(_indent(test.message));
+        print(indent(test.message));
       }
 
-      if (test.stackTrace != null && test.stackTrace != '') {
-        print(_indent(test.stackTrace));
+      if (test.stackTrace != null) {
+        print(indent(test.stackTrace.toString()));
       }
     }
   }
@@ -64,14 +71,11 @@
     // Override and don't call the superclass onDone() to avoid printing the
     // "unittest-suite-..." boilerplate.
     Future.wait([stdout.close(), stderr.close()]).then((_) {
+      _receivePort.close();
       exit(success ? 0 : 1);
     });
   }
 
-  String _indent(String str) {
-    return str.split("\n").map((line) => "  $line").join("\n");
-  }
-
   void onSummary(int passed, int failed, int errors, List<TestCase> results,
       String uncaughtError) {
     var success = false;
diff --git a/pkg/unittest/lib/html_config.dart b/pkg/unittest/lib/html_config.dart
index 303afb6..86123cf 100644
--- a/pkg/unittest/lib/html_config.dart
+++ b/pkg/unittest/lib/html_config.dart
@@ -80,7 +80,9 @@
       </tr>''';
 
   if (test_.stackTrace != null) {
-    html = '$html<tr><td></td><td colspan="2"><pre>${_htmlEscape(test_.stackTrace)}</pre></td></tr>';
+    html = '$html<tr><td></td><td colspan="2"><pre>' +
+        _htmlEscape(test_.stackTrace.toString()) +
+        '</pre></td></tr>';
   }
 
   return html;
diff --git a/pkg/unittest/lib/html_enhanced_config.dart b/pkg/unittest/lib/html_enhanced_config.dart
index 2fd2fa3..5cc5fe5 100644
--- a/pkg/unittest/lib/html_enhanced_config.dart
+++ b/pkg/unittest/lib/html_enhanced_config.dart
@@ -270,7 +270,8 @@
         '${test_.description}. ${_htmlEscape(test_.message)}');
 
     if (test_.stackTrace != null) {
-      addRowElement('', '', '<pre>${_htmlEscape(test_.stackTrace)}</pre>');
+      addRowElement('', '',
+          '<pre>${_htmlEscape(test_.stackTrace.toString())}</pre>');
     }
   }
 
diff --git a/pkg/unittest/lib/interactive_html_config.dart b/pkg/unittest/lib/interactive_html_config.dart
index 9d43d09..b962e1e 100644
--- a/pkg/unittest/lib/interactive_html_config.dart
+++ b/pkg/unittest/lib/interactive_html_config.dart
@@ -20,6 +20,9 @@
 import 'dart:html';
 import 'dart:async';
 import 'dart:math';
+
+import 'package:stack_trace/stack_trace.dart';
+
 import 'unittest.dart';
 
 /** The messages exchanged between parent and child. */
@@ -152,17 +155,25 @@
   }
 
   /**
-   * Get the elapsed time for the test, anbd post the test result
-   * back to the parent window. If the test failed due to an exception
-   * the stack is posted back too (before the test result).
+   * Get the elapsed time for the test, and post the test result back to the
+   * parent window. If the test failed due to an exception the stack is posted
+   * back too (before the test result).
    */
   void onTestResult(TestCase testCase) {
     super.onTestResult(testCase);
     DateTime end = new DateTime.now();
     int elapsed = end.difference(_testStarts[testCase.id]).inMilliseconds;
     if (testCase.stackTrace != null) {
+      var message = json.stringify(testCase.stackTrace.frames.map((frame) {
+        return <String>{
+          "uri": frame.uri.toString(),
+          "line": frame.line,
+          "column": frame.column,
+          "member": frame.member
+        };
+      }).toList());
       _parentWindow.postMessage(
-          _Message.text(_Message.STACK, elapsed, testCase.stackTrace), '*');
+          _Message.text(_Message.STACK, elapsed, message), '*');
     }
     _parentWindow.postMessage(
         _Message.text(testCase.result, elapsed, testCase.message), '*');
@@ -185,7 +196,7 @@
 
 
   /** The stack that was posted back from the child, if any. */
-  String _stack;
+  Trace _stack;
 
   int _testTime;
   /**
@@ -233,7 +244,13 @@
     if (msg.messageType == _Message.LOG) {
       logMessage(e.data);
     } else if (msg.messageType == _Message.STACK) {
-      _stack = msg.body;
+      _stack = new Trace(json.parse(msg.body).map((frame) {
+        return new Frame(
+            Uri.parse(frame['uri']),
+            frame['line'],
+            frame['column'],
+            frame['member']);
+      }));
     } else {
       _testTime = msg.elapsed;
       logMessage(_Message.text(_Message.LOG, _testTime, 'Complete'));
diff --git a/pkg/unittest/lib/src/config.dart b/pkg/unittest/lib/src/config.dart
index 490ef80..a08ee16 100644
--- a/pkg/unittest/lib/src/config.dart
+++ b/pkg/unittest/lib/src/config.dart
@@ -55,8 +55,8 @@
 
   // If stopTestOnExpectFailure is false, we need to capture failures, which
   // we do with this List.
-  List _testLogBuffer = new List();
-  
+  final _testLogBuffer = <Pair<String, Trace>>[];
+
   /**
    * The constructor sets up a failure handler for [expect] that redirects
    * [expect] failures to [onExpectFailure].
@@ -99,24 +99,25 @@
     if (!stopTestOnExpectFailure && _testLogBuffer.length > 0) {
       // Write the message/stack pairs up to the last pairs.
       var reason = new StringBuffer();
-      for (var i = 0; i < _testLogBuffer.length - 2; i += 2) {
-        reason.write(_testLogBuffer[i]);
+      for (var reasonAndTrace in
+             _testLogBuffer.take(_testLogBuffer.length - 1)) {
+        reason.write(reasonAndTrace.first);
         reason.write('\n');
-        reason.write(_formatStack(_testLogBuffer[i+1]));
+        reason.write(reasonAndTrace.last);
         reason.write('\n');
       }
+      var lastReasonAndTrace = _testLogBuffer.last;
       // Write the last message.
-      reason.write(_testLogBuffer[_testLogBuffer.length - 2]);
+      reason.write(lastReasonAndTrace.first);
       if (testCase.result == PASS) {
         testCase._result = FAIL;
         testCase._message = reason.toString();
         // Use the last stack as the overall failure stack.    
-        testCase._stackTrace = 
-            _formatStack(_testLogBuffer[_testLogBuffer.length - 1]);
+        testCase._stackTrace = lastReasonAndTrace.last;
       } else {
         // Add the last stack to the message; we have a further stack
         // caused by some other failure.
-        reason.write(_formatStack(_testLogBuffer[_testLogBuffer.length - 1]));
+        reason.write(lastReasonAndTrace.last);
         reason.write('\n');
         // Add the existing reason to the end of the expect log to 
         // create the final message.
@@ -150,11 +151,11 @@
     if (stopTestOnExpectFailure) {
       throw new TestFailure(reason);
     } else {
-      _testLogBuffer.add(reason);
       try {
         throw '';
       } catch (_, stack) {
-        _testLogBuffer.add(stack);
+        _testLogBuffer.add(
+            new Pair<String, Trace>(reason, new Trace.from(stack)));
       }
     }
   }
@@ -170,12 +171,12 @@
     result.write("\n");
 
     if (testCase.message != '') {
-      result.write(_indent(testCase.message));
+      result.write(indent(testCase.message));
       result.write("\n");
     }
 
-    if (testCase.stackTrace != null && testCase.stackTrace != '') {
-      result.write(_indent(testCase.stackTrace));
+    if (testCase.stackTrace != null) {
+      result.write(indent(testCase.stackTrace.toString()));
       result.write("\n");
     }
     return result.toString();
@@ -228,17 +229,10 @@
     }
   }
 
-  String _indent(String str) {
-    // TODO(nweiz): Use this simpler code once issue 2980 is fixed.
-    // return str.replaceAll(new RegExp("^", multiLine: true), "  ");
-
-    return str.split("\n").map((line) => "  $line").join("\n");
-  }
-
   /** Handle errors that happen outside the tests. */
   // TODO(vsm): figure out how to expose the stack trace here
   // Currently e.message works in dartium, but not in dartc.
-  void handleExternalError(e, String message, [String stack = '']) =>
+  void handleExternalError(e, String message, [stack]) =>
       _reportTestError('$message\nCaught $e', stack);
 
   _postMessage(String message) {
diff --git a/pkg/unittest/lib/src/test_case.dart b/pkg/unittest/lib/src/test_case.dart
index ad5bd6a..e28d21f 100644
--- a/pkg/unittest/lib/src/test_case.dart
+++ b/pkg/unittest/lib/src/test_case.dart
@@ -41,9 +41,9 @@
    */
   String get result => _result;
 
-  String _stackTrace;
+  Trace _stackTrace;
   /** Stack trace associated with this test, or [null] if it succeeded. */
-  String get stackTrace => _stackTrace;
+  Trace get stackTrace => _stackTrace;
 
   /** The group (or groups) under which this test is running. */
   final String currentGroup;
@@ -69,7 +69,6 @@
 
   Function _errorHandler(String stage) => (e) {
     var stack = getAttachedStackTrace(e);
-    stack = (stack == null) ? '' : '$stack';
     if (result == null || result == PASS) {
       if (e is TestFailure) {
         fail("$e", stack);
@@ -122,9 +121,9 @@
 
   // Set the results, notify the config, and return true if this
   // is the first time the result is being set.
-  void _setResult(String testResult, String messageText, String stack) {
+  void _setResult(String testResult, String messageText, stack) {
     _message = messageText;
-    _stackTrace = _formatStack(stack);
+    _stackTrace = _getTrace(stack);
     if (result == null) {
       _result = testResult;
       _config.onTestResult(this);
@@ -134,9 +133,7 @@
     }
   }
 
-  void _complete(String testResult,
-                [String messageText = '',
-                 String stack = '']) {
+  void _complete(String testResult, [String messageText = '', stack]) {
     if (runningTime == null) {
       // The startTime can be `null` if an error happened during setup. In this
       // case we simply report a running time of 0.
@@ -158,8 +155,7 @@
     _complete(PASS);
   }
 
-  void fail(String messageText, [String stack = '']) {
-    assert(stack != null);
+  void fail(String messageText, [stack]) {
     if (result != null) {
       String newMessage = (result == PASS)
           ? 'Test failed after initially passing: $messageText'
@@ -171,8 +167,7 @@
     }
   }
 
-  void error(String messageText, [String stack = '']) {
-    assert(stack != null);
+  void error(String messageText, [stack]) {
     _complete(ERROR, messageText, stack);
   }
 
diff --git a/pkg/unittest/lib/src/utils.dart b/pkg/unittest/lib/src/utils.dart
index 6442ac4..e10c597 100644
--- a/pkg/unittest/lib/src/utils.dart
+++ b/pkg/unittest/lib/src/utils.dart
@@ -46,3 +46,24 @@
     return ch;
 }
 
+/** Indent each line in [str] by two spaces. */
+String indent(String str) =>
+  str.replaceAll(new RegExp("^", multiLine: true), "  ");
+
+/** A pair of values. */
+class Pair<E, F> {
+  E first;
+  F last;
+
+  Pair(this.first, this.last);
+
+  String toString() => '($first, $last)';
+
+  bool operator==(other) {
+    if (other is! Pair) return false;
+    return other.first == first && other.last == last;
+  }
+
+  int get hashCode => first.hashCode ^ last.hashCode;
+}
+
diff --git a/pkg/unittest/lib/unittest.dart b/pkg/unittest/lib/unittest.dart
index ec78877..7b134e9 100644
--- a/pkg/unittest/lib/unittest.dart
+++ b/pkg/unittest/lib/unittest.dart
@@ -173,6 +173,9 @@
 import 'matcher.dart';
 export 'matcher.dart';
 
+import 'package:stack_trace/stack_trace.dart';
+
+import 'src/utils.dart';
 part 'src/config.dart';
 part 'src/test_case.dart';
 
@@ -453,7 +456,7 @@
         testCase.error(
             'Callback ${id}called ($actualCalls) after test case '
             '${testCase.description} has already been marked as '
-            '${testCase.result}.', '');
+            '${testCase.result}.');
       }
       return false;
     } else if (maxExpectedCalls >= 0 && actualCalls > maxExpectedCalls) {
@@ -674,7 +677,7 @@
  * Utility function that can be used to notify the test framework that an
  *  error was caught outside of this library.
  */
-void _reportTestError(String msg, String trace) {
+void _reportTestError(String msg, trace) {
  if (_currentTestCaseIndex < testCases.length) {
     final testCase = testCases[_currentTestCaseIndex];
     testCase.error(msg, trace);
@@ -751,7 +754,6 @@
  * Registers that an exception was caught for the current test.
  */
 void _registerException(TestCase testCase, e, [trace]) {
-  trace = trace == null ? '' : trace.toString();
   String message = (e is TestFailure) ? e.message : 'Caught $e';
   if (testCase.result == null) {
     testCase.fail(message, trace);
@@ -864,85 +866,31 @@
 typedef dynamic TestFunction();
 
 /**
- * A flag that controls whether we hide unittest details in exception stacks.
+ * A flag that controls whether we hide unittest and core library details in
+ * exception stacks.
+ *
  * Useful to disable when debugging unittest or matcher customizations.
  */
 bool formatStacks = true;
 
-// Stack formatting utility. Strips extraneous content from a stack trace.
-// Stack frame lines are parsed with a regexp, which has been tested
-// in Chrome, Firefox and the VM. If a line fails to be parsed it is
-// included in the output to be conservative.
-//
-// The output stack consists of everything after the call to TestCase._run.
-// If we see an 'expect' in the frame we will prune everything above that
-// as well.
-final _frameRegExp = new RegExp(
-    r'^\s*' // Skip leading spaces.
-    r'(?:'  // Group of choices for the prefix.
-      r'(?:#\d+\s*)|' // Skip VM's #<frameNumber>.
-      r'(?:at )|'     // Skip Firefox's 'at '.
-      r'(?:))'        // Other environments have nothing here.
-    r'(.+)'           // Extract the function/method.
-    r'\s*[@\(]'       // Skip space and @ or (.
-    r'('              // This group of choices is for the source file.
-      r'(?:.+:\/\/.+\/[^:]*)|' // Handle file:// or http:// URLs.
-      r'(?:dart:[^:]*)|'  // Handle dart:<lib>.
-      r'(?:package:[^:]*)' // Handle package:<path>
-    r'):([:\d]+)[\)]?$'); // Get the line number and optional column number.
-
-String _formatStack(stack) {
-  if (!formatStacks) return "$stack";
-  var lines;
-  if (stack is StackTrace) {
-    lines = stack.toString().split('\n');
-  } else if (stack is String) {
-    lines = stack.split('\n');
+/** Returns a Trace object from a StackTrace object or a String. */
+Trace _getTrace(stack) {
+  Trace trace;
+  if (stack == null) return null;
+  if (stack is String) {
+    trace = new Trace.parse(stack);
+  } else if (stack is StackTrace) {
+    trace = new Trace.from(stack);
   } else {
-    return stack.toString();
+    throw new Exception('Invalid stack type ${stack.runtimeType} for $stack.');
   }
 
-  // Calculate the max width of first column so we can
-  // pad to align the second columns.
-  int padding = lines.fold(0, (n, line) {
-    var match = _frameRegExp.firstMatch(line);
-    if (match == null) return n;
-    return max(n, match[1].length + 1);
-  });
+  if (!formatStacks) return trace;
 
-  // We remove all entries that have a location in unittest.
-  // We strip out anything before _nextBatch too.
-  var sb = new StringBuffer();
-  for (var i = 0; i < lines.length; i++) {
-    var line = lines[i];
-    if (line == '') continue;
-    var match = _frameRegExp.firstMatch(line);
-    if (match == null) {
-      sb.write(line);
-      sb.write('\n');
-    } else {
-      var member = match[1];
-      var location = match[2];
-      var position = match[3];
-      if (member.indexOf('TestCase._runTest') >= 0) {
-        // Don't include anything after this.
-        break;
-      } else if (member.indexOf('expect') >= 0) {
-        // It looks like this was an expect() failure;
-        // drop all the frames up to here.
-        sb.clear();
-      } else {
-        sb.write(member);
-        // Pad second column to a fixed position.
-        for (var j = 0; j <= padding - member.length; j++) {
-          sb.write(' ');
-        }
-        sb.write(location);
-        sb.write(' ');
-        sb.write(position);
-        sb.write('\n');
-      }
-    }
-  }
-  return sb.toString();
+  // Format the stack trace by removing everything above TestCase._runTest,
+  // which is usually going to be irrelevant. Also fold together unittest and
+  // core library calls so only the function the user called is visible.
+  return new Trace(trace.frames.takeWhile((frame) {
+    return frame.package != 'unittest' || frame.member != 'TestCase._runTest';
+  })).terse.foldFrames((frame) => frame.package == 'unittest' || frame.isCore);
 }
diff --git a/pkg/unittest/pubspec.yaml b/pkg/unittest/pubspec.yaml
index f9051e3..ecaba6d 100644
--- a/pkg/unittest/pubspec.yaml
+++ b/pkg/unittest/pubspec.yaml
@@ -6,4 +6,4 @@
  A library for writing dart unit tests.
 dependencies:
   meta: any
-
+  stack_trace: any
diff --git a/runtime/include/dart_debugger_api.h b/runtime/include/dart_debugger_api.h
index 76f7940..36249ff 100755
--- a/runtime/include/dart_debugger_api.h
+++ b/runtime/include/dart_debugger_api.h
@@ -553,7 +553,7 @@
 
 /**
  * Returns an array containing all static field names and values of
- * the given class \cls.
+ * the given type \target.
  *
  * Requires there to be a current isolate.
  *
@@ -563,7 +563,7 @@
  * values at offset 2*n+1. Field values may also be a handle to an
  * error object if an error was encountered evaluating the field.
  */
-DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle cls);
+DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle target);
 
 
 /**
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 7016190..f14a504 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -6,9 +6,7 @@
   /* patch */ static String _objectToString(Object object) {
     return Object._toString(object);
   }
-}
 
-patch class StackTraceOnThrow {
   // TODO(11680): implement stackTrace on Error.
   /* patch */ StackTrace get stackTrace => null;
 }
@@ -175,7 +173,7 @@
   }
 }
 
-class _FiftyThreeBitOverflowError extends Error with StackTraceOnThrow {
+class _FiftyThreeBitOverflowError extends Error {
   final Object _value;
 
   _FiftyThreeBitOverflowError(this._value);
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 1cb1c74..b8b3546 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -96,52 +96,6 @@
 }
 
 
-static void FreeVMReference(Dart_WeakPersistentHandle weak_ref, void* data) {
-  Dart_PersistentHandle perm_handle =
-      reinterpret_cast<Dart_PersistentHandle>(data);
-  Dart_DeletePersistentHandle(perm_handle);
-  Dart_DeleteWeakPersistentHandle(weak_ref);
-}
-
-
-static Dart_Handle CreateVMReference(Dart_Handle handle) {
-  // Create the VMReference object.
-  Dart_Handle cls_name = NewString("VMReference");
-  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-  Dart_Handle vm_ref =  Dart_New(type, Dart_Null(), 0, NULL);
-  if (Dart_IsError(vm_ref)) {
-    return vm_ref;
-  }
-
-  // Allocate a persistent handle.
-  Dart_PersistentHandle perm_handle = Dart_NewPersistentHandle(handle);
-  ASSERT(perm_handle != NULL);
-
-  // Store the persistent handle in the VMReference.
-  intptr_t perm_handle_value = reinterpret_cast<intptr_t>(perm_handle);
-  Dart_Handle result =
-      Dart_SetNativeInstanceField(vm_ref, 0, perm_handle_value);
-  if (Dart_IsError(result)) {
-    Dart_DeletePersistentHandle(perm_handle);
-    return result;
-  }
-
-  // Create a weak reference.  We use the callback to be informed when
-  // the VMReference is collected, so we can release the persistent
-  // handle.
-  void* perm_handle_data = reinterpret_cast<void*>(perm_handle);
-  Dart_WeakPersistentHandle weak_ref =
-      Dart_NewWeakPersistentHandle(vm_ref, perm_handle_data, FreeVMReference);
-  ASSERT(weak_ref != NULL);
-
-  // Success.
-  return vm_ref;
-}
-
-
 // TODO(11742): Remove once there are no more users of the Dart_Handle-based
 // VMReferences.
 static Dart_Handle CreateMirrorReference(Dart_Handle handle) {
@@ -417,6 +371,7 @@
   }
 
   Dart_Handle args[] = {
+    CreateMirrorReference(type_var),
     type_var_name,
     owner_mirror,
     CreateLazyMirror(upper_bound),
@@ -481,6 +436,7 @@
   }
 
   Dart_Handle args[] = {
+    CreateMirrorReference(cls),
     cls_name,
     owner_mirror,
     CreateLazyMirror(referent),
@@ -496,10 +452,10 @@
                                         Dart_Handle owner_mirror);
 
 
-static Dart_Handle CreateClassMirror(Dart_Handle intf,
-                                     Dart_Handle intf_name,
-                                     Dart_Handle lib,
-                                     Dart_Handle lib_mirror) {
+static Dart_Handle CreateClassMirrorUsingApi(Dart_Handle intf,
+                                             Dart_Handle intf_name,
+                                             Dart_Handle lib,
+                                             Dart_Handle lib_mirror) {
   ASSERT(Dart_IsClass(intf));
   if (Dart_ClassIsTypedef(intf)) {
     // This class is actually a typedef.  Represent it specially in
@@ -541,7 +497,6 @@
 
   Dart_Handle args[] = {
     CreateMirrorReference(intf),
-    CreateVMReference(intf),
     Dart_Null(),  // "name"
     Dart_NewBoolean(Dart_IsClass(intf)),
     lib_mirror,
@@ -557,8 +512,8 @@
 }
 
 
-static Dart_Handle CreateMethodMirror(Dart_Handle func,
-                                      Dart_Handle owner_mirror) {
+static Dart_Handle CreateMethodMirrorUsingApi(Dart_Handle func,
+                                              Dart_Handle owner_mirror) {
   // TODO(11742): Unwrapping is needed until the whole method is converted.
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
@@ -599,7 +554,7 @@
 
 static Dart_Handle CreateVariableMirror(Dart_Handle var,
                                         Dart_Handle var_name,
-                                        Dart_Handle lib_mirror) {
+                                        Dart_Handle owner_mirror) {
   ASSERT(Dart_IsVariable(var));
   Dart_Handle cls_name = NewString("_LocalVariableMirrorImpl");
   Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
@@ -625,8 +580,9 @@
   }
 
   Dart_Handle args[] = {
+    CreateMirrorReference(var),
     var_name,
-    lib_mirror,
+    owner_mirror,
     CreateLazyMirror(var_type),
     Dart_NewBoolean(is_static),
     Dart_NewBoolean(is_final),
@@ -657,7 +613,7 @@
       return intf;
     }
     Dart_Handle intf_mirror =
-        CreateClassMirror(intf, intf_name, owner, owner_mirror);
+        CreateClassMirrorUsingApi(intf, intf_name, owner, owner_mirror);
     if (Dart_IsError(intf_mirror)) {
       return intf_mirror;
     }
@@ -701,7 +657,7 @@
       continue;
     }
 
-    Dart_Handle func_mirror = CreateMethodMirror(func, owner_mirror);
+    Dart_Handle func_mirror = CreateMethodMirrorUsingApi(func, owner_mirror);
     if (Dart_IsError(func_mirror)) {
       return func_mirror;
     }
@@ -745,7 +701,7 @@
       continue;
     }
 
-    Dart_Handle func_mirror = CreateMethodMirror(func, owner_mirror);
+    Dart_Handle func_mirror = CreateMethodMirrorUsingApi(func, owner_mirror);
     if (Dart_IsError(func_mirror)) {
       return func_mirror;
     }
@@ -833,7 +789,7 @@
 }
 
 
-static Dart_Handle CreateLibraryMirror(Dart_Handle lib) {
+static Dart_Handle CreateLibraryMirrorUsingApi(Dart_Handle lib) {
   Dart_Handle cls_name = NewString("_LocalLibraryMirrorImpl");
   Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
   if (Dart_IsError(type)) {
@@ -849,7 +805,6 @@
   }
   Dart_Handle args[] = {
     CreateMirrorReference(lib),
-    CreateVMReference(lib),
     Dart_LibraryName(lib),
     Dart_LibraryUrl(lib),
     member_map,
@@ -888,7 +843,7 @@
     if (Dart_IsError(lib)) {
       return lib;
     }
-    Dart_Handle lib_mirror = CreateLibraryMirror(lib);
+    Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib);
     if (Dart_IsError(lib_mirror)) {
       return lib_mirror;
     }
@@ -948,7 +903,6 @@
   Dart_Handle object_class = Dart_GetClass(CoreLib(), NewString("Object"));
 
   Dart_Handle args[] = {
-    CreateVMReference(Dart_Null()),
     CreateLazyMirror(object_class),
     Dart_Null(),
   };
@@ -990,12 +944,11 @@
     // TODO(turnidge): Pass the function owner here.  This will require
     // us to support functions in CreateLazyMirror.
     Dart_Handle func_mirror =
-        CreateMethodMirror(func, Dart_Null());
+        CreateMethodMirrorUsingApi(func, Dart_Null());
     if (Dart_IsError(func_mirror)) {
       return func_mirror;
     }
     Dart_Handle args[] = {
-      CreateVMReference(instance),
       CreateLazyMirror(instance_cls),
       instance,
       func_mirror,
@@ -1009,7 +962,6 @@
       return type;
     }
     Dart_Handle args[] = {
-      CreateVMReference(instance),
       CreateLazyMirror(instance_cls),
       instance,
     };
@@ -1018,6 +970,75 @@
 }
 
 
+static RawInstance* CreateClassMirror(const Class& cls,
+                                      const Instance& owner_mirror) {
+  Dart_EnterScope();
+  Isolate* isolate = Isolate::Current();
+  Dart_Handle cls_handle = Api::NewHandle(isolate, cls.raw());
+  if (Dart_IsError(cls_handle)) {
+    Dart_PropagateError(cls_handle);
+  }
+  Dart_Handle name_handle = Api::NewHandle(isolate, cls.Name());
+  if (Dart_IsError(name_handle)) {
+    Dart_PropagateError(name_handle);
+  }
+  Dart_Handle lib_handle = Api::NewHandle(isolate, cls.library());
+  if (Dart_IsError(lib_handle)) {
+    Dart_PropagateError(lib_handle);
+  }
+  Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib_handle);
+  if (Dart_IsError(lib_mirror)) {
+    Dart_PropagateError(lib_mirror);
+  }
+  // TODO(11742): At some point the handle calls will be replaced by inlined
+  // functionality.
+  Dart_Handle result =  CreateClassMirrorUsingApi(cls_handle,
+                                                  name_handle,
+                                                  lib_handle,
+                                                  lib_mirror);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
+  }
+  const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+  Dart_ExitScope();
+  return retvalue.raw();
+}
+
+
+static RawInstance* CreateLibraryMirror(const Library& lib) {
+  Dart_EnterScope();
+  Isolate* isolate = Isolate::Current();
+  Dart_Handle lib_handle = Api::NewHandle(isolate, lib.raw());
+  // TODO(11742): At some point the handle calls will be replaced by inlined
+  // functionality.
+  Dart_Handle result = CreateLibraryMirrorUsingApi(lib_handle);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
+  }
+  const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+  Dart_ExitScope();
+  return retvalue.raw();
+}
+
+
+static RawInstance* CreateMethodMirror(const Function& func,
+                                       const Instance& owner_mirror) {
+  Dart_EnterScope();
+  Isolate* isolate = Isolate::Current();
+  Dart_Handle func_handle = Api::NewHandle(isolate, func.raw());
+  Dart_Handle owner_handle = Api::NewHandle(isolate, owner_mirror.raw());
+  // TODO(11742): At some point the handle calls will be replaced by inlined
+  // functionality.
+  Dart_Handle result = CreateMethodMirrorUsingApi(func_handle, owner_handle);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
+  }
+  const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+  Dart_ExitScope();
+  return retvalue.raw();
+}
+
+
 void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalMirrorSystem)(
     Dart_NativeArguments args) {
   Dart_EnterScope();
@@ -1065,14 +1086,14 @@
   if (Dart_IsError(lib_handle)) {
     Dart_PropagateError(lib_handle);
   }
-  Dart_Handle lib_mirror = CreateLibraryMirror(lib_handle);
+  Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib_handle);
   if (Dart_IsError(lib_mirror)) {
     Dart_PropagateError(lib_mirror);
   }
-  Dart_Handle result = CreateClassMirror(cls_handle,
-                                         name_handle,
-                                         lib_handle,
-                                         lib_mirror);
+  Dart_Handle result = CreateClassMirrorUsingApi(cls_handle,
+                                                 name_handle,
+                                                 lib_handle,
+                                                 lib_mirror);
   if (Dart_IsError(result)) {
     Dart_PropagateError(result);
   }
@@ -1080,18 +1101,25 @@
   Dart_ExitScope();
 }
 
-void NATIVE_ENTRY_FUNCTION(Mirrors_metadata)(Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
 
-  Dart_Handle reflectee = UnwrapMirror(mirror);
-  Dart_Handle result = Dart_GetMetadata(reflectee);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
+DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 1) {
+  const MirrorReference& decl_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
+  const Object& decl = Object::Handle(decl_ref.referent());
+
+  Class& klass = Class::Handle();
+  if (decl.IsClass()) {
+    klass ^= decl.raw();
+  } else if (decl.IsFunction()) {
+    klass = Function::Cast(decl).origin();
+  } else if (decl.IsField()) {
+    klass = Field::Cast(decl).origin();
+  } else {
+    return Object::empty_array().raw();
   }
-  ASSERT(Dart_IsList(result));
-  Dart_SetReturnValue(args, result);
-  Dart_ExitScope();
+
+  const Library& library = Library::Handle(klass.library());
+  return library.GetMetadata(decl);
 }
 
 
@@ -1791,4 +1819,21 @@
   return func.UserVisibleName();
 }
 
+
+DEFINE_NATIVE_ENTRY(MethodMirror_owner, 1) {
+  const MirrorReference& func_ref =
+      MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
+  Function& func = Function::Handle();
+  func ^= func_ref.referent();
+  if (func.IsNonImplicitClosureFunction()) {
+    return CreateMethodMirror(Function::Handle(
+        func.parent_function()), Instance::Handle());
+  }
+  const Class& owner = Class::Handle(func.Owner());
+  if (owner.IsTopLevel()) {
+    return CreateLibraryMirror(Library::Handle(owner.library()));
+  }
+  return CreateClassMirror(owner, Instance::Handle());
+}
+
 }  // namespace dart
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 838af66..542e6e8 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -70,8 +70,8 @@
     return result;
 }
 
-List<InstanceMirror> _metadata(mirror) 
-  native 'Mirrors_metadata';
+List _metadata(reflectee)
+  native 'DeclarationMirror_metadata';
 
 // This will verify the argument types, unwrap them, and ensure we have a fixed
 // array.
@@ -164,24 +164,9 @@
   String toString() => "IsolateMirror on '$debugName'";
 }
 
-// A VMReference is used to hold a reference to a VM-internal object,
-// which can include things like libraries, classes, etc.
-class VMReference extends NativeFieldWrapperClass1 {
-}
-
-abstract class _LocalVMObjectMirrorImpl extends _LocalMirrorImpl {
-  _LocalVMObjectMirrorImpl(this._reference) {}
-
-  // For now, all VMObjects hold a VMReference.  We could consider
-  // storing the Object reference itself here if the object is a Dart
-  // language objects (except for objects of type VMReference, of
-  // course).
-  VMReference _reference;
-}
-
-abstract class _LocalObjectMirrorImpl extends _LocalVMObjectMirrorImpl
+abstract class _LocalObjectMirrorImpl extends _LocalMirrorImpl
     implements ObjectMirror {
-  _LocalObjectMirrorImpl(this._reflectee, ref) : super(ref) {}
+  _LocalObjectMirrorImpl(this._reflectee);
 
   final _reflectee; // May be a MirrorReference or an ordinary object.
 
@@ -275,9 +260,8 @@
   // TODO(ahe): This is a hack, see delegate below.
   static Function _invokeOnClosure;
 
-  _LocalInstanceMirrorImpl(ref,
-                           this._type,
-                           reflectee) : super(reflectee, ref) {}
+  _LocalInstanceMirrorImpl(this._type,
+                           reflectee) : super(reflectee) {}
 
   var _type;
   ClassMirror get type {
@@ -321,10 +305,9 @@
 
 class _LocalClosureMirrorImpl extends _LocalInstanceMirrorImpl
     implements ClosureMirror {
-  _LocalClosureMirrorImpl(ref,
-                          type,
+  _LocalClosureMirrorImpl(type,
                           reflectee,
-                          this.function) : super(ref, type, reflectee) {}
+                          this.function) : super(type, reflectee) {}
 
   final MethodMirror function;
 
@@ -404,7 +387,6 @@
 class _LocalClassMirrorImpl extends _LocalObjectMirrorImpl
     implements ClassMirror {
   _LocalClassMirrorImpl(reflectee,
-                        ref,
                         String simpleName,
                         this.isClass,
                         this._owner,
@@ -418,7 +400,7 @@
         this.members = _convertStringToSymbolMap(members),
         this.constructors = _convertStringToSymbolMap(constructors),
         this.typeVariables = _convertStringToSymbolMap(typeVariables),
-        super(reflectee, ref);
+        super(reflectee);
 
   Symbol _simpleName;
   Symbol get simpleName {
@@ -582,10 +564,11 @@
     }
   }
 
-  // get the metadata objects, convert them into InstanceMirrors using
-  // reflect() and then make them into a Dart list
-  List<InstanceMirror> get metadata => _metadata(this).map(reflect).toList();
-
+  List<InstanceMirror> get metadata {
+    // Get the metadata objects, convert them into InstanceMirrors using
+    // reflect() and then make them into a Dart list.
+    return _metadata(_reflectee).map(reflect).toList(growable:false);
+  }
 
   static _name(reflectee)
       native "ClassMirror_name";
@@ -617,12 +600,11 @@
 
 class _LocalFunctionTypeMirrorImpl extends _LocalClassMirrorImpl
     implements FunctionTypeMirror {
-  _LocalFunctionTypeMirrorImpl(ref,
+  _LocalFunctionTypeMirrorImpl(reflectee,
                                simpleName,
                                this._returnType,
                                this.parameters)
-      : super(null,
-              ref,
+      : super(reflectee,
               simpleName,
               true,
               null,
@@ -646,6 +628,17 @@
   String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
 }
 
+abstract class _LocalDeclarationMirrorImpl extends _LocalMirrorImpl
+    implements DeclarationMirror {
+    _LocalDeclarationMirrorImpl(this._reflectee);
+    final _MirrorReference _reflectee;
+
+    List<InstanceMirror> get metadata {
+      // Get the metadata objects, convert them into InstanceMirrors using
+      // reflect() and then make them into a Dart list.
+      return _metadata(_reflectee).map(reflect).toList(growable:false);
+    }
+}
 
 class _LazyTypeVariableMirror {
   _LazyTypeVariableMirror(String variableName, this._owner)
@@ -660,12 +653,14 @@
   final _LazyTypeMirror _owner;
 }
 
-class _LocalTypeVariableMirrorImpl extends _LocalMirrorImpl
+class _LocalTypeVariableMirrorImpl extends _LocalDeclarationMirrorImpl
     implements TypeVariableMirror {
-  _LocalTypeVariableMirrorImpl(String simpleName,
+  _LocalTypeVariableMirrorImpl(reflectee,
+                               String simpleName,
                                this._owner,
                                this._upperBound)
-      : this.simpleName = _s(simpleName);
+      : this.simpleName = _s(simpleName),
+        super(reflectee);
 
   final Symbol simpleName;
 
@@ -702,20 +697,23 @@
     return _upperBound;
   }
 
-  // get the metadata objects, convert them into InstanceMirrors using
-  // reflect() and then make them into a Dart list
-  List<InstanceMirror> get metadata => _metadata(this).map(reflect).toList();
+  List<InstanceMirror> get metadata {
+    throw new UnimplementedError(
+        'TypeVariableMirror.metadata is not implemented');
+  }
 
   String toString() => "TypeVariableMirror on '${_n(simpleName)}'";
 }
 
 
-class _LocalTypedefMirrorImpl extends _LocalMirrorImpl
+class _LocalTypedefMirrorImpl extends _LocalDeclarationMirrorImpl
     implements TypedefMirror {
-  _LocalTypedefMirrorImpl(String simpleName,
+  _LocalTypedefMirrorImpl(reflectee,
+                          String simpleName,
                           this._owner,
                           this._referent)
-      : this.simpleName = _s(simpleName);
+      : this.simpleName = _s(simpleName),
+        super(reflectee);
 
   final Symbol simpleName;
 
@@ -769,14 +767,13 @@
 class _LocalLibraryMirrorImpl extends _LocalObjectMirrorImpl
     implements LibraryMirror {
   _LocalLibraryMirrorImpl(reflectee,
-                          ref,
                           String simpleName,
                           String url,
                           Map<String, Mirror> members)
       : this.simpleName = _s(simpleName),
         this.members = _convertStringToSymbolMap(members),
         this.uri = Uri.parse(url),
-        super(reflectee, ref);
+        super(reflectee);
 
   final Symbol simpleName;
 
@@ -846,9 +843,11 @@
     return _variables;
   }
 
-  // get the metadata objects, convert them into InstanceMirrors using
-  // reflect() and then make them into a Dart list
-  List<InstanceMirror> get metadata => _metadata(this).map(reflect).toList();
+  List<InstanceMirror> get metadata {
+    // Get the metadata objects, convert them into InstanceMirrors using
+    // reflect() and then make them into a Dart list.
+    return _metadata(_reflectee).map(reflect).toList(growable:false);
+  }
 
   String toString() => "LibraryMirror on '${_n(simpleName)}'";
 
@@ -862,9 +861,9 @@
       native 'LibraryMirror_invokeSetter';
 }
 
-class _LocalMethodMirrorImpl extends _LocalMirrorImpl
+class _LocalMethodMirrorImpl extends _LocalDeclarationMirrorImpl
     implements MethodMirror {
-  _LocalMethodMirrorImpl(this._reflectee,
+  _LocalMethodMirrorImpl(reflectee,
                          this._owner,
                          this.parameters,
                          this._returnType,
@@ -876,9 +875,7 @@
                          this.isConstConstructor,
                          this.isGenerativeConstructor,
                          this.isRedirectingConstructor,
-                         this.isFactoryConstructor);
-
-  final _MirrorReference _reflectee;
+                         this.isFactoryConstructor) : super(reflectee);
 
   Symbol _simpleName = null;
   Symbol get simpleName {
@@ -898,6 +895,12 @@
 
   var _owner;
   DeclarationMirror get owner {
+    // For nested closures it is possible, that the mirror for the owner has not
+    // been created yet.
+    if (_owner == null) {
+      _owner = _MethodMirror_owner(_reflectee);
+    }
+    // TODO(11897): This will go away, as soon as lazy mirrors go away.
     if (_owner is! Mirror) {
       _owner = _owner.resolve(mirrors);
     }
@@ -966,27 +969,25 @@
   final bool isRedirectingConstructor;
   final bool isFactoryConstructor;
 
-  List<InstanceMirror> get metadata {
-    owner; // ensure owner is computed
-    // get the metadata objects, convert them into InstanceMirrors using
-    // reflect() and then make them into a Dart list
-    return _metadata(this).map(reflect).toList();
-  }
-
   String toString() => "MethodMirror on '${_n(simpleName)}'";
 
   static String _MethodMirror_name(reflectee)
       native "MethodMirror_name";
+
+  static dynamic _MethodMirror_owner(reflectee)
+      native "MethodMirror_owner";
 }
 
-class _LocalVariableMirrorImpl extends _LocalMirrorImpl
+class _LocalVariableMirrorImpl extends _LocalDeclarationMirrorImpl
     implements VariableMirror {
-  _LocalVariableMirrorImpl(String simpleName,
+  _LocalVariableMirrorImpl(reflectee,
+                           String simpleName,
                            this._owner,
                            this._type,
                            this.isStatic,
                            this.isFinal)
-      : this.simpleName = _s(simpleName);
+      : this.simpleName = _s(simpleName),
+        super(reflectee);
 
   final Symbol simpleName;
 
@@ -1030,20 +1031,13 @@
   final bool isStatic;
   final bool isFinal;
 
-  List<InstanceMirror> get metadata {
-    owner; // ensure owner is computed
-    // get the metadata objects, convert them into InstanceMirrors using
-    // reflect() and then make them into a Dart list
-    return _metadata(this).map(reflect).toList();
-  }
-
   String toString() => "VariableMirror on '${_n(simpleName)}'";
 }
 
 class _LocalParameterMirrorImpl extends _LocalVariableMirrorImpl
     implements ParameterMirror {
   _LocalParameterMirrorImpl(type, this.isOptional)
-      : super('<TODO:unnamed>', null, type, false, false) {}
+      : super(null, '<TODO:unnamed>', null, type, false, false) {}
 
   final bool isOptional;
 
@@ -1056,6 +1050,12 @@
     throw new UnimplementedError(
         'ParameterMirror.hasDefaultValue is not implemented');
   }
+
+  // TODO(11418): Implement.
+  List<InstanceMirror> get metadata {
+    throw new UnimplementedError(
+        'ParameterMirror.metadata is not implemented');
+  }
 }
 
 class _SpecialTypeMirrorImpl extends _LocalMirrorImpl
@@ -1129,7 +1129,13 @@
   static ClassMirror makeLocalClassMirror(Type key)
       native "Mirrors_makeLocalClassMirror";
 
+  static Expando<ClassMirror> _classMirrorCache = new Expando("ClassMirror");
   static ClassMirror reflectClass(Type key) {
-    return makeLocalClassMirror(key);
+    var classMirror = _classMirrorCache[key];
+    if (classMirror == null) {
+      classMirror = makeLocalClassMirror(key);
+      _classMirrorCache[key] = classMirror;
+    }
+    return classMirror;
   }
 }
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index f76089e..e166e10 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -327,11 +327,11 @@
   Expect.equals(const Symbol('dart.core.OutOfMemoryError'),
                 oom_cls.qualifiedName);
   Expect.isFalse(oom_cls.isPrivate);
-  Expect.equals(const Symbol('Error'), oom_cls.superclass.simpleName);
+  Expect.equals(const Symbol('Object'), oom_cls.superclass.simpleName);
   Expect.isTrue(oom_cls.defaultFactory == null);
   Expect.equals(const Symbol('dart.core'), oom_cls.owner.simpleName);
   Expect.isTrue(oom_cls.isClass);
-  Expect.isTrue(oom_cls.superinterfaces.isEmpty);
+  Expect.equals(const Symbol('Error'), oom_cls.superinterfaces[0].simpleName);
   // TODO(ahe): toString() test disabled for now as Symbols are 100% opaque.
   // Expect.equals("ClassMirror on 'OutOfMemoryError'",
   //               oom_cls.toString());
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 8faef96..5e4bfe6 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1279,6 +1279,11 @@
 }
 
 
+void Assembler::vmovq(QRegister qd, QRegister qm) {
+  EmitSIMDqqq(B21 | B8 | B4, kByte, qd, qm, qm);
+}
+
+
 void Assembler::vaddqi(OperandSize sz,
                        QRegister qd, QRegister qn, QRegister qm) {
   EmitSIMDqqq(B11, sz, qd, qn, qm);
@@ -1312,12 +1317,107 @@
 }
 
 
+void Assembler::veorq(QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B24 | B8 | B4, kByte, qd, qn, qm);
+}
+
+
+void Assembler::vorrq(QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B21 | B8 | B4, kByte, qd, qn, qm);
+}
+
+
+void Assembler::vornq(QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B21 | B20 | B8 | B4, kByte, qd, qn, qm);
+}
+
+
+void Assembler::vdup(OperandSize sz, QRegister qd, DRegister dm, int idx) {
+  ASSERT((sz != kDWord) && (sz != kSWord) && (sz != kWordPair));
+  int code = 0;
+
+  switch (sz) {
+    case kByte:
+    case kUnsignedByte: {
+      ASSERT((idx >= 0) && (idx < 8));
+      code = 1 | (idx << 1);
+      break;
+    }
+    case kHalfword:
+    case kUnsignedHalfword: {
+      ASSERT((idx >= 0) && (idx < 4));
+      code = 2 | (idx << 2);
+      break;
+    }
+    case kWord:
+    case kUnsignedWord: {
+      ASSERT((idx >= 0) && (idx < 2));
+      code = 4 | (idx << 3);
+      break;
+    }
+    default: {
+      break;
+    }
+  }
+
+  EmitSIMDddd(B24 | B23 | B11 | B10 | B6, kWordPair,
+              static_cast<DRegister>(qd * 2),
+              static_cast<DRegister>(code & 0xf),
+              dm);
+}
+
+
 void Assembler::vtbl(DRegister dd, DRegister dn, int len, DRegister dm) {
   ASSERT((len >= 1) && (len <= 4));
   EmitSIMDddd(B24 | B23 | B11 | ((len - 1) * B8), kWordPair, dd, dn, dm);
 }
 
 
+void Assembler::vceqqi(OperandSize sz,
+                      QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B24 | B11 | B4, sz, qd, qn, qm);
+}
+
+
+void Assembler::vceqqs(QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B11 | B10 | B9, kSWord, qd, qn, qm);
+}
+
+
+void Assembler::vcgeqi(OperandSize sz,
+                      QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B9 | B8 | B4, sz, qd, qn, qm);
+}
+
+
+void Assembler::vcugeqi(OperandSize sz,
+                      QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B24 | B9 | B8 | B4, sz, qd, qn, qm);
+}
+
+
+void Assembler::vcgeqs(QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B24 | B11 | B10 | B9, kSWord, qd, qn, qm);
+}
+
+
+void Assembler::vcgtqi(OperandSize sz,
+                      QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B9 | B8, sz, qd, qn, qm);
+}
+
+
+void Assembler::vcugtqi(OperandSize sz,
+                      QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B24 | B9 | B8, sz, qd, qn, qm);
+}
+
+
+void Assembler::vcgtqs(QRegister qd, QRegister qn, QRegister qm) {
+  EmitSIMDqqq(B24 | B21 | B11 | B10 | B9, kSWord, qd, qn, qm);
+}
+
+
 void Assembler::svc(uint32_t imm24, Condition cond) {
   ASSERT(cond != kNoCondition);
   ASSERT(imm24 < (1 << 24));
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index e07eab0..ece3212 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -255,10 +255,6 @@
     encoding_ = so.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift);
   }
 
-  bool Equals(const Address& other) {
-    return (encoding_ == other.encoding_) && (kind_ == other.kind_);
-  }
-
   static bool CanHoldLoadOffset(OperandSize type,
                                 int32_t offset,
                                 int32_t* offset_mask);
@@ -448,6 +444,7 @@
   void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
   void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
   void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
+  void vmovq(QRegister qd, QRegister qm);
 
   // Returns false if the immediate cannot be encoded.
   bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
@@ -486,6 +483,18 @@
   void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
   void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
   void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
+  void veorq(QRegister qd, QRegister qn, QRegister qm);
+  void vorrq(QRegister qd, QRegister qn, QRegister qm);
+  void vornq(QRegister qd, QRegister qn, QRegister qm);
+
+  void vceqqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+  void vceqqs(QRegister qd, QRegister qn, QRegister qm);
+  void vcgeqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+  void vcugeqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+  void vcgeqs(QRegister qd, QRegister qn, QRegister qm);
+  void vcgtqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+  void vcugtqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+  void vcgtqs(QRegister qd, QRegister qn, QRegister qm);
 
   void vabss(SRegister sd, SRegister sm, Condition cond = AL);
   void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
@@ -511,6 +520,10 @@
   void vcmpdz(DRegister dd, Condition cond = AL);
   void vmstat(Condition cond = AL);  // VMRS APSR_nzcv, FPSCR
 
+  // Duplicates the operand of size sz at index idx from dm to all elements of
+  // qd. This is a special case of vtbl.
+  void vdup(OperandSize sz, QRegister qd, DRegister dm, int idx);
+
   // Each byte of dm is an index into the table of bytes formed by concatenating
   // a list of 'length' registers starting with dn. The result is placed in dd.
   void vtbl(DRegister dd, DRegister dn, int length, DRegister dm);
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index d1d5b03..f44a564 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -2333,6 +2333,597 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(Veorq, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    // Q0
+    __ LoadImmediate(R0, 0xaaaaaaab);
+    __ vmovsr(S0, R0);
+    __ vmovsr(S1, R0);
+    __ vmovsr(S2, R0);
+    __ vmovsr(S3, R0);
+
+    // Q1
+    __ LoadImmediate(R0, 0x55555555);
+    __ vmovsr(S4, R0);
+    __ vmovsr(S5, R0);
+    __ vmovsr(S6, R0);
+    __ vmovsr(S7, R0);
+
+    // Q2 = -2 -2 -2 -2
+    __ veorq(Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -8);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Veorq, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vornq, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    // Q0
+    __ LoadImmediate(R0, 0xfffffff0);
+    __ vmovsr(S0, R0);
+    __ vmovsr(S1, R0);
+    __ vmovsr(S2, R0);
+    __ vmovsr(S3, R0);
+
+    // Q1
+    __ LoadImmediate(R0, 0);
+    __ vmovsr(S4, R0);
+    __ vmovsr(S5, R0);
+    __ vmovsr(S6, R0);
+    __ vmovsr(S7, R0);
+
+    // Q2 = 15 15 15 15
+    __ vornq(Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 60);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vornq, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(60, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vorrq, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    // Q0
+    __ LoadImmediate(R0, 0xaaaaaaaa);
+    __ vmovsr(S0, R0);
+    __ vmovsr(S1, R0);
+    __ vmovsr(S2, R0);
+    __ vmovsr(S3, R0);
+
+    // Q1
+    __ LoadImmediate(R0, 0x55555555);
+    __ vmovsr(S4, R0);
+    __ vmovsr(S5, R0);
+    __ vmovsr(S6, R0);
+    __ vmovsr(S7, R0);
+
+    // Q2 = -1 -1 -1 -1
+    __ vorrq(Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -4);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vorrq, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vmovq, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    // Q0
+    __ LoadSImmediate(S0, 1.0);
+    __ vmovs(S1, S0);
+    __ vmovs(S2, S0);
+    __ vmovs(S3, S0);
+
+    // Q0
+    __ LoadSImmediate(S4, -1.0);
+    __ vmovs(S5, S0);
+    __ vmovs(S6, S0);
+    __ vmovs(S7, S0);
+
+    // Q1 = Q2
+    __ vmovq(Q1, Q0);
+
+    __ vadds(S4, S4, S5);
+    __ vadds(S4, S4, S6);
+    __ vadds(S4, S4, S7);
+    __ vcvtis(S0, S4);
+    __ vmovrs(R0, S0);
+
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, 4);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vmovq, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vdupb, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadImmediate(R0, 0x00000000);
+    __ LoadImmediate(R1, 0x00ff0000);
+    __ vmovsr(S4, R0);
+    __ vmovsr(S5, R1);
+
+    // Should copy 0xff to each byte of Q0.
+    __ vdup(kByte, Q0, D2, 6);
+
+    __ vmovrs(R0, S0);
+    __ vmovrs(R1, S1);
+    __ vmovrs(R2, S2);
+    __ vmovrs(R3, S3);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -4);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vdupb, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vduph, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadImmediate(R0, 0xffff0000);
+    __ LoadImmediate(R1, 0x00000000);
+    __ vmovsr(S4, R0);
+    __ vmovsr(S5, R1);
+
+    // Should copy 0xff to each byte of Q0.
+    __ vdup(kHalfword, Q0, D2, 1);
+
+    __ vmovrs(R0, S0);
+    __ vmovrs(R1, S1);
+    __ vmovrs(R2, S2);
+    __ vmovrs(R3, S3);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -4);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vduph, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vdupw, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadImmediate(R0, 0x00000000);
+    __ LoadImmediate(R1, 0xffffffff);
+    __ vmovsr(S4, R0);
+    __ vmovsr(S5, R1);
+
+    // Should copy 0xff to each byte of Q0.
+    __ vdup(kWord, Q0, D2, 1);
+
+    __ vmovrs(R0, S0);
+    __ vmovrs(R1, S1);
+    __ vmovrs(R2, S2);
+    __ vmovrs(R3, S3);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -4);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vdupw, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vceqqi32, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(20));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(40));
+    __ vmovsr(S7, R0);
+
+    __ vceqqi(kWord, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -2);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vceqqi32, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vceqqs, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadSImmediate(S0, 1.0);
+    __ LoadSImmediate(S1, 2.0);
+    __ LoadSImmediate(S2, 3.0);
+    __ LoadSImmediate(S3, 4.0);
+    __ LoadSImmediate(S4, 1.0);
+    __ LoadSImmediate(S5, 4.0);
+    __ LoadSImmediate(S6, 3.0);
+    __ LoadSImmediate(S7, 8.0);
+
+    __ vceqqs(Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -2);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vceqqs, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcgeqi32, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S7, R0);
+
+    __ vcgeqi(kWord, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -2);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcgeqi32, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcugeqi32, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ LoadImmediate(R0, -1);
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S5, R0);
+    __ LoadImmediate(R0, -3);
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S7, R0);
+
+    __ vcugeqi(kWord, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -2);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcugeqi32, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcgeqs, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadSImmediate(S0, 1.0);
+    __ LoadSImmediate(S1, 2.0);
+    __ LoadSImmediate(S2, 3.0);
+    __ LoadSImmediate(S3, 4.0);
+    __ LoadSImmediate(S4, 1.0);
+    __ LoadSImmediate(S5, 1.0);
+    __ LoadSImmediate(S6, 3.0);
+    __ LoadSImmediate(S7, 1.0);
+
+    __ vcgeqs(Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -2);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcgeqs, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcgtqi32, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S5, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S7, R0);
+
+    __ vcgtqi(kWord, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -2);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcgtqi32, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcugtqi32, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S0, R0);
+    __ mov(R0, ShifterOperand(2));
+    __ vmovsr(S1, R0);
+    __ mov(R0, ShifterOperand(3));
+    __ vmovsr(S2, R0);
+    __ mov(R0, ShifterOperand(4));
+    __ vmovsr(S3, R0);
+    __ LoadImmediate(R0, -1);
+    __ vmovsr(S4, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S5, R0);
+    __ LoadImmediate(R0, -3);
+    __ vmovsr(S6, R0);
+    __ mov(R0, ShifterOperand(1));
+    __ vmovsr(S7, R0);
+
+    __ vcugtqi(kWord, Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -2);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcugtqi32, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcgtqs, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadSImmediate(S0, 1.0);
+    __ LoadSImmediate(S1, 2.0);
+    __ LoadSImmediate(S2, 3.0);
+    __ LoadSImmediate(S3, 4.0);
+    __ LoadSImmediate(S4, 2.0);
+    __ LoadSImmediate(S5, 1.0);
+    __ LoadSImmediate(S6, 4.0);
+    __ LoadSImmediate(S7, 1.0);
+
+    __ vcgtqs(Q2, Q1, Q0);
+
+    __ vmovrs(R0, S8);
+    __ vmovrs(R1, S9);
+    __ vmovrs(R2, S10);
+    __ vmovrs(R3, S11);
+
+    __ add(R0, R0, ShifterOperand(R1));
+    __ add(R0, R0, ShifterOperand(R2));
+    __ add(R0, R0, ShifterOperand(R3));
+    __ bx(LR);
+  } else {
+    __ LoadImmediate(R0, -2);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcgtqs, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
 // Called from assembler_test.cc.
 // LR: return address.
 // R0: context.
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index df68c46..6702842 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -81,7 +81,7 @@
     return *this;
   }
 
-  bool Equals(const Operand& other) {
+  bool Equals(const Operand& other) const {
     if (length_ != other.length_) return false;
     for (uint8_t i = 0; i < length_; i++) {
       if (encoding_[i] != other.encoding_[i]) return false;
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index bb2bb35..91fa899 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -70,10 +70,6 @@
   Register base() const { return base_; }
   int32_t offset() const { return offset_; }
 
-  bool Equals(const Address& other) {
-    return (base_ == other.base_) && (offset_ == other.offset_);
-  }
-
  private:
   Register base_;
   int32_t offset_;
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 919b1c5..4d82ceb 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -91,7 +91,7 @@
     return *this;
   }
 
-  bool Equals(const Operand& other) {
+  bool Equals(const Operand& other) const {
     if (length_ != other.length_) return false;
     if (rex_ != other.rex_) return false;
     for (uint8_t i = 0; i < length_; i++) {
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 99008cb..d7912dc 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -239,7 +239,6 @@
   V(Mirrors_makeLocalInstanceMirror, 1)                                        \
   V(Mirrors_makeLocalClassMirror, 1)                                           \
   V(Mirrors_makeLocalMirrorSystem, 0)                                          \
-  V(Mirrors_metadata, 1)                                                       \
   V(InstanceMirror_invoke, 4)                                                  \
   V(InstanceMirror_invokeGetter, 3)                                            \
   V(InstanceMirror_invokeSetter, 4)                                            \
@@ -252,7 +251,9 @@
   V(LibraryMirror_invoke, 4)                                                   \
   V(LibraryMirror_invokeGetter, 3)                                             \
   V(LibraryMirror_invokeSetter, 4)                                             \
+  V(DeclarationMirror_metadata, 1)                                             \
   V(MethodMirror_name, 1)                                                      \
+  V(MethodMirror_owner, 1)                                                     \
   V(GrowableObjectArray_allocate, 2)                                           \
   V(GrowableObjectArray_getIndexed, 2)                                         \
   V(GrowableObjectArray_setIndexed, 3)                                         \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index a996ff6..7c69615 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1257,9 +1257,9 @@
 
 
 // Copy the type parameters of the super and mixin classes to the
-// mixin application class. Change type arguments of super type to
-// refer to the respective type parameters of the mixin application
-// class.
+// mixin application class. Change type arguments of super type and of
+// interfaces to refer to the respective type parameters of the mixin
+// application class.
 void ClassFinalizer::CloneTypeParameters(const Class& mixapp_class) {
   ASSERT(mixapp_class.NumTypeParameters() == 0);
 
@@ -1318,6 +1318,7 @@
     // TODO(hausner): May need to handle BoundedType here.
     ASSERT(super_type.IsType());
     Type::Cast(super_type).set_arguments(super_type_args);
+    ASSERT(!super_type.IsFinalized());
   }
 
   // Second, clone the type parameters of the mixin class.
@@ -1328,6 +1329,8 @@
   if (num_mixin_parameters > 0) {
     const TypeArguments& mixin_params =
         TypeArguments::Handle(mixin_class.type_parameters());
+    const TypeArguments& interface_type_args = TypeArguments::Handle(
+        TypeArguments::New(num_mixin_parameters));
     for (int i = 0; i < num_mixin_parameters; i++) {
       param ^= mixin_params.TypeAt(i);
       param_name = param.name();
@@ -1347,8 +1350,21 @@
                                         param_bound,
                                         param.token_pos());
       cloned_type_params.SetTypeAt(cloned_index, cloned_param);
+      interface_type_args.SetTypeAt(i, cloned_param);
       cloned_index++;
     }
+
+    // Lastly, change the type arguments of the single interface type to
+    // refer to the cloned type parameters of the mixin application class.
+    Array& interface_types = Array::Handle(mixapp_class.interfaces());
+    ASSERT(interface_types.Length() == 1);
+    AbstractType& interface_type = AbstractType::Handle();
+    interface_type ^= interface_types.At(0);
+    ASSERT(interface_type.IsResolved());
+    // TODO(hausner): May need to handle BoundedType here.
+    ASSERT(interface_type.IsType());
+    Type::Cast(interface_type).set_arguments(interface_type_args);
+    ASSERT(!interface_type.IsFinalized());
   }
   mixapp_class.set_type_parameters(cloned_type_params);
 }
@@ -1362,7 +1378,7 @@
 
   if (FLAG_trace_class_finalization) {
     OS::Print("Applying mixin type '%s' to '%s' at pos %"Pd"\n",
-              String::Handle(mixin_cls.Name()).ToCString(),
+              String::Handle(mixin_type.Name()).ToCString(),
               cls.ToCString(),
               cls.token_pos());
   }
@@ -1383,7 +1399,8 @@
   CloneTypeParameters(cls);
 
   if (FLAG_trace_class_finalization) {
-    OS::Print("done mixin type appl %s %s extending '%s'\n",
+    OS::Print("Done applying mixin type '%s' to class %s %s extending '%s'\n",
+              String::Handle(mixin_type.Name()).ToCString(),
               String::Handle(cls.Name()).ToCString(),
               TypeArguments::Handle(cls.type_parameters()).ToCString(),
               AbstractType::Handle(cls.super_type()).ToCString());
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 8efe89c..7294784 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -905,8 +905,7 @@
 
 static RawFunction* InlineCacheMissHandler(
     const GrowableArray<const Instance*>& args,
-    const ICData& ic_data,
-    const Array& args_descriptor_array) {
+    const ICData& ic_data) {
   const Instance& receiver = *args[0];
   const Code& target_code =
       Code::Handle(ResolveCompileInstanceCallTarget(receiver, ic_data));
@@ -963,19 +962,17 @@
 // site.
 //   Arg0: Receiver object.
 //   Arg1: IC data object.
-//   Arg2: Arguments descriptor array.
 //   Returns: target function with compiled code or null.
 // Modifies the instance call to hold the updated IC data array.
-DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 3) {
+DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 2) {
   ASSERT(arguments.ArgCount() ==
       kInlineCacheMissHandlerOneArgRuntimeEntry.argument_count());
   const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
   const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
-  const Array& arg_desc_array = Array::CheckedHandle(arguments.ArgAt(2));
   GrowableArray<const Instance*> args(1);
   args.Add(&receiver);
   const Function& result =
-      Function::Handle(InlineCacheMissHandler(args, ic_data, arg_desc_array));
+      Function::Handle(InlineCacheMissHandler(args, ic_data));
   arguments.SetReturn(result);
 }
 
@@ -985,21 +982,19 @@
 //   Arg0: Receiver object.
 //   Arg1: Argument after receiver.
 //   Arg2: IC data object.
-//   Arg3: Arguments descriptor array.
 //   Returns: target function with compiled code or null.
 // Modifies the instance call to hold the updated IC data array.
-DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 4) {
+DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 3) {
   ASSERT(arguments.ArgCount() ==
       kInlineCacheMissHandlerTwoArgsRuntimeEntry.argument_count());
   const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
   const Instance& other = Instance::CheckedHandle(arguments.ArgAt(1));
   const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2));
-  const Array& arg_desc_array = Array::CheckedHandle(arguments.ArgAt(3));
   GrowableArray<const Instance*> args(2);
   args.Add(&receiver);
   args.Add(&other);
   const Function& result =
-      Function::Handle(InlineCacheMissHandler(args, ic_data, arg_desc_array));
+      Function::Handle(InlineCacheMissHandler(args, ic_data));
   arguments.SetReturn(result);
 }
 
@@ -1010,23 +1005,21 @@
 //   Arg1: Argument after receiver.
 //   Arg2: Second argument after receiver.
 //   Arg3: IC data object.
-//   Arg4: Arguments descriptor array.
 //   Returns: target function with compiled code or null.
 // Modifies the instance call to hold the updated IC data array.
-DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs, 5) {
+DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs, 4) {
   ASSERT(arguments.ArgCount() ==
       kInlineCacheMissHandlerThreeArgsRuntimeEntry.argument_count());
   const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
   const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1));
   const Instance& arg2 = Instance::CheckedHandle(arguments.ArgAt(2));
   const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(3));
-  const Array& arg_desc_array = Array::CheckedHandle(arguments.ArgAt(4));
   GrowableArray<const Instance*> args(3);
   args.Add(&receiver);
   args.Add(&arg1);
   args.Add(&arg2);
   const Function& result =
-      Function::Handle(InlineCacheMissHandler(args, ic_data, arg_desc_array));
+      Function::Handle(InlineCacheMissHandler(args, ic_data));
   arguments.SetReturn(result);
 }
 
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index a0dc2814..6cf9ce2 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -450,7 +450,9 @@
       // Attempt to sink allocations of temporary non-escaping objects to
       // the deoptimization path.
       AllocationSinking* sinking = NULL;
-      if (FLAG_allocation_sinking) {
+      if (FLAG_allocation_sinking &&
+          (flow_graph->graph_entry()->SuccessorCount()  == 1)) {
+        // TODO(fschneider): Support allocation sinking with try-catch.
         sinking = new AllocationSinking(flow_graph);
         sinking->Optimize();
       }
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 718cd5d..b3c3739 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -445,10 +445,22 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle cls_in) {
+DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle target) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  UNWRAP_AND_CHECK_PARAM(Class, cls, cls_in);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+  // For backwards compatibility we allow class objects to be passed in
+  // for now. This needs to be removed once all code that uses class
+  // objects is removed.
+  Class& cls = Class::Handle();
+  if (obj.IsType()) {
+    cls = Type::Cast(obj).type_class();
+  } else if (obj.IsClass()) {
+    cls = Class::Cast(obj).raw();
+  } else {
+    return Api::NewError("%s expects argument 'target' to be a type.",
+                         CURRENT_FUNC);
+  }
   return Api::NewHandle(isolate, isolate->debugger()->GetStaticFields(cls));
 }
 
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index d3dd288..078d0a3 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -458,8 +458,23 @@
         ASSERT(STRING_STARTS_WITH(format, "imm12_4"));
         immed16 = instr->BkptField();
       } else {
-        ASSERT(STRING_STARTS_WITH(format, "imm4_12"));
-        immed16 = instr->MovwField();
+        ASSERT(format[3] == '4');
+        if (format[5] == 'v') {
+          ASSERT(STRING_STARTS_WITH(format, "imm4_vdup"));
+          int32_t idx = -1;
+          int32_t imm4 = instr->Bits(16, 4);
+          if ((imm4 & 1) != 0) idx = imm4 >> 1;
+          else if ((imm4 & 2) != 0) idx = imm4 >> 2;
+          else if ((imm4 & 4) != 0) idx = imm4 >> 3;
+          buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
+                                     remaining_size_in_buffer(),
+                                     "%d",
+                                     idx);
+          return 9;
+        } else {
+          ASSERT(STRING_STARTS_WITH(format, "imm4_12"));
+          immed16 = instr->MovwField();
+        }
       }
       buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
                                  remaining_size_in_buffer(),
@@ -1307,6 +1322,56 @@
     } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 1) &&
                (instr->Bits(23, 2) == 2) && (instr->Bit(21) == 0)) {
       Format(instr, "vmulqs 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+               (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
+      Format(instr, "veorq 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+               (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 0)) {
+      Format(instr, "vornq 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+               (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
+      if (instr->QmField() == instr->QnField()) {
+        Format(instr, "vmovq 'qd, 'qm");
+      } else {
+        Format(instr, "vorrq 'qd, 'qm");
+      }
+    } else if ((instr->Bits(8, 4) == 12) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
+               (instr->Bit(7) == 0)) {
+      int32_t imm4 = instr->Bits(16, 4);
+      if (imm4 & 1) {
+        Format(instr, "vdupb 'qd, 'dm['imm4_vdup]");
+      } else if (imm4 & 2) {
+        Format(instr, "vduph 'qd, 'dm['imm4_vdup]");
+      } else if (imm4 & 4) {
+        Format(instr, "vdupw 'qd, 'dm['imm4_vdup]");
+      } else {
+        Unknown(instr);
+      }
+    } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 2)) {
+      Format(instr, "vceqq'sz 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
+      Format(instr, "vceqqs 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 0)) {
+      Format(instr, "vcgeq'sz 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 2)) {
+      Format(instr, "vcugeq'sz 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
+      Format(instr, "vcgeqs 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
+               (instr->Bits(23, 2) == 0)) {
+      Format(instr, "vcgtq'sz 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
+               (instr->Bits(23, 2) == 2)) {
+      Format(instr, "vcugtq'sz 'qd, 'qn, 'qm");
+    } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 2)) {
+      Format(instr, "vcgtqs 'qd, 'qn, 'qm");
     } else {
       Unknown(instr);
     }
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 55fc965..8ee48ca 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -95,6 +95,8 @@
   void StoreObject(const Address& dst, const Object& obj);
   void Exchange(Register reg, const Address& mem);
   void Exchange(const Address& mem1, const Address& mem2);
+  void Exchange(Register reg, intptr_t stack_offset);
+  void Exchange(intptr_t stack_offset1, intptr_t stack_offset2);
 
   FlowGraphCompiler* compiler_;
 
@@ -467,7 +469,7 @@
 
   void EmitFrameEntry();
 
-  void EmitTrySyncMove(Address dest, Location loc, bool* push_emitted);
+  void EmitTrySyncMove(intptr_t dest_offset, Location loc, bool* push_emitted);
 
   void AddStaticCallTarget(const Function& function);
 
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 82deb39..01b166f 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -735,10 +735,7 @@
 }
 
 
-// TODO(regis): Pass an offset instead of an Address to avoid addressing
-// mode restrictions and remove Operand::Equals() on IA32/X64 and
-// Address::Equals() on ARM/MIPS.
-void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset,
                                         Location loc,
                                         bool* push_emitted) {
   if (loc.IsConstant()) {
@@ -747,23 +744,23 @@
       *push_emitted = true;
     }
     __ LoadObject(R0, loc.constant());
-    __ str(R0, dest);
+    __ StoreToOffset(kWord, R0, FP, dest_offset);
   } else if (loc.IsRegister()) {
     if (*push_emitted && (loc.reg() == R0)) {
       __ ldr(R0, Address(SP, 0));
-      __ str(R0, dest);
+      __ StoreToOffset(kWord, R0, FP, dest_offset);
     } else {
-      __ str(loc.reg(), dest);
+      __ StoreToOffset(kWord, loc.reg(), FP, dest_offset);
     }
   } else {
-    Address src = loc.ToStackSlotAddress();
-    if (!src.Equals(dest)) {
+    const intptr_t src_offset = loc.ToStackSlotOffset();
+    if (src_offset != dest_offset) {
       if (!*push_emitted) {
         __ Push(R0);
         *push_emitted = true;
       }
-      __ ldr(R0, src);
-      __ str(R0, dest);
+      __ LoadFromOffset(kWord, R0, FP, src_offset);
+      __ StoreToOffset(kWord, R0, FP, dest_offset);
     }
   }
 }
@@ -784,8 +781,7 @@
   for (; i < num_non_copied_params; ++i) {
     if ((*idefs)[i]->IsConstant()) continue;  // Common constants
     Location loc = env->LocationAt(i);
-    Address dest(FP, (param_base - i) * kWordSize);
-    EmitTrySyncMove(dest, loc, &push_emitted);
+    EmitTrySyncMove((param_base - i) * kWordSize, loc, &push_emitted);
   }
 
   // Process locals. Skip exception_var and stacktrace_var.
@@ -797,8 +793,7 @@
     if (i == ex_idx || i == st_idx) continue;
     if ((*idefs)[i]->IsConstant()) continue;
     Location loc = env->LocationAt(i);
-    Address dest(FP, (local_base - i) * kWordSize);
-    EmitTrySyncMove(dest, loc, &push_emitted);
+    EmitTrySyncMove((local_base - i) * kWordSize, loc, &push_emitted);
     // Update safepoint bitmap to indicate that the target location
     // now contains a pointer.
     instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
@@ -1703,41 +1698,69 @@
       __ mov(destination.reg(), ShifterOperand(source.reg()));
     } else {
       ASSERT(destination.IsStackSlot());
-      __ str(source.reg(), destination.ToStackSlotAddress());
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ StoreToOffset(kWord, source.reg(), FP, dest_offset);
     }
   } else if (source.IsStackSlot()) {
     if (destination.IsRegister()) {
-      __ ldr(destination.reg(), source.ToStackSlotAddress());
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      __ LoadFromOffset(kWord, destination.reg(), FP, source_offset);
     } else {
       ASSERT(destination.IsStackSlot());
-      MoveMemoryToMemory(destination.ToStackSlotAddress(),
-                         source.ToStackSlotAddress());
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ LoadFromOffset(kWord, TMP, FP, source_offset);
+      __ StoreToOffset(kWord, TMP, FP, dest_offset);
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
-      DRegister dst = EvenDRegisterOf(destination.fpu_reg());
-      DRegister src = EvenDRegisterOf(source.fpu_reg());
-      __ vmovd(dst, src);
+      __ vmovq(destination.fpu_reg(), source.fpu_reg());
     } else {
       if (destination.IsDoubleStackSlot()) {
+        const intptr_t dest_offset = destination.ToStackSlotOffset();
         DRegister src = EvenDRegisterOf(source.fpu_reg());
-        __ vstrd(src, destination.ToStackSlotAddress());
+        __ StoreDToOffset(src, FP, dest_offset);
       } else {
         ASSERT(destination.IsQuadStackSlot());
-        UNIMPLEMENTED();
+        const intptr_t dest_offset = destination.ToStackSlotOffset();
+        DRegister dsrc0 = EvenDRegisterOf(source.fpu_reg());
+        DRegister dsrc1 = OddDRegisterOf(source.fpu_reg());
+        // TODO(zra): Write and use {Load,Store}Q{From,To}Offset(), which can
+        // use a single vld1/vst1 instruction.
+        __ StoreDToOffset(dsrc0, FP, dest_offset);
+        __ StoreDToOffset(dsrc1, FP, dest_offset + 2*kWordSize);
       }
     }
   } else if (source.IsDoubleStackSlot()) {
     if (destination.IsFpuRegister()) {
+      const intptr_t dest_offset = source.ToStackSlotOffset();
       DRegister dst = EvenDRegisterOf(destination.fpu_reg());
-      __ vldrd(dst, source.ToStackSlotAddress());
+      __ LoadDFromOffset(dst, FP, dest_offset);
     } else {
       ASSERT(destination.IsDoubleStackSlot());
-      __ vldrd(DTMP, source.ToStackSlotAddress());
-      __ vstrd(DTMP, destination.ToStackSlotAddress());
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ LoadDFromOffset(DTMP, FP, source_offset);
+      __ StoreDToOffset(DTMP, FP, dest_offset);
     }
   } else if (source.IsQuadStackSlot()) {
-    UNIMPLEMENTED();
+    if (destination.IsFpuRegister()) {
+      const intptr_t dest_offset = source.ToStackSlotOffset();
+      DRegister dst0 = EvenDRegisterOf(destination.fpu_reg());
+      DRegister dst1 = OddDRegisterOf(destination.fpu_reg());
+      __ LoadDFromOffset(dst0, FP, dest_offset);
+      __ LoadDFromOffset(dst1, FP, dest_offset + 2*kWordSize);
+    } else {
+      ASSERT(destination.IsQuadStackSlot());
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      DRegister dtmp0 = DTMP;
+      DRegister dtmp1 = OddDRegisterOf(QTMP);
+      __ LoadDFromOffset(dtmp0, FP, source_offset);
+      __ LoadDFromOffset(dtmp1, FP, source_offset + 2*kWordSize);
+      __ StoreDToOffset(dtmp0, FP, dest_offset);
+      __ StoreDToOffset(dtmp1, FP, dest_offset + 2*kWordSize);
+    }
   } else {
     ASSERT(source.IsConstant());
     if (destination.IsRegister()) {
@@ -1745,7 +1768,9 @@
       __ LoadObject(destination.reg(), constant);
     } else {
       ASSERT(destination.IsStackSlot());
-      StoreObject(destination.ToStackSlotAddress(), source.constant());
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ LoadObject(TMP, source.constant());
+      __ StoreToOffset(kWord, TMP, FP, dest_offset);
     }
   }
 
@@ -1765,11 +1790,11 @@
     __ mov(source.reg(), ShifterOperand(destination.reg()));
     __ mov(destination.reg(), ShifterOperand(IP));
   } else if (source.IsRegister() && destination.IsStackSlot()) {
-    Exchange(source.reg(), destination.ToStackSlotAddress());
+    Exchange(source.reg(), destination.ToStackSlotOffset());
   } else if (source.IsStackSlot() && destination.IsRegister()) {
-    Exchange(destination.reg(), source.ToStackSlotAddress());
+    Exchange(destination.reg(), source.ToStackSlotOffset());
   } else if (source.IsStackSlot() && destination.IsStackSlot()) {
-    Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress());
+    Exchange(source.ToStackSlotOffset(), destination.ToStackSlotOffset());
   } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
     DRegister dst = EvenDRegisterOf(destination.fpu_reg());
     DRegister src = EvenDRegisterOf(source.fpu_reg());
@@ -1786,27 +1811,27 @@
     QRegister qreg = source.IsFpuRegister() ? source.fpu_reg()
                                             : destination.fpu_reg();
     DRegister reg = EvenDRegisterOf(qreg);
-    const Address& slot_address = source.IsFpuRegister()
-        ? destination.ToStackSlotAddress()
-        : source.ToStackSlotAddress();
+    const intptr_t slot_offset = source.IsFpuRegister()
+        ? destination.ToStackSlotOffset()
+        : source.ToStackSlotOffset();
 
     if (double_width) {
-      __ vldrd(DTMP, slot_address);
-      __ vstrd(reg, slot_address);
+      __ LoadDFromOffset(DTMP, FP, slot_offset);
+      __ StoreDToOffset(reg, FP, slot_offset);
       __ vmovd(reg, DTMP);
     } else {
       UNIMPLEMENTED();
     }
   } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
-    const Address& source_slot_address = source.ToStackSlotAddress();
-    const Address& destination_slot_address = destination.ToStackSlotAddress();
+    const intptr_t source_offset = source.ToStackSlotOffset();
+    const intptr_t dest_offset = destination.ToStackSlotOffset();
 
     ScratchFpuRegisterScope ensure_scratch(this, QTMP);
     DRegister scratch = EvenDRegisterOf(ensure_scratch.reg());
-    __ vldrd(DTMP, source_slot_address);
-    __ vldrd(scratch, destination_slot_address);
-    __ vstrd(DTMP, destination_slot_address);
-    __ vstrd(scratch, source_slot_address);
+    __ LoadDFromOffset(DTMP, FP, source_offset);
+    __ LoadDFromOffset(scratch, FP, dest_offset);
+    __ StoreDToOffset(DTMP, FP, dest_offset);
+    __ StoreDToOffset(scratch, FP, source_offset);
   } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
     UNIMPLEMENTED();
   } else {
@@ -1844,20 +1869,34 @@
 }
 
 
+// Do not call or implement this function. Instead, use the form below that
+// uses an offset from the frame pointer instead of an Address.
 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
-  ASSERT(reg != IP);
-  __ mov(IP, ShifterOperand(reg));
-  __ ldr(reg, mem);
-  __ str(IP, mem);
+  UNREACHABLE();
 }
 
 
+// Do not call or implement this function. Instead, use the form below that
+// uses offsets from the frame pointer instead of Addresses.
 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
+  UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
+  __ mov(TMP, ShifterOperand(reg));
+  __ LoadFromOffset(kWord, reg, FP, stack_offset);
+  __ StoreToOffset(kWord, TMP, FP, stack_offset);
+}
+
+
+void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
+                                    intptr_t stack_offset2) {
   ScratchRegisterScope ensure_scratch(this, IP);
-  __ ldr(ensure_scratch.reg(), mem1);
-  __ ldr(IP, mem2);
-  __ str(ensure_scratch.reg(), mem2);
-  __ str(IP, mem1);
+  __ LoadFromOffset(kWord, ensure_scratch.reg(), FP, stack_offset1);
+  __ LoadFromOffset(kWord, TMP, FP, stack_offset2);
+  __ StoreToOffset(kWord, ensure_scratch.reg(), FP, stack_offset2);
+  __ StoreToOffset(kWord, TMP, FP, stack_offset1);
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index eab9bcf..6683c36 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -756,9 +756,10 @@
 }
 
 
-void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset,
                                         Location loc,
                                         bool* push_emitted) {
+  const Address dest(EBP, dest_offset);
   if (loc.IsConstant()) {
     if (!*push_emitted) {
       __ pushl(EAX);
@@ -802,8 +803,7 @@
   for (; i < num_non_copied_params; ++i) {
     if ((*idefs)[i]->IsConstant()) continue;  // Common constants
     Location loc = env->LocationAt(i);
-    Address dest(EBP, (param_base - i) * kWordSize);
-    EmitTrySyncMove(dest, loc, &push_emitted);
+    EmitTrySyncMove((param_base - i) * kWordSize, loc, &push_emitted);
   }
 
   // Process locals. Skip exception_var and stacktrace_var.
@@ -815,8 +815,7 @@
     if (i == ex_idx || i == st_idx) continue;
     if ((*idefs)[i]->IsConstant()) continue;
     Location loc = env->LocationAt(i);
-    Address dest(EBP, (local_base - i) * kWordSize);
-    EmitTrySyncMove(dest, loc, &push_emitted);
+    EmitTrySyncMove((local_base - i) * kWordSize, loc, &push_emitted);
     // Update safepoint bitmap to indicate that the target location
     // now contains a pointer.
     instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
@@ -1901,6 +1900,17 @@
 }
 
 
+void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
+  UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
+                                    intptr_t stack_offset2) {
+  UNREACHABLE();
+}
+
+
 void ParallelMoveResolver::SpillScratch(Register reg) {
   __ pushl(reg);
 }
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 114c060..2a5f44f 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -762,7 +762,7 @@
 // TODO(regis): Pass an offset instead of an Address to avoid addressing
 // mode restrictions and remove Operand::Equals() on IA32/X64 and
 // Address::Equals() on ARM/MIPS.
-void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset,
                                         Location loc,
                                         bool* push_emitted) {
   if (loc.IsConstant()) {
@@ -771,23 +771,23 @@
       *push_emitted = true;
     }
     __ LoadObject(T0, loc.constant());
-    __ sw(T0, dest);
+    __ StoreToOffset(T0, FP, dest_offset);
   } else if (loc.IsRegister()) {
     if (*push_emitted && loc.reg() == T0) {
       __ lw(T0, Address(SP, 0));
-      __ sw(T0, dest);
+      __ StoreToOffset(T0, FP, dest_offset);
     } else {
-      __ sw(loc.reg(), dest);
+      __ StoreToOffset(loc.reg(), FP, dest_offset);
     }
   } else {
-    Address src = loc.ToStackSlotAddress();
-    if (!src.Equals(dest)) {
+    const intptr_t src_offset = loc.ToStackSlotOffset();
+    if (src_offset != dest_offset) {
       if (!*push_emitted) {
         __ Push(T0);
         *push_emitted = true;
       }
-      __ lw(T0, src);
-      __ sw(T0, dest);
+      __ LoadFromOffset(T0, FP, src_offset);
+      __ StoreToOffset(T0, FP, dest_offset);
     }
   }
 }
@@ -808,8 +808,7 @@
   for (; i < num_non_copied_params; ++i) {
     if ((*idefs)[i]->IsConstant()) continue;  // Common constants
     Location loc = env->LocationAt(i);
-    Address dest(FP, (param_base - i) * kWordSize);
-    EmitTrySyncMove(dest, loc, &push_emitted);
+    EmitTrySyncMove((param_base - i) * kWordSize, loc, &push_emitted);
   }
 
   // Process locals. Skip exception_var and stacktrace_var.
@@ -821,8 +820,7 @@
     if (i == ex_idx || i == st_idx) continue;
     if ((*idefs)[i]->IsConstant()) continue;
     Location loc = env->LocationAt(i);
-    Address dest(FP, (local_base - i) * kWordSize);
-    EmitTrySyncMove(dest, loc, &push_emitted);
+    EmitTrySyncMove((local_base - i) * kWordSize, loc, &push_emitted);
     // Update safepoint bitmap to indicate that the target location
     // now contains a pointer.
     instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
@@ -1807,34 +1805,40 @@
 
 
 void ParallelMoveResolver::EmitMove(int index) {
-  __ TraceSimMsg("ParallelMoveResolver::EmitMove");
   MoveOperands* move = moves_[index];
   const Location source = move->src();
   const Location destination = move->dest();
+  __ TraceSimMsg("ParallelMoveResolver::EmitMove");
 
   if (source.IsRegister()) {
     if (destination.IsRegister()) {
       __ mov(destination.reg(), source.reg());
     } else {
       ASSERT(destination.IsStackSlot());
-      __ sw(source.reg(), destination.ToStackSlotAddress());
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ StoreToOffset(source.reg(), FP, dest_offset);
     }
   } else if (source.IsStackSlot()) {
     if (destination.IsRegister()) {
-      __ lw(destination.reg(), source.ToStackSlotAddress());
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      __ LoadFromOffset(destination.reg(), FP, source_offset);
     } else {
       ASSERT(destination.IsStackSlot());
-      MoveMemoryToMemory(destination.ToStackSlotAddress(),
-                         source.ToStackSlotAddress());
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ LoadFromOffset(TMP, FP, source_offset);
+      __ StoreToOffset(TMP, FP, dest_offset);
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
-      __ movd(destination.fpu_reg(), source.fpu_reg());
+      DRegister dst = destination.fpu_reg();
+      DRegister src = source.fpu_reg();
+      __ movd(dst, src);
     } else {
       if (destination.IsDoubleStackSlot()) {
-        const Address& addr = destination.ToStackSlotAddress();
-        int32_t offset = addr.offset();
-        __ StoreDToOffset(source.fpu_reg(), FP, offset);
+        const intptr_t dest_offset = destination.ToStackSlotOffset();
+        DRegister src = source.fpu_reg();
+        __ StoreDToOffset(src, FP, dest_offset);
       } else {
         ASSERT(destination.IsQuadStackSlot());
         UNIMPLEMENTED();
@@ -1842,18 +1846,15 @@
     }
   } else if (source.IsDoubleStackSlot()) {
     if (destination.IsFpuRegister()) {
-      const Address &addr = source.ToStackSlotAddress();
-      const Register base = addr.base();
-      const int32_t offset = addr.offset();
-      __ LoadDFromOffset(destination.fpu_reg(), base, offset);
+      const intptr_t dest_offset = source.ToStackSlotOffset();
+      DRegister dst = destination.fpu_reg();
+      __ LoadDFromOffset(dst, FP, dest_offset);
     } else {
       ASSERT(destination.IsDoubleStackSlot());
-      const Address& saddr = source.ToStackSlotAddress();
-      const Address& daddr = destination.ToStackSlotAddress();
-      int32_t soffset = saddr.offset();
-      int32_t doffset = daddr.offset();
-      __ LoadDFromOffset(FpuTMP, FP, soffset);
-      __ StoreDToOffset(FpuTMP, FP, doffset);
+      const intptr_t source_offset = source.ToStackSlotOffset();
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ LoadDFromOffset(DTMP, FP, source_offset);
+      __ StoreDToOffset(DTMP, FP, dest_offset);
     }
   } else if (source.IsQuadStackSlot()) {
     UNIMPLEMENTED();
@@ -1864,7 +1865,9 @@
       __ LoadObject(destination.reg(), constant);
     } else {
       ASSERT(destination.IsStackSlot());
-      StoreObject(destination.ToStackSlotAddress(), source.constant());
+      const intptr_t dest_offset = destination.ToStackSlotOffset();
+      __ LoadObject(TMP, source.constant());
+      __ StoreToOffset(TMP, FP, dest_offset);
     }
   }
 
@@ -1873,27 +1876,28 @@
 
 
 void ParallelMoveResolver::EmitSwap(int index) {
-  __ TraceSimMsg("ParallelMoveResolver::EmitSwap");
   MoveOperands* move = moves_[index];
   const Location source = move->src();
   const Location destination = move->dest();
 
   if (source.IsRegister() && destination.IsRegister()) {
-    ASSERT(source.reg() != TMP1);
-    ASSERT(destination.reg() != TMP1);
-    __ mov(TMP1, source.reg());
+    ASSERT(source.reg() != TMP);
+    ASSERT(destination.reg() != TMP);
+    __ mov(TMP, source.reg());
     __ mov(source.reg(), destination.reg());
-    __ mov(destination.reg(), TMP1);
+    __ mov(destination.reg(), TMP);
   } else if (source.IsRegister() && destination.IsStackSlot()) {
-    Exchange(source.reg(), destination.ToStackSlotAddress());
+    Exchange(source.reg(), destination.ToStackSlotOffset());
   } else if (source.IsStackSlot() && destination.IsRegister()) {
-    Exchange(destination.reg(), source.ToStackSlotAddress());
+    Exchange(destination.reg(), source.ToStackSlotOffset());
   } else if (source.IsStackSlot() && destination.IsStackSlot()) {
-    Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress());
+    Exchange(source.ToStackSlotOffset(), destination.ToStackSlotOffset());
   } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
-    __ movd(FpuTMP, source.fpu_reg());
-    __ movd(source.fpu_reg(), destination.fpu_reg());
-    __ movd(destination.fpu_reg(), FpuTMP);
+    DRegister dst = destination.fpu_reg();
+    DRegister src = source.fpu_reg();
+    __ movd(DTMP, src);
+    __ movd(src, dst);
+    __ movd(dst, DTMP);
   } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
     ASSERT(destination.IsDoubleStackSlot() ||
            destination.IsQuadStackSlot() ||
@@ -1903,32 +1907,27 @@
                         source.IsDoubleStackSlot();
     DRegister reg = source.IsFpuRegister() ? source.fpu_reg()
                                            : destination.fpu_reg();
-    const Address& slot_address = source.IsFpuRegister()
-        ? destination.ToStackSlotAddress()
-        : source.ToStackSlotAddress();
+    const intptr_t slot_offset = source.IsFpuRegister()
+        ? destination.ToStackSlotOffset()
+        : source.ToStackSlotOffset();
 
     if (double_width) {
-      const Register base = slot_address.base();
-      const int32_t offset = slot_address.offset();
-      __ LoadDFromOffset(FpuTMP, base, offset);
-      __ StoreDToOffset(reg, base, offset);
-      __ movd(reg, FpuTMP);
+      __ LoadDFromOffset(DTMP, FP, slot_offset);
+      __ StoreDToOffset(reg, FP, slot_offset);
+      __ movd(reg, DTMP);
     } else {
       UNIMPLEMENTED();
     }
   } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
-    const Address& source_slot_address = source.ToStackSlotAddress();
-    const Address& destination_slot_address = destination.ToStackSlotAddress();
-    const Register sbase = source_slot_address.base();
-    const int32_t soffset = source_slot_address.offset();
-    const Register dbase = destination_slot_address.base();
-    const int32_t doffset = destination_slot_address.offset();
+    const intptr_t source_offset = source.ToStackSlotOffset();
+    const intptr_t dest_offset = destination.ToStackSlotOffset();
 
-    ScratchFpuRegisterScope ensure_scratch(this, FpuTMP);
-    __ LoadDFromOffset(FpuTMP, sbase, soffset);
-    __ LoadDFromOffset(ensure_scratch.reg(), dbase, doffset);
-    __ StoreDToOffset(FpuTMP, dbase, doffset);
-    __ StoreDToOffset(ensure_scratch.reg(), sbase, soffset);
+    ScratchFpuRegisterScope ensure_scratch(this, DTMP);
+    DRegister scratch = ensure_scratch.reg();
+    __ LoadDFromOffset(DTMP, FP, source_offset);
+    __ LoadDFromOffset(scratch, FP, dest_offset);
+    __ StoreDToOffset(DTMP, FP, dest_offset);
+    __ StoreDToOffset(scratch, FP, source_offset);
   } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
     UNIMPLEMENTED();
   } else {
@@ -1968,22 +1967,34 @@
 }
 
 
+// Do not call or implement this function. Instead, use the form below that
+// uses an offset from the frame pointer instead of an Address.
 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
-  __ TraceSimMsg("ParallelMoveResolver::Exchange ra");
-  ASSERT(reg != TMP1);
-  __ mov(TMP1, reg);
-  __ lw(reg, mem);
-  __ sw(TMP1, mem);
+  UNREACHABLE();
 }
 
 
+// Do not call or implement this function. Instead, use the form below that
+// uses offsets from the frame pointer instead of Addresses.
 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
-  __ TraceSimMsg("ParallelMoveResolver::Exchange aa");
-  ScratchRegisterScope ensure_scratch(this, TMP1);
-  __ lw(ensure_scratch.reg(), mem1);
-  __ lw(TMP1, mem2);
-  __ sw(ensure_scratch.reg(), mem2);
-  __ sw(TMP1, mem1);
+  UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
+  __ mov(TMP, reg);
+  __ LoadFromOffset(reg, FP, stack_offset);
+  __ StoreToOffset(TMP, FP, stack_offset);
+}
+
+
+void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
+                                    intptr_t stack_offset2) {
+  ScratchRegisterScope ensure_scratch(this, TMP);
+  __ LoadFromOffset(ensure_scratch.reg(), FP, stack_offset1);
+  __ LoadFromOffset(TMP, FP, stack_offset2);
+  __ StoreToOffset(ensure_scratch.reg(), FP, stack_offset2);
+  __ StoreToOffset(TMP, FP, stack_offset1);
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index b2f730c..22e25a9 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -749,9 +749,10 @@
 }
 
 
-void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset,
                                         Location loc,
                                         bool* push_emitted) {
+  const Address dest(RBP, dest_offset);
   if (loc.IsConstant()) {
     if (!*push_emitted) {
       __ pushq(RAX);
@@ -794,8 +795,7 @@
   for (; i < num_non_copied_params; ++i) {
     if ((*idefs)[i]->IsConstant()) continue;  // Common constants
     Location loc = env->LocationAt(i);
-    Address dest(RBP, (param_base - i) * kWordSize);
-    EmitTrySyncMove(dest, loc, &push_emitted);
+    EmitTrySyncMove((param_base - i) * kWordSize, loc, &push_emitted);
   }
 
   // Process locals. Skip exception_var and stacktrace_var.
@@ -807,8 +807,7 @@
     if (i == ex_idx || i == st_idx) continue;
     if ((*idefs)[i]->IsConstant()) continue;
     Location loc = env->LocationAt(i);
-    Address dest(RBP, (local_base - i) * kWordSize);
-    EmitTrySyncMove(dest, loc, &push_emitted);
+    EmitTrySyncMove((local_base - i) * kWordSize, loc, &push_emitted);
     // Update safepoint bitmap to indicate that the target location
     // now contains a pointer.
     instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
@@ -1880,6 +1879,17 @@
 }
 
 
+void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
+  UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
+                                    intptr_t stack_offset2) {
+  UNREACHABLE();
+}
+
+
 void ParallelMoveResolver::SpillScratch(Register reg) {
   __ pushq(reg);
 }
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index ae18cca..87fba15 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -56,7 +56,8 @@
       __ PushObject(value.constant());
     } else {
       ASSERT(value.IsStackSlot());
-      __ ldr(IP, value.ToStackSlotAddress());
+      const intptr_t value_offset = value.ToStackSlotOffset();
+      __ LoadFromOffset(kWord, IP, FP, value_offset);
       __ Push(IP);
     }
   }
@@ -1203,7 +1204,9 @@
   if ((representation() == kUnboxedDouble) ||
       (representation() == kUnboxedMint) ||
       (representation() == kUnboxedFloat32x4)) {
-    DRegister result = EvenDRegisterOf(locs()->out().fpu_reg());
+    QRegister result = locs()->out().fpu_reg();
+    DRegister dresult0 = EvenDRegisterOf(result);
+    DRegister dresult1 = OddDRegisterOf(result);
     switch (class_id()) {
       case kTypedDataInt32ArrayCid:
         UNIMPLEMENTED();
@@ -1217,16 +1220,18 @@
         __ add(index.reg(), index.reg(), ShifterOperand(array));
         element_address = Address(index.reg(), 0);
         __ vldrs(STMP, element_address);
-        __ vcvtds(result, STMP);
+        __ vcvtds(dresult0, STMP);
         break;
       case kTypedDataFloat64ArrayCid:
         // vldrd does not support indexed addressing.
         __ add(index.reg(), index.reg(), ShifterOperand(array));
         element_address = Address(index.reg(), 0);
-        __ vldrd(result, element_address);
+        __ vldrd(dresult0, element_address);
         break;
       case kTypedDataFloat32x4ArrayCid:
-        UNIMPLEMENTED();
+        __ add(index.reg(), index.reg(), ShifterOperand(array));
+        __ LoadDFromOffset(dresult0, index.reg(), 0);
+        __ LoadDFromOffset(dresult1, index.reg(), 2*kWordSize);
         break;
     }
     return;
@@ -1485,9 +1490,15 @@
       __ StoreDToOffset(in2, index.reg(), 0);
       break;
     }
-    case kTypedDataFloat32x4ArrayCid:
-      UNIMPLEMENTED();
+    case kTypedDataFloat32x4ArrayCid: {
+      QRegister in = locs()->in(2).fpu_reg();
+      DRegister din0 = EvenDRegisterOf(in);
+      DRegister din1 = OddDRegisterOf(in);
+      __ add(index.reg(), index.reg(), ShifterOperand(array));
+      __ StoreDToOffset(din0, index.reg(), 0);
+      __ StoreDToOffset(din1, index.reg(), 2*kWordSize);
       break;
+    }
     default:
       UNREACHABLE();
   }
@@ -2668,46 +2679,211 @@
 
 
 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs,
+                          kNumTemps,
+                          LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
+class BoxFloat32x4SlowPath : public SlowPathCode {
+ public:
+  explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxFloat32x4SlowPath");
+    __ Bind(entry_label());
+    const Class& float32x4_class = compiler->float32x4_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class));
+    const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ mov(locs->out().reg(), ShifterOperand(R0));
+    compiler->RestoreLiveRegisters(locs);
+
+    __ b(exit_label());
+  }
+
+ private:
+  BoxFloat32x4Instr* instruction_;
+};
+
+
 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
+  compiler->AddSlowPathCode(slow_path);
+
+  Register out_reg = locs()->out().reg();
+  QRegister value = locs()->in(0).fpu_reg();
+  DRegister value_even = EvenDRegisterOf(value);
+  DRegister value_odd = OddDRegisterOf(value);
+
+  __ TryAllocate(compiler->float32x4_class(),
+                 slow_path->entry_label(),
+                 out_reg);
+  __ Bind(slow_path->exit_label());
+
+  __ StoreDToOffset(value_even, out_reg,
+      Float32x4::value_offset() - kHeapObjectTag);
+  __ StoreDToOffset(value_odd, out_reg,
+      Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
 }
 
 
 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  if (kNumTemps > 0) {
+    ASSERT(kNumTemps == 1);
+    summary->set_temp(0, Location::RequiresRegister());
+  }
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const Register value = locs()->in(0).reg();
+  const QRegister result = locs()->out().fpu_reg();
+
+  if (value_cid != kFloat32x4Cid) {
+    const Register temp = locs()->temp(0).reg();
+    Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
+    __ tst(value, ShifterOperand(kSmiTagMask));
+    __ b(deopt, EQ);
+    __ CompareClassId(value, kFloat32x4Cid, temp);
+    __ b(deopt, NE);
+  }
+
+  const DRegister result_even = EvenDRegisterOf(result);
+  const DRegister result_odd = OddDRegisterOf(result);
+  __ LoadDFromOffset(result_even, value,
+      Float32x4::value_offset() - kHeapObjectTag);
+  __ LoadDFromOffset(result_odd, value,
+      Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
 }
 
 
 LocationSummary* BoxUint32x4Instr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs,
+                          kNumTemps,
+                          LocationSummary::kCallOnSlowPath);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresRegister());
+  return summary;
 }
 
 
+class BoxUint32x4SlowPath : public SlowPathCode {
+ public:
+  explicit BoxUint32x4SlowPath(BoxUint32x4Instr* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("BoxUint32x4SlowPath");
+    __ Bind(entry_label());
+    const Class& uint32x4_class = compiler->uint32x4_class();
+    const Code& stub =
+        Code::Handle(StubCode::GetAllocationStubForClass(uint32x4_class));
+    const ExternalLabel label(uint32x4_class.ToCString(), stub.EntryPoint());
+
+    LocationSummary* locs = instruction_->locs();
+    locs->live_registers()->Remove(locs->out());
+
+    compiler->SaveLiveRegisters(locs);
+    compiler->GenerateCall(Scanner::kDummyTokenIndex,  // No token position.
+                           &label,
+                           PcDescriptors::kOther,
+                           locs);
+    __ mov(locs->out().reg(), ShifterOperand(R0));
+    compiler->RestoreLiveRegisters(locs);
+
+    __ b(exit_label());
+  }
+
+ private:
+  BoxUint32x4Instr* instruction_;
+};
+
+
 void BoxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  BoxUint32x4SlowPath* slow_path = new BoxUint32x4SlowPath(this);
+  compiler->AddSlowPathCode(slow_path);
+
+  Register out_reg = locs()->out().reg();
+  QRegister value = locs()->in(0).fpu_reg();
+  DRegister value_even = EvenDRegisterOf(value);
+  DRegister value_odd = OddDRegisterOf(value);
+
+  __ TryAllocate(compiler->uint32x4_class(),
+                 slow_path->entry_label(),
+                 out_reg);
+  __ Bind(slow_path->exit_label());
+  __ StoreDToOffset(value_even, out_reg,
+      Uint32x4::value_offset() - kHeapObjectTag);
+  __ StoreDToOffset(value_odd, out_reg,
+      Uint32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
 }
 
 
 LocationSummary* UnboxUint32x4Instr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = value_cid == kUint32x4Cid ? 0 : 1;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  if (kNumTemps > 0) {
+    ASSERT(kNumTemps == 1);
+    summary->set_temp(0, Location::RequiresRegister());
+  }
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void UnboxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  const intptr_t value_cid = value()->Type()->ToCid();
+  const Register value = locs()->in(0).reg();
+  const QRegister result = locs()->out().fpu_reg();
+
+  if (value_cid != kUint32x4Cid) {
+    const Register temp = locs()->temp(0).reg();
+    Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
+    __ tst(value, ShifterOperand(kSmiTagMask));
+    __ b(deopt, EQ);
+    __ CompareClassId(value, kUint32x4Cid, temp);
+    __ b(deopt, NE);
+  }
+
+  const DRegister result_even = EvenDRegisterOf(result);
+  const DRegister result_odd = OddDRegisterOf(result);
+  __ LoadDFromOffset(result_even, value,
+      Uint32x4::value_offset() - kHeapObjectTag);
+  __ LoadDFromOffset(result_odd, value,
+      Uint32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
 }
 
 
@@ -2738,57 +2914,159 @@
 
 
 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  QRegister left = locs()->in(0).fpu_reg();
+  QRegister right = locs()->in(1).fpu_reg();
+  QRegister result = locs()->out().fpu_reg();
+
+  switch (op_kind()) {
+    case Token::kADD: __ vaddqs(result, left, right); break;
+    case Token::kSUB: __ vsubqs(result, left, right); break;
+    case Token::kMUL: __ vmulqs(result, left, right); break;
+    // TODO(zra): Two options for division. Either use vdiv piecewise, or do
+    // vrecpeqs followed by vmulqs.
+    case Token::kDIV: UNIMPLEMENTED(); break;
+    default: UNREACHABLE();
+  }
 }
 
 
 LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  QRegister value = locs()->in(0).fpu_reg();
+  QRegister result = locs()->out().fpu_reg();
+  DRegister dresult0 = EvenDRegisterOf(result);
+  SRegister sresult0 = EvenSRegisterOf(dresult0);
+
+  DRegister dvalue0 = EvenDRegisterOf(value);
+  DRegister dvalue1 = OddDRegisterOf(value);
+
+  // For these cases the vdup instruction requires fewer
+  // instructions. For arbitrary shuffles, vtbl will be needed.
+  switch (op_kind()) {
+    case MethodRecognizer::kFloat32x4ShuffleXXXX:
+      __ vdup(kWord, result, dvalue0, 0);
+      break;
+    case MethodRecognizer::kFloat32x4ShuffleYYYY:
+      __ vdup(kWord, result, dvalue0, 1);
+      break;
+    case MethodRecognizer::kFloat32x4ShuffleZZZZ:
+      __ vdup(kWord, result, dvalue1, 0);
+      break;
+    case MethodRecognizer::kFloat32x4ShuffleWWWW:
+      __ vdup(kWord, result, dvalue1, 1);
+      break;
+    case MethodRecognizer::kFloat32x4ShuffleX:
+      __ vdup(kWord, result, dvalue0, 0);
+      __ vcvtds(dresult0, sresult0);
+      break;
+    case MethodRecognizer::kFloat32x4ShuffleY:
+      __ vdup(kWord, result, dvalue0, 1);
+      __ vcvtds(dresult0, sresult0);
+      break;
+    case MethodRecognizer::kFloat32x4ShuffleZ:
+      __ vdup(kWord, result, dvalue1, 0);
+      __ vcvtds(dresult0, sresult0);
+      break;
+    case MethodRecognizer::kFloat32x4ShuffleW:
+      __ vdup(kWord, result, dvalue1, 1);
+      __ vcvtds(dresult0, sresult0);
+      break;
+    default: UNREACHABLE();
+  }
 }
 
 
 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 4;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_in(2, Location::RequiresFpuRegister());
+  summary->set_in(3, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  QRegister q0 = locs()->in(0).fpu_reg();
+  QRegister q1 = locs()->in(1).fpu_reg();
+  QRegister q2 = locs()->in(2).fpu_reg();
+  QRegister q3 = locs()->in(3).fpu_reg();
+  QRegister r = locs()->out().fpu_reg();
+
+  DRegister dr0 = EvenDRegisterOf(r);
+  DRegister dr1 = OddDRegisterOf(r);
+
+  __ vcvtsd(EvenSRegisterOf(dr0), EvenDRegisterOf(q0));
+  __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1));
+  __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2));
+  __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3));
 }
 
 
 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 0;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  QRegister q = locs()->out().fpu_reg();
+  __ veorq(q, q, q);
 }
 
 
 LocationSummary* Float32x4SplatInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(Location::RequiresFpuRegister());
+  return summary;
 }
 
 
 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  QRegister value = locs()->in(0).fpu_reg();
+  QRegister result = locs()->out().fpu_reg();
+
+  DRegister dvalue0 = EvenDRegisterOf(value);
+
+  // Convert to Float32.
+  __ vcvtsd(STMP, dvalue0);
+
+  // Splat across all lanes.
+  __ vdup(kWord, result, DTMP, 0);
 }
 
 
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 6f379eb..6b8b215 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -57,7 +57,8 @@
       __ PushObject(value.constant());
     } else {
       ASSERT(value.IsStackSlot());
-      __ lw(TMP, value.ToStackSlotAddress());
+      const intptr_t value_offset = value.ToStackSlotOffset();
+      __ LoadFromOffset(TMP, FP, value_offset);
       __ Push(TMP);
     }
   }
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index 6d36d4d..23ab978 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -87,8 +87,6 @@
 }
 
 
-// TODO(regis): Remove all occurences of Address in the architecture independent
-// portion of the vm.
 Address Location::ToStackSlotAddress() const {
   const intptr_t index = stack_index();
   if (index < 0) {
@@ -101,6 +99,18 @@
 }
 
 
+intptr_t Location::ToStackSlotOffset() const {
+  const intptr_t index = stack_index();
+  if (index < 0) {
+    const intptr_t offset = (kParamEndSlotFromFp - index)  * kWordSize;
+    return offset;
+  } else {
+    const intptr_t offset = (kFirstLocalSlotFromFp - index) * kWordSize;
+    return offset;
+  }
+}
+
+
 const char* Location::Name() const {
   switch (kind()) {
     case kInvalid: return "?";
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index d74b91c..24bf0a0 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -284,6 +284,9 @@
   // Return a memory operand for stack slot locations.
   Address ToStackSlotAddress() const;
 
+  // Returns the offset from the frame pointer for stack slot locations.
+  intptr_t ToStackSlotOffset() const;
+
   // Constants.
   static Location RegisterOrConstant(Value* value);
   static Location RegisterOrSmiConstant(Value* value);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 9fdb01e..ad2fc20 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -2914,9 +2914,15 @@
     int8_t* s8d_8 = reinterpret_cast<int8_t*>(&s8d);
     int8_t* s8n_8 = reinterpret_cast<int8_t*>(&s8n);
     int8_t* s8m_8 = reinterpret_cast<int8_t*>(&s8m);
+    uint8_t* s8n_u8 = reinterpret_cast<uint8_t*>(&s8n);
+    uint8_t* s8m_u8 = reinterpret_cast<uint8_t*>(&s8m);
     int16_t* s8d_16 = reinterpret_cast<int16_t*>(&s8d);
     int16_t* s8n_16 = reinterpret_cast<int16_t*>(&s8n);
     int16_t* s8m_16 = reinterpret_cast<int16_t*>(&s8m);
+    uint16_t* s8n_u16 = reinterpret_cast<uint16_t*>(&s8n);
+    uint16_t* s8m_u16 = reinterpret_cast<uint16_t*>(&s8m);
+    int32_t* s8n_32 = reinterpret_cast<int32_t*>(&s8n);
+    int32_t* s8m_32 = reinterpret_cast<int32_t*>(&s8m);
     int64_t* s8d_64 = reinterpret_cast<int64_t*>(&s8d);
     int64_t* s8n_64 = reinterpret_cast<int64_t*>(&s8n);
     int64_t* s8m_64 = reinterpret_cast<int64_t*>(&s8m);
@@ -3007,6 +3013,188 @@
       for (int i = 0; i < 4; i++) {
         s8d.data_[i].f = s8n.data_[i].f * s8m.data_[i].f;
       }
+    } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+               (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
+      // Format(instr, "veorq 'qd, 'qn, 'qm");
+      for (int i = 0; i < 4; i++) {
+        s8d.data_[i].u = s8n.data_[i].u ^ s8m.data_[i].u;
+      }
+    } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+               (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 0)) {
+      // Format(instr, "vornq 'qd, 'qn, 'qm");
+      for (int i = 0; i < 4; i++) {
+        s8d.data_[i].u = s8n.data_[i].u | ~s8m.data_[i].u;
+      }
+    } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+               (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
+      if (qm == qn) {
+        // Format(instr, "vmovq 'qd, 'qm");
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8m.data_[i].u;
+        }
+      } else {
+        // Format(instr, "vorrq 'qd, 'qm");
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8n.data_[i].u | s8m.data_[i].u;
+        }
+      }
+    } else if ((instr->Bits(8, 4) == 12) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
+               (instr->Bit(7) == 0)) {
+      DRegister dm = instr->DmField();
+      int64_t dm_value = get_dregister_bits(dm);
+      int32_t imm4 = instr->Bits(16, 4);
+      int32_t idx;
+      if ((imm4 & 1) != 0) {
+        // Format(instr, "vdupb 'qd, 'dm['imm4_vdup]");
+        int8_t* dm_b = reinterpret_cast<int8_t*>(&dm_value);
+        idx = imm4 >> 1;
+        int8_t val = dm_b[idx];
+        for (int i = 0; i < 16; i++) {
+          s8d_8[i] = val;
+        }
+      } else if ((imm4 & 2) != 0) {
+        // Format(instr, "vduph 'qd, 'dm['imm4_vdup]");
+        int16_t* dm_h = reinterpret_cast<int16_t*>(&dm_value);
+        idx = imm4 >> 2;
+        int16_t val = dm_h[idx];
+        for (int i = 0; i < 8; i++) {
+          s8d_16[i] = val;
+        }
+      } else if ((imm4 & 4) != 0) {
+        // Format(instr, "vdupw 'qd, 'dm['imm4_vdup]");
+        int32_t* dm_w = reinterpret_cast<int32_t*>(&dm_value);
+        idx = imm4 >> 3;
+        int32_t val = dm_w[idx];
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = val;
+        }
+      } else {
+        UnimplementedInstruction(instr);
+      }
+    } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 2)) {
+      // Format(instr, "vceqq'sz 'qd, 'qn, 'qm");
+      const int size = instr->Bits(20, 2);
+      if (size == 0) {
+        for (int i = 0; i < 16; i++) {
+          s8d_8[i] = s8n_8[i] == s8m_8[i] ? 0xff : 0;
+        }
+      } else if (size == 1) {
+        for (int i = 0; i < 8; i++) {
+          s8d_16[i] = s8n_16[i] == s8m_16[i] ? 0xffff : 0;
+        }
+      } else if (size == 2) {
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8n.data_[i].u == s8m.data_[i].u ? 0xffffffff : 0;
+        }
+      } else if (size == 3) {
+        UnimplementedInstruction(instr);
+      } else {
+        UNREACHABLE();
+      }
+    } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
+      // Format(instr, "vceqqs 'qd, 'qn, 'qm");
+      for (int i = 0; i < 4; i++) {
+        s8d.data_[i].u = s8n.data_[i].f == s8m.data_[i].f ? 0xffffffff : 0;
+      }
+    } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 0)) {
+      // Format(instr, "vcgeq'sz 'qd, 'qn, 'qm");
+      const int size = instr->Bits(20, 2);
+      if (size == 0) {
+        for (int i = 0; i < 16; i++) {
+          s8d_8[i] = s8n_8[i] >= s8m_8[i] ? 0xff : 0;
+        }
+      } else if (size == 1) {
+        for (int i = 0; i < 8; i++) {
+          s8d_16[i] = s8n_16[i] >= s8m_16[i] ? 0xffff : 0;
+        }
+      } else if (size == 2) {
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8n_32[i] >= s8m_32[i] ? 0xffffffff : 0;
+        }
+      } else if (size == 3) {
+        UnimplementedInstruction(instr);
+      } else {
+        UNREACHABLE();
+      }
+    } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
+               (instr->Bits(23, 2) == 2)) {
+      // Format(instr, "vcugeq'sz 'qd, 'qn, 'qm");
+      const int size = instr->Bits(20, 2);
+      if (size == 0) {
+        for (int i = 0; i < 16; i++) {
+          s8d_8[i] = s8n_u8[i] >= s8m_u8[i] ? 0xff : 0;
+        }
+      } else if (size == 1) {
+        for (int i = 0; i < 8; i++) {
+          s8d_16[i] = s8n_u16[i] >= s8m_u16[i] ? 0xffff : 0;
+        }
+      } else if (size == 2) {
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8n.data_[i].u >= s8m.data_[i].u ? 0xffffffff : 0;
+        }
+      } else if (size == 3) {
+        UnimplementedInstruction(instr);
+      } else {
+        UNREACHABLE();
+      }
+    } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
+      // Format(instr, "vcgeqs 'qd, 'qn, 'qm");
+      for (int i = 0; i < 4; i++) {
+        s8d.data_[i].u = s8n.data_[i].f >= s8m.data_[i].f ? 0xffffffff : 0;
+      }
+    } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
+               (instr->Bits(23, 2) == 0)) {
+      // Format(instr, "vcgtq'sz 'qd, 'qn, 'qm");
+      const int size = instr->Bits(20, 2);
+      if (size == 0) {
+        for (int i = 0; i < 16; i++) {
+          s8d_8[i] = s8n_8[i] > s8m_8[i] ? 0xff : 0;
+        }
+      } else if (size == 1) {
+        for (int i = 0; i < 8; i++) {
+          s8d_16[i] = s8n_16[i] > s8m_16[i] ? 0xffff : 0;
+        }
+      } else if (size == 2) {
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8n_32[i] > s8m_32[i] ? 0xffffffff : 0;
+        }
+      } else if (size == 3) {
+        UnimplementedInstruction(instr);
+      } else {
+        UNREACHABLE();
+      }
+    } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
+               (instr->Bits(23, 2) == 2)) {
+      // Format(instr, "vcugtq'sz 'qd, 'qn, 'qm");
+      const int size = instr->Bits(20, 2);
+      if (size == 0) {
+        for (int i = 0; i < 16; i++) {
+          s8d_8[i] = s8n_u8[i] > s8m_u8[i] ? 0xff : 0;
+        }
+      } else if (size == 1) {
+        for (int i = 0; i < 8; i++) {
+          s8d_16[i] = s8n_u16[i] > s8m_u16[i] ? 0xffff : 0;
+        }
+      } else if (size == 2) {
+        for (int i = 0; i < 4; i++) {
+          s8d.data_[i].u = s8n.data_[i].u > s8m.data_[i].u ? 0xffffffff : 0;
+        }
+      } else if (size == 3) {
+        UnimplementedInstruction(instr);
+      } else {
+        UNREACHABLE();
+      }
+    } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 2)) {
+      // Format(instr, "vcgtqs 'qd, 'qn, 'qm");
+      for (int i = 0; i < 4; i++) {
+        s8d.data_[i].u = s8n.data_[i].f > s8m.data_[i].f ? 0xffffffff : 0;
+      }
     } else {
       UnimplementedInstruction(instr);
     }
@@ -3031,7 +3219,6 @@
         table[i] = 0;
       }
 
-
       int64_t dm_value = get_dregister_bits(dm);
       int64_t result;
       int8_t* dm_bytes = reinterpret_cast<int8_t*>(&dm_value);
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index ec602d6..c7c1787 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1468,8 +1468,8 @@
     __ LoadFromOffset(kWord, IP, R7, -i * kWordSize);
     __ Push(IP);
   }
-  // Pass IC data object and arguments descriptor array.
-  __ PushList((1 << R4) | (1 << R5));
+  // Pass IC data object.
+  __ Push(R5);
 
   if (num_args == 1) {
     __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
@@ -1480,9 +1480,8 @@
   } else {
     UNIMPLEMENTED();
   }
-  // Remove the call arguments pushed earlier, including the IC data object
-  // and the arguments descriptor array.
-  __ Drop(num_args + 2);
+  // Remove the call arguments pushed earlier, including the IC data object.
+  __ Drop(num_args + 1);
   // Pop returned code object into R0 (null if not found).
   // Restore arguments descriptor array and IC data array.
   __ PopList((1 << R0) | (1 << R4) | (1 << R5));
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index e033ba5..ef24ad8 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1519,7 +1519,6 @@
     __ pushl(EBX);
   }
   __ pushl(ECX);  // Pass IC data object.
-  __ pushl(EDX);  // Pass arguments descriptor array.
   if (num_args == 1) {
     __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
   } else if (num_args == 2) {
@@ -1529,9 +1528,8 @@
   } else {
     UNIMPLEMENTED();
   }
-  // Remove the call arguments pushed earlier, including the IC data object
-  // and the arguments descriptor array.
-  for (intptr_t i = 0; i < num_args + 2; i++) {
+  // Remove the call arguments pushed earlier, including the IC data object.
+  for (intptr_t i = 0; i < num_args + 1; i++) {
     __ popl(EAX);
   }
   __ popl(EAX);  // Pop returned code object into EAX (null if not found).
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 25578d5..0881c59 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -1655,7 +1655,7 @@
   __ EnterStubFrame();
   // Preserve IC data object and arguments descriptor array and
   // setup space on stack for result (target code object).
-  int num_slots = num_args + 5;
+  int num_slots = num_args + 4;
   __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
   __ sw(S5, Address(SP, (num_slots - 1) * kWordSize));
   __ sw(S4, Address(SP, (num_slots - 2) * kWordSize));
@@ -1666,9 +1666,8 @@
     __ lw(TMP1, Address(T1, -i * kWordSize));
     __ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize));
   }
-  // Pass IC data object and arguments descriptor array.
+  // Pass IC data object.
   __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize));
-  __ sw(S4, Address(SP, (num_slots - num_args - 5) * kWordSize));
 
   if (num_args == 1) {
     __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 14c3010..e222c70 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1500,7 +1500,6 @@
     __ pushq(RCX);
   }
   __ pushq(RBX);  // Pass IC data object.
-  __ pushq(R10);  // Pass arguments descriptor array.
   if (num_args == 1) {
     __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
   } else if (num_args == 2) {
@@ -1510,9 +1509,8 @@
   } else {
     UNIMPLEMENTED();
   }
-  // Remove the call arguments pushed earlier, including the IC data object
-  // and the arguments descriptor array.
-  for (intptr_t i = 0; i < num_args + 2; i++) {
+  // Remove the call arguments pushed earlier, including the IC data object.
+  for (intptr_t i = 0; i < num_args + 1; i++) {
     __ popq(RAX);
   }
   __ popq(RAX);  // Pop returned code object into RAX (null if not found).
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 2fd29da..a10ccbd 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -42,6 +42,8 @@
       // cache. One for given node and one for each nested closure.
       if (node is FunctionExpression) {
         translator.translateFunction(element, node);
+      } else if (element.isSynthesized) {
+        return new ClosureClassMap(null, null, null, new ThisElement(element));
       } else {
         // Must be the lazy initializer of a static.
         assert(node is SendSet);
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 79c9a27..610114e 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -689,7 +689,7 @@
     compiler.analyzeElement(constructor.declaration);
 
     InterfaceType type = elements.getType(node);
-    if ( constructor.isRedirectingFactory) {
+    if (constructor.isRedirectingFactory) {
       type = constructor.computeTargetType(compiler, type);
     }
 
@@ -704,7 +704,7 @@
     List<Constant> arguments = evaluateArgumentsToConstructor(
         node, selector, send.arguments, constructor);
     ConstructorEvaluator evaluator =
-        new ConstructorEvaluator(node, constructor, handler, compiler);
+        new ConstructorEvaluator(constructor, handler, compiler);
     evaluator.evaluateConstructorFieldValues(arguments);
     List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement);
 
@@ -761,8 +761,7 @@
    *
    * Invariant: [constructor] must be an implementation element.
    */
-  ConstructorEvaluator(Node node,
-                       FunctionElement constructor,
+  ConstructorEvaluator(FunctionElement constructor,
                        ConstantHandler handler,
                        Compiler compiler)
       : this.constructor = constructor,
@@ -772,7 +771,7 @@
               compiler.resolver.resolveMethodElement(constructor.declaration),
               compiler,
               isConst: true) {
-    assert(invariant(node, constructor.isImplementation));
+    assert(invariant(constructor, constructor.isImplementation));
   }
 
   Constant visitSend(Send send) {
@@ -828,15 +827,10 @@
     });
   }
 
-  void evaluateSuperOrRedirectSend(Node currentNode,
-                                   Selector selector,
-                                   Link<Node> arguments,
+  void evaluateSuperOrRedirectSend(List<Constant> compiledArguments,
                                    FunctionElement targetConstructor) {
-    List<Constant> compiledArguments = evaluateArgumentsToConstructor(
-        currentNode, selector, arguments, targetConstructor);
-
     ConstructorEvaluator evaluator = new ConstructorEvaluator(
-        currentNode, targetConstructor, handler, compiler);
+        targetConstructor, handler, compiler);
     evaluator.evaluateConstructorFieldValues(compiledArguments);
     // Copy over the fieldValues from the super/redirect-constructor.
     // No need to go through [updateFieldValue] because the
@@ -849,6 +843,21 @@
    * the [fieldValues] map.
    */
   void evaluateConstructorInitializers() {
+    if (constructor.isSynthesized) {
+      List<Constant> compiledArguments = <Constant>[];
+
+      Function compileArgument = (element) => definitions[element];
+      Function compileConstant = handler.compileConstant;
+      FunctionElement target = constructor.targetConstructor.implementation;
+      Selector.addForwardingElementArgumentsToList(constructor,
+                                                   compiledArguments,
+                                                   target,
+                                                   compileArgument,
+                                                   compileConstant,
+                                                   compiler);
+      evaluateSuperOrRedirectSend(compiledArguments, target);
+      return;
+    }
     FunctionExpression functionNode = constructor.parseNode(compiler);
     NodeList initializerList = functionNode.initializers;
 
@@ -862,11 +871,10 @@
         if (link.head is !SendSet) {
           // A super initializer or constructor redirection.
           Send call = link.head;
-          FunctionElement targetConstructor = elements[call];
-          Selector selector = elements.getSelector(call);
-          Link<Node> arguments = call.arguments;
-          evaluateSuperOrRedirectSend(
-              call, selector, arguments, targetConstructor);
+          FunctionElement target = elements[call];
+          List<Constant> compiledArguments = evaluateArgumentsToConstructor(
+              call, elements.getSelector(call), call.arguments, target);
+          evaluateSuperOrRedirectSend(compiledArguments, target);
           foundSuperOrRedirect = true;
         } else {
           // A field initializer.
@@ -897,11 +905,9 @@
           compiler.internalError("no default constructor available",
                                  node: functionNode);
         }
-
-        evaluateSuperOrRedirectSend(functionNode,
-                                    selector,
-                                    const Link<Node>(),
-                                    targetConstructor);
+        List<Constant> compiledArguments = evaluateArgumentsToConstructor(
+            functionNode, selector, const Link<Node>(), targetConstructor);
+        evaluateSuperOrRedirectSend(compiledArguments, targetConstructor);
       }
     }
   }
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 5ceb7d3..c301271 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -968,13 +968,7 @@
     if (element.isClass()) {
       ClassElement cls = element;
       cls.ensureResolved(this);
-      cls.forEachLocalMember((e) {
-        if (e.isSynthesized) {
-          // TODO(ahe): Work-around for http://dartbug.com/11205.
-          if (e.getLibrary().isPlatformLibrary) return;
-        }
-        world.addToWorkList(e);
-      });
+      cls.forEachLocalMember(enqueuer.resolution.addToWorkList);
       world.registerInstantiatedClass(element, globalDependencies);
     } else {
       world.addToWorkList(element);
@@ -1048,15 +1042,15 @@
 
   TreeElements analyzeElement(Element element) {
     assert(invariant(element, element.isDeclaration));
-    assert(!element.isForwardingConstructor);
     ResolutionEnqueuer world = enqueuer.resolution;
     TreeElements elements = world.getCachedElements(element);
     if (elements != null) return elements;
     assert(parser != null);
     Node tree = parser.parse(element);
-    validator.validate(tree);
+    assert(invariant(element, !element.isSynthesized || tree == null));
+    if (tree != null) validator.validate(tree);
     elements = resolver.resolve(element);
-    if (elements != null && !analyzeSignaturesOnly) {
+    if (tree != null && elements != null && !analyzeSignaturesOnly) {
       // Only analyze nodes with a corresponding [TreeElements].
       checker.check(elements);
     }
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index d086c19..4c29888 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -240,7 +240,7 @@
     for (final element in resolvedElements.keys) {
       if (!element.isConstructor()) continue;
       Link<Element> optionalParameters =
-          element.functionSignature.optionalParameters;
+          element.computeSignature(compiler).optionalParameters;
       for (final optional in optionalParameters) {
         if (optional.kind != ElementKind.FIELD_PARAMETER) continue;
         fixedMemberNames.add(optional.name.slowToString());
@@ -356,7 +356,8 @@
       // and then overwrite necessary parts.
       var classNode = classElement.parseNode(compiler);
       SynthesizedConstructorElementX constructor =
-          new SynthesizedConstructorElementX(classElement);
+          new SynthesizedConstructorElementX(
+              classElement.name, null, classElement);
       constructor.type = new FunctionType(
           constructor,
           compiler.types.voidType,
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
index 01cdbe9..d816a0b 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -381,7 +381,7 @@
       // Do not forget to rename them as well.
       FunctionElement constructorFunction = constructor;
       Link<Element> optionalParameters =
-          constructorFunction.functionSignature.optionalParameters;
+          constructorFunction.computeSignature(compiler).optionalParameters;
       for (final argument in send.argumentsNode) {
         NamedArgument named = argument.asNamedArgument();
         if (named == null) continue;
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index b39e475..b20faed 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -240,6 +240,7 @@
         compiler.enqueuer.resolution.getCachedElements(element);
     if (elements == null) return new LinkedHashSet<Element>();
     Node node = element.parseNode(compiler);
+    if (node == null) return new LinkedHashSet<Element>();
     var collector = new DependencyCollector(elements, compiler);
     node.accept(collector);
     collector.dependencies.addAll(elements.otherDependencies);
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index f367345..7703b26 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -845,11 +845,7 @@
   void addMember(Element element, DiagnosticListener listener);
   void addToScope(Element element, DiagnosticListener listener);
 
-  /**
-   * Add a synthetic nullary constructor if there are no other
-   * constructors.
-   */
-  void addDefaultConstructorIfNeeded(Compiler compiler);
+  void setDefaultConstructor(FunctionElement constructor, Compiler compiler);
 
   void addBackendMember(Element element);
   void reverseBackendMembers();
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 76b16e4..c2791c8 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1398,63 +1398,31 @@
  * constructors for mixin applications.
  */
 class SynthesizedConstructorElementX extends FunctionElementX {
-  /// The target constructor if this synthetic constructor is a forwarding
-  /// constructor in a mixin application.
-  final FunctionElement target;
+  final FunctionElement superMember;
 
-  SynthesizedConstructorElementX(Element enclosing)
-      : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
-              Modifiers.EMPTY, enclosing),
-        target = null;
+  SynthesizedConstructorElementX(SourceString name,
+                                 this.superMember,
+                                 Element enclosing)
+      : super(name,
+              ElementKind.GENERATIVE_CONSTRUCTOR,
+              Modifiers.EMPTY,
+              enclosing);
 
-  SynthesizedConstructorElementX.forDefault(Element enclosing,
-                                            Compiler compiler)
-      : super(const SourceString(''), ElementKind.GENERATIVE_CONSTRUCTOR,
-              Modifiers.EMPTY, enclosing),
-        target = null {
-    // TODO(karlklose): get rid of the fake AST.
-    type = new FunctionType(this,
-        compiler.types.voidType,
-        const Link<DartType>(),
-        const Link<DartType>(),
-        const Link<SourceString>(),
-        const Link<DartType>());
-    cachedNode = new FunctionExpression(
-        new Identifier(enclosing.position()),
-        new NodeList.empty(),
-        new Block(new NodeList.empty()),
-        null, Modifiers.EMPTY, null, null);
-  }
-
-  /**
-   * Create synthetic constructor that directly forwards to a constructor in the
-   * super class of a mixin application.
-   *
-   * In a mixin application `Base with M`, any constructor defined in `Base` is
-   * available as if they were a constructor defined in the mixin application
-   * with the same formal parameters that calls the constructor in the super
-   * class via a `super` initializer (see Ch. 9.1 in the specification).
-   */
-  SynthesizedConstructorElementX.forwarding(SourceString name, this.target,
-                                            Element enclosing)
-    : super(name, ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY,
-            enclosing);
+  SynthesizedConstructorElementX.forDefault(superMember, Element enclosing)
+      : this(const SourceString(''), superMember, enclosing);
 
   Token position() => enclosingElement.position();
 
   bool get isSynthesized => true;
 
-  bool get isForwardingConstructor => target != null;
-
-  FunctionElement get targetConstructor => target;
+  FunctionElement get targetConstructor => superMember;
 
   FunctionSignature computeSignature(compiler) {
-    if (target != null) {
-      return target.computeSignature(compiler);
-    } else {
-      assert(cachedNode != null);
-      return super.computeSignature(compiler);
+    if (superMember.isErroneous()) {
+      return compiler.objectClass.localLookup(
+          const SourceString('')).computeSignature(compiler);
     }
+    return superMember.computeSignature(compiler);
   }
 
   get declaration => this;
@@ -1604,13 +1572,6 @@
     return this;
   }
 
-  void addDefaultConstructorIfNeeded(Compiler compiler) {
-    if (hasConstructor) return;
-    FunctionElement constructor =
-        new SynthesizedConstructorElementX.forDefault(this, compiler);
-    setDefaultConstructor(constructor, compiler);
-  }
-
   void setDefaultConstructor(FunctionElement constructor, Compiler compiler);
 
   void addBackendMember(Element member) {
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 77a146a..353897d 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -105,12 +105,6 @@
   void addToWorkList(Element element) {
     assert(invariant(element, element.isDeclaration));
     if (element.isForeign(compiler)) return;
-
-    if (element.isForwardingConstructor) {
-      addToWorkList(element.targetConstructor);
-      return;
-    }
-
     internalAddToWorkList(element);
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 281a07a..3a9154a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1387,7 +1387,7 @@
 
     void generateFunctionTypeSignature(Element method, FunctionType type) {
       assert(method.isImplementation);
-      String thisAccess = 'this';
+      jsAst.Expression thisAccess = new jsAst.This();
       Node node = method.parseNode(compiler);
       ClosureClassMap closureData =
           compiler.closureToClassMapper.closureMappingCache[node];
@@ -1397,14 +1397,13 @@
         if (thisElement != null) {
           assert(thisElement.hasFixedBackendName());
           String thisName = thisElement.fixedBackendName();
-          thisAccess = 'this.$thisName';
+          thisAccess = js('this')[js.string(thisName)];
         }
       }
       RuntimeTypes rti = backend.rti;
-      String encoding = rti.getSignatureEncoding(type, () => '$thisAccess');
+      jsAst.Expression encoding = rti.getSignatureEncoding(type, thisAccess);
       String operatorSignature = namer.operatorSignature();
-      builder.addProperty(operatorSignature,
-          new jsAst.LiteralExpression(encoding));
+      builder.addProperty(operatorSignature, encoding);
     }
 
     void generateSubstitution(Element other, {bool emitNull: false}) {
@@ -1412,11 +1411,9 @@
       jsAst.Expression expression;
       bool needsNativeCheck = nativeEmitter.requiresNativeIsCheck(other);
       if (other.kind == ElementKind.CLASS) {
-        String substitution = rti.getSupertypeSubstitution(classElement, other,
-            alwaysGenerateFunction: true);
-        if (substitution != null) {
-          expression = new jsAst.LiteralExpression(substitution);
-        } else if (emitNull || needsNativeCheck) {
+        expression = rti.getSupertypeSubstitution(
+            classElement, other, alwaysGenerateFunction: true);
+        if (expression == null && (emitNull || needsNativeCheck)) {
           expression = new jsAst.LiteralNull();
         }
       }
@@ -1444,15 +1441,20 @@
         buffer.write('$holder.${namer.operatorIs(cls)}$_=${_}true$N');
         Substitution substitution = check.substitution;
         if (substitution != null) {
-          String body = substitution.getCode(rti, false);
-          buffer.write('$holder.${namer.substitutionName(cls)}$_=${_}$body$N');
+          CodeBuffer body =
+             jsAst.prettyPrint(substitution.getCode(rti, false), compiler);
+          buffer.write('$holder.${namer.substitutionName(cls)}$_=${_}');
+          buffer.write(body);
+          buffer.write('$N');
         }
       };
     }
 
     void addSignature(FunctionType type) {
-      String encoding = rti.getTypeEncoding(type);
-      buffer.add('${namer.signatureName(type)}$_=${_}$encoding$N');
+      jsAst.Expression encoding = rti.getTypeEncoding(type);
+      buffer.add('${namer.signatureName(type)}$_=${_}');
+      buffer.write(jsAst.prettyPrint(encoding, compiler));
+      buffer.add('$N');
     }
 
     checkedNonGenericFunctionTypes.forEach(addSignature);
@@ -2262,11 +2264,11 @@
         RuntimeTypes rti = backend.rti;
         // [:() => null:] is dummy encoding of [this] which is never needed for
         // the encoding of the type of the static [method].
-        String encoding = rti.getSignatureEncoding(methodType, () => 'null');
+        jsAst.Expression encoding =
+            rti.getSignatureEncoding(methodType, js('null'));
         String operatorSignature = namer.operatorSignature();
         // TODO(johnniwinther): Make MiniJsParser support function expressions.
-        closureBuilder.addProperty(operatorSignature,
-            new jsAst.LiteralExpression(encoding));
+        closureBuilder.addProperty(operatorSignature, encoding);
       }
 
       void emitIsFunctionTypeTest(FunctionType functionType) {
@@ -2401,11 +2403,10 @@
       addParameterStubs(callElement, boundClosureBuilder.addProperty);
 
       void emitFunctionTypeSignature(Element method, FunctionType methodType) {
-        String encoding = backend.rti.getSignatureEncoding(
-            methodType, () => 'this.${fieldNames[0]}');
+        jsAst.Expression encoding = backend.rti.getSignatureEncoding(
+            methodType, js('this')[fieldNames[0]]);
         String operatorSignature = namer.operatorSignature();
-        boundClosureBuilder.addProperty(operatorSignature,
-            new jsAst.LiteralExpression(encoding));
+        boundClosureBuilder.addProperty(operatorSignature, encoding);
       }
 
       void emitIsFunctionTypeTest(FunctionType functionType) {
@@ -3423,7 +3424,7 @@
     if (!backend.retainMetadataOf(element)) return code;
     return compiler.withCurrentElement(element, () {
       List<int> metadata = <int>[];
-      FunctionSignature signature = element.functionSignature;
+      FunctionSignature signature = element.computeSignature(compiler);
       if (element.isConstructor()) {
         metadata.add(reifyType(element.getEnclosingClass().thisType));
       } else {
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 73e31a1..3f21597 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -12,7 +12,7 @@
   Iterator<ClassElement> get iterator;
 }
 
-typedef String VariableSubstitution(TypeVariableType variable);
+typedef jsAst.Expression OnVariableCallback(TypeVariableType variable);
 
 class RuntimeTypes {
   final Compiler compiler;
@@ -421,7 +421,6 @@
     return (variables.isEmpty == arguments.isEmpty);
   }
 
-  // TODO(karlklose): rewrite to use js.Expressions.
   /**
    * Compute a JavaScript expression that describes the necessary substitution
    * for type arguments in a subtype test.
@@ -436,8 +435,10 @@
    *  3) A function mapping the type variables of the object to be checked to
    *     a list expression.
    */
-  String getSupertypeSubstitution(ClassElement cls, ClassElement check,
-                                  {bool alwaysGenerateFunction: false}) {
+  jsAst.Expression getSupertypeSubstitution(
+       ClassElement cls,
+       ClassElement check,
+       {bool alwaysGenerateFunction: false}) {
     Substitution substitution = getSubstitution(cls, check);
     if (substitution != null) {
       return substitution.getCode(this, alwaysGenerateFunction);
@@ -462,11 +463,6 @@
                                    { bool alwaysGenerateFunction: false }) {
     if (isTrivialSubstitution(cls, check)) return null;
 
-    bool usesTypeVariables = false;
-    String onVariable(TypeVariableType v) {
-      usesTypeVariables = true;
-      return v.toString();
-    };
     InterfaceType type = cls.computeType(compiler);
     InterfaceType target = type.asInstanceOf(check);
     Link<DartType> typeVariables;
@@ -483,61 +479,71 @@
     }
   }
 
-  String getSubstitutionRepresentation(Link<DartType> types,
-                                       VariableSubstitution variableName) {
-    String code = types.toList(growable: false)
-        .map((type) => _getTypeRepresentation(type, variableName))
-        .join(', ');
-    return '[$code]';
+  jsAst.Expression getSubstitutionRepresentation(
+      Link<DartType> types,
+      OnVariableCallback onVariable) {
+    List<jsAst.ArrayElement> elements = <jsAst.ArrayElement>[];
+    int index = 0;
+    for (; !types.isEmpty; types = types.tail, index++) {
+      jsAst.Expression representation =
+          _getTypeRepresentation(types.head, onVariable);
+      elements.add(new jsAst.ArrayElement(index, representation));
+    }
+    return new jsAst.ArrayInitializer(index, elements);
   }
 
-  String getTypeEncoding(DartType type,
-                         {bool alwaysGenerateFunction: false}) {
+  jsAst.Expression getTypeEncoding(DartType type,
+                                   {bool alwaysGenerateFunction: false}) {
     ClassElement contextClass = Types.getClassContext(type);
-    String onVariable(TypeVariableType v) {
-      return v.toString();
+    jsAst.Expression onVariable(TypeVariableType v) {
+      return new jsAst.VariableUse(v.name.slowToString());
     };
-    String encoding = _getTypeRepresentation(type, onVariable);
+    jsAst.Expression encoding = _getTypeRepresentation(type, onVariable);
     if (contextClass == null && !alwaysGenerateFunction) {
       return encoding;
     } else {
-      String parameters = contextClass != null
-          ? contextClass.typeVariables.toList().join(', ')
-          : '';
-      return 'function ($parameters) { return $encoding; }';
+      List<String> parameters = const <String>[];
+      if (contextClass != null) {
+        parameters = contextClass.typeVariables.toList().map((type) {
+            return type.toString();
+        }).toList();
+      }
+      return js.fun(parameters, js.return_(encoding));
     }
   }
 
-  String getSignatureEncoding(DartType type, String generateThis()) {
+  jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_) {
     ClassElement contextClass = Types.getClassContext(type);
-    String encoding = getTypeEncoding(type, alwaysGenerateFunction: true);
+    jsAst.Expression encoding =
+        getTypeEncoding(type, alwaysGenerateFunction: true);
     if (contextClass != null) {
-      String this_ = generateThis();
       JavaScriptBackend backend = compiler.backend;
       String computeSignature =
           backend.namer.getName(backend.getComputeSignature());
       String contextName = backend.namer.getName(contextClass);
-      return 'function () {'
-             ' return ${backend.namer.GLOBAL_OBJECT}.'
-                  '$computeSignature($encoding, $this_, "$contextName"); '
-             '}';
+      List<jsAst.Expression> arguments =
+          <jsAst.Expression>[encoding, this_, js.string(contextName)];
+      return js.fun([], js.return_(
+          new jsAst.Call(
+              js(backend.namer.GLOBAL_OBJECT)[js.string(computeSignature)],
+              arguments)));
     } else {
       return encoding;
     }
   }
 
-  String getTypeRepresentation(DartType type, VariableSubstitution onVariable) {
+  String getTypeRepresentation(DartType type, OnVariableCallback onVariable) {
     // Create a type representation.  For type variables call the original
     // callback for side effects and return a template placeholder.
-    return _getTypeRepresentation(type, (variable) {
+    jsAst.Expression representation = _getTypeRepresentation(type, (variable) {
       onVariable(variable);
-      return '#';
+      return new jsAst.LiteralString('#');
     });
+    return jsAst.prettyPrint(representation, compiler).buffer.toString();
   }
 
-  // TODO(karlklose): rewrite to use js.Expressions.
-  String _getTypeRepresentation(DartType type,
-                                VariableSubstitution onVariable) {
+  jsAst.Expression _getTypeRepresentation(DartType type,
+                                          OnVariableCallback onVariable) {
     return representationGenerator.getTypeRepresentation(type, onVariable);
   }
 
@@ -559,12 +565,9 @@
   }
 }
 
-typedef String OnVariableCallback(TypeVariableType type);
-
 class TypeRepresentationGenerator extends DartTypeVisitor {
   final Compiler compiler;
   OnVariableCallback onVariable;
-  StringBuffer builder;
 
   JavaScriptBackend get backend => compiler.backend;
   Namer get namer => backend.namer;
@@ -575,104 +578,95 @@
    * Creates a type representation for [type]. [onVariable] is called to provide
    * the type representation for type variables.
    */
-  String getTypeRepresentation(DartType type, OnVariableCallback onVariable) {
+  jsAst.Expression getTypeRepresentation(DartType type,
+                                         OnVariableCallback onVariable) {
     this.onVariable = onVariable;
-    builder = new StringBuffer();
-    visit(type);
-    String typeRepresentation = builder.toString();
-    builder = null;
+    jsAst.Expression representation = visit(type);
     this.onVariable = null;
-    return typeRepresentation;
+    return representation;
   }
 
-  String getJsName(Element element) {
-    return namer.isolateAccess(backend.getImplementationClass(element));
+  jsAst.Expression getJavaScriptClassName(Element element) {
+    return js(namer.isolateAccess(backend.getImplementationClass(element)));
   }
 
   visit(DartType type) {
-    type.unalias(compiler).accept(this, null);
+    return type.unalias(compiler).accept(this, null);
   }
 
   visitTypeVariableType(TypeVariableType type, _) {
-    builder.write(onVariable(type));
+    return onVariable(type);
   }
 
   visitDynamicType(DynamicType type, _) {
-    builder.write('null');
+    return js('null');
   }
 
   visitInterfaceType(InterfaceType type, _) {
-    String name = getJsName(type.element);
-    if (type.isRaw) {
-      builder.write(name);
-    } else {
-      builder.write('[');
-      builder.write(name);
-      builder.write(', ');
-      visitList(type.typeArguments);
-      builder.write(']');
-    }
+    jsAst.Expression name = getJavaScriptClassName(type.element);
+    return type.isRaw ? name : visitList(type.typeArguments, head: name);
   }
 
-  visitList(Link<DartType> types) {
-    bool first = true;
-    for (Link<DartType> link = types; !link.isEmpty; link = link.tail) {
-      if (!first) {
-        builder.write(', ');
-      }
-      visit(link.head);
-      first = false;
+  jsAst.Expression visitList(Link<DartType> types, {jsAst.Expression head}) {
+    int index = 0;
+    List<jsAst.ArrayElement> elements = <jsAst.ArrayElement>[];
+    if (head != null) {
+      elements.add(new jsAst.ArrayElement(0, head));
+      index++;
     }
+    for (Link<DartType> link = types; !link.isEmpty; link = link.tail) {
+      elements.add(new jsAst.ArrayElement(index++, visit(link.head)));
+    }
+    return new jsAst.ArrayInitializer(elements.length, elements);
   }
 
   visitFunctionType(FunctionType type, _) {
-    builder.write('{${namer.functionTypeTag()}:'
-                  ' "${namer.getFunctionTypeName(type)}"');
+    List<jsAst.Property> properties = <jsAst.Property>[];
+
+    void addProperty(String name, jsAst.Expression value) {
+      properties.add(new jsAst.Property(js.string(name), value));
+    }
+
+    jsAst.LiteralString name = js.string(namer.getFunctionTypeName(type));
+    addProperty(namer.functionTypeTag(), name);
     if (type.returnType.isVoid) {
-      builder.write(', ${namer.functionTypeVoidReturnTag()}: true');
+      addProperty(namer.functionTypeVoidReturnTag(), js('true'));
     } else if (!type.returnType.isDynamic) {
-      builder.write(', ${namer.functionTypeReturnTypeTag()}: ');
-      visit(type.returnType);
+      addProperty(namer.functionTypeReturnTypeTag(), visit(type.returnType));
     }
     if (!type.parameterTypes.isEmpty) {
-      builder.write(', ${namer.functionTypeRequiredParametersTag()}: [');
-      visitList(type.parameterTypes);
-      builder.write(']');
+      addProperty(namer.functionTypeRequiredParametersTag(),
+                  visitList(type.parameterTypes));
     }
     if (!type.optionalParameterTypes.isEmpty) {
-      builder.write(', ${namer.functionTypeOptionalParametersTag()}: [');
-      visitList(type.optionalParameterTypes);
-      builder.write(']');
+      addProperty(namer.functionTypeOptionalParametersTag(),
+                  visitList(type.optionalParameterTypes));
     }
     if (!type.namedParameterTypes.isEmpty) {
-      builder.write(', ${namer.functionTypeNamedParametersTag()}: {');
-      bool first = true;
+      List<jsAst.Property> namedArguments = <jsAst.Property>[];
       Link<SourceString> names = type.namedParameters;
       Link<DartType> types = type.namedParameterTypes;
       while (!types.isEmpty) {
         assert(!names.isEmpty);
-        if (!first) {
-          builder.write(', ');
-        }
-        builder.write('${names.head.slowToString()}: ');
-        visit(types.head);
-        first = false;
+        jsAst.Expression name = js.string(names.head.slowToString());
+        namedArguments.add(new jsAst.Property(name, visit(types.head)));
         names = names.tail;
         types = types.tail;
       }
-      builder.write('}');
+      addProperty(namer.functionTypeNamedParametersTag(),
+                  new jsAst.ObjectInitializer(namedArguments));
     }
-    builder.write('}');
+    return new jsAst.ObjectInitializer(properties);
   }
 
   visitMalformedType(MalformedType type, _) {
     // Treat malformed types as dynamic at runtime.
-    builder.write('null');
+    return js('null');
   }
 
   visitVoidType(VoidType type, _) {
     // TODO(ahe): Reify void type ("null" means "dynamic").
-    builder.write('null');
+    return js('null');
   }
 
   visitType(DartType type, _) {
@@ -814,19 +808,24 @@
   Substitution.function(this.arguments, this.parameters)
       : isFunction = true;
 
-  String getCode(RuntimeTypes rti, bool ensureIsFunction) {
-    String variableName(TypeVariableType variable) {
-      return variable.name.slowToString();
+  jsAst.Expression getCode(RuntimeTypes rti, bool ensureIsFunction) {
+    jsAst.Expression declaration(TypeVariableType variable) {
+      return new jsAst.Parameter(variable.name.slowToString());
     }
 
-    String code = rti.getSubstitutionRepresentation(arguments, variableName);
+    jsAst.Expression use(TypeVariableType variable) {
+      return new jsAst.VariableUse(variable.name.slowToString());
+    }
+
+    jsAst.Expression value =
+        rti.getSubstitutionRepresentation(arguments, use);
     if (isFunction) {
-      String formals = parameters.toList().map(variableName).join(', ');
-      return 'function ($formals) { return $code; }';
+      List<String> formals = parameters.toList().map(declaration).toList();
+      return js.fun(formals, js.return_(value));
     } else if (ensureIsFunction) {
-      return 'function () { return $code; }';
+      return js.fun([], js.return_(value));
     } else {
-      return code;
+      return value;
     }
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 3868400..12f9cae 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -339,6 +339,14 @@
         assert(isConstructor);
         return elements;
       }
+      if (element.isSynthesized) {
+        Element target = element.targetConstructor;
+        if (!target.isErroneous()) {
+          compiler.enqueuer.resolution.registerStaticUse(
+              element.targetConstructor);
+        }
+        return new TreeElementMapping(element);
+      }
       if (element.isPatched) {
         checkMatchingPatchSignatures(element, element.patch);
         element = element.patch;
@@ -1143,13 +1151,14 @@
       MessageKind kind = isImplicitSuperCall
           ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
           : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
-      error(diagnosticNode, kind, {'constructorName': fullConstructorName});
+      visitor.compiler.reportErrorCode(
+          diagnosticNode, kind, {'constructorName': fullConstructorName});
     } else {
       if (!call.applies(lookedupConstructor, visitor.compiler)) {
         MessageKind kind = isImplicitSuperCall
                            ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
                            : MessageKind.NO_MATCHING_CONSTRUCTOR;
-        error(diagnosticNode, kind);
+        visitor.compiler.reportErrorCode(diagnosticNode, kind);
       }
     }
   }
@@ -2535,7 +2544,9 @@
     { // This entire block is temporary code per the above TODO.
       FunctionElement targetImplementation = redirectionTarget.implementation;
       FunctionExpression function = targetImplementation.parseNode(compiler);
-      if (function.body != null && function.body.asReturn() != null
+      if (function != null
+          && function.body != null
+          && function.body.asReturn() != null
           && function.body.asReturn().isRedirectingFactoryBody) {
         unimplemented(node.expression, 'redirecting to redirecting factory');
       }
@@ -3272,7 +3283,21 @@
     element.interfaces = resolveInterfaces(node.interfaces, node.superclass);
     calculateAllSupertypes(element);
 
-    element.addDefaultConstructorIfNeeded(compiler);
+    if (!element.hasConstructor) {
+      Element superMember =
+          element.superclass.localLookup(const SourceString(''));
+      if (superMember == null || !superMember.isGenerativeConstructor()) {
+        MessageKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR;
+        Map arguments = {'constructorName': const SourceString('')};
+        compiler.reportErrorCode(node, kind, arguments);
+        superMember = new ErroneousElementX(
+            kind, arguments, const SourceString(''), element);
+        compiler.backend.registerThrowNoSuchMethod(mapping);
+      }
+      FunctionElement constructor =
+          new SynthesizedConstructorElementX.forDefault(superMember, element);
+      element.setDefaultConstructor(constructor, compiler);
+    }
     return element.computeType(compiler);
   }
 
@@ -3316,11 +3341,11 @@
         constructor.computeSignature(compiler).parameterCount == 0;
   }
 
-  FunctionElement createForwardingConstructor(FunctionElement constructor,
-                                              ClassElement target) {
-    return new SynthesizedConstructorElementX.forwarding(constructor.name,
-                                                         constructor,
-                                                         target);
+  FunctionElement createForwardingConstructor(FunctionElement target,
+                                              ClassElement enclosing) {
+    return new SynthesizedConstructorElementX(target.name,
+                                              target,
+                                              enclosing);
   }
 
   void doApplyMixinTo(MixinApplicationElement mixinApplication,
@@ -3359,20 +3384,11 @@
     // because they are now hidden by the mixin application.
     ClassElement superclass = supertype.element;
     superclass.forEachLocalMember((Element member) {
-      if (!member.isConstructor()) return;
-      if (member.isSynthesized && !member.isForwardingConstructor) return;
-      if (isDefaultConstructor(member)) return;
-      assert(invariant(node, !member.isFactoryConstructor(),
-             message: 'mixins cannot have factory constructors'));
-      // Skip forwarding constructors and use their target.
-      FunctionElement constructor =
-          member.isForwardingConstructor ? member.targetConstructor : member;
-      assert(invariant(node, !constructor.isForwardingConstructor));
+      if (!member.isGenerativeConstructor()) return;
       FunctionElement forwarder =
-          createForwardingConstructor(constructor, mixinApplication);
+          createForwardingConstructor(member, mixinApplication);
       mixinApplication.addConstructor(forwarder);
     });
-    mixinApplication.addDefaultConstructorIfNeeded(compiler);
     calculateAllSupertypes(mixinApplication);
   }
 
@@ -3467,32 +3483,63 @@
     return result;
   }
 
+  /**
+   * Compute the list of all supertypes.
+   *
+   * The elements of this list are ordered as follows: first the supertype that
+   * the class extends, then the implemented interfaces, and then the supertypes
+   * of these.  The class [Object] appears only once, at the end of the list.
+   *
+   * For example, for a class `class C extends S implements I1, I2`, we compute
+   *   supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1)
+   *                   ++ supertypes(I2),
+   * where ++ stands for list concatenation.
+   *
+   * This order makes sure that if a class implements an interface twice with
+   * different type arguments, the type used in the most specific class comes
+   * first.
+   */
   void calculateAllSupertypes(ClassElement cls) {
     // TODO(karlklose): Check if type arguments match, if a class
     // element occurs more than once in the supertypes.
     if (cls.allSupertypes != null) return;
     final DartType supertype = cls.supertype;
     if (supertype != null) {
-      var allSupertypes = new LinkBuilder<DartType>();
+      LinkBuilder<DartType> allSupertypes = new LinkBuilder<DartType>();
+
+      void add(DartType type) {
+        if (type.element != compiler.objectClass) {
+          allSupertypes.addLast(type);
+        }
+      }
+
+      add(supertype);
+      for (Link<DartType> interfaces = cls.interfaces;
+          !interfaces.isEmpty;
+          interfaces = interfaces.tail) {
+        add(interfaces.head);
+      }
       addAllSupertypes(allSupertypes, supertype);
       for (Link<DartType> interfaces = cls.interfaces;
            !interfaces.isEmpty;
            interfaces = interfaces.tail) {
         addAllSupertypes(allSupertypes, interfaces.head);
       }
+
+      allSupertypes.addLast(compiler.objectClass.rawType);
       cls.allSupertypes = allSupertypes.toLink();
     } else {
       assert(identical(cls, compiler.objectClass));
       cls.allSupertypes = const Link<DartType>();
     }
- }
+  }
 
   /**
-   * Adds [type] and all supertypes of [type] to [builder] while substituting
-   * type variables.
+   * Adds [type] and all supertypes of [type] to [allSupertypes] while
+   * substituting type variables.
    */
-  void addAllSupertypes(LinkBuilder<DartType> builder, InterfaceType type) {
-    builder.addLast(type);
+  void addAllSupertypes(LinkBuilder<DartType> allSupertypes,
+                        InterfaceType type) {
     Link<DartType> typeArguments = type.typeArguments;
     ClassElement classElement = type.element;
     Link<DartType> typeVariables = classElement.typeVariables;
@@ -3502,7 +3549,10 @@
                  "during resolution of $element"));
     while (!supertypes.isEmpty) {
       DartType supertype = supertypes.head;
-      builder.addLast(supertype.subst(typeArguments, typeVariables));
+      if (supertype.element != compiler.objectClass) {
+        DartType substituted = supertype.subst(typeArguments, typeVariables);
+        allSupertypes.addLast(substituted);
+      }
       supertypes = supertypes.tail;
     }
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index b46ef2b..466a9c5 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -212,7 +212,7 @@
    * Invariant: [function] must be an implementation element.
    */
   void startFunction(Element element, Expression node) {
-    assert(invariant(node, element.isImplementation));
+    assert(invariant(element, element.isImplementation));
     Compiler compiler = builder.compiler;
     closureData = compiler.closureToClassMapper.computeClosureToClassMapping(
             element, node, builder.elements);
@@ -1271,6 +1271,8 @@
         return false;
       }
 
+      if (element.isSynthesized) return true;
+
       if (cachedCanBeInlined == true) return cachedCanBeInlined;
 
       int numParameters = function.functionSignature.parameterCount;
@@ -1346,37 +1348,19 @@
    *
    * Invariant: [constructors] must contain only implementation elements.
    */
-  void inlineSuperOrRedirect(FunctionElement constructor,
-                             Selector selector,
-                             Link<Node> arguments,
+  void inlineSuperOrRedirect(FunctionElement callee,
+                             List<HInstruction> compiledArguments,
                              List<FunctionElement> constructors,
                              Map<Element, HInstruction> fieldValues,
-                             FunctionElement inlinedFromElement,
-                             Node callNode) {
-    constructor = constructor.implementation;
-    compiler.withCurrentElement(constructor, () {
-      constructors.add(constructor);
-
-      List<HInstruction> compiledArguments = new List<HInstruction>();
-      bool succeeded =
-          inlinedFrom(inlinedFromElement,
-                       () => addStaticSendArgumentsToList(selector,
-                                                          arguments,
-                                                          constructor,
-                                                          compiledArguments));
-      if (!succeeded) {
-        // Non-matching super and redirects are compile-time errors and thus
-        // checked by the resolver.
-        compiler.internalError(
-            "Parameters and arguments didn't match for super/redirect call",
-            element: constructor);
-      }
-
-      ClassElement enclosingClass = constructor.getEnclosingClass();
+                             FunctionElement caller) {
+    callee = callee.implementation;
+    compiler.withCurrentElement(callee, () {
+      constructors.add(callee);
+      ClassElement enclosingClass = callee.getEnclosingClass();
       if (backend.classNeedsRti(enclosingClass)) {
         // If [enclosingClass] needs RTI, we have to give a value to its
         // type parameters.
-        ClassElement currentClass = inlinedFromElement.getEnclosingClass();
+        ClassElement currentClass = caller.getEnclosingClass();
         // For a super constructor call, the type is the supertype of
         // [currentClass]. For a redirecting constructor, the type is
         // the current type. [InterfaceType.asInstanceOf] takes care
@@ -1384,8 +1368,9 @@
         InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass);
         Link<DartType> typeVariables = enclosingClass.typeVariables;
         type.typeArguments.forEach((DartType argument) {
-          localsHandler.updateLocal(typeVariables.head.element,
-              analyzeTypeArgument(argument, callNode));
+          localsHandler.updateLocal(
+              typeVariables.head.element,
+              analyzeTypeArgument(argument));
           typeVariables = typeVariables.tail;
         });
         // If the supertype is a raw type, we need to set to null the
@@ -1399,13 +1384,13 @@
         }
       }
 
-      inlinedFrom(constructor, () {
-        buildFieldInitializers(constructor.enclosingElement.implementation,
+      inlinedFrom(callee, () {
+        buildFieldInitializers(callee.enclosingElement.implementation,
                                fieldValues);
       });
 
       int index = 0;
-      FunctionSignature params = constructor.computeSignature(compiler);
+      FunctionSignature params = callee.computeSignature(compiler);
       params.orderedForEachParameter((Element parameter) {
         HInstruction argument = compiledArguments[index++];
         // Because we are inlining the initializer, we must update
@@ -1423,19 +1408,15 @@
 
       // Build the initializers in the context of the new constructor.
       TreeElements oldElements = elements;
-      if (constructor.isForwardingConstructor) {
-        constructor = constructor.targetConstructor;
-      }
-      elements =
-          compiler.enqueuer.resolution.getCachedElements(constructor);
+      elements = compiler.enqueuer.resolution.getCachedElements(callee);
       ClosureClassMap oldClosureData = localsHandler.closureData;
-      Node node = constructor.parseNode(compiler);
+      Node node = callee.parseNode(compiler);
       ClosureClassMap newClosureData =
           compiler.closureToClassMapper.computeClosureToClassMapping(
-              constructor, node, elements);
+              callee, node, elements);
       localsHandler.closureData = newClosureData;
-      localsHandler.enterScope(node, constructor);
-      buildInitializers(constructor, constructors, fieldValues);
+      localsHandler.enterScope(node, callee);
+      buildInitializers(callee, constructors, fieldValues);
       localsHandler.closureData = oldClosureData;
       elements = oldElements;
     });
@@ -1455,30 +1436,56 @@
                          List<FunctionElement> constructors,
                          Map<Element, HInstruction> fieldValues) {
     assert(invariant(constructor, constructor.isImplementation));
+    if (constructor.isSynthesized) {
+      List<HInstruction> arguments = <HInstruction>[];
+      HInstruction compileArgument(Element element) {
+        return localsHandler.readLocal(element);
+      }
+
+      Element target = constructor.targetConstructor.implementation;
+      Selector.addForwardingElementArgumentsToList(
+          constructor, 
+          arguments,
+          target,
+          compileArgument,
+          handleConstantForOptionalParameter,
+          compiler);
+      inlineSuperOrRedirect(
+          target,
+          arguments,
+          constructors,
+          fieldValues,
+          constructor);
+      return;
+    }
     FunctionExpression functionNode = constructor.parseNode(compiler);
 
     bool foundSuperOrRedirect = false;
-
     if (functionNode.initializers != null) {
       Link<Node> initializers = functionNode.initializers.nodes;
       for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) {
         assert(link.head is Send);
         if (link.head is !SendSet) {
           // A super initializer or constructor redirection.
+          foundSuperOrRedirect = true;
           Send call = link.head;
           assert(Initializers.isSuperConstructorCall(call) ||
                  Initializers.isConstructorRedirect(call));
-          FunctionElement target = elements[call];
+          FunctionElement target = elements[call].implementation;
           Selector selector = elements.getSelector(call);
           Link<Node> arguments = call.arguments;
+          List<HInstruction> compiledArguments = new List<HInstruction>();
+          inlinedFrom(constructor, () {
+            addStaticSendArgumentsToList(selector,
+                                         arguments,
+                                         target,
+                                         compiledArguments);
+          });
           inlineSuperOrRedirect(target,
-                                selector,
-                                arguments,
+                                compiledArguments,
                                 constructors,
                                 fieldValues,
-                                constructor,
-                                call);
-          foundSuperOrRedirect = true;
+                                constructor);
         } else {
           // A field initializer.
           SendSet init = link.head;
@@ -1507,13 +1514,18 @@
         if (target == null) {
           compiler.internalError("no default constructor available");
         }
+        List<HInstruction> arguments = <HInstruction>[];
+        selector.addArgumentsToList(const Link<Node>(),
+                                    arguments,
+                                    target.implementation,
+                                    null,
+                                    handleConstantForOptionalParameter,
+                                    compiler);
         inlineSuperOrRedirect(target,
-                              selector,
-                              const Link<Node>(),
+                              arguments,
                               constructors,
                               fieldValues,
-                              constructor,
-                              functionNode);
+                              constructor);
       }
     }
   }
@@ -2914,10 +2926,6 @@
       return pop();
     }
 
-    if (element.isForwardingConstructor) {
-      element = element.targetConstructor;
-    }
-
     return selector.addArgumentsToList(arguments,
                                        list,
                                        element,
@@ -3371,8 +3379,8 @@
    *
    * Invariant: [argument] must not be malformed in checked mode.
    */
-  HInstruction analyzeTypeArgument(DartType argument, Node currentNode) {
-    assert(invariant(currentNode,
+  HInstruction analyzeTypeArgument(DartType argument) {
+    assert(invariant(currentElement,
                      !compiler.enableTypeAssertions || !argument.isMalformed,
                      message: '$argument is malformed in checked mode'));
     if (argument == compiler.types.dynamicType || argument.isMalformed) {
@@ -3398,7 +3406,7 @@
     if (!type.isRaw) {
       List<HInstruction> inputs = <HInstruction>[];
       type.typeArguments.forEach((DartType argument) {
-        inputs.add(analyzeTypeArgument(argument, currentNode));
+        inputs.add(analyzeTypeArgument(argument));
       });
       callSetRuntimeTypeInfo(type.element, inputs, newObject);
     }
@@ -3461,13 +3469,6 @@
 
     Element constructor = elements[send];
     Selector selector = elements.getSelector(send);
-    if (constructor.isForwardingConstructor) {
-      compiler.unimplemented('forwarded constructor in named mixin application',
-                             element: constructor.getEnclosingClass());
-    }
-    if (compiler.enqueuer.resolution.getCachedElements(constructor) == null) {
-      compiler.internalError("Unresolved element: $constructor", node: send);
-    }
     FunctionElement functionElement = constructor;
     constructor = functionElement.redirectionTarget;
 
@@ -3508,7 +3509,7 @@
     if (backend.classNeedsRti(cls)) {
       Link<DartType> typeVariable = cls.typeVariables;
       type.typeArguments.forEach((DartType argument) {
-        inputs.add(analyzeTypeArgument(argument, send));
+        inputs.add(analyzeTypeArgument(argument));
         typeVariable = typeVariable.tail;
       });
       // Also add null to non-provided type variables to call the
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index e522e72..496c2e4 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -18,21 +18,28 @@
   js.Fun buildJavaScriptFunction(FunctionElement element,
                                  List<js.Parameter> parameters,
                                  js.Block body) {
-    FunctionExpression expression =
-        element.implementation.parseNode(backend.compiler);
     js.Fun result = new js.Fun(parameters, body);
     // TODO(johnniwinther): remove the 'element.patch' hack.
     Element sourceElement = element.patch == null ? element : element.patch;
     SourceFile sourceFile = sourceElement.getCompilationUnit().script.file;
+    Node expression =
+        element.implementation.parseNode(backend.compiler);
+    Token beginToken;
+    Token endToken;
+    if (expression == null) {
+      // Synthesized node. Use the enclosing element for the location.
+      beginToken = endToken = element.position();
+    } else {
+      beginToken = expression.getBeginToken();
+      endToken = expression.getEndToken();
+    }
     // TODO(podivilov): find the right sourceFile here and remove offset checks
     // below.
-    if (expression.getBeginToken().charOffset < sourceFile.text.length) {
-      result.sourcePosition = new SourceFileLocation(
-          sourceFile, expression.getBeginToken());
+    if (beginToken.charOffset < sourceFile.text.length) {
+      result.sourcePosition = new SourceFileLocation(sourceFile, beginToken);
     }
-    if (expression.getEndToken().charOffset < sourceFile.text.length) {
-      result.endSourcePosition = new SourceFileLocation(
-          sourceFile, expression.getEndToken());
+    if (endToken.charOffset < sourceFile.text.length) {
+      result.endSourcePosition = new SourceFileLocation(sourceFile, endToken);
     }
     return result;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index f8ef54e..44ef282 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -620,26 +620,28 @@
   }
 
   HInstruction visitFieldGet(HFieldGet node) {
+    var receiver = node.receiver;
     if (node.element == backend.jsIndexableLength) {
-      if (node.receiver is HInvokeStatic) {
+      if (receiver is HInvokeStatic) {
         // Try to recognize the length getter with input
         // [:new List(int):].
-        HInvokeStatic call = node.receiver;
-        Element element = call.element;
+        Element element = receiver.element;
         // TODO(ngeoffray): checking if the second input is an integer
         // should not be necessary but it currently makes it easier for
         // other optimizations to reason about a fixed length constructor
         // that we know takes an int.
         if (element == compiler.unnamedListConstructor
-            && call.inputs.length == 1
-            && call.inputs[0].isInteger()) {
-          return call.inputs[0];
+            && receiver.inputs.length == 1
+            && receiver.inputs[0].isInteger()) {
+          return receiver.inputs[0];
         }
-      } else if (node.receiver.isConstantList() ||
-                 node.receiver.isConstantString()) {
-        var instruction = node.receiver;
-        return graph.addConstantInt(
-            instruction.constant.length, compiler);
+      } else if (receiver.isConstantList() || receiver.isConstantString()) {
+        return graph.addConstantInt(receiver.constant.length, compiler);
+      } else {
+        var type = receiver.instructionType.computeMask(compiler);
+        if (type.isContainer && type.length != null) {
+          return graph.addConstantInt(type.length, compiler);
+        }
       }
     }
     return 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 dd1935b..7b016b8 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -1365,7 +1365,7 @@
     });
 
     // handle initializing formals
-    element.functionSignature.forEachParameter((param) {
+    element.computeSignature(compiler).forEachParameter((param) {
       if (param.kind == ElementKind.FIELD_PARAMETER) {
         FieldParameterElement fieldParam = param;
         augmentFieldType(fieldParam.fieldElement,
@@ -1383,7 +1383,7 @@
         new TypeInferrerVisitor(elements, element, this, environment);
 
     bool foundSuperOrRedirect = false;
-    if (tree.initializers != null) {
+    if (tree != null && tree.initializers != null) {
       // we look for a possible call to super in the initializer list
       for (final init in tree.initializers) {
         init.accept(visitor);
@@ -1416,7 +1416,7 @@
       }
     }
 
-    tree.accept(visitor);
+    if (tree != null) tree.accept(visitor);
     return singletonConcreteType(new ClassBaseType(enclosingClass));
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
index 92f69e7..156042e 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
@@ -79,6 +79,60 @@
     'checkGrowable',
   ]);
 
+Set<String> doNotChangeLengthSelectorsSet = new Set<String>.from(
+  const <String>[
+    // From Object.
+    '==',
+    'hashCode',
+    'toString',
+    'noSuchMethod',
+    'runtimeType',
+
+    // From Iterable.
+    'iterator',
+    'map',
+    'where',
+    'expand',
+    'contains',
+    'forEach',
+    'reduce',
+    'fold',
+    'every',
+    'join',
+    'any',
+    'toList',
+    'toSet',
+    'length',
+    'isEmpty',
+    'isNotEmpty',
+    'take',
+    'takeWhile',
+    'skip',
+    'skipWhile',
+    'first',
+    'last',
+    'single',
+    'firstWhere',
+    'lastWhere',
+    'singleWhere',
+    'elementAt',
+
+    // From List.
+    '[]',
+    'length',
+    'reversed',
+    'sort',
+    'indexOf',
+    'lastIndexOf',
+    'sublist',
+    'getRange',
+    'asMap',
+
+    // From JSArray.
+    'checkMutable',
+    'checkGrowable',
+  ]);
+
 bool _VERBOSE = false;
 
 /**
@@ -98,8 +152,7 @@
       internal.concreteTypes.values.forEach((ContainerTypeMask mask) {
         // The element type has already been set for const containers.
         if (mask.elementType != null) return;
-        mask.elementType = new TracerForConcreteContainer(
-            mask, this, compiler, inferrer).run();
+        new TracerForConcreteContainer(mask, this, compiler, inferrer).run();
       });
     });
   }
@@ -112,6 +165,7 @@
   final Compiler compiler;
   final ContainerTracer tracer;
   final SimpleTypesInferrer inferrer;
+  final ContainerTypeMask mask;
 
   final Node analyzedNode;
   final Element startElement;
@@ -138,6 +192,8 @@
   static const int MAX_ANALYSIS_COUNT = 11;
 
   TypeMask potentialType;
+  int potentialLength;
+  bool isLengthTrackingDisabled = false;
   bool continueAnalyzing = true;
 
   TracerForConcreteContainer(ContainerTypeMask mask,
@@ -145,9 +201,10 @@
                              this.compiler,
                              this.inferrer)
       : analyzedNode = mask.allocationNode,
-        startElement = mask.allocationElement;
+        startElement = mask.allocationElement,
+        this.mask = mask;
 
-  TypeMask run() {
+  void run() {
     int analysisCount = 0;
     workList.add(startElement);
     while (!workList.isEmpty) {
@@ -161,11 +218,20 @@
       analysisCount++;
     }
 
-    if (!continueAnalyzing) return compiler.typesTask.dynamicType;
+    if (!continueAnalyzing) {
+      if (mask.forwardTo == compiler.typesTask.fixedListType) {
+        mask.length = potentialLength;
+      }
+      mask.elementType = compiler.typesTask.dynamicType;
+      return;
+    }
 
     // [potentialType] can be null if we did not find any instruction
     // that adds elements to the list.
-    if (potentialType == null) return new TypeMask.nonNullEmpty();
+    if (potentialType == null) {
+      mask.elementType = new TypeMask.nonNullEmpty();
+      return;
+    }
 
     // Walk over the found constraints and update the type according
     // to the selectors of these constraints.
@@ -176,11 +242,26 @@
           inferrer.getTypeOfSelector(constraint), compiler);
     }
     if (_VERBOSE) {
-      print('$potentialType for $analyzedNode $startElement');
+      print('$potentialType and $potentialLength '
+            'for $analyzedNode $startElement');
     }
-    return potentialType;
+    mask.elementType = potentialType;
+    mask.length = potentialLength;
   }
 
+  void disableLengthTracking() {
+    if (mask.forwardTo == compiler.typesTask.fixedListType) {
+      // Bogus update to a fixed list.
+      return;
+    }
+    isLengthTrackingDisabled = true;
+    potentialLength = null;
+  }
+
+  void setPotentialLength(int value) {
+    if (isLengthTrackingDisabled) return;
+    potentialLength = value;
+  }
 
   void unionPotentialTypeWith(TypeMask newType) {
     assert(newType != null);
@@ -360,12 +441,17 @@
   }
 
   TypeMask visitLiteralList(LiteralList node) {
-    if (node.isConst()) return compiler.typesTask.constListType;
+    if (node.isConst()) {
+      return inferrer.internal.concreteTypes[node];
+    }
     if (tracer.couldBeTheList(node)) {
       escaping = true;
+      int length = 0;
       for (Node element in node.elements.nodes) {
         tracer.unionPotentialTypeWith(visit(element));
+        length++;
       }
+      tracer.setPotentialLength(length);
     } else {
       node.visitChildren(this);
     }
@@ -465,7 +551,7 @@
       }
     } else if (isReceiver) {
       if (setterSelector.name == const SourceString('length')) {
-        // Changing the length.
+        tracer.disableLengthTracking();
         tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
       }
     } else if (isValueEscaping) {
@@ -532,24 +618,32 @@
       if (tracer.couldBeTheList(node)) {
         escaping = true;
       }
-      return compiler.typesTask.growableListType;
+      return inferrer.internal.concreteTypes[node];
     } else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
-      tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
       visitArguments(node.arguments, element);
       if (tracer.couldBeTheList(node)) {
+        tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
         escaping = true;
+        LiteralInt length = node.arguments.head.asLiteralInt();
+        if (length != null) {
+          tracer.setPotentialLength(length.value);
+        }
       }
-      return compiler.typesTask.fixedListType;
+      return inferrer.internal.concreteTypes[node];
     } else if (Elements.isFilledListConstructorCall(element, node, compiler)) {
       if (tracer.couldBeTheList(node)) {
         escaping = true;
         visit(node.arguments.head);
         TypeMask fillWithType = visit(node.arguments.tail.head);
         tracer.unionPotentialTypeWith(fillWithType);
+        LiteralInt length = node.arguments.head.asLiteralInt();
+        if (length != null) {
+          tracer.setPotentialLength(length.value);
+        }
       } else {
         visitArguments(node.arguments, element);
       }
-      return compiler.typesTask.fixedListType;
+      return inferrer.internal.concreteTypes[node];
     }
 
     bool isEscaping = visitArguments(node.arguments, element);
@@ -639,6 +733,9 @@
     } else if (!node.isPropertyAccess) {
       visitArguments(node.arguments, selector);
     }
+    if (isReceiver && !doNotChangeLengthSelectorsSet.contains(selectorName)) {
+      tracer.disableLengthTracking();
+    }
     if (tracer.couldBeTheList(selector)) {
       escaping = true;
     }
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
index f9fc659..79281c0 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
@@ -8,8 +8,9 @@
 /// that nullable ContainerTypeMask and non-nullable ContainerTypeMask
 /// share the same [ElementTypeHolder].
 class ElementTypeHolder {
-  // This field will be set after global analysis.
+  // These fields will be set after global analysis.
   TypeMask elementType;
+  int length;
 
   int get hashCode => elementType.hashCode;
 }
@@ -36,6 +37,10 @@
   void set elementType(TypeMask mask) {
     holder.elementType = mask;
   }
+  int get length => holder.length;
+  void set length(int length) {
+    holder.length = length;
+  }
 
   ContainerTypeMask(this.forwardTo,
                     this.allocationNode,
diff --git a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
index eb82a47..d357a35 100644
--- a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
@@ -52,12 +52,73 @@
 }
 
 /**
+ * A variable scope holds types for variables. It has a link to a
+ * parent scope, but never changes the types in that parent. Instead,
+ * updates to locals of a parent scope are put in the current scope.
+ * The inferrer makes sure updates get merged into the parent scope,
+ * once the control flow block has been visited.
+ */
+class VariableScope {
+  Map<Element, TypeMask> variables;
+
+  /// The parent of this scope. Null for the root scope.
+  final VariableScope parent;
+
+  /// The block level of this scope. Starts at 0 for the root scope.
+  final int blockLevel;
+
+  VariableScope([parent])
+      : this.variables = null,
+        this.parent = parent,
+        this.blockLevel = parent == null ? 0 : parent.blockLevel + 1;
+
+  VariableScope.deepCopyOf(VariableScope other)
+      : variables = other.variables == null
+            ? null
+            : new Map<Element, TypeMask>.from(other.variables),
+        blockLevel = other.blockLevel,
+        parent = other.parent == null
+            ? null
+            : new VariableScope.deepCopyOf(other.parent);
+
+  TypeMask operator [](Element variable) {
+    TypeMask result;
+    if (variables == null || (result = variables[variable]) == null) {
+      return parent == null ? null : parent[variable];
+    }
+    return result;
+  }
+
+  void operator []=(Element variable, TypeMask mask) {
+    assert(mask != null);
+    if (variables == null) {
+      variables = new Map<Element, TypeMask>();
+    }
+    variables[variable] = mask;
+  }
+
+  void forEachOwnLocal(void f(Element element, TypeMask mask)) {
+    if (variables == null) return;
+    variables.forEach(f);
+  }
+
+  void remove(Element element) {
+    variables.remove(element);
+  }
+
+  String toString() {
+    String rest = parent == null ? "null" : parent.toString();
+    return '$blockLevel: $variables $rest';
+  }
+}
+
+/**
  * Placeholder for inferred types of local variables.
  */
 class LocalsHandler {
   final Compiler compiler;
   final TypesInferrer inferrer;
-  final Map<Element, TypeMask> locals;
+  final VariableScope locals;
   final Map<Element, Element> capturedAndBoxed;
   final Map<Element, TypeMask> fieldsInitializedInConstructor;
   final bool inTryBlock;
@@ -70,13 +131,14 @@
   }
 
   LocalsHandler(this.inferrer, this.compiler)
-      : locals = new Map<Element, TypeMask>(),
+      : locals = new VariableScope(),
         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),
+      : locals = new VariableScope(other.locals),
         capturedAndBoxed = new Map<Element, Element>.from(
             other.capturedAndBoxed),
         fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
@@ -86,6 +148,17 @@
         compiler = other.compiler,
         isThisExposed = other.isThisExposed;
 
+  LocalsHandler.deepCopyOf(LocalsHandler other)
+      : locals = new VariableScope.deepCopyOf(other.locals),
+        capturedAndBoxed = new Map<Element, Element>.from(
+            other.capturedAndBoxed),
+        fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
+            other.fieldsInitializedInConstructor),
+        inTryBlock = other.inTryBlock,
+        inferrer = other.inferrer,
+        compiler = other.compiler,
+        isThisExposed = other.isThisExposed;
+
   TypeMask use(Element local) {
     if (capturedAndBoxed.containsKey(local)) {
       return inferrer.getTypeOfElement(capturedAndBoxed[local]);
@@ -119,31 +192,43 @@
    * whether the merge changed one of the variables types in [first].
    */
   bool merge(LocalsHandler other, {bool discardIfAborts: true}) {
+    VariableScope currentOther = other.locals;
+    assert(currentOther != locals);
     bool changed = false;
-    List<Element> toRemove = <Element>[];
-    // Iterating over a map and just updating its entries is OK.
-    locals.forEach((Element local, TypeMask oldType) {
-      TypeMask otherType = other.locals[local];
-      bool isCaptured = capturedAndBoxed.containsKey(local);
-      if (otherType == null) {
-        if (!isCaptured) {
-          // If [local] is not in the other map and is not captured
-          // and boxed, we know it is not a
-          // local we want to keep. For example, in an if/else, we don't
-          // want to keep variables declared in the if or in the else
-          // branch at the merge point.
-          toRemove.add(local);
+    // Iterate over all updates in the other handler until we reach
+    // the block level of this handler. We know that [VariableScope]s
+    // that are lower in block level, are the same.
+    do {
+      currentOther.forEachOwnLocal((Element local, TypeMask otherType) {
+        TypeMask myType = locals[local];
+        if (myType == null) return;
+        bool isCaptured = capturedAndBoxed.containsKey(local);
+        if (!isCaptured && aborts && discardIfAborts) {
+          locals[local] = otherType;
+        } else if (!isCaptured && other.aborts && discardIfAborts) {
+          // Don't do anything.
+        } else {
+          TypeMask type = computeLUB(myType, otherType, compiler);
+          if (type != myType) {
+            changed = true;
+          }
+          locals[local] = type;
         }
-        return;
-      }
-      if (!isCaptured && aborts && discardIfAborts) {
-        locals[local] = otherType;
-      } else if (!isCaptured && other.aborts && discardIfAborts) {
-        // Don't do anything.
-      } else {
-        TypeMask type = computeLUB(oldType, otherType, compiler);
-        if (type != oldType) changed = true;
-        locals[local] = type;
+      });
+      currentOther = currentOther.parent;
+    } while (currentOther != null
+             && currentOther.blockLevel >= locals.blockLevel);
+
+    List<Element> toRemove = <Element>[];
+    locals.forEachOwnLocal((Element local, _) {
+      bool isCaptured = capturedAndBoxed.containsKey(local);
+      if (other.locals[local] == null && !isCaptured) {
+        // If [local] is not in the other map and is not captured
+        // and boxed, we know it is not a
+        // local we want to keep. For example, in an if/else, we don't
+        // want to keep variables declared in the if or in the else
+        // branch at the merge point.
+        toRemove.add(local);
       }
     });
 
@@ -159,7 +244,7 @@
       capturedAndBoxed[local] =  field;
       // If [element] is not in our [locals], we need to update it.
       // Otherwise, we have already computed the LUB of it.
-      if (locals[local] == null) {
+      if (locals[local] == null && other.locals[local] != null) {
         locals[local] = other.locals[local];
       }
     });
@@ -394,21 +479,25 @@
       visit(node.receiver);
       accumulateIsChecks = oldAccumulateIsChecks;
       if (!accumulateIsChecks) isChecks = null;
-      LocalsHandler saved = new LocalsHandler.from(locals);
+      LocalsHandler saved = locals;
+      locals = new LocalsHandler.from(locals);
       updateIsChecks(isChecks, usePositive: true);
       visit(node.arguments.head);
-      locals.merge(saved);
+      saved.merge(locals);
+      locals = saved;
       return compiler.typesTask.boolType;
     } else if (const SourceString("||") == op.source) {
       conditionIsSimple = false;
       visit(node.receiver);
-      LocalsHandler saved = new LocalsHandler.from(locals);
+      LocalsHandler saved = locals;
+      locals = new LocalsHandler.from(locals);
       updateIsChecks(isChecks, usePositive: false);
       bool oldAccumulateIsChecks = accumulateIsChecks;
       accumulateIsChecks = false;
       visit(node.arguments.head);
       accumulateIsChecks = oldAccumulateIsChecks;
-      locals.merge(saved);
+      saved.merge(locals);
+      locals = saved;
       return compiler.typesTask.boolType;
     } else if (const SourceString("!") == op.source) {
       bool oldAccumulateIsChecks = accumulateIsChecks;
@@ -446,7 +535,8 @@
   TypeMask visitConditional(Conditional node) {
     List<Send> tests = <Send>[];
     bool simpleCondition = handleCondition(node.condition, tests);
-    LocalsHandler saved = new LocalsHandler.from(locals);
+    LocalsHandler saved = locals;
+    locals = new LocalsHandler.from(locals);
     updateIsChecks(tests, usePositive: true);
     TypeMask firstType = visit(node.thenExpression);
     LocalsHandler thenLocals = locals;
@@ -491,7 +581,8 @@
   TypeMask visitIf(If node) {
     List<Send> tests = <Send>[];
     bool simpleCondition = handleCondition(node.condition, tests);
-    LocalsHandler saved = new LocalsHandler.from(locals);
+    LocalsHandler saved = locals;
+    locals = new LocalsHandler.from(locals);
     updateIsChecks(tests, usePositive: true);
     visit(node.thenPart);
     LocalsHandler thenLocals = locals;
@@ -537,7 +628,8 @@
     TargetElement target = elements[node];
     setupBreaksAndContinues(target);
     do {
-      LocalsHandler saved = new LocalsHandler.from(locals);
+      LocalsHandler saved = locals;
+      locals = new LocalsHandler.from(locals);
       logic();
       changed = saved.merge(locals);
       locals = saved;
@@ -585,7 +677,8 @@
     saved.merge(locals);
     locals = saved;
     for (Node catchBlock in node.catchBlocks) {
-      saved = new LocalsHandler.from(locals);
+      saved = locals;
+      locals = new LocalsHandler.from(locals);
       visit(catchBlock);
       saved.merge(locals);
       locals = saved;
@@ -651,15 +744,19 @@
 
   TypeMask visitBreakStatement(BreakStatement node) {
     TargetElement target = elements[node];
-    breaksFor[target].add(locals);
     locals.seenBreakOrContinue = true;
+    // Do a deep-copy of the locals, because the code following the
+    // break will change them.
+    breaksFor[target].add(new LocalsHandler.deepCopyOf(locals));
     return compiler.typesTask.dynamicType;
   }
 
   TypeMask visitContinueStatement(ContinueStatement node) {
     TargetElement target = elements[node];
-    continuesFor[target].add(locals);
     locals.seenBreakOrContinue = true;
+    // Do a deep-copy of the locals, because the code following the
+    // continue will change them.
+    continuesFor[target].add(new LocalsHandler.deepCopyOf(locals));
     return compiler.typesTask.dynamicType;
   }
 
@@ -695,7 +792,8 @@
       do {
         changed = false;
         for (Node switchCase in node.cases) {
-          LocalsHandler saved = new LocalsHandler.from(locals);
+          LocalsHandler saved = locals;
+          locals = new LocalsHandler.from(locals);
           visit(switchCase);
           changed = saved.merge(locals, discardIfAborts: false) || changed;
           locals = saved;
@@ -706,24 +804,26 @@
         clearBreaksAndContinues(target);
       });
     } else {
-      LocalsHandler saved = new LocalsHandler.from(locals);
-      // If there is a default case, the current values of the local
-      // variable might be overwritten, so we don't need the current
-      // [locals] for the join block.
-      LocalsHandler result = Elements.switchStatementHasDefault(node)
-          ? null
-          : new LocalsHandler.from(locals);
+      LocalsHandler saved = locals;
+      List<LocalsHandler> localsToMerge = <LocalsHandler>[];
 
-      for (Node switchCase in node.cases) {
-        locals = new LocalsHandler.from(saved);
-        visit(switchCase);
-        if (result == null) {
-          result = locals;
+      for (SwitchCase switchCase in node.cases) {
+        if (switchCase.isDefaultCase) {
+          // If there is a default case, the current values of the local
+          // variable might be overwritten, so we don't need the current
+          // [locals] for the join block.
+          locals = saved;
+          visit(switchCase);
         } else {
-          result.merge(locals, discardIfAborts: false);
+          locals = new LocalsHandler.from(saved);
+          visit(switchCase);
+          localsToMerge.add(locals);
         }
       }
-      locals = result;
+      for (LocalsHandler handler in localsToMerge) {
+        saved.merge(handler, discardIfAborts: false);
+      }
+      locals = saved;
     }
     clearBreaksAndContinues(elements[node]);
     // In case there is a default in the switch we discard the
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 6b49b54..2a0c230 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -571,9 +571,6 @@
   }
 
   bool analyze(Element element) {
-    if (element.isForwardingConstructor) {
-      element = element.targetConstructor;
-    }
     SimpleTypeInferrerVisitor visitor =
         new SimpleTypeInferrerVisitor(element, compiler, this);
     TypeMask returnType = visitor.run();
@@ -1439,10 +1436,16 @@
           locals.update(element, parameterType);
         }
       });
-      visitingInitializers = true;
-      visit(node.initializers);
-      visitingInitializers = false;
-      visit(node.body);
+      if (analyzedElement.isSynthesized) {
+        // Use the enclosing class of the synthesized constructor as
+        // the location for the initialized fields.
+        node = analyzedElement.enclosingElement.parseNode(compiler);
+      } else {
+        visitingInitializers = true;
+        visit(node.initializers);
+        visitingInitializers = false;
+        visit(node.body);
+      }
       ClassElement cls = analyzedElement.getEnclosingClass();
       if (!isConstructorRedirect) {
         // Iterate over all instance fields, and give a null type to
@@ -1540,10 +1543,13 @@
         ContainerTypeMask container = new ContainerTypeMask(
             inferrer.constListType, node, outermostElement);
         TypeMask elementType = new TypeMask.nonNullEmpty();
+        int length = 0;
         for (Node element in node.elements.nodes) {
+          length++;
           elementType = computeLUB(elementType, visit(element), compiler);
         }
         container.elementType = elementType;
+        container.length = length;
         return container;
       });
     } else {
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index db18031..5f76676 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -376,7 +376,7 @@
    * of an argument located in [arguments].
    *
    * [compileConstant] is a function that returns a compiled constant
-   * of an optional argument that is not in [arguments.
+   * of an optional argument that is not in [arguments].
    *
    * Returns [:true:] if the selector and the [element] match; [:false:]
    * otherwise.
@@ -429,6 +429,79 @@
     return true;
   }
 
+  /**
+   * Fills [list] with the arguments in the order expected by
+   * [callee], and where [caller] is a synthesized element
+   *
+   * [compileArgument] is a function that returns a compiled version
+   * of a parameter of [callee].
+   *
+   * [compileConstant] is a function that returns a compiled constant
+   * of an optional argument that is not in the parameters of [callee].
+   *
+   * Returns [:true:] if the signature of the [caller] matches the
+   * signature of the [callee], [:false:] otherwise.
+   */
+  static bool addForwardingElementArgumentsToList(
+      FunctionElement caller,
+      List list,
+      FunctionElement callee,
+      compileArgument(Element element),
+      compileConstant(Element element),
+      Compiler compiler) {
+
+    FunctionSignature signature = caller.computeSignature(compiler);
+    Map mapping = new Map();
+
+    // TODO(ngeoffray): This is a hack that fakes up AST nodes, so
+    // that we can call [addArgumentsToList].
+    Link computeCallNodesFromParameters() {
+      LinkBuilder builder = new LinkBuilder();
+      signature.forEachRequiredParameter((Element element) {
+        Node node = element.parseNode(compiler);
+        mapping[node] = element;
+        builder.addLast(node);
+      });
+      if (signature.optionalParametersAreNamed) {
+        signature.forEachOptionalParameter((Element element) {
+          Node node = element.parseNode(compiler);
+          mapping[node] = element;
+          builder.addLast(new NamedArgument(null, null, node));
+        });
+      } else {
+        signature.forEachOptionalParameter((Element element) {
+          Node node = element.parseNode(compiler);
+          mapping[node] = element;
+          builder.addLast(node);
+        });
+      }
+      return builder.toLink();
+    }
+
+    internalCompileArgument(Node node) => compileArgument(mapping[node]);
+
+    Link<Node> nodes = computeCallNodesFromParameters();
+
+    // Synthesize a selector for the call.
+    // TODO(ngeoffray): Should the resolver do it instead?
+    List<SourceString> namedParameters;
+    if (signature.optionalParametersAreNamed) {
+      namedParameters =
+          signature.optionalParameters.toList().map((e) => e.name).toList();
+    }
+    Selector selector = new Selector.call(callee.name,
+                                          caller.getLibrary(),
+                                          signature.parameterCount,
+                                          namedParameters);
+
+    return selector.addArgumentsToList(nodes,
+                                       list,
+                                       callee,
+                                       internalCompileArgument,
+                                       compileConstant,
+                                       compiler);
+  }
+
   static bool sameNames(List<SourceString> first, List<SourceString> second) {
     for (int i = 0; i < first.length; i++) {
       if (first[i] != second[i]) return false;
diff --git a/sdk/lib/_internal/lib/core_patch.dart b/sdk/lib/_internal/lib/core_patch.dart
index 7306375..9d44abf 100644
--- a/sdk/lib/_internal/lib/core_patch.dart
+++ b/sdk/lib/_internal/lib/core_patch.dart
@@ -114,13 +114,12 @@
   patch static String _objectToString(Object object) {
     return Primitives.objectToString(object);
   }
-}
 
-patch class StackTraceOnThrow {
-  // TODO(11681): implement stackTrace on thrown Error.
+  // TODO(11681): implement stackTrace in error object.
   patch StackTrace get stackTrace => null;
 }
 
+
 // Patch for DateTime implementation.
 patch class DateTime {
   patch DateTime._internal(int year,
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index 52324fb..32835bf 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -1486,7 +1486,7 @@
 /**
  * Error thrown when a runtime error occurs.
  */
-class RuntimeError extends Error with StackTraceOnThrow {
+class RuntimeError extends Error {
   final message;
   RuntimeError(this.message);
   String toString() => "RuntimeError: $message";
diff --git a/sdk/lib/_internal/pub/lib/src/source/hosted.dart b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
index f65a56a..aec150c 100644
--- a/sdk/lib/_internal/pub/lib/src/source/hosted.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
@@ -31,7 +31,11 @@
   /// Gets the default URL for the package server for hosted dependencies.
   static String get defaultUrl {
     var url = io.Platform.environment["PUB_HOSTED_URL"];
-    if (url != null) return url;
+    if (url != null) {
+      log.fine("Got server $url from PUB_HOSTED_URL.");
+      return url;
+    }
+
     return "https://pub.dartlang.org";
   }
 
diff --git a/sdk/lib/_internal/pub/test/install/switch_source_test.dart b/sdk/lib/_internal/pub/test/install/switch_source_test.dart
index 428292e..6ca3981 100644
--- a/sdk/lib/_internal/pub/test/install/switch_source_test.dart
+++ b/sdk/lib/_internal/pub/test/install/switch_source_test.dart
@@ -12,6 +12,8 @@
 main() {
   initConfig();
   integration('re-installs a package if its source has changed', () {
+    servePackages([packageMap("foo", "1.2.3")]);
+
     d.dir('foo', [
       d.libDir('foo', 'foo 0.0.1'),
       d.libPubspec('foo', '0.0.1')
@@ -22,7 +24,6 @@
     pubInstall();
 
     d.packagesDir({"foo": "0.0.1"}).validate();
-    servePackages([packageMap("foo", "1.2.3")]);
     d.appDir([dependencyMap("foo", "any")]).create();
 
     pubInstall();
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index f1b66b7..5d1afcf 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -91,6 +91,8 @@
 void serve([List<d.Descriptor> contents]) {
   var baseDir = d.dir("serve-dir", contents);
 
+  _hasServer = true;
+
   schedule(() {
     return _closeServer().then((_) {
       return SafeHttpServer.bind("localhost", 0).then((server) {
@@ -144,6 +146,9 @@
   return sleep(10);
 }
 
+/// `true` if the current test spins up an HTTP server.
+bool _hasServer = false;
+
 /// The [d.DirectoryDescriptor] describing the server layout of `/api/packages`
 /// on the test server.
 ///
@@ -458,6 +463,16 @@
       environment['_PUB_TEST_TOKEN_ENDPOINT'] =
         tokenEndpoint.toString();
     }
+
+    // If there is a server running, tell pub what its URL is so hosted
+    // dependencies will look there.
+    if (_hasServer) {
+      return port.then((p) {
+        environment['PUB_HOSTED_URL'] = "http://localhost:$p";
+        return environment;
+      });
+    }
+
     return environment;
   });
 
@@ -609,8 +624,7 @@
 /// Describes a map representing a dependency on a package in the package
 /// repository.
 Map dependencyMap(String name, [String versionConstraint]) {
-  var url = port.then((p) => "http://localhost:$p");
-  var dependency = {"hosted": {"name": name, "url": url}};
+  var dependency = {"hosted": name};
   if (versionConstraint != null) dependency["version"] = versionConstraint;
   return dependency;
 }
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 6f01ce0..f61cdfe 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -5,8 +5,6 @@
 part of dart.core;
 
 class Error {
-  const Error();
-
   /**
    * Safely convert a value to a [String] description.
    *
@@ -33,33 +31,13 @@
 
   external static String _objectToString(Object object);
 
-  /**
-   * The stack trace of `this` error. May be null.
-   */
-  StackTrace get stackTrace => null;
-}
-
-/**
- * Captures the stack trace when thrown.
- */
-class StackTraceOnThrow {
-  /**
-   * Captures the current stack-trace when thrown.
-   *
-   * Classes extending or mixing-in this class will automatically have a stack
-   * trace captured the first time they are thrown. This stack trace is returned
-   * by the [stackTrace] getter.
-   *
-   * Throwing the object again will not cause overwrite the first stack trace,
-   * so bjects that are `StackTraceOnThrow` instances should not be reused.
-   */
   external StackTrace get stackTrace;
 }
 
 /**
  * Error thrown by the runtime system when an assert statement fails.
  */
-class AssertionError extends Error with StackTraceOnThrow {
+class AssertionError extends Error {
 }
 
 /**
@@ -71,13 +49,13 @@
 /**
  * Error thrown by the runtime system when a cast operation fails.
  */
-class CastError extends Error with StackTraceOnThrow {
+class CastError extends Error {
 }
 
 /**
  * Error thrown when attempting to throw [:null:].
  */
-class NullThrownError extends Error with StackTraceOnThrow {
+class NullThrownError extends Error {
   NullThrownError();
   String toString() => "Throw of null.";
 }
@@ -85,7 +63,7 @@
 /**
  * Error thrown when a function is passed an unacceptable argument.
  */
-class ArgumentError extends Error with StackTraceOnThrow {
+class ArgumentError extends Error {
   final message;
 
   /** The [message] describes the erroneous argument. */
@@ -132,12 +110,12 @@
  * of a switch) without meeting a break or similar end of the control
  * flow.
  */
-class FallThroughError extends Error with StackTraceOnThrow {
+class FallThroughError extends Error {
+  FallThroughError();
 }
 
 
-class AbstractClassInstantiationError
-    extends Error with StackTraceOnThrow {
+class AbstractClassInstantiationError extends Error {
   final String _className;
   AbstractClassInstantiationError(String this._className);
   String toString() => "Cannot instantiate abstract class: '$_className'";
@@ -146,7 +124,7 @@
 /**
  * Error thrown by the default implementation of [:noSuchMethod:] on [Object].
  */
-class NoSuchMethodError extends Error with StackTraceOnThrow {
+class NoSuchMethodError extends Error {
   final Object _receiver;
   final String _memberName;
   final List _arguments;
@@ -184,7 +162,7 @@
  * This [Error] is thrown when an instance cannot implement one of the methods
  * in its signature.
  */
-class UnsupportedError extends Error with StackTraceOnThrow {
+class UnsupportedError extends Error {
   final String message;
   UnsupportedError(this.message);
   String toString() => "Unsupported operation: $message";
@@ -201,8 +179,7 @@
  * an [UnsupportedError] instead. This error is only intended for
  * use during development.
  */
-class UnimplementedError
-    extends Error with StackTraceOnThrow implements UnsupportedError {
+class UnimplementedError extends Error implements UnsupportedError {
   final String message;
   UnimplementedError([String this.message]);
   String toString() => (this.message != null
@@ -217,7 +194,7 @@
  * This is a generic error used for a variety of different erroneous
  * actions. The message should be descriptive.
  */
-class StateError extends Error with StackTraceOnThrow {
+class StateError extends Error {
   final String message;
   StateError(this.message);
   String toString() => "Bad state: $message";
@@ -231,7 +208,7 @@
  * ([Iterable] or similar collection of values) should declare which operations
  * are allowed during an iteration.
  */
-class ConcurrentModificationError extends Error with StackTraceOnThrow {
+class ConcurrentModificationError extends Error {
   /** The object that was modified in an incompatible way. */
   final Object modifiedObject;
 
@@ -247,15 +224,19 @@
 }
 
 
-class OutOfMemoryError extends Error {
+class OutOfMemoryError implements Error {
   const OutOfMemoryError();
   String toString() => "Out of Memory";
+
+  StackTrace get stackTrace => null;
 }
 
 
-class StackOverflowError extends Error {
+class StackOverflowError implements Error {
   const StackOverflowError();
   String toString() => "Stack Overflow";
+
+  StackTrace get stackTrace => null;
 }
 
 /**
@@ -265,7 +246,7 @@
  * the first time it is read. If evaluating the initializer expression causes
  * another read of the variable, this error is thrown.
  */
-class CyclicInitializationError extends Error with StackTraceOnThrow {
+class CyclicInitializationError extends Error {
   final String variableName;
   CyclicInitializationError([this.variableName]);
   String toString() => variableName == null
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 1733d9e..2870931 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -63,6 +63,7 @@
 // Workaround for tags like <cite> that lack their own Element subclass --
 // Dart issue 1990.
 class _HTMLElement extends Element native "HTMLElement" {
+  factory _HTMLElement() { throw new UnsupportedError("Not supported"); }
 }
 
 // Support for Send/ReceivePortSync.
diff --git a/sdk/lib/json/json.dart b/sdk/lib/json/json.dart
index 79e5aba..28d3df9 100644
--- a/sdk/lib/json/json.dart
+++ b/sdk/lib/json/json.dart
@@ -16,7 +16,7 @@
  * [cause] field. If the call returns an object that isn't directly
  * serializable, the [cause] will be null.
  */
-class JsonUnsupportedObjectError extends Error with StackTraceOnThrow {
+class JsonUnsupportedObjectError extends Error {
   /** The object that could not be serialized. */
   final unsupportedObject;
   /** The exception thrown by object's [:toJson:] method, if any. */
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 2820b5f..aaea30a 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -89,11 +89,6 @@
 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
-
 # co19 issue #420, 'throw' without exception; deprecated; rethrow should be used
 Language/11_Expressions/08_Throw_A05_t01: fail, OK
 Language/11_Expressions/08_Throw_A05_t02: fail, OK
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index 2df61b1..ec291dd 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -4,7 +4,6 @@
 
 library analyze_api;
 
-import "package:expect/expect.dart";
 import '../../../sdk/lib/_internal/libraries.dart';
 import 'analyze_helper.dart';
 
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index 1171906..d6e1a83 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -160,7 +160,9 @@
   }
   class bool {}
   class String {}
-  class Object {}
+  class Object {
+    Object();
+  }
   class Function {}
   abstract class List<E> {
     factory List([int length]) {}
diff --git a/tests/compiler/dart2js/dart_backend_test.dart b/tests/compiler/dart2js/dart_backend_test.dart
index 112f0fa..aa5a70f 100644
--- a/tests/compiler/dart2js/dart_backend_test.dart
+++ b/tests/compiler/dart2js/dart_backend_test.dart
@@ -14,7 +14,9 @@
 
 const coreLib = r'''
 library corelib;
-class Object {}
+class Object {
+  Object();
+}
 class bool {}
 class num {}
 class int extends num {}
diff --git a/tests/compiler/dart2js/list_tracer2_test.dart b/tests/compiler/dart2js/list_tracer2_test.dart
new file mode 100644
index 0000000..0bc6126
--- /dev/null
+++ b/tests/compiler/dart2js/list_tracer2_test.dart
@@ -0,0 +1,38 @@
+// 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.
+
+// We used to always nullify the element type of a list we are tracing in
+// the presence of a fixed length list constructor call.
+
+import 'package:expect/expect.dart';
+import
+    '../../../sdk/lib/_internal/compiler/implementation/types/types.dart'
+    show ContainerTypeMask, TypeMask;
+
+import 'compiler_helper.dart';
+import 'parser_helper.dart';
+
+
+const String TEST = r'''
+var myList = [42];
+main() {
+  var a = new List(42);
+  return myList[0];
+}
+''';
+
+void main() {
+  Uri uri = new Uri(scheme: 'source');
+  var compiler = compilerFor(TEST, uri);
+  compiler.runCompiler(uri);
+  var typesInferrer = compiler.typesTask.typesInferrer;
+
+  checkType(String name, type) {
+    var element = findElement(compiler, name);
+    ContainerTypeMask mask = typesInferrer.getTypeOfElement(element);
+    Expect.equals(type, mask.elementType.simplify(compiler), name);
+  }
+
+  checkType('myList', compiler.typesTask.intType);
+}
diff --git a/tests/compiler/dart2js/list_tracer_length_test.dart b/tests/compiler/dart2js/list_tracer_length_test.dart
new file mode 100644
index 0000000..2a48ef5
--- /dev/null
+++ b/tests/compiler/dart2js/list_tracer_length_test.dart
@@ -0,0 +1,80 @@
+// 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";
+import 'compiler_helper.dart';
+
+const String TEST1 = r"""
+var a = [42];
+main() {
+  return a[0];
+}
+""";
+
+String TEST2(selectorName, args) {
+  return """
+var a = [42];
+main() {
+  a.$selectorName($args);
+  return a[0];
+}
+""";
+}
+
+const String TEST3 = r"""
+var a = new List(42);
+main() {
+  return a[0];
+}
+""";
+
+const String TEST4 = r"""
+var a = new List(0);
+main() {
+  return a[0];
+}
+""";
+
+const String TEST5 = r"""
+var a = [42];
+main() {
+  a.length = 54;
+  return a[0];
+}
+""";
+
+// Test that the order in which we visit the methods will not bring
+// back a length after it has been disabled.
+const String TEST6 = r"""
+foo(b) {
+  var a = [42];
+  doIt(a);
+  return a[0];
+}
+
+doIt(a) {
+  a.clear();
+  foo(a);
+}
+main() {
+  foo(null);
+}
+""";
+
+void checkRangeError(String test, {bool hasRangeError}) {
+  String generated = compileAll(test);
+  Expect.equals(hasRangeError, generated.contains('ioore'));
+}
+
+main() {
+  checkRangeError(TEST1, hasRangeError: false);
+  checkRangeError(TEST2('insert', 'null, null'), hasRangeError: true);
+  checkRangeError(TEST2('add', 'null'), hasRangeError: true);
+  checkRangeError(TEST2('clear', ''), hasRangeError: true);
+  checkRangeError(TEST2('toString', ''), hasRangeError: false);
+  checkRangeError(TEST3, hasRangeError: false);
+  checkRangeError(TEST4, hasRangeError: true);
+  checkRangeError(TEST5, hasRangeError: true);
+  checkRangeError(TEST6, hasRangeError: true);
+}
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 3510801..cf84f928 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -177,6 +177,7 @@
   class bool {}
   class String implements Pattern {}
   class Object {
+    Object();
     operator ==(other) { return true; }
     get hashCode => throw "Object.hashCode not implemented.";
     String toString() { return null; }
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index 1902d65..c8fc25c 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -75,6 +75,43 @@
   testIndexedOperator();
   testIncrementsAndDecrements();
   testOverrideHashCodeCheck();
+  testSupertypeOrder();
+}
+
+testSupertypeOrder() {
+  MockCompiler compiler = new MockCompiler();
+  compiler.parseScript("""
+class I1 {}
+class I2 {}
+class J1 extends K1 {}
+class J2 implements K2 {}
+class K1 {}
+class K2 {}
+class L1 {}
+class A implements I1, I2 {}
+class B extends A implements J1, J2 {}
+class C extends B implements L1 {}
+""");
+  compiler.resolveStatement("C c;");
+  ClassElement classA = compiler.mainApp.find(buildSourceString("A"));
+  ClassElement classB = compiler.mainApp.find(buildSourceString("B"));
+  ClassElement classC = compiler.mainApp.find(buildSourceString("C"));
+  Expect.equals('[ I2, I1, Object ]', classA.allSupertypes.toString());
+  Expect.equals('[ A, J2, J1, I2, I1, K2, K1, Object ]',
+                classB.allSupertypes.toString());
+  Expect.equals('[ B, L1, A, J2, J1, I2, I1, K2, K1, Object ]',
+                classC.allSupertypes.toString());
+
+ compiler = new MockCompiler();
+  compiler.parseScript("""
+class X<T> {}
+class Foo extends X<Foo> {}
+class Bar extends Foo implements X<Bar> {}
+""");
+  compiler.resolveStatement("Bar bar;");
+  ClassElement classBar = compiler.mainApp.find(buildSourceString("Bar"));
+  Expect.equals('[ Foo, X<Bar>, X<Foo>, Object ]',
+                classBar.allSupertypes.toString());
 }
 
 testTypeVariables() {
@@ -599,9 +636,11 @@
   FunctionElement mainElement = compiler.mainApp.find(MAIN);
   compiler.resolver.resolve(mainElement);
   Expect.equals(0, compiler.warnings.length);
-  Expect.equals(1, compiler.errors.length);
+  Expect.equals(2, compiler.errors.length);
   Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY,
                 compiler.errors[0].message.kind);
+  Expect.equals(MessageKind.CANNOT_FIND_CONSTRUCTOR,
+                compiler.errors[1].message.kind);
 
   compiler = new MockCompiler();
   compiler.parseScript("""abstract class A extends B {}
@@ -643,7 +682,7 @@
   supertypes = aElement.allSupertypes;
   // Object is once per inheritance path, that is from both A and I.
   Expect.equals(<String>['A<int>', 'B<bool, String>', 'I<bool, List<String>>',
-                         'Object', 'Object'].toString(),
+                         'Object'].toString(),
                 asSortedStrings(supertypes).toString());
 
   compiler = new MockCompiler();
diff --git a/tests/compiler/dart2js/size_test.dart b/tests/compiler/dart2js/size_test.dart
index 3d6fd7b..446a6dc 100644
--- a/tests/compiler/dart2js/size_test.dart
+++ b/tests/compiler/dart2js/size_test.dart
@@ -8,7 +8,9 @@
 const String TEST = "main() => [];";
 
 const String DEFAULT_CORELIB_WITH_LIST = r'''
-  class Object {}
+  class Object {
+    Object();
+  }
   class bool {}
   abstract class List {}
   class num {}
diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart
index 1c946ee..001a030 100644
--- a/tests/compiler/dart2js/type_representation_test.dart
+++ b/tests/compiler/dart2js/type_representation_test.dart
@@ -7,6 +7,7 @@
 import 'package:expect/expect.dart';
 import 'type_test_helper.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/js/js.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart'
        show Element, ClassElement;
 import '../../../sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart'
@@ -34,12 +35,24 @@
 
   TypeRepresentationGenerator typeRepresentation =
       new TypeRepresentationGenerator(env.compiler);
-  String onVariable(TypeVariableType type) => type.name.slowToString();
+
+  Expression onVariable(TypeVariableType variable) {
+    return new VariableUse(variable.name.slowToString());
+  }
+
+  String stringify(Expression expression) {
+    return prettyPrint(expression, env.compiler).buffer.toString();
+  }
 
   void expect(String expectedRepresentation, DartType type) {
-    String foundRepresentation =
+    Expression expression =
         typeRepresentation.getTypeRepresentation(type, onVariable);
-    Expect.stringEquals(expectedRepresentation, foundRepresentation);
+    Expect.stringEquals(expectedRepresentation, stringify(expression));
+  }
+
+  String getJsName(ClassElement cls) {
+    Expression name = typeRepresentation.getJavaScriptClassName(cls);
+    return stringify(name);
   }
 
   JavaScriptBackend backend = env.compiler.backend;
@@ -62,15 +75,15 @@
   DartType dynamic_ = env['dynamic'];
   DartType Typedef_ = env['Typedef'];
 
-  String List_rep = typeRepresentation.getJsName(List_);
-  String List_E_rep = onVariable(List_E);
-  String Map_rep = typeRepresentation.getJsName(Map_);
-  String Map_K_rep = onVariable(Map_K);
-  String Map_V_rep = onVariable(Map_V);
+  String List_rep = getJsName(List_);
+  String List_E_rep = stringify(onVariable(List_E));
+  String Map_rep = getJsName(Map_);
+  String Map_K_rep = stringify(onVariable(Map_K));
+  String Map_V_rep = stringify(onVariable(Map_V));
 
-  String Object_rep = typeRepresentation.getJsName(Object_.element);
-  String int_rep = typeRepresentation.getJsName(int_.element);
-  String String_rep = typeRepresentation.getJsName(String_.element);
+  String Object_rep = getJsName(Object_.element);
+  String int_rep = getJsName(int_.element);
+  String String_rep = getJsName(String_.element);
 
   expect('$int_rep', int_);
   expect('$String_rep', String_);
diff --git a/tests/compiler/dart2js/value_range_test.dart b/tests/compiler/dart2js/value_range_test.dart
index 940b615..eff5ad8 100644
--- a/tests/compiler/dart2js/value_range_test.dart
+++ b/tests/compiler/dart2js/value_range_test.dart
@@ -209,7 +209,9 @@
   abstract class double extends num { }
   class bool {}
   class String {}
-  class Object {}
+  class Object {
+    Object();
+  }
   class Type {}
   class Function {}
   class List {
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index dc665bb..2a81416 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -8,7 +8,6 @@
 typed_locals_test: Fail
 no_such_method_test: Fail # Wrong Invocation.memberName.
 
-deferred_semantics_test/none: Fail # TODO(ahe): Multitest cannot use import.
 constant_javascript_semantics4_test: Fail, OK
 
 [ $runtime == ff || $jscl ]
diff --git a/tests/html/html.status b/tests/html/html.status
index 5a76fb9..4852e32 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -50,6 +50,9 @@
 
 touchevent_test/supported: Fail
 
+xhr_test: Pass, Fail # Issue 11884
+xhr_cross_origin_test: Pass, Fail # Issue 11884
+
 [ $runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt || $runtime == safari ]
 audiocontext_test: Skip # Issue 9322
 
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 3f441b4..ab28e12 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -127,7 +127,7 @@
 isolate_stress_test: Pass, Timeout # http://dartbug.com/10697
 
 [ $compiler == dart2js && ( $runtime == drt || $runtime == chrome ) ]
-isolate_stress_test: Pass, Timeout # issue 11648
+isolate_stress_test: Pass, Crash, Timeout # issue 11648
 
 [ $arch == arm || $arch == simarm ]
 *: Skip
diff --git a/tests/language/const_constructor_mixin_test.dart b/tests/language/const_constructor_mixin_test.dart
new file mode 100644
index 0000000..832be8c
--- /dev/null
+++ b/tests/language/const_constructor_mixin_test.dart
@@ -0,0 +1,18 @@
+// 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.
+
+class Mixin {
+}
+
+class A {
+  const A(foo);
+}
+
+class B extends A with Mixin {
+  const B(foo) : super(foo);
+}
+
+main() {
+  var a = const B(42);
+}
diff --git a/tests/language/inference_mixin_field_test.dart b/tests/language/inference_mixin_field_test.dart
new file mode 100644
index 0000000..9669846
--- /dev/null
+++ b/tests/language/inference_mixin_field_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 Mixin {
+  var field;
+  createIt() {
+    if (field == null) field = 42;
+  }
+}
+
+class A {
+  A(foo);
+}
+
+class B extends A with Mixin {
+  // Because [super] references a synthesized constructor, dart2js
+  // used to not see the null assignment to it.
+  B(foo) : super(foo);
+}
+
+main() {
+  var a = new B(42);
+  a.createIt();
+  Expect.equals(42, a.field);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 0c2d5300..a04ad53 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -16,13 +16,11 @@
 # 3) Update the language/src directory with the updated test.
 
 [ $compiler == dart2dart ]
-mixin_type_parameters_simple_test: Fail, Crash # issue 11803
 mixin_super_constructor_named_test: Fail
 mixin_super_constructor_positionals_test: Fail
 const_constructor_super_test/01: fail
 
 [ $compiler == none ]
-mixin_type_parameters_simple_test: Fail, Crash # issue 11803
 mixin_super_constructor_named_test: Fail
 mixin_super_constructor_positionals_test: Fail
 built_in_identifier_prefix_test: Fail # http://dartbug.com/6970
@@ -73,6 +71,8 @@
 closures_initializer_test: Crash # issue 8847
 closures_initializer2_test: Crash # issue 8847
 
+mixin_forwarding_constructor2_test: Fail # Issue 11888
+mixin_typedef_constructor_test: Fail # Issue 11888
 
 [ $compiler == none && $unchecked ]
 
@@ -142,7 +142,10 @@
 # Mixins fail on the VM.
 mixin_mixin_test: Fail                      # VM issue
 mixin_issue10216_2_test: Fail               # VM issue
+mixin_forwarding_constructor2_test: Fail # Issue 11888
+mixin_typedef_constructor_test: Fail # Issue 11888
 
+mixin_with_two_implicit_constructors_test: Fail # Issue 11889
 
 # Malformed types not handled as unresolved:
 import_core_prefix_test: Fail
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index acbbb4c..8e01e1e 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -5,6 +5,8 @@
 [ $compiler == dartanalyzer ]
 #argument_definition_test/01: fail  # issue 11565 (passing for the wrong reason)
 
+illegal_invocation_test/01: fail # Issue: 11892
+
 # test issue 11581, it is not warning to call dynamic
 call_through_getter_test: fail
 
@@ -170,9 +172,6 @@
 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
-
 # test issue 10889, "throw" requires expression, "rethrow" should be used instead
 execute_finally10_test: fail
 execute_finally11_test: fail
diff --git a/tests/language/mixin_forwarding_constructor1_test.dart b/tests/language/mixin_forwarding_constructor1_test.dart
new file mode 100644
index 0000000..b0e97ab
--- /dev/null
+++ b/tests/language/mixin_forwarding_constructor1_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";
+
+abstract class Mixin1 {
+  var mixin1Field = 1;
+}
+
+abstract class Mixin2 {
+  var mixin2Field = 2;
+}
+
+class A {
+  var superField;
+  A(foo) : superField = foo;
+}
+
+class B extends A with Mixin1, Mixin2 {
+  var field = 4;
+  B(unused) : super(3);
+}
+
+main() {
+  var b = new B(null);
+  Expect.equals(1, b.mixin1Field);
+  Expect.equals(2, b.mixin2Field);
+  Expect.equals(3, b.superField);
+  Expect.equals(4, b.field);
+}
diff --git a/tests/language/mixin_forwarding_constructor2_test.dart b/tests/language/mixin_forwarding_constructor2_test.dart
new file mode 100644
index 0000000..1178196
--- /dev/null
+++ b/tests/language/mixin_forwarding_constructor2_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class Mixin1 {
+  var mixin1Field = 1;
+}
+
+abstract class Mixin2 {
+  var mixin2Field = 2;
+}
+
+class A {
+  var superField;
+  A([this.superField = 3]);
+}
+
+class B extends A with Mixin1, Mixin2 {
+  var field = 4;
+}
+
+main() {
+  var b = new B();
+  Expect.equals(1, b.mixin1Field);
+  Expect.equals(2, b.mixin2Field);
+  Expect.equals(3, b.superField);
+  Expect.equals(4, b.field);
+}
diff --git a/tests/language/mixin_typedef_constructor_test.dart b/tests/language/mixin_typedef_constructor_test.dart
new file mode 100644
index 0000000..01735bd
--- /dev/null
+++ b/tests/language/mixin_typedef_constructor_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A {
+  var field;
+  A(this.field);
+}
+
+class Mixin {
+  var mixinField = 54;
+}
+
+typedef MyClass = A with Mixin;
+
+main() {
+  var a = new MyClass(42);
+  Expect.equals(42, a.field);
+  Expect.equals(54, a.mixinField);
+}
diff --git a/tests/language/mixin_with_two_implicit_constructors_test.dart b/tests/language/mixin_with_two_implicit_constructors_test.dart
new file mode 100644
index 0000000..16c3606
--- /dev/null
+++ b/tests/language/mixin_with_two_implicit_constructors_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A {
+  var field;
+  A.bar() : field = 1;
+  A() : field = 2;
+}
+
+class Mixin {
+}
+
+class B extends A with Mixin {
+}
+
+main() {
+  Expect.equals(2, new B().field);
+  Expect.throws(() => new B.bar(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/try_catch_optimized2_test.dart b/tests/language/try_catch_optimized2_test.dart
new file mode 100644
index 0000000..d383a7f
--- /dev/null
+++ b/tests/language/try_catch_optimized2_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.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+import "package:expect/expect.dart";
+
+// Test allocation sinking with optimized try-catch.
+
+bar() {  // Should not be inlined.
+  try {
+  } finally { }
+}
+
+foo(a) {
+  var r = 0;
+  for (var i in a) {
+    r += i;
+  }
+  try {
+    bar();
+  } finally {
+  }
+  return r;
+}
+
+main() {
+  var a = [1,2,3];
+  for (var i = 0; i < 20; i++) foo(a);
+  Expect.equals(6, foo(a));
+}
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index 227e5c6..20a7804 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -3,7 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2analyzer ]
-lib/async/async: fail
 lib/core/core: fail
 lib/typed_data/typed_data: fail
 lib/io/io: fail
diff --git a/tests/lib/analyzer/analyze_tests.status b/tests/lib/analyzer/analyze_tests.status
index 6348c8b..9b23190 100644
--- a/tests/lib/analyzer/analyze_tests.status
+++ b/tests/lib/analyzer/analyze_tests.status
@@ -30,6 +30,9 @@
 # pkg issue https://code.google.com/p/dart/issues/detail?id=11856
 standalone/io/secure_socket_renegotiate_test: fail
 
+# https://code.google.com/p/dart/issues/detail?id=11647
+standalone/package/package_isolate_test: fail
+
 
 [ $compiler == dart2analyzer ]
 53bit_overflow_literal_test/01: fail, ok
@@ -58,3 +61,6 @@
 
 # pkg issue https://code.google.com/p/dart/issues/detail?id=11856
 standalone/io/secure_socket_renegotiate_test: fail
+
+# https://code.google.com/p/dart/issues/detail?id=11647
+standalone/package/package_isolate_test: fail
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index b443409..0e75568 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -108,7 +108,6 @@
 
 [ $arch == arm || $arch == simarm ]
 typed_data/float32x4_unbox_regress_test: Crash # Unimplemented
-typed_data/float32x4_unbox_phi_test: Crash # Unimplemented
 typed_data/float32x4_list_test: Crash # Unimplemented
 typed_data/float32x4_test: Crash # Unimplemented
 
diff --git a/tests/lib/typed_data/float32x4_unbox_phi_test.dart b/tests/lib/typed_data/float32x4_unbox_phi_test.dart
index 008d9c9..34c85ef 100644
--- a/tests/lib/typed_data/float32x4_unbox_phi_test.dart
+++ b/tests/lib/typed_data/float32x4_unbox_phi_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// VMOptions=--deoptimization_counter_threshold=1000
+// VMOptions=--deoptimization_counter_threshold=1000 --optimization-counter-threshold=10
 
 // Library tag to be able to run in html test framework.
 library float32x4_unbox_regress_test;
@@ -23,7 +23,7 @@
   for (int i = 0; i < floatList.length; i++) {
     floatList[i] = i.toDouble();
   }
-  for (int i = 0; i < 2000; i++) {
+  for (int i = 0; i < 20; i++) {
     double r = testUnboxPhi(list);
     Expect.equals(780.0, r);
   }
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index cf1d4c3..c678bcd 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -73,8 +73,12 @@
 # This is runtime test.
 io/process_exit_negative_test: Skip
 
+# https://code.google.com/p/dart/issues/detail?id=11647
+package/package_isolate_test: fail
+
 [ $compiler == dart2analyzer ]
 53bit_overflow_literal_test/01: fail, ok
+package/package_isolate_test: fail # issue 11647
 
 # test issue https://code.google.com/p/dart/issues/detail?id=11518
 io/file_constructor_test: fail
@@ -91,6 +95,9 @@
 # This is runtime test.
 io/process_exit_negative_test: Skip
 
+# https://code.google.com/p/dart/issues/detail?id=11647
+package/package_isolate_test: fail
+
 [ $compiler == dart2js ]
 number_identity_test: Skip # Bigints and int/double diff. not supported.
 typed_data_test: Skip # dart:typed_data support needed.
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index acc3501..f341977 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -20,6 +20,7 @@
       source = """
 library core;
 class Object {
+  Object();
   operator==(other) {}
   get hashCode => throw 'Object.hashCode not implemented.';
 }
diff --git a/tests/utils/recursive_import_test.dart b/tests/utils/recursive_import_test.dart
index fc7bd93..f827089 100644
--- a/tests/utils/recursive_import_test.dart
+++ b/tests/utils/recursive_import_test.dart
@@ -10,7 +10,8 @@
 
 const CORE_LIB = """
 library core;
-class Object{
+class Object {
+  Object();
   operator==(other) {}
 }
 class bool {}
diff --git a/tools/VERSION b/tools/VERSION
index 9d22974..9a50ffe 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 6
-BUILD 6
+BUILD 7
 PATCH 0
diff --git a/tools/coverage.dart b/tools/coverage.dart
index cc12e94..3f51f00 100644
--- a/tools/coverage.dart
+++ b/tools/coverage.dart
@@ -24,6 +24,7 @@
 // Whether or not to print the debugger wire messages on the console.
 var verboseWire = false;
 
+var debugger = null;
 
 class Program {
   static int numBps = 0;
@@ -33,17 +34,19 @@
 
   // Takes a JSON Debugger response and increments the count for
   // the source position.
-  static void recordBp(Debugger debugger, Map<String,dynamic> msg) {
+  static void recordBp(Map<String,dynamic> msg) {
     // Progress indicator.
     if (++numBps % 1000 == 0) print(numBps);
     var location = msg["params"]["location"];
     if (location == null) return;
     String url = location["url"];
     assert(url != null);
+    int libId = location["libraryId"];
+    assert(libId != null);
     int tokenPos = location["tokenOffset"];;
     Source s = sources[url];
     if (s == null) {
-      debugger.GetLineNumberTable(url);
+      debugger.getLineNumberTable(url, libId);
       s = new Source(url);
       sources[url] = s;
     }
@@ -146,6 +149,47 @@
 }
 
 
+class GetLibrariesCmd {
+  Map msg;
+  GetLibrariesCmd(int isolateId) {
+    msg = { "id": 0,
+            "command":  "getLibraries",
+            "params": { "isolateId" : isolateId } };
+  }
+
+  void handleResponse(Map response) {
+    List libs = response["result"]["libraries"];
+    for (var lib in libs) {
+      String url = lib["url"];
+      int libraryId = lib["id"];
+      bool enable = !url.startsWith("dart:") && !url.startsWith("package:");
+      if (enable) {
+        print("Enable stepping for '$url'");
+        debugger.enableDebugging(libraryId, true);
+      }
+    }
+  }
+}
+
+
+class SetLibraryPropertiesCmd {
+  Map msg;
+  SetLibraryPropertiesCmd(int isolateId, int libraryId, bool enableDebugging) {
+    // Note that in the debugger protocol, boolean values true and false
+    // must be sent as string literals.
+    msg = { "id": 0,
+            "command":  "setLibraryProperties",
+            "params": { "isolateId" : isolateId,
+                        "libraryId": libraryId,
+                        "debuggingEnabled": "$enableDebugging" } };
+  }
+
+  void handleResponse(Map response) {
+    // Nothing to do.
+  }
+}
+
+
 class Debugger {
   // Debug target process properties.
   Process targetProcess;
@@ -157,7 +201,7 @@
   // Data collected from debug target.
   Map currentMessage = null;  // Currently handled message sent by target.
   var outstandingCommand = null;
-  var queuedCommand = null;
+  var queuedCommands = new List();
   String scriptUrl = null;
   bool shutdownEventSeen = false;
   int isolateId = 0;
@@ -221,9 +265,12 @@
       if (libraryId == null) {
         libraryId = msg["params"]["location"]["libraryId"];
         assert(libraryId != null);
+        // This is the first paused event we got. Get all libraries from
+        // the debugger so we can turn on debugging events for them.
+        getLibraries();
       }
       if (msg["params"]["reason"] == "breakpoint") {
-        Program.recordBp(this, msg);
+        Program.recordBp(msg);
       }
     } else {
       error("Error: unknown debugger event received");
@@ -280,8 +327,7 @@
         return;
       }
       if (isPaused && (outstandingCommand == null)) {
-        var cmd = queuedCommand;
-        queuedCommand = null;
+        var cmd = queuedCommands.length > 0 ? queuedCommands.removeAt(0) : null;
         if (cmd == null) {
           cmd = new StepCmd(isolateId);
           isPaused = false;
@@ -302,11 +348,18 @@
     socket.write(jsonMsg);
   }
 
-  void GetLineNumberTable(String url) {
-    assert(queuedCommand == null);
-    queuedCommand = new GetLineTableCmd(isolateId, libraryId, url);
+  void getLineNumberTable(String url, int libId) {
+    queuedCommands.add(new GetLineTableCmd(isolateId, libId, url));
+  }
+
+  void getLibraries() {
+    queuedCommands.add(new GetLibrariesCmd(isolateId));
   }
   
+  void enableDebugging(libraryId, enable) {
+    queuedCommands.add(new SetLibraryPropertiesCmd(isolateId, libraryId, enable));
+  }
+
   bool get errorsDetected => errors.length > 0;
 
   // Record error message.
@@ -490,6 +543,6 @@
 
   Process.start(options.executable, targetOpts).then((Process process) {
     process.stdin.close();
-    var debugger = new Debugger(process);
+    debugger = new Debugger(process);
   });
 }
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index a3c0333..4a94db8 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -88,6 +88,7 @@
 // Workaround for tags like <cite> that lack their own Element subclass --
 // Dart issue 1990.
 class _HTMLElement extends Element native "HTMLElement" {
+  factory _HTMLElement() { throw new UnsupportedError("Not supported"); }
 }
 
 // Support for Send/ReceivePortSync.
diff --git a/tools/publish_all_pkgs.py b/tools/publish_all_pkgs.py
index 729d9a1..2e3d181 100644
--- a/tools/publish_all_pkgs.py
+++ b/tools/publish_all_pkgs.py
@@ -29,7 +29,7 @@
     os.path.join('sdk', 'lib', '_internal', 'compiler'))
 
   for pkg in pkgs_to_publish:
-    print "Publishing " + pkg
+    print "\n\nPublishing %s:\n-------------------------------" % pkg
     subprocess.call(['python', 'tools/publish_pkg.py', pkg])
 
 if __name__ == '__main__':
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index 11e5ce1..1159a8a 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -150,14 +150,12 @@
 
 // Find all relative imports and copy them into the dir that contains
 // the generated tests.
-Set<Path> _findAllRelativeImports(Path topLibrary) {
+Set<String> _findAllRelativeImports(Path topLibrary) {
   Set<Path> toSearch = new Set<Path>.from([topLibrary]);
-  Set<Path> foundImports = new Set<Path>();
+  Set<String> foundImports = new Set<String>();
   Path libraryDir = topLibrary.directoryPath;
-  // Matches #import( or #source( followed by " or ' followed by anything
-  // except dart:, dart-ext: or /, at the beginning of a line.
   RegExp relativeImportRegExp = new RegExp(
-      '^#(import|source)[(]["\'](?!(dart:|dart-ext:|/))([^"\']*)["\']');
+      '^(import|part)\\s+["\'](?!(dart:|dart-ext:|package:|/))([^"\']*)["\']');
   while (!toSearch.isEmpty) {
     var thisPass = toSearch;
     toSearch = new Set<Path>();
@@ -167,7 +165,7 @@
         Match match = relativeImportRegExp.firstMatch(line);
         if (match != null) {
           Path relativePath = new Path(match.group(3));
-          if (foundImports.contains(relativePath)) {
+          if (foundImports.contains(relativePath.toString())) {
             continue;
           }
           if (relativePath.toString().contains('..')) {
@@ -177,7 +175,7 @@
             print("relative paths containing .. are not allowed.");
             exit(1);
           }
-          foundImports.add(relativePath);
+          foundImports.add(relativePath.toString());
           toSearch.add(libraryDir.join(relativePath));
         }
       }
@@ -198,9 +196,10 @@
   assert(targetDir != null);
 
   // Copy all the relative imports of the multitest.
-  Set<Path> importsToCopy = _findAllRelativeImports(filePath);
+  Set<String> importsToCopy = _findAllRelativeImports(filePath);
   List<Future> futureCopies = [];
-  for (Path importPath in importsToCopy) {
+  for (String relativeImport in importsToCopy) {
+    Path importPath = new Path(relativeImport);
     // Make sure the target directory exists.
     Path importDir = importPath.directoryPath;
     if (!importDir.isEmpty) {
diff --git a/utils/testrunner/standard_test_runner.dart b/utils/testrunner/standard_test_runner.dart
index dddc2fd..89fcc2f 100644
--- a/utils/testrunner/standard_test_runner.dart
+++ b/utils/testrunner/standard_test_runner.dart
@@ -199,7 +199,7 @@
       List<TestCase> results, String uncaughtError) {
     TestCase test = results[0];
     parentPort.send([test.result, test.runningTime.inMilliseconds,
-                     test.message, test.stackTrace]);
+                     test.message, test.stackTrace.toString()]);
   }
 }