Version 0.6.2.0 .

svn merge -r 24475:24603  https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@24607 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/docgen/bin/docgen.dart b/pkg/docgen/bin/docgen.dart
index 6222b0f..f181a83 100644
--- a/pkg/docgen/bin/docgen.dart
+++ b/pkg/docgen/bin/docgen.dart
@@ -17,7 +17,7 @@
   logger.onRecord.listen((record) => print(record.message));
   var results = initArgParser().parse(new Options().arguments);
   if (results['help']) return;  
-  new Docgen(results);
+  docgen(results);
 }
 
 /**
@@ -31,7 +31,7 @@
       callback: (help) {
         if (help) {
           logger.info(parser.getUsage());
-          logger.info(usage);
+          logger.info(USAGE);
         }
       });
   parser.addFlag('verbose', abbr: 'v', 
@@ -52,6 +52,9 @@
       help: 'Flag to include private declarations.', negatable: false);
   parser.addFlag('include-sdk', 
       help: 'Flag to parse SDK Library files.', negatable: false);
+  parser.addFlag('parse-sdk', 
+      help: 'Parses the SDK libraries only.', 
+      defaultsTo: false, negatable: false);
   
   return parser;
 }
diff --git a/pkg/docgen/lib/dart2yaml.dart b/pkg/docgen/lib/dart2yaml.dart
index a03c7f1..a481aca 100644
--- a/pkg/docgen/lib/dart2yaml.dart
+++ b/pkg/docgen/lib/dart2yaml.dart
@@ -52,7 +52,8 @@
  * Returns an escaped String form of the inputted element.
  */
 String _processElement(var element) {
-  return "\"${element.toString().replaceAll("\"", "\\\"")}\"\n";
+  return "\"${element.toString().replaceAll('\\', '\\\\')
+    .replaceAll("\"", "\\\"")}\"\n";
 }
 
 /**
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index 52d10d2..a542195 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -33,275 +33,311 @@
 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dart';
 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
+import '../../../sdk/lib/_internal/libraries.dart';
 
 var logger = new Logger('Docgen');
 
-const String usage = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]';
+const String USAGE = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]';
+
+/// Current library being documented to be used for comment links.
+LibraryMirror _currentLibrary;
+
+/// Current class being documented to be used for comment links.
+ClassMirror _currentClass;
+
+/// Current member being documented to be used for comment links.
+MemberMirror _currentMember;
+
+/// Resolves reference links in doc comments. 
+markdown.Resolver linkResolver;
+
+/// Package directory of directory being analyzed. 
+String packageDir;
+
+bool outputToYaml;
+bool outputToJson;
+bool includePrivate;
+/// State for whether imported SDK libraries should also be outputted.
+bool includeSdk;
+/// State for whether all SDK libraries should be outputted. 
+bool parseSdk;
 
 /**
- * This class documents a list of libraries.
+ * Docgen constructor initializes the link resolver for markdown parsing.
+ * Also initializes the command line arguments. 
  */
-class Docgen {
-
-  /// Libraries to be documented.
-  List<LibraryMirror> _libraries;
-
-  /// Current library being documented to be used for comment links.
-  LibraryMirror _currentLibrary;
+void docgen(ArgResults argResults) {  
+  _setCommandLineArguments(argResults);
   
-  /// Current class being documented to be used for comment links.
-  ClassMirror _currentClass;
+  linkResolver = (name) => 
+      fixReference(name, _currentLibrary, _currentClass, _currentMember);
   
-  /// Current member being documented to be used for comment links.
-  MemberMirror _currentMember;
-  
-  /// Resolves reference links in doc comments. 
-  markdown.Resolver linkResolver;
-  
-  /// Package directory of directory being analyzed. 
-  String packageDir;
-  
-  bool outputToYaml;
-  bool outputToJson;
-  bool includePrivate;
-  /// State for whether or not the SDK libraries should also be outputted.
-  bool includeSdk;
-
-  /**
-   * Docgen constructor initializes the link resolver for markdown parsing.
-   * Also initializes the command line arguments. 
-   */
-  Docgen(ArgResults argResults) {  
-    if (argResults['output-format'] == null) {
-      outputToYaml = 
-          (argResults['yaml'] == false && argResults['json'] == false) ?
-              true : argResults['yaml'];
-    } else {
-      if ((argResults['output-format'] == 'yaml' && 
-          argResults['json'] == true) || 
-          (argResults['output-format'] == 'json' && 
-          argResults['yaml'] == true)) {
-        throw new UnsupportedError('Cannot have contradictory output flags.');
-      }
-      outputToYaml = argResults['output-format'] == 'yaml' ? true : false;
+  getMirrorSystem(argResults.rest).then((MirrorSystem mirrorSystem) {
+    if (mirrorSystem.libraries.values.isEmpty) {
+      throw new StateError('No Library Mirrors.');
     }
-    outputToJson = !outputToYaml;
-    includePrivate = argResults['include-private'];
-    includeSdk = argResults['include-sdk'];
-    
-    this.linkResolver = (name) => 
-        fixReference(name, _currentLibrary, _currentClass, _currentMember);
-    
-    analyze(argResults.rest);
-  }
-  
-  List<String> listLibraries(List<String> args) {
-    // TODO(janicejl): At the moment, only have support to have either one file,
-    // or one directory. This is because there can only be one package directory
-    // since only one docgen is created per run. 
-    if (args.length != 1) throw new UnsupportedError(usage);
-    var libraries = new List<String>();
-    var type = FileSystemEntity.typeSync(args[0]);
-    
-    if (type == FileSystemEntityType.FILE) {
-      libraries.add(path.absolute(args[0]));
-      logger.info('Added to libraries: ${libraries.last}');
-    } else {
-      libraries.addAll(listDartFromDir(args[0]));
-    } 
-    logger.info('Package Directory: $packageDir');
-    return libraries;
-  }
+    _documentLibraries(mirrorSystem.libraries.values);
+  });
+}
 
-  List<String> listDartFromDir(String args) {
-    var files = listDir(args, recursive: true);
-    packageDir = files.firstWhere((f) => 
-        f.endsWith('/pubspec.yaml'), orElse: () => '');
-    if (packageDir != '') packageDir = path.dirname(packageDir) + '/packages';
-    return files.where((f) => 
-        f.endsWith('.dart') && !f.contains('/packages')).toList()
-        ..forEach((lib) => logger.info('Added to libraries: $lib'));
+void _setCommandLineArguments(ArgResults argResults) {
+  outputToYaml = argResults['yaml'] || argResults['output-format'] == 'yaml';
+  outputToJson = argResults['json'] || argResults['output-format'] == 'json';
+  if (outputToYaml && outputToJson) {
+    throw new ArgumentError('Cannot have contradictory output flags.');
   }
+  outputToYaml = outputToYaml || !outputToJson;
+  includePrivate = argResults['include-private'];
+  parseSdk = argResults['parse-sdk'];
+  includeSdk = parseSdk || argResults['include-sdk'];
+}
 
-  /**
-   * Analyzes set of libraries by getting a mirror system and triggers the 
-   * documentation of the libraries. 
-   */
-  void analyze(List<String> args) {
-    var libraries = listLibraries(args);
-    if (libraries.isEmpty) throw new StateError('No Libraries.');
-    // DART_SDK should be set to the root of the SDK library. 
-    var sdkRoot = Platform.environment['DART_SDK'];
-    if (sdkRoot != null) {
-      logger.info('Using DART_SDK to find SDK at $sdkRoot');
-    } else {
-      // If DART_SDK is not defined in the environment, 
-      // assuming the dart executable is from the Dart SDK folder inside bin. 
-      sdkRoot = path.dirname(path.dirname(new Options().executable));
-      logger.info('SDK Root: ${sdkRoot}');
-    }
-    
-    getMirrorSystem(libraries, sdkRoot, packageRoot: packageDir)
-        .then((MirrorSystem mirrorSystem) {
-          if (mirrorSystem.libraries.values.isEmpty) {
-            throw new UnsupportedError('No Library Mirrors.');
-          } 
-          this.libraries = mirrorSystem.libraries.values;
-          documentLibraries();
-        });
-  }
+List<String> _listLibraries(List<String> args) {
+  // TODO(janicejl): At the moment, only have support to have either one file,
+  // or one directory. This is because there can only be one package directory
+  // since only one docgen is created per run. 
+  if (args.length != 1) throw new UnsupportedError(USAGE);
+  var libraries = new List<String>();
+  var type = FileSystemEntity.typeSync(args[0]);
   
-  /**
-   * Analyzes set of libraries and provides a mirror system which can be used 
-   * for static inspection of the source code.
-   */
-  Future<MirrorSystem> getMirrorSystem(List<String> libraries,
-        String libraryRoot, {String packageRoot}) {
-    SourceFileProvider provider = new SourceFileProvider();
-    api.DiagnosticHandler diagnosticHandler =
-          new FormattingDiagnosticHandler(provider).diagnosticHandler;
-    Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot'));
-    Uri packageUri = null;
-    if (packageRoot != null) {
-      packageUri = currentDirectory.resolve(appendSlash('$packageRoot'));
-    }
-    List<Uri> librariesUri = <Uri>[];
-    libraries.forEach((library) {
-      librariesUri.add(currentDirectory.resolve(library));
-    });
-    return dart2js.analyze(librariesUri, libraryUri, packageUri,
-        provider.readStringFromUri, diagnosticHandler,
-        ['--preserve-comments', '--categories=Client,Server']);
-  }
-  
-  /**
-   * Creates documentation for filtered libraries.
-   */
-  void documentLibraries() {
-    _libraries.forEach((library) {
-      // Files belonging to the SDK have a uri that begins with 'dart:'.
-      if (includeSdk || !library.uri.toString().startsWith('dart:')) {
-        _currentLibrary = library;
-        var result = new Library(library.qualifiedName, _getComment(library),
-            _getVariables(library.variables), _getMethods(library.functions),
-            _getClasses(library.classes));
-        if (outputToJson) {
-          _writeToFile(stringify(result.toMap()), '${result.name}.json');
-        } 
-        if (outputToYaml) {
-          _writeToFile(getYamlString(result.toMap()), '${result.name}.yaml');
-        }
-     }
-    });
-   }
-
-  /// Saves list of libraries for Docgen object.
-  void set libraries(value){
-    _libraries = value;
-  }
-  
-  /**
-   * Returns any documentation comments associated with a mirror with
-   * simple markdown converted to html.
-   */
-  String _getComment(DeclarationMirror mirror) {
-    String commentText;
-    mirror.metadata.forEach((metadata) {
-      if (metadata is CommentInstanceMirror) {
-        CommentInstanceMirror comment = metadata;
-        if (comment.isDocComment) {
-          if (commentText == null) {
-            commentText = comment.trimmedText;
-          } else {
-            commentText = '$commentText ${comment.trimmedText}';
-          }
-        } 
-      }
-    });
-    commentText = commentText == null ? '' : 
-        markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver)
-        .replaceAll('\n', '');
-    return commentText;
-  }
-
-  /**
-   * Converts all [_] references in comments to <code>_</code>.
-   */
-  // TODO(tmandel): Create proper links for [_] style markdown based
-  // on scope once layout of viewer is finished.
-  markdown.Node fixReference(String name, LibraryMirror currentLibrary, 
-      ClassMirror currentClass, MemberMirror currentMember) {
-    return new markdown.Element.text('code', name);
-  }
-  
-  /**
-   * Returns a map of [Variable] objects constructed from inputted mirrors.
-   */
-  Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap) {
-    var data = {};
-    mirrorMap.forEach((String mirrorName, VariableMirror mirror) {
-      if (includePrivate || !mirror.isPrivate) {
-        _currentMember = mirror;
-        data[mirrorName] = new Variable(mirrorName, mirror.qualifiedName, 
-            mirror.isFinal, mirror.isStatic, mirror.type.qualifiedName, 
-            _getComment(mirror));
-      }
-    });
-    return data;
-  }
-  
-  /**
-   * Returns a map of [Method] objects constructed from inputted mirrors.
-   */
-  Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap) {
-    var data = {};
-    mirrorMap.forEach((String mirrorName, MethodMirror mirror) {
-      if (includePrivate || !mirror.isPrivate) {
-        _currentMember = mirror;
-        data[mirrorName] = new Method(mirrorName, mirror.qualifiedName, 
-            mirror.isSetter, mirror.isGetter, mirror.isConstructor, 
-            mirror.isOperator, mirror.isStatic, mirror.returnType.qualifiedName, 
-            _getComment(mirror), _getParameters(mirror.parameters));
-      }
-    });
-    return data;
+  if (type == FileSystemEntityType.FILE) {
+    libraries.add(path.absolute(args[0]));
+    logger.info('Added to libraries: ${libraries.last}');
+  } else {
+    libraries.addAll(_listDartFromDir(args[0]));
   } 
-  
-  /**
-   * Returns a map of [Class] objects constructed from inputted mirrors.
-   */
-  Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap) {
-    var data = {};
-    mirrorMap.forEach((String mirrorName, ClassMirror mirror) {
-      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, mirror.qualifiedName, 
-            superclass, mirror.isAbstract, mirror.isTypedef, 
-            _getComment(mirror), interfaces.toList(),
-            _getVariables(mirror.variables), _getMethods(mirror.methods));
-      }
-    });
-    return data;
+  logger.info('Package Directory: $packageDir');
+  return libraries;
+}
+
+List<String> _listDartFromDir(String args) {
+  var files = listDir(args, recursive: true);
+  packageDir = files.firstWhere((f) => 
+      f.endsWith('/pubspec.yaml'), orElse: () => '');
+  if (packageDir != '') packageDir = path.dirname(packageDir) + '/packages';
+  return files.where((f) => 
+      f.endsWith('.dart') && !f.contains('/packages')).toList()
+      ..forEach((lib) => logger.info('Added to libraries: $lib'));
+}
+
+List<String> _listSdk() {
+  var sdk = new List<String>();
+  LIBRARIES.forEach((String name, LibraryInfo info) {
+    if (info.documented) { 
+      sdk.add('dart:$name');
+      logger.info('Add to SDK: ${sdk.last}');
+    }
+  });
+  return sdk;
+}
+
+/**
+ * Analyzes set of libraries by getting a mirror system and triggers the 
+ * documentation of the libraries. 
+ */
+Future<MirrorSystem> getMirrorSystem(List<String> args) {
+  var libraries = !parseSdk ? _listLibraries(args) : _listSdk();
+  if (libraries.isEmpty) throw new StateError('No Libraries.');
+  // DART_SDK should be set to the root of the SDK library. 
+  var sdkRoot = Platform.environment['DART_SDK'];
+  if (sdkRoot != null) {
+    logger.info('Using DART_SDK to find SDK at $sdkRoot');
+  } else {
+    // If DART_SDK is not defined in the environment, 
+    // assuming the dart executable is from the Dart SDK folder inside bin. 
+    sdkRoot = path.dirname(path.dirname(new Options().executable));
+    logger.info('SDK Root: ${sdkRoot}');
   }
   
-  /**
-   * Returns a map of [Parameter] objects constructed from inputted mirrors.
-   */
-  Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) {
-    var data = {};
-    mirrorList.forEach((ParameterMirror mirror) {
+  return _getMirrorSystemHelper(libraries, sdkRoot, packageRoot: packageDir);
+}
+
+/**
+ * Analyzes set of libraries and provides a mirror system which can be used 
+ * for static inspection of the source code.
+ */
+Future<MirrorSystem> _getMirrorSystemHelper(List<String> libraries,
+      String libraryRoot, {String packageRoot}) {
+  SourceFileProvider provider = new SourceFileProvider();
+  api.DiagnosticHandler diagnosticHandler =
+        new FormattingDiagnosticHandler(provider).diagnosticHandler;
+  Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot'));
+  Uri packageUri = null;
+  if (packageRoot != null) {
+    packageUri = currentDirectory.resolve(appendSlash('$packageRoot'));
+  }
+  List<Uri> librariesUri = <Uri>[];
+  libraries.forEach((library) {
+    librariesUri.add(currentDirectory.resolve(library));
+  });
+  return dart2js.analyze(librariesUri, libraryUri, packageUri,
+      provider.readStringFromUri, diagnosticHandler,
+      ['--preserve-comments', '--categories=Client,Server']);
+}
+
+/**
+ * Creates documentation for filtered libraries.
+ */
+void _documentLibraries(List<LibraryMirror> libraries) {
+  libraries.forEach((lib) {
+    // Files belonging to the SDK have a uri that begins with 'dart:'.
+    if (includeSdk || !lib.uri.toString().startsWith('dart:')) {
+      var library = generateLibrary(lib);
+      _outputLibrary(library);
+    }
+  });
+  // Outputs a text file with a list of files available after creating all 
+  // the libraries. This will help the viewer know what files are available 
+  // to read in. 
+  _writeToFile(listDir("docs").join('\n'), 'library_list.txt');
+}
+
+Library generateLibrary(dart2js.Dart2JsLibraryMirror library) {
+  _currentLibrary = library;
+  var result = new Library(library.qualifiedName, _getComment(library),
+      _getVariables(library.variables), _getMethods(library.functions),
+      _getClasses(library.classes));
+  logger.fine('Generated library for ${result.name}');
+  return result;
+}
+
+void _outputLibrary(Library result) {
+  if (outputToJson) {
+    _writeToFile(stringify(result.toMap()), '${result.name}.json');
+  } 
+  if (outputToYaml) {
+    _writeToFile(getYamlString(result.toMap()), '${result.name}.yaml');
+  }
+}
+
+/**
+ * Returns a list of meta annotations assocated with a mirror. 
+ */
+List<String> _getAnnotations(DeclarationMirror mirror) {
+  var annotations = mirror.metadata.where((e) => 
+      e is dart2js.Dart2JsConstructedConstantMirror);
+  return annotations.map((e) => e.type.qualifiedName).toList();
+}
+
+/**
+ * Returns any documentation comments associated with a mirror with
+ * simple markdown converted to html.
+ */
+String _getComment(DeclarationMirror mirror) {
+  String commentText;
+  mirror.metadata.forEach((metadata) {
+    if (metadata is CommentInstanceMirror) {
+      CommentInstanceMirror comment = metadata;
+      if (comment.isDocComment) {
+        if (commentText == null) {
+          commentText = comment.trimmedText;
+        } else {
+          commentText = '$commentText ${comment.trimmedText}';
+        }
+      } 
+    }
+  });
+  commentText = commentText == null ? '' : 
+      markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver)
+      .replaceAll('\n', ' ');
+  return commentText;
+}
+
+/**
+ * Converts all [_] references in comments to <code>_</code>.
+ */
+// TODO(tmandel): Create proper links for [_] style markdown based
+// on scope once layout of viewer is finished.
+markdown.Node fixReference(String name, LibraryMirror currentLibrary, 
+    ClassMirror currentClass, MemberMirror currentMember) {
+  return new markdown.Element.text('code', name);
+}
+
+/**
+ * Returns a map of [Variable] objects constructed from inputted mirrors.
+ */
+Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap) {
+  var data = {};
+  mirrorMap.forEach((String mirrorName, VariableMirror mirror) {
+    if (includePrivate || !mirror.isPrivate) {
       _currentMember = mirror;
-      data[mirror.simpleName] = new Parameter(mirror.simpleName, 
-          mirror.qualifiedName, mirror.isOptional, mirror.isNamed, 
-          mirror.hasDefaultValue, mirror.type.qualifiedName, 
-          mirror.defaultValue);
-    });
-    return data;
+      data[mirrorName] = new Variable(mirrorName, mirror.qualifiedName, 
+          mirror.isFinal, mirror.isStatic, mirror.type.qualifiedName, 
+          _getComment(mirror), _getAnnotations(mirror));
+    }
+  });
+  return data;
+}
+
+/**
+ * Returns a map of [Method] objects constructed from inputted mirrors.
+ */
+Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap) {
+  var data = {};
+  mirrorMap.forEach((String mirrorName, MethodMirror mirror) {
+    if (includePrivate || !mirror.isPrivate) {
+      _currentMember = mirror;
+      data[mirrorName] = new Method(mirrorName, mirror.qualifiedName, 
+          mirror.isSetter, mirror.isGetter, mirror.isConstructor, 
+          mirror.isOperator, mirror.isStatic, mirror.returnType.qualifiedName, 
+          _getComment(mirror), _getParameters(mirror.parameters), 
+          _getAnnotations(mirror));
+    }
+  });
+  return data;
+} 
+
+/**
+ * Returns a map of [Class] objects constructed from inputted mirrors.
+ */
+Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap) {
+  var data = {};
+  mirrorMap.forEach((String mirrorName, ClassMirror mirror) {
+    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, mirror.qualifiedName, 
+          superclass, mirror.isAbstract, mirror.isTypedef, 
+          _getComment(mirror), interfaces.toList(),
+          _getVariables(mirror.variables), _getMethods(mirror.methods), 
+          _getAnnotations(mirror));
+    }
+  });
+  return data;
+}
+
+/**
+ * Returns a map of [Parameter] objects constructed from inputted mirrors.
+ */
+Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) {
+  var data = {};
+  mirrorList.forEach((ParameterMirror mirror) {
+    _currentMember = mirror;
+    data[mirror.simpleName] = new Parameter(mirror.simpleName, 
+        mirror.qualifiedName, mirror.isOptional, mirror.isNamed, 
+        mirror.hasDefaultValue, mirror.type.qualifiedName, 
+        mirror.defaultValue, _getAnnotations(mirror));
+  });
+  return data;
+}
+
+/**
+ * Writes text to a file in the 'docs' directory.
+ */
+void _writeToFile(String text, String filename) {
+  Directory dir = new Directory('docs');
+  if (!dir.existsSync()) {
+    dir.createSync();
   }
+  File file = new File('docs/$filename');
+  if (!file.existsSync()) {
+    file.createSync();
+  }
+  file.openSync();
+  file.writeAsString(text);
 }
 
 /**
@@ -372,9 +408,13 @@
   String superclass;
   bool isAbstract;
   bool isTypedef;
+  
+  /// List of the meta annotations on the class. 
+  List<String> annotations;
  
-  Class(this.name, this.qualifiedName, this.superclass, this.isAbstract, this.isTypedef,
-      this.comment, this.interfaces, this.variables, this.methods);
+  Class(this.name, this.qualifiedName, this.superclass, this.isAbstract, 
+      this.isTypedef, this.comment, this.interfaces, this.variables, 
+      this.methods, this.annotations);
   
   /// Generates a map describing the [Class] object.
   Map toMap() {
@@ -388,6 +428,7 @@
     classMap['implements'] = new List.from(interfaces);
     classMap['variables'] = recurseMap(variables);
     classMap['methods'] = recurseMap(methods);
+    classMap['annotations'] = new List.from(annotations);
     return classMap;
   }
 }
@@ -405,9 +446,12 @@
   bool isFinal;
   bool isStatic;
   String type;
+
+  /// List of the meta annotations on the variable. 
+  List<String> annotations;
   
   Variable(this.name, this.qualifiedName, this.isFinal, this.isStatic, 
-      this.type, this.comment);
+      this.type, this.comment, this.annotations);
   
   /// Generates a map describing the [Variable] object.
   Map toMap() {
@@ -418,6 +462,7 @@
     variableMap['final'] = isFinal.toString();
     variableMap['static'] = isStatic.toString();
     variableMap['type'] = type;
+    variableMap['annotations'] = new List.from(annotations);
     return variableMap;
   }
 }
@@ -442,9 +487,12 @@
   bool isStatic;
   String returnType;
   
+  /// List of the meta annotations on the method.  
+  List<String> annotations;
+  
   Method(this.name, this.qualifiedName, this.isSetter, this.isGetter, 
       this.isConstructor, this.isOperator, this.isStatic, this.returnType, 
-      this.comment, this.parameters);
+      this.comment, this.parameters, this.annotations);
   
   /// Generates a map describing the [Method] object.
   Map toMap() {
@@ -457,6 +505,7 @@
     methodMap['static'] = isStatic.toString();
     methodMap['return'] = returnType;
     methodMap['parameters'] = recurseMap(parameters);
+    methodMap['annotations'] = new List.from(annotations);
     return methodMap;
   }  
 }
@@ -474,8 +523,11 @@
   String type;
   String defaultValue;
   
-  Parameter(this.name, this.qualifiedName, this.isOptional, this.isNamed, this.hasDefaultValue,
-      this.type, this.defaultValue);
+  /// List of the meta annotations on the parameter. 
+  List<String> annotations;
+  
+  Parameter(this.name, this.qualifiedName, this.isOptional, this.isNamed, 
+      this.hasDefaultValue, this.type, this.defaultValue, this.annotations);
   
   /// Generates a map describing the [Parameter] object.
   Map toMap() {
@@ -487,22 +539,7 @@
     parameterMap['default'] = hasDefaultValue.toString();
     parameterMap['type'] = type;
     parameterMap['value'] = defaultValue;
+    parameterMap['annotations'] = new List.from(annotations);
     return parameterMap;
   } 
 }
-
-/**
- * Writes text to a file in the 'docs' directory.
- */
-void _writeToFile(String text, String filename) {
-  Directory dir = new Directory('docs');
-  if (!dir.existsSync()) {
-    dir.createSync();
-  }
-  File file = new File('docs/$filename');
-  if (!file.existsSync()) {
-    file.createSync();
-  }
-  file.openSync();
-  file.writeAsString(text);
-}
\ No newline at end of file
diff --git a/pkg/http_server/lib/src/virtual_directory.dart b/pkg/http_server/lib/src/virtual_directory.dart
index 6ce667b..bb3b7ac 100644
--- a/pkg/http_server/lib/src/virtual_directory.dart
+++ b/pkg/http_server/lib/src/virtual_directory.dart
@@ -46,6 +46,13 @@
   void serveRequest(HttpRequest request);
 
   /**
+   * Set the [callback] to override the default directory listing. The
+   * [callback] will be called with the [Directory] to be listed and the
+   * [HttpRequest].
+   */
+  void setDirectoryHandler(void callback(Directory dir, HttpRequest request));
+
+  /**
    * Set the [callback] to override the error page handler. When [callback] is
    * invoked, the `statusCode` property of the response is set.
    */
@@ -59,6 +66,7 @@
   bool followLinks = true;
 
   Function _errorCallback;
+  Function _dirCallback;
 
   _VirtualDirectory(this.root);
 
@@ -81,12 +89,18 @@
           }
           if (entity is File) {
             _serveFile(entity, request);
+          } else if (entity is Directory) {
+            _serveDirectory(entity, request);
           } else {
             _serveErrorPage(HttpStatus.NOT_FOUND, request);
           }
         });
   }
 
+  void setDirectoryHandler(void callback(Directory dir, HttpRequest request)) {
+    _dirCallback = callback;
+  }
+
   void setErrorPageHandler(void callback(HttpRequest request)) {
     _errorCallback = callback;
   }
@@ -118,10 +132,13 @@
                     .then((target) {
                       var targetPath = new Path(target).canonicalize();
                       if (targetPath.isAbsolute) return null;
-                      targetPath = path.directoryPath.join(targetPath)
-                          .canonicalize();
+                      targetPath =
+                          path.directoryPath.join(targetPath).canonicalize();
                       if (targetPath.segments().isEmpty ||
                           targetPath.segments().first == '..') return null;
+                      if (segments.isEmpty) {
+                        return _locateResource(targetPath, []);
+                      }
                       return _locateResource(targetPath.append(segments.first),
                                              segments.skip(1));
                     });
@@ -197,6 +214,86 @@
     });
   }
 
+  void _serveDirectory(Directory dir, HttpRequest request) {
+    if (_dirCallback != null) {
+      _dirCallback(dir, request);
+      return;
+    }
+    var response = request.response;
+    dir.stat().then((stats) {
+      if (request.headers.ifModifiedSince != null &&
+          !stats.modified.isAfter(request.headers.ifModifiedSince)) {
+        response.statusCode = HttpStatus.NOT_MODIFIED;
+        response.close();
+        return;
+      }
+
+      response.headers.set(HttpHeaders.LAST_MODIFIED, stats.modified);
+      var path = request.uri.path;
+      var header =
+'''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Index of $path</title>
+</head>
+<body>
+<h1>Index of $path</h1>
+<table>
+  <tr>
+    <td>Name</td>
+    <td>Last modified</td>
+    <td>Size</td>
+  </tr>
+''';
+      var server = response.headers.value(HttpHeaders.SERVER);
+      if (server == null) server = "";
+      var footer =
+'''</table>
+$server
+</body>
+</html>
+''';
+
+      response.write(header);
+
+      void add(String name, String modified, var size) {
+        if (size == null) size = "-";
+        if (modified == null) modified = "";
+        var p = new Path(path).append(name).canonicalize().toString();
+        var entry =
+'''  <tr>
+    <td><a href="$p">$name</a></td>
+    <td>$modified</td>
+    <td style="text-align: right">$size</td>
+  </tr>''';
+        response.write(entry);
+      }
+
+      if (path != '/') {
+        add('../', null, null);
+      }
+
+      dir.list(followLinks: true).listen((entity) {
+        // TODO(ajohnsen): Consider async dir listing.
+        if (entity is File) {
+          var stat = entity.statSync();
+          add(new Path(entity.path).filename,
+              stat.modified.toString(),
+              stat.size);
+        } else if (entity is Directory) {
+          add(new Path(entity.path).filename + '/',
+              entity.statSync().modified.toString(),
+              null);
+        }
+      }, onError: (e) {
+      }, onDone: () {
+        response.write(footer);
+        response.close();
+      });
+    }, onError: (e) => response.close());
+  }
+
   void _serveErrorPage(int error, HttpRequest request) {
     var response = request.response;
     response.statusCode = error;
@@ -207,22 +304,22 @@
     // Default error page.
     var path = request.uri.path;
     var reason = response.reasonPhrase;
-    response.write(
-        '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\n');
-    response.writeln(
-        '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">');
-    response.writeln('<html xmlns="http://www.w3.org/1999/xhtml">');
-    response.writeln('<head>');
-    response.writeln('<title>$reason: $path</title>');
-    response.writeln('</head>');
-    response.writeln('<body>');
-    response.writeln('<h1>Error $error at \'$path\': $reason</h1>');
+
     var server = response.headers.value(HttpHeaders.SERVER);
-    if (server != null) {
-      response.writeln(server);
-    }
-    response.writeln('</body>');
-    response.writeln('</html>');
+    if (server == null) server = "";
+    var page =
+'''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>$reason: $path</title>
+</head>
+<body>
+<h1>Error $error at \'$path\': $reason</h1>
+$server
+</body>
+</html>''';
+    response.write(page);
     response.close();
   }
 }
diff --git a/pkg/http_server/test/virtual_directory_test.dart b/pkg/http_server/test/virtual_directory_test.dart
index 1c579da..ca70948 100644
--- a/pkg/http_server/test/virtual_directory_test.dart
+++ b/pkg/http_server/test/virtual_directory_test.dart
@@ -115,6 +115,119 @@
     });
   });
 
+  group('serve-dir', () {
+    group('top-level', () {
+      test('simple', () {
+        expect(HttpServer.bind('localhost', 0).then((server) {
+          var dir = new Directory('').createTempSync();
+          var virDir = new VirtualDirectory(dir.path);
+          virDir.allowDirectoryListing = true;
+
+          virDir.serve(server);
+
+          return getAsString(server.port, '/')
+          .whenComplete(() {
+            server.close();
+            dir.deleteSync();
+          });
+        }), completion(contains('Index of /')));
+      });
+
+      test('files', () {
+        expect(HttpServer.bind('localhost', 0).then((server) {
+          var dir = new Directory('').createTempSync();
+          var virDir = new VirtualDirectory(dir.path);
+          for (int i = 0; i < 10; i++) {
+            new File('${dir.path}/$i').createSync();
+          }
+          virDir.allowDirectoryListing = true;
+
+          virDir.serve(server);
+
+          return getAsString(server.port, '/')
+          .whenComplete(() {
+            server.close();
+            dir.deleteSync(recursive: true);
+          });
+        }), completion(contains('Index of /')));
+      });
+
+      test('dirs', () {
+        expect(HttpServer.bind('localhost', 0).then((server) {
+          var dir = new Directory('').createTempSync();
+          var virDir = new VirtualDirectory(dir.path);
+          for (int i = 0; i < 10; i++) {
+            new Directory('${dir.path}/$i').createSync();
+          }
+          virDir.allowDirectoryListing = true;
+
+          virDir.serve(server);
+
+          return getAsString(server.port, '/')
+          .whenComplete(() {
+            server.close();
+            dir.deleteSync(recursive: true);
+          });
+        }), completion(contains('Index of /')));
+      });
+
+      if (!Platform.isWindows) {
+        test('recursive-link', () {
+          expect(HttpServer.bind('localhost', 0).then((server) {
+            var dir = new Directory('').createTempSync();
+            var link = new Link('${dir.path}/recursive')..createSync('.');
+            var virDir = new VirtualDirectory(dir.path);
+            virDir.allowDirectoryListing = true;
+
+            virDir.serve(server);
+
+            return Future.wait([
+                getAsString(server.port, '/').then(
+                    (s) => s.contains('recursive/')),
+                getAsString(server.port, '/').then(
+                    (s) => !s.contains('../')),
+                getAsString(server.port, '/').then(
+                    (s) => s.contains('Index of /')),
+                getAsString(server.port, '/recursive').then(
+                    (s) => s.contains('recursive/')),
+                getAsString(server.port, '/recursive').then(
+                    (s) => s.contains('../')),
+                getAsString(server.port, '/recursive').then(
+                    (s) => s.contains('Index of /recursive'))])
+                .whenComplete(() {
+                  server.close();
+                  dir.deleteSync(recursive: true);
+                });
+          }), completion(equals([true, true, true, true, true, true])));
+        });
+      }
+    });
+
+    group('custom', () {
+      test('simple', () {
+        expect(HttpServer.bind('localhost', 0).then((server) {
+          var dir = new Directory('').createTempSync();
+          var virDir = new VirtualDirectory(dir.path);
+          virDir.allowDirectoryListing = true;
+          virDir.setDirectoryHandler((dir2, request) {
+            expect(dir2, isNotNull);
+            expect(FileSystemEntity.identicalSync(dir.path, dir2.path), isTrue);
+            request.response.write('My handler ${request.uri.path}');
+            request.response.close();
+          });
+
+          virDir.serve(server);
+
+          return getAsString(server.port, '/')
+          .whenComplete(() {
+            server.close();
+            dir.deleteSync();
+          });
+        }), completion(contains('My handler /')));
+      });
+    });
+  });
+
   group('links', () {
     if (!Platform.isWindows) {
       group('follow-links', () {
diff --git a/pkg/mdv/lib/mdv.dart b/pkg/mdv/lib/mdv.dart
new file mode 100644
index 0000000..29a4a0b
--- /dev/null
+++ b/pkg/mdv/lib/mdv.dart
@@ -0,0 +1,103 @@
+// 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.
+
+// TODO(jmesserly): more commentary here.
+/**
+ * This library provides access to Model-Driven-Views APIs on HTML elements.
+ * More information can be found at: <https://github.com/toolkitchen/mdv>.
+ */
+library mdv;
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:html';
+import 'dart:math' as math;
+import 'package:observe/observe.dart';
+
+// TODO(jmesserly): get this from somewhere else. See http://dartbug.com/4161.
+import 'package:serialization/src/serialization_helpers.dart' show IdentityMap;
+
+part 'src/bindings.dart';
+part 'src/element.dart';
+part 'src/input_element.dart';
+part 'src/node.dart';
+part 'src/template.dart';
+part 'src/text.dart';
+
+/** Initialize the Model-Driven Views polyfill. */
+void initialize() {
+  TemplateElement.mdvPackage = _mdv;
+}
+
+StreamController<DocumentFragment> _instanceCreated;
+
+/**
+ * *Warning*: This is an implementation helper for Model-Driven Views and
+ * should not be used in your code.
+ *
+ * This event is fired whenever a template is instantiated via
+ * [Element.createInstance].
+ */
+// TODO(rafaelw): This is a hack, and is neccesary for the polyfill
+// because custom elements are not upgraded during clone()
+Stream<DocumentFragment> get instanceCreated {
+  if (_instanceCreated == null) {
+    _instanceCreated =
+        new StreamController<DocumentFragment>(sync: true);
+  }
+  return _instanceCreated.stream;
+}
+
+/**
+ * Binds all mustaches recursively starting from the [root] node.
+ *
+ * Note: this is not an official Model-Driven-Views API; it is intended to
+ * support binding the [ShadowRoot]'s content to a model.
+ */
+// TODO(jmesserly): this is needed to avoid two <template> nodes when using
+// bindings in a custom element's template. See also:
+// https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
+// Called from:
+// https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
+void bindModel(Node root, model, [CustomBindingSyntax syntax]) {
+  _Bindings._addBindings(root, model, syntax);
+}
+
+
+// TODO(jmesserly): investigate if expandos give us enough performance.
+
+// The expando for storing our MDV wrappers.
+//
+// In general, we need state associated with the nodes. Rather than having a
+// bunch of individual expandos, we keep one per node.
+//
+// Aside from the potentially helping performance, it also keeps things simpler
+// if we decide to integrate MDV into the DOM later, and means less code needs
+// to worry about expandos.
+final Expando _mdvExpando = new Expando('mdv');
+
+_mdv(node) {
+  var wrapper = _mdvExpando[node];
+  if (wrapper != null) return wrapper;
+
+  if (node is InputElement) {
+    wrapper = new _InputElementExtension(node);
+  } else if (node is Element) {
+    if (node.isTemplate) {
+      wrapper = new _TemplateExtension(node);
+    } else {
+      wrapper = new _ElementExtension(node);
+    }
+  } else if (node is Text) {
+    wrapper = new _TextExtension(node);
+  } else if (node is Node) {
+    wrapper = new _NodeExtension(node);
+  } else {
+    // TODO(jmesserly): this happens for things like CompoundBinding.
+    wrapper = node;
+  }
+
+  _mdvExpando[node] = wrapper;
+  return wrapper;
+}
diff --git a/pkg/mdv/lib/src/bindings.dart b/pkg/mdv/lib/src/bindings.dart
new file mode 100644
index 0000000..2b40671
--- /dev/null
+++ b/pkg/mdv/lib/src/bindings.dart
@@ -0,0 +1,513 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of mdv;
+
+// This code is a port of Model-Driven-Views:
+// https://github.com/polymer-project/mdv
+// The code mostly comes from src/template_element.js
+
+typedef void _ChangeHandler(value);
+
+abstract class _InputBinding {
+  final InputElement element;
+  PathObserver binding;
+  StreamSubscription _pathSub;
+  StreamSubscription _eventSub;
+
+  _InputBinding(this.element, model, String path) {
+    binding = new PathObserver(model, path);
+    _pathSub = binding.bindSync(valueChanged);
+    _eventSub = _getStreamForInputType(element).listen(updateBinding);
+  }
+
+  void valueChanged(newValue);
+
+  void updateBinding(e);
+
+  void unbind() {
+    binding = null;
+    _pathSub.cancel();
+    _eventSub.cancel();
+  }
+
+  static EventStreamProvider<Event> _checkboxEventType = () {
+    // Attempt to feature-detect which event (change or click) is fired first
+    // for checkboxes.
+    var div = new DivElement();
+    var checkbox = div.append(new InputElement());
+    checkbox.type = 'checkbox';
+    var fired = [];
+    checkbox.onClick.listen((e) {
+      fired.add(Element.clickEvent);
+    });
+    checkbox.onChange.listen((e) {
+      fired.add(Element.changeEvent);
+    });
+    checkbox.dispatchEvent(new MouseEvent('click', view: window));
+    // WebKit/Blink don't fire the change event if the element is outside the
+    // document, so assume 'change' for that case.
+    return fired.length == 1 ? Element.changeEvent : fired.first;
+  }();
+
+  static Stream<Event> _getStreamForInputType(InputElement element) {
+    switch (element.type) {
+      case 'checkbox':
+        return _checkboxEventType.forTarget(element);
+      case 'radio':
+      case 'select-multiple':
+      case 'select-one':
+        return element.onChange;
+      default:
+        return element.onInput;
+    }
+  }
+}
+
+class _ValueBinding extends _InputBinding {
+  _ValueBinding(element, model, path) : super(element, model, path);
+
+  void valueChanged(value) {
+    element.value = value == null ? '' : '$value';
+  }
+
+  void updateBinding(e) {
+    binding.value = element.value;
+  }
+}
+
+class _CheckedBinding extends _InputBinding {
+  _CheckedBinding(element, model, path) : super(element, model, path);
+
+  void valueChanged(value) {
+    element.checked = _Bindings._toBoolean(value);
+  }
+
+  void updateBinding(e) {
+    binding.value = element.checked;
+
+    // Only the radio button that is getting checked gets an event. We
+    // therefore find all the associated radio buttons and update their
+    // CheckedBinding manually.
+    if (element is InputElement && element.type == 'radio') {
+      for (var r in _getAssociatedRadioButtons(element)) {
+        var checkedBinding = _mdv(r)._checkedBinding;
+        if (checkedBinding != null) {
+          // Set the value directly to avoid an infinite call stack.
+          checkedBinding.binding.value = false;
+        }
+      }
+    }
+  }
+
+  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
+  // Returns an array containing all radio buttons other than |element| that
+  // have the same |name|, either in the form that |element| belongs to or,
+  // if no form, in the document tree to which |element| belongs.
+  //
+  // This implementation is based upon the HTML spec definition of a
+  // "radio button group":
+  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
+  //
+  static Iterable _getAssociatedRadioButtons(element) {
+    if (!_isNodeInDocument(element)) return [];
+    if (element.form != null) {
+      return element.form.nodes.where((el) {
+        return el != element &&
+            el is InputElement &&
+            el.type == 'radio' &&
+            el.name == element.name;
+      });
+    } else {
+      var radios = element.document.queryAll(
+          'input[type="radio"][name="${element.name}"]');
+      return radios.where((el) => el != element && el.form == null);
+    }
+  }
+
+  // TODO(jmesserly): polyfill document.contains API instead of doing it here
+  static bool _isNodeInDocument(Node node) {
+    // On non-IE this works:
+    // return node.document.contains(node);
+    var document = node.document;
+    if (node == document || node.parentNode == document) return true;
+    return document.documentElement.contains(node);
+  }
+}
+
+class _Bindings {
+  // TODO(jmesserly): not sure what kind of boolean conversion rules to
+  // apply for template data-binding. HTML attributes are true if they're
+  // present. However Dart only treats "true" as true. Since this is HTML we'll
+  // use something closer to the HTML rules: null (missing) and false are false,
+  // everything else is true. See: https://github.com/polymer-project/mdv/issues/59
+  static bool _toBoolean(value) => null != value && false != value;
+
+  static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
+    var clone = node.clone(false); // Shallow clone.
+    if (clone is Element && clone.isTemplate) {
+      TemplateElement.decorate(clone, node);
+      if (syntax != null) {
+        clone.attributes.putIfAbsent('syntax', () => syntax);
+      }
+    }
+
+    for (var c = node.firstChild; c != null; c = c.nextNode) {
+      clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
+    }
+    return clone;
+  }
+
+  static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
+    if (node is Element) {
+      _addAttributeBindings(node, model, syntax);
+    } else if (node is Text) {
+      _parseAndBind(node, 'text', node.text, model, syntax);
+    }
+
+    for (var c = node.firstChild; c != null; c = c.nextNode) {
+      _addBindings(c, model, syntax);
+    }
+  }
+
+  static void _addAttributeBindings(Element element, model, syntax) {
+    element.attributes.forEach((name, value) {
+      if (value == '' && (name == 'bind' || name == 'repeat')) {
+        value = '{{}}';
+      }
+      _parseAndBind(element, name, value, model, syntax);
+    });
+  }
+
+  static void _parseAndBind(Node node, String name, String text, model,
+      CustomBindingSyntax syntax) {
+
+    var tokens = _parseMustacheTokens(text);
+    if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
+      return;
+    }
+
+    // If this is a custom element, give the .xtag a change to bind.
+    node = _nodeOrCustom(node);
+
+    if (tokens.length == 1 && tokens[0].isBinding) {
+      _bindOrDelegate(node, name, model, tokens[0].value, syntax);
+      return;
+    }
+
+    var replacementBinding = new CompoundBinding();
+    for (var i = 0; i < tokens.length; i++) {
+      var token = tokens[i];
+      if (token.isBinding) {
+        _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
+      }
+    }
+
+    replacementBinding.combinator = (values) {
+      var newValue = new StringBuffer();
+
+      for (var i = 0; i < tokens.length; i++) {
+        var token = tokens[i];
+        if (token.isText) {
+          newValue.write(token.value);
+        } else {
+          var value = values[i];
+          if (value != null) {
+            newValue.write(value);
+          }
+        }
+      }
+
+      return newValue.toString();
+    };
+
+    node.bind(name, replacementBinding, 'value');
+  }
+
+  static void _bindOrDelegate(node, name, model, String path,
+      CustomBindingSyntax syntax) {
+
+    if (syntax != null) {
+      var delegateBinding = syntax.getBinding(model, path, name, node);
+      if (delegateBinding != null) {
+        model = delegateBinding;
+        path = 'value';
+      }
+    }
+
+    node.bind(name, model, path);
+  }
+
+  /**
+   * Gets the [node]'s custom [Element.xtag] if present, otherwise returns
+   * the node. This is used so nodes can override [Node.bind], [Node.unbind],
+   * and [Node.unbindAll] like InputElement does.
+   */
+  // TODO(jmesserly): remove this when we can extend Element for real.
+  static _nodeOrCustom(node) => node is Element ? node.xtag : node;
+
+  static List<_BindingToken> _parseMustacheTokens(String s) {
+    var result = [];
+    var length = s.length;
+    var index = 0, lastIndex = 0;
+    while (lastIndex < length) {
+      index = s.indexOf('{{', lastIndex);
+      if (index < 0) {
+        result.add(new _BindingToken(s.substring(lastIndex)));
+        break;
+      } else {
+        // There is a non-empty text run before the next path token.
+        if (index > 0 && lastIndex < index) {
+          result.add(new _BindingToken(s.substring(lastIndex, index)));
+        }
+        lastIndex = index + 2;
+        index = s.indexOf('}}', lastIndex);
+        if (index < 0) {
+          var text = s.substring(lastIndex - 2);
+          if (result.length > 0 && result.last.isText) {
+            result.last.value += text;
+          } else {
+            result.add(new _BindingToken(text));
+          }
+          break;
+        }
+
+        var value = s.substring(lastIndex, index).trim();
+        result.add(new _BindingToken(value, isBinding: true));
+        lastIndex = index + 2;
+      }
+    }
+    return result;
+  }
+
+  static void _addTemplateInstanceRecord(fragment, model) {
+    if (fragment.firstChild == null) {
+      return;
+    }
+
+    var instanceRecord = new TemplateInstance(
+        fragment.firstChild, fragment.lastChild, model);
+
+    var node = instanceRecord.firstNode;
+    while (node != null) {
+      _mdv(node)._templateInstance = instanceRecord;
+      node = node.nextNode;
+    }
+  }
+}
+
+class _BindingToken {
+  final String value;
+  final bool isBinding;
+
+  _BindingToken(this.value, {this.isBinding: false});
+
+  bool get isText => !isBinding;
+}
+
+class _TemplateIterator {
+  final Element _templateElement;
+  final List<Node> terminators = [];
+  final CompoundBinding inputs;
+  List iteratedValue;
+  Object _lastValue;
+
+  StreamSubscription _sub;
+  StreamSubscription _valueBinding;
+
+  _TemplateIterator(this._templateElement)
+    : inputs = new CompoundBinding(resolveInputs) {
+
+    _valueBinding = new PathObserver(inputs, 'value').bindSync(valueChanged);
+  }
+
+  static Object resolveInputs(Map values) {
+    if (values.containsKey('if') && !_Bindings._toBoolean(values['if'])) {
+      return null;
+    }
+
+    if (values.containsKey('repeat')) {
+      return values['repeat'];
+    }
+
+    if (values.containsKey('bind')) {
+      return [values['bind']];
+    }
+
+    return null;
+  }
+
+  void valueChanged(value) {
+    // TODO(jmesserly): should PathObserver do this for us?
+    var oldValue = _lastValue;
+    _lastValue = value;
+
+    if (value is! List) {
+      value = [];
+    }
+
+    unobserve();
+    iteratedValue = value;
+
+    if (value is Observable) {
+      _sub = value.changes.listen(_handleChanges);
+    }
+
+    int addedCount = iteratedValue.length;
+    var removedCount = oldValue is List ? (oldValue as List).length : 0;
+    if (addedCount == 0 && removedCount == 0) return; // nothing to do.
+
+    _handleChanges([new ListChangeRecord(0, addedCount: addedCount,
+        removedCount: removedCount)]);
+  }
+
+  Node getTerminatorAt(int index) {
+    if (index == -1) return _templateElement;
+    var terminator = terminators[index];
+    if (terminator is Element && (terminator as Element).isTemplate) {
+      var subIterator = _mdv(terminator)._templateIterator;
+      if (subIterator != null) {
+        return subIterator.getTerminatorAt(subIterator.terminators.length - 1);
+      }
+    }
+
+    return terminator;
+  }
+
+  void insertInstanceAt(int index, List<Node> instanceNodes) {
+    var previousTerminator = getTerminatorAt(index - 1);
+    var terminator = instanceNodes.length > 0 ? instanceNodes.last
+        : previousTerminator;
+
+    terminators.insert(index, terminator);
+
+    var parent = _templateElement.parentNode;
+    var insertBeforeNode = previousTerminator.nextNode;
+    for (var node in instanceNodes) {
+      parent.insertBefore(node, insertBeforeNode);
+    }
+  }
+
+  List<Node> extractInstanceAt(int index) {
+    var instanceNodes = <Node>[];
+    var previousTerminator = getTerminatorAt(index - 1);
+    var terminator = getTerminatorAt(index);
+    terminators.removeAt(index);
+
+    var parent = _templateElement.parentNode;
+    while (terminator != previousTerminator) {
+      var node = terminator;
+      terminator = node.previousNode;
+      node.remove();
+      instanceNodes.add(node);
+    }
+    return instanceNodes;
+  }
+
+  getInstanceModel(model, syntax) {
+    if (syntax != null) {
+      return syntax.getInstanceModel(_templateElement, model);
+    }
+    return model;
+  }
+
+  Node getInstanceFragment(syntax) {
+    if (syntax != null) {
+      return syntax.getInstanceFragment(_templateElement);
+    }
+    return _templateElement.createInstance();
+  }
+
+  List<Node> getInstanceNodes(model, syntax) {
+    // TODO(jmesserly): this line of code is jumping ahead of what MDV supports.
+    // It doesn't let the custom syntax override createInstance().
+    var fragment = getInstanceFragment(syntax);
+
+    _Bindings._addBindings(fragment, model, syntax);
+    _Bindings._addTemplateInstanceRecord(fragment, model);
+
+    var instanceNodes = fragment.nodes.toList();
+    fragment.nodes.clear();
+    return instanceNodes;
+  }
+
+  void _handleChanges(Iterable<ChangeRecord> splices) {
+    splices = splices.where((s) => s is ListChangeRecord);
+
+    var template = _templateElement;
+    var syntax = TemplateElement.syntax[template.attributes['syntax']];
+
+    if (template.parentNode == null || template.document.window == null) {
+      abandon();
+      // TODO(jmesserly): MDV calls templateIteratorTable.delete(this) here,
+      // but I think that's a no-op because only nodes are used as keys.
+      // See https://github.com/Polymer/mdv/pull/114.
+      return;
+    }
+
+    // TODO(jmesserly): IdentityMap matches JS semantics, but it's O(N) right
+    // now. See http://dartbug.com/4161.
+    var instanceCache = new IdentityMap();
+    var removeDelta = 0;
+    for (var splice in splices) {
+      for (int i = 0; i < splice.removedCount; i++) {
+        var instanceNodes = extractInstanceAt(splice.index + removeDelta);
+        var model = _mdv(instanceNodes.first)._templateInstance.model;
+        instanceCache[model] = instanceNodes;
+      }
+
+      removeDelta -= splice.addedCount;
+    }
+
+    for (var splice in splices) {
+      for (var addIndex = splice.index;
+          addIndex < splice.index + splice.addedCount;
+          addIndex++) {
+
+        var model = getInstanceModel(iteratedValue[addIndex], syntax);
+
+        var instanceNodes = instanceCache.remove(model);
+        if (instanceNodes == null) {
+          instanceNodes = getInstanceNodes(model, syntax);
+        }
+        insertInstanceAt(addIndex, instanceNodes);
+      }
+    }
+
+    for (var instanceNodes in instanceCache.values) {
+      instanceNodes.forEach(_unbindAllRecursively);
+    }
+  }
+
+  void unobserve() {
+    if (_sub == null) return;
+    _sub.cancel();
+    _sub = null;
+  }
+
+  void abandon() {
+    unobserve();
+    _valueBinding.cancel();
+    terminators.clear();
+    inputs.dispose();
+  }
+
+  static void _unbindAllRecursively(Node node) {
+    var nodeExt = _mdv(node);
+    nodeExt._templateInstance = null;
+    if (node is Element && (node as Element).isTemplate) {
+      // Make sure we stop observing when we remove an element.
+      var templateIterator = nodeExt._templateIterator;
+      if (templateIterator != null) {
+        templateIterator.abandon();
+        nodeExt._templateIterator = null;
+      }
+    }
+
+    _Bindings._nodeOrCustom(node).unbindAll();
+    for (var c = node.firstChild; c != null; c = c.nextNode) {
+      _unbindAllRecursively(c);
+    }
+  }
+}
diff --git a/pkg/mdv/lib/src/element.dart b/pkg/mdv/lib/src/element.dart
new file mode 100644
index 0000000..6c0f405
--- /dev/null
+++ b/pkg/mdv/lib/src/element.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of mdv;
+
+/** Extensions to the [Element] API. */
+class _ElementExtension extends _NodeExtension {
+  _ElementExtension(Element node) : super(node);
+
+  Element get node => super.node;
+
+  Map<String, StreamSubscription> _attributeBindings;
+
+  // TODO(jmesserly): should path be optional, and default to empty path?
+  // It is used that way in at least one path in JS TemplateElement tests
+  // (see "BindImperative" test in original JS code).
+  void bind(String name, model, String path) {
+    if (_attributeBindings == null) {
+      _attributeBindings = new Map<String, StreamSubscription>();
+    }
+
+    node.xtag.attributes.remove(name);
+
+    var changed;
+    if (name.endsWith('?')) {
+      name = name.substring(0, name.length - 1);
+
+      changed = (value) {
+        if (_Bindings._toBoolean(value)) {
+          node.xtag.attributes[name] = '';
+        } else {
+          node.xtag.attributes.remove(name);
+        }
+      };
+    } else {
+      changed = (value) {
+        // TODO(jmesserly): escape value if needed to protect against XSS.
+        // See https://github.com/polymer-project/mdv/issues/58
+        node.xtag.attributes[name] = value == null ? '' : '$value';
+      };
+    }
+
+    unbind(name);
+
+    _attributeBindings[name] =
+        new PathObserver(model, path).bindSync(changed);
+  }
+
+  void unbind(String name) {
+    if (_attributeBindings != null) {
+      var binding = _attributeBindings.remove(name);
+      if (binding != null) binding.cancel();
+    }
+  }
+
+  void unbindAll() {
+    if (_attributeBindings != null) {
+      for (var binding in _attributeBindings.values) {
+        binding.cancel();
+      }
+      _attributeBindings = null;
+    }
+  }
+}
diff --git a/pkg/mdv/lib/src/input_element.dart b/pkg/mdv/lib/src/input_element.dart
new file mode 100644
index 0000000..32b9834
--- /dev/null
+++ b/pkg/mdv/lib/src/input_element.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of mdv;
+
+/** Extensions to the [InputElement] API. */
+class _InputElementExtension extends _ElementExtension {
+  _InputElementExtension(InputElement node) : super(node);
+
+  InputElement get node => super.node;
+
+  _ValueBinding _valueBinding;
+
+  _CheckedBinding _checkedBinding;
+
+  void bind(String name, model, String path) {
+    switch (name) {
+      case 'value':
+        unbind('value');
+        node.attributes.remove('value');
+        _valueBinding = new _ValueBinding(node, model, path);
+        break;
+      case 'checked':
+        unbind('checked');
+        node.attributes.remove('checked');
+        _checkedBinding = new _CheckedBinding(node, model, path);
+        break;
+      default:
+        super.bind(name, model, path);
+        break;
+    }
+  }
+
+  void unbind(String name) {
+    switch (name) {
+      case 'value':
+        if (_valueBinding != null) {
+          _valueBinding.unbind();
+          _valueBinding = null;
+        }
+        break;
+      case 'checked':
+        if (_checkedBinding != null) {
+          _checkedBinding.unbind();
+          _checkedBinding = null;
+        }
+        break;
+      default:
+        super.unbind(name);
+        break;
+    }
+  }
+
+  void unbindAll() {
+    unbind('value');
+    unbind('checked');
+    super.unbindAll();
+  }
+}
diff --git a/pkg/mdv/lib/src/node.dart b/pkg/mdv/lib/src/node.dart
new file mode 100644
index 0000000..0379838
--- /dev/null
+++ b/pkg/mdv/lib/src/node.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of mdv;
+
+/** Extensions to the [Node] API. */
+class _NodeExtension {
+  final Node node;
+
+  _NodeExtension(this.node);
+
+  /**
+   * Binds the attribute [name] to the [path] of the [model].
+   * Path is a String of accessors such as `foo.bar.baz`.
+   */
+  void bind(String name, model, String path) {
+    window.console.error('Unhandled binding to Node: '
+        '$this $name $model $path');
+  }
+
+  /** Unbinds the attribute [name]. */
+  void unbind(String name) {}
+
+  /** Unbinds all bound attributes. */
+  void unbindAll() {}
+
+  TemplateInstance _templateInstance;
+
+  /** Gets the template instance that instantiated this node, if any. */
+  TemplateInstance get templateInstance =>
+      _templateInstance != null ? _templateInstance :
+      (node.parent != null ? node.parent.templateInstance : null);
+}
diff --git a/pkg/mdv/lib/src/template.dart b/pkg/mdv/lib/src/template.dart
new file mode 100644
index 0000000..9b379ea
--- /dev/null
+++ b/pkg/mdv/lib/src/template.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of mdv;
+
+/** Extensions to [Element]s that behave as templates. */
+class _TemplateExtension extends _ElementExtension {
+  var _model;
+  _TemplateIterator _templateIterator;
+
+  _TemplateExtension(Element node) : super(node);
+
+  void bind(String name, model, String path) {
+    switch (name) {
+      case 'bind':
+      case 'repeat':
+      case 'if':
+        if (_templateIterator == null) {
+          _templateIterator = new _TemplateIterator(node);
+        }
+        _templateIterator.inputs.bind(name, model, path);
+        return;
+      default:
+        super.bind(name, model, path);
+    }
+  }
+
+  void unbind(String name) {
+    switch (name) {
+      case 'bind':
+      case 'repeat':
+      case 'if':
+        if (_templateIterator != null) {
+          _templateIterator.inputs.unbind(name);
+        }
+        return;
+      default:
+        super.unbind(name);
+    }
+  }
+
+  void unbindAll() {
+    unbind('bind');
+    unbind('repeat');
+    unbind('if');
+    super.unbindAll();
+  }
+
+  /**
+   * Creates an instance of the template.
+   */
+  DocumentFragment createInstance() {
+    var template = node.ref;
+    if (template == null) template = node;
+
+    var instance = _Bindings._createDeepCloneAndDecorateTemplates(
+        template.content, node.attributes['syntax']);
+
+    if (_instanceCreated != null) {
+      _instanceCreated.add(instance);
+    }
+    return instance;
+  }
+
+  /**
+   * The data model which is inherited through the tree.
+   */
+  get model => _model;
+
+  void set model(value) {
+    var syntax = TemplateElement.syntax[node.attributes['syntax']];
+    _model = value;
+    _Bindings._addBindings(node, model, syntax);
+  }
+}
diff --git a/pkg/mdv/lib/src/text.dart b/pkg/mdv/lib/src/text.dart
new file mode 100644
index 0000000..6d2b380
--- /dev/null
+++ b/pkg/mdv/lib/src/text.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of mdv;
+
+/** Extensions to the [Text] API. */
+class _TextExtension extends _NodeExtension {
+  _TextExtension(Text node) : super(node);
+
+  Text get node => super.node;
+
+  StreamSubscription _textBinding;
+
+  void bind(String name, model, String path) {
+    if (name != 'text') {
+      super.bind(name, model, path);
+      return;
+    }
+
+    unbind('text');
+
+    _textBinding = new PathObserver(model, path).bindSync((value) {
+      node.text = value == null ? '' : '$value';
+    });
+  }
+
+  void unbind(String name) {
+    if (name != 'text') {
+      super.unbind(name);
+      return;
+    }
+
+    if (_textBinding == null) return;
+
+    _textBinding.cancel();
+    _textBinding = null;
+  }
+
+  void unbindAll() {
+    unbind('text');
+    super.unbindAll();
+  }
+}
diff --git a/pkg/mdv/pubspec.yaml b/pkg/mdv/pubspec.yaml
new file mode 100644
index 0000000..f1149f6
--- /dev/null
+++ b/pkg/mdv/pubspec.yaml
@@ -0,0 +1,15 @@
+name: mdv
+author: "Web UI Team <web-ui-dev@dartlang.org>"
+homepage: https://github.com/dart-lang/web-ui
+description: >
+  Model-Driven-Views (MDV) extends HTML and the DOM APIs to support a sensible
+  separation between the UI (DOM) of a document or application and its
+  underlying data (model).
+  Updates to the model are reflected in the DOM and user input into the DOM is
+  immediately assigned to the model.
+dependencies:
+  observe: any
+  # This is only for IdentityMap. See http://dartbug.com/4161.
+  serialization: any
+dev_dependencies:
+  unittest: any
diff --git a/tests/html/binding_syntax_test.dart b/pkg/mdv/test/binding_syntax_test.dart
similarity index 97%
rename from tests/html/binding_syntax_test.dart
rename to pkg/mdv/test/binding_syntax_test.dart
index 4e89a0a..55bb1f4 100644
--- a/tests/html/binding_syntax_test.dart
+++ b/pkg/mdv/test/binding_syntax_test.dart
@@ -7,15 +7,17 @@
 import 'dart:async';
 import 'dart:collection';
 import 'dart:html';
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:mdv/mdv.dart' as mdv;
+import 'package:observe/observe.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_observe_utils.dart';
+import 'observe_utils.dart';
 
 // Note: this file ported from
 // https://github.com/toolkitchen/mdv/blob/master/tests/syntax.js
 
 main() {
+  mdv.initialize();
   useHtmlConfiguration();
   group('Syntax', syntaxTests);
 }
diff --git a/tests/html/custom_element_bindings_test.dart b/pkg/mdv/test/custom_element_bindings_test.dart
similarity index 96%
rename from tests/html/custom_element_bindings_test.dart
rename to pkg/mdv/test/custom_element_bindings_test.dart
index 6548a7f..af9919e 100644
--- a/tests/html/custom_element_bindings_test.dart
+++ b/pkg/mdv/test/custom_element_bindings_test.dart
@@ -6,12 +6,14 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:mdv/mdv.dart' as mdv;
+import 'package:observe/observe.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_observe_utils.dart';
+import 'observe_utils.dart';
 
 main() {
+  mdv.initialize();
   useHtmlConfiguration();
   group('Custom Element Bindings', customElementBindingsTest);
 }
@@ -120,7 +122,7 @@
           '</my-custom-element>'
         '</template>');
 
-    TemplateElement.instanceCreated.listen((fragment) {
+    mdv.instanceCreated.listen((fragment) {
       for (var e in fragment.queryAll('my-custom-element')) {
         new MyCustomElement.attach(e);
       }
@@ -208,14 +210,12 @@
     switch (name) {
       case 'my-point':
         if (_sub1 != null) {
-          print('!!! unbind $name');
           _sub1.cancel();
           _sub1 = null;
         }
         return;
       case 'scary-monster':
         if (_sub2 != null) {
-          print('!!! unbind $name');
           _sub2.cancel();
           _sub2 = null;
         }
diff --git a/tests/html/element_bindings_test.dart b/pkg/mdv/test/element_bindings_test.dart
similarity index 87%
rename from tests/html/element_bindings_test.dart
rename to pkg/mdv/test/element_bindings_test.dart
index b960c99..e0f7973 100644
--- a/tests/html/element_bindings_test.dart
+++ b/pkg/mdv/test/element_bindings_test.dart
@@ -6,15 +6,17 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:mdv/mdv.dart' as mdv;
+import 'package:observe/observe.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_observe_utils.dart';
+import 'observe_utils.dart';
 
 // Note: this file ported from
 // https://github.com/toolkitchen/mdv/blob/master/tests/element_bindings.js
 
 main() {
+  mdv.initialize();
   useHtmlConfiguration();
   group('Element Bindings', elementBindingTests);
 }
@@ -187,8 +189,51 @@
 
     el.click();
     expect(model[sym('val')], false);
+
+    el.onClick.listen((_) {
+      expect(model[sym('val')], true);
+    });
+    el.onChange.listen((_) {
+      expect(model[sym('val')], true);
+    });
+
+    el.dispatchEvent(new MouseEvent('click', view: window));
   });
 
+  test('InputElementCheckbox - binding updated on click', () {
+    var model = toSymbolMap({'val': true});
+
+    var el = new InputElement();
+    testDiv.append(el);
+    el.type = 'checkbox';
+    el.bind('checked', model, 'val');
+    deliverChangeRecords();
+    expect(el.checked, true);
+
+    el.onClick.listen((_) {
+      expect(model[sym('val')], false);
+    });
+
+    el.dispatchEvent(new MouseEvent('click', view: window));
+  });
+
+  test('InputElementCheckbox - binding updated on change', () {
+    var model = toSymbolMap({'val': true});
+
+    var el = new InputElement();
+    testDiv.append(el);
+    el.type = 'checkbox';
+    el.bind('checked', model, 'val');
+    deliverChangeRecords();
+    expect(el.checked, true);
+
+    el.onChange.listen((_) {
+      expect(model[sym('val')], false);
+    });
+
+    el.dispatchEvent(new MouseEvent('click', view: window));
+   });
+
   test('InputElementRadio', () {
     var model = toSymbolMap({'val1': true, 'val2': false, 'val3': false,
         'val4': true});
diff --git a/tests/html/node_bindings_test.dart b/pkg/mdv/test/node_bindings_test.dart
similarity index 96%
rename from tests/html/node_bindings_test.dart
rename to pkg/mdv/test/node_bindings_test.dart
index fd08fd4..e97f3dce 100644
--- a/tests/html/node_bindings_test.dart
+++ b/pkg/mdv/test/node_bindings_test.dart
@@ -6,15 +6,17 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:mdv/mdv.dart' as mdv;
+import 'package:observe/observe.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_observe_utils.dart';
+import 'observe_utils.dart';
 
 // Note: this file ported from
 // https://github.com/toolkitchen/mdv/blob/master/tests/node_bindings.js
 
 main() {
+  mdv.initialize();
   useHtmlConfiguration();
   group('Node Bindings', nodeBindingTests);
 }
diff --git a/tests/html/mdv_observe_utils.dart b/pkg/mdv/test/observe_utils.dart
similarity index 84%
rename from tests/html/mdv_observe_utils.dart
rename to pkg/mdv/test/observe_utils.dart
index 56c3ceb..d3f33e1 100644
--- a/tests/html/mdv_observe_utils.dart
+++ b/pkg/mdv/test/observe_utils.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library mdv_observe_utils;
+library observe_utils;
 
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:observe/observe.dart';
 
 toSymbolMap(Map map) {
   var result = new ObservableMap.linked();
diff --git a/tests/html/template_element_test.dart b/pkg/mdv/test/template_element_test.dart
similarity index 89%
rename from tests/html/template_element_test.dart
rename to pkg/mdv/test/template_element_test.dart
index d71f854..10b39e1 100644
--- a/tests/html/template_element_test.dart
+++ b/pkg/mdv/test/template_element_test.dart
@@ -8,10 +8,11 @@
 import 'dart:collection';
 import 'dart:html';
 import 'dart:math' as math;
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:mdv/mdv.dart' as mdv;
+import 'package:observe/observe.dart';
 import 'package:unittest/html_config.dart';
 import 'package:unittest/unittest.dart';
-import 'mdv_observe_utils.dart';
+import 'observe_utils.dart';
 
 // Note: this file ported from
 // https://github.com/toolkitchen/mdv/blob/master/tests/template_element.js
@@ -20,6 +21,7 @@
 // look for "assertNodesAre".
 
 main() {
+  mdv.initialize();
   useHtmlConfiguration();
   group('Template Element', templateElementTests);
 }
@@ -71,6 +73,22 @@
     target.dispatchEvent(new Event(type, cancelable: false));
   }
 
+  var expando = new Expando('test');
+  void addExpandos(node) {
+    while (node != null) {
+      expando[node] = node.text;
+      node = node.nextNode;
+    }
+  }
+
+  void checkExpandos(node) {
+    expect(node, isNotNull);
+    while (node != null) {
+      expect(expando[node], node.text);
+      node = node.nextNode;
+    }
+  }
+
   test('Template', () {
     var div = createTestHtml('<template bind={{}}>text</template>');
     recursivelySetTemplateModel(div, null);
@@ -79,6 +97,31 @@
     expect(div.nodes.last.text, 'text');
   });
 
+  test('Template bind, no parent', () {
+    var div = createTestHtml('<template bind>text</template>');
+    var template = div.nodes[0];
+    template.remove();
+
+    recursivelySetTemplateModel(template, toSymbolMap({}));
+    deliverChangeRecords();
+    expect(template.nodes.length, 0);
+    expect(template.nextNode, null);
+    // TODO(jmesserly): the JS tests assert that observer callbacks had no
+    // exceptions. How do we replicate this?
+  });
+
+  test('Template bind, no defaultView', () {
+    var div = createTestHtml('<template bind>text</template>');
+    var template = div.nodes[0];
+    var doc = document.implementation.createHtmlDocument('');
+    doc.adoptNode(div);
+    recursivelySetTemplateModel(template, toSymbolMap({}));
+    deliverChangeRecords();
+    expect(div.nodes.length, 1);
+    // TODO(jmesserly): the JS tests assert that observer callbacks had no
+    // exceptions. How do we replicate this?
+  });
+
   test('Template-Empty Bind', () {
     var div = createTestHtml('<template bind>text</template>');
     recursivelySetTemplateModel(div, null);
@@ -240,6 +283,67 @@
     expect(div.nodes.length, 3);
   });
 
+  test('Repeat - Reuse Instances', () {
+    var div = createTestHtml('<template repeat>{{ val }}</template>');
+
+    var model = toSymbols([
+      {'val': 10},
+      {'val': 5},
+      {'val': 2},
+      {'val': 8},
+      {'val': 1}
+    ]);
+    recursivelySetTemplateModel(div, model);
+
+    deliverChanges(model);
+    expect(div.nodes.length, 6);
+    var template = div.firstChild;
+
+    addExpandos(template.nextNode);
+    checkExpandos(template.nextNode);
+
+    final VAL = const Symbol('val');
+    model.sort((a, b) => a[VAL] - b[VAL]);
+    deliverChanges(model);
+    checkExpandos(template.nextNode);
+
+    model = toObservable(model.reversed);
+    recursivelySetTemplateModel(div, model);
+    deliverChanges(model);
+    checkExpandos(template.nextNode);
+
+    for (var item in model) {
+      item[VAL] += 1;
+    }
+
+    deliverChanges(model);
+    expect(div.nodes[1].text, "11");
+    expect(div.nodes[2].text, "9");
+    expect(div.nodes[3].text, "6");
+    expect(div.nodes[4].text, "3");
+    expect(div.nodes[5].text, "2");
+  });
+
+  test('Bind - Reuse Instance', () {
+    var div = createTestHtml(
+        '<template bind="{{ foo }}">{{ bar }}</template>');
+
+    var model = toObservable({ 'foo': { 'bar': 5 }});
+    recursivelySetTemplateModel(div, model);
+
+    deliverChanges(model);
+    expect(div.nodes.length, 2);
+    var template = div.firstChild;
+
+    addExpandos(template.nextNode);
+    checkExpandos(template.nextNode);
+
+    model = toObservable({'foo': model['foo']});
+    recursivelySetTemplateModel(div, model);
+    deliverChanges(model);
+    checkExpandos(template.nextNode);
+  });
+
   test('Repeat-Empty', () {
     var div = createTestHtml(
         '<template repeat>text</template>');
@@ -943,6 +1047,39 @@
     expect(div.nodes[i++].text, 'Item 2');
   });
 
+  test('Attribute Template Option/Optgroup', () {
+    var div = createTestHtml(
+        '<template bind>'
+          '<select>'
+            '<optgroup template repeat="{{ groups }}" label="{{ name }}">'
+              '<option template repeat="{{ items }}">{{ val }}</option>'
+            '</optgroup>'
+          '</select>'
+        '</template>');
+
+    var m = toSymbols({
+      'selected': 1,
+      'groups': [{
+        'name': 'one', 'items': [{ 'val': 0 }, { 'val': 1 }]
+      }],
+    });
+
+    recursivelySetTemplateModel(div, m);
+    deliverChanges(m);
+
+    var select = div.nodes[0].nextNode;
+    expect(select.nodes.length, 2);
+    expect(select.nodes[0].tagName, 'TEMPLATE');
+    expect(select.nodes[0].ref.content.nodes[0].tagName, 'OPTGROUP');
+
+    var optgroup = select.nodes[1];
+    expect(optgroup.nodes[0].tagName, 'TEMPLATE');
+    expect(optgroup.nodes[1].tagName, 'OPTION');
+    expect(optgroup.nodes[1].text, '0');
+    expect(optgroup.nodes[2].tagName, 'OPTION');
+    expect(optgroup.nodes[2].text, '1');
+  });
+
   test('NestedIterateTableMixedSemanticNative', () {
     if (!TemplateElement.supported) return;
 
@@ -1212,14 +1349,15 @@
         '</template>');
     var template = div.nodes.first;
 
+    // Note: this test data is a little different from the JS version, because
+    // we allow binding to the "length" field of the Map in preference to
+    // binding keys.
     var m = toSymbols({
       'a': [
-        {'length': 0},
-        {
-          'length': 1,
-          'b': {'length': 4}
-        },
-        {'length': 2}
+        [],
+        { 'b': [1,2,3,4] },
+        // Note: this will use the Map "length" property, not the "length" key.
+        {'length': 42, 'c': 123}
       ]
     });
     recursivelySetTemplateModel(div, m);
@@ -1324,7 +1462,7 @@
     if (ShadowRoot.supported) {
       var root = createShadowTestHtml('Hi {{ name }}');
       var model = toSymbolMap({'name': 'Leela'});
-      TemplateElement.bindModel(root, model);
+      mdv.bindModel(root, model);
       deliverChangeRecords();
       expect(root.text, 'Hi Leela');
     }
@@ -1333,11 +1471,21 @@
   test('bindModel to polyfilled shadow root', () {
     var root = createTestHtml('Hi {{ name }}');
     var model = toSymbolMap({'name': 'Leela'});
-    TemplateElement.bindModel(root, model);
+    mdv.bindModel(root, model);
     deliverChangeRecords();
     expect(root.text, 'Hi Leela');
   });
 
+  test('BindShadowDOM Template Ref', () {
+    if (ShadowRoot.supported) {
+      var root = createShadowTestHtml(
+          '<template id=foo>Hi</template><template bind ref=foo></template>');
+      recursivelySetTemplateModel(root, toSymbolMap({}));
+      deliverChangeRecords();
+      expect(root.nodes.length, 3);
+    }
+  });
+
   // https://github.com/toolkitchen/mdv/issues/8
   test('UnbindingInNestedBind', () {
     var div = createTestHtml(
@@ -1445,7 +1593,7 @@
 
   test('instanceCreated hack', () {
     var called = false;
-    var sub = TemplateElement.instanceCreated.listen((node) {
+    var sub = mdv.instanceCreated.listen((node) {
       called = true;
       expect(node.nodeType, Node.DOCUMENT_FRAGMENT_NODE);
     });
diff --git a/pkg/mdv_observe/lib/mdv_observe.dart b/pkg/mdv_observe/lib/mdv_observe.dart
deleted file mode 100644
index 8864b36..0000000
--- a/pkg/mdv_observe/lib/mdv_observe.dart
+++ /dev/null
@@ -1,104 +0,0 @@
-// 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.
-
-/**
- * *Warning*: this library is experimental, and APIs are subject to change.
- *
- * This library is used to observe changes to [Observable] types. It also
- * has helpers to implement [Observable] objects.
- *
- * For example:
- *
- *     class Monster extends Object with ObservableMixin {
- *       static const _HEALTH = const Symbol('health');
- *
- *       int _health = 100;
- *       get health => _health;
- *       set health(value) {
- *         _health = notifyChange(_HEALTH, _health, value);
- *       }
- *
- *       void damage(int amount) {
- *         print('$this takes $amount damage!');
- *         health -= amount;
- *       }
- *
- *       toString() => 'Monster with $health hit points';
- *
- *       // These methods are temporary until dart2js supports mirrors.
- *       getValueWorkaround(key) {
- *         if (key == _HEALTH) return health;
- *         return null;
- *       }
- *       setValueWorkaround(key, val) {
- *         if (key == _HEALTH) health = val;
- *       }
- *     }
- *
- *     main() {
- *       var obj = new Monster();
- *       obj.changes.listen((records) {
- *         print('Changes to $obj were: $records');
- *       });
- *       // Schedules asynchronous delivery of these changes
- *       obj.damage(10);
- *       obj.damage(20);
- *       print('done!');
- *     }
- */
-library mdv_observe;
-
-import 'dart:collection';
-
-// Import and reexport the observe implementation library. It contains the types
-// that are required to implement Model-Driven-Views in dart:html.
-// NOTE: always use package:mdv_observe (this package) in your code!
-// DO NOT import mdv_observe_impl; it may break unpredictably.
-import 'dart:mdv_observe_impl';
-export 'dart:mdv_observe_impl';
-
-part 'src/observable_box.dart';
-part 'src/observable_list.dart';
-part 'src/observable_map.dart';
-
-
-/**
- * Converts the [Iterable] or [Map] to an [ObservableList] or [ObservableMap],
- * respectively. This is a convenience function to make it easier to convert
- * literals into the corresponding observable collection type.
- *
- * If [value] is not one of those collection types, or is already [Observable],
- * it will be returned unmodified.
- *
- * If [value] is a [Map], the resulting value will use the appropriate kind of
- * backing map: either [HashMap], [LinkedHashMap], or [SplayTreeMap].
- *
- * By default this performs a deep conversion, but you can set [deep] to false
- * for a shallow conversion. This does not handle circular data structures.
- */
-// TODO(jmesserly): ObservableSet?
-toObservable(value, {bool deep: true}) =>
-    deep ? _toObservableDeep(value) : _toObservableShallow(value);
-
-_toObservableShallow(value) {
-  if (value is Observable) return value;
-  if (value is Map) return new ObservableMap.from(value);
-  if (value is Iterable) return new ObservableList.from(value);
-  return value;
-}
-
-_toObservableDeep(value) {
-  if (value is Observable) return value;
-  if (value is Map) {
-    var result = new ObservableMap._createFromType(value);
-    value.forEach((k, v) {
-      result[_toObservableDeep(k)] = _toObservableDeep(v);
-    });
-    return result;
-  }
-  if (value is Iterable) {
-    return new ObservableList.from(value.map(_toObservableDeep));
-  }
-  return value;
-}
diff --git a/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart b/pkg/observe/lib/observe.dart
similarity index 69%
rename from sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
rename to pkg/observe/lib/observe.dart
index 9429da1..2f6a59d 100644
--- a/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
+++ b/pkg/observe/lib/observe.dart
@@ -2,17 +2,51 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// This library itself is undocumented and not supported for end use.
-// Because dart:html must use some of this functionality, it has to be available
-// via a dart:* library. The public APIs are reexported via package:mdv_observe.
-// Generally we try to keep this library minimal, with utility types and
-// functions in the package.
-library dart.mdv_observe_impl;
+/**
+ * *Warning*: this library is experimental, and APIs are subject to change.
+ *
+ * This library is used to observe changes to [Observable] types. It also
+ * has helpers to implement [Observable] objects.
+ *
+ * For example:
+ *
+ *     class Monster extends Unit with ObservableMixin {
+ *       int _health = 100;
+ *       get health => _health;
+ *       set health(value) {
+ *         _health = notifyChange(const Symbol('health'), _health, value);
+ *       }
+ *
+ *       void damage(int amount) {
+ *         print('$this takes $amount damage!');
+ *         health -= amount;
+ *       }
+ *
+ *       toString() => 'Monster with $health hit points';
+ *     }
+ *
+ *     main() {
+ *       var obj = new Monster();
+ *       obj.changes.listen((records) {
+ *         print('Changes to $obj were: $records');
+ *       });
+ *       // Schedules asynchronous delivery of these changes
+ *       obj.damage(10);
+ *       obj.damage(20);
+ *       print('done!');
+ *     }
+ */
+library observe;
 
 import 'dart:async';
 import 'dart:collection';
+import 'dart:mirrors';
 
-part 'path_observer.dart';
+part 'src/compound_binding.dart';
+part 'src/observable_box.dart';
+part 'src/observable_list.dart';
+part 'src/observable_map.dart';
+part 'src/path_observer.dart';
 
 /**
  * Interface representing an observable object. This is used by data in
@@ -33,21 +67,6 @@
    * [deliverChangeRecords] can be called to force delivery.
    */
   Stream<List<ChangeRecord>> get changes;
-
-  // TODO(jmesserly): remove these ASAP.
-  /**
-   * *Warning*: this method is temporary until dart2js supports mirrors.
-   * Gets the value of a field or index. This should return null if it was
-   * not found.
-   */
-  getValueWorkaround(key);
-
-  /**
-   * *Warning*: this method is temporary until dart2js supports mirrors.
-   * Sets the value of a field or index. This should have no effect if the field
-   * was not found.
-   */
-  void setValueWorkaround(key, Object value);
 }
 
 /**
@@ -226,3 +245,46 @@
 }
 
 Queue _deliverCallbacks;
+
+
+/**
+ * Converts the [Iterable] or [Map] to an [ObservableList] or [ObservableMap],
+ * respectively. This is a convenience function to make it easier to convert
+ * literals into the corresponding observable collection type.
+ *
+ * If [value] is not one of those collection types, or is already [Observable],
+ * it will be returned unmodified.
+ *
+ * If [value] is a [Map], the resulting value will use the appropriate kind of
+ * backing map: either [HashMap], [LinkedHashMap], or [SplayTreeMap].
+ *
+ * By default this performs a deep conversion, but you can set [deep] to false
+ * for a shallow conversion. This does not handle circular data structures.
+ * If a conversion is peformed, mutations are only observed to the result of
+ * this function. Changing the original collection will not affect it.
+ */
+// TODO(jmesserly): ObservableSet?
+toObservable(value, {bool deep: true}) =>
+    deep ? _toObservableDeep(value) : _toObservableShallow(value);
+
+_toObservableShallow(value) {
+  if (value is Observable) return value;
+  if (value is Map) return new ObservableMap.from(value);
+  if (value is Iterable) return new ObservableList.from(value);
+  return value;
+}
+
+_toObservableDeep(value) {
+  if (value is Observable) return value;
+  if (value is Map) {
+    var result = new ObservableMap._createFromType(value);
+    value.forEach((k, v) {
+      result[_toObservableDeep(k)] = _toObservableDeep(v);
+    });
+    return result;
+  }
+  if (value is Iterable) {
+    return new ObservableList.from(value.map(_toObservableDeep));
+  }
+  return value;
+}
diff --git a/pkg/observe/lib/src/compound_binding.dart b/pkg/observe/lib/src/compound_binding.dart
new file mode 100644
index 0000000..c239abe
--- /dev/null
+++ b/pkg/observe/lib/src/compound_binding.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of observe;
+
+/** The callback used in the [CompoundBinding.combinator] field. */
+typedef Object CompoundBindingCombinator(Map objects);
+
+/**
+ * Model-Driven Views contains a helper object which is useful for the
+ * implementation of a Custom Syntax.
+ *
+ *     var binding = new CompoundBinding((values) {
+ *       var combinedValue;
+ *       // compute combinedValue based on the current values which are provided
+ *       return combinedValue;
+ *     });
+ *     binding.bind('name1', obj1, path1);
+ *     binding.bind('name2', obj2, path2);
+ *     //...
+ *     binding.bind('nameN', objN, pathN);
+ *
+ * CompoundBinding is an object which knows how to listen to multiple path
+ * values (registered via [bind]) and invoke its [combinator] when one or more
+ * of the values have changed and set its [value] property to the return value
+ * of the function. When any value has changed, all current values are provided
+ * to the [combinator] in the single `values` argument.
+ */
+// TODO(jmesserly): rename to something that indicates it's a computed value?
+class CompoundBinding extends ObservableBase {
+  CompoundBindingCombinator _combinator;
+
+  // TODO(jmesserly): ideally these would be String keys, but sometimes we
+  // use integers.
+  Map<dynamic, StreamSubscription> _bindings = new Map();
+  Map _values = new Map();
+  bool _scheduled = false;
+  bool _disposed = false;
+  Object _value;
+
+  CompoundBinding([CompoundBindingCombinator combinator]) {
+    // TODO(jmesserly): this is a tweak to the original code, it seemed to me
+    // that passing the combinator to the constructor should be equivalent to
+    // setting it via the property.
+    // I also added a null check to the combinator setter.
+    this.combinator = combinator;
+  }
+
+  CompoundBindingCombinator get combinator => _combinator;
+
+  set combinator(CompoundBindingCombinator combinator) {
+    _combinator = combinator;
+    if (combinator != null) _scheduleResolve();
+  }
+
+  static const _VALUE = const Symbol('value');
+
+  get value => _value;
+
+  void set value(newValue) {
+    _value = notifyPropertyChange(_VALUE, _value, newValue);
+  }
+
+  void bind(name, model, String path) {
+    unbind(name);
+
+    _bindings[name] = new PathObserver(model, path).bindSync((value) {
+      _values[name] = value;
+      _scheduleResolve();
+    });
+  }
+
+  void unbind(name, {bool suppressResolve: false}) {
+    var binding = _bindings.remove(name);
+    if (binding == null) return;
+
+    binding.cancel();
+    _values.remove(name);
+    if (!suppressResolve) _scheduleResolve();
+  }
+
+  // TODO(rafaelw): Is this the right processing model?
+  // TODO(rafaelw): Consider having a seperate ChangeSummary for
+  // CompoundBindings so to excess dirtyChecks.
+  void _scheduleResolve() {
+    if (_scheduled) return;
+    _scheduled = true;
+    queueChangeRecords(resolve);
+  }
+
+  void resolve() {
+    if (_disposed) return;
+    _scheduled = false;
+
+    if (_combinator == null) {
+      throw new StateError(
+          'CompoundBinding attempted to resolve without a combinator');
+    }
+
+    value = _combinator(_values);
+  }
+
+  void dispose() {
+    for (var binding in _bindings.values) {
+      binding.cancel();
+    }
+    _bindings.clear();
+    _values.clear();
+
+    _disposed = true;
+    value = null;
+  }
+}
diff --git a/pkg/mdv_observe/lib/src/observable_box.dart b/pkg/observe/lib/src/observable_box.dart
similarity index 73%
rename from pkg/mdv_observe/lib/src/observable_box.dart
rename to pkg/observe/lib/src/observable_box.dart
index 484a900..7cc8fac 100644
--- a/pkg/mdv_observe/lib/src/observable_box.dart
+++ b/pkg/observe/lib/src/observable_box.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv_observe;
+part of observe;
 
 // TODO(jmesserly): should the property name be configurable?
 // That would be more convenient.
@@ -13,8 +13,6 @@
  * [ObservableMixin]. The property name for changes is "value".
  */
 class ObservableBox<T> extends ObservableBase {
-  static const _VALUE = const Symbol('value');
-
   T _value;
 
   ObservableBox([T initialValue]) : _value = initialValue;
@@ -22,16 +20,8 @@
   T get value => _value;
 
   void set value(T newValue) {
-    _value = notifyPropertyChange(_VALUE, _value, newValue);
+    _value = notifyPropertyChange(const Symbol('value'), _value, newValue);
   }
 
   String toString() => '#<$runtimeType value: $value>';
-
-  getValueWorkaround(key) {
-    if (key == _VALUE) return value;
-    return null;
-  }
-  void setValueWorkaround(key, newValue) {
-    if (key == _VALUE) value = newValue;
-  }
 }
diff --git a/pkg/mdv_observe/lib/src/observable_list.dart b/pkg/observe/lib/src/observable_list.dart
similarity index 96%
rename from pkg/mdv_observe/lib/src/observable_list.dart
rename to pkg/observe/lib/src/observable_list.dart
index 66ca771..bc66ea02 100644
--- a/pkg/mdv_observe/lib/src/observable_list.dart
+++ b/pkg/observe/lib/src/observable_list.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv_observe;
+part of observe;
 
 /**
  * Represents an observable list of model values. If any items are added,
@@ -14,8 +14,6 @@
     implements List<E> {
   List<ListChangeRecord> _records;
 
-  static const _LENGTH = const Symbol('length');
-
   /** The inner [List<E>] with the actual storage. */
   final List<E> _list;
 
@@ -38,13 +36,6 @@
   factory ObservableList.from(Iterable<E> other) =>
       new ObservableList<E>()..addAll(other);
 
-  // TODO(jmesserly): remove once we have mirrors
-  getValueWorkaround(key) => key == _LENGTH ? length : null;
-
-  setValueWorkaround(key, value) {
-    if (key == _LENGTH) length = value;
-  }
-
   int get length => _list.length;
 
   set length(int value) {
@@ -230,7 +221,7 @@
     }
 
     if (length != oldLength) {
-      notifyPropertyChange(_LENGTH, oldLength, length);
+      notifyPropertyChange(const Symbol('length'), oldLength, length);
     }
 
     if (_records.length == 1) {
diff --git a/pkg/mdv_observe/lib/src/observable_map.dart b/pkg/observe/lib/src/observable_map.dart
similarity index 97%
rename from pkg/mdv_observe/lib/src/observable_map.dart
rename to pkg/observe/lib/src/observable_map.dart
index 3ce2d82..0c345fb 100644
--- a/pkg/mdv_observe/lib/src/observable_map.dart
+++ b/pkg/observe/lib/src/observable_map.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of mdv_observe;
+part of observe;
 
 // TODO(jmesserly): this needs to be faster. We currently require multiple
 // lookups per key to get the old value.
@@ -68,7 +68,7 @@
    */
   factory ObservableMap.from(Map<K, V> other) {
     var result = new ObservableMap<K, V>._createFromType(other);
-    other.forEach((K key, V value) { result[key] = value; });
+    other.forEach((key, value) { result[key] = value; });
     return result;
   }
 
diff --git a/sdk/lib/mdv_observe_impl/path_observer.dart b/pkg/observe/lib/src/path_observer.dart
similarity index 93%
rename from sdk/lib/mdv_observe_impl/path_observer.dart
rename to pkg/observe/lib/src/path_observer.dart
index 5d3fae4..7f26c39 100644
--- a/sdk/lib/mdv_observe_impl/path_observer.dart
+++ b/pkg/observe/lib/src/path_observer.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of dart.mdv_observe_impl;
+part of observe;
 
 // This code is inspired by ChangeSummary:
 // https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
@@ -171,7 +171,6 @@
   }
 }
 
-// TODO(jmesserly): these should go away in favor of mirrors!
 _getObjectProperty(object, property) {
   if (object is List && property is int) {
     if (property >= 0 && property < object.length) {
@@ -181,27 +180,45 @@
     }
   }
 
-  // TODO(jmesserly): what about length?
-  if (object is Map) return object[property];
+  if (property is Symbol) {
+    var mirror = reflect(object);
+    try {
+      return mirror.getField(property).reflectee;
+    } catch (e) {}
+  }
 
-  if (object is Observable) return object.getValueWorkaround(property);
+  if (object is Map) {
+    return object[property];
+  }
 
   return null;
 }
 
 bool _setObjectProperty(object, property, value) {
   if (object is List && property is int) {
-    object[property] = value;
-  } else if (object is Map) {
-    object[property] = value;
-  } else if (object is Observable) {
-    (object as Observable).setValueWorkaround(property, value);
-  } else {
-    return false;
+    if (property >= 0 && property < object.length) {
+      object[property] = value;
+      return true;
+    } else {
+      return false;
+    }
   }
-  return true;
-}
 
+  if (property is Symbol) {
+    var mirror = reflect(object);
+    try {
+      mirror.setField(property, value);
+      return true;
+    } catch (e) {}
+  }
+
+  if (object is Map) {
+    object[property] = value;
+    return true;
+  }
+
+  return false;
+}
 
 class _PropertyObserver {
   final PathObserver _path;
diff --git a/pkg/mdv_observe/pubspec.yaml b/pkg/observe/pubspec.yaml
similarity index 96%
rename from pkg/mdv_observe/pubspec.yaml
rename to pkg/observe/pubspec.yaml
index 59da442..6479be6 100644
--- a/pkg/mdv_observe/pubspec.yaml
+++ b/pkg/observe/pubspec.yaml
@@ -1,4 +1,4 @@
-name: mdv_observe
+name: observe
 author: "Web UI Team <web-ui-dev@dartlang.org>"
 homepage: https://github.com/dart-lang/web-ui
 description: >
diff --git a/pkg/mdv_observe/test/list_change_test.dart b/pkg/observe/test/list_change_test.dart
similarity index 99%
rename from pkg/mdv_observe/test/list_change_test.dart
rename to pkg/observe/test/list_change_test.dart
index e7e1249..46b04ed 100644
--- a/pkg/mdv_observe/test/list_change_test.dart
+++ b/pkg/observe/test/list_change_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:observe/observe.dart';
 import 'package:unittest/unittest.dart';
 import 'utils.dart';
 
diff --git a/pkg/mdv_observe/test/observable_list_test.dart b/pkg/observe/test/observable_list_test.dart
similarity index 98%
rename from pkg/mdv_observe/test/observable_list_test.dart
rename to pkg/observe/test/observable_list_test.dart
index 3a4c945..e211243 100644
--- a/pkg/mdv_observe/test/observable_list_test.dart
+++ b/pkg/observe/test/observable_list_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:observe/observe.dart';
 import 'package:unittest/unittest.dart';
 import 'utils.dart';
 
diff --git a/pkg/mdv_observe/test/observable_map_test.dart b/pkg/observe/test/observable_map_test.dart
similarity index 98%
rename from pkg/mdv_observe/test/observable_map_test.dart
rename to pkg/observe/test/observable_map_test.dart
index 155bfe1..35f7613 100644
--- a/pkg/mdv_observe/test/observable_map_test.dart
+++ b/pkg/observe/test/observable_map_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:observe/observe.dart';
 import 'package:unittest/unittest.dart';
 import 'utils.dart';
 
diff --git a/pkg/mdv_observe/test/observe_test.dart b/pkg/observe/test/observe_test.dart
similarity index 98%
rename from pkg/mdv_observe/test/observe_test.dart
rename to pkg/observe/test/observe_test.dart
index 8d6e6d3b..e60f740 100644
--- a/pkg/mdv_observe/test/observe_test.dart
+++ b/pkg/observe/test/observe_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:observe/observe.dart';
 import 'package:unittest/unittest.dart';
 import 'utils.dart';
 
diff --git a/pkg/mdv_observe/test/path_observer_test.dart b/pkg/observe/test/path_observer_test.dart
similarity index 84%
rename from pkg/mdv_observe/test/path_observer_test.dart
rename to pkg/observe/test/path_observer_test.dart
index 4222f73..471ca27 100644
--- a/pkg/mdv_observe/test/path_observer_test.dart
+++ b/pkg/observe/test/path_observer_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:mdv_observe/mdv_observe.dart';
+import 'package:observe/observe.dart';
 import 'package:unittest/unittest.dart';
 
 // This file contains code ported from:
@@ -163,45 +163,43 @@
   });
 
   test('Path Observation', () {
-    var model = new TestModel(const Symbol('a'),
-        new TestModel(const Symbol('b'),
-            new TestModel(const Symbol('c'), 'hello, world')));
+    var model = new TestModel()..a =
+        (new TestModel()..b = (new TestModel()..c = 'hello, world'));
 
     var path = observePath(model, 'a.b.c');
     var lastValue = null;
     var sub = path.values.listen((v) { lastValue = v; });
 
-    model.value.value.value = 'hello, mom';
+    model.a.b.c = 'hello, mom';
 
     expect(lastValue, null);
     deliverChangeRecords();
     expect(lastValue, 'hello, mom');
 
-    model.value.value = new TestModel(const Symbol('c'), 'hello, dad');
+    model.a.b = new TestModel()..c = 'hello, dad';
     deliverChangeRecords();
     expect(lastValue, 'hello, dad');
 
-    model.value = new TestModel(const Symbol('b'),
-        new TestModel(const Symbol('c'), 'hello, you'));
+    model.a = new TestModel()..b =
+        (new TestModel()..c = 'hello, you');
     deliverChangeRecords();
     expect(lastValue, 'hello, you');
 
-    model.value.value = 1;
+    model.a.b = 1;
     deliverChangeRecords();
     expect(lastValue, null);
 
     // Stop observing
     sub.cancel();
 
-    model.value.value = new TestModel(const Symbol('c'),
-        'hello, back again -- but not observing');
+    model.a.b = new TestModel()..c = 'hello, back again -- but not observing';
     deliverChangeRecords();
     expect(lastValue, null);
 
     // Resume observing
     sub = path.values.listen((v) { lastValue = v; });
 
-    model.value.value.value = 'hello. Back for reals';
+    model.a.b.c = 'hello. Back for reals';
     deliverChangeRecords();
     expect(lastValue, 'hello. Back for reals');
   });
@@ -226,24 +224,25 @@
 }
 
 class TestModel extends ObservableBase {
-  final Symbol fieldName;
-  var _value;
+  var _a, _b, _c;
 
-  TestModel(this.fieldName, [initialValue]) : _value = initialValue;
+  TestModel();
 
-  get value => _value;
+  get a => _a;
 
-  void set value(newValue) {
-    _value = notifyPropertyChange(fieldName, _value, newValue);
+  void set a(newValue) {
+    _a = notifyPropertyChange(const Symbol('a'), _a, newValue);
   }
 
-  getValueWorkaround(key) {
-    if (key == fieldName) return value;
-    return null;
-  }
-  void setValueWorkaround(key, newValue) {
-    if (key == fieldName) value = newValue;
+  get b => _b;
+
+  void set b(newValue) {
+    _b = notifyPropertyChange(const Symbol('b'), _b, newValue);
   }
 
-  toString() => '#<$runtimeType $fieldName: $_value>';
+  get c => _c;
+
+  void set c(newValue) {
+    _c = notifyPropertyChange(const Symbol('c'), _c, newValue);
+  }
 }
diff --git a/pkg/mdv_observe/test/utils.dart b/pkg/observe/test/utils.dart
similarity index 71%
rename from pkg/mdv_observe/test/utils.dart
rename to pkg/observe/test/utils.dart
index 5dd5e38..dafedc1 100644
--- a/pkg/mdv_observe/test/utils.dart
+++ b/pkg/observe/test/utils.dart
@@ -2,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library mdv_observe.test.utils;
+library observe.test.utils;
 
 import 'package:unittest/unittest.dart';
 
-// TODO(jmesserly): use matchers when this is supported. For now just
-// compare to toStrings.
+// TODO(jmesserly): use matchers when we have a way to compare ChangeRecords.
+// For now just use the toString.
 expectChanges(actual, expected, {reason}) =>
     expect('$actual', '$expected', reason: reason);
diff --git a/pkg/pkg.status b/pkg/pkg.status
index da54056..31818ec 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -32,6 +32,7 @@
 
 [ $runtime == d8 || $runtime == jsshell ]
 unittest/test/unittest_test: Pass, Fail # http://dartbug.com/10109
+stack_trace/test/vm_test: Fail, OK # VM-specific traces
 
 [$compiler == dart2dart]
 *: Skip
@@ -106,6 +107,7 @@
 
 [ $compiler == dart2js && $browser ]
 pathos/test/pathos_dartium_test: Fail # Issue 6490
+stack_trace/test/vm_test: Fail, OK # VM-specific traces
 crypto/test/sha256_test: Slow, Pass
 crypto/test/sha1_test: Slow, Pass
 
@@ -157,9 +159,6 @@
 scheduled_test/test/scheduled_test/wrap_async_test: Fail # http://dartbug.com/8440
 scheduled_test/test/scheduled_test/wrap_future_test: Fail # http://dartbug.com/8440
 
-stack_trace/test/frame_test: Fail # http://dartbug.com/6943
-stack_trace/test/trace_test: Fail # http://dartbug.com/6943
-
 
 [ $runtime == safari]
  # Bug in JSC: the test only passes when being debugged.
@@ -194,6 +193,6 @@
 [ ($runtime == dartium || $runtime == drt) && $compiler == none ]
 pathos/test/pathos_dart2js_test: Fail, OK # Issue 6490
 
-# Skip mdv_observe tests on command line VM, they only run in the browser.
+# Skip mdv tests on command line VM, they only run in the browser.
 [ $runtime == vm ]
-mdv_observe: Skip
+mdv: Skip
diff --git a/pkg/serialization/lib/serialization.dart b/pkg/serialization/lib/serialization.dart
index 522a7d1..5ec329d 100644
--- a/pkg/serialization/lib/serialization.dart
+++ b/pkg/serialization/lib/serialization.dart
@@ -361,7 +361,7 @@
    * The [format] parameter determines the form of the result. The default
    * format returns a String in [json] format.
    */
-  write(Object object, [Format format]) {
+  write(Object object, {Format format}) {
     return newWriter(format).write(object);
   }
 
@@ -370,13 +370,14 @@
    * want to do something more complex with the writer than just returning
    * the final result.
    */
-  Writer newWriter([Format format]) =>
-      new Writer(this, format);
+  Writer newWriter([Format format]) => new Writer(this, format);
 
   /**
    * Read the serialized data from [input] and return the root object
    * from the result. The [input] can be of any type that the [Format]
    * reads/writes, but normally will be a [List], [Map], or a simple type.
+   * The [format] parameter determines the form of the result. The default
+   * format returns a String in [json] format.
    * If there are objects that need to be resolved
    * in the current context, they should be provided in [externals] as a
    * Map from names to values. In particular, in the current implementation
@@ -384,8 +385,8 @@
    * class name as a key. In addition to the [externals] map provided here,
    * values will be looked up in the [namedObjects] map.
    */
-  read(input, [Map externals = const {}]) {
-    return newReader().read(input, externals);
+  read(input, {Format format, Map externals: const {}}) {
+    return newReader(format).read(input, externals);
   }
 
   /**
@@ -500,6 +501,6 @@
  */
 class SerializationException implements Exception {
   final String message;
-  const SerializationException([this.message]);
-  toString() => "SerializationException($message)";
+  const SerializationException(this.message);
+  String toString() => "SerializationException($message)";
 }
diff --git a/pkg/serialization/lib/src/format.dart b/pkg/serialization/lib/src/format.dart
index 2c71e42..791cc83 100644
--- a/pkg/serialization/lib/src/format.dart
+++ b/pkg/serialization/lib/src/format.dart
@@ -115,7 +115,7 @@
    * of [Reference] objects instead of the [Reference] so that the structure
    * can be serialized between isolates and json easily.
    */
-  forAllStates(ReaderOrWriter w, bool predicate(value),
+  void forAllStates(ReaderOrWriter w, bool predicate(value),
                void transform(value)) {
     for (var eachRule in w.rules) {
       var ruleData = w.states[eachRule.number];
@@ -214,7 +214,7 @@
    * of Reference objects and to add rule numbers if [storeRoundTripInfo]
    * is true.
    */
-  jsonify(Writer w) {
+  void jsonify(Writer w) {
     for (var eachRule in w.rules) {
       var ruleData = w.states[eachRule.number];
       jsonifyForRule(ruleData, w, eachRule);
@@ -224,7 +224,7 @@
   /**
    * For a particular [rule] modify the [ruleData] to conform to this format.
    */
-  jsonifyForRule(List ruleData, Writer w, SerializationRule rule) {
+  void jsonifyForRule(List ruleData, Writer w, SerializationRule rule) {
     for (var i = 0; i < ruleData.length; i++) {
       var each = ruleData[i];
       if (each is List) {
@@ -241,7 +241,7 @@
    * For one particular entry, which is either a Map or a List, update it
    * to turn References into a nested List/Map.
    */
-  jsonifyEntry(map, Writer w) {
+  void jsonifyEntry(map, Writer w) {
     // Note, if this is a Map, and the key might be a reference, we need to
     // bend over backwards to avoid concurrent modifications. Non-string keys
     // won't actually work if we try to write this to json, but might happen
@@ -496,7 +496,7 @@
    * Read data for [rule] from [input] with [length] number of entries,
    * creating lists from the results.
    */
-  readLists(Iterator input, SerializationRule rule, int length, Reader r) {
+  List readLists(Iterator input, SerializationRule rule, int length, Reader r) {
     var ruleData = [];
     for (var i = 0; i < length; i++) {
       var subLength =
@@ -514,7 +514,7 @@
    * Read data for [rule] from [input] with [length] number of entries,
    * creating maps from the results.
    */
-  readMaps(Iterator input, SerializationRule rule, int length, Reader r) {
+  List readMaps(Iterator input, SerializationRule rule, int length, Reader r) {
     var ruleData = [];
     for (var i = 0; i < length; i++) {
       var subLength =
@@ -534,7 +534,7 @@
    * Read data for [rule] from [input] with [length] number of entries,
    * treating the data as primitives that can be returned directly.
    */
-  readPrimitives(Iterator input, SerializationRule rule, int length) {
+  List readPrimitives(Iterator input, SerializationRule rule, int length) {
     var ruleData = [];
     for (var i = 0; i < length; i++) {
       ruleData.add(_next(input));
diff --git a/pkg/serialization/test/serialization_test.dart b/pkg/serialization/test/serialization_test.dart
index 1e2d3aa..3c20605 100644
--- a/pkg/serialization/test/serialization_test.dart
+++ b/pkg/serialization/test/serialization_test.dart
@@ -297,10 +297,10 @@
     var metaWithMaps = metaSerializationUsingMaps();
     for (var eachFormat in formats) {
       for (var eachMeta in [meta, metaWithMaps]) {
-        var serialized = eachMeta.write(s, eachFormat);
-        var reader = new Reader(eachMeta, eachFormat);
-        var newSerialization = reader.read(serialized,
-           {"serialization_test.Node" : reflect(new Node('')).type});
+        var serialized = eachMeta.write(s, format: eachFormat);
+        var newSerialization = eachMeta.read(serialized, format: eachFormat,
+            externals: {"serialization_test.Node" : reflect(new Node('')).type}
+        );
         runRoundTripTest((x) => newSerialization);
       }
     }
@@ -339,9 +339,7 @@
     var s = new Serialization()
       ..selfDescribing = false
       ..addRuleFor(n1, constructorFields: ["name"]);
-    var w = new Writer(s);
-    var r = new Reader(s);
-    var m1 = r.read(w.write(n1));
+    var m1 = writeAndReadBack(s, null, n1);
     var m2 = m1.children.first;
     var m3 = m1.children.last;
     expect(m1, m2);
@@ -437,8 +435,7 @@
     for (var eachFormat in formats) {
       var w = s.newWriter(eachFormat);
       var output = w.write({"stuff" : p1});
-      var r = s.newReader(w.format);
-      var result = r.read(output);
+      var result = s.read(output, format: w.format);
       var p2 = result["stuff"];
       expect(p2.name, "Alice");
       var a2 = p2.address;
@@ -482,10 +479,9 @@
       ..addRuleFor(a1)
       ..addRuleFor(p1).configureForMaps()
       ..namedObjects["foo"] = a1;
-    var writer = s.newWriter(const SimpleJsonFormat(storeRoundTripInfo: true));
-    var out = writer.write(p1);
-    var reader = s.newReader(const SimpleJsonFormat(storeRoundTripInfo: true));
-    var p2 = reader.read(out, {"foo" : 12});
+    var format = const SimpleJsonFormat(storeRoundTripInfo: true);
+    var out = s.write(p1, format: format);
+    var p2 = s.read(out, format: format, externals: {"foo" : 12});
     expect(p2.name, "Alice");
     var a2 = p2.address;
     expect(a2, 12);
@@ -499,9 +495,8 @@
     data[p1] = a1;
     data[a1] = p1;
     for (var eachFormat in formats) {
-      var output = s.write(data, eachFormat);
-      var reader = s.newReader(eachFormat);
-      var input = reader.read(output);
+      var output = s.write(data, format: eachFormat);
+      var input = s.read(output, format: eachFormat);
       expect(input["simple data"], data["simple data"]);
       var p2 = input.keys.firstWhere((x) => x is Person);
       var a2 = input.keys.firstWhere((x) => x is Address);
@@ -528,7 +523,7 @@
     var s = new Serialization()..addRuleFor(new Person());
     var data = {"abc" : 1, "def" : "ghi"};
     data["person"] = new Person()..name = "Foo";
-    var output = s.write(data, const InternalMapFormat());
+    var output = s.write(data, format: const InternalMapFormat());
     var mapRule = s.rules.firstWhere((x) => x is MapRule);
     var map = output["data"][mapRule.number][0];
     expect(map is Map, isTrue);
@@ -563,8 +558,7 @@
  */
 void verify(input) {
   var s2 = nodeSerializerReflective(new Node("a"));
-  var reader = new Reader(s2);
-  var m2 = reader.read(input);
+  var m2 = s2.read(input);
   var m1 = m2.parent;
   expect(m1 is Node, isTrue);
   var children = m1.children;
@@ -583,10 +577,8 @@
  ******************************************************************************/
 
 writeAndReadBack(Serialization s, Format format, object) {
-  var w = s.newWriter(format);
-  var output = w.write(object);
-  var r = s.newReader(w.format);
-  return r.read(output);
+  var output = s.write(object, format: format);
+  return s.read(output, format: format);
 }
 
 /** Create a Serialization for serializing Serializations. */
@@ -726,8 +718,7 @@
   var s = serializerSetUp(n1);
   var output = s.write(n2);
   var s2 = serializerSetUp(n1);
-  var reader = new Reader(s2);
-  var m2 = reader.read(output);
+  var m2 = s2.read(output);
   var m1 = m2.parent;
   expect(m1 is Node, isTrue);
   var children = m1.children;
@@ -750,11 +741,10 @@
   n2.parent = n1;
   n3.parent = n1;
   var s = serializerSetUp(n1);
-  var output = s.write(n2, const SimpleFlatFormat());
+  var output = s.write(n2, format: const SimpleFlatFormat());
   expect(output is List, isTrue);
   var s2 = serializerSetUp(n1);
-  var reader = new Reader(s2, const SimpleFlatFormat());
-  var m2 = reader.read(output);
+  var m2 = s2.read(output, format: const SimpleFlatFormat());
   var m1 = m2.parent;
   expect(m1 is Node, isTrue);
   var children = m1.children;
diff --git a/pkg/stack_trace/lib/src/frame.dart b/pkg/stack_trace/lib/src/frame.dart
index d750b91..6daca46 100644
--- a/pkg/stack_trace/lib/src/frame.dart
+++ b/pkg/stack_trace/lib/src/frame.dart
@@ -9,9 +9,23 @@
 
 import 'trace.dart';
 
-final _nativeFrameRegExp = new RegExp(
+// #1      Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)
+final _vmFrame = new RegExp(
     r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$');
 
+//     at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28)
+//     at http://pub.dartlang.org/stuff.dart.js:560:28
+final _v8Frame = new RegExp(
+    r'^\s*at (?:([^\s].*) \((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$');
+
+// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560
+// .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560
+// .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560
+final _firefoxFrame = new RegExp(
+    r'^([^@(/]*)(?:\(.*\))?(/[^<]*<?)?(?:\(.*\))?@(.*):(\d+)$');
+
+final _initialDot = new RegExp(r"^\.");
+
 /// A single stack frame. Each frame points to a precise location in Dart code.
 class Frame {
   /// The URI of the file in which the code is located.
@@ -76,13 +90,11 @@
     return new Trace.current(level + 1).frames.first;
   }
 
-  /// Parses a string representation of a stack frame.
-  ///
-  /// [frame] should be formatted in the same way as a native stack trace frame.
-  factory Frame.parse(String frame) {
-    var match = _nativeFrameRegExp.firstMatch(frame);
+  /// Parses a string representation of a Dart VM stack frame.
+  factory Frame.parseVM(String frame) {
+    var match = _vmFrame.firstMatch(frame);
     if (match == null) {
-      throw new FormatException("Couldn't parse stack trace line '$frame'.");
+      throw new FormatException("Couldn't parse VM stack trace line '$frame'.");
     }
 
     var uri = Uri.parse(match[2]);
@@ -90,6 +102,48 @@
     return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member);
   }
 
+  /// Parses a string representation of a Chrome/V8 stack frame.
+  factory Frame.parseV8(String frame) {
+    var match = _v8Frame.firstMatch(frame);
+    if (match == null) {
+      throw new FormatException("Couldn't parse V8 stack trace line '$frame'.");
+    }
+
+    // V8 stack frames can be in two forms.
+    if (match[2] != null) {
+      // The first form looks like "  at FUNCTION (URI:LINE:COL)"
+      var uri = Uri.parse(match[2]);
+      var member = match[1].replaceAll("<anonymous>", "<fn>");
+      return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member);
+    } else {
+      // The second form looks like " at URI:LINE:COL", and is used for
+      // anonymous functions.
+      var uri = Uri.parse(match[5]);
+      return new Frame(uri, int.parse(match[6]), int.parse(match[7]), "<fn>");
+    }
+  }
+
+  /// Parses a string representation of a Firefox stack frame.
+  factory Frame.parseFirefox(String frame) {
+    var match = _firefoxFrame.firstMatch(frame);
+    if (match == null) {
+      throw new FormatException(
+          "Couldn't parse Firefox stack trace line '$frame'.");
+    }
+
+    var uri = Uri.parse(match[3]);
+    var member = match[1];
+    if (member == "") {
+      member = "<fn>";
+    } else if (match[2] != null) {
+      member = "$member.<fn>";
+    }
+    // Some Firefox members have initial dots. We remove them for consistency
+    // with other platforms.
+    member = member.replaceFirst(_initialDot, '');
+    return new Frame(uri, int.parse(match[4]), null, member);
+  }
+
   Frame(this.uri, this.line, this.column, this.member);
 
   String toString() => '$location in $member';
diff --git a/pkg/stack_trace/lib/src/trace.dart b/pkg/stack_trace/lib/src/trace.dart
index db0e70b..db7a404 100644
--- a/pkg/stack_trace/lib/src/trace.dart
+++ b/pkg/stack_trace/lib/src/trace.dart
@@ -12,6 +12,13 @@
 
 final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$");
 
+/// A RegExp to match Firefox's stack traces.
+///
+/// Firefox's trace frames start with the name of the function in which the
+/// error occurred, possibly including its parameters inside `()`. For example,
+/// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`.
+final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]*|\(.*\))*@");
+
 /// A stack trace, comprised of a list of stack frames.
 class Trace implements StackTrace {
   /// The stack frames that comprise this stack trace.
@@ -57,9 +64,30 @@
 
   /// Parses a string representation of a stack trace.
   ///
-  /// [trace] should be formatted in the same way as native stack traces.
-  Trace.parse(String trace)
-      : this(trace.trim().split("\n").map((line) => new Frame.parse(line)));
+  /// [trace] should be formatted in the same way as a Dart VM or browser stack
+  /// trace.
+  factory Trace.parse(String trace) {
+    if (trace.isEmpty) return new Trace(<Frame>[]);
+    if (trace.startsWith("Error\n")) return new Trace.parseV8(trace);
+    if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace);
+
+    // Default to parsing the stack trace as a VM trace. This is also hit on IE
+    // and Safari, where the stack trace is just an empty string (issue 11257).
+    return new Trace.parseVM(trace);
+  }
+
+  /// Parses a string representation of a Dart VM stack trace.
+  Trace.parseVM(String trace)
+      : this(trace.trim().split("\n").map((line) => new Frame.parseVM(line)));
+
+  /// Parses a string representation of a Chrome/V8 stack trace.
+  Trace.parseV8(String trace)
+      : this(trace.split("\n").skip(1).map((line) => new Frame.parseV8(line)));
+
+  /// Parses a string representation of a Firefox stack trace.
+  Trace.parseFirefox(String trace)
+      : this(trace.trim().split("\n")
+          .map((line) => new Frame.parseFirefox(line)));
 
   /// Returns a new [Trace] comprised of [frames].
   Trace(Iterable<Frame> frames)
@@ -115,10 +143,9 @@
 
   /// Returns a human-readable string representation of [this].
   String toString() {
-    if (frames.length == '') return '';
-
     // Figure out the longest path so we know how much to pad.
-    var longest = frames.map((frame) => frame.location.length).reduce(math.max);
+    var longest = frames.map((frame) => frame.location.length)
+        .fold(0, math.max);
 
     // Print out the stack trace nicely formatted.
     return frames.map((frame) {
diff --git a/pkg/stack_trace/test/frame_test.dart b/pkg/stack_trace/test/frame_test.dart
index a140670..2ab310c 100644
--- a/pkg/stack_trace/test/frame_test.dart
+++ b/pkg/stack_trace/test/frame_test.dart
@@ -4,73 +4,190 @@
 
 library frame_test;
 
-import 'dart:io';
-
 import 'package:pathos/path.dart' as path;
 import 'package:stack_trace/stack_trace.dart';
 import 'package:unittest/unittest.dart';
 
-String getStackFrame() {
-  try {
-    throw '';
-  } catch (_, stackTrace) {
-    return stackTrace.toString().split("\n").first;
-  }
-}
-
-Frame getCaller([int level]) {
-  if (level == null) return new Frame.caller();
-  return new Frame.caller(level);
-}
-
-Frame nestedGetCaller(int level) => getCaller(level);
-
 void main() {
-  test('parses a stack frame correctly', () {
-    var frame = new Frame.parse("#1      Foo._bar "
-        "(file:///home/nweiz/code/stuff.dart:42:21)");
-    expect(frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart")));
-    expect(frame.line, equals(42));
-    expect(frame.column, equals(21));
-    expect(frame.member, equals('Foo._bar'));
+  group('.parseVM', () {
+    test('parses a stack frame correctly', () {
+      var frame = new Frame.parseVM("#1      Foo._bar "
+          "(file:///home/nweiz/code/stuff.dart:42:21)");
+      expect(frame.uri,
+          equals(Uri.parse("file:///home/nweiz/code/stuff.dart")));
+      expect(frame.line, equals(42));
+      expect(frame.column, equals(21));
+      expect(frame.member, equals('Foo._bar'));
+    });
+
+    test('converts "<anonymous closure>" to "<fn>"', () {
+      String parsedMember(String member) =>
+          new Frame.parseVM('#0 $member (foo:0:0)').member;
+
+      expect(parsedMember('Foo.<anonymous closure>'), equals('Foo.<fn>'));
+      expect(parsedMember('<anonymous closure>.<anonymous closure>.bar'),
+          equals('<fn>.<fn>.bar'));
+    });
+
+    test('throws a FormatException for malformed frames', () {
+      expect(() => new Frame.parseVM(''), throwsFormatException);
+      expect(() => new Frame.parseVM('#1'), throwsFormatException);
+      expect(() => new Frame.parseVM('#1      Foo'), throwsFormatException);
+      expect(() => new Frame.parseVM('#1      Foo (dart:async/future.dart)'),
+          throwsFormatException);
+      expect(() => new Frame.parseVM('#1      Foo (dart:async/future.dart:10)'),
+          throwsFormatException);
+      expect(() => new Frame.parseVM('#1      (dart:async/future.dart:10:15)'),
+          throwsFormatException);
+      expect(() => new Frame.parseVM('Foo (dart:async/future.dart:10:15)'),
+          throwsFormatException);
+    });
   });
 
-  test('parses a real stack frame correctly', () {
-    var frame = new Frame.parse(getStackFrame());
-    // TODO(nweiz): use URL-style paths when such a thing exists.
-    var builder = new path.Builder(style: path.Style.posix);
-    expect(builder.basename(frame.uri.path), equals('frame_test.dart'));
-    expect(frame.line, equals(15));
-    expect(frame.column, equals(5));
-    expect(frame.member, equals('getStackFrame'));
+  group('.parseV8', () {
+    test('parses a stack frame correctly', () {
+      var frame = new Frame.parseV8("    at VW.call\$0 "
+          "(http://pub.dartlang.org/stuff.dart.js:560:28)");
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, equals(28));
+      expect(frame.member, equals('VW.call\$0'));
+    });
+
+    test('parses an anonymous stack frame correctly', () {
+      var frame = new Frame.parseV8(
+          "    at http://pub.dartlang.org/stuff.dart.js:560:28");
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, equals(28));
+      expect(frame.member, equals('<fn>'));
+    });
+
+    test('converts "<anonymous>" to "<fn>"', () {
+      String parsedMember(String member) =>
+          new Frame.parseV8('    at $member (foo:0:0)').member;
+
+      expect(parsedMember('Foo.<anonymous>'), equals('Foo.<fn>'));
+      expect(parsedMember('<anonymous>.<anonymous>.bar'),
+          equals('<fn>.<fn>.bar'));
+    });
+
+    test('throws a FormatException for malformed frames', () {
+      expect(() => new Frame.parseV8(''), throwsFormatException);
+      expect(() => new Frame.parseV8('    at'), throwsFormatException);
+      expect(() => new Frame.parseV8('    at Foo'), throwsFormatException);
+      expect(() => new Frame.parseV8('    at Foo (dart:async/future.dart)'),
+          throwsFormatException);
+      expect(() => new Frame.parseV8('    at Foo (dart:async/future.dart:10)'),
+          throwsFormatException);
+      expect(() => new Frame.parseV8('    at (dart:async/future.dart:10:15)'),
+          throwsFormatException);
+      expect(() => new Frame.parseV8('Foo (dart:async/future.dart:10:15)'),
+          throwsFormatException);
+      expect(() => new Frame.parseV8('    at dart:async/future.dart'),
+          throwsFormatException);
+      expect(() => new Frame.parseV8('    at dart:async/future.dart:10'),
+          throwsFormatException);
+      expect(() => new Frame.parseV8('dart:async/future.dart:10:15'),
+          throwsFormatException);
+    });
   });
 
-  test('converts "<anonymous closure>" to "<fn>"', () {
-    String parsedMember(String member) =>
-        new Frame.parse('#0 $member (foo:0:0)').member;
+  group('.parseFirefox', () {
+    test('parses a simple stack frame correctly', () {
+      var frame = new Frame.parseFirefox(
+          ".VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560");
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals('VW.call\$0'));
+    });
 
-    expect(parsedMember('Foo.<anonymous closure>'), equals('Foo.<fn>'));
-    expect(parsedMember('<anonymous closure>.<anonymous closure>.bar'),
-        equals('<fn>.<fn>.bar'));
-  });
+    test('parses a simple anonymous stack frame correctly', () {
+      var frame = new Frame.parseFirefox(
+          "@http://pub.dartlang.org/stuff.dart.js:560");
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals("<fn>"));
+    });
 
-  test('throws a FormatException for malformed frames', () {
-    expect(() => new Frame.parse(''), throwsFormatException);
-    expect(() => new Frame.parse('#1'), throwsFormatException);
-    expect(() => new Frame.parse('#1      Foo'), throwsFormatException);
-    expect(() => new Frame.parse('#1      Foo (dart:async/future.dart)'),
-        throwsFormatException);
-    expect(() => new Frame.parse('#1      Foo (dart:async/future.dart:10)'),
-        throwsFormatException);
-    expect(() => new Frame.parse('#1      (dart:async/future.dart:10:15)'),
-        throwsFormatException);
-    expect(() => new Frame.parse('Foo (dart:async/future.dart:10:15)'),
-        throwsFormatException);
+    test('parses a nested anonymous stack frame correctly', () {
+      var frame = new Frame.parseFirefox(
+          ".foo/<@http://pub.dartlang.org/stuff.dart.js:560");
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals("foo.<fn>"));
+
+      frame = new Frame.parseFirefox(
+          ".foo/@http://pub.dartlang.org/stuff.dart.js:560");
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals("foo.<fn>"));
+    });
+
+    test('parses a named nested anonymous stack frame correctly', () {
+      var frame = new Frame.parseFirefox(
+          ".foo/.name<@http://pub.dartlang.org/stuff.dart.js:560");
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals("foo.<fn>"));
+
+      frame = new Frame.parseFirefox(
+          ".foo/.name@http://pub.dartlang.org/stuff.dart.js:560");
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals("foo.<fn>"));
+    });
+
+    test('parses a stack frame with parameters correctly', () {
+      var frame = new Frame.parseFirefox(
+          '.foo(12, "@)()/<")@http://pub.dartlang.org/stuff.dart.js:560');
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals("foo"));
+    });
+
+    test('parses a nested anonymous stack frame with parameters correctly', () {
+      var frame = new Frame.parseFirefox(
+          '.foo(12, "@)()/<")/.fn<@'
+          'http://pub.dartlang.org/stuff.dart.js:560');
+      expect(frame.uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js")));
+      expect(frame.line, equals(560));
+      expect(frame.column, isNull);
+      expect(frame.member, equals("foo.<fn>"));
+    });
+
+    test('throws a FormatException for malformed frames', () {
+      expect(() => new Frame.parseFirefox(''), throwsFormatException);
+      expect(() => new Frame.parseFirefox('.foo'), throwsFormatException);
+      expect(() => new Frame.parseFirefox('.foo@dart:async/future.dart'),
+          throwsFormatException);
+      expect(() => new Frame.parseFirefox('.foo(@dart:async/future.dart:10'),
+          throwsFormatException);
+      expect(() => new Frame.parseFirefox('@dart:async/future.dart'),
+          throwsFormatException);
+    });
   });
 
   test('only considers dart URIs to be core', () {
     bool isCore(String library) =>
-      new Frame.parse('#0 Foo ($library:0:0)').isCore;
+      new Frame.parseVM('#0 Foo ($library:0:0)').isCore;
 
     expect(isCore('dart:core'), isTrue);
     expect(isCore('dart:async'), isTrue);
@@ -82,39 +199,17 @@
     expect(isCore('bart:core/uri.dart'), isFalse);
   });
 
-  group('.caller()', () {
-    test('with no argument returns the parent frame', () {
-      expect(getCaller().member, equals('main.<fn>.<fn>'));
-    });
-
-    test('at level 0 returns the current frame', () {
-      expect(getCaller(0).member, equals('getCaller'));
-    });
-
-    test('at level 1 returns the current frame', () {
-      expect(getCaller(1).member, equals('main.<fn>.<fn>'));
-    });
-
-    test('at level 2 returns the grandparent frame', () {
-      expect(nestedGetCaller(2).member, equals('main.<fn>.<fn>'));
-    });
-
-    test('throws an ArgumentError for negative levels', () {
-      expect(() => new Frame.caller(-1), throwsArgumentError);
-    });
-  });
-
   group('.library', () {
     test('returns the URI string for non-file URIs', () {
-      expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').library,
+      expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').library,
           equals('dart:async/future.dart'));
-      expect(new Frame.parse('#0 Foo '
+      expect(new Frame.parseVM('#0 Foo '
               '(http://dartlang.org/stuff/thing.dart:0:0)').library,
           equals('http://dartlang.org/stuff/thing.dart'));
     });
 
     test('returns the relative path for file URIs', () {
-      expect(new Frame.parse('#0 Foo (foo/bar.dart:0:0)').library,
+      expect(new Frame.parseVM('#0 Foo (foo/bar.dart:0:0)').library,
           equals('foo/bar.dart'));
     });
   });
@@ -122,27 +217,27 @@
   group('.location', () {
     test('returns the library and line/column numbers for non-core '
         'libraries', () {
-      expect(new Frame.parse('#0 Foo '
+      expect(new Frame.parseVM('#0 Foo '
               '(http://dartlang.org/thing.dart:5:10)').location,
           equals('http://dartlang.org/thing.dart 5:10'));
-      expect(new Frame.parse('#0 Foo (foo/bar.dart:1:2)').location,
+      expect(new Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location,
           equals('foo/bar.dart 1:2'));
     });
   });
 
   group('.package', () {
     test('returns null for non-package URIs', () {
-      expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').package,
+      expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').package,
           isNull);
-      expect(new Frame.parse('#0 Foo '
+      expect(new Frame.parseVM('#0 Foo '
               '(http://dartlang.org/stuff/thing.dart:0:0)').package,
           isNull);
     });
 
     test('returns the package name for package: URIs', () {
-      expect(new Frame.parse('#0 Foo (package:foo/foo.dart:0:0)').package,
+      expect(new Frame.parseVM('#0 Foo (package:foo/foo.dart:0:0)').package,
           equals('foo'));
-      expect(new Frame.parse('#0 Foo (package:foo/zap/bar.dart:0:0)').package,
+      expect(new Frame.parseVM('#0 Foo (package:foo/zap/bar.dart:0:0)').package,
           equals('foo'));
     });
   });
@@ -150,13 +245,13 @@
   group('.toString()', () {
     test('returns the library and line/column numbers for non-core '
         'libraries', () {
-      expect(new Frame.parse('#0 Foo (http://dartlang.org/thing.dart:5:10)')
+      expect(new Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)')
               .toString(),
           equals('http://dartlang.org/thing.dart 5:10 in Foo'));
     });
 
     test('converts "<anonymous closure>" to "<fn>"', () {
-      expect(new Frame.parse('#0 Foo.<anonymous closure> '
+      expect(new Frame.parseVM('#0 Foo.<anonymous closure> '
               '(dart:core/uri.dart:5:10)').toString(),
           equals('dart:core/uri.dart 5:10 in Foo.<fn>'));
     });
diff --git a/pkg/stack_trace/test/trace_test.dart b/pkg/stack_trace/test/trace_test.dart
index fcf4fe5..95753a0 100644
--- a/pkg/stack_trace/test/trace_test.dart
+++ b/pkg/stack_trace/test/trace_test.dart
@@ -4,8 +4,6 @@
 
 library trace_test;
 
-import 'dart:io';
-
 import 'package:pathos/path.dart' as path;
 import 'package:stack_trace/stack_trace.dart';
 import 'package:unittest/unittest.dart';
@@ -31,61 +29,82 @@
 Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level);
 
 void main() {
-  test('parses a stack trace correctly', () {
-    var trace = new Trace.parse('''
-#0      Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)
-#1      zip.<anonymous closure>.zap (dart:async/future.dart:0:2)
-#2      zip.<anonymous closure>.zap (http://pub.dartlang.org/thing.dart:1:100)
-''');
+  // This just shouldn't crash.
+  test('a native stack trace is parseable', () => new Trace.current());
 
-    expect(trace.frames[0].uri,
-        equals(Uri.parse("file:///home/nweiz/code/stuff.dart")));
-    expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart")));
-    expect(trace.frames[2].uri,
-        equals(Uri.parse("http://pub.dartlang.org/thing.dart")));
-  });
+  group('.parse', () {
+    test('.parse parses a VM stack trace correctly', () {
+      var trace = new Trace.parse(
+          '#0      Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n'
+          '#1      zip.<anonymous closure>.zap (dart:async/future.dart:0:2)\n'
+          '#2      zip.<anonymous closure>.zap (http://pub.dartlang.org/thing.'
+              'dart:1:100)');
 
-  test('parses a real stack trace correctly', () {
-    var trace = new Trace.parse(getStackTraceString());
-    // TODO(nweiz): use URL-style paths when such a thing exists.
-    var builder = new path.Builder(style: path.Style.posix);
-    expect(builder.basename(trace.frames.first.uri.path),
-        equals('trace_test.dart'));
-    expect(trace.frames.first.member, equals('getStackTraceString'));
-  });
-
-  test('converts from a native stack trace correctly', () {
-    var trace = new Trace.from(getStackTraceObject());
-    // TODO(nweiz): use URL-style paths when such a thing exists.
-    var builder = new path.Builder(style: path.Style.posix);
-    expect(builder.basename(trace.frames.first.uri.path),
-        equals('trace_test.dart'));
-    expect(trace.frames.first.member, equals('getStackTraceObject'));
-  });
-
-  group('.current()', () {
-    test('with no argument returns a trace starting at the current frame', () {
-      var trace = new Trace.current();
-      expect(trace.frames.first.member, equals('main.<fn>.<fn>'));
+      expect(trace.frames[0].uri,
+          equals(Uri.parse("file:///home/nweiz/code/stuff.dart")));
+      expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart")));
+      expect(trace.frames[2].uri,
+          equals(Uri.parse("http://pub.dartlang.org/thing.dart")));
     });
 
-    test('at level 0 returns a trace starting at the current frame', () {
-      var trace = new Trace.current(0);
-      expect(trace.frames.first.member, equals('main.<fn>.<fn>'));
+    test('parses a V8 stack trace correctly', () {
+      var trace = new Trace.parse(
+          'Error\n'
+          '    at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n'
+          '    at http://pub.dartlang.org/stuff.js:0:2\n'
+          '    at zip.<anonymous>.zap '
+              '(http://pub.dartlang.org/thing.js:1:100)');
+
+      expect(trace.frames[0].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[1].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[2].uri,
+          equals(Uri.parse("http://pub.dartlang.org/thing.js")));
     });
 
-    test('at level 1 returns a trace starting at the parent frame', () {
-      var trace = getCurrentTrace(1);
-      expect(trace.frames.first.member, equals('main.<fn>.<fn>'));
+    test('parses a Firefox stack trace correctly', () {
+      var trace = new Trace.parse(
+          'Foo._bar@http://pub.dartlang.org/stuff.js:42\n'
+          'zip/<@http://pub.dartlang.org/stuff.js:0\n'
+          'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1');
+
+      expect(trace.frames[0].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[1].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[2].uri,
+          equals(Uri.parse("http://pub.dartlang.org/thing.js")));
+
+      trace = new Trace.parse(
+          'zip/<@http://pub.dartlang.org/stuff.js:0\n'
+          'Foo._bar@http://pub.dartlang.org/stuff.js:42\n'
+          'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1');
+
+      expect(trace.frames[0].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[1].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[2].uri,
+          equals(Uri.parse("http://pub.dartlang.org/thing.js")));
+
+      trace = new Trace.parse(
+          'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n'
+          'zip/<@http://pub.dartlang.org/stuff.js:0\n'
+          'Foo._bar@http://pub.dartlang.org/stuff.js:42');
+
+      expect(trace.frames[0].uri,
+          equals(Uri.parse("http://pub.dartlang.org/thing.js")));
+      expect(trace.frames[1].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
+      expect(trace.frames[2].uri,
+          equals(Uri.parse("http://pub.dartlang.org/stuff.js")));
     });
 
-    test('at level 2 returns a trace starting at the grandparent frame', () {
-      var trace = nestedGetCurrentTrace(2);
-      expect(trace.frames.first.member, equals('main.<fn>.<fn>'));
-    });
-
-    test('throws an ArgumentError for negative levels', () {
-      expect(() => new Trace.current(-1), throwsArgumentError);
+    test('parses an empty string correctly', () {
+      var trace = new Trace.parse('');
+      expect(trace.frames, isEmpty);
+      expect(trace.toString(), equals(''));
     });
   });
 
diff --git a/pkg/stack_trace/test/vm_test.dart b/pkg/stack_trace/test/vm_test.dart
new file mode 100644
index 0000000..38b2b80
--- /dev/null
+++ b/pkg/stack_trace/test/vm_test.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This file tests stack_trace's ability to parse live stack traces. It's a
+/// dual of dartium_test.dart, since method names can differ somewhat from
+/// platform to platform. No similar file exists for dart2js since the specific
+/// method names there are implementation details.
+
+import 'package:pathos/path.dart' as path;
+import 'package:stack_trace/stack_trace.dart';
+import 'package:unittest/unittest.dart';
+
+String getStackTraceString() {
+  try {
+    throw '';
+  } catch (_, stackTrace) {
+    return stackTrace.toString();
+  }
+}
+
+StackTrace getStackTraceObject() {
+  try {
+    throw '';
+  } catch (_, stackTrace) {
+    return stackTrace;
+  }
+}
+
+Frame getCaller([int level]) {
+  if (level == null) return new Frame.caller();
+  return new Frame.caller(level);
+}
+
+Frame nestedGetCaller(int level) => getCaller(level);
+
+Trace getCurrentTrace([int level]) => new Trace.current(level);
+
+Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level);
+
+void main() {
+  group('Trace', () {
+    test('.parse parses a real stack trace correctly', () {
+      var string = getStackTraceString();
+      var trace = new Trace.parse(string);
+      var builder = new path.Builder(style: path.Style.url);
+      expect(builder.basename(trace.frames.first.uri.path),
+          equals('vm_test.dart'));
+      expect(trace.frames.first.member, equals('getStackTraceString'));
+    });
+
+    test('converts from a native stack trace correctly', () {
+      var trace = new Trace.from(getStackTraceObject());
+      var builder = new path.Builder(style: path.Style.url);
+      expect(builder.basename(trace.frames.first.uri.path),
+          equals('vm_test.dart'));
+      expect(trace.frames.first.member, equals('getStackTraceObject'));
+    });
+
+    group('.current()', () {
+      test('with no argument returns a trace starting at the current frame',
+          () {
+        var trace = new Trace.current();
+        expect(trace.frames.first.member, equals('main.<fn>.<fn>.<fn>'));
+      });
+
+      test('at level 0 returns a trace starting at the current frame', () {
+        var trace = new Trace.current(0);
+        expect(trace.frames.first.member, equals('main.<fn>.<fn>.<fn>'));
+      });
+
+      test('at level 1 returns a trace starting at the parent frame', () {
+        var trace = getCurrentTrace(1);
+        expect(trace.frames.first.member, equals('main.<fn>.<fn>.<fn>'));
+      });
+
+      test('at level 2 returns a trace starting at the grandparent frame', () {
+        var trace = nestedGetCurrentTrace(2);
+        expect(trace.frames.first.member, equals('main.<fn>.<fn>.<fn>'));
+      });
+
+      test('throws an ArgumentError for negative levels', () {
+        expect(() => new Trace.current(-1), throwsArgumentError);
+      });
+    });
+  });
+
+  group('Frame.caller()', () {
+    test('with no argument returns the parent frame', () {
+      expect(getCaller().member, equals('main.<fn>.<fn>'));
+    });
+
+    test('at level 0 returns the current frame', () {
+      expect(getCaller(0).member, equals('getCaller'));
+    });
+
+    test('at level 1 returns the current frame', () {
+      expect(getCaller(1).member, equals('main.<fn>.<fn>'));
+    });
+
+    test('at level 2 returns the grandparent frame', () {
+      expect(nestedGetCaller(2).member, equals('main.<fn>.<fn>'));
+    });
+
+    test('throws an ArgumentError for negative levels', () {
+      expect(() => new Frame.caller(-1), throwsArgumentError);
+    });
+  });
+}
diff --git a/pkg/unittest/test/instance_test.dart b/pkg/unittest/test/instance_test.dart
index cac6ca0..d9e9875 100644
--- a/pkg/unittest/test/instance_test.dart
+++ b/pkg/unittest/test/instance_test.dart
@@ -21,7 +21,7 @@
       shouldPass(doesThrow, throwsA(equals('X')));
       shouldFail(doesThrow, throwsA(equals('Y')),
           "Expected: throws 'Y' "
-          "Actual: <Closure: (dynamic) => dynamic "
+          "Actual: <Closure: () => dynamic "
               "from Function 'doesThrow': static.> "
           "Which: threw 'X'");
     });
diff --git a/pkg/unittest/test/matchers_minified_test.dart b/pkg/unittest/test/matchers_minified_test.dart
index d9ee642..787c9e1 100644
--- a/pkg/unittest/test/matchers_minified_test.dart
+++ b/pkg/unittest/test/matchers_minified_test.dart
@@ -25,7 +25,7 @@
           throwsFormatException,
           matches(
               r"Expected: throws FormatException +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw " + _minifiedName + r":<Exception>"));
     });
 
@@ -36,7 +36,7 @@
           throwsArgumentError,
           matches(
               r"Expected: throws ArgumentError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw " + _minifiedName + r":<Exception>"));
     });
 
@@ -47,7 +47,7 @@
           throwsRangeError,
           matches(
               r"Expected: throws RangeError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw " + _minifiedName + r":<Exception>"));
     });
 
@@ -58,7 +58,7 @@
           throwsNoSuchMethodError,
           matches(
               r"Expected: throws NoSuchMethodError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw " + _minifiedName + r":<Exception>"));
     });
 
@@ -69,7 +69,7 @@
           throwsUnimplementedError,
           matches(
               r"Expected: throws UnimplementedError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw " + _minifiedName + r":<Exception>"));
     });
 
@@ -80,7 +80,7 @@
           throwsUnsupportedError,
           matches(
               r"Expected: throws UnsupportedError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw " + _minifiedName + r":<Exception>"));
     });
 
@@ -91,7 +91,7 @@
           throwsStateError,
           matches(
               r"Expected: throws StateError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw " + _minifiedName + r":<Exception>"));
     });
   });
diff --git a/pkg/unittest/test/matchers_test.dart b/pkg/unittest/test/matchers_test.dart
index ebe87e9..51020b7 100644
--- a/pkg/unittest/test/matchers_test.dart
+++ b/pkg/unittest/test/matchers_test.dart
@@ -65,7 +65,7 @@
       shouldFail(doesNotThrow, throws,
           matches(
               r"Expected: throws"
-              r"  Actual: <Closure(: \(dynamic\) => dynamic "
+              r"  Actual: <Closure(: \(\) => dynamic "
               r"from Function 'doesNotThrow': static\.)?>"
               r"   Which: did not throw"));
       shouldPass(doesThrow, throws);
@@ -80,7 +80,7 @@
       shouldFail(doesThrow, throwsA(equals('Y')),
           matches(
               r"Expected: throws 'Y'"
-              r"  Actual: <Closure(: \(dynamic\) => dynamic "
+              r"  Actual: <Closure(: \(\) => dynamic "
               r"from Function 'doesThrow': static\.)?>"
               r"   Which: threw 'X'"));
     });
@@ -90,7 +90,7 @@
       shouldFail(doesThrow, returnsNormally,
           matches(
               r"Expected: return normally"
-              r"  Actual: <Closure(: \(dynamic\) => dynamic "
+              r"  Actual: <Closure(: \(\) => dynamic "
               r"from Function 'doesThrow': static\.)?>"
               r"   Which: threw 'X'"));
     });
diff --git a/pkg/unittest/test/matchers_unminified_test.dart b/pkg/unittest/test/matchers_unminified_test.dart
index 11fb2e9..8a1b005 100644
--- a/pkg/unittest/test/matchers_unminified_test.dart
+++ b/pkg/unittest/test/matchers_unminified_test.dart
@@ -23,7 +23,7 @@
           throwsFormatException,
           matches(
               r"Expected: throws FormatException +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw \?:<Exception>"));
 
     });
@@ -35,7 +35,7 @@
           throwsArgumentError,
           matches(
               r"Expected: throws ArgumentError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw \?:<Exception>"));
     });
 
@@ -46,7 +46,7 @@
           throwsRangeError,
           matches(
               r"Expected: throws RangeError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw \?:<Exception>"));
     });
 
@@ -57,7 +57,7 @@
           throwsNoSuchMethodError,
           matches(
               r"Expected: throws NoSuchMethodError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw \?:<Exception>"));
     });
 
@@ -68,7 +68,7 @@
           throwsUnimplementedError,
           matches(
               r"Expected: throws UnimplementedError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw \?:<Exception>"));
     });
 
@@ -79,7 +79,7 @@
           throwsUnsupportedError,
           matches(
               r"Expected: throws UnsupportedError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw \?:<Exception>"));
     });
 
@@ -90,7 +90,7 @@
           throwsStateError,
           matches(
               r"Expected: throws StateError +"
-              r"Actual: <Closure(: \(dynamic\) => dynamic)?> +"
+              r"Actual: <Closure(: \(\) => dynamic)?> +"
               r"Which: threw \?:<Exception>"));
     });
   });
diff --git a/pkg/unittest/test/pretty_print_test.dart b/pkg/unittest/test/pretty_print_test.dart
index e5cd2e2..a0608ac 100644
--- a/pkg/unittest/test/pretty_print_test.dart
+++ b/pkg/unittest/test/pretty_print_test.dart
@@ -12,7 +12,7 @@
     expect(prettyPrint(true), equals('<true>'));
     expect(prettyPrint(null), equals('<null>'));
     expect(prettyPrint(() => 12),
-        matches(r'<Closure(: \(dynamic\) => dynamic)?>'));
+        matches(r'<Closure(: \(\) => dynamic)?>'));
   });
 
   group('with a string', () {
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index bbc8acb..74fb5da 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -14,6 +14,7 @@
 #include <sys/epoll.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
@@ -215,7 +216,15 @@
         // next message.
         RemoveFromEpollInstance(epoll_fd_, sd);
         intptr_t fd = sd->fd();
-        sd->Close();
+        if (fd == STDOUT_FILENO) {
+          // If stdout, redirect fd to /dev/null.
+          int null_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY));
+          ASSERT(null_fd >= 0);
+          VOID_TEMP_FAILURE_RETRY(dup2(null_fd, STDOUT_FILENO));
+          VOID_TEMP_FAILURE_RETRY(close(null_fd));
+        } else {
+          sd->Close();
+        }
         socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
         delete sd;
       } else {
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index aa852d1..9ed591a 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -14,6 +14,7 @@
 #include <sys/epoll.h>  // NOLINT
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
@@ -223,7 +224,15 @@
         // next message.
         RemoveFromEpollInstance(epoll_fd_, sd);
         intptr_t fd = sd->fd();
-        sd->Close();
+        if (fd == STDOUT_FILENO) {
+          // If stdout, redirect fd to /dev/null.
+          int null_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY));
+          ASSERT(null_fd >= 0);
+          VOID_TEMP_FAILURE_RETRY(dup2(null_fd, STDOUT_FILENO));
+          VOID_TEMP_FAILURE_RETRY(close(null_fd));
+        } else {
+          sd->Close();
+        }
         socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
         delete sd;
       } else {
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index a6554c9..826e600 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -13,6 +13,7 @@
 #include <string.h>  // NOLINT
 #include <sys/event.h>  // NOLINT
 #include <unistd.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
@@ -235,7 +236,15 @@
         // Close the socket and free system resources.
         RemoveFromKqueue(kqueue_fd_, sd);
         intptr_t fd = sd->fd();
-        sd->Close();
+        if (fd == STDOUT_FILENO) {
+          // If stdout, redirect fd to /dev/null.
+          int null_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY));
+          ASSERT(null_fd >= 0);
+          VOID_TEMP_FAILURE_RETRY(dup2(null_fd, STDOUT_FILENO));
+          VOID_TEMP_FAILURE_RETRY(close(null_fd));
+        } else {
+          sd->Close();
+        }
         socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
         delete sd;
       } else {
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 7c96ce8..f1257c3 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -11,6 +11,8 @@
 #include <winsock2.h>  // NOLINT
 #include <ws2tcpip.h>  // NOLINT
 #include <mswsock.h>  // NOLINT
+#include <io.h>  // NOLINT
+#include <fcntl.h>  // NOLINT
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
@@ -326,6 +328,18 @@
 }
 
 
+void FileHandle::DoClose() {
+  if (GetStdHandle(STD_OUTPUT_HANDLE) == handle_) {
+    int fd = _open("NUL", _O_WRONLY);
+    ASSERT(fd >= 0);
+    _dup2(fd, _fileno(stdout));
+    close(fd);
+  } else {
+    Handle::DoClose();
+  }
+}
+
+
 void SocketHandle::HandleIssueError() {
   int error = WSAGetLastError();
   if (error == WSAECONNRESET) {
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h
index 9bb0610..73e8917 100644
--- a/runtime/bin/eventhandler_win.h
+++ b/runtime/bin/eventhandler_win.h
@@ -251,6 +251,7 @@
 
   virtual void EnsureInitialized(EventHandlerImplementation* event_handler);
   virtual bool IsClosed();
+  virtual void DoClose();
 };
 
 
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index df53cd5..a6a5e2c 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -16,7 +16,7 @@
 static const int kProcessIdNativeField = 0;
 
 int Process::global_exit_code_ = 0;
-dart::Mutex Process::global_exit_code_mutex_;
+dart::Mutex* Process::global_exit_code_mutex_ = new dart::Mutex();
 
 // Extract an array of C strings from a list of Dart strings.
 static char** ExtractCStringList(Dart_Handle strings,
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index c0d8b8b..8e82f39 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -38,12 +38,12 @@
   static void TerminateExitCodeHandler();
 
   static int GlobalExitCode() {
-    MutexLocker ml(&global_exit_code_mutex_);
+    MutexLocker ml(global_exit_code_mutex_);
     return global_exit_code_;
   }
 
   static void SetGlobalExitCode(int exit_code) {
-    MutexLocker ml(&global_exit_code_mutex_);
+    MutexLocker ml(global_exit_code_mutex_);
     global_exit_code_ = exit_code;
   }
 
@@ -56,7 +56,7 @@
 
  private:
   static int global_exit_code_;
-  static dart::Mutex global_exit_code_mutex_;
+  static dart::Mutex* global_exit_code_mutex_;
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(Process);
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 8fbc446..49df0c5 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -55,7 +55,7 @@
 class ProcessInfoList {
  public:
   static void AddProcess(pid_t pid, intptr_t fd) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* info = new ProcessInfo(pid, fd);
     info->set_next(active_processes_);
     active_processes_ = info;
@@ -63,7 +63,7 @@
 
 
   static intptr_t LookupProcessExitFd(pid_t pid) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* current = active_processes_;
     while (current != NULL) {
       if (current->pid() == pid) {
@@ -76,7 +76,7 @@
 
 
   static void RemoveProcess(pid_t pid) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* prev = NULL;
     ProcessInfo* current = active_processes_;
     while (current != NULL) {
@@ -100,12 +100,12 @@
   static ProcessInfo* active_processes_;
   // Mutex protecting all accesses to the linked list of active
   // processes.
-  static dart::Mutex mutex_;
+  static dart::Mutex* mutex_;
 };
 
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-dart::Mutex ProcessInfoList::mutex_;
+dart::Mutex* ProcessInfoList::mutex_ = new dart::Mutex();
 
 
 // The exit code handler sets up a separate thread which is signalled
@@ -119,7 +119,7 @@
     // Multiple isolates could be starting processes at the same
     // time. Make sure that only one of them initializes the
     // ExitCodeHandler.
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     if (initialized_) {
       return true;
     }
@@ -155,7 +155,7 @@
   }
 
   static void TerminateExitCodeThread() {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     if (!initialized_) {
       return;
     }
@@ -168,7 +168,7 @@
     }
 
     {
-      MonitorLocker terminate_locker(&thread_terminate_monitor_);
+      MonitorLocker terminate_locker(thread_terminate_monitor_);
       while (!thread_terminated_) {
         terminate_locker.Wait();
       }
@@ -176,7 +176,7 @@
   }
 
   static void ExitCodeThreadTerminated() {
-    MonitorLocker locker(&thread_terminate_monitor_);
+    MonitorLocker locker(thread_terminate_monitor_);
     thread_terminated_ = true;
     locker.Notify();
   }
@@ -251,19 +251,19 @@
     }
   }
 
-  static dart::Mutex mutex_;
+  static dart::Mutex* mutex_;
   static bool initialized_;
   static int sig_chld_fds_[2];
   static bool thread_terminated_;
-  static dart::Monitor thread_terminate_monitor_;
+  static dart::Monitor* thread_terminate_monitor_;
 };
 
 
-dart::Mutex ExitCodeHandler::mutex_;
+dart::Mutex* ExitCodeHandler::mutex_ = new dart::Mutex();
 bool ExitCodeHandler::initialized_ = false;
 int ExitCodeHandler::sig_chld_fds_[2] = { 0, 0 };
 bool ExitCodeHandler::thread_terminated_ = false;
-dart::Monitor ExitCodeHandler::thread_terminate_monitor_;
+dart::Monitor* ExitCodeHandler::thread_terminate_monitor_ = new dart::Monitor();
 
 
 static void SetChildOsErrorMessage(char** os_error_message) {
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index e55cb5d..7d97425 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -57,7 +57,7 @@
 class ProcessInfoList {
  public:
   static void AddProcess(pid_t pid, intptr_t fd) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* info = new ProcessInfo(pid, fd);
     info->set_next(active_processes_);
     active_processes_ = info;
@@ -65,7 +65,7 @@
 
 
   static intptr_t LookupProcessExitFd(pid_t pid) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* current = active_processes_;
     while (current != NULL) {
       if (current->pid() == pid) {
@@ -78,7 +78,7 @@
 
 
   static void RemoveProcess(pid_t pid) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* prev = NULL;
     ProcessInfo* current = active_processes_;
     while (current != NULL) {
@@ -102,12 +102,12 @@
   static ProcessInfo* active_processes_;
   // Mutex protecting all accesses to the linked list of active
   // processes.
-  static dart::Mutex mutex_;
+  static dart::Mutex* mutex_;
 };
 
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-dart::Mutex ProcessInfoList::mutex_;
+dart::Mutex* ProcessInfoList::mutex_ = new dart::Mutex();
 
 
 // The exit code handler sets up a separate thread which is signalled
@@ -121,7 +121,7 @@
     // Multiple isolates could be starting processes at the same
     // time. Make sure that only one of them initializes the
     // ExitCodeHandler.
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     if (initialized_) {
       return true;
     }
@@ -157,7 +157,7 @@
   }
 
   static void TerminateExitCodeThread() {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     if (!initialized_) {
       return;
     }
@@ -170,7 +170,7 @@
     }
 
     {
-      MonitorLocker terminate_locker(&thread_terminate_monitor_);
+      MonitorLocker terminate_locker(thread_terminate_monitor_);
       while (!thread_terminated_) {
         terminate_locker.Wait();
       }
@@ -178,7 +178,7 @@
   }
 
   static void ExitCodeThreadTerminated() {
-    MonitorLocker locker(&thread_terminate_monitor_);
+    MonitorLocker locker(thread_terminate_monitor_);
     thread_terminated_ = true;
     locker.Notify();
   }
@@ -253,19 +253,19 @@
     }
   }
 
-  static dart::Mutex mutex_;
+  static dart::Mutex* mutex_;
   static bool initialized_;
   static int sig_chld_fds_[2];
   static bool thread_terminated_;
-  static dart::Monitor thread_terminate_monitor_;
+  static dart::Monitor* thread_terminate_monitor_;
 };
 
 
-dart::Mutex ExitCodeHandler::mutex_;
+dart::Mutex* ExitCodeHandler::mutex_ = new dart::Mutex();
 bool ExitCodeHandler::initialized_ = false;
 int ExitCodeHandler::sig_chld_fds_[2] = { 0, 0 };
 bool ExitCodeHandler::thread_terminated_ = false;
-dart::Monitor ExitCodeHandler::thread_terminate_monitor_;
+dart::Monitor* ExitCodeHandler::thread_terminate_monitor_ = new dart::Monitor();
 
 
 static void SetChildOsErrorMessage(char** os_error_message) {
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 43dcc28..3335181 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -56,7 +56,7 @@
 class ProcessInfoList {
  public:
   static void AddProcess(pid_t pid, intptr_t fd) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* info = new ProcessInfo(pid, fd);
     info->set_next(active_processes_);
     active_processes_ = info;
@@ -64,7 +64,7 @@
 
 
   static intptr_t LookupProcessExitFd(pid_t pid) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* current = active_processes_;
     while (current != NULL) {
       if (current->pid() == pid) {
@@ -77,7 +77,7 @@
 
 
   static void RemoveProcess(pid_t pid) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* prev = NULL;
     ProcessInfo* current = active_processes_;
     while (current != NULL) {
@@ -101,12 +101,12 @@
   static ProcessInfo* active_processes_;
   // Mutex protecting all accesses to the linked list of active
   // processes.
-  static dart::Mutex mutex_;
+  static dart::Mutex* mutex_;
 };
 
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-dart::Mutex ProcessInfoList::mutex_;
+dart::Mutex* ProcessInfoList::mutex_ = new dart::Mutex();
 
 
 // The exit code handler sets up a separate thread which is signalled
@@ -120,7 +120,7 @@
     // Multiple isolates could be starting processes at the same
     // time. Make sure that only one of them initializes the
     // ExitCodeHandler.
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     if (initialized_) {
       return true;
     }
@@ -156,7 +156,7 @@
   }
 
   static void TerminateExitCodeThread() {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     if (!initialized_) {
       return;
     }
@@ -169,7 +169,7 @@
     }
 
     {
-      MonitorLocker terminate_locker(&thread_terminate_monitor_);
+      MonitorLocker terminate_locker(thread_terminate_monitor_);
       while (!thread_terminated_) {
         terminate_locker.Wait();
       }
@@ -177,7 +177,7 @@
   }
 
   static void ExitCodeThreadTerminated() {
-    MonitorLocker locker(&thread_terminate_monitor_);
+    MonitorLocker locker(thread_terminate_monitor_);
     thread_terminated_ = true;
     locker.Notify();
   }
@@ -252,19 +252,19 @@
     }
   }
 
-  static dart::Mutex mutex_;
+  static dart::Mutex* mutex_;
   static bool initialized_;
   static int sig_chld_fds_[2];
   static bool thread_terminated_;
-  static dart::Monitor thread_terminate_monitor_;
+  static dart::Monitor* thread_terminate_monitor_;
 };
 
 
-dart::Mutex ExitCodeHandler::mutex_;
+dart::Mutex* ExitCodeHandler::mutex_ = new dart::Mutex();
 bool ExitCodeHandler::initialized_ = false;
 int ExitCodeHandler::sig_chld_fds_[2] = { 0, 0 };
 bool ExitCodeHandler::thread_terminated_ = false;
-dart::Monitor ExitCodeHandler::thread_terminate_monitor_;
+dart::Monitor* ExitCodeHandler::thread_terminate_monitor_ = new dart::Monitor();
 
 
 static void SetChildOsErrorMessage(char** os_error_message) {
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 1237f13..f6c809a 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -80,7 +80,7 @@
     // is signaled.  The callback runs in a independent thread from the OS pool.
     // Because the callback depends on the process list containing
     // the process, lock the mutex until the process is added to the list.
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     HANDLE wait_handle = INVALID_HANDLE_VALUE;
     BOOL success = RegisterWaitForSingleObject(
         &wait_handle,
@@ -102,7 +102,7 @@
                             HANDLE* handle,
                             HANDLE* wait_handle,
                             HANDLE* pipe) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* current = active_processes_;
     while (current != NULL) {
       if (current->pid() == pid) {
@@ -117,7 +117,7 @@
   }
 
   static void RemoveProcess(DWORD pid) {
-    MutexLocker locker(&mutex_);
+    MutexLocker locker(mutex_);
     ProcessInfo* prev = NULL;
     ProcessInfo* current = active_processes_;
     while (current != NULL) {
@@ -186,12 +186,12 @@
   static ProcessInfo* active_processes_;
   // Mutex protecting all accesses to the linked list of active
   // processes.
-  static dart::Mutex mutex_;
+  static dart::Mutex* mutex_;
 };
 
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-dart::Mutex ProcessInfoList::mutex_;
+dart::Mutex* ProcessInfoList::mutex_ = new dart::Mutex();
 
 
 // Types of pipes to create.
@@ -343,10 +343,10 @@
 
 static bool EnsureInitialized() {
   static bool load_attempted = false;
-  static dart::Mutex mutex;
+  static dart::Mutex* mutex = new dart::Mutex();
   HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll");
   if (!load_attempted) {
-    MutexLocker locker(&mutex);
+    MutexLocker locker(mutex);
     if (load_attempted) return delete_proc_thread_attr_list != NULL;
     init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>(
         GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList"));
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index e6aacd7..1cfc508 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -36,7 +36,8 @@
 namespace bin {
 
 bool SSLFilter::library_initialized_ = false;
-dart::Mutex SSLFilter::mutex_;  // To protect library initialization.
+// To protect library initialization.
+dart::Mutex* SSLFilter::mutex_ = new dart::Mutex();
 // The password is needed when creating secure server sockets.  It can
 // be null if only secure client sockets are used.
 const char* SSLFilter::password_ = NULL;
@@ -527,7 +528,7 @@
                                   const char* password,
                                   bool use_builtin_root_certificates,
                                   bool report_duplicate_initialization) {
-  MutexLocker locker(&mutex_);
+  MutexLocker locker(mutex_);
   SECStatus status;
   if (!library_initialized_) {
     password_ = strdup(password);  // This one copy persists until Dart exits.
@@ -536,7 +537,7 @@
     if (certificate_database == NULL || certificate_database[0] == '\0') {
       status = NSS_NoDB_Init(NULL);
       if (status != SECSuccess) {
-        mutex_.Unlock();  // MutexLocker destructor not called when throwing.
+        mutex_->Unlock();  // MutexLocker destructor not called when throwing.
         ThrowPRException("TlsException",
                          "Failed NSS_NoDB_Init call.");
       }
@@ -544,7 +545,7 @@
         SECMODModule* module = SECMOD_LoadUserModule(
             const_cast<char*>(builtin_roots_module), NULL, PR_FALSE);
         if (!module) {
-          mutex_.Unlock();  // MutexLocker destructor not called when throwing.
+          mutex_->Unlock();  // MutexLocker destructor not called when throwing.
           ThrowPRException("TlsException",
                            "Failed to load builtin root certificates.");
         }
@@ -560,7 +561,7 @@
                               SECMOD_DB,
                               init_flags);
       if (status != SECSuccess) {
-        mutex_.Unlock();  // MutexLocker destructor not called when throwing.
+        mutex_->Unlock();  // MutexLocker destructor not called when throwing.
         ThrowPRException("TlsException",
                          "Failed NSS_Init call.");
       }
@@ -569,26 +570,26 @@
 
     status = NSS_SetDomesticPolicy();
     if (status != SECSuccess) {
-      mutex_.Unlock();  // MutexLocker destructor not called when throwing.
+      mutex_->Unlock();  // MutexLocker destructor not called when throwing.
       ThrowPRException("TlsException",
                        "Failed NSS_SetDomesticPolicy call.");
     }
     // Enable TLS, as well as SSL3 and SSL2.
     status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
     if (status != SECSuccess) {
-      mutex_.Unlock();  // MutexLocker destructor not called when throwing.
+      mutex_->Unlock();  // MutexLocker destructor not called when throwing.
       ThrowPRException("TlsException",
                        "Failed SSL_OptionSetDefault enable TLS call.");
     }
     status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL);
     if (status != SECSuccess) {
-      mutex_.Unlock();  // MutexLocker destructor not called when throwing.
+      mutex_->Unlock();  // MutexLocker destructor not called when throwing.
       ThrowPRException("TlsException",
                        "Failed SSL_ConfigServerSessionIDCache call.");
     }
 
   } else if (report_duplicate_initialization) {
-    mutex_.Unlock();  // MutexLocker destructor not called when throwing.
+    mutex_->Unlock();  // MutexLocker destructor not called when throwing.
     // Like ThrowPRException, without adding an OSError.
     Dart_ThrowException(DartUtils::NewDartIOException("TlsException",
         "Called SecureSocket.initialize more than once",
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 2f8225e..acdcda8 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -90,7 +90,7 @@
   static const int kMemioBufferSize = 20 * KB;
   static bool library_initialized_;
   static const char* password_;
-  static dart::Mutex mutex_;  // To protect library initialization.
+  static dart::Mutex* mutex_;  // To protect library initialization.
   static NativeService filter_service_;
 
   uint8_t* buffers_[kNumBuffers];
diff --git a/runtime/bin/secure_socket_unsupported.cc b/runtime/bin/secure_socket_unsupported.cc
index a571c85..99e5e3b 100644
--- a/runtime/bin/secure_socket_unsupported.cc
+++ b/runtime/bin/secure_socket_unsupported.cc
@@ -86,5 +86,20 @@
   Dart_ExitScope();
 }
 
+
+void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_NewServicePort)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
 }  // namespace bin
 }  // namespace dart
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 41bcc9e..b97661d 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -20,7 +20,7 @@
 
 static const int kSocketIdNativeField = 0;
 
-dart::Mutex Socket::mutex_;
+dart::Mutex* Socket::mutex_ = new dart::Mutex();
 int Socket::service_ports_size_ = 0;
 Dart_Port* Socket::service_ports_ = NULL;
 int Socket::service_ports_index_ = 0;
@@ -550,7 +550,7 @@
 
 
 Dart_Port Socket::GetServicePort() {
-  MutexLocker lock(&mutex_);
+  MutexLocker lock(mutex_);
   if (service_ports_size_ == 0) {
     ASSERT(service_ports_ == NULL);
     service_ports_size_ = 16;
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index ffca207..8c6464b 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -191,7 +191,7 @@
   static Dart_Handle GetSocketIdNativeField(Dart_Handle socket, intptr_t* id);
 
  private:
-  static dart::Mutex mutex_;
+  static dart::Mutex* mutex_;
   static int service_ports_size_;
   static Dart_Port* service_ports_;
   static int service_ports_index_;
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 748f33e..dd0e256 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -12,7 +12,6 @@
 #include <sys/stat.h>  // NOLINT
 #include <unistd.h>  // NOLINT
 #include <netinet/tcp.h>  // NOLINT
-#include <ifaddrs.h>  // NOLINT
 
 #include "bin/fdutils.h"
 #include "bin/file.h"
@@ -246,50 +245,12 @@
 }
 
 
-static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
-  int family = ifa->ifa_addr->sa_family;
-  if (lookup_family == family) return true;
-  if (lookup_family == AF_UNSPEC &&
-      (family == AF_INET || family == AF_INET6)) {
-    return true;
-  }
-  return false;
-}
-
-
 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
     int type,
     OSError** os_error) {
-  struct ifaddrs* ifaddr;
-
-  int status = getifaddrs(&ifaddr);
-  if (status != 0) {
-    ASSERT(*os_error == NULL);
-    *os_error = new OSError(status,
-                            gai_strerror(status),
-                            OSError::kGetAddressInfo);
-    return NULL;
-  }
-
-  int lookup_family = SocketAddress::FromType(type);
-
-  intptr_t count = 0;
-  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
-    if (ShouldIncludeIfaAddrs(ifa, lookup_family)) count++;
-  }
-
-  AddressList<InterfaceSocketAddress>* addresses =
-      new AddressList<InterfaceSocketAddress>(count);
-  int i = 0;
-  for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
-    if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
-      addresses->SetAt(i, new InterfaceSocketAddress(
-          ifa->ifa_addr, strdup(ifa->ifa_name)));
-      i++;
-    }
-  }
-  freeifaddrs(ifaddr);
-  return addresses;
+  // The ifaddrs.h header is not provided on Android.  An Android
+  // implementation would have to use IOCTL or netlink.
+  return NULL;
 }
 
 
@@ -325,11 +286,11 @@
 
   // Test for invalid socket port 65535 (some browsers disallow it).
   if (port == 0 && Socket::GetPort(fd) == 65535) {
-    // Don't close fd until we have created new. By doing that we ensure another
-    // port.
+    // Don't close the socket until we have created a new socket, ensuring
+    // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, 0, backlog, v6_only);
     int err = errno;
-    TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY(close(fd));
     errno = err;
     return new_fd;
   }
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 1aaba00..e2fdf5c 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -324,11 +324,11 @@
 
   // Test for invalid socket port 65535 (some browsers disallow it).
   if (port == 0 && Socket::GetPort(fd) == 65535) {
-    // Don't close fd until we have created new. By doing that we ensure another
-    // port.
+    // Don't close the socket until we have created a new socket, ensuring
+    // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, 0, backlog, v6_only);
     int err = errno;
-    TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY(close(fd));
     errno = err;
     return new_fd;
   }
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index b9c6298..66737cd 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -324,11 +324,11 @@
 
   // Test for invalid socket port 65535 (some browsers disallow it).
   if (port == 0 && Socket::GetPort(fd) == 65535) {
-    // Don't close fd until we have created new. By doing that we ensure another
-    // port.
+    // Don't close the socket until we have created a new socket, ensuring
+    // that we do not get the bad port number again.
     intptr_t new_fd = CreateBindListen(addr, 0, backlog, v6_only);
     int err = errno;
-    TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY(close(fd));
     errno = err;
     return new_fd;
   }
diff --git a/runtime/embedders/openglui/common/extension.cc b/runtime/embedders/openglui/common/extension.cc
index 3e1885e..6304c3b 100644
--- a/runtime/embedders/openglui/common/extension.cc
+++ b/runtime/embedders/openglui/common/extension.cc
@@ -14,6 +14,7 @@
 #include "embedders/openglui/common/log.h"
 #include "embedders/openglui/common/opengl.h"
 #include "include/dart_api.h"
+#include "include/dart_native_api.h"
 
 Dart_Handle HandleError(Dart_Handle handle) {
   if (Dart_IsError(handle)) Dart_PropagateError(handle);
@@ -861,13 +862,13 @@
 void WrappedRandomArray(Dart_Port dest_port_id,
                         Dart_Port reply_port_id,
                         Dart_CObject* message) {
-  if (message->type == Dart_CObject::kArray &&
+  if (message->type == Dart_CObject_kArray &&
       2 == message->value.as_array.length) {
     // Use .as_array and .as_int32 to access the data in the Dart_CObject.
     Dart_CObject* param0 = message->value.as_array.values[0];
     Dart_CObject* param1 = message->value.as_array.values[1];
-    if (param0->type == Dart_CObject::kInt32 &&
-        param1->type == Dart_CObject::kInt32) {
+    if (param0->type == Dart_CObject_kInt32 &&
+        param1->type == Dart_CObject_kInt32) {
       int length = param0->value.as_int32;
       int seed = param1->value.as_int32;
 
@@ -875,8 +876,8 @@
 
       if (values != NULL) {
         Dart_CObject result;
-        result.type = Dart_CObject::kTypedData;
-        result.value.as_typed_data.type = Dart_CObject::kUint8Array;
+        result.type = Dart_CObject_kTypedData;
+        result.value.as_typed_data.type = Dart_TypedData_kUint8;
         result.value.as_typed_data.values = values;
         result.value.as_typed_data.length = length;
         Dart_PostCObject(reply_port_id, &result);
@@ -888,7 +889,7 @@
     }
   }
   Dart_CObject result;
-  result.type = Dart_CObject::kNull;
+  result.type = Dart_CObject_kNull;
   Dart_PostCObject(reply_port_id, &result);
 }
 
diff --git a/runtime/embedders/openglui/openglui_embedder.gypi b/runtime/embedders/openglui/openglui_embedder.gypi
index c67cf90..4b058cc 100644
--- a/runtime/embedders/openglui/openglui_embedder.gypi
+++ b/runtime/embedders/openglui/openglui_embedder.gypi
@@ -24,7 +24,7 @@
               'libdart_vm',
               'libjscre',
               'libdouble_conversion',
-              'generate_version_cc_file',
+              'generate_version_cc_file#host',
             ],
             'include_dirs': [
               '../..',
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 7825319..efb2d16 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -47,11 +47,11 @@
 
 static Dart_Handle MapNew() {
   // TODO(turnidge): Switch to an order-preserving map type.
-  Dart_Handle cls = Dart_GetClass(CoreLib(), NewString("Map"));
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(CoreLib(), NewString("Map"), 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
-  return Dart_New(cls, Dart_Null(), 0, NULL);
+  return Dart_New(type, Dart_Null(), 0, NULL);
 }
 
 
@@ -69,11 +69,11 @@
 
 static Dart_Handle IsMirror(Dart_Handle object, bool* is_mirror) {
   Dart_Handle cls_name = NewString("Mirror");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
-  Dart_Handle result = Dart_ObjectIsType(object, cls, is_mirror);
+  Dart_Handle result = Dart_ObjectIsType(object, type, is_mirror);
   if (Dart_IsError(result)) {
     return result;
   }
@@ -82,11 +82,11 @@
 
 static Dart_Handle IsMethodMirror(Dart_Handle object, bool* is_mirror) {
   Dart_Handle cls_name = NewString("MethodMirror");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
-  Dart_Handle result = Dart_ObjectIsType(object, cls, is_mirror);
+  Dart_Handle result = Dart_ObjectIsType(object, type, is_mirror);
   if (Dart_IsError(result)) {
     return result;
   }
@@ -95,11 +95,11 @@
 
 static Dart_Handle IsVariableMirror(Dart_Handle object, bool* is_mirror) {
   Dart_Handle cls_name = NewString("VariableMirror");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
-  Dart_Handle result = Dart_ObjectIsType(object, cls, is_mirror);
+  Dart_Handle result = Dart_ObjectIsType(object, type, is_mirror);
   if (Dart_IsError(result)) {
     return result;
   }
@@ -126,11 +126,11 @@
 static Dart_Handle CreateVMReference(Dart_Handle handle) {
   // Create the VMReference object.
   Dart_Handle cls_name = NewString("VMReference");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
-  Dart_Handle vm_ref =  Dart_New(cls, Dart_Null(), 0, NULL);
+  Dart_Handle vm_ref =  Dart_New(type, Dart_Null(), 0, NULL);
   if (Dart_IsError(vm_ref)) {
     return vm_ref;
   }
@@ -340,22 +340,22 @@
   }
 
   Dart_Handle param_cls_name = NewString("_LocalParameterMirrorImpl");
-  Dart_Handle param_cls = Dart_GetClass(MirrorLib(), param_cls_name);
-  if (Dart_IsError(param_cls)) {
-    return param_cls;
+  Dart_Handle param_type = Dart_GetType(MirrorLib(), param_cls_name, 0, NULL);
+  if (Dart_IsError(param_type)) {
+    return param_type;
   }
 
   for (int64_t i = 0; i < param_count; i++) {
-    Dart_Handle param_type = Dart_FunctionParameterType(func, i);
-    if (Dart_IsError(param_type)) {
-      return param_type;
+    Dart_Handle arg_type = Dart_FunctionParameterType(func, i);
+    if (Dart_IsError(arg_type)) {
+      return arg_type;
     }
     Dart_Handle args[] = {
-      CreateLazyMirror(param_type),
+      CreateLazyMirror(arg_type),
       Dart_NewBoolean(i >= fixed_param_count),  // optional param?
     };
     Dart_Handle param =
-        Dart_New(param_cls, Dart_Null(), ARRAY_SIZE(args), args);
+        Dart_New(param_type, Dart_Null(), ARRAY_SIZE(args), args);
     if (Dart_IsError(param)) {
       return param;
     }
@@ -375,15 +375,15 @@
 
   if (Dart_IsLibrary(target)) {
     Dart_Handle cls_name = NewString("_LazyLibraryMirror");
-    Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
+    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
     Dart_Handle args[] = { Dart_LibraryUrl(target) };
-    return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+    return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   }
 
   if (Dart_IsClass(target)) {
     if (Dart_ClassIsFunctionType(target)) {
       Dart_Handle cls_name = NewString("_LazyFunctionTypeMirror");
-      Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
+      Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
 
       Dart_Handle sig = Dart_ClassGetFunctionTypeSignature(target);
       Dart_Handle return_type = Dart_FunctionReturnType(sig);
@@ -395,10 +395,10 @@
         CreateLazyMirror(return_type),
         CreateParameterMirrorList(sig),
       };
-      return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+      return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
     } else {
       Dart_Handle cls_name = NewString("_LazyTypeMirror");
-      Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
+      Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
       Dart_Handle lib = Dart_ClassGetLibrary(target);
       Dart_Handle lib_url;
       if (Dart_IsNull(lib)) {
@@ -407,7 +407,7 @@
         lib_url = Dart_LibraryUrl(lib);
       }
       Dart_Handle args[] = { lib_url, Dart_ClassName(target) };
-      return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+      return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
     }
   }
 
@@ -417,10 +417,10 @@
     Dart_Handle owner_mirror = CreateLazyMirror(owner);
 
     Dart_Handle cls_name = NewString("_LazyTypeVariableMirror");
-    Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
+    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
 
     Dart_Handle args[] = { var_name, owner_mirror };
-    return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+    return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   }
 
   UNREACHABLE();
@@ -463,9 +463,9 @@
                                             Dart_Handle owner_mirror) {
   ASSERT(Dart_IsTypeVariable(type_var));
   Dart_Handle cls_name = NewString("_LocalTypeVariableMirrorImpl");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
 
   Dart_Handle upper_bound = Dart_TypeVariableUpperBound(type_var);
@@ -478,7 +478,7 @@
     owner_mirror,
     CreateLazyMirror(upper_bound),
   };
-  Dart_Handle mirror = Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   return mirror;
 }
 
@@ -527,9 +527,9 @@
                                        Dart_Handle owner,
                                        Dart_Handle owner_mirror) {
   Dart_Handle mirror_cls_name = NewString("_LocalTypedefMirrorImpl");
-  Dart_Handle mirror_cls = Dart_GetClass(MirrorLib(), mirror_cls_name);
-  if (Dart_IsError(mirror_cls)) {
-    return mirror_cls;
+  Dart_Handle mirror_type = Dart_GetType(MirrorLib(), mirror_cls_name, 0, NULL);
+  if (Dart_IsError(mirror_type)) {
+    return mirror_type;
   }
 
   Dart_Handle referent = Dart_ClassGetTypedefReferent(cls);
@@ -543,7 +543,7 @@
     CreateLazyMirror(referent),
   };
   Dart_Handle mirror =
-      Dart_New(mirror_cls, Dart_Null(), ARRAY_SIZE(args), args);
+      Dart_New(mirror_type, Dart_Null(), ARRAY_SIZE(args), args);
   return mirror;
 }
 
@@ -565,9 +565,9 @@
   }
 
   Dart_Handle cls_name = NewString("_LocalClassMirrorImpl");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
 
   // TODO(turnidge): Why am I getting Null when I expect Object?
@@ -608,7 +608,7 @@
     constructor_map,
     type_var_map,
   };
-  Dart_Handle mirror = Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   return mirror;
 }
 
@@ -618,9 +618,9 @@
                                       Dart_Handle owner_mirror) {
   ASSERT(Dart_IsFunction(func));
   Dart_Handle mirror_cls_name = NewString("_LocalMethodMirrorImpl");
-  Dart_Handle mirror_cls = Dart_GetClass(MirrorLib(), mirror_cls_name);
-  if (Dart_IsError(mirror_cls)) {
-    return mirror_cls;
+  Dart_Handle mirror_type = Dart_GetType(MirrorLib(), mirror_cls_name, 0, NULL);
+  if (Dart_IsError(mirror_type)) {
+    return mirror_type;
   }
 
   bool is_static = false;
@@ -681,7 +681,7 @@
     Dart_False(),
   };
   Dart_Handle mirror =
-      Dart_New(mirror_cls, Dart_Null(), ARRAY_SIZE(args), args);
+      Dart_New(mirror_type, Dart_Null(), ARRAY_SIZE(args), args);
   return mirror;
 }
 
@@ -691,9 +691,9 @@
                                         Dart_Handle lib_mirror) {
   ASSERT(Dart_IsVariable(var));
   Dart_Handle cls_name = NewString("_LocalVariableMirrorImpl");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
 
   bool is_static = false;
@@ -708,19 +708,19 @@
     return result;
   }
 
-  Dart_Handle type = Dart_VariableType(var);
-  if (Dart_IsError(type)) {
-    return type;
+  Dart_Handle var_type = Dart_VariableType(var);
+  if (Dart_IsError(var_type)) {
+    return var_type;
   }
 
   Dart_Handle args[] = {
     var_name,
     lib_mirror,
-    CreateLazyMirror(type),
+    CreateLazyMirror(var_type),
     Dart_NewBoolean(is_static),
     Dart_NewBoolean(is_final),
   };
-  Dart_Handle mirror = Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   return mirror;
 }
 
@@ -924,9 +924,9 @@
 
 static Dart_Handle CreateLibraryMirror(Dart_Handle lib) {
   Dart_Handle cls_name = NewString("_LocalLibraryMirrorImpl");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
   Dart_Handle lazy_lib_mirror = CreateLazyMirror(lib);
   if (Dart_IsError(lazy_lib_mirror)) {
@@ -942,7 +942,7 @@
     Dart_LibraryUrl(lib),
     member_map,
   };
-  Dart_Handle lib_mirror = Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+  Dart_Handle lib_mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   if (Dart_IsError(lib_mirror)) {
     return lib_mirror;
   }
@@ -988,23 +988,23 @@
 
 static Dart_Handle CreateIsolateMirror() {
   Dart_Handle cls_name = NewString("_LocalIsolateMirrorImpl");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
   Dart_Handle args[] = {
     Dart_DebugName(),
     CreateLazyMirror(Dart_RootLibrary()),
   };
-  return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+  return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
 }
 
 
 static Dart_Handle CreateMirrorSystem() {
   Dart_Handle cls_name = NewString("_LocalMirrorSystemImpl");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
 
   Dart_Handle libraries = CreateLibrariesMap();
@@ -1016,7 +1016,7 @@
     libraries,
     CreateIsolateMirror(),
   };
-  Dart_Handle mirror = Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   if (Dart_IsError(mirror)) {
     return mirror;
   }
@@ -1027,9 +1027,9 @@
 
 static Dart_Handle CreateNullMirror() {
   Dart_Handle cls_name = NewString("_LocalInstanceMirrorImpl");
-  Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-  if (Dart_IsError(cls)) {
-    return cls;
+  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+  if (Dart_IsError(type)) {
+    return type;
   }
 
   // TODO(turnidge): This is wrong.  The Null class is distinct from object.
@@ -1040,7 +1040,7 @@
     CreateLazyMirror(object_class),
     Dart_Null(),
   };
-  Dart_Handle mirror = Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   return mirror;
 }
 
@@ -1058,9 +1058,9 @@
 
   if (Dart_IsClosure(instance)) {
     Dart_Handle cls_name = NewString("_LocalClosureMirrorImpl");
-    Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-    if (Dart_IsError(cls)) {
-      return cls;
+    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+    if (Dart_IsError(type)) {
+      return type;
     }
     // We set the function field of ClosureMirrors outside of the constructor
     // to break the mutual recursion.
@@ -1089,20 +1089,20 @@
       instance,
       func_mirror,
     };
-    return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+    return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
 
   } else {
     Dart_Handle cls_name = NewString("_LocalInstanceMirrorImpl");
-    Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
-    if (Dart_IsError(cls)) {
-      return cls;
+    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
+    if (Dart_IsError(type)) {
+      return type;
     }
     Dart_Handle args[] = {
       CreateVMReference(instance),
       CreateLazyMirror(instance_cls),
       instance,
     };
-    return Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+    return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
   }
 }
 
@@ -1128,22 +1128,22 @@
       return stack;
     }
     Dart_Handle cls_name = NewString("MirroredUncaughtExceptionError");
-    Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
+    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
     Dart_Handle args[] = {
       CreateInstanceMirror(exc),
       exc_string,
       stack,
     };
     Dart_Handle mirrored_exc =
-        Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+        Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
     return Dart_NewUnhandledExceptionError(mirrored_exc);
   } else if (Dart_IsApiError(error) ||
              Dart_IsCompilationError(error)) {
     Dart_Handle cls_name = NewString("MirroredCompilationError");
-    Dart_Handle cls = Dart_GetClass(MirrorLib(), cls_name);
+    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
     Dart_Handle args[] = { NewString(Dart_GetError(error)) };
     Dart_Handle mirrored_exc =
-        Dart_New(cls, Dart_Null(), ARRAY_SIZE(args), args);
+        Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
     return Dart_NewUnhandledExceptionError(mirrored_exc);
   } else {
     ASSERT(Dart_IsFatalError(error));
diff --git a/runtime/tools/benchmark.py b/runtime/tools/benchmark.py
index b3a587f..694b87c 100755
--- a/runtime/tools/benchmark.py
+++ b/runtime/tools/benchmark.py
@@ -54,7 +54,7 @@
       default=False, action="store_true")
   result.add_option("--arch",
       help='Target architectures (comma-separated).',
-      metavar='[all,ia32,x64,simarm,arm,dartc]',
+      metavar='[all,ia32,x64,simarm,simmips,arm,mips,dartc]',
       default=utils.GuessArchitecture())
   result.add_option("--executable",
       help='Virtual machine to execute.',
@@ -68,7 +68,7 @@
 
 def ProcessOptions(options):
   if options.arch == 'all':
-    options.arch = 'ia32,x64,simarm,dartc'
+    options.arch = 'ia32,x64,simarm,simmips,dartc'
   if options.mode == 'all':
     options.mode = 'debug,release'
   options.mode = options.mode.split(',')
@@ -78,7 +78,7 @@
       print "Unknown mode %s" % mode
       return False
   for arch in options.arch:
-    if not arch in ['ia32', 'x64', 'simarm', 'arm', 'dartc']:
+    if not arch in ['ia32', 'x64', 'simarm', 'simmips', 'arm', 'mips', 'dartc']:
       print "Unknown arch %s" % arch
       return False
   return True
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index c1803e2..87b1dbf 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -530,6 +530,13 @@
 }
 
 
+void Assembler::umlal(Register rd_lo, Register rd_hi,
+                      Register rn, Register rm, Condition cond) {
+  // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+  EmitMulOp(cond, B23 | B21, rd_lo, rd_hi, rn, rm);
+}
+
+
 void Assembler::EmitDivOp(Condition cond, int32_t opcode,
                           Register rd, Register rn, Register rm) {
   ASSERT(CPUFeatures::integer_division_supported());
@@ -1375,12 +1382,16 @@
     StoreIntoObjectFilterNoSmi(object, value, &done);
   }
   // A store buffer update is required.
-  if (value != R0) Push(R0);  // Preserve R0.
+  RegList regs = (1 << LR);
+  if (value != R0) {
+    regs |= (1 << R0);  // Preserve R0.
+  }
+  PushList(regs);
   if (object != R0) {
     mov(R0, ShifterOperand(object));
   }
   BranchLink(&StubCode::UpdateStoreBufferLabel());
-  if (value != R0) Pop(R0);  // Restore R0.
+  PopList(regs);
   Bind(&done);
 }
 
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 7230266..16438d8 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -402,6 +402,8 @@
              Condition cond = AL);
   void smlal(Register rd_lo, Register rd_hi, Register rn, Register rm,
              Condition cond = AL);
+  void umlal(Register rd_lo, Register rd_hi, Register rn, Register rm,
+             Condition cond = AL);
 
   // Division instructions.
   void sdiv(Register rd, Register rn, Register rm, Condition cond = AL);
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index f4f3de1..40db73b 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -264,12 +264,26 @@
     StoreIntoObjectFilterNoSmi(object, value, &done);
   }
   // A store buffer update is required.
-  if (value != T0) Push(T0);  // Preserve T0.
+  if (value != T0) {
+    // Preserve T0.
+    addiu(SP, SP, Immediate(-2 * kWordSize));
+    sw(T0, Address(SP, 1 * kWordSize));
+  } else {
+    addiu(SP, SP, Immediate(-1 * kWordSize));
+  }
+  sw(RA, Address(SP, 0 * kWordSize));
   if (object != T0) {
     mov(T0, object);
   }
   BranchLink(&StubCode::UpdateStoreBufferLabel());
-  if (value != T0) Pop(T0);  // Restore T0.
+  lw(RA, Address(SP, 0 * kWordSize));
+  if (value != T0) {
+    // Restore T0.
+    lw(T0, Address(SP, 1 * kWordSize));
+    addiu(SP, SP, Immediate(2 * kWordSize));
+  } else {
+    addiu(SP, SP, Immediate(1 * kWordSize));
+  }
   Bind(&done);
 }
 
@@ -486,6 +500,18 @@
 }
 
 
+void Assembler::LeaveDartFrame() {
+  addiu(SP, FP, Immediate(-kWordSize));
+
+  lw(RA, Address(SP, 2 * kWordSize));
+  lw(FP, Address(SP, 1 * kWordSize));
+  lw(PP, Address(SP, 0 * kWordSize));
+
+  // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame.
+  addiu(SP, SP, Immediate(4 * kWordSize));
+}
+
+
 void Assembler::LeaveDartFrameAndReturn() {
   addiu(SP, FP, Immediate(-kWordSize));
 
@@ -493,7 +519,7 @@
   lw(FP, Address(SP, 1 * kWordSize));
   lw(PP, Address(SP, 0 * kWordSize));
 
-  // Adjust SP for PC pushed in EnterDartFrame, and return.
+  // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return.
   Ret();
   delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize));
 }
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index b94675a..7b4a462 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -995,6 +995,26 @@
     sra(reg, reg, kSmiTagSize);
   }
 
+  void LoadFromOffset(Register reg, Register base, int32_t offset) {
+    if (Utils::IsInt(kImmBits, offset)) {
+      lw(reg, Address(base, offset));
+    } else {
+      LoadImmediate(TMP, offset);
+      addu(TMP, base, TMP);
+      lw(reg, Address(TMP, 0));
+    }
+  }
+
+  void StoreToOffset(Register reg, Register base, int32_t offset) {
+    if (Utils::IsInt(kImmBits, offset)) {
+      sw(reg, Address(base, offset));
+    } else {
+      LoadImmediate(TMP, offset);
+      addu(TMP, base, TMP);
+      sw(reg, Address(TMP, 0));
+    }
+  }
+
   void StoreDToOffset(DRegister reg, Register base, int32_t offset) {
     FRegister lo = static_cast<FRegister>(reg * 2);
     FRegister hi = static_cast<FRegister>(reg * 2 + 1);
@@ -1049,6 +1069,7 @@
   // enable easy access to the RawInstruction object of code corresponding
   // to this frame.
   void EnterDartFrame(intptr_t frame_size);
+  void LeaveDartFrame();
   void LeaveDartFrameAndReturn();
 
  private:
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index 0f2b66e..ffce35a 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -32,7 +32,6 @@
   V(ForNode, "for")                                                            \
   V(JumpNode, "jump")                                                          \
   V(ArgumentListNode, "args")                                                  \
-  V(ArgumentDefinitionTestNode, "defined")                                     \
   V(ArrayNode, "array")                                                        \
   V(ClosureNode, "closure")                                                    \
   V(InstanceCallNode, "instance call")                                         \
@@ -229,41 +228,6 @@
 };
 
 
-class ArgumentDefinitionTestNode : public AstNode {
- public:
-  ArgumentDefinitionTestNode(intptr_t token_pos,
-                             intptr_t formal_parameter_index,
-                             const String& formal_parameter_name,
-                             LocalVariable* saved_arguments_descriptor)
-     : AstNode(token_pos),
-       formal_parameter_index_(formal_parameter_index),
-       formal_parameter_name_(formal_parameter_name),
-       saved_arguments_descriptor_(*saved_arguments_descriptor) {
-    ASSERT(formal_parameter_index_ >= 0);
-    ASSERT(formal_parameter_name_.IsZoneHandle());
-    ASSERT(formal_parameter_name_.IsSymbol());
-    ASSERT(saved_arguments_descriptor != NULL);
-  }
-
-  virtual void VisitChildren(AstNodeVisitor* visitor) const { }
-
-  intptr_t formal_parameter_index() const { return formal_parameter_index_; }
-  const String& formal_parameter_name() const { return formal_parameter_name_; }
-  const LocalVariable& saved_arguments_descriptor() const {
-    return saved_arguments_descriptor_;
-  }
-
-  DECLARE_COMMON_NODE_FUNCTIONS(ArgumentDefinitionTestNode);
-
- private:
-  const intptr_t formal_parameter_index_;
-  const String& formal_parameter_name_;
-  const LocalVariable& saved_arguments_descriptor_;
-
-  DISALLOW_COPY_AND_ASSIGN(ArgumentDefinitionTestNode);
-};
-
-
 class LetNode : public AstNode {
  public:
   explicit LetNode(intptr_t token_pos);
diff --git a/runtime/vm/ast_printer.cc b/runtime/vm/ast_printer.cc
index 58fce94..db100d7 100644
--- a/runtime/vm/ast_printer.cc
+++ b/runtime/vm/ast_printer.cc
@@ -48,15 +48,6 @@
 }
 
 
-void AstPrinter::VisitArgumentDefinitionTestNode(
-    ArgumentDefinitionTestNode* node) {
-  OS::Print("(%s ?%s @%"Pd")",
-            node->Name(),
-            node->formal_parameter_name().ToCString(),
-            node->formal_parameter_index());
-}
-
-
 void AstPrinter::VisitReturnNode(ReturnNode* node) {
   VisitGenericAstNode(node);
 }
diff --git a/runtime/vm/bigint_operations_test.cc b/runtime/vm/bigint_operations_test.cc
index 54dd297..46867fe 100644
--- a/runtime/vm/bigint_operations_test.cc
+++ b/runtime/vm/bigint_operations_test.cc
@@ -1340,9 +1340,6 @@
 }
 
 
-#if defined(TARGET_ARCH_IA32) ||                                               \
-    defined(TARGET_ARCH_X64) ||                                                \
-    defined(TARGET_ARCH_ARM)
 static void TestBigintMultiplyDivide(const char* a,
                                      const char* b,
                                      const char* product) {
@@ -2134,7 +2131,6 @@
       "000000000000000000000000000000000000000000000000000000000000000000000000"
       "0000000000000000000000000000000000000000000000000000000001");
 }
-#endif
 
 
 static void TestBigintDivideRemainder(const char* a,
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 680fb33..ac1b3d5 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -30,29 +30,32 @@
 DEFINE_FLAG(bool, deoptimize_alot, false,
     "Deoptimizes all live frames when we are about to return to Dart code from"
     " native entries.");
+DEFINE_FLAG(int, max_subtype_cache_entries, 100,
+    "Maximum number of subtype cache entries (number of checks cached).");
+DEFINE_FLAG(int, optimization_counter_threshold, 15000,
+    "Function's usage-counter value before it is optimized, -1 means never");
+DEFINE_FLAG(charp, optimization_filter, NULL, "Optimize only named function");
+DEFINE_FLAG(int, reoptimization_counter_threshold, 2000,
+    "Counter threshold before a function gets reoptimized.");
+DEFINE_FLAG(bool, stop_on_excessive_deoptimization, false,
+    "Debugging: stops program if deoptimizing same function too often");
 DEFINE_FLAG(bool, trace_deoptimization, false, "Trace deoptimization");
 DEFINE_FLAG(bool, trace_deoptimization_verbose, false,
     "Trace deoptimization verbose");
+DEFINE_FLAG(bool, trace_failed_optimization_attempts, false,
+    "Traces all failed optimization attempts");
 DEFINE_FLAG(bool, trace_ic, false, "Trace IC handling");
 DEFINE_FLAG(bool, trace_ic_miss_in_optimized, false,
     "Trace IC miss in optimized code");
-DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code.");
-DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
-DEFINE_FLAG(int, optimization_counter_threshold, 15000,
-    "Function's usage-counter value before it is optimized, -1 means never");
-DECLARE_FLAG(bool, enable_type_checks);
-DECLARE_FLAG(bool, trace_type_checks);
-DECLARE_FLAG(bool, report_usage_count);
-DECLARE_FLAG(int, deoptimization_counter_threshold);
-DEFINE_FLAG(charp, optimization_filter, NULL, "Optimize only named function");
-DEFINE_FLAG(bool, trace_failed_optimization_attempts, false,
-    "Traces all failed optimization attempts");
 DEFINE_FLAG(bool, trace_optimized_ic_calls, false,
     "Trace IC calls in optimized code.");
-DEFINE_FLAG(int, reoptimization_counter_threshold, 2000,
-    "Counter threshold before a function gets reoptimized.");
-DEFINE_FLAG(int, max_subtype_cache_entries, 100,
-    "Maximum number of subtype cache entries (number of checks cached).");
+DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code.");
+DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
+
+DECLARE_FLAG(int, deoptimization_counter_threshold);
+DECLARE_FLAG(bool, enable_type_checks);
+DECLARE_FLAG(bool, report_usage_count);
+DECLARE_FLAG(bool, trace_type_checks);
 
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
 DEFINE_FLAG(bool, use_osr, true, "Use on-stack replacement.");
@@ -1297,9 +1300,13 @@
   }
   if (function.deoptimization_counter() >=
       FLAG_deoptimization_counter_threshold) {
-    if (FLAG_trace_failed_optimization_attempts) {
+    if (FLAG_trace_failed_optimization_attempts ||
+        FLAG_stop_on_excessive_deoptimization) {
       OS::PrintErr("Too Many Deoptimizations: %s\n",
           function.ToFullyQualifiedCString());
+      if (FLAG_stop_on_excessive_deoptimization) {
+        FATAL("Stop on excessive deoptimization");
+      }
     }
     // TODO(srdjan): Investigate excessive deoptimization.
     function.set_usage_counter(kLowInvocationCount);
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 2faa434..ee9a5a0 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -48,6 +48,8 @@
     "attempt to sink temporary allocations to side exits");
 DEFINE_FLAG(int, deoptimization_counter_threshold, 16,
     "How many times we allow deoptimization before we disallow optimization.");
+DEFINE_FLAG(int, deoptimization_counter_licm_threshold, 8,
+    "How many times we allow deoptimization before we disable LICM.");
 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining");
 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis");
 DEFINE_FLAG(bool, verify_compiler, false,
@@ -400,7 +402,7 @@
       }
       if (FLAG_loop_invariant_code_motion &&
           (function.deoptimization_counter() <
-           (FLAG_deoptimization_counter_threshold - 1))) {
+           FLAG_deoptimization_counter_licm_threshold)) {
         LICM licm(flow_graph);
         licm.Optimize();
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index 2287be2..43b7d58 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -11,11 +11,6 @@
 
 namespace dart {
 
-// Compiler only implemented on IA32, X64, and ARM.
-#if defined(TARGET_ARCH_IA32) ||                                               \
-    defined(TARGET_ARCH_X64) ||                                                \
-    defined(TARGET_ARCH_ARM)
-
 TEST_CASE(CompileScript) {
   const char* kScriptChars =
       "class A {\n"
@@ -67,6 +62,4 @@
   EXPECT(function_moo.HasCode());
 }
 
-#endif  // TARGET_ARCH_IA32 || TARGET_ARCH_X64 || TARGET_ARCH_ARM
-
 }  // namespace dart
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 2c78b52..c030ea6 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -2815,8 +2815,8 @@
 
   // Error cases.
   EXPECT_ERROR(Dart_ClassGetInterfaceCount(Dart_True(), &len),
-               "Dart_ClassGetInterfaceCount expects argument 'clazz' to be of "
-               "type Class.");
+               "Dart_ClassGetInterfaceCount expects argument 'object' to be of "
+               "type Class/Type.");
   EXPECT_ERROR(Dart_ClassGetInterfaceCount(Dart_NewApiError("MyError"), &len),
                "MyError");
 }
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index ea92980..339f51d 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -638,6 +638,11 @@
             Format(instr, "umull'cond's 'rd, 'rn, 'rm, 'rs");
             break;
           }
+          case 5: {
+            // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+            Format(instr, "umlal'cond's 'rd, 'rn, 'rm, 'rs");
+            break;
+          }
           case 6: {
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             Format(instr, "smull'cond's 'rd, 'rn, 'rm, 'rs");
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 2f96f61..e3700f6 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1813,17 +1813,6 @@
 }
 
 
-void EffectGraphVisitor::VisitArgumentDefinitionTestNode(
-    ArgumentDefinitionTestNode* node) {
-  InlineBailout("EffectGraphVisitor::VisitArgumentDefinitionTestNode");
-  Definition* load = BuildLoadLocal(node->saved_arguments_descriptor());
-  Value* arguments_descriptor = Bind(load);
-  ArgumentDefinitionTestInstr* arg_def_test =
-      new ArgumentDefinitionTestInstr(node, arguments_descriptor);
-  ReturnDefinition(arg_def_test);
-}
-
-
 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const {
   return kFirstLocalSlotFromFp
       - owner()->num_stack_locals()
@@ -3117,15 +3106,9 @@
     if (node == owner()->parsed_function()->node_sequence()) {
       ASSERT(scope->context_level() == 1);
       const Function& function = owner()->parsed_function()->function();
-      int num_params = function.NumParameters();
+      const int num_params = function.NumParameters();
       int param_frame_index = (num_params == function.num_fixed_parameters()) ?
           (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp;
-      // Handle the saved arguments descriptor as an additional parameter.
-      if (owner()->parsed_function()->GetSavedArgumentsDescriptorVar() !=
-          NULL) {
-        ASSERT(param_frame_index == kFirstLocalSlotFromFp);
-        num_params++;
-      }
       for (int pos = 0; pos < num_params; param_frame_index--, pos++) {
         const LocalVariable& parameter = *scope->VariableAt(pos);
         ASSERT(parameter.owner() == scope);
@@ -3244,45 +3227,52 @@
 
 void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
   InlineBailout("EffectGraphVisitor::VisitTryCatchNode (exception)");
-  intptr_t old_try_index = owner()->try_index();
-  intptr_t try_index = owner()->AllocateTryIndex();
-  owner()->set_try_index(try_index);
+  intptr_t original_handler_index = owner()->try_index();
+  intptr_t try_handler_index = owner()->AllocateTryIndex();
+  owner()->set_try_index(try_handler_index);
 
   // Preserve CTX into local variable '%saved_context'.
   BuildStoreContext(node->context_var());
 
-  EffectGraphVisitor for_try_block(owner(), temp_index());
-  node->try_block()->Visit(&for_try_block);
+  EffectGraphVisitor for_try(owner(), temp_index());
+  node->try_block()->Visit(&for_try);
 
-  if (for_try_block.is_open()) {
+  if (for_try.is_open()) {
     JoinEntryInstr* after_try =
-        new JoinEntryInstr(owner()->AllocateBlockId(), old_try_index);
-    for_try_block.Goto(after_try);
-    for_try_block.exit_ = after_try;
+        new JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index);
+    for_try.Goto(after_try);
+    for_try.exit_ = after_try;
   }
 
   JoinEntryInstr* try_entry =
-      new JoinEntryInstr(owner()->AllocateBlockId(), try_index);
+      new JoinEntryInstr(owner()->AllocateBlockId(), try_handler_index);
 
   Goto(try_entry);
-  AppendFragment(try_entry, for_try_block);
-  exit_ = for_try_block.exit_;
+  AppendFragment(try_entry, for_try);
+  exit_ = for_try.exit_;
 
   // We are done generating code for the try block.
-  owner()->set_try_index(old_try_index);
+  owner()->set_try_index(original_handler_index);
 
   CatchClauseNode* catch_block = node->catch_block();
+  SequenceNode* finally_block = node->finally_block();
   if (catch_block != NULL) {
-    EffectGraphVisitor for_catch_block(owner(), temp_index());
-    catch_block->Visit(&for_catch_block);
+    // If there is a finally block, it is the handler for code in the catch
+    // block.
+    intptr_t catch_handler_index = (finally_block == NULL)
+        ? original_handler_index
+        : owner()->AllocateTryIndex();
+    owner()->set_try_index(catch_handler_index);
+    EffectGraphVisitor for_catch(owner(), temp_index());
+    catch_block->Visit(&for_catch);
     CatchBlockEntryInstr* catch_entry =
         new CatchBlockEntryInstr(owner()->AllocateBlockId(),
-                                 old_try_index,
+                                 catch_handler_index,
                                  catch_block->handler_types(),
-                                 try_index);
+                                 try_handler_index);
     owner()->AddCatchEntry(catch_entry);
-    ASSERT(!for_catch_block.is_open());
-    AppendFragment(catch_entry, for_catch_block);
+    ASSERT(!for_catch.is_open());
+    AppendFragment(catch_entry, for_catch);
     if (node->end_catch_label() != NULL) {
       JoinEntryInstr* join = node->end_catch_label()->join_for_continue();
       if (join != NULL) {
@@ -3290,12 +3280,47 @@
         exit_ = join;
       }
     }
+
+    if (finally_block != NULL) {
+      // Create a handler for the code in the catch block, containing the
+      // code in the finally block.
+      owner()->set_try_index(original_handler_index);
+      EffectGraphVisitor for_finally(owner(), temp_index());
+      for_finally.AddInstruction(
+          new CatchEntryInstr(catch_block->exception_var(),
+                              catch_block->stacktrace_var()));
+      for_finally.BuildLoadContext(catch_block->context_var());
+
+      finally_block->Visit(&for_finally);
+      if (for_finally.is_open()) {
+        // Rethrow the exception.  Manually build the graph for rethrow.
+        Value* exception = for_finally.Bind(
+            for_finally.BuildLoadLocal(catch_block->exception_var()));
+        for_finally.PushArgument(exception);
+        Value* stacktrace = for_finally.Bind(
+            for_finally.BuildLoadLocal(catch_block->stacktrace_var()));
+        for_finally.PushArgument(stacktrace);
+        for_finally.AddInstruction(new ReThrowInstr(catch_block->token_pos()));
+        for_finally.CloseFragment();
+      }
+      ASSERT(!for_finally.is_open());
+
+      const Array& types = Array::ZoneHandle(Array::New(1, Heap::kOld));
+      types.SetAt(0, Type::Handle(Type::DynamicType()));
+      CatchBlockEntryInstr* finally_entry =
+          new CatchBlockEntryInstr(owner()->AllocateBlockId(),
+                                   original_handler_index,
+                                   types,
+                                   catch_handler_index);
+      owner()->AddCatchEntry(finally_entry);
+      AppendFragment(finally_entry, for_finally);
+    }
   }
 
   // Generate code for the finally block if one exists.
-  if ((node->finally_block() != NULL) && is_open()) {
+  if ((finally_block != NULL) && is_open()) {
     EffectGraphVisitor for_finally_block(owner(), temp_index());
-    node->finally_block()->Visit(&for_finally_block);
+    finally_block->Visit(&for_finally_block);
     Append(for_finally_block);
   }
 }
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 6e61549..9aa4474 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1035,8 +1035,6 @@
   // the presence of optional parameters.
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
-  LocalVariable* saved_args_desc_var =
-      parsed_function().GetSavedArgumentsDescriptorVar();
   if (num_copied_params == 0) {
 #ifdef DEBUG
     ASSERT(!parsed_function().function().HasOptionalParameters());
@@ -1078,26 +1076,12 @@
       }
       __ Bind(&correct_num_arguments);
     }
-    // The arguments descriptor is never saved in the absence of optional
-    // parameters, since any argument definition test would always yield true.
-    ASSERT(saved_args_desc_var == NULL);
   } else {
-    if (saved_args_desc_var != NULL) {
-      __ Comment("Save arguments descriptor");
-      const Register kArgumentsDescriptorReg = R4;
-      // The saved_args_desc_var is allocated one slot before the first local.
-      const intptr_t slot = parsed_function().first_stack_local_index() + 1;
-      // If the saved_args_desc_var is captured, it is first moved to the stack
-      // and later to the context, once the context is allocated.
-      ASSERT(saved_args_desc_var->is_captured() ||
-             (saved_args_desc_var->index() == slot));
-      __ str(kArgumentsDescriptorReg, Address(FP, slot * kWordSize));
-    }
     CopyParameters();
   }
 
   // In unoptimized code, initialize (non-argument) stack allocated slots to
-  // null. This does not cover the saved_args_desc_var slot.
+  // null.
   if (!is_optimizing() && (num_locals > 0)) {
     __ Comment("Initialize spill slots");
     const intptr_t slot_base = parsed_function().first_stack_local_index();
@@ -1354,7 +1338,11 @@
       (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) {
     __ Push(reg);
     __ PushObject(obj);
-    __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
+    if (is_optimizing()) {
+      __ BranchLink(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
+    } else {
+      __ BranchLink(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
+    }
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
@@ -1374,7 +1362,11 @@
   if (needs_number_check) {
     __ Push(left);
     __ Push(right);
-    __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
+    if (is_optimizing()) {
+      __ BranchLink(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
+    } else {
+      __ BranchLink(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
+    }
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
@@ -1566,7 +1558,7 @@
     intptr_t index_scale,
     Register array,
     intptr_t index) {
-  UNIMPLEMENTED();
+  UNREACHABLE();
   return FieldAddress(array, index);
 }
 
@@ -1575,7 +1567,7 @@
     intptr_t index_scale,
     Register array,
     Register index) {
-  UNIMPLEMENTED();
+  UNREACHABLE();
   return FieldAddress(array, index);
 }
 
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 6504aa6..ca0a90e 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -992,16 +992,6 @@
   }
 
   __ Bind(&wrong_num_arguments);
-  if (StackSize() != 0) {
-    // We need to unwind the space we reserved for locals and copied parameters.
-    // The NoSuchMethodFunction stub does not expect to see that area on the
-    // stack.
-    __ addl(ESP, Immediate(StackSize() * kWordSize));
-  }
-  // The call below has an empty stackmap because we have just
-  // dropped the spill slots.
-  BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
-
   // Invoke noSuchMethod function passing the original name of the function.
   // If the function is a closure function, use "call" as the original name.
   const String& name = String::Handle(
@@ -1011,24 +1001,10 @@
       ICData::New(function, name, Object::null_array(),
                   Isolate::kNoDeoptId, kNumArgsChecked));
   __ LoadObject(ECX, ic_data);
-  // EBP - 4 : PC marker, allows easy identification of RawInstruction obj.
-  // EBP : points to previous frame pointer.
-  // EBP + 4 : points to return address.
-  // EBP + 8 : address of last argument (arg n-1).
-  // ESP + 8 + 4*(n-1) : address of first argument (arg 0).
-  // ECX : ic-data.
-  // EDX : arguments descriptor array.
-  __ call(&StubCode::CallNoSuchMethodFunctionLabel());
-  // Emit descriptors in order to provide correct postion in stacktrace.
-  AddCurrentDescriptor(PcDescriptors::kOther, -1, function.token_pos());
-  if (is_optimizing()) {
-    stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
-                                      empty_stack_bitmap,
-                                      0);  // No registers.
-  }
-  // The noSuchMethod call may return.
-  __ LeaveFrame();
-  __ ret();
+  __ LeaveFrame();  // The arguments are still on the stack.
+  __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
+  // The noSuchMethod call may return to the caller, but not here.
+  __ int3();
 
   __ Bind(&all_arguments_processed);
   // Nullify originally passed arguments only after they have been copied and
@@ -1142,8 +1118,6 @@
   // the presence of optional parameters.
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
-  LocalVariable* saved_args_desc_var =
-      parsed_function().GetSavedArgumentsDescriptorVar();
   if (num_copied_params == 0) {
 #ifdef DEBUG
     ASSERT(!parsed_function().function().HasOptionalParameters());
@@ -1167,16 +1141,6 @@
 
       __ Bind(&wrong_num_arguments);
       if (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) {
-        if (StackSize() != 0) {
-          // We need to unwind the space we reserved for locals and copied
-          // parameters. The NoSuchMethodFunction stub does not expect to see
-          // that area on the stack.
-          __ addl(ESP, Immediate(StackSize() * kWordSize));
-        }
-        // The call below has an empty stackmap because we have just
-        // dropped the spill slots.
-        BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
-
         // Invoke noSuchMethod function passing the original function name.
         // For closure functions, use "call" as the original name.
         const String& name =
@@ -1188,49 +1152,21 @@
             ICData::New(function, name, Object::null_array(),
                         Isolate::kNoDeoptId, kNumArgsChecked));
         __ LoadObject(ECX, ic_data);
-        // EBP - 4 : PC marker, for easy identification of RawInstruction obj.
-        // EBP : points to previous frame pointer.
-        // EBP + 4 : points to return address.
-        // EBP + 8 : address of last argument (arg n-1).
-        // ESP + 8 + 4*(n-1) : address of first argument (arg 0).
-        // ECX : ic-data.
-        // EDX : arguments descriptor array.
-        __ call(&StubCode::CallNoSuchMethodFunctionLabel());
-        // Emit descriptors in order to provide correct postion in stacktrace.
-        AddCurrentDescriptor(PcDescriptors::kOther, -1, function.token_pos());
-        if (is_optimizing()) {
-          stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
-                                            empty_stack_bitmap,
-                                            0);  // No registers.
-        }
-        // The noSuchMethod call may return.
-        __ LeaveFrame();
-        __ ret();
+        __ LeaveFrame();  // The arguments are still on the stack.
+        __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
+        // The noSuchMethod call may return to the caller, but not here.
+        __ int3();
       } else {
         __ Stop("Wrong number of arguments");
       }
       __ Bind(&correct_num_arguments);
     }
-    // The arguments descriptor is never saved in the absence of optional
-    // parameters, since any argument definition test would always yield true.
-    ASSERT(saved_args_desc_var == NULL);
   } else if (!flow_graph().IsCompiledForOsr()) {
-    if (saved_args_desc_var != NULL) {
-      __ Comment("Save arguments descriptor");
-      const Register kArgumentsDescriptorReg = EDX;
-      // The saved_args_desc_var is allocated one slot before the first local.
-      const intptr_t slot = parsed_function().first_stack_local_index() + 1;
-      // If the saved_args_desc_var is captured, it is first moved to the stack
-      // and later to the context, once the context is allocated.
-      ASSERT(saved_args_desc_var->is_captured() ||
-             (saved_args_desc_var->index() == slot));
-      __ movl(Address(EBP, slot * kWordSize), kArgumentsDescriptorReg);
-    }
     CopyParameters();
   }
 
   // In unoptimized code, initialize (non-argument) stack allocated slots to
-  // null. This does not cover the saved_args_desc_var slot.
+  // null.
   if (!is_optimizing() && (num_locals > 0)) {
     __ Comment("Initialize spill slots");
     const intptr_t slot_base = parsed_function().first_stack_local_index();
@@ -1496,7 +1432,11 @@
   if (needs_number_check) {
     __ pushl(reg);
     __ PushObject(obj);
-    __ call(&StubCode::IdenticalWithNumberCheckLabel());
+    if (is_optimizing()) {
+      __ call(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
+    } else {
+      __ call(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
+    }
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
@@ -1516,7 +1456,11 @@
   if (needs_number_check) {
     __ pushl(left);
     __ pushl(right);
-    __ call(&StubCode::IdenticalWithNumberCheckLabel());
+    if (is_optimizing()) {
+      __ call(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
+    } else {
+      __ call(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
+    }
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 2177423..b618668 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -920,16 +920,6 @@
   }
 
   __ Bind(&wrong_num_arguments);
-  if (StackSize() != 0) {
-    // We need to unwind the space we reserved for locals and copied parameters.
-    // The NoSuchMethodFunction stub does not expect to see that area on the
-    // stack.
-    __ AddImmediate(SP, StackSize() * kWordSize);
-  }
-  // The call below has an empty stackmap because we have just
-  // dropped the spill slots.
-  BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
-
   // Invoke noSuchMethod function passing the original name of the function.
   // If the function is a closure function, use "call" as the original name.
   const String& name = String::Handle(
@@ -939,25 +929,10 @@
       ICData::New(function, name, Object::null_array(),
                   Isolate::kNoDeoptId, kNumArgsChecked));
   __ LoadObject(S5, ic_data);
-  // FP - 4 : saved PP, object pool pointer of caller.
-  // FP + 0 : previous frame pointer.
-  // FP + 4 : return address.
-  // FP + 8 : PC marker, for easy identification of RawInstruction obj.
-  // FP + 12: last argument (arg n-1).
-  // SP + 0 : saved PP.
-  // SP + 16 + 4*(n-1) : first argument (arg 0).
-  // S5 : ic-data.
-  // S4 : arguments descriptor array.
-  __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel());
-  // Emit descriptors in order to provide correct postion in stacktrace.
-  AddCurrentDescriptor(PcDescriptors::kOther, -1, function.token_pos());
-  if (is_optimizing()) {
-    stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
-                                      empty_stack_bitmap,
-                                      0);  // No registers.
-  }
-  // The noSuchMethod call may return.
-  __ LeaveDartFrameAndReturn();
+  __ LeaveDartFrame();  // The arguments are still on the stack.
+  __ Branch(&StubCode::CallNoSuchMethodFunctionLabel());
+  // The noSuchMethod call may return to the caller, but not here.
+  __ break_(0);
 
   __ Bind(&all_arguments_processed);
   // Nullify originally passed arguments only after they have been copied and
@@ -1110,8 +1085,6 @@
   // the presence of optional parameters.
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
-  LocalVariable* saved_args_desc_var =
-      parsed_function().GetSavedArgumentsDescriptorVar();
   if (num_copied_params == 0) {
 #ifdef DEBUG
     ASSERT(!parsed_function().function().HasOptionalParameters());
@@ -1134,16 +1107,6 @@
       __ beq(T0, T1, &correct_num_arguments);
       __ Bind(&wrong_num_arguments);
       if (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) {
-        if (StackSize() != 0) {
-          // We need to unwind the space we reserved for locals and copied
-          // parameters. The NoSuchMethodFunction stub does not expect to see
-          // that area on the stack.
-          __ AddImmediate(SP, StackSize() * kWordSize);
-        }
-        // The call below has an empty stackmap because we have just
-        // dropped the spill slots.
-        BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
-
         // Invoke noSuchMethod function passing the original function name.
         // For closure functions, use "call" as the original name.
         const String& name =
@@ -1155,50 +1118,21 @@
             ICData::New(function, name, Object::null_array(),
                         Isolate::kNoDeoptId, kNumArgsChecked));
         __ LoadObject(S5, ic_data);
-        // FP - 4 : saved PP, object pool pointer of caller.
-        // FP + 0 : previous frame pointer.
-        // FP + 4 : return address.
-        // FP + 8 : PC marker, for easy identification of RawInstruction obj.
-        // FP + 12: last argument (arg n-1).
-        // SP + 0 : saved PP.
-        // SP + 16 + 4*(n-1) : first argument (arg 0).
-        // S5 : ic-data.
-        // S4 : arguments descriptor array.
-        __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel());
-        // Emit descriptors in order to provide correct postion in stacktrace.
-        AddCurrentDescriptor(PcDescriptors::kOther, -1, function.token_pos());
-        if (is_optimizing()) {
-          stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
-                                            empty_stack_bitmap,
-                                            0);  // No registers.
-        }
-        // The noSuchMethod call may return.
-        __ LeaveDartFrameAndReturn();
+        __ LeaveDartFrame();  // The arguments are still on the stack.
+        __ Branch(&StubCode::CallNoSuchMethodFunctionLabel());
+        // The noSuchMethod call may return to the caller, but not here.
+        __ break_(0);
       } else {
         __ Stop("Wrong number of arguments");
       }
       __ Bind(&correct_num_arguments);
     }
-    // The arguments descriptor is never saved in the absence of optional
-    // parameters, since any argument definition test would always yield true.
-    ASSERT(saved_args_desc_var == NULL);
   } else {
-    if (saved_args_desc_var != NULL) {
-      __ Comment("Save arguments descriptor");
-      const Register kArgumentsDescriptorReg = S4;
-      // The saved_args_desc_var is allocated one slot before the first local.
-      const intptr_t slot = parsed_function().first_stack_local_index() + 1;
-      // If the saved_args_desc_var is captured, it is first moved to the stack
-      // and later to the context, once the context is allocated.
-      ASSERT(saved_args_desc_var->is_captured() ||
-             (saved_args_desc_var->index() == slot));
-      __ sw(kArgumentsDescriptorReg, Address(FP, slot * kWordSize));
-    }
     CopyParameters();
   }
 
   // In unoptimized code, initialize (non-argument) stack allocated slots to
-  // null. This does not cover the saved_args_desc_var slot.
+  // null.
   if (!is_optimizing() && (num_locals > 0)) {
     __ TraceSimMsg("Initialize spill slots");
     __ Comment("Initialize spill slots");
@@ -1465,7 +1399,11 @@
     __ sw(reg, Address(SP, 1 * kWordSize));
     __ LoadObject(TMP1, obj);
     __ sw(TMP1, Address(SP, 0 * kWordSize));
-    __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
+    if (is_optimizing()) {
+      __ BranchLink(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
+    } else {
+      __ BranchLink(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
+    }
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
@@ -1488,7 +1426,11 @@
     __ addiu(SP, SP, Immediate(-2 * kWordSize));
     __ sw(left, Address(SP, 1 * kWordSize));
     __ sw(right, Address(SP, 0 * kWordSize));
-    __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
+    if (is_optimizing()) {
+      __ BranchLink(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
+    } else {
+      __ BranchLink(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
+    }
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
@@ -1663,6 +1605,7 @@
 
   switch (true_condition) {
     case EQ: assembler()->ceqd(left, right); break;
+    case NE: assembler()->ceqd(left, right); break;
     case LT: assembler()->coltd(left, right); break;
     case LE: assembler()->coled(left, right); break;
     case GT: assembler()->coltd(right, left); break;
@@ -1675,8 +1618,13 @@
   }
 
   assembler()->LoadImmediate(TMP, 1);
-  assembler()->movf(CMPRES, TMP);
-  assembler()->movt(CMPRES, ZR);
+  if (true_condition == NE) {
+    assembler()->movf(CMPRES, ZR);
+    assembler()->movt(CMPRES, TMP);
+  } else {
+    assembler()->movf(CMPRES, TMP);
+    assembler()->movt(CMPRES, ZR);
+  }
   assembler()->mov(TMP, ZR);
 
   // EmitBranchOnCondition expects ordering to be described by CMPRES, TMP1.
@@ -1696,6 +1644,7 @@
 
   switch (true_condition) {
     case EQ: assembler()->ceqd(left, right); break;
+    case NE: assembler()->ceqd(left, right); break;
     case LT: assembler()->coltd(left, right); break;
     case LE: assembler()->coled(left, right); break;
     case GT: assembler()->coltd(right, left); break;
@@ -1707,7 +1656,11 @@
     }
   }
 
-  assembler()->bc1f(&done);  // False is already in result.
+  if (true_condition == NE) {
+    assembler()->bc1t(&done);  // False is already in result.
+  } else {
+    assembler()->bc1f(&done);
+  }
   assembler()->LoadObject(result, Bool::True());
   assembler()->Bind(&done);
 }
@@ -1726,7 +1679,7 @@
                                                           intptr_t index_scale,
                                                           Register array,
                                                           Register index) {
-  UNIMPLEMENTED();
+  UNREACHABLE();
   return FieldAddress(array, index);
 }
 
@@ -1735,7 +1688,7 @@
     intptr_t index_scale,
     Register array,
     intptr_t index) {
-  UNIMPLEMENTED();
+  UNREACHABLE();
   return FieldAddress(array, index);
 }
 
@@ -1744,7 +1697,7 @@
     intptr_t index_scale,
     Register array,
     Register index) {
-  UNIMPLEMENTED();
+  UNREACHABLE();
   return FieldAddress(array, index);
 }
 
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 6190bb1..aabc161 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -986,16 +986,6 @@
   }
 
   __ Bind(&wrong_num_arguments);
-  if (StackSize() != 0) {
-    // We need to unwind the space we reserved for locals and copied parameters.
-    // The NoSuchMethodFunction stub does not expect to see that area on the
-    // stack.
-    __ addq(RSP, Immediate(StackSize() * kWordSize));
-  }
-  // The call below has an empty stackmap because we have just
-  // dropped the spill slots.
-  BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
-
   // Invoke noSuchMethod function passing the original name of the function.
   // If the function is a closure function, use "call" as the original name.
   const String& name = String::Handle(
@@ -1005,24 +995,10 @@
       ICData::New(function, name, Object::null_array(),
                   Isolate::kNoDeoptId, kNumArgsChecked));
   __ LoadObject(RBX, ic_data);
-  // RBP - 8 : PC marker, allows easy identification of RawInstruction obj.
-  // RBP : points to previous frame pointer.
-  // RBP + 8 : points to return address.
-  // RBP + 16 : address of last argument (arg n-1).
-  // RSP + 16 + 8*(n-1) : address of first argument (arg 0).
-  // RBX : ic-data.
-  // R10 : arguments descriptor array.
-  __ call(&StubCode::CallNoSuchMethodFunctionLabel());
-  // Emit descriptors in order to provide correct postion in stacktrace.
-  AddCurrentDescriptor(PcDescriptors::kOther, -1, function.token_pos());
-  if (is_optimizing()) {
-    stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
-                                      empty_stack_bitmap,
-                                      0);  // No registers.
-  }
-  // The noSuchMethod call may return.
-  __ LeaveFrame();
-  __ ret();
+  __ LeaveFrame();  // The arguments are still on the stack.
+  __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
+  // The noSuchMethod call may return to the caller, but not here.
+  __ int3();
 
   __ Bind(&all_arguments_processed);
   // Nullify originally passed arguments only after they have been copied and
@@ -1137,8 +1113,6 @@
   // the presence of optional parameters.
   // No such checking code is generated if only fixed parameters are declared,
   // unless we are in debug mode or unless we are compiling a closure.
-  LocalVariable* saved_args_desc_var =
-      parsed_function().GetSavedArgumentsDescriptorVar();
   if (num_copied_params == 0) {
 #ifdef DEBUG
     ASSERT(!parsed_function().function().HasOptionalParameters());
@@ -1162,16 +1136,6 @@
 
       __ Bind(&wrong_num_arguments);
       if (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) {
-        if (StackSize() != 0) {
-          // We need to unwind the space we reserved for locals and copied
-          // parameters. The NoSuchMethodFunction stub does not expect to see
-          // that area on the stack.
-          __ addq(RSP, Immediate(StackSize() * kWordSize));
-        }
-        // The call below has an empty stackmap because we have just
-        // dropped the spill slots.
-        BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
-
         // Invoke noSuchMethod function passing the original function name.
         // For closure functions, use "call" as the original name.
         const String& name =
@@ -1183,49 +1147,21 @@
             ICData::New(function, name, Object::null_array(),
                         Isolate::kNoDeoptId, kNumArgsChecked));
         __ LoadObject(RBX, ic_data);
-        // RBP - 8 : PC marker, for easy identification of RawInstruction obj.
-        // RBP : points to previous frame pointer.
-        // RBP + 8 : points to return address.
-        // RBP + 16 : address of last argument (arg n-1).
-        // RSP + 16 + 8*(n-1) : address of first argument (arg 0).
-        // RBX : ic-data.
-        // R10 : arguments descriptor array.
-        __ call(&StubCode::CallNoSuchMethodFunctionLabel());
-        // Emit descriptors in order to provide correct postion in stacktrace.
-        AddCurrentDescriptor(PcDescriptors::kOther, -1, function.token_pos());
-        if (is_optimizing()) {
-          stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
-                                            empty_stack_bitmap,
-                                            0);  // No registers.
-        }
-        // The noSuchMethod call may return.
-        __ LeaveFrame();
-        __ ret();
+        __ LeaveFrame();  // The arguments are still on the stack.
+        __ jmp(&StubCode::CallNoSuchMethodFunctionLabel());
+        // The noSuchMethod call may return to the caller, but not here.
+        __ int3();
       } else {
         __ Stop("Wrong number of arguments");
       }
       __ Bind(&correct_num_arguments);
     }
-    // The arguments descriptor is never saved in the absence of optional
-    // parameters, since any argument definition test would always yield true.
-    ASSERT(saved_args_desc_var == NULL);
   } else if (!flow_graph().IsCompiledForOsr()) {
-    if (saved_args_desc_var != NULL) {
-      __ Comment("Save arguments descriptor");
-      const Register kArgumentsDescriptorReg = R10;
-      // The saved_args_desc_var is allocated one slot before the first local.
-      const intptr_t slot = parsed_function().first_stack_local_index() + 1;
-      // If the saved_args_desc_var is captured, it is first moved to the stack
-      // and later to the context, once the context is allocated.
-      ASSERT(saved_args_desc_var->is_captured() ||
-             (saved_args_desc_var->index() == slot));
-      __ movq(Address(RBP, slot * kWordSize), kArgumentsDescriptorReg);
-    }
     CopyParameters();
   }
 
   // In unoptimized code, initialize (non-argument) stack allocated slots to
-  // null. This does not cover the saved_args_desc_var slot.
+  // null.
   if (!is_optimizing() && (num_locals > 0)) {
     __ Comment("Initialize spill slots");
     const intptr_t slot_base = parsed_function().first_stack_local_index();
@@ -1491,7 +1427,11 @@
   if (needs_number_check) {
     __ pushq(reg);
     __ PushObject(obj);
-    __ call(&StubCode::IdenticalWithNumberCheckLabel());
+    if (is_optimizing()) {
+      __ call(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
+    } else {
+      __ call(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
+    }
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
@@ -1511,7 +1451,11 @@
   if (needs_number_check) {
     __ pushq(left);
     __ pushq(right);
-    __ call(&StubCode::IdenticalWithNumberCheckLabel());
+    if (is_optimizing()) {
+      __ call(&StubCode::OptimizedIdenticalWithNumberCheckLabel());
+    } else {
+      __ call(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
+    }
     AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
                          Isolate::kNoDeoptId,
                          token_pos);
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index fe8573a..b388cdc 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -19,6 +19,8 @@
 
 namespace dart {
 
+DEFINE_FLAG(int, deoptimization_counter_inlining_threshold, 12,
+    "How many times we allow deoptimization before we stop inlining.");
 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
 
@@ -387,6 +389,10 @@
   void InlineCalls() {
     // If inlining depth is less then one abort.
     if (FLAG_inlining_depth_threshold < 1) return;
+    if (caller_graph_->parsed_function().function().deoptimization_counter() >=
+        FLAG_deoptimization_counter_inlining_threshold) {
+      return;
+    }
     // Create two call site collections to swap between.
     CallSites sites1(caller_graph_);
     CallSites sites2(caller_graph_);
@@ -543,16 +549,6 @@
                                     arguments,
                                     param_stubs,
                                     callee_graph);
-        // Add a bogus parameter at the end for the (unused) arguments
-        // descriptor slot. The parser allocates an extra slot between
-        // locals and parameters to hold the arguments descriptor in case it
-        // escapes.  We currently bailout if there are argument test
-        // expressions or escaping variables so this parameter and the stack
-        // slot are not used.
-        if (parsed_function->GetSavedArgumentsDescriptorVar() != NULL) {
-          param_stubs->Add(new ParameterInstr(
-              function.NumParameters(), callee_graph->graph_entry()));
-        }
       }
 
       // After treating optional parameters the actual/formal count must match.
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 8a66d91..279bf96 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -4047,6 +4047,34 @@
 
   const PhiPlaceMoves* phi_moves() const { return phi_moves_; }
 
+  // Returns true if the result of AllocateObject can be aliased by some
+  // other SSA variable and false otherwise. Currently simply checks if
+  // this value is stored in a field, escapes to another function or
+  // participates in a phi.
+  static bool CanBeAliased(AllocateObjectInstr* alloc) {
+    if (alloc->identity() == AllocateObjectInstr::kUnknown) {
+      bool escapes = false;
+      for (Value* use = alloc->input_use_list();
+           use != NULL;
+           use = use->next_use()) {
+        Instruction* instr = use->instruction();
+        if (instr->IsPushArgument() ||
+            (instr->IsStoreVMField() && (use->use_index() != 1)) ||
+            (instr->IsStoreInstanceField() && (use->use_index() != 0)) ||
+            (instr->IsStoreStaticField()) ||
+            (instr->IsPhi())) {
+          escapes = true;
+          break;
+        }
+      }
+
+      alloc->set_identity(escapes ? AllocateObjectInstr::kAliased
+                                  : AllocateObjectInstr::kNotAliased);
+    }
+
+    return alloc->identity() != AllocateObjectInstr::kNotAliased;
+  }
+
  private:
   // Get id assigned to the given field. Assign a new id if the field is seen
   // for the first time.
@@ -4094,34 +4122,6 @@
     return GetFieldId(kAnyInstance, field);
   }
 
-  // Returns true if the result of AllocateObject can be aliased by some
-  // other SSA variable and false otherwise. Currently simply checks if
-  // this value is stored in a field, escapes to another function or
-  // participates in a phi.
-  bool CanBeAliased(AllocateObjectInstr* alloc) {
-    if (alloc->identity() == AllocateObjectInstr::kUnknown) {
-      bool escapes = false;
-      for (Value* use = alloc->input_use_list();
-           use != NULL;
-           use = use->next_use()) {
-        Instruction* instr = use->instruction();
-        if (instr->IsPushArgument() ||
-            (instr->IsStoreVMField() && (use->use_index() != 0)) ||
-            (instr->IsStoreInstanceField() && (use->use_index() != 0)) ||
-            (instr->IsStoreStaticField()) ||
-            (instr->IsPhi())) {
-          escapes = true;
-          break;
-        }
-      }
-
-      alloc->set_identity(escapes ? AllocateObjectInstr::kAliased
-                                  : AllocateObjectInstr::kNotAliased);
-    }
-
-    return alloc->identity() != AllocateObjectInstr::kNotAliased;
-  }
-
   // Returns true if the given load is unaffected by external side-effects.
   // This essentially means that no stores to the same location can
   // occur in other functions.
@@ -4507,9 +4507,8 @@
         }
 
         // For object allocation forward initial values of the fields to
-        // subsequent loads.
-        // For simplicity we ignore escaping objects and objects that have
-        // type arguments.
+        // subsequent loads. For simplicity we ignore escaping objects.
+        //
         // The reason to ignore escaping objects is that final fields are
         // initialized in constructor that potentially can be not inlined into
         // the function that we are currently optimizing. However at the same
@@ -4521,7 +4520,7 @@
         // escaping object.
         AllocateObjectInstr* alloc = instr->AsAllocateObject();
         if ((alloc != NULL) &&
-            (alloc->identity() == AllocateObjectInstr::kNotAliased) &&
+            !AliasedSet::CanBeAliased(alloc) &&
             HasSimpleTypeArguments(alloc)) {
           for (Value* use = alloc->input_use_list();
                use != NULL;
@@ -5559,12 +5558,6 @@
 }
 
 
-void ConstantPropagator::VisitArgumentDefinitionTest(
-    ArgumentDefinitionTestInstr* instr) {
-  SetValue(instr, non_constant_);
-}
-
-
 void ConstantPropagator::VisitCurrentContext(CurrentContextInstr* instr) {
   SetValue(instr, non_constant_);
 }
@@ -5705,7 +5698,7 @@
   if (instr->left()->definition() == instr->right()->definition()) {
     // Fold x == x, and x != x to true/false for numbers and checked strict
     // comparisons.
-    if (instr->is_checked_strict_equal() ||
+    if (instr->IsCheckedStrictEqual() ||
         RawObject::IsIntegerClassId(instr->receiver_class_id())) {
       return SetValue(instr,
                       (instr->kind() == Token::kEQ)
@@ -6964,11 +6957,8 @@
                     alloc->ssa_temp_index());
         }
 
-        if (alloc->identity() == AllocateObjectInstr::kAliased) {
-          // Allocation might have been classified as aliased earlier due to
-          // some operations that are now eliminated.
-          alloc->set_identity(AllocateObjectInstr::kNotAliased);
-        }
+        // All sinking candidate are known to be not aliased.
+        alloc->set_identity(AllocateObjectInstr::kNotAliased);
 
         candidates.Add(alloc);
       }
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 7366821..3006a6a 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -786,11 +786,6 @@
 }
 
 
-CompileType ArgumentDefinitionTestInstr::ComputeType() const {
-  return CompileType::Bool();
-}
-
-
 CompileType BooleanNegateInstr::ComputeType() const {
   return CompileType::Bool();
 }
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index cdddcd7..d0cd907 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -329,14 +329,6 @@
 }
 
 
-void ArgumentDefinitionTestInstr::PrintOperandsTo(BufferFormatter* f) const {
-  saved_arguments_descriptor()->PrintTo(f);
-  f->Print(", ?%s @%"Pd"",
-           formal_parameter_name().ToCString(),
-           formal_parameter_index());
-}
-
-
 void ClosureCallInstr::PrintOperandsTo(BufferFormatter* f) const {
   for (intptr_t i = 0; i < ArgumentCount(); ++i) {
     if (i > 0) f->Print(", ");
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 9ade377..b04cc21 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -21,6 +21,9 @@
 
 namespace dart {
 
+DEFINE_FLAG(int, max_equality_polymorphic_checks, 32,
+    "Maximum number of polymorphic checks in equality operator,"
+    " otherwise use megamorphic dispatch.");
 DEFINE_FLAG(bool, new_identity_spec, true,
     "Use new identity check rules for numbers.");
 DEFINE_FLAG(bool, propagate_ic_data, true,
@@ -1034,6 +1037,14 @@
 }
 
 
+bool EqualityCompareInstr::IsCheckedStrictEqual() const {
+  if (!HasICData()) return false;
+  return ic_data()->AllTargetsHaveSameOwner(kInstanceCid) &&
+         (unary_ic_data_->NumberOfChecks() <=
+             FLAG_max_equality_polymorphic_checks);
+}
+
+
 bool BinarySmiOpInstr::CanDeoptimize() const {
   if (FLAG_throw_on_javascript_int_overflow) return true;
   switch (op_kind()) {
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index f4dc796..0e0df87 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -523,7 +523,6 @@
   M(Branch)                                                                    \
   M(AssertAssignable)                                                          \
   M(AssertBoolean)                                                             \
-  M(ArgumentDefinitionTest)                                                    \
   M(CurrentContext)                                                            \
   M(StoreContext)                                                              \
   M(ClosureCall)                                                               \
@@ -2514,42 +2513,6 @@
 };
 
 
-class ArgumentDefinitionTestInstr : public TemplateDefinition<1> {
- public:
-  ArgumentDefinitionTestInstr(ArgumentDefinitionTestNode* node,
-                              Value* saved_arguments_descriptor)
-      : ast_node_(*node) {
-    SetInputAt(0, saved_arguments_descriptor);
-  }
-
-  DECLARE_INSTRUCTION(ArgumentDefinitionTest)
-  virtual CompileType ComputeType() const;
-
-  intptr_t token_pos() const { return ast_node_.token_pos(); }
-  intptr_t formal_parameter_index() const {
-    return ast_node_.formal_parameter_index();
-  }
-  const String& formal_parameter_name() const {
-    return ast_node_.formal_parameter_name();
-  }
-
-  Value* saved_arguments_descriptor() const { return inputs_[0]; }
-
-  virtual void PrintOperandsTo(BufferFormatter* f) const;
-
-  virtual bool CanDeoptimize() const { return true; }
-
-  virtual EffectSet Effects() const { return EffectSet::None(); }
-
-  virtual bool MayThrow() const { return true; }
-
- private:
-  const ArgumentDefinitionTestNode& ast_node_;
-
-  DISALLOW_COPY_AND_ASSIGN(ArgumentDefinitionTestInstr);
-};
-
-
 // Denotes the current context, normally held in a register.  This is
 // a computation, not a value, because it's mutable.
 class CurrentContextInstr : public TemplateDefinition<0> {
@@ -2867,8 +2830,12 @@
                        const Array& ic_data_array)
       : ComparisonInstr(token_pos, kind, left, right),
         ic_data_(GetICData(ic_data_array)),
+        unary_ic_data_(NULL),
         receiver_class_id_(kIllegalCid) {
     ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
+    if (HasICData()) {
+      unary_ic_data_ = &ICData::ZoneHandle(ic_data_->AsUnaryClassChecks());
+    }
   }
 
   DECLARE_INSTRUCTION(EqualityCompare)
@@ -2879,7 +2846,12 @@
   bool HasICData() const {
     return (ic_data() != NULL) && !ic_data()->IsNull();
   }
-  void set_ic_data(const ICData* value) { ic_data_ = value; }
+  void set_ic_data(const ICData* value) {
+    ic_data_ = value;
+    if (HasICData()) {
+      unary_ic_data_ = &ICData::ZoneHandle(ic_data_->AsUnaryClassChecks());
+    }
+  }
 
   // Receiver class id is computed from collected ICData.
   void set_receiver_class_id(intptr_t value) { receiver_class_id_ = value; }
@@ -2891,9 +2863,7 @@
         || (receiver_class_id() == kSmiCid);
   }
 
-  bool is_checked_strict_equal() const {
-    return HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
-  }
+  bool IsCheckedStrictEqual() const;
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
@@ -2922,11 +2892,12 @@
   }
 
   virtual bool MayThrow() const {
-    return !IsInlinedNumericComparison() && !is_checked_strict_equal();
+    return !IsInlinedNumericComparison() && !IsCheckedStrictEqual();
   }
 
  private:
   const ICData* ic_data_;
+  ICData* unary_ic_data_;
   intptr_t receiver_class_id_;  // Set by optimizer.
 
   DISALLOW_COPY_AND_ASSIGN(EqualityCompareInstr);
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index d313806..218b64c 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -264,36 +264,6 @@
 }
 
 
-LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(R0));
-  locs->set_out(Location::RegisterLocation(R0));
-  return locs;
-}
-
-
-void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register saved_args_desc = locs()->in(0).reg();
-  Register result = locs()->out().reg();
-
-  // Push the result place holder initialized to NULL.
-  __ PushObject(Object::ZoneHandle());
-  __ LoadImmediate(IP, Smi::RawValue(formal_parameter_index()));
-  __ Push(IP);
-  __ PushObject(formal_parameter_name());
-  __ Push(saved_args_desc);
-  compiler->GenerateCallRuntime(token_pos(),
-                                deopt_id(),
-                                kArgumentDefinitionTestRuntimeEntry,
-                                locs());
-  __ Drop(3);
-  __ Pop(result);  // Pop bool result.
-}
-
-
 static Condition TokenKindToSmiCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ: return EQ;
@@ -343,7 +313,7 @@
     locs->set_out(Location::RequiresRegister());
     return locs;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@@ -786,7 +756,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
                            deopt_id());
     return;
@@ -827,7 +797,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
     return;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
                            deopt_id());
     return;
@@ -1193,42 +1163,41 @@
   Location index = locs()->in(1);
 
   Address element_address(kNoRegister, 0);
-  if (IsExternal()) {
-    UNIMPLEMENTED();
-  } else {
-    ASSERT(this->array()->definition()->representation() == kTagged);
-    ASSERT(index.IsRegister());  // TODO(regis): Revisit.
-    // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
-    // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
-    // index is expected to be untagged before accessing.
-    ASSERT(kSmiTagShift == 1);
-    switch (index_scale()) {
-      case 1: {
-        __ SmiUntag(index.reg());
-        break;
-      }
-      case 2: {
-        break;
-      }
-      case 4: {
-        __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 1));
-        break;
-      }
-      case 8: {
-        __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 2));
-        break;
-      }
-      case 16: {
-        __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 3));
-        break;
-      }
-      default:
-        UNREACHABLE();
+  ASSERT(index.IsRegister());  // TODO(regis): Revisit.
+  // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
+  // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
+  // index is expected to be untagged before accessing.
+  ASSERT(kSmiTagShift == 1);
+  switch (index_scale()) {
+    case 1: {
+      __ SmiUntag(index.reg());
+      break;
     }
+    case 2: {
+      break;
+    }
+    case 4: {
+      __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 1));
+      break;
+    }
+    case 8: {
+      __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 2));
+      break;
+    }
+    case 16: {
+      __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 3));
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+
+  if (!IsExternal()) {
+    ASSERT(this->array()->definition()->representation() == kTagged);
     __ AddImmediate(index.reg(),
         FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
-    element_address = Address(array, index.reg(), LSL, 0);
   }
+  element_address = Address(array, index.reg(), LSL, 0);
 
   if ((representation() == kUnboxedDouble) ||
       (representation() == kUnboxedMint) ||
@@ -1391,42 +1360,40 @@
   Location index = locs()->in(1);
 
   Address element_address(kNoRegister, 0);
-  if (IsExternal()) {
-    UNIMPLEMENTED();
-  } else {
-    ASSERT(this->array()->definition()->representation() == kTagged);
-    ASSERT(index.IsRegister());  // TODO(regis): Revisit.
-    // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
-    // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
-    // index is expected to be untagged before accessing.
-    ASSERT(kSmiTagShift == 1);
-    switch (index_scale()) {
-      case 1: {
-        __ SmiUntag(index.reg());
-        break;
-      }
-      case 2: {
-        break;
-      }
-      case 4: {
-        __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 1));
-        break;
-      }
-      case 8: {
-        __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 2));
-        break;
-      }
-      case 16: {
-        __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 3));
-        break;
-      }
-      default:
-        UNREACHABLE();
+  ASSERT(index.IsRegister());  // TODO(regis): Revisit.
+  // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
+  // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
+  // index is expected to be untagged before accessing.
+  ASSERT(kSmiTagShift == 1);
+  switch (index_scale()) {
+    case 1: {
+      __ SmiUntag(index.reg());
+      break;
     }
+    case 2: {
+      break;
+    }
+    case 4: {
+      __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 1));
+      break;
+    }
+    case 8: {
+      __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 2));
+      break;
+    }
+    case 16: {
+      __ mov(index.reg(), ShifterOperand(index.reg(), LSL, 3));
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+  if (!IsExternal()) {
+    ASSERT(this->array()->definition()->representation() == kTagged);
     __ AddImmediate(index.reg(),
         FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
-    element_address = Address(array, index.reg(), LSL, 0);
   }
+  element_address = Address(array, index.reg(), LSL, 0);
 
   switch (class_id()) {
     case kArrayCid:
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 2780369..b8c4942 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -213,35 +213,6 @@
 }
 
 
-LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(EAX));
-  locs->set_out(Location::RegisterLocation(EAX));
-  return locs;
-}
-
-
-void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register saved_args_desc = locs()->in(0).reg();
-  Register result = locs()->out().reg();
-
-  // Push the result place holder initialized to NULL.
-  __ PushObject(Object::ZoneHandle());
-  __ pushl(Immediate(Smi::RawValue(formal_parameter_index())));
-  __ PushObject(formal_parameter_name());
-  __ pushl(saved_args_desc);
-  compiler->GenerateCallRuntime(token_pos(),
-                                deopt_id(),
-                                kArgumentDefinitionTestRuntimeEntry,
-                                locs());
-  __ Drop(3);
-  __ popl(result);  // Pop bool result.
-}
-
-
 static Condition TokenKindToSmiCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ: return EQUAL;
@@ -292,7 +263,7 @@
     locs->set_out(Location::RequiresRegister());
     return locs;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@@ -835,7 +806,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
                            deopt_id());
     return;
@@ -875,7 +846,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
     return;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
                            deopt_id());
     return;
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index bbb4f5e..c954766 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -268,41 +268,6 @@
 }
 
 
-LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(T0));
-  locs->set_out(Location::RegisterLocation(T0));
-  return locs;
-}
-
-
-void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register saved_args_desc = locs()->in(0).reg();
-  Register result = locs()->out().reg();
-
-  __ TraceSimMsg("ArgumentDefinitionTestInstr");
-
-  __ addiu(SP, SP, Immediate(-4 * kWordSize));
-  // Push the result place holder initialized to NULL.
-  __ LoadObject(TMP1, Object::ZoneHandle());
-  __ sw(TMP1, Address(SP, 3 * kWordSize));
-  __ LoadImmediate(TMP1, Smi::RawValue(formal_parameter_index()));
-  __ sw(TMP1, Address(SP, 2 * kWordSize));
-  __ LoadObject(TMP1, formal_parameter_name());
-  __ sw(TMP1, Address(SP, 1 * kWordSize));
-  __ sw(saved_args_desc, Address(SP, 0 * kWordSize));
-  compiler->GenerateCallRuntime(token_pos(),
-                                deopt_id(),
-                                kArgumentDefinitionTestRuntimeEntry,
-                                locs());
-  __ lw(result, Address(SP, 3 * kWordSize));  // Pop bool result.
-  __ addiu(SP, SP, Immediate(4 * kWordSize));
-}
-
-
 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   if (receiver_class_id() == kMintCid) {
@@ -337,7 +302,7 @@
     locs->set_out(Location::RequiresRegister());
     return locs;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@@ -839,7 +804,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
                            deopt_id());
     return;
@@ -884,7 +849,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
     return;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
                            deopt_id());
     return;
@@ -1129,13 +1094,17 @@
 
 
 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  return LocationSummary::Make(kNumInputs,
+                               Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
 }
 
 
 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register object = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  __ LoadFromOffset(result, object, offset() - kHeapObjectTag);
 }
 
 
@@ -1256,39 +1225,44 @@
   Location index = locs()->in(1);
 
   Address element_address(kNoRegister, 0);
+
+  ASSERT(index.IsRegister());  // TODO(regis): Revisit.
+  // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
+  // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
+  // index is expected to be untagged before accessing.
+  ASSERT(kSmiTagShift == 1);
+  switch (index_scale()) {
+    case 1: {
+      __ SmiUntag(index.reg());
+      break;
+    }
+    case 2: {
+      break;
+    }
+    case 4: {
+      __ sll(index.reg(), index.reg(), 1);
+      break;
+    }
+    case 8: {
+      __ sll(index.reg(), index.reg(), 2);
+      break;
+    }
+    case 16: {
+      __ sll(index.reg(), index.reg(), 3);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+  __ addu(index.reg(), array, index.reg());
+
   if (IsExternal()) {
-    UNIMPLEMENTED();
+    element_address = Address(index.reg(), 0);
   } else {
     ASSERT(this->array()->definition()->representation() == kTagged);
-    ASSERT(index.IsRegister());  // TODO(regis): Revisit.
-    // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
-    // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
-    // index is expected to be untagged before accessing.
-    ASSERT(kSmiTagShift == 1);
-    switch (index_scale()) {
-      case 1: {
-        __ SmiUntag(index.reg());
-        break;
-      }
-      case 2: {
-        break;
-      }
-      case 4: {
-        __ sll(index.reg(), index.reg(), 1);
-        break;
-      }
-      case 8: {
-        __ sll(index.reg(), index.reg(), 2);
-        break;
-      }
-      case 16: {
-        __ sll(index.reg(), index.reg(), 3);
-        break;
-      }
-      default:
-        UNREACHABLE();
-    }
-    __ addu(index.reg(), array, index.reg());
+    // If the data offset doesn't fit into the 18 bits we get for the addressing
+    // mode, then we must load the offset into a register and add it to the
+    // index.
     element_address = Address(index.reg(),
         FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
   }
@@ -1454,39 +1428,40 @@
   Location index = locs()->in(1);
 
   Address element_address(kNoRegister, 0);
+  ASSERT(index.IsRegister());  // TODO(regis): Revisit.
+  // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
+  // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
+  // index is expected to be untagged before accessing.
+  ASSERT(kSmiTagShift == 1);
+  switch (index_scale()) {
+    case 1: {
+      __ SmiUntag(index.reg());
+      break;
+    }
+    case 2: {
+      break;
+    }
+    case 4: {
+      __ sll(index.reg(), index.reg(), 1);
+      break;
+    }
+    case 8: {
+      __ sll(index.reg(), index.reg(), 2);
+      break;
+    }
+    case 16: {
+      __ sll(index.reg(), index.reg(), 3);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+  __ addu(index.reg(), array, index.reg());
+
   if (IsExternal()) {
-    UNIMPLEMENTED();
+    element_address = Address(index.reg(), 0);
   } else {
     ASSERT(this->array()->definition()->representation() == kTagged);
-    ASSERT(index.IsRegister());  // TODO(regis): Revisit.
-    // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
-    // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
-    // index is expected to be untagged before accessing.
-    ASSERT(kSmiTagShift == 1);
-    switch (index_scale()) {
-      case 1: {
-        __ SmiUntag(index.reg());
-        break;
-      }
-      case 2: {
-        break;
-      }
-      case 4: {
-        __ sll(index.reg(), index.reg(), 1);
-        break;
-      }
-      case 8: {
-        __ sll(index.reg(), index.reg(), 2);
-        break;
-      }
-      case 16: {
-        __ sll(index.reg(), index.reg(), 3);
-        break;
-      }
-      default:
-        UNREACHABLE();
-    }
-    __ addu(index.reg(), array, index.reg());
     element_address = Address(index.reg(),
         FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
   }
@@ -2285,8 +2260,7 @@
       __ sltiu(CMPRES,
           right, Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
       __ movz(result, ZR, CMPRES);  // result = right >= kBits ? 0 : result.
-      __ mov(TMP1, right);
-      __ SmiUntag(TMP1);
+      __ sra(TMP1, right, kSmiTagSize);
       __ sllv(TMP1, left, TMP1);
       // result = right < kBits ? left << right : result.
       __ movn(result, TMP1, CMPRES);
@@ -2309,7 +2283,7 @@
     __ srav(temp, temp, TMP);
     __ bne(temp, left, deopt);  // Overflow.
     // Shift for result now we know there is no overflow.
-    __ sll(result, left, TMP);
+    __ sllv(result, left, TMP);
   }
 }
 
@@ -3107,13 +3081,48 @@
 
 
 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+  result->set_in(0, Location::RegisterLocation(T1));
+  result->set_out(Location::RegisterLocation(V0));
+  return result;
 }
 
 
 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register result = locs()->out().reg();
+  Register value_obj = locs()->in(0).reg();
+  ASSERT(result == V0);
+  ASSERT(result != value_obj);
+  __ LoadDFromOffset(DTMP, value_obj, Double::value_offset() - kHeapObjectTag);
+  __ cvtwd(STMP1, DTMP);
+  __ mfc1(result, STMP1);
+
+  // Overflow is signaled with minint.
+  Label do_call, done;
+  // Check for overflow and that it fits into Smi.
+  __ LoadImmediate(TMP, 0xC0000000);
+  __ subu(CMPRES, result, TMP);
+  __ bltz(CMPRES, &do_call);
+  __ SmiTag(result);
+  __ b(&done);
+  __ Bind(&do_call);
+  __ Push(value_obj);
+  ASSERT(instance_call()->HasICData());
+  const ICData& ic_data = *instance_call()->ic_data();
+  ASSERT((ic_data.NumberOfChecks() == 1));
+  const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
+
+  const intptr_t kNumberOfArguments = 1;
+  compiler->GenerateStaticCall(deopt_id(),
+                               instance_call()->token_pos(),
+                               target,
+                               kNumberOfArguments,
+                               Object::null_array(),  // No argument names.,
+                               locs());
+  __ Bind(&done);
 }
 
 
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 16cb424..3d91a75 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -379,35 +379,6 @@
 }
 
 
-LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs =
-      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(RAX));
-  locs->set_out(Location::RegisterLocation(RAX));
-  return locs;
-}
-
-
-void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register saved_args_desc = locs()->in(0).reg();
-  Register result = locs()->out().reg();
-
-  // Push the result place holder initialized to NULL.
-  __ PushObject(Object::ZoneHandle());
-  __ pushq(Immediate(Smi::RawValue(formal_parameter_index())));
-  __ PushObject(formal_parameter_name());
-  __ pushq(saved_args_desc);
-  compiler->GenerateCallRuntime(token_pos(),
-                                deopt_id(),
-                                kArgumentDefinitionTestRuntimeEntry,
-                                locs());
-  __ Drop(3);
-  __ popq(result);  // Pop bool result.
-}
-
-
 static Condition TokenKindToSmiCondition(Token::Kind kind) {
   switch (kind) {
     case Token::kEQ: return EQUAL;
@@ -448,7 +419,7 @@
     locs->set_out(Location::RequiresRegister());
     return locs;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@@ -880,7 +851,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
     return;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
                            deopt_id());
     return;
@@ -917,7 +888,7 @@
     EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
     return;
   }
-  if (is_checked_strict_equal()) {
+  if (IsCheckedStrictEqual()) {
     EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
                            deopt_id());
     return;
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 74ab05b..5b59253 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -237,7 +237,6 @@
 
   // Note that R1 is Smi, i.e, times 2.
   ASSERT(kSmiTagShift == 1);
-  // Destroy R2 as we will not continue in the function.
   __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
   __ add(R1, R0, ShifterOperand(R1, LSL, 1));  // R1 is Smi.
   __ StoreIntoObject(R0,
@@ -788,11 +787,14 @@
 
 
 bool Intrinsifier::Integer_negate(Assembler* assembler) {
+  Label fall_through;
   __ ldr(R0, Address(SP, + 0 * kWordSize));  // Grab first argument.
   __ tst(R0, ShifterOperand(kSmiTagMask));  // Test for Smi.
-  __ rsb(R0, R0, ShifterOperand(0), EQ);  // R0 is a Smi. R0 <- 0 - R0.
-  __ bx(LR, EQ);  // Return.
+  __ b(&fall_through, NE);
+  __ rsbs(R0, R0, ShifterOperand(0));  // R0 is a Smi. R0 <- 0 - R0.
+  __ bx(LR, VC);  // Return if there wasn't overflow, fall through otherwise.
   // R0 is not a Smi. Fall through.
+  __ Bind(&fall_through);
   return false;
 }
 
@@ -1400,9 +1402,9 @@
   __ LoadImmediate(R0, a_int32_value);
   __ LoadFromOffset(kLoadWord, R2, R1, disp_0 - kHeapObjectTag);
   __ LoadFromOffset(kLoadWord, R3, R1, disp_1 - kHeapObjectTag);
-  __ mov(R6, ShifterOperand(R3, ASR, 31));  // Sign extend into R6.
-  // 64-bit multiply and accumulate into R6:R3.
-  __ smlal(R3, R6, R0, R2);  // R6:R3 <- R6:R3 + R0 * R2.
+  __ mov(R6, ShifterOperand(0));  // Zero extend unsigned _state[kSTATE_HI].
+  // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3.
+  __ umlal(R3, R6, R0, R2);  // R6:R3 <- R6:R3 + R0 * R2.
   __ StoreToOffset(kStoreWord, R3, R1, disp_0 - kHeapObjectTag);
   __ StoreToOffset(kStoreWord, R6, R1, disp_1 - kHeapObjectTag);
   __ Ret();
@@ -1422,7 +1424,6 @@
 
 
 bool Intrinsifier::String_getHashCode(Assembler* assembler) {
-  __ Untested("Intrinsifier::String_getHashCode");
   __ ldr(R0, Address(SP, 0 * kWordSize));
   __ ldr(R0, FieldAddress(R0, String::hash_offset()));
   __ cmp(R0, ShifterOperand(0));
@@ -1439,9 +1440,8 @@
 }
 
 
-// TODO(srdjan): Implement for two and four byte strings as well.
 bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
-  Label fall_through;
+  Label fall_through, try_two_byte_string;
 
   __ ldr(R1, Address(SP, 0 * kWordSize));  // Index.
   __ ldr(R0, Address(SP, 1 * kWordSize));  // String.
@@ -1452,12 +1452,22 @@
   __ cmp(R1, ShifterOperand(R2));
   __ b(&fall_through, CS);  // Runtime throws exception.
   __ CompareClassId(R0, kOneByteStringCid, R3);
-  __ b(&fall_through, NE);
+  __ b(&try_two_byte_string, NE);
   __ SmiUntag(R1);
   __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag);
   __ ldrb(R0, Address(R0, R1));
   __ SmiTag(R0);
   __ Ret();
+
+  __ Bind(&try_two_byte_string);
+  __ CompareClassId(R0, kTwoByteStringCid, R3);
+  __ b(&fall_through, NE);
+  ASSERT(kSmiTagShift == 1);
+  __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag);
+  __ ldrh(R0, Address(R0, R1));
+  __ SmiTag(R0);
+  __ Ret();
+
   __ Bind(&fall_through);
   return false;
 }
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 5b704ce..62ec306 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -235,7 +235,7 @@
   __ j(ABOVE_EQUAL, &fall_through);
   // Note that EBX is Smi, i.e, times 2.
   ASSERT(kSmiTagShift == 1);
-  // Destroy ECX as we will not continue in the function.
+  // Destroy ECX (ic data) as we will not continue in the function.
   __ movl(ECX, Address(ESP, + 1 * kWordSize));  // Value.
   __ StoreIntoObject(EAX,
                      FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()),
@@ -1510,9 +1510,8 @@
 }
 
 
-// TODO(srdjan): Implement for two and four byte strings as well.
 bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
-  Label fall_through;
+  Label fall_through, try_two_byte_string;
   __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Index.
   __ movl(EAX, Address(ESP, + 2 * kWordSize));  // String.
   __ testl(EBX, Immediate(kSmiTagMask));
@@ -1522,11 +1521,20 @@
   // Runtime throws exception.
   __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
   __ CompareClassId(EAX, kOneByteStringCid, EDI);
-  __ j(NOT_EQUAL, &fall_through);
+  __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump);
   __ SmiUntag(EBX);
   __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()));
   __ SmiTag(EAX);
   __ ret();
+
+  __ Bind(&try_two_byte_string);
+  __ CompareClassId(EAX, kTwoByteStringCid, EDI);
+  __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
+  ASSERT(kSmiTagShift == 1);
+  __ movzxw(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()));
+  __ SmiTag(EAX);
+  __ ret();
+
   __ Bind(&fall_through);
   return false;
 }
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 2627738..9f4f783d 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -241,7 +241,6 @@
 
   // Note that T1 is Smi, i.e, times 2.
   ASSERT(kSmiTagShift == 1);
-  // Destroy T2 as we will not continue in the function.
   __ lw(T2, Address(SP, 0 * kWordSize));  // Value.
   __ sll(T1, T1, 1);  // T1 is Smi.
   __ addu(T1, T0, T1);
@@ -795,11 +794,12 @@
 bool Intrinsifier::Integer_negate(Assembler* assembler) {
   Label fall_through;
 
-  __ lw(V0, Address(SP, + 0 * kWordSize));  // Grabs first argument.
-  __ andi(CMPRES, V0, Immediate(kSmiTagMask));  // Test for Smi.
+  __ lw(T0, Address(SP, + 0 * kWordSize));  // Grabs first argument.
+  __ andi(CMPRES, T0, Immediate(kSmiTagMask));  // Test for Smi.
   __ bne(CMPRES, ZR, &fall_through);  // Fall through if not a Smi.
+  __ SubuDetectOverflow(V0, ZR, T0, CMPRES);
+  __ bltz(CMPRES, &fall_through);  // There was overflow.
   __ Ret();
-  __ delay_slot()->subu(V0, ZR, V0);
   __ Bind(&fall_through);
   return false;
 }
@@ -1459,11 +1459,10 @@
   __ LoadImmediate(T0, a_int32_value);
   __ lw(T2, addr_0);
   __ lw(T3, addr_1);
-  __ sra(T6, T3, 31);  // Sign extend T3 into T6.
   __ mtlo(T3);
-  __ mthi(T6);  // HI:LO <- T6:T3
+  __ mthi(ZR);  // HI:LO <- ZR:T3  Zero extend T3 into HI.
   // 64-bit multiply and accumulate into T6:T3.
-  __ madd(T0, T2);  // HI:LO <- HI:LO + T0 * T2.
+  __ maddu(T0, T2);  // HI:LO <- HI:LO + T0 * T2.
   __ mflo(T3);
   __ mfhi(T6);
   __ sw(T3, addr_0);
@@ -1490,7 +1489,6 @@
 
 bool Intrinsifier::String_getHashCode(Assembler* assembler) {
   Label fall_through;
-  __ Untested("Intrinsifier::String_getHashCode");
   __ lw(T0, Address(SP, 0 * kWordSize));
   __ lw(V0, FieldAddress(T0, String::hash_offset()));
   __ beq(V0, ZR, &fall_through);
@@ -1508,9 +1506,8 @@
 }
 
 
-// TODO(srdjan): Implement for two and four byte strings as well.
 bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
-  Label fall_through;
+  Label fall_through, try_two_byte_string;
 
   __ lw(T1, Address(SP, 0 * kWordSize));  // Index.
   __ lw(T0, Address(SP, 1 * kWordSize));  // String.
@@ -1522,7 +1519,7 @@
   // Runtime throws exception.
   __ BranchUnsignedGreaterEqual(T1, T2, &fall_through);
   __ LoadClassId(TMP1, T0);  // Class ID check.
-  __ BranchNotEqual(TMP1, kOneByteStringCid, &fall_through);
+  __ BranchNotEqual(TMP1, kOneByteStringCid, &try_two_byte_string);
 
   // Grab byte and return.
   __ SmiUntag(T1);
@@ -1530,6 +1527,15 @@
   __ lbu(V0, FieldAddress(T2, OneByteString::data_offset()));
   __ Ret();
   __ delay_slot()->SmiTag(V0);
+
+  __ Bind(&try_two_byte_string);
+  __ BranchNotEqual(TMP1, kTwoByteStringCid, &fall_through);
+  ASSERT(kSmiTagShift == 1);
+  __ addu(T2, T0, T1);
+  __ lhu(V0, FieldAddress(T2, OneByteString::data_offset()));
+  __ Ret();
+  __ delay_slot()->SmiTag(V0);
+
   __ Bind(&fall_through);
   return false;
 }
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 15bec3d..5daa399 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -189,7 +189,7 @@
   __ j(ABOVE_EQUAL, &fall_through);
   // Note that RBX is Smi, i.e, times 2.
   ASSERT(kSmiTagShift == 1);
-  // Destroy RCX as we will not continue in the function.
+  // Destroy RCX (ic data) as we will not continue in the function.
   __ StoreIntoObject(RAX,
                      FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()),
                      RDX);
@@ -1426,9 +1426,8 @@
 }
 
 
-// TODO(srdjan): Implement for two and four byte strings as well.
 bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
-  Label fall_through;
+  Label fall_through, try_two_byte_string;
   __ movq(RCX, Address(RSP, + 1 * kWordSize));  // Index.
   __ movq(RAX, Address(RSP, + 2 * kWordSize));  // String.
   __ testq(RCX, Immediate(kSmiTagMask));
@@ -1438,11 +1437,20 @@
   // Runtime throws exception.
   __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
   __ CompareClassId(RAX, kOneByteStringCid);
-  __ j(NOT_EQUAL, &fall_through);
+  __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump);
   __ SmiUntag(RCX);
   __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
   __ SmiTag(RAX);
   __ ret();
+
+  __ Bind(&try_two_byte_string);
+  __ CompareClassId(RAX, kTwoByteStringCid);
+  __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
+  ASSERT(kSmiTagShift == 1);
+  __ movzxw(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
+  __ SmiTag(RAX);
+  __ ret();
+
   __ Bind(&fall_through);
   return false;
 }
diff --git a/runtime/vm/mirrors_api_impl.cc b/runtime/vm/mirrors_api_impl.cc
index 537c9ed..82132be 100644
--- a/runtime/vm/mirrors_api_impl.cc
+++ b/runtime/vm/mirrors_api_impl.cc
@@ -48,24 +48,29 @@
 
 // --- Classes and Interfaces Reflection ---
 
-DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle clazz) {
+DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle object) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (obj.IsType() || obj.IsClass()) {
+    const Class& cls = (obj.IsType()) ?
+        Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
+    return Api::NewHandle(isolate, cls.UserVisibleName());
+  } else {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
-  return Api::NewHandle(isolate, cls.UserVisibleName());
 }
 
 
-DART_EXPORT Dart_Handle Dart_ClassGetLibrary(Dart_Handle clazz) {
+DART_EXPORT Dart_Handle Dart_ClassGetLibrary(Dart_Handle object) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
 
 #if defined(DEBUG)
   const Library& lib = Library::Handle(cls.library());
@@ -81,15 +86,16 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_ClassGetInterfaceCount(Dart_Handle clazz,
+DART_EXPORT Dart_Handle Dart_ClassGetInterfaceCount(Dart_Handle object,
                                                     intptr_t* count) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
-
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
   const Array& interface_types = Array::Handle(isolate, cls.interfaces());
   if (interface_types.IsNull()) {
     *count = 0;
@@ -100,14 +106,16 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_ClassGetInterfaceAt(Dart_Handle clazz,
+DART_EXPORT Dart_Handle Dart_ClassGetInterfaceAt(Dart_Handle object,
                                                  intptr_t index) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
 
   // Finalize all classes.
   Dart_Handle state = Api::CheckIsolateState(isolate);
@@ -131,27 +139,30 @@
 }
 
 
-DART_EXPORT bool Dart_ClassIsTypedef(Dart_Handle clazz) {
+DART_EXPORT bool Dart_ClassIsTypedef(Dart_Handle object) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
   // For now we represent typedefs as non-canonical signature classes.
   // I anticipate this may change if we make typedefs more general.
   return cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass();
 }
 
 
-DART_EXPORT Dart_Handle Dart_ClassGetTypedefReferent(Dart_Handle clazz) {
+DART_EXPORT Dart_Handle Dart_ClassGetTypedefReferent(Dart_Handle object) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
-
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
   if (!cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass()) {
     const String& cls_name = String::Handle(cls.UserVisibleName());
     return Api::NewError("%s: class '%s' is not a typedef class. "
@@ -164,26 +175,30 @@
 }
 
 
-DART_EXPORT bool Dart_ClassIsFunctionType(Dart_Handle clazz) {
+DART_EXPORT bool Dart_ClassIsFunctionType(Dart_Handle object) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
   // A class represents a function type when it is a canonical
   // signature class.
   return cls.IsCanonicalSignatureClass();
 }
 
 
-DART_EXPORT Dart_Handle Dart_ClassGetFunctionTypeSignature(Dart_Handle clazz) {
+DART_EXPORT Dart_Handle Dart_ClassGetFunctionTypeSignature(Dart_Handle object) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
   if (!cls.IsCanonicalSignatureClass()) {
     const String& cls_name = String::Handle(cls.UserVisibleName());
     return Api::NewError("%s: class '%s' is not a function-type class. "
@@ -221,8 +236,12 @@
   Function& func = Function::Handle();
   String& name = String::Handle();
 
-  if (obj.IsClass()) {
-    const Class& cls = Class::Cast(obj);
+  if (obj.IsType() || obj.IsClass()) {
+    // 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 to invoke Dart_Invoke is removed.
+    const Class& cls = (obj.IsType()) ?
+        Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
     const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate));
     if (!error.IsNull()) {
       return Api::NewHandle(isolate, error.raw());
@@ -283,8 +302,12 @@
 
   Function& func = Function::Handle(isolate);
   String& tmp_name = String::Handle(isolate);
-  if (obj.IsClass()) {
-    const Class& cls = Class::Cast(obj);
+  if (obj.IsType() || obj.IsClass()) {
+    // 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 to invoke Dart_Invoke is removed.
+    const Class& cls = (obj.IsType()) ?
+        Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
 
     // Case 1.  Lookup the unmodified function name.
     func = cls.LookupFunctionAllowPrivate(func_name);
@@ -561,8 +584,12 @@
   Field& field = Field::Handle(isolate);
   String& name = String::Handle(isolate);
 
-  if (obj.IsClass()) {
-    const Class& cls = Class::Cast(obj);
+  if (obj.IsType() || obj.IsClass()) {
+    // 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 to invoke Dart_Invoke is removed.
+    const Class& cls = (obj.IsType()) ?
+        Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
     const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate));
     if (!error.IsNull()) {
       return Api::NewHandle(isolate, error.raw());
@@ -614,8 +641,12 @@
   if (var_name.IsNull()) {
     RETURN_TYPE_ERROR(isolate, variable_name, String);
   }
-  if (obj.IsClass()) {
-    const Class& cls = Class::Cast(obj);
+  if (obj.IsType() || obj.IsClass()) {
+    // 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 to invoke Dart_Invoke is removed.
+    const Class& cls = (obj.IsType()) ?
+        Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
     return Api::NewHandle(isolate, cls.LookupField(var_name));
   }
   if (obj.IsLibrary()) {
@@ -684,14 +715,15 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_GetTypeVariableNames(Dart_Handle clazz) {
+DART_EXPORT Dart_Handle Dart_GetTypeVariableNames(Dart_Handle object) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
-
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
   const intptr_t num_type_params = cls.NumTypeParameters();
   const TypeArguments& type_params =
       TypeArguments::Handle(cls.type_parameters());
@@ -710,14 +742,16 @@
 
 
 DART_EXPORT Dart_Handle Dart_LookupTypeVariable(
-    Dart_Handle clazz,
+    Dart_Handle object,
     Dart_Handle type_variable_name) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
-  const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
-  if (cls.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, clazz, Class);
+  const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+  if (!obj.IsType() && !obj.IsClass()) {
+    RETURN_TYPE_ERROR(isolate, object, Class/Type);
   }
+  const Class& cls = (obj.IsType()) ?
+      Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
   const String& var_name = Api::UnwrapStringHandle(isolate, type_variable_name);
   if (var_name.IsNull()) {
     RETURN_TYPE_ERROR(isolate, type_variable_name, String);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 966aa45..b043be0 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4626,7 +4626,7 @@
   const Class& cls = Class::Handle(Owner());
 
   if (IsClosureFunction()) {
-    if (IsLocalFunction()) {
+    if (IsLocalFunction() && !IsImplicitClosureFunction()) {
       const Function& parent = Function::Handle(parent_function());
       tmp = parent.QualifiedUserVisibleName();
     } else {
@@ -13289,7 +13289,7 @@
 const char* Closure::ToCString(const Instance& closure) {
   const Function& fun = Function::Handle(Closure::function(closure));
   const bool is_implicit_closure = fun.IsImplicitClosureFunction();
-  const char* fun_sig = String::Handle(fun.Signature()).ToCString();
+  const char* fun_sig = String::Handle(fun.UserVisibleSignature()).ToCString();
   const char* from = is_implicit_closure ? " from " : "";
   const char* fun_desc = is_implicit_closure ? fun.ToCString() : "";
   const char* format = "Closure: %s%s%s";
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index b307f6a..3dfc08a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1324,6 +1324,17 @@
     return BuildSignature(instantiate, kInternalName, TypeArguments::Handle());
   }
 
+  // Build a string of the form '(T, {b: B, c: C}) => R' representing the
+  // user visible signature of the given function. In this example, T and R are
+  // type parameters of class C, the owner of the function.
+  // Implicit parameters are hidden, as well as the prefix denoting the
+  // signature class and its type parameters.
+  RawString* UserVisibleSignature() const {
+    const bool instantiate = false;
+    return BuildSignature(
+        instantiate, kUserVisibleName, TypeArguments::Handle());
+  }
+
   // Build a string of the form '(A, {b: B, c: C}) => D' representing the
   // signature of the given function, where all generic types (e.g. '<T, R>' in
   // 'C<T, R>(T, {b: B, c: C}) => R') are instantiated using the given
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 8773376..a3c43dd 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -131,50 +131,22 @@
 }
 
 
-LocalVariable* ParsedFunction::GetSavedArgumentsDescriptorVar() const {
-  const int num_parameters = function().NumParameters();
-  LocalScope* scope = node_sequence()->scope();
-  if (scope->num_variables() > num_parameters) {
-    LocalVariable* saved_args_desc_var = scope->VariableAt(num_parameters);
-    ASSERT(saved_args_desc_var != NULL);
-    // The scope of the formal parameters may also contain at this position
-    // an alias for the saved arguments descriptor variable of the enclosing
-    // function (check its scope owner) or an internal variable such as the
-    // expression temp variable or the saved entry context variable (check its
-    // name).
-    if ((saved_args_desc_var->owner() == scope) &&
-        saved_args_desc_var->name().StartsWith(
-            Symbols::SavedArgDescVarPrefix())) {
-      return saved_args_desc_var;
-    }
-  }
-  return NULL;
-}
-
-
 void ParsedFunction::AllocateVariables() {
   LocalScope* scope = node_sequence()->scope();
   const intptr_t num_fixed_params = function().num_fixed_parameters();
   const intptr_t num_opt_params = function().NumOptionalParameters();
-  intptr_t num_params = num_fixed_params + num_opt_params;
+  const intptr_t num_params = num_fixed_params + num_opt_params;
   // Compute start indices to parameters and locals, and the number of
   // parameters to copy.
   if (num_opt_params == 0) {
     // Parameter i will be at fp[kParamEndSlotFromFp + num_params - i] and
     // local variable j will be at fp[kFirstLocalSlotFromFp - j].
-    ASSERT(GetSavedArgumentsDescriptorVar() == NULL);
     first_parameter_index_ = kParamEndSlotFromFp + num_params;
     first_stack_local_index_ = kFirstLocalSlotFromFp;
     num_copied_params_ = 0;
   } else {
     // Parameter i will be at fp[kFirstLocalSlotFromFp - i] and local variable
     // j will be at fp[kFirstLocalSlotFromFp - num_params - j].
-    // The saved arguments descriptor variable must be allocated similarly to
-    // a parameter, so that it gets both a frame slot and a context slot when
-    // captured.
-    if (GetSavedArgumentsDescriptorVar() != NULL) {
-      num_params += 1;
-    }
     first_parameter_index_ = kFirstLocalSlotFromFp;
     first_stack_local_index_ = first_parameter_index_ - num_params;
     num_copied_params_ = num_params;
@@ -6417,13 +6389,6 @@
       node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index);
       tokens_iterator_.SetCurrentPosition(finally_pos);
     }
-    if (!generic_catch_seen) {
-      // No generic catch handler exists so execute this finally block
-      // before rethrowing the exception.
-      finally_block = ParseFinallyBlock();
-      catch_handler_list->Add(finally_block);
-      tokens_iterator_.SetCurrentPosition(finally_pos);
-    }
     finally_block = ParseFinallyBlock();
   } else {
     if (!catch_seen) {
@@ -8074,97 +8039,6 @@
 }
 
 
-// Returns true if ident resolves to a formal parameter of the current function
-// or of one of its enclosing functions.
-// Make sure not to capture the formal parameter, since it is not accessed.
-bool Parser::IsFormalParameter(const String& ident,
-                               Function* owner_function,
-                               LocalScope** owner_scope,
-                               intptr_t* local_index) {
-  if (current_block_ == NULL) {
-    return false;
-  }
-  if (ident.Equals(Symbols::This())) {
-    // 'this' is not a formal parameter that can be tested with '?this'.
-    return false;
-  }
-  // Since an argument definition test does not use the value of the formal
-  // parameter, there is no reason to capture it.
-  const bool kTestOnly = true;  // No capturing.
-  LocalVariable* local =
-      current_block_->scope->LookupVariable(ident, kTestOnly);
-  if ((local == NULL) ||
-      (local->owner()->HasContextLevel() &&
-       (local->owner()->context_level() < 1))) {
-    if ((local == NULL) && !current_function().IsLocalFunction()) {
-      // We are not generating code for a local function, so all locals,
-      // captured or not, are in scope. However, 'ident' was not found, so it
-      // does not exist.
-      return false;
-    }
-    // The formal parameter belongs to an enclosing function and may not have
-    // been captured, so it was not included in the context scope and it cannot
-    // be found by LookupVariable.
-    ASSERT((local == NULL) || local->is_captured());
-    // 'ident' necessarily refers to the formal parameter of one of the
-    // enclosing functions, or a compile error would have prevented the
-    // outermost enclosing function to be executed and we would not be compiling
-    // this local function.
-    // Therefore, look for ident directly in the formal parameter lists of the
-    // enclosing functions.
-    // There is no need to return the owner_scope, since the caller will not
-    // create the saved_arguments_descriptor variable, which already exists.
-    Function& function = Function::Handle(innermost_function().raw());
-    String& param_name = String::Handle();
-    do {
-      const int num_parameters = function.NumParameters();
-      for (intptr_t i = 0; i < num_parameters; i++) {
-        param_name = function.ParameterNameAt(i);
-        if (ident.Equals(param_name)) {
-          *owner_function = function.raw();
-          *owner_scope = NULL;
-          *local_index = i;
-          return true;
-        }
-      }
-      function = function.parent_function();
-    } while (!function.IsNull());
-    UNREACHABLE();
-  }
-  // Verify that local is a formal parameter of the current function or of one
-  // of its enclosing functions.
-  // Note that scopes are not yet associated to functions.
-  Function& function = Function::Handle(innermost_function().raw());
-  LocalScope* scope = current_block_->scope;
-  while (scope != NULL) {
-    ASSERT(!function.IsNull());
-    // Find the top scope for this function level.
-    while ((scope->parent() != NULL) &&
-           (scope->parent()->function_level() == scope->function_level())) {
-      scope = scope->parent();
-    }
-    if (scope == local->owner()) {
-      // Scope contains 'local' and the formal parameters of 'function'.
-      const int num_parameters = function.NumParameters();
-      for (intptr_t i = 0; i < num_parameters; i++) {
-        if (scope->VariableAt(i) == local) {
-          *owner_function = function.raw();
-          *owner_scope = scope;
-          *local_index = i;
-          return true;
-        }
-      }
-      // The variable 'local' is not a formal parameter.
-      return false;
-    }
-    scope = scope->parent();
-    function = function.parent_function();
-  }
-  // The variable 'local' does not belong to a function top scope.
-  return false;
-}
-
-
 void Parser::CheckInstanceFieldAccess(intptr_t field_pos,
                                       const String& field_name) {
   // Fields are not accessible from a static function, except from a
@@ -9649,57 +9523,6 @@
 }
 
 
-AstNode* Parser::ParseArgumentDefinitionTest() {
-  const intptr_t test_pos = TokenPos();
-  ConsumeToken();
-  const intptr_t ident_pos = TokenPos();
-  String* ident = ExpectIdentifier("parameter name expected");
-  Function& owner_function = Function::Handle();
-  LocalScope* owner_scope;
-  intptr_t param_index;
-  if (!IsFormalParameter(*ident, &owner_function, &owner_scope, &param_index)) {
-    ErrorMsg(ident_pos, "formal parameter name expected");
-  }
-  if (param_index < owner_function.num_fixed_parameters()) {
-    // The formal parameter is not optional, therefore the corresponding
-    // argument is always passed and defined.
-    return new LiteralNode(test_pos, Bool::True());
-  }
-  char name[64];
-  OS::SNPrint(name, 64, "%s_%"Pd"",
-              Symbols::Name(Symbols::kSavedArgDescVarPrefixId),
-              owner_function.token_pos());
-  const String& saved_args_desc_name = String::ZoneHandle(Symbols::New(name));
-  LocalVariable* saved_args_desc_var = LookupLocalScope(saved_args_desc_name);
-  if (saved_args_desc_var == NULL) {
-    ASSERT(owner_scope != NULL);
-    saved_args_desc_var =
-        new LocalVariable(owner_function.token_pos(),
-                          saved_args_desc_name,
-                          Type::ZoneHandle(Type::ArrayType()));
-    saved_args_desc_var->set_is_final();
-    // The saved arguments descriptor variable must be added just after the
-    // formal parameters. This simplifies the 2-step saving of a captured
-    // arguments descriptor.
-    // At this time, the owner scope should only contain formal parameters.
-    ASSERT(owner_scope->num_variables() == owner_function.NumParameters());
-    bool success = owner_scope->AddVariable(saved_args_desc_var);
-    ASSERT(success);
-    // Capture the saved arguments descriptor variable if necessary.
-    LocalVariable* local = LookupLocalScope(saved_args_desc_name);
-    ASSERT(local == saved_args_desc_var);
-  }
-  // If we currently generate code for the local function of an enclosing owner
-  // function, the saved arguments descriptor variable must have been captured
-  // by the above lookup.
-  ASSERT((owner_function.raw() == innermost_function().raw()) ||
-         saved_args_desc_var->is_captured());
-  const String& param_name = String::ZoneHandle(Symbols::New(*ident));
-  return new ArgumentDefinitionTestNode(
-      test_pos, param_index, param_name, saved_args_desc_var);
-}
-
-
 AstNode* Parser::ParsePrimary() {
   TRACE_PARSER("ParsePrimary");
   ASSERT(!is_top_level_);
@@ -9830,8 +9653,6 @@
     } else {
       primary = new PrimaryNode(TokenPos(), Symbols::Super());
     }
-  } else if (CurrentToken() == Token::kCONDITIONAL) {
-    primary = ParseArgumentDefinitionTest();
   } else {
     UnexpectedToken();
   }
@@ -10031,12 +9852,6 @@
     case Token::kINDEX:
       SkipCompoundLiteral();
       break;
-    case Token::kCONDITIONAL:
-      ConsumeToken();
-      if (IsIdentifier()) {
-        ConsumeToken();
-      }
-      break;
     default:
       if (IsIdentifier()) {
         ConsumeToken();  // Handle pseudo-keyword identifiers.
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index f80c674..6fe1e2e 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -87,10 +87,6 @@
     saved_entry_context_var_ = saved_entry_context_var;
   }
 
-  // Returns NULL if this function does not save the arguments descriptor on
-  // entry.
-  LocalVariable* GetSavedArgumentsDescriptorVar() const;
-
   LocalVariable* expression_temp_var() const {
     ASSERT(has_expression_temp_var());
     return expression_temp_var_;
@@ -533,7 +529,6 @@
                            bool is_const,
                            const AbstractTypeArguments& type_arguments);
   AstNode* ParseNewOperator(Token::Kind op_kind);
-  AstNode* ParseArgumentDefinitionTest();
 
   // An implicit argument, if non-null, is prepended to the returned list.
   ArgumentListNode* ParseActualParameters(ArgumentListNode* implicit_arguments,
@@ -551,10 +546,6 @@
                                   bool consume_cascades);
 
   LocalVariable* LookupLocalScope(const String& ident);
-  bool IsFormalParameter(const String& ident,
-                         Function* owner_function,
-                         LocalScope** owner_scope,
-                         intptr_t* local_index);
   void CheckInstanceFieldAccess(intptr_t field_pos, const String& field_name);
   bool ParsingStaticMember() const;
   const Type* ReceiverType(intptr_t type_pos) const;
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index 78bf848..3c39714 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -76,7 +76,7 @@
 // When an expression obj.M is evaluated for the first time and receiver obj
 // does not have a getter called M but has a method called M then an extractor
 // is created and injected as a getter (under the name get:M) into the class
-// ownining method M.
+// owning method M.
 static RawFunction* CreateMethodExtractor(const String& getter_name,
                                           const Function& method) {
   const Function& closure_function =
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index c7b0c05..153ca1e 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -282,7 +282,6 @@
         desc.info.index = var->index();
         vars->Add(desc);
       }
-      // The saved arguments descriptor variable is not currently collected.
     }
   }
   LocalScope* child = this->child();
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 1401625..07b8383 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1697,33 +1697,22 @@
             }
             break;
           }
-          case 4: {
+          case 4:
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             // Format(instr, "umull'cond's 'rd, 'rn, 'rm, 'rs");
-            uint64_t left_op  = static_cast<uint32_t>(rm_val);
-            uint64_t right_op = static_cast<uint32_t>(rs_val);
-            uint64_t result = left_op * right_op;
-            int32_t hi_res = Utils::High32Bits(result);
-            int32_t lo_res = Utils::Low32Bits(result);
-            set_register(rd, lo_res);
-            set_register(rn, hi_res);
-            if (instr->HasS()) {
-              if (lo_res != 0) {
-                // Collapse bits 0..31 into bit 32 so that 32-bit Z check works.
-                hi_res |= 1;
-              }
-              ASSERT((result == 0) == (hi_res == 0));  // Z bit
-              ASSERT(((result & (1LL << 63)) != 0) == (hi_res < 0));  // N bit
-              SetNZFlags(hi_res);
-            }
-            break;
-          }
           case 6: {
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             // Format(instr, "smull'cond's 'rd, 'rn, 'rm, 'rs");
-            int64_t left_op  = static_cast<int32_t>(rm_val);
-            int64_t right_op = static_cast<int32_t>(rs_val);
-            int64_t result = left_op * right_op;
+            int64_t result;
+            if (instr->Bits(21, 3) == 4) {  // umull
+              uint64_t left_op  = static_cast<uint32_t>(rm_val);
+              uint64_t right_op = static_cast<uint32_t>(rs_val);
+              result = left_op * right_op;  // Unsigned nultiplication.
+            } else {  // smull
+              int64_t left_op  = static_cast<int32_t>(rm_val);
+              int64_t right_op = static_cast<int32_t>(rs_val);
+              result = left_op * right_op;  // Signed nultiplication.
+            }
             int32_t hi_res = Utils::High32Bits(result);
             int32_t lo_res = Utils::Low32Bits(result);
             set_register(rd, lo_res);
@@ -1739,17 +1728,27 @@
             }
             break;
           }
+          case 5:
+            // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+            // Format(instr, "umlal'cond's 'rd, 'rn, 'rm, 'rs");
           case 7: {
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             // Format(instr, "smlal'cond's 'rd, 'rn, 'rm, 'rs");
             int32_t rd_lo_val = get_register(rd);
             int32_t rd_hi_val = get_register(rn);
-            int64_t left_op  = static_cast<int32_t>(rm_val);
-            int64_t right_op = static_cast<int32_t>(rs_val);
             uint32_t accum_lo = static_cast<uint32_t>(rd_lo_val);
             int32_t accum_hi = static_cast<int32_t>(rd_hi_val);
             int64_t accum = Utils::LowHighTo64Bits(accum_lo, accum_hi);
-            int64_t result = accum + left_op * right_op;
+            int64_t result;
+            if (instr->Bits(21, 3) == 5) {  // umlal
+              uint64_t left_op  = static_cast<uint32_t>(rm_val);
+              uint64_t right_op = static_cast<uint32_t>(rs_val);
+              result = accum + left_op * right_op;  // Unsigned nultiplication.
+            } else {  // smlal
+              int64_t left_op  = static_cast<int32_t>(rm_val);
+              int64_t right_op = static_cast<int32_t>(rs_val);
+              result = accum + left_op * right_op;  // Signed nultiplication.
+            }
             int32_t hi_res = Utils::High32Bits(result);
             int32_t lo_res = Utils::Low32Bits(result);
             set_register(rd, lo_res);
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index a04d8f1..fd858ec 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1394,8 +1394,8 @@
       uint32_t lo = get_lo_register();
       int32_t hi = get_hi_register();
       int64_t accum = Utils::LowHighTo64Bits(lo, hi);
-      int64_t rs = static_cast<int64_t>(get_register(instr->RsField()));
-      int64_t rt = static_cast<int64_t>(get_register(instr->RtField()));
+      int64_t rs = get_register(instr->RsField());
+      int64_t rt = get_register(instr->RtField());
       int64_t res = accum + rs * rt;
       set_hi_register(Utils::High32Bits(res));
       set_lo_register(Utils::Low32Bits(res));
@@ -1408,8 +1408,8 @@
       uint32_t lo = get_lo_register();
       uint32_t hi = get_hi_register();
       uint64_t accum = Utils::LowHighTo64Bits(lo, hi);
-      uint64_t rs = static_cast<uint64_t>(get_register(instr->RsField()));
-      uint64_t rt = static_cast<uint64_t>(get_register(instr->RtField()));
+      uint64_t rs = static_cast<uint32_t>(get_register(instr->RsField()));
+      uint64_t rt = static_cast<uint32_t>(get_register(instr->RtField()));
       uint64_t res = accum + rs * rt;
       set_hi_register(Utils::High32Bits(res));
       set_lo_register(Utils::Low32Bits(res));
@@ -2028,7 +2028,7 @@
   delay_slot_ = true;
   icount_++;
   Instr* instr = Instr::At(pc_ + Instr::kInstrSize);
-  if (icount_ == FLAG_stop_sim_at) {
+  if ((FLAG_stop_sim_at != 0) && (icount_ == FLAG_stop_sim_at)) {
     SimulatorDebugger dbg(this);
     dbg.Stop(instr, "Instruction count reached");
   }
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index d634fe1..185ca37 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -39,7 +39,8 @@
   V(Subtype3TestCache)                                                         \
   V(GetStackPointer)                                                           \
   V(JumpToExceptionHandler)                                                    \
-  V(IdenticalWithNumberCheck)                                                  \
+  V(UnoptimizedIdenticalWithNumberCheck)                                       \
+  V(OptimizedIdenticalWithNumberCheck)                                         \
 
 // Is it permitted for the stubs above to refer to Object::null(), which is
 // allocated in the VM isolate and shared across all isolates.
@@ -197,6 +198,13 @@
   static void GenerateUsageCounterIncrement(Assembler* assembler,
                                             Register temp_reg);
   static void GenerateOptimizedUsageCounterIncrement(Assembler* assembler);
+
+  static void GenerateIdenticalWithNumberCheckStub(
+      Assembler* assembler,
+      const Register left,
+      const Register right,
+      const Register temp1 = kNoRegister,
+      const Register temp2 = kNoRegister);
 };
 
 }  // namespace dart
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 6e26bd9..4b25872 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1281,8 +1281,12 @@
 }
 
 
-// The target function was not found, so invoke method
-// "dynamic noSuchMethod(Invocation invocation)".
+// Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
+// from the entry code of a dart function after an error in passed argument
+// name or number is detected.
+// Input parameters:
+//  LR : return address.
+//  SP : address of last argument.
 //  R5: inline cache data object.
 //  R4: arguments descriptor array.
 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
@@ -1974,24 +1978,14 @@
 // Does identical check (object references are equal or not equal) with special
 // checks for boxed numbers.
 // LR: return address.
-// SP + 4: left operand.
-// SP + 0: right operand.
 // Return Zero condition flag set if equal.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) {
-  const Register temp = R2;
-  const Register left = R1;
-  const Register right = R0;
-  // Preserve left, right and temp.
-  __ PushList((1 << R0) | (1 << R1) | (1 << R2));
-  // TOS + 4: left argument.
-  // TOS + 3: right argument.
-  // TOS + 2: saved temp
-  // TOS + 1: saved left
-  // TOS + 0: saved right
-  __ ldr(left, Address(SP, 4 * kWordSize));
-  __ ldr(right, Address(SP, 3 * kWordSize));
+void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                    const Register left,
+                                                    const Register right,
+                                                    const Register temp,
+                                                    const Register unused) {
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ tst(left, ShifterOperand(kSmiTagMask));
@@ -2046,6 +2040,42 @@
   __ Bind(&reference_compare);
   __ cmp(left, ShifterOperand(right));
   __ Bind(&done);
+}
+
+
+// Called only from unoptimized code. All relevant registers have been saved.
+// LR: return address.
+// SP + 4: left operand.
+// SP + 0: right operand.
+// Return Zero condition flag set if equal.
+void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register temp = R2;
+  const Register left = R1;
+  const Register right = R0;
+  __ ldr(left, Address(SP, 1 * kWordSize));
+  __ ldr(right, Address(SP, 0 * kWordSize));
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
+  __ Ret();
+}
+
+
+// Called from otpimzied code only. Must preserve any registers that are
+// destroyed.
+// LR: return address.
+// SP + 4: left operand.
+// SP + 0: right operand.
+// Return Zero condition flag set if equal.
+void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register temp = R2;
+  const Register left = R1;
+  const Register right = R0;
+  // Preserve left, right and temp.
+  __ PushList((1 << R0) | (1 << R1) | (1 << R2));
+  __ ldr(left, Address(SP, 4 * kWordSize));
+  __ ldr(right, Address(SP, 3 * kWordSize));
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
   __ PopList((1 << R0) | (1 << R1) | (1 << R2));
   __ Ret();
 }
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 3797ffd..30bbf63 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -227,8 +227,9 @@
 
 // Input parameters:
 //   EDX: smi-tagged argument count, may be zero.
+//   EBP[kParamEndSlotFromFp + 1]: last argument.
 // Uses EAX, EBX, ECX, EDX.
-static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) {
+static void PushArgumentsArray(Assembler* assembler) {
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
 
@@ -239,8 +240,10 @@
   // EAX: newly allocated array.
   // EDX: length of the array (was preserved by the stub).
   __ pushl(EAX);  // Array is in EAX and on top of stack.
-  __ leal(EBX, Address(ESP, EDX, TIMES_4, arg_offset));  // Addr of first arg.
+  __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize));
   __ leal(ECX, FieldAddress(EAX, Array::data_offset()));
+  // EBX: address of first argument on stack.
+  // ECX: address of first argument in array.
   Label loop, loop_condition;
   __ jmp(&loop_condition, Assembler::kNearJump);
   __ Bind(&loop);
@@ -280,25 +283,12 @@
 
   // Pass the call's arguments array.
   __ movl(EDX, EDI);  // Smi-tagged arguments array length.
-  PushArgumentsArray(assembler, (7 * kWordSize));
-  // Stack layout explaining "(7 * kWordSize)" offset.
-  // TOS + 0: Arguments array.
-  // TOS + 1: Arguments descriptor array.
-  // TOS + 2: IC data object.
-  // TOS + 3: Receiver.
-  // TOS + 4: Space for the result of the runtime call.
-  // TOS + 5: Stub's PC marker (0)
-  // TOS + 6: Saved FP
-  // TOS + 7: Dart code return address
-  // TOS + 8: Last argument of caller.
-  // ....
+  PushArgumentsArray(assembler);
 
   __ CallRuntime(kInstanceFunctionLookupRuntimeEntry);
+
   // Remove arguments.
-  __ popl(EAX);
-  __ popl(EAX);
-  __ popl(EAX);
-  __ popl(EAX);
+  __ Drop(4);
   __ popl(EAX);  // Get result into EAX.
   __ LeaveFrame();
   __ ret();
@@ -691,22 +681,11 @@
   __ pushl(EDX);  // Arguments descriptor.
   // Load smi-tagged arguments array length, including the non-closure.
   __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  // See stack layout below explaining "wordSize * 5" offset.
-  PushArgumentsArray(assembler, (kWordSize * 5));
+  PushArgumentsArray(assembler);
 
-  // Stack:
-  // TOS + 0: Argument array.
-  // TOS + 1: Arguments descriptor array.
-  // TOS + 2: Place for result from the call.
-  // TOS + 3: PC marker => RawInstruction object.
-  // TOS + 4: Saved EBP of previous frame. <== EBP
-  // TOS + 5: Dart code return address
-  // TOS + 6: Last argument of caller.
-  // ....
   __ CallRuntime(kInvokeNonClosureRuntimeEntry);
   // Remove arguments.
-  __ popl(EAX);
-  __ popl(EAX);
+  __ Drop(2);
   __ popl(EAX);  // Get result into EAX.
 
   // Remove the stub frame as we are about to return.
@@ -1356,58 +1335,37 @@
 }
 
 
-// Called for invoking noSuchMethod function from the entry code of a dart
-// function after an error in passed named arguments is detected.
+// Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
+// from the entry code of a dart function after an error in passed argument
+// name or number is detected.
 // Input parameters:
-//   EBP - 4 : PC marker => RawInstruction object.
-//   EBP : points to previous frame pointer.
-//   EBP + 4 : points to return address.
-//   EBP + 8 : address of last argument (arg n-1).
-//   EBP + 8 + 4*(n-1) : address of first argument (arg 0).
+//   ESP : points to return address.
+//   ESP + 4 : address of last argument.
 //   ECX : ic-data.
 //   EDX : arguments descriptor array.
 // Uses EAX, EBX, EDI as temporary registers.
 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
-  // The target function was not found, so invoke method
-  // "dynamic noSuchMethod(Invocation invocation)".
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  __ movl(EAX, Address(EBP, EDI, TIMES_2, kWordSize));  // Get receiver.
-
-  // Create a stub frame as we are pushing some objects on the stack before
-  // calling into the runtime.
   __ EnterStubFrame();
 
+  // Load the receiver.
+  __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
+  __ movl(EAX, Address(EBP, EDI, TIMES_2, kParamEndSlotFromFp * kWordSize));
+
+  const Immediate& raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   __ pushl(raw_null);  // Setup space on stack for result from noSuchMethod.
   __ pushl(EAX);  // Receiver.
   __ pushl(ECX);  // IC data array.
   __ pushl(EDX);  // Arguments descriptor array.
 
   __ movl(EDX, EDI);
-  // See stack layout below explaining "wordSize * 10" offset.
-  PushArgumentsArray(assembler, (kWordSize * 10));
+  // EDX: Smi-tagged arguments array length.
+  PushArgumentsArray(assembler);
 
-  // Stack:
-  // TOS + 0: Argument array.
-  // TOS + 1: Arguments descriptor array.
-  // TOS + 2: Ic-data.
-  // TOS + 3: Receiver.
-  // TOS + 4: Place for result from noSuchMethod.
-  // TOS + 5: PC marker => RawInstruction object.
-  // TOS + 6: Saved EBP of previous frame. <== EBP
-  // TOS + 7: Dart callee (or stub) code return address
-  // TOS + 8: PC marker => RawInstruction object of dart caller frame.
-  // TOS + 9: Saved EBP of dart caller frame.
-  // TOS + 10: Dart caller code return address
-  // TOS + 11: Last argument of caller.
-  // ....
   __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry);
+
   // Remove arguments.
-  __ popl(EAX);
-  __ popl(EAX);
-  __ popl(EAX);
-  __ popl(EAX);
+  __ Drop(4);
   __ popl(EAX);  // Get result into EAX.
 
   // Remove the stub frame as we are about to return.
@@ -2106,26 +2064,14 @@
 
 // Does identical check (object references are equal or not equal) with special
 // checks for boxed numbers.
-// Left and right are pushed on stack.
 // Return ZF set.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) {
-  const Register left = EAX;
-  const Register right = EDX;
-  const Register temp = ECX;
-  // Preserve left, right and temp.
-  __ pushl(left);
-  __ pushl(right);
-  __ pushl(temp);
-  // TOS + 0: saved temp
-  // TOS + 1: saved right
-  // TOS + 2: saved left
-  // TOS + 3: return address
-  // TOS + 4: right argument.
-  // TOS + 5: left argument.
-  __ movl(left, Address(ESP, 5 * kWordSize));
-  __ movl(right, Address(ESP, 4 * kWordSize));
+void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                    const Register left,
+                                                    const Register right,
+                                                    const Register temp,
+                                                    const Register unused) {
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ testl(left, Immediate(kSmiTagMask));
@@ -2177,6 +2123,44 @@
   __ Bind(&reference_compare);
   __ cmpl(left, right);
   __ Bind(&done);
+}
+
+
+// Called only from unoptimized code. All relevant registers have been saved.
+// TOS + 0: return address
+// TOS + 1: right argument.
+// TOS + 2: left argument.
+// Returns ZF set.
+void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register left = EAX;
+  const Register right = EDX;
+  const Register temp = ECX;
+  __ movl(left, Address(ESP, 2 * kWordSize));
+  __ movl(right, Address(ESP, 1 * kWordSize));
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
+  __ ret();
+}
+
+
+// Called from otpimzied code only. Must preserve any registers that are
+// destroyed.
+// TOS + 0: return address
+// TOS + 1: right argument.
+// TOS + 2: left argument.
+// Returns ZF set.
+void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register left = EAX;
+  const Register right = EDX;
+  const Register temp = ECX;
+  // Preserve left, right and temp.
+  __ pushl(left);
+  __ pushl(right);
+  __ pushl(temp);
+  __ movl(left, Address(ESP, 5 * kWordSize));
+  __ movl(right, Address(ESP, 4 * kWordSize));
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
   __ popl(temp);
   __ popl(right);
   __ popl(left);
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 659a20b..fef92c4 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -1453,8 +1453,12 @@
 }
 
 
-// The target function was not found, so invoke method
-// "dynamic noSuchMethod(Invocation invocation)".
+// Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
+// from the entry code of a dart function after an error in passed argument
+// name or number is detected.
+// Input parameters:
+//  RA : return address.
+//  SP : address of last argument.
 //  S5: inline cache data object.
 //  S4: arguments descriptor array.
 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
@@ -2220,31 +2224,16 @@
 
 // Does identical check (object references are equal or not equal) with special
 // checks for boxed numbers.
-// RA: return address.
-// SP + 4: left operand.
-// SP + 0: right operand.
-// Return: CMPRES is zero if equal, non-zero otherwise.
+// Returns: CMPRES is zero if equal, non-zero otherwise.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) {
+void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                    const Register left,
+                                                    const Register right,
+                                                    const Register temp1,
+                                                    const Register temp2) {
   __ TraceSimMsg("IdenticalWithNumberCheckStub");
   __ Comment("IdenticalWithNumberCheckStub");
-  const Register temp1 = T2;
-  const Register temp2 = T3;
-  const Register left = T1;
-  const Register right = T0;
-  // Preserve left, right.
-  __ addiu(SP, SP, Immediate(-4 * kWordSize));
-  __ sw(temp1, Address(SP, 3 * kWordSize));
-  __ sw(temp2, Address(SP, 2 * kWordSize));
-  __ sw(left, Address(SP, 1 * kWordSize));
-  __ sw(right, Address(SP, 0 * kWordSize));
-  // TOS + 3: left argument.
-  // TOS + 2: right argument.
-  // TOS + 1: saved left
-  // TOS + 0: saved right
-  __ lw(left, Address(SP, 5 * kWordSize));
-  __ lw(right, Address(SP, 4 * kWordSize));
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ andi(temp1, left, Immediate(kSmiTagMask));
@@ -2313,6 +2302,48 @@
   __ Bind(&done);
   // A branch or test after this comparison will check CMPRES == TMP1.
   __ mov(TMP1, ZR);
+}
+
+
+// Called only from unoptimized code. All relevant registers have been saved.
+// RA: return address.
+// SP + 4: left operand.
+// SP + 0: right operand.
+// Returns: CMPRES is zero if equal, non-zero otherwise.
+void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register temp1 = T2;
+  const Register temp2 = T3;
+  const Register left = T1;
+  const Register right = T0;
+  // Preserve left, right.
+  __ lw(left, Address(SP, 1 * kWordSize));
+  __ lw(right, Address(SP, 0 * kWordSize));
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2);
+  __ Ret();
+}
+
+
+// Called from otpimzied code only. Must preserve any registers that are
+// destroyed.
+// SP + 4: left operand.
+// SP + 0: right operand.
+// Returns: CMPRES is zero if equal, non-zero otherwise.
+void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register temp1 = T2;
+  const Register temp2 = T3;
+  const Register left = T1;
+  const Register right = T0;
+  // Preserve left, right.
+  __ addiu(SP, SP, Immediate(-4 * kWordSize));
+  __ sw(temp1, Address(SP, 3 * kWordSize));
+  __ sw(temp2, Address(SP, 2 * kWordSize));
+  __ sw(left, Address(SP, 1 * kWordSize));
+  __ sw(right, Address(SP, 0 * kWordSize));
+  __ lw(left, Address(SP, 5 * kWordSize));
+  __ lw(right, Address(SP, 4 * kWordSize));
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2);
   __ lw(right, Address(SP, 0 * kWordSize));
   __ lw(left, Address(SP, 1 * kWordSize));
   __ lw(temp2, Address(SP, 2 * kWordSize));
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 97e2bbc..c89df162 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -224,7 +224,8 @@
 
 // Input parameters:
 //   R10: smi-tagged argument count, may be zero.
-static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) {
+//   RBP[kParamEndSlotFromFp + 1]: last argument.
+static void PushArgumentsArray(Assembler* assembler) {
   const Immediate& raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
 
@@ -235,8 +236,10 @@
   // RAX: newly allocated array.
   // R10: length of the array (was preserved by the stub).
   __ pushq(RAX);  // Array is in RAX and on top of stack.
-  __ leaq(R12, Address(RSP, R10, TIMES_8, arg_offset));  // Addr of first arg.
+  __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize));
   __ leaq(RBX, FieldAddress(RAX, Array::data_offset()));
+  // R12: address of first argument on stack.
+  // RBX: address of first argument in array.
   Label loop, loop_condition;
   __ jmp(&loop_condition, Assembler::kNearJump);
   __ Bind(&loop);
@@ -275,25 +278,12 @@
 
   // Pass the call's arguments array.
   __ movq(R10, R13);  // Smi-tagged arguments array length.
-  PushArgumentsArray(assembler, (7 * kWordSize));
-  // Stack layout explaining "(7 * kWordSize)" offset.
-  // TOS + 0: Arguments array.
-  // TOS + 1: Arguments descriptor array.
-  // TOS + 2: IC data object.
-  // TOS + 3: Receiver.
-  // TOS + 4: Space for the result of the runtime call.
-  // TOS + 5: Stub's PC marker (0)
-  // TOS + 6: Saved FP
-  // TOS + 7: Dart code return address
-  // TOS + 8: Last argument of caller.
-  // ....
+  PushArgumentsArray(assembler);
 
   __ CallRuntime(kInstanceFunctionLookupRuntimeEntry);
+
   // Remove arguments.
-  __ popq(RAX);
-  __ popq(RAX);
-  __ popq(RAX);
-  __ popq(RAX);
+  __ Drop(4);
   __ popq(RAX);  // Get result into RAX.
   __ LeaveFrame();
   __ ret();
@@ -678,22 +668,12 @@
   __ pushq(R10);  // Arguments descriptor.
   // Load smi-tagged arguments array length, including the non-closure.
   __ movq(R10, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  // See stack layout below explaining "wordSize * 5" offset.
-  PushArgumentsArray(assembler, (kWordSize * 5));
+  PushArgumentsArray(assembler);
 
-  // Stack:
-  // TOS + 0: Argument array.
-  // TOS + 1: Arguments descriptor array.
-  // TOS + 2: Place for result from the call.
-  // TOS + 3: PC marker => RawInstruction object.
-  // TOS + 4: Saved RBP of previous frame. <== RBP
-  // TOS + 5: Dart code return address
-  // TOS + 6: Last argument of caller.
-  // ....
   __ CallRuntime(kInvokeNonClosureRuntimeEntry);
+
   // Remove arguments.
-  __ popq(RAX);
-  __ popq(RAX);
+  __ Drop(2);
   __ popq(RAX);  // Get result into RAX.
 
   // Remove the stub frame as we are about to return.
@@ -1341,56 +1321,35 @@
 }
 
 
-// Called for invoking noSuchMethod function from the entry code of a dart
-// function after an error in passed named arguments is detected.
+// Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
+// from the entry code of a dart function after an error in passed argument
+// name or number is detected.
 // Input parameters:
-//   RBP - 8 : PC marker => RawInstruction object.
-//   RBP : points to previous frame pointer.
-//   RBP + 8 : points to return address.
-//   RBP + 16 : address of last argument (arg n-1).
-//   RBP + 16 + 8*(n-1) : address of first argument (arg 0).
+//   RSP : points to return address.
+//   RSP + 8 : address of last argument.
 //   RBX : ic-data.
 //   R10 : arguments descriptor array.
 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
-  // The target function was not found, so invoke method
-  // "dynamic noSuchMethod(Invocation invocation)".
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  __ movq(RAX, Address(RBP, R13, TIMES_4, kWordSize));  // Get receiver.
-
-  // Create a stub frame.
   __ EnterStubFrame();
 
+  // Load the receiver.
+  __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
+  __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize));
+
+  const Immediate& raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   __ pushq(raw_null);  // Setup space on stack for result from noSuchMethod.
   __ pushq(RAX);  // Receiver.
   __ pushq(RBX);  // IC data array.
   __ pushq(R10);  // Arguments descriptor array.
 
   __ movq(R10, R13);  // Smi-tagged arguments array length.
-  // See stack layout below explaining "wordSize * 10" offset.
-  PushArgumentsArray(assembler, (kWordSize * 10));
+  PushArgumentsArray(assembler);
 
-  // Stack:
-  // TOS + 0: Argument array.
-  // TOS + 1: Arguments descriptor array.
-  // TOS + 2: Ic-data array.
-  // TOS + 3: Receiver.
-  // TOS + 4: Place for result from noSuchMethod.
-  // TOS + 5: PC marker => RawInstruction object.
-  // TOS + 6: Saved RBP of previous frame. <== RBP
-  // TOS + 7: Dart callee (or stub) code return address
-  // TOS + 8: PC marker => RawInstruction object of dart caller frame.
-  // TOS + 9: Saved RBP of dart caller frame.
-  // TOS + 10: Dart caller code return address
-  // TOS + 11: Last argument of caller.
-  // ....
   __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry);
+
   // Remove arguments.
-  __ popq(RAX);
-  __ popq(RAX);
-  __ popq(RAX);
-  __ popq(RAX);
+  __ Drop(4);
   __ popq(RAX);  // Get result into RAX.
 
   // Remove the stub frame as we are about to return.
@@ -2079,19 +2038,11 @@
 // Return ZF set.
 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
 // cannot contain a value that fits in Mint or Smi.
-void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) {
-  const Register left = RAX;
-  const Register right = RDX;
-  // Preserve left, right and temp.
-  __ pushq(left);
-  __ pushq(right);
-  // TOS + 0: saved right
-  // TOS + 1: saved left
-  // TOS + 2: return address
-  // TOS + 3: right argument.
-  // TOS + 4: left argument.
-  __ movq(left, Address(RSP, 4 * kWordSize));
-  __ movq(right, Address(RSP, 3 * kWordSize));
+void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
+                                                    const Register left,
+                                                    const Register right,
+                                                    const Register unused1,
+                                                    const Register unused2) {
   Label reference_compare, done, check_mint, check_bigint;
   // If any of the arguments is Smi do reference compare.
   __ testq(left, Immediate(kSmiTagMask));
@@ -2137,6 +2088,42 @@
   __ Bind(&reference_compare);
   __ cmpq(left, right);
   __ Bind(&done);
+}
+
+
+// Called only from unoptimized code. All relevant registers have been saved.
+// TOS + 0: return address
+// TOS + 1: right argument.
+// TOS + 2: left argument.
+// Returns ZF set.
+void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register left = RAX;
+  const Register right = RDX;
+
+  __ movq(left, Address(RSP, 2 * kWordSize));
+  __ movq(right, Address(RSP, 1 * kWordSize));
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right);
+  __ ret();
+}
+
+
+// Called from otpimzied code only. Must preserve any registers that are
+// destroyed.
+// TOS + 0: return address
+// TOS + 1: right argument.
+// TOS + 2: left argument.
+// Returns ZF set.
+void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
+    Assembler* assembler) {
+  const Register left = RAX;
+  const Register right = RDX;
+  // Preserve left and right.
+  __ pushq(left);
+  __ pushq(right);
+  __ movq(left, Address(RSP, 4 * kWordSize));
+  __ movq(right, Address(RSP, 3 * kWordSize));
+  GenerateIdenticalWithNumberCheckStub(assembler, left, right);
   __ popq(right);
   __ popq(left);
   __ ret();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 0fb42e2..d1def31 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -52,7 +52,6 @@
   V(Interpolate, "_interpolate")                                               \
   V(GetIterator, "iterator")                                                   \
   V(NoSuchMethod, "noSuchMethod")                                              \
-  V(SavedArgDescVarPrefix, ":saved_args_desc_var")                             \
   V(SavedCurrentContextVar, ":saved_current_context_var")                      \
   V(SavedEntryContextVar, ":saved_entry_context_var")                          \
   V(SavedTryContextVar, ":saved_try_context_var")                              \
diff --git a/sdk/lib/_collection_dev/list.dart b/sdk/lib/_collection_dev/list.dart
index 7f894bb..1008dc1 100644
--- a/sdk/lib/_collection_dev/list.dart
+++ b/sdk/lib/_collection_dev/list.dart
@@ -267,6 +267,10 @@
   void clear() {
     throw new UnsupportedError("Cannot modify an unmodifiable map");
   }
+
+  void addAll(Map<int, E> other) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
 }
 
 class ReversedListIterable<E> extends ListIterable<E> {
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index e10326a..47cb937 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -370,6 +370,9 @@
   // Initialized when symbolImplementationClass has been resolved.
   FunctionElement symbolValidatedConstructor;
 
+  // Initialized when dart:mirrors is loaded.
+  ClassElement deferredLibraryClass;
+
   ClassElement jsInvocationMirrorClass;
   /// Document class from dart:mirrors.
   ClassElement documentClass;
@@ -695,14 +698,30 @@
         library.addToScope(dynamicClass, this);
       });
     }
-    if (uri == Uri.parse('dart:mirrors')) {
-      mirrorSystemClass = library.find(const SourceString('MirrorSystem'));
-    } else if (uri == Uri.parse('dart:_collection-dev')) {
-      symbolImplementationClass = library.find(const SourceString('Symbol'));
+    if (uri == new Uri(scheme: 'dart', path: 'dart:mirrors')) {
+      mirrorSystemClass =
+          findRequiredElement(library, const SourceString('MirrorSystem'));
+    } else if (uri == new Uri(scheme: 'dart', path: '_collection-dev')) {
+      symbolImplementationClass =
+          findRequiredElement(library, const SourceString('Symbol'));
+    } else if (uri == new Uri(scheme: 'dart', path: 'async')) {
+      deferredLibraryClass =
+          findRequiredElement(library, const SourceString('DeferredLibrary'));
     }
     backend.onLibraryScanned(library, uri);
   }
 
+  Element findRequiredElement(LibraryElement library, SourceString name) {
+    var element = library.find(name);
+    if (element == null) {
+      internalErrorOnElement(
+          library,
+          'The library "${library.canonicalUri}" does not contain required '
+          'element: ${name.slowToString()}');
+      }
+    return element;
+  }
+
   void onClassResolved(ClassElement cls) {
     if (mirrorSystemClass == cls) {
       mirrorSystemGetNameFunction =
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index fd9ed63..873b926 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -94,10 +94,6 @@
    */
   bool forEachMalformedType(bool f(MalformedType type)) => true;
 
-  // TODO(ahe): This is implicitly inherited from Object.  What is the purpose
-  // of duplicating it here?
-  bool operator ==(other);
-
   /**
    * Is [: true :] if this type has no explict type arguments.
    */
@@ -346,10 +342,6 @@
     return visitor.visitMalformedType(this, argument);
   }
 
-  // TODO(ahe): This is the default implementation that would be inherited if
-  // DartType didn't declare an abstract method.  What is the purpose?
-  bool operator ==(other) => identical(this, other);
-
   String toString() {
     var sb = new StringBuffer();
     if (typeArguments != null) {
@@ -456,7 +448,8 @@
 
   bool operator ==(other) {
     if (other is !GenericType) return false;
-    return identical(element, other.element)
+    return kind == other.kind
+        && element == other.element
         && typeArguments == other.typeArguments;
   }
 
@@ -465,7 +458,6 @@
   GenericType asRaw() => element.rawType;
 }
 
-// TODO(johnniwinther): Add common supertype for InterfaceType and TypedefType.
 class InterfaceType extends GenericType {
   final ClassElement element;
 
@@ -553,17 +545,6 @@
     return null;
   }
 
-  bool operator ==(other) {
-    // TODO(johnniwinther,karlklose): This is a bad implementation of
-    // operator==.  This implementation is not compatible with the
-    // implementation in the superclass: another subclass of GenericType might
-    // compare equal to an instance of this class if the other subclass forgets
-    // to implement operator==.  This is brittle and easy to avoid, ask ahe@
-    // for concrete suggestions.
-    if (other is !InterfaceType) return false;
-    return super == other;
-  }
-
   int get hashCode => super.hashCode;
 
   InterfaceType asRaw() => super.asRaw();
@@ -826,12 +807,6 @@
     return definition.subst(typeArguments, declaration.typeArguments);
   }
 
-  bool operator ==(other) {
-    // TODO(johnniwinther,karlklose): See InterfaceType.operator==.
-    if (other is !TypedefType) return false;
-    return super == other;
-  }
-
   int get hashCode => super.hashCode;
 
   TypedefType asRaw() => super.asRaw();
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index 1a8d770..38a6245 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -54,26 +54,7 @@
   String get name => 'Deferred Loading';
 
   /// DeferredLibrary from dart:async
-  ClassElement get deferredLibraryClass {
-    if (cachedDeferredLibraryClass == null) {
-      cachedDeferredLibraryClass = findDeferredLibraryClass();
-    }
-    return cachedDeferredLibraryClass;
-  }
-
-  ClassElement findDeferredLibraryClass() {
-    var uri = new Uri(scheme: 'dart', path: 'async');
-    LibraryElement asyncLibrary =
-        compiler.libraryLoader.loadLibrary(uri, null, uri);
-    var element = asyncLibrary.find(const SourceString('DeferredLibrary'));
-    if (element == null) {
-      compiler.internalErrorOnElement(
-          asyncLibrary,
-          'dart:async library does not contain required class: '
-          'DeferredLibrary');
-    }
-    return element;
-  }
+  ClassElement get deferredLibraryClass => compiler.deferredLibraryClass;
 
   bool isDeferred(Element element) {
     element = element.implementation;
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 0d78456..79ac960 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -176,8 +176,13 @@
   Token position() => null;
 
   Token findMyName(Token token) {
-    for (Token t = token; !identical(t.kind, EOF_TOKEN); t = t.next) {
-      if (t.value == name) return t;
+    // We search for the token that has the name of this element.
+    // For constructors, that doesn't work because they may have
+    // named formed out of multiple tokens (named constructors) so
+    // for those we search for the class name instead.
+    SourceString needle = isConstructor() ? enclosingElement.name : name;
+    for (Token t = token; EOF_TOKEN != t.kind; t = t.next) {
+      if (needle == t.value) return t;
     }
     return token;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 46abf0a..c8fd503 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -1403,6 +1403,13 @@
   bool retainName(SourceString name) => mustPreserveNames;
 
   bool retainMetadataOf(Element element) {
+    if (mustRetainMetadata) {
+      // TODO(ahe): This is a little hacky, but I'll have to rewrite this when
+      // implementing @MirrorsUsed anyways.
+      compiler.constantHandler.compiledConstants.addAll(
+          compiler.metadataHandler.compiledConstants);
+      compiler.metadataHandler.compiledConstants.clear();
+    }
     if (mustRetainMetadata) hasRetainedMetadata = true;
     return mustRetainMetadata;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index e502f25..e8abbb2 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -85,6 +85,13 @@
   final Set<String> recordedMangledNames = new Set<String>();
   final Set<String> interceptorInvocationNames = new Set<String>();
 
+  /// A list of JS expressions that represent metadata, parameter names and
+  /// type, and return types.
+  final List<String> globalMetadata = [];
+
+  /// A map used to canonicalize the entries of globalMetadata.
+  final Map<String, int> globalMetadataMap = <String, int>{};
+
   // TODO(ngeoffray): remove this field.
   Set<ClassElement> instantiatedClasses;
 
@@ -1207,11 +1214,8 @@
       if (backend.isInterceptedMethod(member)) {
         interceptorInvocationNames.add(name);
       }
+      code = extendWithMetadata(member, code);
       builder.addProperty(name, code);
-      var metadata = buildMetadataFunction(member);
-      if (metadata != null) {
-        builder.addProperty('@$name', metadata);
-      }
       String reflectionName = getReflectionName(member, name);
       if (reflectionName != null) {
         builder.addProperty('+$reflectionName', js('0'));
@@ -2056,12 +2060,8 @@
       CodeBuffer buffer = bufferForElement(element, eagerBuffer);
       jsAst.Expression code = backend.generatedCode[element];
       String name = namer.getName(element);
+      code = extendWithMetadata(element, code);
       emitStaticFunction(buffer, name, code);
-      var metadata = buildMetadataFunction(element);
-      if (metadata != null) {
-        buffer.write(',$n$n"@$name":$_');
-        buffer.write(jsAst.prettyPrint(metadata, compiler));
-      }
       String reflectionName = getReflectionName(element, name);
       if (reflectionName != null) {
         buffer.write(',$n$n"+$reflectionName":${_}0');
@@ -2883,16 +2883,6 @@
           js.if_(js('receiver instanceof #',
                     js(namer.isolateAccess(compiler.objectClass))),
                  js.return_(js('receiver'))));
-
-      // TODO(sra): Fold this 'Object' check into the `getNativeInterceptor`
-      // check by patching `Object.prototype` with a special hook function.
-      // TODO(9556): This test is needed in plain non-browser code because
-      // 'holders' are not Dart classes.
-      block.statements.add(
-          js.if_(
-              js('Object.getPrototypeOf(receiver) === Object.prototype'),
-              buildReturnInterceptor(backend.jsInterceptorClass)));
-
       block.statements.add(
           js.return_(
               js(namer.isolateAccess(backend.getNativeInterceptorMethod))(
@@ -3272,6 +3262,76 @@
     });
   }
 
+  int reifyMetadata(MetadataAnnotation annotation) {
+    Constant value = annotation.value;
+    if (value == null) {
+      compiler.reportInternalError(
+          annotation, 'Internal error: value is null');
+      return -1;
+    }
+    return addGlobalMetadata(
+        jsAst.prettyPrint(constantReference(value), compiler).getText());
+  }
+
+  int reifyType(DartType type) {
+    // TODO(ahe): Handle type variables correctly instead of using "#".
+    String representation = backend.rti.getTypeRepresentation(type, (_) {});
+    return addGlobalMetadata(representation.replaceAll('#', 'null'));
+  }
+
+  int reifyName(SourceString name) {
+    return addGlobalMetadata('"${name.slowToString()}"');
+  }
+
+  int addGlobalMetadata(String string) {
+    return globalMetadataMap.putIfAbsent(string, () {
+      globalMetadata.add(string);
+      return globalMetadata.length - 1;
+    });
+  }
+
+  jsAst.Fun extendWithMetadata(FunctionElement element, jsAst.Fun code) {
+    if (!backend.retainMetadataOf(element)) return code;
+    return compiler.withCurrentElement(element, () {
+      List<int> metadata = <int>[];
+      FunctionSignature signature = element.functionSignature;
+      if (element.isConstructor()) {
+        metadata.add(reifyType(element.getEnclosingClass().thisType));
+      } else {
+        metadata.add(reifyType(signature.returnType));
+      }
+      signature.forEachParameter((Element parameter) {
+        metadata
+            ..add(reifyName(parameter.name))
+            ..add(reifyType(parameter.computeType(compiler)));
+      });
+      Link link = element.metadata;
+      // TODO(ahe): Why is metadata sometimes null?
+      if (link != null) {
+        for (; !link.isEmpty; link = link.tail) {
+          metadata.add(reifyMetadata(link.head));
+        }
+      }
+      code.body.statements.add(js.string(metadata.join(',')).toStatement());
+      return code;
+    });
+  }
+
+  void emitMetadata(CodeBuffer buffer) {
+    buffer.write('init.metadata$_=$_[');
+    for (var metadata in globalMetadata) {
+      if (metadata is String) {
+        if (metadata != 'null') {
+          buffer.write(metadata);
+        }
+      } else {
+        throw 'Unexpected value in metadata: ${Error.safeToString(metadata)}';
+      }
+      buffer.write(',$n');
+    }
+    buffer.write('];$n');
+  }
+
   String assembleProgram() {
     measure(() {
       // Compute the required type checks to know which classes need a
@@ -3430,6 +3490,7 @@
 
       mainBuffer.add(nativeBuffer);
 
+      emitMetadata(mainBuffer);
 
       isolateProperties = isolatePropertiesName;
       // The following code should not use the short-hand for the
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 3adbd63..0ae4696 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -663,6 +663,11 @@
     builder.write('null');
   }
 
+  visitVoidType(VoidType type, _) {
+    // TODO(ahe): Reify void type ("null" means "dynamic").
+    builder.write('null');
+  }
+
   visitType(DartType type, _) {
     compiler.internalError('Unexpected type: $type (${type.kind})');
   }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/partial_parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/partial_parser.dart
index 02f409a..3b666ae 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/partial_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/partial_parser.dart
@@ -34,7 +34,9 @@
           (identical(value, ',')) ||
           (identical(value, ']')))
         return token;
-      if (identical(value, '=')) {
+      if (identical(value, '=') ||
+          identical(value, '?') ||
+          identical(value, ':')) {
         var nextValue = token.next.stringValue;
         if (identical(nextValue, 'const')) {
           token = token.next;
@@ -45,6 +47,7 @@
           // class Foo {
           //   var map;
           //   Foo() : map = {};
+          //   Foo.x() : map = true ? {} : {};
           // }
           BeginGroupToken begin = token.next;
           token = (begin.endGroup != null) ? begin.endGroup : token;
@@ -56,6 +59,7 @@
           // class Foo {
           //   var map;
           //   Foo() : map = <String, Foo>{};
+          //   Foo.x() : map = true ? <String, Foo>{} : <String, Foo>{};
           // }
           BeginGroupToken begin = token.next;
           token = (begin.endGroup != null) ? begin.endGroup : token;
diff --git a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
index b990532..4cbd641 100644
--- a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
@@ -94,7 +94,7 @@
     // This is used to suppress info about a warning when warnings are
     // suppressed, and similar for hints.
     var previousKind = lastKind;
-    if (previousKind != api.Diagnostic.INFO) {
+    if (kind != api.Diagnostic.INFO) {
       lastKind = kind;
     }
     var color;
diff --git a/sdk/lib/_internal/lib/constant_map.dart b/sdk/lib/_internal/lib/constant_map.dart
index 1647f32..60300fc 100644
--- a/sdk/lib/_internal/lib/constant_map.dart
+++ b/sdk/lib/_internal/lib/constant_map.dart
@@ -51,6 +51,7 @@
   V putIfAbsent(String key, V ifAbsent()) => _throwUnmodifiable();
   V remove(String key) => _throwUnmodifiable();
   void clear() => _throwUnmodifiable();
+  void addAll(Map<String, V> other) => _throwUnmodifiable();
 }
 
 // This class has no constructor. This is on purpose since the instantiation
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index d904246..1d1c825 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -16,7 +16,9 @@
     Null,
     Primitives,
     RuntimeError,
-    createUnmangledInvocationMirror;
+    createRuntimeType,
+    createUnmangledInvocationMirror,
+    runtimeTypeToString;
 import 'dart:_interceptors' show Interceptor, JSExtendableArray;
 import 'dart:_js_names';
 
@@ -77,6 +79,9 @@
     }
     return result;
   }
+
+  // TODO(ahe): Implement this.
+  IsolateMirror get isolate => throw new UnimplementedError();
 }
 
 abstract class JsMirror {
@@ -85,6 +90,9 @@
   abstract String get _prettyName;
 
   String toString() => _prettyName;
+
+  // TODO(ahe): Remove this method from the API.
+  MirrorSystem get mirrors => currentJsMirrorSystem;
 }
 
 abstract class JsDeclarationMirror extends JsMirror
@@ -93,11 +101,16 @@
 
   const JsDeclarationMirror(this.simpleName);
 
+  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
+
   bool get isPrivate => n(simpleName).startsWith('_');
 
   bool get isTopLevel => owner != null && owner is LibraryMirror;
 
   String toString() => "$_prettyName on '${n(simpleName)}'";
+
+  // TODO(ahe): Implement this.
+  SourceLocation get location => throw new UnimplementedError();
 }
 
 class JsTypeMirror extends JsDeclarationMirror implements TypeMirror {
@@ -105,6 +118,14 @@
       : super(simpleName);
 
   String get _prettyName => 'TypeMirror';
+
+  DeclarationMirror get owner => null;
+
+  // TODO(ahe): Doesn't match the specification, see http://dartbug.com/11569.
+  bool get isTopLevel => true;
+
+  // TODO(ahe): Implement this.
+  List<InstanceMirror> get metadata => throw new UnimplementedError();
 }
 
 class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
@@ -152,26 +173,20 @@
     var result = new List<JsMethodMirror>(_functions.length);
     for (int i = 0; i < _functions.length; i++) {
       String name = _functions[i];
+      // TODO(ahe): Create accessor for accessing $.  It is also
+      // used in js_helper.
+      var jsFunction = JS('', '#[#]', JS_CURRENT_ISOLATE(), name);
       String unmangledName = mangledGlobalNames[name];
       if (unmangledName == null) unmangledName = name;
-      int parameterCount = null; // TODO(ahe): Compute this.
-      bool isSetter = false; // TODO(ahe): Compute this.
-      bool isGetter = false; // TODO(ahe): Compute this.
       bool isConstructor = unmangledName.startsWith('new ');
-      bool isStatic = true && !isConstructor; // Top-level functions are
-                                              // static, but constructors are
-                                              // not.
+      bool isStatic = !isConstructor; // Top-level functions are static, but
+                                      // constructors are not.
       if (isConstructor) {
         unmangledName = unmangledName.substring(4).replaceAll(r'$', '.');
       }
-      unmangledName = unmangledName.split(':')[0];
-      Symbol symbol = s(unmangledName);
       JsMethodMirror mirror =
-          // TODO(ahe): Create accessor for accessing $.  It is also
-          // used in js_helper.
-          new JsMethodMirror(
-              symbol, JS('', '#[#]', JS_CURRENT_ISOLATE(), name),
-              parameterCount, isGetter, isSetter, isStatic, isConstructor);
+          new JsMethodMirror.fromUnmangledName(
+              unmangledName, jsFunction, isStatic, isConstructor);
       result[i] = mirror;
       mirror._owner = this;
     }
@@ -220,6 +235,14 @@
     preserveMetadata();
     return _metadata.map(reflect).toList();
   }
+
+  // TODO(ahe): Implement these.
+  DeclarationMirror get owner => throw new UnimplementedError();
+  InstanceMirror invoke(Symbol memberName,
+                        List positionalArguments,
+                        [Map<Symbol,dynamic> namedArguments]) {
+    throw new UnimplementedError();
+  }
 }
 
 String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
@@ -298,6 +321,13 @@
   Future<InstanceMirror> getFieldAsync(Symbol fieldName) {
     return new Future<InstanceMirror>(() => this.getField(fieldName));
   }
+
+  Future<InstanceMirror> invokeAsync(Symbol memberName,
+                                     List positionalArguments,
+                                     [Map<Symbol, dynamic> namedArguments]) {
+    return new Future<InstanceMirror>(
+        () => this.invoke(memberName, positionalArguments, namedArguments));
+  }
 }
 
 class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
@@ -365,6 +395,9 @@
   }
 
   String toString() => 'InstanceMirror on ${Error.safeToString(reflectee)}';
+
+  // TODO(ahe): Remove this method from the API.
+  MirrorSystem get mirrors => currentJsMirrorSystem;
 }
 
 class JsClassMirror extends JsTypeMirror with JsObjectMirror
@@ -387,8 +420,6 @@
 
   String get _prettyName => 'ClassMirror';
 
-  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
-
   get _jsConstructor {
     if (_jsConstructorOrInterceptor is Interceptor) {
       return JS('', '#.constructor', _jsConstructorOrInterceptor);
@@ -400,8 +431,7 @@
   Map<Symbol, MethodMirror> get constructors {
     Map<Symbol, MethodMirror> result = new Map<Symbol, MethodMirror>();
     JsLibraryMirror library = owner;
-    String unmangledName = mangledGlobalNames[n(simpleName)];
-    if (unmangledName == null) unmangledName = n(simpleName);
+    String unmangledName = n(simpleName);
     for (JsMethodMirror mirror in library._functionMirrors) {
       Symbol name = mirror.simpleName;
       if (mirror.isConstructor
@@ -428,7 +458,9 @@
       // reflection with metadata.
       if (simpleName == null) continue;
       var function = JS('', '#[#]', prototype, key);
-      var mirror = new JsMethodMirror.fromUnmangledName(simpleName, function);
+      var mirror =
+          new JsMethodMirror.fromUnmangledName(
+              simpleName, function, false, false);
       result.add(mirror);
       mirror._owner = this;
     }
@@ -591,6 +623,21 @@
     }
     return _superclass == this ? null : _superclass;
   }
+
+  // TODO(ahe): Implement these;
+  InstanceMirror invoke(Symbol memberName,
+                        List positionalArguments,
+                        [Map<Symbol,dynamic> namedArguments]) {
+    throw new UnimplementedError();
+  }
+  List<ClassMirror> get superinterfaces => throw new UnimplementedError();
+  Map<Symbol, TypeVariableMirror> get typeVariables
+      => throw new UnimplementedError();
+  Map<Symbol, TypeMirror> get typeArguments => throw new UnimplementedError();
+  bool get isOriginalDeclaration => throw new UnimplementedError();
+  ClassMirror get originalDeclaration => throw new UnimplementedError();
+  bool get isClass => throw new UnimplementedError();
+  ClassMirror get defaultFactory => throw new UnimplementedError();
 }
 
 class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
@@ -636,8 +683,6 @@
 
   DeclarationMirror get owner => _owner;
 
-  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
-
   List<InstanceMirror> get metadata {
     preserveMetadata();
     if (_metadata == null) {
@@ -703,6 +748,11 @@
   }
 
   String toString() => "ClosureMirror on '${Error.safeToString(reflectee)}'";
+
+  // TODO(ahe): Implement these.
+  String get source => throw new UnimplementedError();
+  Future<InstanceMirror> findInContext(Symbol name)
+      => throw new UnimplementedError();
 }
 
 class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
@@ -714,6 +764,8 @@
   final bool isConstructor;
   DeclarationMirror _owner;
   List _metadata;
+  var _returnType;
+  var _parameters;
 
   JsMethodMirror(Symbol simpleName,
                  this._jsFunction,
@@ -724,7 +776,10 @@
                  this.isConstructor)
       : super(simpleName);
 
-  factory JsMethodMirror.fromUnmangledName(String name, jsFunction) {
+  factory JsMethodMirror.fromUnmangledName(String name,
+                                           jsFunction,
+                                           bool isStatic,
+                                           bool isConstructor) {
     List<String> info = name.split(':');
     name = info[0];
     bool isSetter = name.endsWith('=');
@@ -744,29 +799,96 @@
     }
     return new JsMethodMirror(
         s(name), jsFunction, requiredParameterCount + optionalParameterCount,
-        isGetter, isSetter, false, false);
+        isGetter, isSetter, isStatic, isConstructor);
   }
 
   String get _prettyName => 'MethodMirror';
 
   List<ParameterMirror> get parameters {
-    // TODO(ahe): Fill the list with parameter mirrors.
-    return new List<ParameterMirror>(_parameterCount);
+    metadata; // Compute _parameters as a side-effect of extracting metadata.
+    return new List<ParameterMirror>.from(_parameters);
   }
 
   DeclarationMirror get owner => _owner;
 
-  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
-
-  // TODO(ahe): Improve this information and test it.
-  TypeMirror get returnType => JsMirrorSystem._dynamicType;
+  TypeMirror get returnType {
+    metadata; // Compute _returnType as a side-effect of extracting metadata.
+    return typeMirrorFromRuntimeTypeRepresentation(_returnType);
+  }
 
   List<InstanceMirror> get metadata {
     if (_metadata == null) {
-      _metadata = extractMetadata(_jsFunction);
+      var raw = extractMetadata(_jsFunction);
+      _returnType = raw[0];
+      int parameterLength = 1 + _parameterCount * 2;
+      var formals = new List<ParameterMirror>(_parameterCount);
+      int formalsCount = 0;
+      for (int i = 1; i < parameterLength; i += 2) {
+        var name = raw[i];
+        var type = raw[i + 1];
+        formals[formalsCount++] = new JsParameterMirror(name, this, type);
+      }
+      _parameters = formals;
+      _metadata = raw.sublist(parameterLength);
     }
     return _metadata.map(reflect).toList();
   }
+
+  Symbol get constructorName {
+    // TODO(ahe): I believe it is more appropriate to throw an exception or
+    // return null.
+    if (!isConstructor) return const Symbol('');
+    String name = n(simpleName);
+    int index = name.indexOf('.');
+    if (index == -1) return const Symbol('');
+    return s(name.substring(index + 1));
+  }
+
+  // TODO(ahe): Implement these.
+  bool get isAbstract => throw new UnimplementedError();
+  bool get isRegularMethod => throw new UnimplementedError();
+  bool get isOperator => throw new UnimplementedError();
+  bool get isConstConstructor => throw new UnimplementedError();
+  bool get isGenerativeConstructor => throw new UnimplementedError();
+  bool get isRedirectingConstructor => throw new UnimplementedError();
+  bool get isFactoryConstructor => throw new UnimplementedError();
+}
+
+class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror {
+  final JsMethodMirror owner;
+  // A JS object representing the type.
+  final _type;
+
+  JsParameterMirror(String unmangledName, this.owner, this._type)
+      : super(s(unmangledName));
+
+  String get _prettyName => 'ParameterMirror';
+
+  TypeMirror get type => typeMirrorFromRuntimeTypeRepresentation(_type);
+
+  bool get isStatic => owner.isStatic;
+
+  // TODO(ahe): Implement this.
+  bool get isFinal => false;
+
+  // TODO(ahe): Implement this.
+  bool get isOptional => false;
+
+  // TODO(ahe): Implement this.
+  bool get isNamed => false;
+
+  // TODO(ahe): Implement this.
+  bool get hasDefaultValue => false;
+
+  // TODO(ahe): Implement this.
+  get defaultValue => null;
+}
+
+TypeMirror typeMirrorFromRuntimeTypeRepresentation(type) {
+  if (type == null) return JsMirrorSystem._dynamicType;
+  String representation = runtimeTypeToString(type);
+  if (representation == null) return reflectClass(Function);
+  return reflectClass(createRuntimeType(representation));
 }
 
 Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
@@ -779,6 +901,12 @@
 List extractMetadata(victim) {
   preserveMetadata();
   var metadataFunction = JS('', '#["@"]', victim);
-  return (metadataFunction == null)
-      ? const [] : JS('', '#()', metadataFunction);
+  if (metadataFunction != null) return JS('', '#()', metadataFunction);
+  String source = JS('String', 'Function.prototype.toString.call(#)', victim);
+  int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}'));
+  if (index == -1) return const [];
+  index++;
+  int endQuote = source.indexOf('"', index);
+  return source.substring(index, endQuote).split(',').map(int.parse).map(
+      (int i) => JS('', 'init.metadata[#]', i)).toList();
 }
diff --git a/sdk/lib/_internal/lib/js_rti.dart b/sdk/lib/_internal/lib/js_rti.dart
index 01d8ace..4441214 100644
--- a/sdk/lib/_internal/lib/js_rti.dart
+++ b/sdk/lib/_internal/lib/js_rti.dart
@@ -132,9 +132,11 @@
   } else if (isJsArray(type)) {
     // A list representing a type with arguments.
     return getRuntimeTypeAsString(type);
-  } else {
+  } else if (isJsFunction(type)) {
     // A reference to the constructor.
     return getConstructorName(type);
+  } else {
+    return null;
   }
 }
 
diff --git a/sdk/lib/_internal/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
index 8ad597e..56c098f 100644
--- a/sdk/lib/_internal/lib/native_helper.dart
+++ b/sdk/lib/_internal/lib/native_helper.dart
@@ -17,15 +17,6 @@
 
 String typeNameInWebKitCommon(tag) {
   String name = JS('String', '#', tag);
-  if (name == 'CanvasPixelArray') return 'Uint8ClampedArray';
-  if (name == 'AudioChannelMerger') return 'ChannelMergerNode';
-  if (name == 'AudioChannelSplitter') return 'ChannelSplitterNode';
-  if (name == 'AudioGainNode') return 'GainNode';
-  if (name == 'AudioPannerNode') return 'PannerNode';
-  if (name == 'JavaScriptAudioNode') return 'ScriptProcessorNode';
-  if (name == 'Oscillator') return 'OscillatorNode';
-  if (name == 'RealtimeAnalyserNode') return 'AnalyserNode';
-  if (name == 'IDBVersionChangeRequest') return 'IDBOpenDBRequest';
   return name;
 }
 
@@ -37,9 +28,7 @@
 String typeNameInFirefox(obj) {
   String name = JS('String', '#', constructorNameFallback(obj));
   if (name == 'BeforeUnloadEvent') return 'Event';
-  if (name == 'CSS2Properties') return 'CSSStyleDeclaration';
   if (name == 'DataTransfer') return 'Clipboard';
-  if (name == 'DragEvent') return 'MouseEvent';
   if (name == 'GeoGeolocation') return 'Geolocation';
   if (name == 'WorkerMessageEvent') return 'MessageEvent';
   if (name == 'XMLDocument') return 'Document';
@@ -55,15 +44,10 @@
     return 'HTMLDocument';
   }
   if (name == 'BeforeUnloadEvent') return 'Event';
-  if (name == 'CanvasPixelArray') return 'Uint8ClampedArray';
   if (name == 'DataTransfer') return 'Clipboard';
-  if (name == 'DragEvent') return 'MouseEvent';
   if (name == 'HTMLDDElement') return 'HTMLElement';
   if (name == 'HTMLDTElement') return 'HTMLElement';
-  if (name == 'HTMLTableDataCellElement') return 'HTMLTableCellElement';
-  if (name == 'HTMLTableHeaderCellElement') return 'HTMLTableCellElement';
   if (name == 'HTMLPhraseElement') return 'HTMLElement';
-  if (name == 'MSStyleCSSProperties') return 'CSSStyleDeclaration';
   if (name == 'Position') return 'Geoposition';
 
   // Patches for types which report themselves as Objects.
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 51e5037..6c6a3a0 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -83,12 +83,6 @@
       documented: false,
       platforms: VM_PLATFORM),
 
-  "mdv_observe_impl": const LibraryInfo(
-      "mdv_observe_impl/mdv_observe_impl.dart",
-      category: "Client",
-      documented: false,
-      implementation: true),
-
   "typed_data": const LibraryInfo(
       "typed_data/typed_data.dart",
       dart2jsPath: "typed_data/dart2js/typed_data_dart2js.dart"),
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index 73bf471..6b5f63d 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -2,20 +2,22 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+library pub.command;
+
 import 'dart:io';
 import 'dart:async';
 
 import 'package:args/args.dart';
 import 'package:pathos/path.dart' as path;
 
-import 'command_cache.dart';
-import 'command_deploy.dart';
-import 'command_help.dart';
-import 'command_install.dart';
-import 'command_lish.dart';
-import 'command_update.dart';
-import 'command_uploader.dart';
-import 'command_version.dart';
+import 'command/cache.dart';
+import 'command/deploy.dart';
+import 'command/help.dart';
+import 'command/install.dart';
+import 'command/lish.dart';
+import 'command/update.dart';
+import 'command/uploader.dart';
+import 'command/version.dart';
 import 'entrypoint.dart';
 import 'exit_codes.dart' as exit_codes;
 import 'http.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/command_cache.dart b/sdk/lib/_internal/pub/lib/src/command/cache.dart
similarity index 91%
rename from sdk/lib/_internal/pub/lib/src/command_cache.dart
rename to sdk/lib/_internal/pub/lib/src/command/cache.dart
index 9beb611..b33a045 100644
--- a/sdk/lib/_internal/pub/lib/src/command_cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/cache.dart
@@ -2,15 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library command_cache;
+library pub.command.cache;
 
 import 'dart:async';
 import 'dart:io';
 import 'dart:json' as json;
 
-import 'command.dart';
-import 'exit_codes.dart' as exit_codes;
-import 'log.dart' as log;
+import '../command.dart';
+import '../exit_codes.dart' as exit_codes;
+import '../log.dart' as log;
 
 /// Handles the `cache` pub command.
 class CacheCommand extends PubCommand {
diff --git a/sdk/lib/_internal/pub/lib/src/command_deploy.dart b/sdk/lib/_internal/pub/lib/src/command/deploy.dart
similarity index 96%
rename from sdk/lib/_internal/pub/lib/src/command_deploy.dart
rename to sdk/lib/_internal/pub/lib/src/command/deploy.dart
index 7261b12..76904a8 100644
--- a/sdk/lib/_internal/pub/lib/src/command_deploy.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/deploy.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library command_deploy;
+library pub.command.deploy;
 
 import 'dart:async';
 import 'dart:math' as math;
@@ -10,11 +10,11 @@
 import 'package:analyzer_experimental/analyzer.dart';
 import 'package:pathos/path.dart' as path;
 
-import 'command.dart';
-import 'dart.dart' as dart;
-import 'io.dart';
-import 'log.dart' as log;
-import 'utils.dart';
+import '../command.dart';
+import '../dart.dart' as dart;
+import '../io.dart';
+import '../log.dart' as log;
+import '../utils.dart';
 
 final _arrow = getSpecial('\u2192', '=>');
 
diff --git a/sdk/lib/_internal/pub/lib/src/command_help.dart b/sdk/lib/_internal/pub/lib/src/command/help.dart
similarity index 82%
rename from sdk/lib/_internal/pub/lib/src/command_help.dart
rename to sdk/lib/_internal/pub/lib/src/command/help.dart
index 25218bc3..a53c575 100644
--- a/sdk/lib/_internal/pub/lib/src/command_help.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/help.dart
@@ -2,17 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library command_help;
+library pub.command.help;
 
 import 'dart:async';
 import 'dart:io' as io;
 
-import 'command.dart';
-import 'exit_codes.dart' as exit_codes;
-import 'io.dart';
-import 'log.dart' as log;
+import '../command.dart';
+import '../exit_codes.dart' as exit_codes;
+import '../io.dart';
+import '../log.dart' as log;
 
-/// Handles the `help` pub command. 
+/// Handles the `help` pub command.
 class HelpCommand extends PubCommand {
   String get description => "Display help information for Pub.";
   String get usage => 'pub help [command]';
diff --git a/sdk/lib/_internal/pub/lib/src/command_install.dart b/sdk/lib/_internal/pub/lib/src/command/install.dart
similarity index 87%
rename from sdk/lib/_internal/pub/lib/src/command_install.dart
rename to sdk/lib/_internal/pub/lib/src/command/install.dart
index afc9d2f..f5621de 100644
--- a/sdk/lib/_internal/pub/lib/src/command_install.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/install.dart
@@ -2,15 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library command_install;
+library pub.command.install;
 
 import 'dart:async';
 
 import 'package:args/args.dart';
 
-import 'command.dart';
-import 'entrypoint.dart';
-import 'log.dart' as log;
+import '../command.dart';
+import '../entrypoint.dart';
+import '../log.dart' as log;
 
 /// Handles the `install` pub command.
 class InstallCommand extends PubCommand {
diff --git a/sdk/lib/_internal/pub/lib/src/command_lish.dart b/sdk/lib/_internal/pub/lib/src/command/lish.dart
similarity index 93%
rename from sdk/lib/_internal/pub/lib/src/command_lish.dart
rename to sdk/lib/_internal/pub/lib/src/command/lish.dart
index 8e4e09c..3721522 100644
--- a/sdk/lib/_internal/pub/lib/src/command_lish.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/lish.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library command_lish;
+library pub.command.lish;
 
 import 'dart:async';
 import 'dart:io';
@@ -12,17 +12,17 @@
 import 'package:http/http.dart' as http;
 import 'package:pathos/path.dart' as path;
 
-import 'command.dart';
-import 'directory_tree.dart';
-import 'exit_codes.dart' as exit_codes;
-import 'git.dart' as git;
-import 'hosted_source.dart';
-import 'http.dart';
-import 'io.dart';
-import 'log.dart' as log;
-import 'oauth2.dart' as oauth2;
-import 'utils.dart';
-import 'validator.dart';
+import '../command.dart';
+import '../directory_tree.dart';
+import '../exit_codes.dart' as exit_codes;
+import '../git.dart' as git;
+import '../http.dart';
+import '../io.dart';
+import '../log.dart' as log;
+import '../oauth2.dart' as oauth2;
+import '../source/hosted.dart';
+import '../utils.dart';
+import '../validator.dart';
 
 /// Handles the `lish` and `publish` pub commands.
 class LishCommand extends PubCommand {
diff --git a/sdk/lib/_internal/pub/lib/src/command_update.dart b/sdk/lib/_internal/pub/lib/src/command/update.dart
similarity index 90%
rename from sdk/lib/_internal/pub/lib/src/command_update.dart
rename to sdk/lib/_internal/pub/lib/src/command/update.dart
index 3db7ba8..e47c80b 100644
--- a/sdk/lib/_internal/pub/lib/src/command_update.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/update.dart
@@ -2,15 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library command_update;
+library pub.command.update;
 
 import 'dart:async';
 
 import 'package:args/args.dart';
 
-import 'command.dart';
-import 'entrypoint.dart';
-import 'log.dart' as log;
+import '../command.dart';
+import '../entrypoint.dart';
+import '../log.dart' as log;
 
 /// Handles the `update` pub command.
 class UpdateCommand extends PubCommand {
diff --git a/sdk/lib/_internal/pub/lib/src/command_uploader.dart b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
similarity index 89%
rename from sdk/lib/_internal/pub/lib/src/command_uploader.dart
rename to sdk/lib/_internal/pub/lib/src/command/uploader.dart
index cb6bf8b..0bae108 100644
--- a/sdk/lib/_internal/pub/lib/src/command_uploader.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library command_uploader;
+library pub.command.uploader;
 
 import 'dart:async';
 import 'dart:io';
@@ -10,15 +10,15 @@
 import 'package:args/args.dart';
 import 'package:pathos/path.dart' as path;
 
-import 'command.dart';
-import 'entrypoint.dart';
-import 'exit_codes.dart' as exit_codes;
-import 'http.dart';
-import 'hosted_source.dart';
-import 'io.dart';
-import 'log.dart' as log;
-import 'oauth2.dart' as oauth2;
-import 'utils.dart';
+import '../command.dart';
+import '../entrypoint.dart';
+import '../exit_codes.dart' as exit_codes;
+import '../http.dart';
+import '../io.dart';
+import '../log.dart' as log;
+import '../oauth2.dart' as oauth2;
+import '../source/hosted.dart';
+import '../utils.dart';
 
 /// Handles the `uploader` pub command.
 class UploaderCommand extends PubCommand {
diff --git a/sdk/lib/_internal/pub/lib/src/command_version.dart b/sdk/lib/_internal/pub/lib/src/command/version.dart
similarity index 75%
rename from sdk/lib/_internal/pub/lib/src/command_version.dart
rename to sdk/lib/_internal/pub/lib/src/command/version.dart
index 457eebd..5fa6026 100644
--- a/sdk/lib/_internal/pub/lib/src/command_version.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/version.dart
@@ -2,15 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library command_version;
+library pub.command.version;
 
 import 'dart:async';
 
-import 'command.dart';
-import 'log.dart' as log;
-import 'sdk.dart' as sdk;
+import '../command.dart';
+import '../log.dart' as log;
+import '../sdk.dart' as sdk;
 
-/// Handles the `version` pub command. 
+/// Handles the `version` pub command.
 class VersionCommand extends PubCommand {
   String get description => 'Print pub version.';
   String get usage => 'pub version';
diff --git a/sdk/lib/_internal/pub/lib/src/dart.dart b/sdk/lib/_internal/pub/lib/src/dart.dart
index 0ad59c0..5c27f09 100644
--- a/sdk/lib/_internal/pub/lib/src/dart.dart
+++ b/sdk/lib/_internal/pub/lib/src/dart.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// A library for compiling Dart code and manipulating analyzer parse trees.
-library dart;
+library pub.dart;
 
 import 'dart:async';
 import 'dart:io';
diff --git a/sdk/lib/_internal/pub/lib/src/directory_tree.dart b/sdk/lib/_internal/pub/lib/src/directory_tree.dart
index a4d501e..7a5f953 100644
--- a/sdk/lib/_internal/pub/lib/src/directory_tree.dart
+++ b/sdk/lib/_internal/pub/lib/src/directory_tree.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// A simple library for rendering a list of files as a directory tree.
-library directory_tree;
+library pub.directory_tree;
 
 import 'package:pathos/path.dart' as path;
 
diff --git a/sdk/lib/_internal/pub/lib/src/entrypoint.dart b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
index a10a0c1..b2c47c2 100644
--- a/sdk/lib/_internal/pub/lib/src/entrypoint.dart
+++ b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library entrypoint;
+library pub.entrypoint;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/error_group.dart b/sdk/lib/_internal/pub/lib/src/error_group.dart
index 51fb27d..303628a 100644
--- a/sdk/lib/_internal/pub/lib/src/error_group.dart
+++ b/sdk/lib/_internal/pub/lib/src/error_group.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library error_group;
+library pub.error_group;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/exit_codes.dart b/sdk/lib/_internal/pub/lib/src/exit_codes.dart
index fd39d15..028fd1c 100644
--- a/sdk/lib/_internal/pub/lib/src/exit_codes.dart
+++ b/sdk/lib/_internal/pub/lib/src/exit_codes.dart
@@ -7,7 +7,7 @@
 /// appropriate for errors encountered by pub.
 ///
 /// [manpage]: http://www.freebsd.org/cgi/man.cgi?query=sysexits
-library exit_codes;
+library pub.exit_codes;
 
 /// The command was used incorrectly.
 final USAGE = 64;
diff --git a/sdk/lib/_internal/pub/lib/src/git.dart b/sdk/lib/_internal/pub/lib/src/git.dart
index 8d996229..9e946e2 100644
--- a/sdk/lib/_internal/pub/lib/src/git.dart
+++ b/sdk/lib/_internal/pub/lib/src/git.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Helper functionality for invoking Git.
-library git;
+library pub.git;
 
 import 'dart:async';
 import 'io.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/lock_file.dart b/sdk/lib/_internal/pub/lib/src/lock_file.dart
index 7f69ca1..85b63a8 100644
--- a/sdk/lib/_internal/pub/lib/src/lock_file.dart
+++ b/sdk/lib/_internal/pub/lib/src/lock_file.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library lock_file;
+library pub.lock_file;
 
 import 'dart:collection';
 
diff --git a/sdk/lib/_internal/pub/lib/src/log.dart b/sdk/lib/_internal/pub/lib/src/log.dart
index 047f621..2d61143 100644
--- a/sdk/lib/_internal/pub/lib/src/log.dart
+++ b/sdk/lib/_internal/pub/lib/src/log.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Message logging.
-library log;
+library pub.log;
 
 import 'dart:io';
 import 'dart:async';
diff --git a/sdk/lib/_internal/pub/lib/src/oauth2.dart b/sdk/lib/_internal/pub/lib/src/oauth2.dart
index dd2c7b6..66e5f88 100644
--- a/sdk/lib/_internal/pub/lib/src/oauth2.dart
+++ b/sdk/lib/_internal/pub/lib/src/oauth2.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library oauth2;
+library pub.oauth2;
 
 import 'dart:async';
 import 'dart:io';
diff --git a/sdk/lib/_internal/pub/lib/src/package.dart b/sdk/lib/_internal/pub/lib/src/package.dart
index 22d3bee..2979849 100644
--- a/sdk/lib/_internal/pub/lib/src/package.dart
+++ b/sdk/lib/_internal/pub/lib/src/package.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library package;
+library pub.package;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/pubspec.dart b/sdk/lib/_internal/pub/lib/src/pubspec.dart
index 2100cc6..3a7738e 100644
--- a/sdk/lib/_internal/pub/lib/src/pubspec.dart
+++ b/sdk/lib/_internal/pub/lib/src/pubspec.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library pubspec;
+library pub.pubspec;
 
 import 'package:yaml/yaml.dart';
 import 'package:pathos/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
index 0f3b9f1..aeb24ac 100644
--- a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
+++ b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library safe_http_server;
+library pub.safe_http_server;
 
 import 'dart:async';
 import 'dart:io';
diff --git a/sdk/lib/_internal/pub/lib/src/sdk.dart b/sdk/lib/_internal/pub/lib/src/sdk.dart
index 7f4e26a..8f86ab4 100644
--- a/sdk/lib/_internal/pub/lib/src/sdk.dart
+++ b/sdk/lib/_internal/pub/lib/src/sdk.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Operations relative to the user's installed Dart SDK.
-library sdk;
+library pub.sdk;
 
 import 'dart:io';
 
diff --git a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
index 00a6ba2..e318ca2 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
@@ -31,7 +31,7 @@
 /// doing this, traversing and then backtracking when it meets a failure until
 /// a valid solution has been found or until all possible options for all
 /// speculative choices have been exhausted.
-library solver.backtracking_solver;
+library pub.solver.backtracking_solver;
 
 import 'dart:async';
 import 'dart:collection' show Queue;
diff --git a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
index 9a98698..2dc215e 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/version_solver.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library version_solver;
+library pub.solver.version_solver;
 
 import 'dart:async';
 import 'dart:json' as json;
@@ -196,6 +196,8 @@
     return buffer.toString();
   }
 
+  String get message => toString();
+
   /// A message describing the specific kind of solve failure.
   String get _message {
     throw new UnimplementedError("Must override _message or toString().");
diff --git a/sdk/lib/_internal/pub/lib/src/source.dart b/sdk/lib/_internal/pub/lib/src/source.dart
index f72f173..4557fa1 100644
--- a/sdk/lib/_internal/pub/lib/src/source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library source;
+library pub.source;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/git_source.dart b/sdk/lib/_internal/pub/lib/src/source/git.dart
similarity index 96%
rename from sdk/lib/_internal/pub/lib/src/git_source.dart
rename to sdk/lib/_internal/pub/lib/src/source/git.dart
index bccae27..c623cdb 100644
--- a/sdk/lib/_internal/pub/lib/src/git_source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/git.dart
@@ -2,19 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library git_source;
+library pub.source.git;
 
 import 'dart:async';
 
 import 'package:pathos/path.dart' as path;
 
-import 'git.dart' as git;
-import 'io.dart';
-import 'log.dart' as log;
-import 'package.dart';
-import 'source.dart';
-import 'source_registry.dart';
-import 'utils.dart';
+import '../git.dart' as git;
+import '../io.dart';
+import '../log.dart' as log;
+import '../package.dart';
+import '../source.dart';
+import '../source_registry.dart';
+import '../utils.dart';
 
 /// A package source that installs packages from Git repos.
 class GitSource extends Source {
diff --git a/sdk/lib/_internal/pub/lib/src/hosted_source.dart b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
similarity index 96%
rename from sdk/lib/_internal/pub/lib/src/hosted_source.dart
rename to sdk/lib/_internal/pub/lib/src/source/hosted.dart
index 6967aa6..f69924f 100644
--- a/sdk/lib/_internal/pub/lib/src/hosted_source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library hosted_source;
+library pub.source.hosted;
 
 import 'dart:async';
 import 'dart:io' as io;
@@ -11,15 +11,15 @@
 import 'package:http/http.dart' as http;
 import 'package:pathos/path.dart' as path;
 
-import 'http.dart';
-import 'io.dart';
-import 'log.dart' as log;
-import 'package.dart';
-import 'pubspec.dart';
-import 'source.dart';
-import 'source_registry.dart';
-import 'utils.dart';
-import 'version.dart';
+import '../http.dart';
+import '../io.dart';
+import '../log.dart' as log;
+import '../package.dart';
+import '../pubspec.dart';
+import '../source.dart';
+import '../source_registry.dart';
+import '../utils.dart';
+import '../version.dart';
 
 /// A package source that installs packages from a package hosting site that
 /// uses the same API as pub.dartlang.org.
diff --git a/sdk/lib/_internal/pub/lib/src/path_source.dart b/sdk/lib/_internal/pub/lib/src/source/path.dart
similarity index 94%
rename from sdk/lib/_internal/pub/lib/src/path_source.dart
rename to sdk/lib/_internal/pub/lib/src/source/path.dart
index 5972050..a8a5306 100644
--- a/sdk/lib/_internal/pub/lib/src/path_source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/path.dart
@@ -2,21 +2,21 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library path_source;
+library pub.source.path;
 
 import 'dart:async';
 import 'dart:io';
 
 import 'package:pathos/path.dart' as path;
 
-import 'log.dart' as log;
+import '../log.dart' as log;
 
-import 'io.dart';
-import 'package.dart';
-import 'pubspec.dart';
-import 'version.dart';
-import 'source.dart';
-import 'utils.dart';
+import '../io.dart';
+import '../package.dart';
+import '../pubspec.dart';
+import '../version.dart';
+import '../source.dart';
+import '../utils.dart';
 
 /// A package [Source] that installs packages from a given local file path.
 class PathSource extends Source {
diff --git a/sdk/lib/_internal/pub/lib/src/source_registry.dart b/sdk/lib/_internal/pub/lib/src/source_registry.dart
index a963e1d..00deb4a 100644
--- a/sdk/lib/_internal/pub/lib/src/source_registry.dart
+++ b/sdk/lib/_internal/pub/lib/src/source_registry.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library source_registry;
+library pub.source_registry;
 
 import 'source.dart';
 
diff --git a/sdk/lib/_internal/pub/lib/src/system_cache.dart b/sdk/lib/_internal/pub/lib/src/system_cache.dart
index 63de5dc..08f031d 100644
--- a/sdk/lib/_internal/pub/lib/src/system_cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/system_cache.dart
@@ -2,21 +2,21 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library system_cache;
+library pub.system_cache;
 
 import 'dart:io';
 import 'dart:async';
 
 import 'package:pathos/path.dart' as path;
 
-import 'git_source.dart';
-import 'hosted_source.dart';
 import 'io.dart';
 import 'io.dart' as io show createTempDir;
 import 'log.dart' as log;
 import 'package.dart';
-import 'path_source.dart';
 import 'pubspec.dart';
+import 'source/git.dart';
+import 'source/hosted.dart';
+import 'source/path.dart';
 import 'source.dart';
 import 'source_registry.dart';
 import 'utils.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index d5210f3..8c41b92 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Generic utility functions. Stuff that should possibly be in core.
-library utils;
+library pub.utils;
 
 import 'dart:async';
 import 'dart:io';
diff --git a/sdk/lib/_internal/pub/lib/src/validator.dart b/sdk/lib/_internal/pub/lib/src/validator.dart
index 4bfff03..c4a258f 100644
--- a/sdk/lib/_internal/pub/lib/src/validator.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library validator;
+library pub.validator;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart b/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
index 45a8fba..94f7031 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library compiled_dartdoc_validator;
+library pub.validator.compiled_dartdoc;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/validator/dependency.dart b/sdk/lib/_internal/pub/lib/src/validator/dependency.dart
index a1a8f99..b447a8d 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/dependency.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/dependency.dart
@@ -2,15 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library dependency_validator;
+library pub.validator.dependency;
 
 import 'dart:async';
 
 import '../entrypoint.dart';
-import '../hosted_source.dart';
 import '../http.dart';
 import '../package.dart';
-import '../path_source.dart';
+import '../source/hosted.dart';
+import '../source/path.dart';
 import '../utils.dart';
 import '../validator.dart';
 import '../version.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/validator/directory.dart b/sdk/lib/_internal/pub/lib/src/validator/directory.dart
index 5e90437..30f4ddd 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/directory.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/directory.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library directory_validator;
+library pub.validator.directory;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/validator/lib.dart b/sdk/lib/_internal/pub/lib/src/validator/lib.dart
index 2e72738..42d6366 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/lib.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/lib.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library lib_validator;
+library pub.validator.lib;
 
 import 'dart:async';
 import 'dart:io';
diff --git a/sdk/lib/_internal/pub/lib/src/validator/license.dart b/sdk/lib/_internal/pub/lib/src/validator/license.dart
index 16b202f..844c223 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/license.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/license.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library license_validator;
+library pub.validator.license;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/validator/name.dart b/sdk/lib/_internal/pub/lib/src/validator/name.dart
index 542d9fd..8df191a 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/name.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/name.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library name_validator;
+library pub.validator.name;
 
 import 'dart:async';
 import 'dart:io';
diff --git a/sdk/lib/_internal/pub/lib/src/validator/pubspec_field.dart b/sdk/lib/_internal/pub/lib/src/validator/pubspec_field.dart
index 03a1b8e..6cb1d83 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/pubspec_field.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/pubspec_field.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library pubspec_field_validator;
+library pub.validator.pubspec_field;
 
 import 'dart:async';
 
diff --git a/sdk/lib/_internal/pub/lib/src/validator/size.dart b/sdk/lib/_internal/pub/lib/src/validator/size.dart
index 8014b29..0b8d05f 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/size.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/size.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library size_validator;
+library pub.validator.size;
 
 import 'dart:async';
 import 'dart:math' as math;
diff --git a/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart b/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
index cbb85c4..2ae7ad3 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library utf8_readme_validator;
+library pub.validator.utf8_readme;
 
 import 'dart:async';
 import 'dart:utf';
diff --git a/sdk/lib/_internal/pub/lib/src/version.dart b/sdk/lib/_internal/pub/lib/src/version.dart
index 62669e4..c3943a6 100644
--- a/sdk/lib/_internal/pub/lib/src/version.dart
+++ b/sdk/lib/_internal/pub/lib/src/version.dart
@@ -5,7 +5,7 @@
 /// Handles version numbers, following the [Semantic Versioning][semver] spec.
 ///
 /// [semver]: http://semver.org/
-library version;
+library pub.version;
 
 import 'dart:math';
 
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index c35ab69..b3bbc82 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -28,13 +28,13 @@
 // with the git descriptor method. Maybe we should try to clean up the top level
 // scope a bit?
 import '../lib/src/git.dart' as gitlib;
-import '../lib/src/git_source.dart';
-import '../lib/src/hosted_source.dart';
 import '../lib/src/http.dart';
 import '../lib/src/io.dart';
 import '../lib/src/log.dart' as log;
-import '../lib/src/path_source.dart';
 import '../lib/src/safe_http_server.dart';
+import '../lib/src/source/git.dart';
+import '../lib/src/source/hosted.dart';
+import '../lib/src/source/path.dart';
 import '../lib/src/system_cache.dart';
 import '../lib/src/utils.dart';
 import '../lib/src/validator.dart';
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index ab1f09c..e2f22a6 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -18,10 +18,50 @@
 class HashMap<K, V> implements Map<K, V> {
   external HashMap();
 
+  /**
+   * Creates a [HashMap] that contains all key value pairs of [other].
+   */
   factory HashMap.from(Map<K, V> other) {
     return new HashMap<K, V>()..addAll(other);
   }
 
+  /**
+   * Creates a [HashMap] where the keys and values are computed from the
+   * [iterable].
+   *
+   * For each element of the [iterable] this constructor computes a key/value
+   * pair, by applying [key] and [value] respectively.
+   *
+   * The keys of the key/value pairs do not need to be unique. The last
+   * occurrence of a key will simply overwrite any previous value.
+   *
+   * If no values are specified for [key] and [value] the default is the
+   * identity function.
+   */
+  factory HashMap.fromIterable(Iterable<K> iterable,
+      {K key(element), V value(element)}) {
+    HashMap<K, V> map = new HashMap<K, V>();
+    Maps._fillMapWithMappedIterable(map, iterable, key, value);
+    return map;
+  }
+
+  /**
+   * Creates a [HashMap] associating the given [keys] to [values].
+   *
+   * This constructor iterates over [keys] and [values] and maps each element of
+   * [keys] to the corresponding element of [values].
+   *
+   * If [keys] contains the same object multiple times, the last occurrence
+   * overwrites the previous value.
+   *
+   * It is an error if the two [Iterable]s don't have the same length.
+   */
+  factory HashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
+    HashMap<K, V> map = new HashMap<K, V>();
+    Maps._fillMapWithIterables(map, keys, values);
+    return map;
+  }
+
   external int get length;
   external bool get isEmpty;
   external bool get isNotEmpty;
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index 3082ce0..4ace589 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -21,10 +21,50 @@
 class LinkedHashMap<K, V> implements Map<K, V> {
   external LinkedHashMap();
 
+  /**
+   * Creates a [LinkedHashMap] that contains all key value pairs of [other].
+   */
   factory LinkedHashMap.from(Map<K, V> other) {
     return new LinkedHashMap<K, V>()..addAll(other);
   }
 
+  /**
+   * Creates a [LinkedHashMap] where the keys and values are computed from the
+   * [iterable].
+   *
+   * For each element of the [iterable] this constructor computes a key/value
+   * pair, by applying [key] and [value] respectively.
+   *
+   * The keys of the key/value pairs do not need to be unique. The last
+   * occurrence of a key will simply overwrite any previous value.
+   *
+   * If no values are specified for [key] and [value] the default is the
+   * identity function.
+   */
+  factory LinkedHashMap.fromIterable(Iterable<K> iterable,
+      {K key(element), V value(element)}) {
+    LinkedHashMap<K, V> map = new LinkedHashMap<K, V>();
+    Maps._fillMapWithMappedIterable(map, iterable, key, value);
+    return map;
+  }
+
+  /**
+   * Creates a [LinkedHashMap] associating the given [keys] to [values].
+   *
+   * This constructor iterates over [keys] and [values] and maps each element of
+   * [keys] to the corresponding element of [values].
+   *
+   * If [keys] contains the same object multiple times, the last occurrence
+   * overwrites the previous value.
+   *
+   * It is an error if the two [Iterable]s don't have the same length.
+   */
+  factory LinkedHashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
+    LinkedHashMap<K, V> map = new LinkedHashMap<K, V>();
+    Maps._fillMapWithIterables(map, keys, values);
+    return map;
+  }
+
   external bool containsKey(Object key);
 
   external bool containsValue(Object value);
diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart
index bd7d755..303008c 100644
--- a/sdk/lib/collection/maps.dart
+++ b/sdk/lib/collection/maps.dart
@@ -77,4 +77,45 @@
    * simply return the results of this method applied to the collection.
    */
   static String mapToString(Map m) => ToString.mapToString(m);
+
+  static _id(x) => x;
+
+  /**
+   * Fills a map with key/value pairs computed from [iterable].
+   *
+   * This method is used by Map classes in the named constructor fromIterable.
+   */
+  static void _fillMapWithMappedIterable(Map map, Iterable iterable,
+                                         key(element), value(element)) {
+    if (key == null) key = _id;
+    if (value == null) value = _id;
+
+    for (var element in iterable) {
+      map[key(element)] = value(element);
+    }
+  }
+
+  /**
+   * Fills a map by associating the [keys] to [values].
+   *
+   * This method is used by Map classes in the named constructor fromIterables.
+   */
+  static void _fillMapWithIterables(Map map, Iterable keys,
+                                    Iterable values) {
+    Iterator keyIterator = keys.iterator;
+    Iterator valueIterator = values.iterator;
+
+    bool hasNextKey = keyIterator.moveNext();
+    bool hasNextValue = valueIterator.moveNext();
+
+    while (hasNextKey && hasNextValue) {
+      map[keyIterator.current] = valueIterator.current;
+      hasNextKey = keyIterator.moveNext();
+      hasNextValue = valueIterator.moveNext();
+    }
+
+    if (hasNextKey || hasNextValue) {
+      throw new ArgumentError("Iterables do not have same length.");
+    }
+  }
 }
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 84e61e1..7dac687 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -248,9 +248,50 @@
   SplayTreeMap([int compare(K key1, K key2)])
       : _comparator = (compare == null) ? Comparable.compare : compare;
 
+  /**
+   * Creates a [SplayTreeMap] that contains all key value pairs of [other].
+   */
   factory SplayTreeMap.from(Map<K, V> other, [int compare(K key1, K key2)]) =>
       new SplayTreeMap(compare)..addAll(other);
 
+  /**
+   * Creates a [SplayTreeMap] where the keys and values are computed from the
+   * [iterable].
+   *
+   * For each element of the [iterable] this constructor computes a key/value
+   * pair, by applying [key] and [value] respectively.
+   *
+   * The keys of the key/value pairs do not need to be unique. The last
+   * occurrence of a key will simply overwrite any previous value.
+   *
+   * If no values are specified for [key] and [value] the default is the
+   * identity function.
+   */
+  factory SplayTreeMap.fromIterable(Iterable<K> iterable,
+      {K key(element), V value(element), int compare(K key1, K key2)}) {
+    SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare);
+    Maps._fillMapWithMappedIterable(map, iterable, key, value);
+    return map;
+  }
+
+  /**
+   * Creates a [SplayTreeMap] associating the given [keys] to [values].
+   *
+   * This constructor iterates over [keys] and [values] and maps each element of
+   * [keys] to the corresponding element of [values].
+   *
+   * If [keys] contains the same object multiple times, the last occurrence
+   * overwrites the previous value.
+   *
+   * It is an error if the two [Iterable]s don't have the same length.
+   */
+  factory SplayTreeMap.fromIterables(Iterable<K> keys, Iterable<V> values,
+      [int compare(K key1, K key2)]) {
+    SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare);
+    Maps._fillMapWithIterables(map, keys, values);
+    return map;
+  }
+
   int _compare(K key1, K key2) => _comparator(key1, key2);
 
   SplayTreeMap._internal();
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index 88776c1..e74b936 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -20,6 +20,35 @@
   factory Map.from(Map<K, V> other) => new HashMap<K, V>.from(other);
 
   /**
+   * Creates a [Map] where the keys and values are computed from the [iterable].
+   *
+   * For each element of the [iterable] this constructor computes a key/value
+   * pair, by applying [key] and [value] respectively.
+   *
+   * The keys of the key/value pairs do not need to be unique. The last
+   * occurrence of a key will simply overwrite any previous value.
+   *
+   * If no values are specified for [key] and [value] the default is the
+   * identity function.
+   */
+  factory Map.fromIterable(Iterable<K> iterable,
+      {K key(element), V value(element)}) = HashMap<K, V>.fromIterable;
+
+  /**
+   * Creates a [Map] associating the given [keys] to [values].
+   *
+   * This constructor iterates over [keys] and [values] and maps each element of
+   * [keys] to the corresponding element of [values].
+   *
+   * If [keys] contains the same object multiple times, the last occurrence
+   * overwrites the previous value.
+   *
+   * It is an error if the two [Iterable]s don't have the same length.
+   */
+  factory Map.fromIterables(Iterable<K> keys, Iterable<V> values)
+      = HashMap<K, V>.fromIterables;
+
+  /**
    * Returns whether this map contains the given [value].
    */
   bool containsValue(Object value);
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 8f155b4..8e307a4 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -13,7 +13,6 @@
 import 'dart:isolate';
 import 'dart:json' as json;
 import 'dart:math';
-import 'dart:mdv_observe_impl';
 import 'dart:typed_data';
 import 'dart:svg' as svg;
 import 'dart:web_audio' as web_audio;
@@ -2498,7 +2497,7 @@
 
 
 @DomName('CSSStyleDeclaration')
-class CssStyleDeclaration native "CSSStyleDeclaration" {
+class CssStyleDeclaration native "CSSStyleDeclaration,MSStyleCSSProperties,CSS2Properties" {
   factory CssStyleDeclaration() => new CssStyleDeclaration.css('');
 
   factory CssStyleDeclaration.css(String css) {
@@ -8280,21 +8279,6 @@
     throw new UnsupportedError("Not supported on this platform");
   }
 
-  @Creates('Null') // Set from Dart code; does not instantiate a native type.
-  Map<String, StreamSubscription> _attributeBindings;
-
-  // TODO(jmesserly): I'm concerned about adding these to every element.
-  // Conceptually all of these belong on TemplateElement. They are here to
-  // support browsers that don't have <template> yet.
-  // However even in the polyfill they're restricted to certain tags
-  // (see [isTemplate]). So we can probably convert it to a (public) mixin, and
-  // only mix it in to the elements that need it.
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  var _model;
-
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  _TemplateIterator _templateIterator;
-
   @Creates('Null')  // Set from Dart code; does not instantiate a native type.
   Element _templateInstanceRef;
 
@@ -8304,124 +8288,6 @@
 
   bool _templateIsDecorated;
 
-  // TODO(jmesserly): should path be optional, and default to empty path?
-  // It is used that way in at least one path in JS TemplateElement tests
-  // (see "BindImperative" test in original JS code).
-  @Experimental
-  void bind(String name, model, String path) {
-    _bindElement(this, name, model, path);
-  }
-
-  // TODO(jmesserly): this is static to work around http://dartbug.com/10166
-  // Similar issue for unbind/unbindAll below.
-  static void _bindElement(Element self, String name, model, String path) {
-    if (self._bindTemplate(name, model, path)) return;
-
-    if (self._attributeBindings == null) {
-      self._attributeBindings = new Map<String, StreamSubscription>();
-    }
-
-    self.xtag.attributes.remove(name);
-
-    var changed;
-    if (name.endsWith('?')) {
-      name = name.substring(0, name.length - 1);
-
-      changed = (value) {
-        if (_Bindings._toBoolean(value)) {
-          self.xtag.attributes[name] = '';
-        } else {
-          self.xtag.attributes.remove(name);
-        }
-      };
-    } else {
-      changed = (value) {
-        // TODO(jmesserly): escape value if needed to protect against XSS.
-        // See https://github.com/polymer-project/mdv/issues/58
-        self.xtag.attributes[name] = value == null ? '' : '$value';
-      };
-    }
-
-    self.unbind(name);
-
-    self._attributeBindings[name] =
-        new PathObserver(model, path).bindSync(changed);
-  }
-
-  @Experimental
-  void unbind(String name) {
-    _unbindElement(this, name);
-  }
-
-  static _unbindElement(Element self, String name) {
-    if (self._unbindTemplate(name)) return;
-    if (self._attributeBindings != null) {
-      var binding = self._attributeBindings.remove(name);
-      if (binding != null) binding.cancel();
-    }
-  }
-
-  @Experimental
-  void unbindAll() {
-    _unbindAllElement(this);
-  }
-
-  static void _unbindAllElement(Element self) {
-    self._unbindAllTemplate();
-
-    if (self._attributeBindings != null) {
-      for (var binding in self._attributeBindings.values) {
-        binding.cancel();
-      }
-      self._attributeBindings = null;
-    }
-  }
-
-  // TODO(jmesserly): unlike the JS polyfill, we can't mixin
-  // HTMLTemplateElement at runtime into things that are semantically template
-  // elements. So instead we implement it here with a runtime check.
-  // If the bind succeeds, we return true, otherwise we return false and let
-  // the normal Element.bind logic kick in.
-  bool _bindTemplate(String name, model, String path) {
-    if (isTemplate) {
-      switch (name) {
-        case 'bind':
-        case 'repeat':
-        case 'if':
-          _ensureTemplate();
-          if (_templateIterator == null) {
-            _templateIterator = new _TemplateIterator(this);
-          }
-          _templateIterator.inputs.bind(name, model, path);
-          return true;
-      }
-    }
-    return false;
-  }
-
-  bool _unbindTemplate(String name) {
-    if (isTemplate) {
-      switch (name) {
-        case 'bind':
-        case 'repeat':
-        case 'if':
-          _ensureTemplate();
-          if (_templateIterator != null) {
-            _templateIterator.inputs.unbind(name);
-          }
-          return true;
-      }
-    }
-    return false;
-  }
-
-  void _unbindAllTemplate() {
-    if (isTemplate) {
-      unbind('bind');
-      unbind('repeat');
-      unbind('if');
-    }
-  }
 
   /**
    * Gets the template this node refers to.
@@ -8434,7 +8300,19 @@
     Element ref = null;
     var refId = attributes['ref'];
     if (refId != null) {
-      ref = document.getElementById(refId);
+      var treeScope = this;
+      while (treeScope.parentNode != null) {
+        treeScope = treeScope.parentNode;
+      }
+
+      // Note: JS code tests that getElementById is present. We can't do that
+      // easily, so instead check for the types known to implement it.
+      if (treeScope is Document ||
+          treeScope is ShadowRoot ||
+          treeScope is svg.SvgSvgElement) {
+
+        ref = treeScope.getElementById(refId);
+      }
     }
 
     return ref != null ? ref : _templateInstanceRef;
@@ -8457,38 +8335,20 @@
   @Experimental
   DocumentFragment createInstance() {
     _ensureTemplate();
-
-    var template = ref;
-    if (template == null) template = this;
-
-    var instance = _Bindings._createDeepCloneAndDecorateTemplates(
-        template.content, attributes['syntax']);
-
-    if (TemplateElement._instanceCreated != null) {
-      TemplateElement._instanceCreated.add(instance);
-    }
-    return instance;
+    return TemplateElement.mdvPackage(this).createInstance();
   }
 
   /**
    * The data model which is inherited through the tree.
    * This is only supported if [isTemplate] is true.
-   *
-   * Setting this will destructive propagate the value to all descendant nodes,
-   * and reinstantiate all of the nodes expanded by this template.
-   *
-   * Currently this does not support propagation through Shadow DOMs.
    */
   @Experimental
-  get model => _model;
+  get model => TemplateElement.mdvPackage(this).model;
 
   @Experimental
   void set model(value) {
     _ensureTemplate();
-
-    var syntax = TemplateElement.syntax[attributes['syntax']];
-    _model = value;
-    _Bindings._addBindings(this, model, syntax);
+    TemplateElement.mdvPackage(this).model = value;
   }
 
   // TODO(jmesserly): const set would be better
@@ -8505,7 +8365,8 @@
   };
 
   bool get _isAttributeTemplate => attributes.containsKey('template') &&
-      (localName == 'option' || _TABLE_TAGS.containsKey(localName));
+      (localName == 'option' || localName == 'optgroup' ||
+       _TABLE_TAGS.containsKey(localName));
 
   /**
    * Returns true if this node is a template.
@@ -8514,7 +8375,7 @@
    * 'template' attribute and this tag supports attribute form for backwards
    * compatibility with existing HTML parsers. The nodes that can use attribute
    * form are table elments (THEAD, TBODY, TFOOT, TH, TR, TD, CAPTION, COLGROUP
-   * and COL) and OPTION.
+   * and COL), OPTION, and OPTGROUP.
    */
   // TODO(jmesserly): this is not a public MDV API, but it seems like a useful
   // place to document which tags our polyfill considers to be templates.
@@ -12524,61 +12385,6 @@
     return e;
   }
 
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  _ValueBinding _valueBinding;
-
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  _CheckedBinding _checkedBinding;
-
-  @Experimental
-  void bind(String name, model, String path) {
-    switch (name) {
-      case 'value':
-        unbind('value');
-        attributes.remove('value');
-        _valueBinding = new _ValueBinding(this, model, path);
-        break;
-      case 'checked':
-        unbind('checked');
-        attributes.remove('checked');
-        _checkedBinding = new _CheckedBinding(this, model, path);
-        break;
-      default:
-        // TODO(jmesserly): this should be "super" (http://dartbug.com/10166).
-        // Similar issue for unbind/unbindAll below.
-        Element._bindElement(this, name, model, path);
-        break;
-    }
-  }
-
-  @Experimental
-  void unbind(String name) {
-    switch (name) {
-      case 'value':
-        if (_valueBinding != null) {
-          _valueBinding.unbind();
-          _valueBinding = null;
-        }
-        break;
-      case 'checked':
-        if (_checkedBinding != null) {
-          _checkedBinding.unbind();
-          _checkedBinding = null;
-        }
-        break;
-      default:
-        Element._unbindElement(this, name);
-        break;
-    }
-  }
-
-  @Experimental
-  void unbindAll() {
-    unbind('value');
-    unbind('checked');
-    Element._unbindAllElement(this);
-  }
-
 
   @DomName('HTMLInputElement.webkitSpeechChangeEvent')
   @DocsEditable
@@ -15627,7 +15433,7 @@
 
 
 @DomName('MouseEvent')
-class MouseEvent extends UIEvent native "MouseEvent" {
+class MouseEvent extends UIEvent native "MouseEvent,DragEvent" {
   factory MouseEvent(String type,
       {Window view, int detail: 0, int screenX: 0, int screenY: 0,
       int clientX: 0, int clientY: 0, int button: 0, bool canBubble: true,
@@ -16380,8 +16186,7 @@
       if (!identical(otherList._this, _this)) {
         // Optimized route for copying between nodes.
         for (var i = 0, len = otherList.length; i < len; ++i) {
-          // Should use $dom_firstChild, Bug 8886.
-          _this.append(otherList[0]);
+          _this.append(otherList._this.firstChild);
         }
       }
       return;
@@ -16439,7 +16244,7 @@
     // This implementation of removeWhere/retainWhere is more efficient
     // than the default in ListBase. Child nodes can be removed in constant
     // time.
-    Node child = _this.$dom_firstChild;
+    Node child = _this.firstChild;
     while (child != null) {
       Node nextChild = child.nextNode;
       if (test(child) == removeMatching) {
@@ -16498,6 +16303,27 @@
   Node operator[](int index) => _this.$dom_childNodes[index];
 }
 
+/** Information about the instantiated template. */
+class TemplateInstance {
+  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
+  // in cases where script has modified the template instance boundary.
+
+  /** The first node of this template instantiation. */
+  final Node firstNode;
+
+  /**
+   * The last node of this template instantiation.
+   * This could be identical to [firstNode] if the template only expanded to a
+   * single node.
+   */
+  final Node lastNode;
+
+  /** The model used to instantiate the template. */
+  final model;
+
+  TemplateInstance(this.firstNode, this.lastNode, this.model);
+}
+
 @DomName('Node')
 class Node extends EventTarget native "Node" {
   List<Node> get nodes {
@@ -16557,8 +16383,7 @@
 
       // Optimized route for copying between nodes.
       for (var i = 0, len = otherList.length; i < len; ++i) {
-        // Should use $dom_firstChild, Bug 8886.
-        this.insertBefore(otherList[0], refChild);
+        this.insertBefore(otherList._this.firstChild, refChild);
       }
     } else {
       for (var node in newNodes) {
@@ -16578,26 +16403,25 @@
    */
   @Experimental
   void bind(String name, model, String path) {
-    // TODO(jmesserly): should we throw instead?
-    window.console.error('Unhandled binding to Node: '
-        '$this $name $model $path');
+    TemplateElement.mdvPackage(this).bind(name, model, path);
   }
 
   /** Unbinds the attribute [name]. */
   @Experimental
-  void unbind(String name) {}
+  void unbind(String name) {
+    TemplateElement.mdvPackage(this).unbind(name);
+  }
 
   /** Unbinds all bound attributes. */
   @Experimental
-  void unbindAll() {}
-
-  TemplateInstance _templateInstance;
+  void unbindAll() {
+    TemplateElement.mdvPackage(this).unbindAll();
+  }
 
   /** Gets the template instance that instantiated this node, if any. */
   @Experimental
   TemplateInstance get templateInstance =>
-      _templateInstance != null ? _templateInstance :
-      (parent != null ? parent.templateInstance : null);
+      TemplateElement.mdvPackage(this).templateInstance;
 
 
   @DomName('Node.ATTRIBUTE_NODE')
@@ -16655,15 +16479,13 @@
   @Creates('NodeList')
   final List<Node> $dom_childNodes;
 
-  @JSName('firstChild')
   @DomName('Node.firstChild')
   @DocsEditable
-  final Node $dom_firstChild;
+  final Node firstChild;
 
-  @JSName('lastChild')
   @DomName('Node.lastChild')
   @DocsEditable
-  final Node $dom_lastChild;
+  final Node lastChild;
 
   @JSName('localName')
   @DomName('Node.localName')
@@ -20803,7 +20625,7 @@
 
 @DocsEditable
 @DomName('HTMLTableCellElement')
-class TableCellElement extends _HTMLElement native "HTMLTableCellElement" {
+class TableCellElement extends _HTMLElement native "HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement" {
 
   @DomName('HTMLTableCellElement.HTMLTableCellElement')
   @DocsEditable
@@ -21037,6 +20859,99 @@
 // WARNING: Do not edit - generated code.
 
 
+
+/**
+ * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
+ * but (by design) don't attempt to implement a wide array of specialized
+ * behaviors.
+ *
+ * Enabling these features in MDV is a matter of implementing and registering an
+ * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
+ * delegation functions which implement specialized behavior. This object is
+ * registered with MDV via [TemplateElement.syntax]:
+ *
+ *
+ * HTML:
+ *     <template bind syntax="MySyntax">
+ *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
+ *     </template>
+ *
+ * Dart:
+ *     class MySyntax extends CustomBindingSyntax {
+ *       getBinding(model, path, name, node) {
+ *         // The magic happens here!
+ *       }
+ *     }
+ *
+ *     ...
+ *
+ *     TemplateElement.syntax['MySyntax'] = new MySyntax();
+ *
+ * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
+ * more information about Custom Syntax.
+ */
+// TODO(jmesserly): if this is just one method, a function type would make it
+// more Dart-friendly.
+@Experimental
+abstract class CustomBindingSyntax {
+  /**
+   * This syntax method allows for a custom interpretation of the contents of
+   * mustaches (`{{` ... `}}`).
+   *
+   * When a template is inserting an instance, it will invoke this method for
+   * each mustache which is encountered. The function is invoked with four
+   * arguments:
+   *
+   * - [model]: The data context for which this instance is being created.
+   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
+   * - [name]: The context in which the mustache occurs. Within element
+   *   attributes, this will be the name of the attribute. Within text,
+   *   this will be 'text'.
+   * - [node]: A reference to the node to which this binding will be created.
+   *
+   * If the method wishes to handle binding, it is required to return an object
+   * which has at least a `value` property that can be observed. If it does,
+   * then MDV will call [Node.bind on the node:
+   *
+   *     node.bind(name, retval, 'value');
+   *
+   * If the 'getBinding' does not wish to override the binding, it should return
+   * null.
+   */
+  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
+  // Normally they are String and Node respectively. But sometimes it will pass
+  // (int name, CompoundBinding node). That seems very confusing; we may want
+  // to change this API.
+  getBinding(model, String path, name, node) => null;
+
+  /**
+   * This syntax method allows a syntax to provide an alterate model than the
+   * one the template would otherwise use when producing an instance.
+   *
+   * When a template is about to create an instance, it will invoke this method
+   * The function is invoked with two arguments:
+   *
+   * - [template]: The template element which is about to create and insert an
+   *   instance.
+   * - [model]: The data context for which this instance is being created.
+   *
+   * The template element will always use the return value of `getInstanceModel`
+   * as the model for the new instance. If the syntax does not wish to override
+   * the value, it should simply return the `model` value it was passed.
+   */
+  getInstanceModel(Element template, model) => model;
+
+  /**
+   * This syntax method allows a syntax to provide an alterate expansion of
+   * the [template] contents. When the template wants to create an instance,
+   * it will call this method with the template element.
+   *
+   * By default this will call `template.createInstance()`.
+   */
+  getInstanceFragment(Element template) => template.createInstance();
+}
+
+
 @Experimental
 @DomName('HTMLTemplateElement')
 @SupportedBrowser(SupportedBrowser.CHROME)
@@ -21062,24 +20977,23 @@
   @Experimental
   DocumentFragment get content => $dom_content;
 
-  static StreamController<DocumentFragment> _instanceCreated;
 
   /**
-   * *Warning*: This is an implementation helper for Model-Driven Views and
-   * should not be used in your code.
+   * The MDV package, if available.
    *
-   * This event is fired whenever a template is instantiated via
-   * [createInstance].
+   * This can be used to initialize MDV support via:
+   *
+   *     import 'dart:html';
+   *     import 'package:mdv/mdv.dart' as mdv;
+   *     main() {
+   *       mdv.initialize();
+   *     }
    */
-  // TODO(rafaelw): This is a hack, and is neccesary for the polyfill
-  // because custom elements are not upgraded during clone()
-  @Experimental
-  static Stream<DocumentFragment> get instanceCreated {
-    if (_instanceCreated == null) {
-      _instanceCreated = new StreamController<DocumentFragment>(sync: true);
-    }
-    return _instanceCreated.stream;
-  }
+  static Function mdvPackage = (node) {
+    throw new UnsupportedError("The MDV package is not available. "
+        "You can enable it with `import 'package:mdv/mdv.dart' as mdv;` and "
+        "`mdv.initialize()`");
+  };
 
   /**
    * Ensures proper API and content model for template elements.
@@ -21096,30 +21010,111 @@
     // == true check because it starts as a null field.
     if (template._templateIsDecorated == true) return false;
 
-    template._templateIsDecorated = true;
-
     _injectStylesheet();
 
-    // Create content
-    if (template is! TemplateElement) {
-      var doc = _Bindings._getTemplateContentsOwner(template.document);
-      template._templateContent = doc.createDocumentFragment();
+    var templateElement = template;
+    var isNative = templateElement is TemplateElement;
+    var bootstrapContents = isNative;
+    var liftContents = !isNative;
+    var liftRoot = false;
+
+    if (!isNative && templateElement._isAttributeTemplate) {
+      if (instanceRef != null) {
+        // TODO(jmesserly): this is just an assert in MDV.
+        throw new ArgumentError('instanceRef should not be supplied for '
+            'attribute templates.');
+      }
+      templateElement = _extractTemplateFromAttributeTemplate(template);
+      isNative = templateElement is TemplateElement;
+      liftRoot = true;
+     }
+
+    templateElement._templateIsDecorated = true;
+
+    if (!isNative) {
+      var doc = _getTemplateContentsOwner(templateElement.document);
+      templateElement._templateContent = doc.createDocumentFragment();
     }
 
     if (instanceRef != null) {
-      template._templateInstanceRef = instanceRef;
-      return true; // content is empty.
-    }
-
-    if (template is TemplateElement) {
-      bootstrap(template.content);
-    } else {
-      _Bindings._liftNonNativeChildrenIntoContent(template);
+      // template is contained within an instance, its direct content must be
+      // empty
+      templateElement._templateInstanceRef = instanceRef;
+    } else if (liftContents) {
+      _liftNonNativeChildrenIntoContent(templateElement, template, liftRoot);
+    } else if (bootstrapContents) {
+      bootstrap(templateElement.content);
     }
 
     return true;
   }
 
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  static Document _getTemplateContentsOwner(HtmlDocument doc) {
+    if (doc.window == null) {
+      return doc;
+    }
+    var d = doc._templateContentsOwner;
+    if (d == null) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHtmlDocument('');
+      while (d.lastChild != null) {
+        d.lastChild.remove();
+      }
+      doc._templateContentsOwner = d;
+    }
+    return d;
+  }
+
+  // For non-template browsers, the parser will disallow <template> in certain
+  // locations, so we allow "attribute templates" which combine the template
+  // element with the top-level container node of the content, e.g.
+  //
+  //   <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
+  //
+  // becomes
+  //
+  //   <template repeat="{{ foo }}">
+  //   + #document-fragment
+  //     + <tr class="bar">
+  //       + <td>Bar</td>
+  //
+  static Element _extractTemplateFromAttributeTemplate(Element el) {
+    var template = el.document.$dom_createElement('template');
+    el.parentNode.insertBefore(template, el);
+
+    for (var name in el.attributes.keys.toList()) {
+      switch (name) {
+        case 'template':
+          el.attributes.remove(name);
+          break;
+        case 'repeat':
+        case 'bind':
+        case 'ref':
+          template.attributes[name] = el.attributes.remove(name);
+          break;
+      }
+    }
+
+    return template;
+  }
+
+  static void _liftNonNativeChildrenIntoContent(Element template, Element el,
+      bool useRoot) {
+
+    var content = template.content;
+    if (useRoot) {
+      content.append(el);
+      return;
+    }
+
+    var child;
+    while ((child = el.firstChild) != null) {
+      content.append(child);
+    }
+  }
+
   /**
    * This used to decorate recursively all templates from a given node.
    *
@@ -21130,24 +21125,26 @@
   // TODO(rafaelw): Review whether this is the right public API.
   @Experimental
   static void bootstrap(Node content) {
-    _Bindings._bootstrapTemplatesRecursivelyFrom(content);
+    void _bootstrap(template) {
+      if (!TemplateElement.decorate(template)) {
+        bootstrap(template.content);
+      }
+    }
+
+    // Need to do this first as the contents may get lifted if |node| is
+    // template.
+    // TODO(jmesserly): content is DocumentFragment or Element
+    var descendents = (content as dynamic).queryAll(_allTemplatesSelectors);
+    if (content is Element && (content as Element).isTemplate) {
+      _bootstrap(content);
+    }
+
+    descendents.forEach(_bootstrap);
   }
 
-  /**
-   * Binds all mustaches recursively starting from the [root] node.
-   *
-   * Note: this is not an official Model-Driven-Views API; it is intended to
-   * support binding the [ShadowRoot]'s content to a model.
-   */
-  // TODO(jmesserly): this is needed to avoid two <template> nodes when using
-  // bindings in a custom element's template. See also:
-  // https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
-  // Called from:
-  // https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
-  @Experimental
-  static void bindModel(Node root, model, [CustomBindingSyntax syntax]) {
-    _Bindings._addBindings(root, model, syntax);
-  }
+  static final String _allTemplatesSelectors =
+      'template, option[template], optgroup[template], ' +
+      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
 
   static bool _initStyles;
 
@@ -21205,42 +21202,6 @@
   @DocsEditable
   Text splitText(int offset) native;
 
-
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-  StreamSubscription _textBinding;
-
-  @Experimental
-  void bind(String name, model, String path) {
-    if (name != 'text') {
-      super.bind(name, model, path);
-      return;
-    }
-
-    unbind('text');
-
-    _textBinding = new PathObserver(model, path).bindSync((value) {
-      text = value == null ? '' : '$value';
-    });
-  }
-
-  @Experimental
-  void unbind(String name) {
-    if (name != 'text') {
-      super.unbind(name);
-      return;
-    }
-
-    if (_textBinding == null) return;
-
-    _textBinding.cancel();
-    _textBinding = null;
-  }
-
-  @Experimental
-  void unbindAll() {
-    unbind('text');
-    super.unbindAll();
-  }
 }
 // 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
@@ -27706,794 +27667,6 @@
   Point get bottomRight => new Point(this.left + this.width,
       this.top + this.height);
 }
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-
-// This code is a port of Model-Driven-Views:
-// https://github.com/polymer-project/mdv
-// The code mostly comes from src/template_element.js
-
-typedef void _ChangeHandler(value);
-
-/**
- * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
- * but (by design) don't attempt to implement a wide array of specialized
- * behaviors.
- *
- * Enabling these features in MDV is a matter of implementing and registering an
- * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
- * delegation functions which implement specialized behavior. This object is
- * registered with MDV via [TemplateElement.syntax]:
- *
- *
- * HTML:
- *     <template bind syntax="MySyntax">
- *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
- *     </template>
- *
- * Dart:
- *     class MySyntax extends CustomBindingSyntax {
- *       getBinding(model, path, name, node) {
- *         // The magic happens here!
- *       }
- *     }
- *
- *     ...
- *
- *     TemplateElement.syntax['MySyntax'] = new MySyntax();
- *
- * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for more
- * information about Custom Syntax.
- */
-// TODO(jmesserly): if this is just one method, a function type would make it
-// more Dart-friendly.
-@Experimental
-abstract class CustomBindingSyntax {
-  /**
-   * This syntax method allows for a custom interpretation of the contents of
-   * mustaches (`{{` ... `}}`).
-   *
-   * When a template is inserting an instance, it will invoke this method for
-   * each mustache which is encountered. The function is invoked with four
-   * arguments:
-   *
-   * - [model]: The data context for which this instance is being created.
-   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
-   * - [name]: The context in which the mustache occurs. Within element
-   *   attributes, this will be the name of the attribute. Within text,
-   *   this will be 'text'.
-   * - [node]: A reference to the node to which this binding will be created.
-   *
-   * If the method wishes to handle binding, it is required to return an object
-   * which has at least a `value` property that can be observed. If it does,
-   * then MDV will call [Node.bind on the node:
-   *
-   *     node.bind(name, retval, 'value');
-   *
-   * If the 'getBinding' does not wish to override the binding, it should return
-   * null.
-   */
-  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
-  // Normally they are String and Node respectively. But sometimes it will pass
-  // (int name, CompoundBinding node). That seems very confusing; we may want
-  // to change this API.
-  getBinding(model, String path, name, node) => null;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate model than the
-   * one the template would otherwise use when producing an instance.
-   *
-   * When a template is about to create an instance, it will invoke this method
-   * The function is invoked with two arguments:
-   *
-   * - [template]: The template element which is about to create and insert an
-   *   instance.
-   * - [model]: The data context for which this instance is being created.
-   *
-   * The template element will always use the return value of `getInstanceModel`
-   * as the model for the new instance. If the syntax does not wish to override
-   * the value, it should simply return the `model` value it was passed.
-   */
-  getInstanceModel(Element template, model) => model;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate expansion of
-   * the [template] contents. When the template wants to create an instance,
-   * it will call this method with the template element.
-   *
-   * By default this will call `template.createInstance()`.
-   */
-  getInstanceFragment(Element template) => template.createInstance();
-}
-
-/** The callback used in the [CompoundBinding.combinator] field. */
-@Experimental
-typedef Object CompoundBindingCombinator(Map objects);
-
-/** Information about the instantiated template. */
-@Experimental
-class TemplateInstance {
-  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
-  // in cases where script has modified the template instance boundary.
-
-  /** The first node of this template instantiation. */
-  final Node firstNode;
-
-  /**
-   * The last node of this template instantiation.
-   * This could be identical to [firstNode] if the template only expanded to a
-   * single node.
-   */
-  final Node lastNode;
-
-  /** The model used to instantiate the template. */
-  final model;
-
-  TemplateInstance(this.firstNode, this.lastNode, this.model);
-}
-
-/**
- * Model-Driven Views contains a helper object which is useful for the
- * implementation of a Custom Syntax.
- *
- *     var binding = new CompoundBinding((values) {
- *       var combinedValue;
- *       // compute combinedValue based on the current values which are provided
- *       return combinedValue;
- *     });
- *     binding.bind('name1', obj1, path1);
- *     binding.bind('name2', obj2, path2);
- *     //...
- *     binding.bind('nameN', objN, pathN);
- *
- * CompoundBinding is an object which knows how to listen to multiple path
- * values (registered via [bind]) and invoke its [combinator] when one or more
- * of the values have changed and set its [value] property to the return value
- * of the function. When any value has changed, all current values are provided
- * to the [combinator] in the single `values` argument.
- *
- * See [CustomBindingSyntax] for more information.
- */
-// TODO(jmesserly): what is the public API surface here? I just guessed;
-// most of it seemed non-public.
-@Experimental
-class CompoundBinding extends ObservableBase {
-  CompoundBindingCombinator _combinator;
-
-  // TODO(jmesserly): ideally these would be String keys, but sometimes we
-  // use integers.
-  Map<dynamic, StreamSubscription> _bindings = new Map();
-  Map _values = new Map();
-  bool _scheduled = false;
-  bool _disposed = false;
-  Object _value;
-
-  CompoundBinding([CompoundBindingCombinator combinator]) {
-    // TODO(jmesserly): this is a tweak to the original code, it seemed to me
-    // that passing the combinator to the constructor should be equivalent to
-    // setting it via the property.
-    // I also added a null check to the combinator setter.
-    this.combinator = combinator;
-  }
-
-  CompoundBindingCombinator get combinator => _combinator;
-
-  set combinator(CompoundBindingCombinator combinator) {
-    _combinator = combinator;
-    if (combinator != null) _scheduleResolve();
-  }
-
-  static const _VALUE = const Symbol('value');
-
-  get value => _value;
-
-  void set value(newValue) {
-    _value = notifyPropertyChange(_VALUE, _value, newValue);
-  }
-
-  // TODO(jmesserly): remove these workarounds when dart2js supports mirrors!
-  getValueWorkaround(key) {
-    if (key == _VALUE) return value;
-    return null;
-  }
-  setValueWorkaround(key, val) {
-    if (key == _VALUE) value = val;
-  }
-
-  void bind(name, model, String path) {
-    unbind(name);
-
-    _bindings[name] = new PathObserver(model, path).bindSync((value) {
-      _values[name] = value;
-      _scheduleResolve();
-    });
-  }
-
-  void unbind(name, {bool suppressResolve: false}) {
-    var binding = _bindings.remove(name);
-    if (binding == null) return;
-
-    binding.cancel();
-    _values.remove(name);
-    if (!suppressResolve) _scheduleResolve();
-  }
-
-  // TODO(rafaelw): Is this the right processing model?
-  // TODO(rafaelw): Consider having a seperate ChangeSummary for
-  // CompoundBindings so to excess dirtyChecks.
-  void _scheduleResolve() {
-    if (_scheduled) return;
-    _scheduled = true;
-    queueChangeRecords(resolve);
-  }
-
-  void resolve() {
-    if (_disposed) return;
-    _scheduled = false;
-
-    if (_combinator == null) {
-      throw new StateError(
-          'CompoundBinding attempted to resolve without a combinator');
-    }
-
-    value = _combinator(_values);
-  }
-
-  void dispose() {
-    for (var binding in _bindings.values) {
-      binding.cancel();
-    }
-    _bindings.clear();
-    _values.clear();
-
-    _disposed = true;
-    value = null;
-  }
-}
-
-abstract class _InputBinding {
-  final InputElement element;
-  PathObserver binding;
-  StreamSubscription _pathSub;
-  StreamSubscription _eventSub;
-
-  _InputBinding(this.element, model, String path) {
-    binding = new PathObserver(model, path);
-    _pathSub = binding.bindSync(valueChanged);
-    _eventSub = _getStreamForInputType(element).listen(updateBinding);
-  }
-
-  void valueChanged(newValue);
-
-  void updateBinding(e);
-
-  void unbind() {
-    binding = null;
-    _pathSub.cancel();
-    _eventSub.cancel();
-  }
-
-
-  static Stream<Event> _getStreamForInputType(InputElement element) {
-    switch (element.type) {
-      case 'checkbox':
-        return element.onClick;
-      case 'radio':
-      case 'select-multiple':
-      case 'select-one':
-        return element.onChange;
-      default:
-        return element.onInput;
-    }
-  }
-}
-
-class _ValueBinding extends _InputBinding {
-  _ValueBinding(element, model, path) : super(element, model, path);
-
-  void valueChanged(value) {
-    element.value = value == null ? '' : '$value';
-  }
-
-  void updateBinding(e) {
-    binding.value = element.value;
-  }
-}
-
-class _CheckedBinding extends _InputBinding {
-  _CheckedBinding(element, model, path) : super(element, model, path);
-
-  void valueChanged(value) {
-    element.checked = _Bindings._toBoolean(value);
-  }
-
-  void updateBinding(e) {
-    binding.value = element.checked;
-
-    // Only the radio button that is getting checked gets an event. We
-    // therefore find all the associated radio buttons and update their
-    // CheckedBinding manually.
-    if (element is InputElement && element.type == 'radio') {
-      for (var r in _getAssociatedRadioButtons(element)) {
-        var checkedBinding = r._checkedBinding;
-        if (checkedBinding != null) {
-          // Set the value directly to avoid an infinite call stack.
-          checkedBinding.binding.value = false;
-        }
-      }
-    }
-  }
-
-  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
-  // Returns an array containing all radio buttons other than |element| that
-  // have the same |name|, either in the form that |element| belongs to or,
-  // if no form, in the document tree to which |element| belongs.
-  //
-  // This implementation is based upon the HTML spec definition of a
-  // "radio button group":
-  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
-  //
-  static Iterable _getAssociatedRadioButtons(element) {
-    if (!_isNodeInDocument(element)) return [];
-    if (element.form != null) {
-      return element.form.nodes.where((el) {
-        return el != element &&
-            el is InputElement &&
-            el.type == 'radio' &&
-            el.name == element.name;
-      });
-    } else {
-      var radios = element.document.queryAll(
-          'input[type="radio"][name="${element.name}"]');
-      return radios.where((el) => el != element && el.form == null);
-    }
-  }
-
-  // TODO(jmesserly): polyfill document.contains API instead of doing it here
-  static bool _isNodeInDocument(Node node) {
-    // On non-IE this works:
-    // return node.document.contains(node);
-    var document = node.document;
-    if (node == document || node.parentNode == document) return true;
-    return document.documentElement.contains(node);
-  }
-}
-
-class _Bindings {
-  // TODO(jmesserly): not sure what kind of boolean conversion rules to
-  // apply for template data-binding. HTML attributes are true if they're
-  // present. However Dart only treats "true" as true. Since this is HTML we'll
-  // use something closer to the HTML rules: null (missing) and false are false,
-  // everything else is true. See: https://github.com/polymer-project/mdv/issues/59
-  static bool _toBoolean(value) => null != value && false != value;
-
-  static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
-    var clone = node.clone(false); // Shallow clone.
-    if (clone is Element && clone.isTemplate) {
-      TemplateElement.decorate(clone, node);
-      if (syntax != null) {
-        clone.attributes.putIfAbsent('syntax', () => syntax);
-      }
-    }
-
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
-    }
-    return clone;
-  }
-
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(HtmlDocument doc) {
-    if (doc.window == null) {
-      return doc;
-    }
-    var d = doc._templateContentsOwner;
-    if (d == null) {
-      // TODO(arv): This should either be a Document or HTMLDocument depending
-      // on doc.
-      d = doc.implementation.createHtmlDocument('');
-      while (d.$dom_lastChild != null) {
-        d.$dom_lastChild.remove();
-      }
-      doc._templateContentsOwner = d;
-    }
-    return d;
-  }
-
-  static Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
-    var clone = templateElement.clone(false);
-    var attributes = templateElement.attributes;
-    for (var name in attributes.keys.toList()) {
-      switch (name) {
-        case 'template':
-        case 'repeat':
-        case 'bind':
-        case 'ref':
-          clone.attributes.remove(name);
-          break;
-        default:
-          attributes.remove(name);
-          break;
-      }
-    }
-
-    return clone;
-  }
-
-  static void _liftNonNativeChildrenIntoContent(Element templateElement) {
-    var content = templateElement.content;
-
-    if (!templateElement._isAttributeTemplate) {
-      var child;
-      while ((child = templateElement.$dom_firstChild) != null) {
-        content.append(child);
-      }
-      return;
-    }
-
-    // For attribute templates we copy the whole thing into the content and
-    // we move the non template attributes into the content.
-    //
-    //   <tr foo template>
-    //
-    // becomes
-    //
-    //   <tr template>
-    //   + #document-fragment
-    //     + <tr foo>
-    //
-    var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
-    var child;
-    while ((child = templateElement.$dom_firstChild) != null) {
-      newRoot.append(child);
-    }
-    content.append(newRoot);
-  }
-
-  static void _bootstrapTemplatesRecursivelyFrom(Node node) {
-    void bootstrap(template) {
-      if (!TemplateElement.decorate(template)) {
-        _bootstrapTemplatesRecursivelyFrom(template.content);
-      }
-    }
-
-    // Need to do this first as the contents may get lifted if |node| is
-    // template.
-    // TODO(jmesserly): node is DocumentFragment or Element
-    var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-    if (node is Element && (node as Element).isTemplate) bootstrap(node);
-
-    descendents.forEach(bootstrap);
-  }
-
-  static final String _allTemplatesSelectors = 'template, option[template], ' +
-      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-  static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
-    if (node is Element) {
-      _addAttributeBindings(node, model, syntax);
-    } else if (node is Text) {
-      _parseAndBind(node, 'text', node.text, model, syntax);
-    }
-
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      _addBindings(c, model, syntax);
-    }
-  }
-
-  static void _addAttributeBindings(Element element, model, syntax) {
-    element.attributes.forEach((name, value) {
-      if (value == '' && (name == 'bind' || name == 'repeat')) {
-        value = '{{}}';
-      }
-      _parseAndBind(element, name, value, model, syntax);
-    });
-  }
-
-  static void _parseAndBind(Node node, String name, String text, model,
-      CustomBindingSyntax syntax) {
-
-    var tokens = _parseMustacheTokens(text);
-    if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
-      return;
-    }
-
-    // If this is a custom element, give the .xtag a change to bind.
-    node = _nodeOrCustom(node);
-
-    if (tokens.length == 1 && tokens[0].isBinding) {
-      _bindOrDelegate(node, name, model, tokens[0].value, syntax);
-      return;
-    }
-
-    var replacementBinding = new CompoundBinding();
-    for (var i = 0; i < tokens.length; i++) {
-      var token = tokens[i];
-      if (token.isBinding) {
-        _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
-      }
-    }
-
-    replacementBinding.combinator = (values) {
-      var newValue = new StringBuffer();
-
-      for (var i = 0; i < tokens.length; i++) {
-        var token = tokens[i];
-        if (token.isText) {
-          newValue.write(token.value);
-        } else {
-          var value = values[i];
-          if (value != null) {
-            newValue.write(value);
-          }
-        }
-      }
-
-      return newValue.toString();
-    };
-
-    node.bind(name, replacementBinding, 'value');
-  }
-
-  static void _bindOrDelegate(node, name, model, String path,
-      CustomBindingSyntax syntax) {
-
-    if (syntax != null) {
-      var delegateBinding = syntax.getBinding(model, path, name, node);
-      if (delegateBinding != null) {
-        model = delegateBinding;
-        path = 'value';
-      }
-    }
-
-    node.bind(name, model, path);
-  }
-
-  /**
-   * Gets the [node]'s custom [Element.xtag] if present, otherwise returns
-   * the node. This is used so nodes can override [Node.bind], [Node.unbind],
-   * and [Node.unbindAll] like InputElement does.
-   */
-  // TODO(jmesserly): remove this when we can extend Element for real.
-  static _nodeOrCustom(node) => node is Element ? node.xtag : node;
-
-  static List<_BindingToken> _parseMustacheTokens(String s) {
-    var result = [];
-    var length = s.length;
-    var index = 0, lastIndex = 0;
-    while (lastIndex < length) {
-      index = s.indexOf('{{', lastIndex);
-      if (index < 0) {
-        result.add(new _BindingToken(s.substring(lastIndex)));
-        break;
-      } else {
-        // There is a non-empty text run before the next path token.
-        if (index > 0 && lastIndex < index) {
-          result.add(new _BindingToken(s.substring(lastIndex, index)));
-        }
-        lastIndex = index + 2;
-        index = s.indexOf('}}', lastIndex);
-        if (index < 0) {
-          var text = s.substring(lastIndex - 2);
-          if (result.length > 0 && result.last.isText) {
-            result.last.value += text;
-          } else {
-            result.add(new _BindingToken(text));
-          }
-          break;
-        }
-
-        var value = s.substring(lastIndex, index).trim();
-        result.add(new _BindingToken(value, isBinding: true));
-        lastIndex = index + 2;
-      }
-    }
-    return result;
-  }
-
-  static void _addTemplateInstanceRecord(fragment, model) {
-    if (fragment.$dom_firstChild == null) {
-      return;
-    }
-
-    var instanceRecord = new TemplateInstance(
-        fragment.$dom_firstChild, fragment.$dom_lastChild, model);
-
-    var node = instanceRecord.firstNode;
-    while (node != null) {
-      node._templateInstance = instanceRecord;
-      node = node.nextNode;
-    }
-  }
-
-  static void _removeAllBindingsRecursively(Node node) {
-    _nodeOrCustom(node).unbindAll();
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      _removeAllBindingsRecursively(c);
-    }
-  }
-
-  static void _removeChild(Node parent, Node child) {
-    child._templateInstance = null;
-    if (child is Element && (child as Element).isTemplate) {
-      Element childElement = child;
-      // Make sure we stop observing when we remove an element.
-      var templateIterator = childElement._templateIterator;
-      if (templateIterator != null) {
-        templateIterator.abandon();
-        childElement._templateIterator = null;
-      }
-    }
-    child.remove();
-    _removeAllBindingsRecursively(child);
-  }
-}
-
-class _BindingToken {
-  final String value;
-  final bool isBinding;
-
-  _BindingToken(this.value, {this.isBinding: false});
-
-  bool get isText => !isBinding;
-}
-
-class _TemplateIterator {
-  final Element _templateElement;
-  final List<Node> terminators = [];
-  final CompoundBinding inputs;
-  List iteratedValue;
-
-  StreamSubscription _sub;
-  StreamSubscription _valueBinding;
-
-  _TemplateIterator(this._templateElement)
-    : inputs = new CompoundBinding(resolveInputs) {
-
-    _valueBinding = new PathObserver(inputs, 'value').bindSync(valueChanged);
-  }
-
-  static Object resolveInputs(Map values) {
-    if (values.containsKey('if') && !_Bindings._toBoolean(values['if'])) {
-      return null;
-    }
-
-    if (values.containsKey('repeat')) {
-      return values['repeat'];
-    }
-
-    if (values.containsKey('bind')) {
-      return [values['bind']];
-    }
-
-    return null;
-  }
-
-  void valueChanged(value) {
-    clear();
-    if (value is! List) return;
-
-    iteratedValue = value;
-
-    if (value is Observable) {
-      _sub = value.changes.listen(_handleChanges);
-    }
-
-    int len = iteratedValue.length;
-    if (len > 0) {
-      _handleChanges([new ListChangeRecord(0, addedCount: len)]);
-    }
-  }
-
-  Node getTerminatorAt(int index) {
-    if (index == -1) return _templateElement;
-    var terminator = terminators[index];
-    if (terminator is! Element) return terminator;
-
-    var subIterator = terminator._templateIterator;
-    if (subIterator == null) return terminator;
-
-    return subIterator.getTerminatorAt(subIterator.terminators.length - 1);
-  }
-
-  void insertInstanceAt(int index, Node fragment) {
-    var previousTerminator = getTerminatorAt(index - 1);
-    var terminator = fragment.$dom_lastChild;
-    if (terminator == null) terminator = previousTerminator;
-
-    terminators.insert(index, terminator);
-    var parent = _templateElement.parentNode;
-    parent.insertBefore(fragment, previousTerminator.nextNode);
-  }
-
-  void removeInstanceAt(int index) {
-    var previousTerminator = getTerminatorAt(index - 1);
-    var terminator = getTerminatorAt(index);
-    terminators.removeAt(index);
-
-    var parent = _templateElement.parentNode;
-    while (terminator != previousTerminator) {
-      var node = terminator;
-      terminator = node.previousNode;
-      _Bindings._removeChild(parent, node);
-    }
-  }
-
-  void removeAllInstances() {
-    if (terminators.length == 0) return;
-
-    var previousTerminator = _templateElement;
-    var terminator = getTerminatorAt(terminators.length - 1);
-    terminators.length = 0;
-
-    var parent = _templateElement.parentNode;
-    while (terminator != previousTerminator) {
-      var node = terminator;
-      terminator = node.previousNode;
-      _Bindings._removeChild(parent, node);
-    }
-  }
-
-  void clear() {
-    unobserve();
-    removeAllInstances();
-    iteratedValue = null;
-  }
-
-  getInstanceModel(model, syntax) {
-    if (syntax != null) {
-      return syntax.getInstanceModel(_templateElement, model);
-    }
-    return model;
-  }
-
-  getInstanceFragment(syntax) {
-    if (syntax != null) {
-      return syntax.getInstanceFragment(_templateElement);
-    }
-    return _templateElement.createInstance();
-  }
-
-  void _handleChanges(List<ListChangeRecord> splices) {
-    var syntax = TemplateElement.syntax[_templateElement.attributes['syntax']];
-
-    for (var splice in splices) {
-      if (splice is! ListChangeRecord) continue;
-
-      for (int i = 0; i < splice.removedCount; i++) {
-        removeInstanceAt(splice.index);
-      }
-
-      for (var addIndex = splice.index;
-          addIndex < splice.index + splice.addedCount;
-          addIndex++) {
-
-        var model = getInstanceModel(iteratedValue[addIndex], syntax);
-
-        var fragment = getInstanceFragment(syntax);
-
-        _Bindings._addBindings(fragment, model, syntax);
-        _Bindings._addTemplateInstanceRecord(fragment, model);
-
-        insertInstanceAt(addIndex, fragment);
-      }
-    }
-  }
-
-  void unobserve() {
-    if (_sub == null) return;
-    _sub.cancel();
-    _sub = null;
-  }
-
-  void abandon() {
-    unobserve();
-    _valueBinding.cancel();
-    inputs.dispose();
-  }
-}
 // 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.
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 0e28ef6..c31f588 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -14,7 +14,6 @@
 import 'dart:json' as json;
 import 'dart:math';
 import 'dart:nativewrappers';
-import 'dart:mdv_observe_impl';
 import 'dart:typed_data';
 import 'dart:web_gl' as gl;
 import 'dart:web_sql';
@@ -8698,18 +8697,6 @@
   }
 
 
-  Map<String, StreamSubscription> _attributeBindings;
-
-  // TODO(jmesserly): I'm concerned about adding these to every element.
-  // Conceptually all of these belong on TemplateElement. They are here to
-  // support browsers that don't have <template> yet.
-  // However even in the polyfill they're restricted to certain tags
-  // (see [isTemplate]). So we can probably convert it to a (public) mixin, and
-  // only mix it in to the elements that need it.
-  var _model;
-
-  _TemplateIterator _templateIterator;
-
   Element _templateInstanceRef;
 
   // Note: only used if `this is! TemplateElement`
@@ -8717,124 +8704,6 @@
 
   bool _templateIsDecorated;
 
-  // TODO(jmesserly): should path be optional, and default to empty path?
-  // It is used that way in at least one path in JS TemplateElement tests
-  // (see "BindImperative" test in original JS code).
-  @Experimental
-  void bind(String name, model, String path) {
-    _bindElement(this, name, model, path);
-  }
-
-  // TODO(jmesserly): this is static to work around http://dartbug.com/10166
-  // Similar issue for unbind/unbindAll below.
-  static void _bindElement(Element self, String name, model, String path) {
-    if (self._bindTemplate(name, model, path)) return;
-
-    if (self._attributeBindings == null) {
-      self._attributeBindings = new Map<String, StreamSubscription>();
-    }
-
-    self.xtag.attributes.remove(name);
-
-    var changed;
-    if (name.endsWith('?')) {
-      name = name.substring(0, name.length - 1);
-
-      changed = (value) {
-        if (_Bindings._toBoolean(value)) {
-          self.xtag.attributes[name] = '';
-        } else {
-          self.xtag.attributes.remove(name);
-        }
-      };
-    } else {
-      changed = (value) {
-        // TODO(jmesserly): escape value if needed to protect against XSS.
-        // See https://github.com/polymer-project/mdv/issues/58
-        self.xtag.attributes[name] = value == null ? '' : '$value';
-      };
-    }
-
-    self.unbind(name);
-
-    self._attributeBindings[name] =
-        new PathObserver(model, path).bindSync(changed);
-  }
-
-  @Experimental
-  void unbind(String name) {
-    _unbindElement(this, name);
-  }
-
-  static _unbindElement(Element self, String name) {
-    if (self._unbindTemplate(name)) return;
-    if (self._attributeBindings != null) {
-      var binding = self._attributeBindings.remove(name);
-      if (binding != null) binding.cancel();
-    }
-  }
-
-  @Experimental
-  void unbindAll() {
-    _unbindAllElement(this);
-  }
-
-  static void _unbindAllElement(Element self) {
-    self._unbindAllTemplate();
-
-    if (self._attributeBindings != null) {
-      for (var binding in self._attributeBindings.values) {
-        binding.cancel();
-      }
-      self._attributeBindings = null;
-    }
-  }
-
-  // TODO(jmesserly): unlike the JS polyfill, we can't mixin
-  // HTMLTemplateElement at runtime into things that are semantically template
-  // elements. So instead we implement it here with a runtime check.
-  // If the bind succeeds, we return true, otherwise we return false and let
-  // the normal Element.bind logic kick in.
-  bool _bindTemplate(String name, model, String path) {
-    if (isTemplate) {
-      switch (name) {
-        case 'bind':
-        case 'repeat':
-        case 'if':
-          _ensureTemplate();
-          if (_templateIterator == null) {
-            _templateIterator = new _TemplateIterator(this);
-          }
-          _templateIterator.inputs.bind(name, model, path);
-          return true;
-      }
-    }
-    return false;
-  }
-
-  bool _unbindTemplate(String name) {
-    if (isTemplate) {
-      switch (name) {
-        case 'bind':
-        case 'repeat':
-        case 'if':
-          _ensureTemplate();
-          if (_templateIterator != null) {
-            _templateIterator.inputs.unbind(name);
-          }
-          return true;
-      }
-    }
-    return false;
-  }
-
-  void _unbindAllTemplate() {
-    if (isTemplate) {
-      unbind('bind');
-      unbind('repeat');
-      unbind('if');
-    }
-  }
 
   /**
    * Gets the template this node refers to.
@@ -8847,7 +8716,19 @@
     Element ref = null;
     var refId = attributes['ref'];
     if (refId != null) {
-      ref = document.getElementById(refId);
+      var treeScope = this;
+      while (treeScope.parentNode != null) {
+        treeScope = treeScope.parentNode;
+      }
+
+      // Note: JS code tests that getElementById is present. We can't do that
+      // easily, so instead check for the types known to implement it.
+      if (treeScope is Document ||
+          treeScope is ShadowRoot ||
+          treeScope is svg.SvgSvgElement) {
+
+        ref = treeScope.getElementById(refId);
+      }
     }
 
     return ref != null ? ref : _templateInstanceRef;
@@ -8870,38 +8751,20 @@
   @Experimental
   DocumentFragment createInstance() {
     _ensureTemplate();
-
-    var template = ref;
-    if (template == null) template = this;
-
-    var instance = _Bindings._createDeepCloneAndDecorateTemplates(
-        template.content, attributes['syntax']);
-
-    if (TemplateElement._instanceCreated != null) {
-      TemplateElement._instanceCreated.add(instance);
-    }
-    return instance;
+    return TemplateElement.mdvPackage(this).createInstance();
   }
 
   /**
    * The data model which is inherited through the tree.
    * This is only supported if [isTemplate] is true.
-   *
-   * Setting this will destructive propagate the value to all descendant nodes,
-   * and reinstantiate all of the nodes expanded by this template.
-   *
-   * Currently this does not support propagation through Shadow DOMs.
    */
   @Experimental
-  get model => _model;
+  get model => TemplateElement.mdvPackage(this).model;
 
   @Experimental
   void set model(value) {
     _ensureTemplate();
-
-    var syntax = TemplateElement.syntax[attributes['syntax']];
-    _model = value;
-    _Bindings._addBindings(this, model, syntax);
+    TemplateElement.mdvPackage(this).model = value;
   }
 
   // TODO(jmesserly): const set would be better
@@ -8918,7 +8781,8 @@
   };
 
   bool get _isAttributeTemplate => attributes.containsKey('template') &&
-      (localName == 'option' || _TABLE_TAGS.containsKey(localName));
+      (localName == 'option' || localName == 'optgroup' ||
+       _TABLE_TAGS.containsKey(localName));
 
   /**
    * Returns true if this node is a template.
@@ -8927,7 +8791,7 @@
    * 'template' attribute and this tag supports attribute form for backwards
    * compatibility with existing HTML parsers. The nodes that can use attribute
    * form are table elments (THEAD, TBODY, TFOOT, TH, TR, TD, CAPTION, COLGROUP
-   * and COL) and OPTION.
+   * and COL), OPTION, and OPTGROUP.
    */
   // TODO(jmesserly): this is not a public MDV API, but it seems like a useful
   // place to document which tags our polyfill considers to be templates.
@@ -13170,59 +13034,6 @@
     return e;
   }
 
-  _ValueBinding _valueBinding;
-
-  _CheckedBinding _checkedBinding;
-
-  @Experimental
-  void bind(String name, model, String path) {
-    switch (name) {
-      case 'value':
-        unbind('value');
-        attributes.remove('value');
-        _valueBinding = new _ValueBinding(this, model, path);
-        break;
-      case 'checked':
-        unbind('checked');
-        attributes.remove('checked');
-        _checkedBinding = new _CheckedBinding(this, model, path);
-        break;
-      default:
-        // TODO(jmesserly): this should be "super" (http://dartbug.com/10166).
-        // Similar issue for unbind/unbindAll below.
-        Element._bindElement(this, name, model, path);
-        break;
-    }
-  }
-
-  @Experimental
-  void unbind(String name) {
-    switch (name) {
-      case 'value':
-        if (_valueBinding != null) {
-          _valueBinding.unbind();
-          _valueBinding = null;
-        }
-        break;
-      case 'checked':
-        if (_checkedBinding != null) {
-          _checkedBinding.unbind();
-          _checkedBinding = null;
-        }
-        break;
-      default:
-        Element._unbindElement(this, name);
-        break;
-    }
-  }
-
-  @Experimental
-  void unbindAll() {
-    unbind('value');
-    unbind('checked');
-    Element._unbindAllElement(this);
-  }
-
   InputElement.internal() : super.internal();
 
   @DomName('HTMLInputElement.webkitSpeechChangeEvent')
@@ -17527,12 +17338,12 @@
 
 
   Node get first {
-    Node result = _this.$dom_firstChild;
+    Node result = _this.firstChild;
     if (result == null) throw new StateError("No elements");
     return result;
   }
   Node get last {
-    Node result = _this.$dom_lastChild;
+    Node result = _this.lastChild;
     if (result == null) throw new StateError("No elements");
     return result;
   }
@@ -17540,7 +17351,7 @@
     int l = this.length;
     if (l == 0) throw new StateError("No elements");
     if (l > 1) throw new StateError("More than one element");
-    return _this.$dom_firstChild;
+    return _this.firstChild;
   }
 
   void add(Node value) {
@@ -17553,8 +17364,7 @@
       if (!identical(otherList._this, _this)) {
         // Optimized route for copying between nodes.
         for (var i = 0, len = otherList.length; i < len; ++i) {
-          // Should use $dom_firstChild, Bug 8886.
-          _this.append(otherList[0]);
+          _this.append(otherList._this.firstChild);
         }
       }
       return;
@@ -17612,7 +17422,7 @@
     // This implementation of removeWhere/retainWhere is more efficient
     // than the default in ListBase. Child nodes can be removed in constant
     // time.
-    Node child = _this.$dom_firstChild;
+    Node child = _this.firstChild;
     while (child != null) {
       Node nextChild = child.nextNode;
       if (test(child) == removeMatching) {
@@ -17671,6 +17481,27 @@
   Node operator[](int index) => _this.$dom_childNodes[index];
 }
 
+/** Information about the instantiated template. */
+class TemplateInstance {
+  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
+  // in cases where script has modified the template instance boundary.
+
+  /** The first node of this template instantiation. */
+  final Node firstNode;
+
+  /**
+   * The last node of this template instantiation.
+   * This could be identical to [firstNode] if the template only expanded to a
+   * single node.
+   */
+  final Node lastNode;
+
+  /** The model used to instantiate the template. */
+  final model;
+
+  TemplateInstance(this.firstNode, this.lastNode, this.model);
+}
+
 @DomName('Node')
 class Node extends EventTarget {
   List<Node> get nodes {
@@ -17730,8 +17561,7 @@
 
       // Optimized route for copying between nodes.
       for (var i = 0, len = otherList.length; i < len; ++i) {
-        // Should use $dom_firstChild, Bug 8886.
-        this.insertBefore(otherList[0], refChild);
+        this.insertBefore(otherList._this.firstChild, refChild);
       }
     } else {
       for (var node in newNodes) {
@@ -17751,26 +17581,25 @@
    */
   @Experimental
   void bind(String name, model, String path) {
-    // TODO(jmesserly): should we throw instead?
-    window.console.error('Unhandled binding to Node: '
-        '$this $name $model $path');
+    TemplateElement.mdvPackage(this).bind(name, model, path);
   }
 
   /** Unbinds the attribute [name]. */
   @Experimental
-  void unbind(String name) {}
+  void unbind(String name) {
+    TemplateElement.mdvPackage(this).unbind(name);
+  }
 
   /** Unbinds all bound attributes. */
   @Experimental
-  void unbindAll() {}
-
-  TemplateInstance _templateInstance;
+  void unbindAll() {
+    TemplateElement.mdvPackage(this).unbindAll();
+  }
 
   /** Gets the template instance that instantiated this node, if any. */
   @Experimental
   TemplateInstance get templateInstance =>
-      _templateInstance != null ? _templateInstance :
-      (parent != null ? parent.templateInstance : null);
+      TemplateElement.mdvPackage(this).templateInstance;
 
   Node.internal() : super.internal();
 
@@ -17828,11 +17657,11 @@
 
   @DomName('Node.firstChild')
   @DocsEditable
-  Node get $dom_firstChild native "Node_firstChild_Getter";
+  Node get firstChild native "Node_firstChild_Getter";
 
   @DomName('Node.lastChild')
   @DocsEditable
-  Node get $dom_lastChild native "Node_lastChild_Getter";
+  Node get lastChild native "Node_lastChild_Getter";
 
   @DomName('Node.localName')
   @DocsEditable
@@ -22727,6 +22556,99 @@
 // WARNING: Do not edit - generated code.
 
 
+
+/**
+ * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
+ * but (by design) don't attempt to implement a wide array of specialized
+ * behaviors.
+ *
+ * Enabling these features in MDV is a matter of implementing and registering an
+ * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
+ * delegation functions which implement specialized behavior. This object is
+ * registered with MDV via [TemplateElement.syntax]:
+ *
+ *
+ * HTML:
+ *     <template bind syntax="MySyntax">
+ *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
+ *     </template>
+ *
+ * Dart:
+ *     class MySyntax extends CustomBindingSyntax {
+ *       getBinding(model, path, name, node) {
+ *         // The magic happens here!
+ *       }
+ *     }
+ *
+ *     ...
+ *
+ *     TemplateElement.syntax['MySyntax'] = new MySyntax();
+ *
+ * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
+ * more information about Custom Syntax.
+ */
+// TODO(jmesserly): if this is just one method, a function type would make it
+// more Dart-friendly.
+@Experimental
+abstract class CustomBindingSyntax {
+  /**
+   * This syntax method allows for a custom interpretation of the contents of
+   * mustaches (`{{` ... `}}`).
+   *
+   * When a template is inserting an instance, it will invoke this method for
+   * each mustache which is encountered. The function is invoked with four
+   * arguments:
+   *
+   * - [model]: The data context for which this instance is being created.
+   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
+   * - [name]: The context in which the mustache occurs. Within element
+   *   attributes, this will be the name of the attribute. Within text,
+   *   this will be 'text'.
+   * - [node]: A reference to the node to which this binding will be created.
+   *
+   * If the method wishes to handle binding, it is required to return an object
+   * which has at least a `value` property that can be observed. If it does,
+   * then MDV will call [Node.bind on the node:
+   *
+   *     node.bind(name, retval, 'value');
+   *
+   * If the 'getBinding' does not wish to override the binding, it should return
+   * null.
+   */
+  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
+  // Normally they are String and Node respectively. But sometimes it will pass
+  // (int name, CompoundBinding node). That seems very confusing; we may want
+  // to change this API.
+  getBinding(model, String path, name, node) => null;
+
+  /**
+   * This syntax method allows a syntax to provide an alterate model than the
+   * one the template would otherwise use when producing an instance.
+   *
+   * When a template is about to create an instance, it will invoke this method
+   * The function is invoked with two arguments:
+   *
+   * - [template]: The template element which is about to create and insert an
+   *   instance.
+   * - [model]: The data context for which this instance is being created.
+   *
+   * The template element will always use the return value of `getInstanceModel`
+   * as the model for the new instance. If the syntax does not wish to override
+   * the value, it should simply return the `model` value it was passed.
+   */
+  getInstanceModel(Element template, model) => model;
+
+  /**
+   * This syntax method allows a syntax to provide an alterate expansion of
+   * the [template] contents. When the template wants to create an instance,
+   * it will call this method with the template element.
+   *
+   * By default this will call `template.createInstance()`.
+   */
+  getInstanceFragment(Element template) => template.createInstance();
+}
+
+
 @Experimental
 @DomName('HTMLTemplateElement')
 @SupportedBrowser(SupportedBrowser.CHROME)
@@ -22752,24 +22674,23 @@
   @Experimental
   DocumentFragment get content => $dom_content;
 
-  static StreamController<DocumentFragment> _instanceCreated;
 
   /**
-   * *Warning*: This is an implementation helper for Model-Driven Views and
-   * should not be used in your code.
+   * The MDV package, if available.
    *
-   * This event is fired whenever a template is instantiated via
-   * [createInstance].
+   * This can be used to initialize MDV support via:
+   *
+   *     import 'dart:html';
+   *     import 'package:mdv/mdv.dart' as mdv;
+   *     main() {
+   *       mdv.initialize();
+   *     }
    */
-  // TODO(rafaelw): This is a hack, and is neccesary for the polyfill
-  // because custom elements are not upgraded during clone()
-  @Experimental
-  static Stream<DocumentFragment> get instanceCreated {
-    if (_instanceCreated == null) {
-      _instanceCreated = new StreamController<DocumentFragment>(sync: true);
-    }
-    return _instanceCreated.stream;
-  }
+  static Function mdvPackage = (node) {
+    throw new UnsupportedError("The MDV package is not available. "
+        "You can enable it with `import 'package:mdv/mdv.dart' as mdv;` and "
+        "`mdv.initialize()`");
+  };
 
   /**
    * Ensures proper API and content model for template elements.
@@ -22786,30 +22707,111 @@
     // == true check because it starts as a null field.
     if (template._templateIsDecorated == true) return false;
 
-    template._templateIsDecorated = true;
-
     _injectStylesheet();
 
-    // Create content
-    if (template is! TemplateElement) {
-      var doc = _Bindings._getTemplateContentsOwner(template.document);
-      template._templateContent = doc.createDocumentFragment();
+    var templateElement = template;
+    var isNative = templateElement is TemplateElement;
+    var bootstrapContents = isNative;
+    var liftContents = !isNative;
+    var liftRoot = false;
+
+    if (!isNative && templateElement._isAttributeTemplate) {
+      if (instanceRef != null) {
+        // TODO(jmesserly): this is just an assert in MDV.
+        throw new ArgumentError('instanceRef should not be supplied for '
+            'attribute templates.');
+      }
+      templateElement = _extractTemplateFromAttributeTemplate(template);
+      isNative = templateElement is TemplateElement;
+      liftRoot = true;
+     }
+
+    templateElement._templateIsDecorated = true;
+
+    if (!isNative) {
+      var doc = _getTemplateContentsOwner(templateElement.document);
+      templateElement._templateContent = doc.createDocumentFragment();
     }
 
     if (instanceRef != null) {
-      template._templateInstanceRef = instanceRef;
-      return true; // content is empty.
-    }
-
-    if (template is TemplateElement) {
-      bootstrap(template.content);
-    } else {
-      _Bindings._liftNonNativeChildrenIntoContent(template);
+      // template is contained within an instance, its direct content must be
+      // empty
+      templateElement._templateInstanceRef = instanceRef;
+    } else if (liftContents) {
+      _liftNonNativeChildrenIntoContent(templateElement, template, liftRoot);
+    } else if (bootstrapContents) {
+      bootstrap(templateElement.content);
     }
 
     return true;
   }
 
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  static Document _getTemplateContentsOwner(HtmlDocument doc) {
+    if (doc.window == null) {
+      return doc;
+    }
+    var d = doc._templateContentsOwner;
+    if (d == null) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHtmlDocument('');
+      while (d.lastChild != null) {
+        d.lastChild.remove();
+      }
+      doc._templateContentsOwner = d;
+    }
+    return d;
+  }
+
+  // For non-template browsers, the parser will disallow <template> in certain
+  // locations, so we allow "attribute templates" which combine the template
+  // element with the top-level container node of the content, e.g.
+  //
+  //   <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
+  //
+  // becomes
+  //
+  //   <template repeat="{{ foo }}">
+  //   + #document-fragment
+  //     + <tr class="bar">
+  //       + <td>Bar</td>
+  //
+  static Element _extractTemplateFromAttributeTemplate(Element el) {
+    var template = el.document.$dom_createElement('template');
+    el.parentNode.insertBefore(template, el);
+
+    for (var name in el.attributes.keys.toList()) {
+      switch (name) {
+        case 'template':
+          el.attributes.remove(name);
+          break;
+        case 'repeat':
+        case 'bind':
+        case 'ref':
+          template.attributes[name] = el.attributes.remove(name);
+          break;
+      }
+    }
+
+    return template;
+  }
+
+  static void _liftNonNativeChildrenIntoContent(Element template, Element el,
+      bool useRoot) {
+
+    var content = template.content;
+    if (useRoot) {
+      content.append(el);
+      return;
+    }
+
+    var child;
+    while ((child = el.firstChild) != null) {
+      content.append(child);
+    }
+  }
+
   /**
    * This used to decorate recursively all templates from a given node.
    *
@@ -22820,24 +22822,26 @@
   // TODO(rafaelw): Review whether this is the right public API.
   @Experimental
   static void bootstrap(Node content) {
-    _Bindings._bootstrapTemplatesRecursivelyFrom(content);
+    void _bootstrap(template) {
+      if (!TemplateElement.decorate(template)) {
+        bootstrap(template.content);
+      }
+    }
+
+    // Need to do this first as the contents may get lifted if |node| is
+    // template.
+    // TODO(jmesserly): content is DocumentFragment or Element
+    var descendents = (content as dynamic).queryAll(_allTemplatesSelectors);
+    if (content is Element && (content as Element).isTemplate) {
+      _bootstrap(content);
+    }
+
+    descendents.forEach(_bootstrap);
   }
 
-  /**
-   * Binds all mustaches recursively starting from the [root] node.
-   *
-   * Note: this is not an official Model-Driven-Views API; it is intended to
-   * support binding the [ShadowRoot]'s content to a model.
-   */
-  // TODO(jmesserly): this is needed to avoid two <template> nodes when using
-  // bindings in a custom element's template. See also:
-  // https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
-  // Called from:
-  // https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
-  @Experimental
-  static void bindModel(Node root, model, [CustomBindingSyntax syntax]) {
-    _Bindings._addBindings(root, model, syntax);
-  }
+  static final String _allTemplatesSelectors =
+      'template, option[template], optgroup[template], ' +
+      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
 
   static bool _initStyles;
 
@@ -22896,41 +22900,6 @@
   @DocsEditable
   Text splitText(int offset) native "Text_splitText_Callback";
 
-
-  StreamSubscription _textBinding;
-
-  @Experimental
-  void bind(String name, model, String path) {
-    if (name != 'text') {
-      super.bind(name, model, path);
-      return;
-    }
-
-    unbind('text');
-
-    _textBinding = new PathObserver(model, path).bindSync((value) {
-      text = value == null ? '' : '$value';
-    });
-  }
-
-  @Experimental
-  void unbind(String name) {
-    if (name != 'text') {
-      super.unbind(name);
-      return;
-    }
-
-    if (_textBinding == null) return;
-
-    _textBinding.cancel();
-    _textBinding = null;
-  }
-
-  @Experimental
-  void unbindAll() {
-    unbind('text');
-    super.unbindAll();
-  }
 }
 // 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
@@ -29705,794 +29674,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 
-// This code is a port of Model-Driven-Views:
-// https://github.com/polymer-project/mdv
-// The code mostly comes from src/template_element.js
-
-typedef void _ChangeHandler(value);
-
-/**
- * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
- * but (by design) don't attempt to implement a wide array of specialized
- * behaviors.
- *
- * Enabling these features in MDV is a matter of implementing and registering an
- * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
- * delegation functions which implement specialized behavior. This object is
- * registered with MDV via [TemplateElement.syntax]:
- *
- *
- * HTML:
- *     <template bind syntax="MySyntax">
- *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
- *     </template>
- *
- * Dart:
- *     class MySyntax extends CustomBindingSyntax {
- *       getBinding(model, path, name, node) {
- *         // The magic happens here!
- *       }
- *     }
- *
- *     ...
- *
- *     TemplateElement.syntax['MySyntax'] = new MySyntax();
- *
- * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for more
- * information about Custom Syntax.
- */
-// TODO(jmesserly): if this is just one method, a function type would make it
-// more Dart-friendly.
-@Experimental
-abstract class CustomBindingSyntax {
-  /**
-   * This syntax method allows for a custom interpretation of the contents of
-   * mustaches (`{{` ... `}}`).
-   *
-   * When a template is inserting an instance, it will invoke this method for
-   * each mustache which is encountered. The function is invoked with four
-   * arguments:
-   *
-   * - [model]: The data context for which this instance is being created.
-   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
-   * - [name]: The context in which the mustache occurs. Within element
-   *   attributes, this will be the name of the attribute. Within text,
-   *   this will be 'text'.
-   * - [node]: A reference to the node to which this binding will be created.
-   *
-   * If the method wishes to handle binding, it is required to return an object
-   * which has at least a `value` property that can be observed. If it does,
-   * then MDV will call [Node.bind on the node:
-   *
-   *     node.bind(name, retval, 'value');
-   *
-   * If the 'getBinding' does not wish to override the binding, it should return
-   * null.
-   */
-  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
-  // Normally they are String and Node respectively. But sometimes it will pass
-  // (int name, CompoundBinding node). That seems very confusing; we may want
-  // to change this API.
-  getBinding(model, String path, name, node) => null;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate model than the
-   * one the template would otherwise use when producing an instance.
-   *
-   * When a template is about to create an instance, it will invoke this method
-   * The function is invoked with two arguments:
-   *
-   * - [template]: The template element which is about to create and insert an
-   *   instance.
-   * - [model]: The data context for which this instance is being created.
-   *
-   * The template element will always use the return value of `getInstanceModel`
-   * as the model for the new instance. If the syntax does not wish to override
-   * the value, it should simply return the `model` value it was passed.
-   */
-  getInstanceModel(Element template, model) => model;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate expansion of
-   * the [template] contents. When the template wants to create an instance,
-   * it will call this method with the template element.
-   *
-   * By default this will call `template.createInstance()`.
-   */
-  getInstanceFragment(Element template) => template.createInstance();
-}
-
-/** The callback used in the [CompoundBinding.combinator] field. */
-@Experimental
-typedef Object CompoundBindingCombinator(Map objects);
-
-/** Information about the instantiated template. */
-@Experimental
-class TemplateInstance {
-  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
-  // in cases where script has modified the template instance boundary.
-
-  /** The first node of this template instantiation. */
-  final Node firstNode;
-
-  /**
-   * The last node of this template instantiation.
-   * This could be identical to [firstNode] if the template only expanded to a
-   * single node.
-   */
-  final Node lastNode;
-
-  /** The model used to instantiate the template. */
-  final model;
-
-  TemplateInstance(this.firstNode, this.lastNode, this.model);
-}
-
-/**
- * Model-Driven Views contains a helper object which is useful for the
- * implementation of a Custom Syntax.
- *
- *     var binding = new CompoundBinding((values) {
- *       var combinedValue;
- *       // compute combinedValue based on the current values which are provided
- *       return combinedValue;
- *     });
- *     binding.bind('name1', obj1, path1);
- *     binding.bind('name2', obj2, path2);
- *     //...
- *     binding.bind('nameN', objN, pathN);
- *
- * CompoundBinding is an object which knows how to listen to multiple path
- * values (registered via [bind]) and invoke its [combinator] when one or more
- * of the values have changed and set its [value] property to the return value
- * of the function. When any value has changed, all current values are provided
- * to the [combinator] in the single `values` argument.
- *
- * See [CustomBindingSyntax] for more information.
- */
-// TODO(jmesserly): what is the public API surface here? I just guessed;
-// most of it seemed non-public.
-@Experimental
-class CompoundBinding extends ObservableBase {
-  CompoundBindingCombinator _combinator;
-
-  // TODO(jmesserly): ideally these would be String keys, but sometimes we
-  // use integers.
-  Map<dynamic, StreamSubscription> _bindings = new Map();
-  Map _values = new Map();
-  bool _scheduled = false;
-  bool _disposed = false;
-  Object _value;
-
-  CompoundBinding([CompoundBindingCombinator combinator]) {
-    // TODO(jmesserly): this is a tweak to the original code, it seemed to me
-    // that passing the combinator to the constructor should be equivalent to
-    // setting it via the property.
-    // I also added a null check to the combinator setter.
-    this.combinator = combinator;
-  }
-
-  CompoundBindingCombinator get combinator => _combinator;
-
-  set combinator(CompoundBindingCombinator combinator) {
-    _combinator = combinator;
-    if (combinator != null) _scheduleResolve();
-  }
-
-  static const _VALUE = const Symbol('value');
-
-  get value => _value;
-
-  void set value(newValue) {
-    _value = notifyPropertyChange(_VALUE, _value, newValue);
-  }
-
-  // TODO(jmesserly): remove these workarounds when dart2js supports mirrors!
-  getValueWorkaround(key) {
-    if (key == _VALUE) return value;
-    return null;
-  }
-  setValueWorkaround(key, val) {
-    if (key == _VALUE) value = val;
-  }
-
-  void bind(name, model, String path) {
-    unbind(name);
-
-    _bindings[name] = new PathObserver(model, path).bindSync((value) {
-      _values[name] = value;
-      _scheduleResolve();
-    });
-  }
-
-  void unbind(name, {bool suppressResolve: false}) {
-    var binding = _bindings.remove(name);
-    if (binding == null) return;
-
-    binding.cancel();
-    _values.remove(name);
-    if (!suppressResolve) _scheduleResolve();
-  }
-
-  // TODO(rafaelw): Is this the right processing model?
-  // TODO(rafaelw): Consider having a seperate ChangeSummary for
-  // CompoundBindings so to excess dirtyChecks.
-  void _scheduleResolve() {
-    if (_scheduled) return;
-    _scheduled = true;
-    queueChangeRecords(resolve);
-  }
-
-  void resolve() {
-    if (_disposed) return;
-    _scheduled = false;
-
-    if (_combinator == null) {
-      throw new StateError(
-          'CompoundBinding attempted to resolve without a combinator');
-    }
-
-    value = _combinator(_values);
-  }
-
-  void dispose() {
-    for (var binding in _bindings.values) {
-      binding.cancel();
-    }
-    _bindings.clear();
-    _values.clear();
-
-    _disposed = true;
-    value = null;
-  }
-}
-
-abstract class _InputBinding {
-  final InputElement element;
-  PathObserver binding;
-  StreamSubscription _pathSub;
-  StreamSubscription _eventSub;
-
-  _InputBinding(this.element, model, String path) {
-    binding = new PathObserver(model, path);
-    _pathSub = binding.bindSync(valueChanged);
-    _eventSub = _getStreamForInputType(element).listen(updateBinding);
-  }
-
-  void valueChanged(newValue);
-
-  void updateBinding(e);
-
-  void unbind() {
-    binding = null;
-    _pathSub.cancel();
-    _eventSub.cancel();
-  }
-
-
-  static Stream<Event> _getStreamForInputType(InputElement element) {
-    switch (element.type) {
-      case 'checkbox':
-        return element.onClick;
-      case 'radio':
-      case 'select-multiple':
-      case 'select-one':
-        return element.onChange;
-      default:
-        return element.onInput;
-    }
-  }
-}
-
-class _ValueBinding extends _InputBinding {
-  _ValueBinding(element, model, path) : super(element, model, path);
-
-  void valueChanged(value) {
-    element.value = value == null ? '' : '$value';
-  }
-
-  void updateBinding(e) {
-    binding.value = element.value;
-  }
-}
-
-class _CheckedBinding extends _InputBinding {
-  _CheckedBinding(element, model, path) : super(element, model, path);
-
-  void valueChanged(value) {
-    element.checked = _Bindings._toBoolean(value);
-  }
-
-  void updateBinding(e) {
-    binding.value = element.checked;
-
-    // Only the radio button that is getting checked gets an event. We
-    // therefore find all the associated radio buttons and update their
-    // CheckedBinding manually.
-    if (element is InputElement && element.type == 'radio') {
-      for (var r in _getAssociatedRadioButtons(element)) {
-        var checkedBinding = r._checkedBinding;
-        if (checkedBinding != null) {
-          // Set the value directly to avoid an infinite call stack.
-          checkedBinding.binding.value = false;
-        }
-      }
-    }
-  }
-
-  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
-  // Returns an array containing all radio buttons other than |element| that
-  // have the same |name|, either in the form that |element| belongs to or,
-  // if no form, in the document tree to which |element| belongs.
-  //
-  // This implementation is based upon the HTML spec definition of a
-  // "radio button group":
-  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
-  //
-  static Iterable _getAssociatedRadioButtons(element) {
-    if (!_isNodeInDocument(element)) return [];
-    if (element.form != null) {
-      return element.form.nodes.where((el) {
-        return el != element &&
-            el is InputElement &&
-            el.type == 'radio' &&
-            el.name == element.name;
-      });
-    } else {
-      var radios = element.document.queryAll(
-          'input[type="radio"][name="${element.name}"]');
-      return radios.where((el) => el != element && el.form == null);
-    }
-  }
-
-  // TODO(jmesserly): polyfill document.contains API instead of doing it here
-  static bool _isNodeInDocument(Node node) {
-    // On non-IE this works:
-    // return node.document.contains(node);
-    var document = node.document;
-    if (node == document || node.parentNode == document) return true;
-    return document.documentElement.contains(node);
-  }
-}
-
-class _Bindings {
-  // TODO(jmesserly): not sure what kind of boolean conversion rules to
-  // apply for template data-binding. HTML attributes are true if they're
-  // present. However Dart only treats "true" as true. Since this is HTML we'll
-  // use something closer to the HTML rules: null (missing) and false are false,
-  // everything else is true. See: https://github.com/polymer-project/mdv/issues/59
-  static bool _toBoolean(value) => null != value && false != value;
-
-  static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
-    var clone = node.clone(false); // Shallow clone.
-    if (clone is Element && clone.isTemplate) {
-      TemplateElement.decorate(clone, node);
-      if (syntax != null) {
-        clone.attributes.putIfAbsent('syntax', () => syntax);
-      }
-    }
-
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
-    }
-    return clone;
-  }
-
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(HtmlDocument doc) {
-    if (doc.window == null) {
-      return doc;
-    }
-    var d = doc._templateContentsOwner;
-    if (d == null) {
-      // TODO(arv): This should either be a Document or HTMLDocument depending
-      // on doc.
-      d = doc.implementation.createHtmlDocument('');
-      while (d.$dom_lastChild != null) {
-        d.$dom_lastChild.remove();
-      }
-      doc._templateContentsOwner = d;
-    }
-    return d;
-  }
-
-  static Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
-    var clone = templateElement.clone(false);
-    var attributes = templateElement.attributes;
-    for (var name in attributes.keys.toList()) {
-      switch (name) {
-        case 'template':
-        case 'repeat':
-        case 'bind':
-        case 'ref':
-          clone.attributes.remove(name);
-          break;
-        default:
-          attributes.remove(name);
-          break;
-      }
-    }
-
-    return clone;
-  }
-
-  static void _liftNonNativeChildrenIntoContent(Element templateElement) {
-    var content = templateElement.content;
-
-    if (!templateElement._isAttributeTemplate) {
-      var child;
-      while ((child = templateElement.$dom_firstChild) != null) {
-        content.append(child);
-      }
-      return;
-    }
-
-    // For attribute templates we copy the whole thing into the content and
-    // we move the non template attributes into the content.
-    //
-    //   <tr foo template>
-    //
-    // becomes
-    //
-    //   <tr template>
-    //   + #document-fragment
-    //     + <tr foo>
-    //
-    var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
-    var child;
-    while ((child = templateElement.$dom_firstChild) != null) {
-      newRoot.append(child);
-    }
-    content.append(newRoot);
-  }
-
-  static void _bootstrapTemplatesRecursivelyFrom(Node node) {
-    void bootstrap(template) {
-      if (!TemplateElement.decorate(template)) {
-        _bootstrapTemplatesRecursivelyFrom(template.content);
-      }
-    }
-
-    // Need to do this first as the contents may get lifted if |node| is
-    // template.
-    // TODO(jmesserly): node is DocumentFragment or Element
-    var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-    if (node is Element && (node as Element).isTemplate) bootstrap(node);
-
-    descendents.forEach(bootstrap);
-  }
-
-  static final String _allTemplatesSelectors = 'template, option[template], ' +
-      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-  static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
-    if (node is Element) {
-      _addAttributeBindings(node, model, syntax);
-    } else if (node is Text) {
-      _parseAndBind(node, 'text', node.text, model, syntax);
-    }
-
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      _addBindings(c, model, syntax);
-    }
-  }
-
-  static void _addAttributeBindings(Element element, model, syntax) {
-    element.attributes.forEach((name, value) {
-      if (value == '' && (name == 'bind' || name == 'repeat')) {
-        value = '{{}}';
-      }
-      _parseAndBind(element, name, value, model, syntax);
-    });
-  }
-
-  static void _parseAndBind(Node node, String name, String text, model,
-      CustomBindingSyntax syntax) {
-
-    var tokens = _parseMustacheTokens(text);
-    if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
-      return;
-    }
-
-    // If this is a custom element, give the .xtag a change to bind.
-    node = _nodeOrCustom(node);
-
-    if (tokens.length == 1 && tokens[0].isBinding) {
-      _bindOrDelegate(node, name, model, tokens[0].value, syntax);
-      return;
-    }
-
-    var replacementBinding = new CompoundBinding();
-    for (var i = 0; i < tokens.length; i++) {
-      var token = tokens[i];
-      if (token.isBinding) {
-        _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
-      }
-    }
-
-    replacementBinding.combinator = (values) {
-      var newValue = new StringBuffer();
-
-      for (var i = 0; i < tokens.length; i++) {
-        var token = tokens[i];
-        if (token.isText) {
-          newValue.write(token.value);
-        } else {
-          var value = values[i];
-          if (value != null) {
-            newValue.write(value);
-          }
-        }
-      }
-
-      return newValue.toString();
-    };
-
-    node.bind(name, replacementBinding, 'value');
-  }
-
-  static void _bindOrDelegate(node, name, model, String path,
-      CustomBindingSyntax syntax) {
-
-    if (syntax != null) {
-      var delegateBinding = syntax.getBinding(model, path, name, node);
-      if (delegateBinding != null) {
-        model = delegateBinding;
-        path = 'value';
-      }
-    }
-
-    node.bind(name, model, path);
-  }
-
-  /**
-   * Gets the [node]'s custom [Element.xtag] if present, otherwise returns
-   * the node. This is used so nodes can override [Node.bind], [Node.unbind],
-   * and [Node.unbindAll] like InputElement does.
-   */
-  // TODO(jmesserly): remove this when we can extend Element for real.
-  static _nodeOrCustom(node) => node is Element ? node.xtag : node;
-
-  static List<_BindingToken> _parseMustacheTokens(String s) {
-    var result = [];
-    var length = s.length;
-    var index = 0, lastIndex = 0;
-    while (lastIndex < length) {
-      index = s.indexOf('{{', lastIndex);
-      if (index < 0) {
-        result.add(new _BindingToken(s.substring(lastIndex)));
-        break;
-      } else {
-        // There is a non-empty text run before the next path token.
-        if (index > 0 && lastIndex < index) {
-          result.add(new _BindingToken(s.substring(lastIndex, index)));
-        }
-        lastIndex = index + 2;
-        index = s.indexOf('}}', lastIndex);
-        if (index < 0) {
-          var text = s.substring(lastIndex - 2);
-          if (result.length > 0 && result.last.isText) {
-            result.last.value += text;
-          } else {
-            result.add(new _BindingToken(text));
-          }
-          break;
-        }
-
-        var value = s.substring(lastIndex, index).trim();
-        result.add(new _BindingToken(value, isBinding: true));
-        lastIndex = index + 2;
-      }
-    }
-    return result;
-  }
-
-  static void _addTemplateInstanceRecord(fragment, model) {
-    if (fragment.$dom_firstChild == null) {
-      return;
-    }
-
-    var instanceRecord = new TemplateInstance(
-        fragment.$dom_firstChild, fragment.$dom_lastChild, model);
-
-    var node = instanceRecord.firstNode;
-    while (node != null) {
-      node._templateInstance = instanceRecord;
-      node = node.nextNode;
-    }
-  }
-
-  static void _removeAllBindingsRecursively(Node node) {
-    _nodeOrCustom(node).unbindAll();
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      _removeAllBindingsRecursively(c);
-    }
-  }
-
-  static void _removeChild(Node parent, Node child) {
-    child._templateInstance = null;
-    if (child is Element && (child as Element).isTemplate) {
-      Element childElement = child;
-      // Make sure we stop observing when we remove an element.
-      var templateIterator = childElement._templateIterator;
-      if (templateIterator != null) {
-        templateIterator.abandon();
-        childElement._templateIterator = null;
-      }
-    }
-    child.remove();
-    _removeAllBindingsRecursively(child);
-  }
-}
-
-class _BindingToken {
-  final String value;
-  final bool isBinding;
-
-  _BindingToken(this.value, {this.isBinding: false});
-
-  bool get isText => !isBinding;
-}
-
-class _TemplateIterator {
-  final Element _templateElement;
-  final List<Node> terminators = [];
-  final CompoundBinding inputs;
-  List iteratedValue;
-
-  StreamSubscription _sub;
-  StreamSubscription _valueBinding;
-
-  _TemplateIterator(this._templateElement)
-    : inputs = new CompoundBinding(resolveInputs) {
-
-    _valueBinding = new PathObserver(inputs, 'value').bindSync(valueChanged);
-  }
-
-  static Object resolveInputs(Map values) {
-    if (values.containsKey('if') && !_Bindings._toBoolean(values['if'])) {
-      return null;
-    }
-
-    if (values.containsKey('repeat')) {
-      return values['repeat'];
-    }
-
-    if (values.containsKey('bind')) {
-      return [values['bind']];
-    }
-
-    return null;
-  }
-
-  void valueChanged(value) {
-    clear();
-    if (value is! List) return;
-
-    iteratedValue = value;
-
-    if (value is Observable) {
-      _sub = value.changes.listen(_handleChanges);
-    }
-
-    int len = iteratedValue.length;
-    if (len > 0) {
-      _handleChanges([new ListChangeRecord(0, addedCount: len)]);
-    }
-  }
-
-  Node getTerminatorAt(int index) {
-    if (index == -1) return _templateElement;
-    var terminator = terminators[index];
-    if (terminator is! Element) return terminator;
-
-    var subIterator = terminator._templateIterator;
-    if (subIterator == null) return terminator;
-
-    return subIterator.getTerminatorAt(subIterator.terminators.length - 1);
-  }
-
-  void insertInstanceAt(int index, Node fragment) {
-    var previousTerminator = getTerminatorAt(index - 1);
-    var terminator = fragment.$dom_lastChild;
-    if (terminator == null) terminator = previousTerminator;
-
-    terminators.insert(index, terminator);
-    var parent = _templateElement.parentNode;
-    parent.insertBefore(fragment, previousTerminator.nextNode);
-  }
-
-  void removeInstanceAt(int index) {
-    var previousTerminator = getTerminatorAt(index - 1);
-    var terminator = getTerminatorAt(index);
-    terminators.removeAt(index);
-
-    var parent = _templateElement.parentNode;
-    while (terminator != previousTerminator) {
-      var node = terminator;
-      terminator = node.previousNode;
-      _Bindings._removeChild(parent, node);
-    }
-  }
-
-  void removeAllInstances() {
-    if (terminators.length == 0) return;
-
-    var previousTerminator = _templateElement;
-    var terminator = getTerminatorAt(terminators.length - 1);
-    terminators.length = 0;
-
-    var parent = _templateElement.parentNode;
-    while (terminator != previousTerminator) {
-      var node = terminator;
-      terminator = node.previousNode;
-      _Bindings._removeChild(parent, node);
-    }
-  }
-
-  void clear() {
-    unobserve();
-    removeAllInstances();
-    iteratedValue = null;
-  }
-
-  getInstanceModel(model, syntax) {
-    if (syntax != null) {
-      return syntax.getInstanceModel(_templateElement, model);
-    }
-    return model;
-  }
-
-  getInstanceFragment(syntax) {
-    if (syntax != null) {
-      return syntax.getInstanceFragment(_templateElement);
-    }
-    return _templateElement.createInstance();
-  }
-
-  void _handleChanges(List<ListChangeRecord> splices) {
-    var syntax = TemplateElement.syntax[_templateElement.attributes['syntax']];
-
-    for (var splice in splices) {
-      if (splice is! ListChangeRecord) continue;
-
-      for (int i = 0; i < splice.removedCount; i++) {
-        removeInstanceAt(splice.index);
-      }
-
-      for (var addIndex = splice.index;
-          addIndex < splice.index + splice.addedCount;
-          addIndex++) {
-
-        var model = getInstanceModel(iteratedValue[addIndex], syntax);
-
-        var fragment = getInstanceFragment(syntax);
-
-        _Bindings._addBindings(fragment, model, syntax);
-        _Bindings._addTemplateInstanceRecord(fragment, model);
-
-        insertInstanceAt(addIndex, fragment);
-      }
-    }
-  }
-
-  void unobserve() {
-    if (_sub == null) return;
-    _sub.cancel();
-    _sub = null;
-  }
-
-  void abandon() {
-    unobserve();
-    _valueBinding.cancel();
-    inputs.dispose();
-  }
-}
-// 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.
-
-
 /**
  * Helper class to implement custom events which wrap DOM events.
  */
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index e8ab65e..fa39c0b 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -1056,7 +1056,7 @@
 @DocsEditable
 @DomName('IDBOpenDBRequest')
 @Unstable
-class OpenDBRequest extends Request implements EventTarget native "IDBOpenDBRequest" {
+class OpenDBRequest extends Request implements EventTarget native "IDBOpenDBRequest,IDBVersionChangeRequest" {
 
   @DomName('IDBOpenDBRequest.blockedEvent')
   @DocsEditable
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index ba5f07d..6ae39cf 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -23,7 +23,7 @@
 /**
  * Returns an Exception or an Error
  */
-_exceptionFromResponse(response, String message) {
+_exceptionFromResponse(response, String message, String path) {
   assert(_isErrorResponse(response));
   switch (response[_ERROR_RESPONSE_ERROR_TYPE]) {
     case _ILLEGAL_ARGUMENT_RESPONSE:
@@ -31,9 +31,9 @@
     case _OSERROR_RESPONSE:
       var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE],
                             response[_OSERROR_RESPONSE_ERROR_CODE]);
-      return new FileException(message, err);
+      return new FileException(message, path, err);
     case _FILE_CLOSED_RESPONSE:
-      return new FileException("File closed");
+      return new FileException("File closed", path);
     default:
       return new Exception("Unknown error");
   }
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index c8423b5..0c9e048 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -212,8 +212,8 @@
 
 class DirectoryException implements IOException {
   const DirectoryException([String this.message = "",
-                              String this.path = "",
-                              OSError this.osError = null]);
+                            String this.path = "",
+                            OSError this.osError = null]);
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("DirectoryException");
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 4472fcb..5429a29 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -168,8 +168,8 @@
     request[1] = _path;
     return _directoryService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionOrErrorFromResponse(response,
-                                      "Creation of temporary directory failed");
+        throw _exceptionOrErrorFromResponse(
+            response, "Creation of temporary directory failed");
       }
       return new Directory(response);
     });
@@ -182,8 +182,8 @@
     var result = _createTemp(path);
     if (result is OSError) {
       throw new DirectoryException("Creation of temporary directory failed",
-                                     _path,
-                                     result);
+                                   _path,
+                                   result);
     }
     return new Directory(result);
   }
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 450a902..2115d31 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -525,21 +525,30 @@
 
 
 class FileException implements IOException {
+  final String message;
+  final String path;
+  final OSError osError;
   const FileException([String this.message = "",
-                         OSError this.osError = null]);
+                       String this.path = "",
+                       OSError this.osError]);
+
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("FileException");
     if (!message.isEmpty) {
       sb.write(": $message");
+      if (path != null) {
+        sb.write(", path = $path");
+      }
       if (osError != null) {
         sb.write(" ($osError)");
       }
     } else if (osError != null) {
       sb.write(": osError");
+      if (path != null) {
+        sb.write(", path = $path");
+      }
     }
     return sb.toString();
   }
-  final String message;
-  final OSError osError;
 }
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 6d15154..bc5aa47 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -253,8 +253,7 @@
     request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "Cannot check existence of file '$_path'");
+        throw _exceptionFromResponse(response, "Cannot check existence", _path);
       }
       return response;
     });
@@ -264,7 +263,7 @@
 
   bool existsSync() {
     var result = _exists(_path);
-    throwIfError(result, "Cannot check existence of file '$_path'");
+    throwIfError(result, "Cannot check existence of file", _path);
     return result;
   }
 
@@ -279,7 +278,7 @@
     request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot create file '$_path'");
+        throw _exceptionFromResponse(response, "Cannot create file", _path);
       }
       return this;
     });
@@ -293,7 +292,7 @@
 
   void createSync() {
     var result = _create(_path);
-    throwIfError(result, "Cannot create file '$_path'");
+    throwIfError(result, "Cannot create file", _path);
   }
 
   Future<File> delete() {
@@ -303,7 +302,7 @@
     request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot delete file '$_path'");
+        throw _exceptionFromResponse(response, "Cannot delete file", _path);
       }
       return this;
     });
@@ -315,7 +314,7 @@
 
   void deleteSync() {
     var result = _delete(_path);
-    throwIfError(result, "Cannot delete file '$_path'");
+    throwIfError(result, "Cannot delete file", _path);
   }
 
   Future<File> rename(String newPath) {
@@ -327,7 +326,7 @@
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(
-            response, "Cannot rename file '$_path' to '$newPath'");
+            response, "Cannot rename file to '$newPath'", _path);
       }
       return new File(newPath);
     });
@@ -339,7 +338,7 @@
 
   File renameSync(String newPath) {
     var result = _rename(_path, newPath);
-    throwIfError(result, "Cannot rename file '$_path' to '$newPath'");
+    throwIfError(result, "Cannot rename file to '$newPath'", _path);
     return new File(newPath);
   }
 
@@ -361,7 +360,7 @@
     request[2] = mode._mode;  // Direct int value for serialization.
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot open file '$_path'");
+        throw _exceptionFromResponse(response, "Cannot open file", _path);
       }
       return new _RandomAccessFile(response, _path);
     });
@@ -375,8 +374,8 @@
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "Cannot retrieve length of "
-                                     "file '$_path'");
+                                     "Cannot retrieve length of file",
+                                     _path);
       }
       return response;
     });
@@ -387,7 +386,7 @@
 
   int lengthSync() {
     var result = _lengthFromPath(_path);
-    throwIfError(result, "Cannot retrieve length of file '$_path'");
+    throwIfError(result, "Cannot retrieve length of file", _path);
     return result;
   }
 
@@ -399,8 +398,8 @@
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "Cannot retrieve modification time "
-                                     "for file '$_path'");
+                                     "Cannot retrieve modification time",
+                                     _path);
       }
       return new DateTime.fromMillisecondsSinceEpoch(response);
     });
@@ -410,7 +409,7 @@
 
   DateTime lastModifiedSync() {
     var ms = _lastModified(path);
-    throwIfError(ms, "Cannot retrieve modification time for file '$_path'");
+    throwIfError(ms, "Cannot retrieve modification time", _path);
     return new DateTime.fromMillisecondsSinceEpoch(ms);
   }
 
@@ -421,10 +420,11 @@
         mode != FileMode.WRITE &&
         mode != FileMode.APPEND) {
       throw new FileException("Unknown file mode. Use FileMode.READ, "
-                                "FileMode.WRITE or FileMode.APPEND.");
+                              "FileMode.WRITE or FileMode.APPEND.",
+                              _path);
     }
     var id = _open(_path, mode._mode);
-    throwIfError(id, "Cannot open file '$_path'");
+    throwIfError(id, "Cannot open file", _path);
     return new _RandomAccessFile(id, _path);
   }
 
@@ -446,8 +446,8 @@
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "Cannot retrieve full path"
-                                     " for '$_path'");
+                                     "Cannot retrieve full path",
+                                     _path);
       }
       return response;
     });
@@ -457,7 +457,7 @@
 
   String fullPathSync() {
     var result = _fullPath(_path);
-    throwIfError(result, "Cannot retrieve full path for file '$_path'");
+    throwIfError(result, "Cannot retrieve full path", _path);
     return result;
   }
 
@@ -469,7 +469,7 @@
                     Encoding encoding: Encoding.UTF_8}) {
     if (mode != FileMode.WRITE &&
         mode != FileMode.APPEND) {
-      throw new FileException(
+      throw new ArgumentError(
           "Wrong FileMode. Use FileMode.WRITE or FileMode.APPEND");
     }
     var consumer = new _FileStreamConsumer(this, mode);
@@ -584,9 +584,9 @@
     }
   }
 
-  static throwIfError(Object result, String msg) {
+  static throwIfError(Object result, String msg, String path) {
     if (result is OSError) {
-      throw new FileException(msg, result);
+      throw new FileException(msg, path, result);
     }
   }
 
@@ -613,7 +613,7 @@
         _id = result;
         return this;
       } else {
-        throw new FileException("Cannot close file '$_path'");
+        throw new FileException("Cannot close file", _path);
       }
     });
   }
@@ -624,7 +624,7 @@
     _checkNotClosed();
     var id = _close(_id);
     if (id == -1) {
-      throw new FileException("Cannot close file '$_path'");
+      throw new FileException("Cannot close file", _path);
     }
     _id = id;
   }
@@ -637,8 +637,7 @@
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "readByte failed for file '$_path'");
+        throw _exceptionFromResponse(response, "readByte failed", _path);
       }
       return response;
     });
@@ -650,7 +649,7 @@
     _checkNotClosed();
     var result = _readByte(_id);
     if (result is OSError) {
-      throw new FileException("readByte failed for file '$_path'", result);
+      throw new FileException("readByte failed", _path, result);
     }
     return result;
   }
@@ -658,8 +657,7 @@
   Future<List<int>> read(int bytes) {
     _ensureFileService();
     if (bytes is !int) {
-      return new Future.error(new FileException(
-          "Invalid arguments to read for file '$_path'"));
+      throw new ArgumentError(bytes);
     }
     if (closed) return _closedException();
     List request = new List(3);
@@ -668,8 +666,7 @@
     request[2] = bytes;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "read failed for file '$_path'");
+        throw _exceptionFromResponse(response, "read failed", _path);
       }
       return response[1];
     });
@@ -680,13 +677,11 @@
   List<int> readSync(int bytes) {
     _checkNotClosed();
     if (bytes is !int) {
-      throw new FileException(
-          "Invalid arguments to readSync for file '$_path'");
+      throw new ArgumentError(bytes);
     }
     var result = _read(_id, bytes);
     if (result is OSError) {
-      throw new FileException("readSync failed for file '$_path'",
-                                result);
+      throw new FileException("readSync failed",_path, result);
     }
     return result;
   }
@@ -696,9 +691,8 @@
     if (buffer is !List ||
         (start != null && start is !int) ||
         (end != null && end is !int)) {
-      return new Future.error(new FileException(
-          "Invalid arguments to readInto for file '$_path'"));
-    };
+      throw new ArgumentError();
+    }
     if (closed) return _closedException();
     List request = new List(3);
     if (start == null) start = 0;
@@ -708,8 +702,7 @@
     request[2] = end - start;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "readInto failed for file '$_path'");
+        throw _exceptionFromResponse(response, "readInto failed", _path);
       }
       var read = response[1];
       var data = response[2];
@@ -733,8 +726,7 @@
     if (buffer is !List ||
         (start != null && start is !int) ||
         (end != null && end is !int)) {
-      throw new FileException(
-          "Invalid arguments to readInto for file '$_path'");
+      throw new ArgumentError();
     }
     if (start == null) start = 0;
     if (end == null) end = buffer.length;
@@ -742,8 +734,7 @@
     _checkReadWriteListArguments(buffer.length, start, end);
     var result = _readInto(_id, buffer, start, end);
     if (result is OSError) {
-      throw new FileException("readInto failed for file '$_path'",
-                                result);
+      throw new FileException("readInto failed", _path, result);
     }
     return result;
   }
@@ -751,8 +742,7 @@
   Future<RandomAccessFile> writeByte(int value) {
     _ensureFileService();
     if (value is !int) {
-      return new Future.error(new FileException(
-          "Invalid argument to writeByte for file '$_path'"));
+      throw new ArgumentError(value);
     }
     if (closed) return _closedException();
     List request = new List(3);
@@ -761,8 +751,7 @@
     request[2] = value;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "writeByte failed for file '$_path'");
+        throw _exceptionFromResponse(response, "writeByte failed",_path);
       }
       return this;
     });
@@ -773,13 +762,11 @@
   int writeByteSync(int value) {
     _checkNotClosed();
     if (value is !int) {
-      throw new FileException(
-          "Invalid argument to writeByte for file '$_path'");
+      throw new ArgumentError(value);
     }
     var result = _writeByte(_id, value);
     if (result is OSError) {
-      throw new FileException("writeByte failed for file '$_path'",
-                                result);
+      throw new FileException("writeByte failed", _path, result);
     }
     return result;
   }
@@ -789,8 +776,7 @@
     if ((buffer is !List && buffer is !ByteData) ||
         (start != null && start is !int) ||
         (end != null && end is !int)) {
-      return new Future.error(new FileException(
-          "Invalid arguments to writeFrom for file '$_path'"));
+      throw new ArgumentError("Invalid arguments to writeFrom");
     }
 
     if (closed) return _closedException();
@@ -810,8 +796,7 @@
     request[4] = end - (start - result.start);
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "writeFrom failed for file '$_path'");
+        throw _exceptionFromResponse(response, "writeFrom failed", _path);
       }
       return this;
     });
@@ -824,8 +809,7 @@
     if (buffer is !List ||
         (start != null && start is !int) ||
         (end != null && end is !int)) {
-      throw new FileException(
-          "Invalid arguments to writeFrom for file '$_path'");
+      throw new ArgumentError("Invalid arguments to writeFromSync");
     }
     if (start == null) start = 0;
     if (end == null) end = buffer.length;
@@ -838,15 +822,14 @@
                             bufferAndStart.start,
                             end - (start - bufferAndStart.start));
     if (result is OSError) {
-      throw new FileException("writeFrom failed for file '$_path'", result);
+      throw new FileException("writeFrom failed", _path, result);
     }
   }
 
   Future<RandomAccessFile> writeString(String string,
                                        {Encoding encoding: Encoding.UTF_8}) {
     if (encoding is! Encoding) {
-      return new Future.error(new FileException(
-          "Invalid encoding in writeString: $encoding"));
+      throw new ArgumentError(encoding);
     }
     var data = _encodeString(string, encoding);
     return writeFrom(data, 0, data.length);
@@ -854,8 +837,7 @@
 
   void writeStringSync(String string, {Encoding encoding: Encoding.UTF_8}) {
     if (encoding is! Encoding) {
-      throw new FileException(
-          "Invalid encoding in writeStringSync: $encoding");
+      throw new ArgumentError(encoding);
     }
     var data = _encodeString(string, encoding);
     writeFromSync(data, 0, data.length);
@@ -869,8 +851,7 @@
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "position failed for file '$_path'");
+        throw _exceptionFromResponse(response, "position failed", _path);
       }
       return response;
     });
@@ -882,7 +863,7 @@
     _checkNotClosed();
     var result = _position(_id);
     if (result is OSError) {
-      throw new FileException("position failed for file '$_path'", result);
+      throw new FileException("position failed", _path, result);
     }
     return result;
   }
@@ -896,8 +877,7 @@
     request[2] = position;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "setPosition failed for file '$_path'");
+        throw _exceptionFromResponse(response, "setPosition failed", _path);
       }
       return this;
     });
@@ -909,7 +889,7 @@
     _checkNotClosed();
     var result = _setPosition(_id, position);
     if (result is OSError) {
-      throw new FileException("setPosition failed for file '$_path'", result);
+      throw new FileException("setPosition failed", _path, result);
     }
   }
 
@@ -922,8 +902,7 @@
     request[2] = length;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "truncate failed for file '$_path'");
+        throw _exceptionFromResponse(response, "truncate failed", _path);
       }
       return this;
     });
@@ -935,7 +914,7 @@
     _checkNotClosed();
     var result = _truncate(_id, length);
     if (result is OSError) {
-      throw new FileException("truncate failed for file '$_path'", result);
+      throw new FileException("truncate failed", _path, result);
     }
   }
 
@@ -947,8 +926,7 @@
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "length failed for file '$_path'");
+        throw _exceptionFromResponse(response, "length failed", _path);
       }
       return response;
     });
@@ -960,7 +938,7 @@
     _checkNotClosed();
     var result = _length(_id);
     if (result is OSError) {
-      throw new FileException("length failed for file '$_path'", result);
+      throw new FileException("length failed", _path, result);
     }
     return result;
   }
@@ -974,7 +952,8 @@
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "flush failed for file '$_path'");
+                                     "flush failed",
+                                     _path);
       }
       return this;
     });
@@ -986,7 +965,7 @@
     _checkNotClosed();
     var result = _flush(_id);
     if (result is OSError) {
-      throw new FileException("flush failed for file '$_path'", result);
+      throw new FileException("flush failed", _path, result);
     }
   }
 
@@ -1002,12 +981,12 @@
 
   void _checkNotClosed() {
     if (closed) {
-      throw new FileException("File closed '$_path'");
+      throw new FileException("File closed", _path);
     }
   }
 
   Future _closedException() {
-    return new Future.error(new FileException("File closed '$_path'"));
+    return new Future.error(new FileException("File closed", _path));
   }
 
   final String _path;
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 1723508..b764f04 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -79,7 +79,8 @@
     return service.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "Error getting stat of '$path'");
+                                     "Error getting stat",
+                                     path);
       }
       // Unwrap the real list from the "I'm not an error" wrapper.
       List data = response[1];
@@ -185,8 +186,7 @@
     request[2] = followLinks;
     return service.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-                                     "Error getting type of '$path'");
+        throw _exceptionFromResponse(response, "Error getting type", path);
       }
       return response;
     });
@@ -214,7 +214,7 @@
     return service.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-            "Error in FileSystemEntity.identical($path1, $path2)");
+            "Error in FileSystemEntity.identical($path1, $path2)", "");
       }
       return response;
     });
@@ -271,6 +271,27 @@
   bool existsSync();
 
   /**
+   * Renames this file system entity. Returns a `Future<FileSystemEntity>`
+   * that completes with a [FileSystemEntity] instance for the renamed
+   * file system entity.
+   *
+   * If [newPath] identifies an existing entity of the same type, that entity
+   * is replaced. If [newPath] identifies an existing entity of a different
+   * type, the operation fails and the future completes with an exception.
+   */
+  Future<FileSystemEntity> rename(String newPath);
+
+   /**
+   * Synchronously renames this file system entity. Returns a [FileSystemEntity]
+   * instance for the renamed entity.
+   *
+   * If [newPath] identifies an existing entity of the same type, that entity
+   * is replaced. If [newPath] identifies an existing entity of a different
+   * type, the operation fails and an exception is thrown.
+   */
+  FileSystemEntity renameSync(String newPath);
+
+  /**
    * Calls the operating system's stat() function on the [path] of this
    * [FileSystemEntity].  Identical to [:FileStat.stat(this.path):].
    *
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 29d561d..09b7d8c 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -55,11 +55,31 @@
 
 
 /**
- * HTTP server.
+ * The [HttpServer] class implements the server side of the HTTP
+ * protocol. The [HttpServer] is a [Stream] of [HttpRequest]s. Each
+ * [HttpRequest] has an associated [HttpResponse] object as its
+ * [HttpRequest.response] member, and the server responds to a request by
+ * writing to that [HttpResponse] object.
+ *
+ * Incomplete requests where all or parts of the header is missing, are
+ * ignored and no exceptions or [HttpRequest] objects are generated for them.
+ * Likewise, when writing to a [HttpResponse], any [Socket] exceptions are
+ * ignored and any future writes are ignored.
+ *
+ * The [HttpRequest] exposes the request headers, and provides the request body,
+ * if it exists, as a stream of data. If the body is unread, it'll be drained
+ * when the [HttpResponse] is being written to or closed.
+ *
+ * The following example shows how to bind a [HttpServer] to a IPv6
+ * [InternetAddress] on port 80, and listening to requests.
+ *
+ *   HttpServer.bind(InternetAddress.ANY_IP_V6, 80).then((server) {
+ *     server.listen((HttpRequest request) {
+ *       // Handle requests.
+ *     });
+ *   });
  */
 abstract class HttpServer implements Stream<HttpRequest> {
-  // TODO(ajohnsen): Document with example, once the stream API is final.
-  // TODO(ajohnsen): Add HttpServer.secure.
   /**
    * Starts listening for HTTP requests on the specified [address] and
    * [port].
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index 4dab40f..351a30b 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -26,7 +26,9 @@
   Encoding encoding;
 
   /**
-   * Writes the bytes uninterpreted to the consumer.
+   * Writes the bytes uninterpreted to the consumer. While the call is
+   * synchronous, the data may be buffered until the underlying resource is
+   * ready. The data should not be modified after a call to [add].
    */
   void add(List<int> data);
 
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 0be5994..4fc0312 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -154,8 +154,8 @@
     request[2] = target;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-            "Cannot create link '$path' to target '$target'");
+        throw _exceptionFromResponse(
+            response, "Cannot create link to target '$target'", path);
       }
       return this;
     });
@@ -204,7 +204,7 @@
     request[1] = path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot delete link '$path'");
+        throw _exceptionFromResponse(response, "Cannot delete link", path);
       }
       return this;
     });
@@ -224,7 +224,7 @@
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(
-            response, "Cannot rename link '$path' to '$newPath'");
+            response, "Cannot rename link to '$newPath'", path);
       }
       return new Link(newPath);
     });
@@ -243,8 +243,8 @@
     request[1] = path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response,
-            "Cannot get target of link '$path'");
+        throw _exceptionFromResponse(
+            response, "Cannot get target of link", path);
       }
       return response;
     });
@@ -272,7 +272,7 @@
     }
   }
 
-  _exceptionFromResponse(response, String message) {
+  _exceptionFromResponse(response, String message, String path) {
     assert(_isErrorResponse(response));
     switch (response[_ERROR_RESPONSE_ERROR_TYPE]) {
       case _ILLEGAL_ARGUMENT_RESPONSE:
@@ -280,7 +280,7 @@
       case _OSERROR_RESPONSE:
         var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE],
                               response[_OSERROR_RESPONSE_ERROR_CODE]);
-        return new LinkException(message, err);
+        return new LinkException(message, path, err);
       default:
         return new Exception("Unknown error");
     }
diff --git a/sdk/lib/io/secure_server_socket.dart b/sdk/lib/io/secure_server_socket.dart
index e9da3c6..8ae021e 100644
--- a/sdk/lib/io/secure_server_socket.dart
+++ b/sdk/lib/io/secure_server_socket.dart
@@ -212,9 +212,17 @@
   }
 
   void _onData(RawSocket connection) {
+    var remotePort;
+    try {
+      remotePort = connection.remotePort;
+    } catch (e) {
+      // If connection is already closed, remotePort throws an exception.
+      // Do nothing - connection is closed.
+      return;
+    }
     _RawSecureSocket.connect(
         connection.address,
-        connection.remotePort,
+        remotePort,
         certificateName,
         is_server: true,
         socket: connection,
diff --git a/sdk/lib/io/timer_impl.dart b/sdk/lib/io/timer_impl.dart
index 5a7981e..73c7cae 100644
--- a/sdk/lib/io/timer_impl.dart
+++ b/sdk/lib/io/timer_impl.dart
@@ -144,7 +144,8 @@
           // null.
           if (timer._callback != null) {
             timer._callback(timer);
-            if (timer._repeating) {
+            // Re-insert repeating timer if not canceled.
+            if (timer._repeating && timer._callback != null) {
               timer._advanceWakeupTime();
               timer._addTimerToList();
             }
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index e29c225..fd91660 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -1111,21 +1111,19 @@
  *
  * Example usage:
  *
- * [:
- * @MirrorsUsed(symbols: 'foo', override: '*')
- * import 'dart:mirrors';
+ *     @MirrorsUsed(symbols: 'foo', override: '*')
+ *     import 'dart:mirrors';
  *
- * class Foo {
- *   noSuchMethod(Invocation invocation) {
- *     print(Mirrors.getName(invocation.memberName));
- *   }
- * }
+ *     class Foo {
+ *       noSuchMethod(Invocation invocation) {
+ *         print(Mirrors.getName(invocation.memberName));
+ *       }
+ *     }
  *
- * main() {
- *   new Foo().foo(); // Prints "foo".
- *   new Foo().bar(); // Might print an arbitrary (mangled) name, "bar".
- * }
- * :]
+ *     main() {
+ *       new Foo().foo(); // Prints "foo".
+ *       new Foo().bar(); // Might print an arbitrary (mangled) name, "bar".
+ *     }
  */
 // TODO(ahe): Remove ", override: '*'" when it isn't necessary anymore.
 class MirrorsUsed {
diff --git a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
index 41e2450..b38c130 100644
--- a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
+++ b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
@@ -1786,7 +1786,7 @@
   // -- end List<int> mixins.
 }
 
-class Uint8ClampedList extends Uint8List implements JavaScriptIndexingBehavior, List<int> native "Uint8ClampedArray" {
+class Uint8ClampedList extends Uint8List implements JavaScriptIndexingBehavior, List<int> native "Uint8ClampedArray,CanvasPixelArray" {
 
   factory Uint8ClampedList(int length) =>
     _TypedArrayFactoryProvider.createUint8ClampedList(length);
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index a61c68d..3cec0dd 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -25,7 +25,7 @@
 @DomName('AnalyserNode')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AnalyserNode
 @Experimental
-class AnalyserNode extends AudioNode native "AnalyserNode" {
+class AnalyserNode extends AudioNode native "AnalyserNode,RealtimeAnalyserNode" {
 
   @DomName('AnalyserNode.fftSize')
   @DocsEditable
@@ -626,7 +626,7 @@
 @DomName('ChannelMergerNode')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#ChannelMergerNode-section
 @Experimental
-class ChannelMergerNode extends AudioNode native "ChannelMergerNode" {
+class ChannelMergerNode extends AudioNode native "ChannelMergerNode,AudioChannelMerger" {
 }
 // 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
@@ -637,7 +637,7 @@
 @DomName('ChannelSplitterNode')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#ChannelSplitterNode-section
 @Experimental
-class ChannelSplitterNode extends AudioNode native "ChannelSplitterNode" {
+class ChannelSplitterNode extends AudioNode native "ChannelSplitterNode,AudioChannelSplitter" {
 }
 // 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
@@ -717,7 +717,7 @@
 @DomName('GainNode')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#GainNode
 @Experimental
-class GainNode extends AudioNode native "GainNode" {
+class GainNode extends AudioNode native "GainNode,AudioGainNode" {
 
   @DomName('GainNode.gain')
   @DocsEditable
@@ -811,7 +811,7 @@
 @DomName('OscillatorNode')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#dfn-OscillatorNode
 @Experimental
-class OscillatorNode extends AudioSourceNode native "OscillatorNode" {
+class OscillatorNode extends AudioSourceNode native "OscillatorNode,Oscillator" {
 
   @DomName('OscillatorNode.CUSTOM')
   @DocsEditable
@@ -904,7 +904,7 @@
 @DomName('PannerNode')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#PannerNode
 @Experimental
-class PannerNode extends AudioNode native "PannerNode" {
+class PannerNode extends AudioNode native "PannerNode,AudioPannerNode" {
 
   @DomName('PannerNode.EQUALPOWER')
   @DocsEditable
@@ -994,7 +994,7 @@
 @DomName('ScriptProcessorNode')
 // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#ScriptProcessorNode
 @Experimental
-class ScriptProcessorNode extends AudioNode native "ScriptProcessorNode" {
+class ScriptProcessorNode extends AudioNode native "ScriptProcessorNode,JavaScriptAudioNode" {
   Stream<AudioProcessingEvent> _eventStream;
 
   /**
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index eb14d3a..1858391 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -2351,8 +2351,8 @@
 
   @DomName('WebGLRenderingContext.getShaderParameter')
   @DocsEditable
-  @Creates('int|Null')
-  @Returns('int|Null')
+  @Creates('int|bool|Null')
+  @Returns('int|bool|Null')
   Object getShaderParameter(Shader shader, int pname) native;
 
   @DomName('WebGLRenderingContext.getShaderPrecisionFormat')
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 98b0881..3a34dff 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -3,38 +3,29 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dartanalyzer ]
-Language/05_Variables/05_Variables_A05_t04: fail
-Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t06: fail
-Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t07: fail
-Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t03: fail
+
+# not clear: g([var foo = foo + 10]) is parameter 'foo' in the scope of its own initialzer?
 Language/06_Functions/2_Formal_Parameters_A02_t02: fail
+
+# not clear: null..[1](1)[2](2).foo(3, bar: 4)=5 - it seems that verything before =5 it not assignable
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: fail
+
+# not initialized final instance variable, should be static warning
 Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail
+
+# invalid argument for constant constructor
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: fail
-Language/11_Expressions/01_Constants_A16_t01: fail
-Language/11_Expressions/01_Constants_A16_t02: fail
 Language/11_Expressions/01_Constants_A16_t03: fail
+
+# final instance variable created instance of the enclosing class
 Language/11_Expressions/01_Constants_A17_t03: fail
-Language/11_Expressions/05_Strings_A02_t46: fail
-Language/11_Expressions/05_Strings_A02_t48: fail
-Language/11_Expressions/11_Instance_Creation/1_New_A13_t02: fail
-Language/11_Expressions/11_Instance_Creation_A05_t02: fail
-Language/11_Expressions/22_Equality_A01_t15: fail
-Language/11_Expressions/22_Equality_A01_t16: fail
-Language/13_Libraries_and_Scripts/1_Imports_A05_t01: fail
-Language/13_Libraries_and_Scripts/5_URIs_A01_t24: fail
-Language/13_Libraries_and_Scripts/5_URIs_A01_t25: fail
-Language/14_Types/3_Type_Declarations/1_Typedef_A07_t01: fail
-Language/14_Types/3_Type_Declarations/1_Typedef_A07_t02: fail
-Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: fail
-Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: fail
-Language/15_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: fail
-Language/15_Reference/1_Lexical_Rules_A02_t06: fail
 
-
-# fails locally, passes on bot
+# analyzer problem: forward reference of typedef with type parameters
 Language/13_Libraries_and_Scripts/3_Parts_A02_t03: skip
 
+
+
+
 # co19 issue #380, Strings class has been removed
 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: fail, OK
 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: fail, OK
@@ -104,7 +95,7 @@
 Language/11_Expressions/08_Throw_A05_t02: fail, OK
 Language/11_Expressions/08_Throw_A05_t03: fail, OK
 
-# infinite loop
+# analyzer issue https://code.google.com/p/dart/issues/detail?id=11534
 Language/14_Types/4_Interface_Types_A11_t01: skip
 Language/14_Types/4_Interface_Types_A11_t02: skip
 
@@ -189,8 +180,28 @@
 Language/11_Expressions/33_Argument_Definition_Test_A01_t14: fail, OK
 Language/11_Expressions/33_Argument_Definition_Test_A01_t18: fail, OK
 
-# co19 issue #435, AssertioError has not properties
+# co19 issue #435, AssertionError has not properties
 LibTest/core/AssertionError/column_A01_t02: fail, OK
 LibTest/core/AssertionError/failedAssertion_A01_t01: fail, OK
 LibTest/core/AssertionError/line_A01_t02: fail, OK
 LibTest/core/AssertionError/url_A01_t01: fail, OK
+
+# co19 issue #437, annotation should be constant _variable_ or constant constructor invocation
+Language/07_Classes/07_Classes_A01_t20: fail, OK
+Language/07_Classes/07_Classes_A02_t34: fail, OK
+Language/07_Classes/07_Classes_A03_t10: fail, OK
+Language/13_Libraries_and_Scripts/2_Exports_A01_t17: fail, OK
+
+# co19 issue 438, Static variables are initialized lazily, need not be constants
+Language/11_Expressions/01_Constants_A16_t01: fail, OK
+Language/11_Expressions/01_Constants_A16_t02: fail, OK
+
+# co19 issue 439, it is warning, not error to import two different libraries with the same name
+Language/13_Libraries_and_Scripts/1_Imports_A05_t01: fail, OK
+
+# co19 issue #440, adj strings is not a string interpolation
+Language/13_Libraries_and_Scripts/5_URIs_A01_t24: fail, OK
+Language/13_Libraries_and_Scripts/5_URIs_A01_t25: fail, OK
+
+# co19 issue #441, assignment in constructor is not initializing
+Language/05_Variables/05_Variables_A05_t04: fail, OK
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 41e881a..8dddc20 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -335,7 +335,6 @@
 Language/12_Statements/09_Switch_A06_t02: Fail # Inherited from VM (does not throw NSME).
 Language/12_Statements/10_Try_A06_t01: Fail, Pass # Passes in conservative renaming mode. Test depends on function names.
 Language/12_Statements/10_Try_A07_t03: Fail # Test depends on out file name.
-Language/12_Statements/10_Try_A11_t01: Fail # Inherited from VM.
 Language/12_Statements/11_Return_A05_t01: Fail # Inherited from dart2js
 Language/12_Statements/11_Return_A05_t02: Fail # Inherited from dart2js
 Language/12_Statements/11_Return_A05_t03: Fail # Inherited from dart2js
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 9ec08cd..8cae6ca 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -2,6 +2,13 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+[ $compiler == none]
+Language/11_Expressions/33_Argument_Definition_Test_A01_t02: Fail, OK # co19 issue 436
+Language/11_Expressions/33_Argument_Definition_Test_A02_t01: Fail, OK # co19 issue 436
+Language/11_Expressions/33_Argument_Definition_Test_A02_t02: Fail, OK # co19 issue 436
+Language/11_Expressions/33_Argument_Definition_Test_A03_t01: Fail, OK # co19 issue 436
+Language/11_Expressions/33_Argument_Definition_Test_A03_t02: Fail, OK # co19 issue 436
+
 [ $runtime == vm && $system == windows ]
 LibTest/core/Stopwatch/elapsed_A01_t01: Pass, Fail # Issue 11382.
 
@@ -142,7 +149,6 @@
 Language/12_Statements/10_Try_A03_t01: Fail # Dart issue 7311
 Language/12_Statements/10_Try_A03_t02: Fail # Dart issue 7311
 Language/12_Statements/10_Try_A03_t03: Fail # Dart issue 7311
-Language/12_Statements/10_Try_A11_t01: Fail # Dart issue 430
 Language/12_Statements/12_Labels_A01_t03: Fail # Dart issue 2238
 Language/13_Libraries_and_Scripts/13_Libraries_and_Scripts_A05_t04: Fail # Dart issue 5839
 Language/13_Libraries_and_Scripts/1_Imports_A05_t01: Fail # Dart issue 3206
@@ -161,7 +167,6 @@
 LibTest/math/pow_A01_t01: Fail # Dart issue 7318
 LibTest/math/pow_A11_t01: Fail # Dart issue 449
 LibTest/math/pow_A13_t01: Fail # Dart issue 449
-LibTest/math/sin_A01_t01: Fail # Dart issue 7318
 
 Language/05_Variables/05_Variables_A05_t04: Fail # Dart issue 5881
 Language/05_Variables/05_Variables_A05_t11: Fail # Dart issue 5885
@@ -263,7 +268,7 @@
 LibTest/core/double/toRadixString_A01_t01: Fail # Issue 463
 LibTest/core/int/toRadixString_A01_t01: Fail # Issue 461
 
-LibTest/math/sin_A01_t01: Fail, OK # Issue co19 - 44
+LibTest/math/sin_A01_t01: Pass, Fail, OK # Issue co19 - 44
 
 LibTest/core/Date/toString_A02_t01: Fail # Argument error. Year 999999 is out of range. Needs to be specified (and then potentially reported to co19): issue 1878.
 LibTest/core/Date/year_A01_t01: Fail # Year out of range. Needs to be specified: issue 8808. Possibly a co19 bug.
@@ -480,7 +485,6 @@
 [ $compiler == none && $runtime == vm && $mode == debug ]
 LibTest/isolate/isolate_api/spawnFunction_A02_t01: Crash
 
-
 [ $compiler == none && $runtime == vm && $system == macos ]
 LibTest/math/exp_A01_t01: Fail, OK # Issue co19 - 44
 LibTest/math/acos_A01_t01: Fail, OK # Issue co19 - 44
@@ -488,64 +492,35 @@
 LibTest/math/atan_A01_t01: Fail, OK # Issue co19 - 44
 LibTest/math/tan_A01_t01: Fail, OK  # Issue co19 - 44
 
-
 [ $compiler == none && $runtime == vm && $system == linux ]
 LibTest/math/exp_A01_t01: Fail
 
-
-[ $compiler == none && $runtime == vm && $system == linux && $arch == ia32 ]
-LibTest/math/sin_A01_t01: Fail
+[ $compiler == none && $runtime == vm && $system != windows && $arch != x64 && $arch != arm ]
 LibTest/math/tan_A01_t01: Fail
 
-
-[ $compiler == none && $runtime == vm && $arch == x64 && $mode == debug ]
-LibTest/core/Map/Map_class_A01_t04: Skip # Timeout
-
-
-[ $compiler == none && $runtime == vm && $arch == ia32 ]
+[ $compiler == none && $runtime == vm && $arch != x64 ]
 LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
 
 
-[ $compiler == none && $runtime == vm && $arch == arm ]
-LibTest/math/tan_A01_t01: Pass, Fail
-LibTest/math/sin_A01_t01: Pass, Fail
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-LibTest/core/int/operator_unary_minus_A01_t01: Pass, Fail
-
-
 [ $compiler == none && $runtime == vm && $arch == arm && $mode == debug ]
-LibTest/core/List/sort_A01_t05: Crash
-LibTest/core/List/sort_A01_t06: Crash
+LibTest/core/List/sort_A01_t05: Crash # Too far relative jump.
+LibTest/core/List/sort_A01_t06: Crash # Too far relative jump.
 
-[ $compiler == none && $runtime == vm && $arch == simarm && $mode == release ]
-LibTest/math/tan_A01_t01: Fail
+[ $compiler == none && $runtime == vm && $arch == simarm ]
 LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-LibTest/core/int/operator_unary_minus_A01_t01: Fail
 
 [ $compiler == none && $runtime == vm && $arch == simarm && $mode == debug ]
-LibTest/math/tan_A01_t01: Fail
-LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
-LibTest/core/List/sort_A01_t05: Crash
-LibTest/core/List/sort_A01_t06: Crash
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-LibTest/core/int/operator_unary_minus_A01_t01: Fail
+LibTest/core/List/sort_A01_t05: Crash # Too far relative jump.
+LibTest/core/List/sort_A01_t06: Crash # Too far relative jump.
+
 
 [ $compiler == none && $runtime == vm && $arch == mips ]
 *: Skip
 
-
-[ $compiler == none && $runtime == vm && $arch == simmips && $mode == release ]
-LibTest/math/tan_A01_t01: Fail
+[ $compiler == none && $runtime == vm && $arch == simmips ]
 LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-LibTest/core/int/operator_unary_minus_A01_t01: Fail
 
 [ $compiler == none && $runtime == vm && $arch == simmips && $mode == debug ]
-LibTest/math/tan_A01_t01: Fail
-LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
 LibTest/core/List/sort_A01_t04: Crash # Too far relative jump.
 LibTest/core/List/sort_A01_t05: Crash
 LibTest/core/List/sort_A01_t06: Crash
-LibTest/core/int/operator_unary_minus_A01_t01: Fail
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index e7d7e24..3c5c9e7 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -20,16 +20,13 @@
 // TODO(johnniwinther): Support canonical URIs as keys and message kinds as
 // values.
 const Map<String, List<String>> WHITE_LIST = const {
-  'path_observer.dart':
-      const ['Hint: Using "new Symbol"', // Issue 10565.
-            ],
   'sdk/lib/html/dart2js/html_dart2js.dart':
       const ['Hint: The class "Rect" overrides "operator==", '
-             'but not "get hashCode".',
+             'but not "get hashCode".', // http://dartbug.com/11613
              'Hint: The class "Point" overrides "operator==", '
-             'but not "get hashCode".',
+             'but not "get hashCode".', // http://dartbug.com/11613
              'Hint: The class "_ClientRect" overrides "operator==", '
-             'but not "get hashCode".',
+             'but not "get hashCode".', // http://dartbug.com/11613
       ],
 };
 
diff --git a/tests/compiler/dart2js/find_my_name_test.dart b/tests/compiler/dart2js/find_my_name_test.dart
index 1c24d17..d5e7d0f 100644
--- a/tests/compiler/dart2js/find_my_name_test.dart
+++ b/tests/compiler/dart2js/find_my_name_test.dart
@@ -7,18 +7,36 @@
 import "mock_compiler.dart";
 import "parser_helper.dart";
 
-main() {
-  MockCompiler compiler = new MockCompiler();
-
-  String code = '''
+String TEST_0 = '''
 class Foo {
+  Foo();
+  Foo.named();
+  factory Foo._internal() => null;
   operator+(other) => null;
 }
 ''';
 
-  ClassElement foo = parseUnit(code, compiler, compiler.mainApp).head;
-  foo.parseNode(compiler);
-  for (Element e in foo.localMembers) {
-    Expect.equals(code.indexOf(e.name.slowToString()), e.position().charOffset);
+String TEST_1 = '''
+class Bar {
+  const Bar();
+  const Bar.named();
+  Map<int, List<int>> baz() => null;
+}
+''';
+
+main() {
+  MockCompiler compiler = new MockCompiler();
+  testClass(TEST_0, compiler);
+  testClass(TEST_1, compiler);
+}
+
+testClass(String code, MockCompiler compiler) {
+  int skip = code.indexOf('{');
+  ClassElement cls = parseUnit(code, compiler, compiler.mainApp).head;
+  cls.parseNode(compiler);
+  for (Element e in cls.localMembers) {
+    String name = e.name.slowToString();
+    if (e.isConstructor()) name = name.replaceFirst(r'$', '.');
+    Expect.equals(code.indexOf(name, skip), e.position().charOffset);
   }
 }
diff --git a/tests/compiler/dart2js/type_equals_test.dart b/tests/compiler/dart2js/type_equals_test.dart
index 0c283db..2493d8c 100644
--- a/tests/compiler/dart2js/type_equals_test.dart
+++ b/tests/compiler/dart2js/type_equals_test.dart
@@ -8,7 +8,7 @@
 import "parser_helper.dart";
 
 bool test(compiler, String name1, String name2, {bool expect}) {
-  Expect.isTrue(?expect, 'required parameter "expect" not given');
+  Expect.isTrue((expect != null), 'required parameter "expect" not given');
   var clazz = findElement(compiler, "Class");
   clazz.ensureResolved(compiler);
   var element1 = clazz.buildScope().lookup(buildSourceString(name1));
diff --git a/tests/corelib/apply_test.dart b/tests/corelib/apply_test.dart
index d872227..e06cf6d 100644
--- a/tests/corelib/apply_test.dart
+++ b/tests/corelib/apply_test.dart
@@ -16,9 +16,6 @@
 int test2(int i, int j) => i + j;
 int test2a(int i, int j, {int a}) => i + j + a;
 
-bool testPassed1([int x]) => ?x;
-bool testPassedX({int x}) => ?x;
-
 class C {
   int x = 10;
   int foo(y) => this.x + y;
@@ -60,14 +57,6 @@
   testList(42, test2, [20, 22]);
   test(42, test2a, [10, 15], {"a" : 17});
 
-  testList(false, testPassed1, null);
-  testList(false, testPassed1, []);
-  testList(true, testPassed1, [42]);
-
-  testMap(false, testPassedX, null);
-  testMap(false, testPassedX, {});
-  testMap(true, testPassedX, {"x": 42});
-
   // Test that "this" is correct when calling closurized functions.
   var cfoo = new C().foo;
   testList(42, cfoo, [32]);
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 7a3c170..77edb53 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -53,11 +53,6 @@
 
 string_replace_func_test: Skip # Bug 6554 - doesn't terminate.
 
-[ $compiler == dart2js || $compiler == dart2dart ]
-apply_test: Fail, OK # Depends on ?parameter check.
-iterable_join_test: Fail, OK # Depends on ?parameter check.
-list_fill_range_test: Fail, OK # Depends on ?parameter check.
-
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
@@ -108,6 +103,9 @@
 list_insert_test: fail
 list_removeat_test: fail
 
+[ $arch == arm ]
+collection_to_string_test: Pass, Crash # Issue: 11207
+
 [ $arch == simarm && $mode == debug ]
 collection_to_string_test: Pass, Crash # Issue: 11207
 
@@ -119,7 +117,7 @@
 
 [ $arch == simmips && $checked ]
 hash_map2_test: Crash # Too far PC relative branch.
-collection_length_test: Skip # Timeout.
+collection_length_test: Pass, Timeout
 
 [ $arch == simmips && $mode == debug ]
 collection_to_string_test: Pass, Crash # Issue: 11207
diff --git a/tests/corelib/iterable_join_test.dart b/tests/corelib/iterable_join_test.dart
index e374be4..d2c750f 100644
--- a/tests/corelib/iterable_join_test.dart
+++ b/tests/corelib/iterable_join_test.dart
@@ -9,8 +9,8 @@
   String toString() => "${count++}";
 }
 
-testJoin(String expect, Iterable iterable, [String separator = ""]) {
-  if (?separator) {
+testJoin(String expect, Iterable iterable, [String separator]) {
+  if (separator != null) {
     Expect.equals(expect, iterable.join(separator));
   } else {
     Expect.equals(expect, iterable.join());
diff --git a/tests/corelib/linked_hash_map_from_iterable_test.dart b/tests/corelib/linked_hash_map_from_iterable_test.dart
new file mode 100644
index 0000000..d581532
--- /dev/null
+++ b/tests/corelib/linked_hash_map_from_iterable_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:collection';
+
+main() {
+  defaultFunctionValuesTest();
+  defaultKeyFunctionTest();
+  defaultValueFunctionTest();
+  noDefaultValuesTest();
+  emptyIterableTest();
+  equalElementsTest();
+  genericTypeTest();
+}
+
+void defaultFunctionValuesTest() {
+  var map = new LinkedHashMap.fromIterable([1, 2, 3]);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(1, map[1]);
+  Expect.equals(2, map[2]);
+  Expect.equals(3, map[3]);
+}
+
+void defaultKeyFunctionTest() {
+  var map = new LinkedHashMap.fromIterable([1, 2, 3], value: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(2, map[1]);
+  Expect.equals(3, map[2]);
+  Expect.equals(4, map[3]);
+}
+
+void defaultValueFunctionTest() {
+  var map = new LinkedHashMap.fromIterable([1, 2, 3], key: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(1, map[2]);
+  Expect.equals(2, map[3]);
+  Expect.equals(3, map[4]);
+}
+
+void noDefaultValuesTest() {
+  var map = new LinkedHashMap.fromIterable([1, 2, 3],
+      key: (x) => x + 1, value: (x) => x - 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(0, map[2]);
+  Expect.equals(1, map[3]);
+  Expect.equals(2, map[4]);
+}
+
+void emptyIterableTest() {
+  var map = new LinkedHashMap.fromIterable([]);
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(0, map.length);
+  Expect.equals(0, map.keys.length);
+  Expect.equals(0, map.values.length);
+}
+
+void equalElementsTest() {
+  var map = new LinkedHashMap.fromIterable([1, 2, 2], key: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(2, map.length);
+  Expect.equals(2, map.keys.length);
+  Expect.equals(2, map.values.length);
+
+  Expect.equals(1, map[2]);
+  Expect.equals(2, map[3]);
+}
+
+void genericTypeTest() {
+  var map = new LinkedHashMap<int, String>.fromIterable([1, 2, 3], value: (x) => '$x');
+  Expect.isTrue(map is Map<int, String>);
+  Expect.isTrue(map is LinkedHashMap<int, String>);
+
+  // Make sure it is not just LinkedHashMap<dynamic, dynamic>.
+  Expect.isFalse(map is LinkedHashMap<String, dynamic>);
+  Expect.isFalse(map is LinkedHashMap<dynamic, int>);
+}
+
diff --git a/tests/corelib/linked_hash_map_from_iterables_test.dart b/tests/corelib/linked_hash_map_from_iterables_test.dart
new file mode 100644
index 0000000..0212dd4
--- /dev/null
+++ b/tests/corelib/linked_hash_map_from_iterables_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:collection';
+
+main() {
+  positiveTest();
+  emptyMapTest();
+  fewerKeysIterableTest();
+  fewerValuesIterableTest();
+  equalElementsTest();
+  genericTypeTest();
+}
+
+void positiveTest() {
+  var map = new LinkedHashMap.fromIterables([1, 2, 3], ["one", "two", "three"]);
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("two", map[2]);
+  Expect.equals("three", map[3]);
+}
+
+void emptyMapTest() {
+  var map = new LinkedHashMap.fromIterables([], []);
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(0, map.length);
+  Expect.equals(0, map.keys.length);
+  Expect.equals(0, map.values.length);
+}
+
+void fewerValuesIterableTest() {
+  Expect.throws(() => new LinkedHashMap.fromIterables([1,2], [0]));
+}
+
+void fewerKeysIterableTest() {
+  Expect.throws(() => new LinkedHashMap.fromIterables([1], [0,2]));
+}
+
+void equalElementsTest() {
+  var map = new LinkedHashMap.fromIterables([1, 2, 2], ["one", "two", "three"]);
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is LinkedHashMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(2, map.length);
+  Expect.equals(2, map.keys.length);
+  Expect.equals(2, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("three", map[2]);
+}
+
+
+void genericTypeTest() {
+  var map = new LinkedHashMap<int, String>.fromIterables(
+      [1, 2, 3], ["one", "two", "three"]);
+  Expect.isTrue(map is Map<int, String>);
+  Expect.isTrue(map is LinkedHashMap<int, String>);
+
+  // Make sure it is not just LinkedHashMap<dynamic, dynamic>.
+  Expect.isFalse(map is LinkedHashMap<String, dynamic>);
+  Expect.isFalse(map is LinkedHashMap<dynamic, int>);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("two", map[2]);
+  Expect.equals("three", map[3]);
+}
diff --git a/tests/corelib/list_fill_range_test.dart b/tests/corelib/list_fill_range_test.dart
index cd0e023..4553e43 100644
--- a/tests/corelib/list_fill_range_test.dart
+++ b/tests/corelib/list_fill_range_test.dart
@@ -7,11 +7,7 @@
 
 test(List list, int start, int end, [fillValue]) {
   List copy = list.toList();
-  if (?fillValue) {
-    list.fillRange(start, end, fillValue);
-  } else {
-    list.fillRange(start, end, fillValue);
-  }
+  list.fillRange(start, end, fillValue);
   Expect.equals(copy.length, list.length);
   for (int i = 0; i < start; i++) {
     Expect.equals(copy[i], list[i]);
diff --git a/tests/corelib/map_from_iterable_test.dart b/tests/corelib/map_from_iterable_test.dart
new file mode 100644
index 0000000..4d0468d
--- /dev/null
+++ b/tests/corelib/map_from_iterable_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:collection';
+
+main() {
+  defaultFunctionValuesTest();
+  defaultKeyFunctionTest();
+  defaultValueFunctionTest();
+  noDefaultValuesTest();
+  emptyIterableTest();
+  equalElementsTest();
+  genericTypeTest();
+}
+
+void defaultFunctionValuesTest() {
+  var map = new Map.fromIterable([1, 2, 3]);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(1, map[1]);
+  Expect.equals(2, map[2]);
+  Expect.equals(3, map[3]);
+}
+
+void defaultKeyFunctionTest() {
+  var map = new Map.fromIterable([1, 2, 3], value: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(2, map[1]);
+  Expect.equals(3, map[2]);
+  Expect.equals(4, map[3]);
+}
+
+void defaultValueFunctionTest() {
+  var map = new Map.fromIterable([1, 2, 3], key: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(1, map[2]);
+  Expect.equals(2, map[3]);
+  Expect.equals(3, map[4]);
+}
+
+void noDefaultValuesTest() {
+  var map = new Map.fromIterable([1, 2, 3],
+      key: (x) => x + 1, value: (x) => x - 1);
+
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(0, map[2]);
+  Expect.equals(1, map[3]);
+  Expect.equals(2, map[4]);
+}
+
+void emptyIterableTest() {
+  var map = new Map.fromIterable([]);
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(0, map.length);
+  Expect.equals(0, map.keys.length);
+  Expect.equals(0, map.values.length);
+}
+
+void equalElementsTest() {
+  var map = new Map.fromIterable([1, 2, 2], key: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(2, map.length);
+  Expect.equals(2, map.keys.length);
+  Expect.equals(2, map.values.length);
+
+  Expect.equals(1, map[2]);
+  Expect.equals(2, map[3]);
+}
+
+void genericTypeTest() {
+  var map = new Map<int, String>.fromIterable([1, 2, 3], value: (x) => '$x');
+  Expect.isTrue(map is Map<int, String>);
+
+  // Make sure it is not just Map<dynamic, dynamic>.
+  Expect.isFalse(map is Map<String, dynamic>);
+  Expect.isFalse(map is Map<dynamic, int>);
+}
+
diff --git a/tests/corelib/map_from_iterables_test.dart b/tests/corelib/map_from_iterables_test.dart
new file mode 100644
index 0000000..8c21e9f
--- /dev/null
+++ b/tests/corelib/map_from_iterables_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:collection';
+
+main() {
+  positiveTest();
+  emptyMapTest();
+  fewerKeysIterableTest();
+  fewerValuesIterableTest();
+  equalElementsTest();
+  genericTypeTest();
+}
+
+void positiveTest() {
+  var map = new Map.fromIterables([1, 2, 3], ["one", "two", "three"]);
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("two", map[2]);
+  Expect.equals("three", map[3]);
+}
+
+void emptyMapTest() {
+  var map = new Map.fromIterables([], []);
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(0, map.length);
+  Expect.equals(0, map.keys.length);
+  Expect.equals(0, map.values.length);
+}
+
+void fewerValuesIterableTest() {
+  Expect.throws(() => new Map.fromIterables([1,2], [0]));
+}
+
+void fewerKeysIterableTest() {
+  Expect.throws(() => new Map.fromIterables([1], [0,2]));
+}
+
+void equalElementsTest() {
+  var map = new Map.fromIterables([1, 2, 2], ["one", "two", "three"]);
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is HashMap);
+
+  Expect.equals(2, map.length);
+  Expect.equals(2, map.keys.length);
+  Expect.equals(2, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("three", map[2]);
+}
+
+
+void genericTypeTest() {
+  var map = new Map<int, String>.fromIterables(
+      [1, 2, 3], ["one", "two", "three"]);
+  Expect.isTrue(map is Map<int, String>);
+
+  // Make sure it is not just Map<dynamic, dynamic>.
+  Expect.isFalse(map is Map<String, dynamic>);
+  Expect.isFalse(map is Map<dynamic, int>);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("two", map[2]);
+  Expect.equals("three", map[3]);
+}
diff --git a/tests/corelib/splay_tree_from_iterable_test.dart b/tests/corelib/splay_tree_from_iterable_test.dart
new file mode 100644
index 0000000..18d0106
--- /dev/null
+++ b/tests/corelib/splay_tree_from_iterable_test.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:collection';
+
+main() {
+  defaultFunctionValuesTest();
+  defaultKeyFunctionTest();
+  defaultValueFunctionTest();
+  noDefaultValuesTest();
+  emptyIterableTest();
+  equalElementsTest();
+  genericTypeTest();
+}
+
+void defaultFunctionValuesTest() {
+  var map = new SplayTreeMap.fromIterable([1, 2, 3]);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(1, map[1]);
+  Expect.equals(2, map[2]);
+  Expect.equals(3, map[3]);
+}
+
+void defaultKeyFunctionTest() {
+  var map = new SplayTreeMap.fromIterable([1, 2, 3], value: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(2, map[1]);
+  Expect.equals(3, map[2]);
+  Expect.equals(4, map[3]);
+}
+
+void defaultValueFunctionTest() {
+  var map = new SplayTreeMap.fromIterable([1, 2, 3], key: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(1, map[2]);
+  Expect.equals(2, map[3]);
+  Expect.equals(3, map[4]);
+}
+
+void noDefaultValuesTest() {
+  var map = new SplayTreeMap.fromIterable([1, 2, 3],
+      key: (x) => x + 1, value: (x) => x - 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals(0, map[2]);
+  Expect.equals(1, map[3]);
+  Expect.equals(2, map[4]);
+}
+
+void emptyIterableTest() {
+  var map = new SplayTreeMap.fromIterable([]);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(0, map.length);
+  Expect.equals(0, map.keys.length);
+  Expect.equals(0, map.values.length);
+}
+
+void equalElementsTest() {
+  var map = new SplayTreeMap.fromIterable([1, 2, 2], key: (x) => x + 1);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(2, map.length);
+  Expect.equals(2, map.keys.length);
+  Expect.equals(2, map.values.length);
+
+  Expect.equals(1, map[2]);
+  Expect.equals(2, map[3]);
+}
+
+void genericTypeTest() {
+  var map = new SplayTreeMap<int, String>.fromIterable([1, 2, 3], value: (x) => '$x');
+  Expect.isTrue(map is Map<int, String>);
+  Expect.isTrue(map is SplayTreeMap<int, String>);
+
+  // Make sure it is not just SplayTreeMap<dynamic, dynamic>.
+  Expect.isFalse(map is SplayTreeMap<String, dynamic>);
+  Expect.isFalse(map is SplayTreeMap<dynamic, int>);
+}
+
diff --git a/tests/corelib/splay_tree_from_iterables_test.dart b/tests/corelib/splay_tree_from_iterables_test.dart
new file mode 100644
index 0000000..5ac195f
--- /dev/null
+++ b/tests/corelib/splay_tree_from_iterables_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:collection';
+
+main() {
+  positiveTest();
+  emptyMapTest();
+  fewerKeysIterableTest();
+  fewerValuesIterableTest();
+  equalElementsTest();
+  genericTypeTest();
+}
+
+void positiveTest() {
+  var map = new SplayTreeMap.fromIterables([1, 2, 3], ["one", "two", "three"]);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("two", map[2]);
+  Expect.equals("three", map[3]);
+}
+
+void emptyMapTest() {
+  var map = new SplayTreeMap.fromIterables([], []);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(0, map.length);
+  Expect.equals(0, map.keys.length);
+  Expect.equals(0, map.values.length);
+}
+
+void fewerValuesIterableTest() {
+  Expect.throws(() => new SplayTreeMap.fromIterables([1,2], [0]));
+}
+
+void fewerKeysIterableTest() {
+  Expect.throws(() => new SplayTreeMap.fromIterables([1], [0,2]));
+}
+
+void equalElementsTest() {
+  var map = new SplayTreeMap.fromIterables([1, 2, 2], ["one", "two", "three"]);
+
+  Expect.isTrue(map is Map);
+  Expect.isTrue(map is SplayTreeMap);
+  Expect.isFalse(map is HashMap);
+
+  Expect.equals(2, map.length);
+  Expect.equals(2, map.keys.length);
+  Expect.equals(2, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("three", map[2]);
+}
+
+
+void genericTypeTest() {
+  var map = new SplayTreeMap<int, String>.fromIterables(
+      [1, 2, 3], ["one", "two", "three"]);
+  Expect.isTrue(map is Map<int, String>);
+  Expect.isTrue(map is SplayTreeMap<int, String>);
+
+  // Make sure it is not just SplayTreeMap<dynamic, dynamic>.
+  Expect.isFalse(map is SplayTreeMap<String, dynamic>);
+  Expect.isFalse(map is SplayTreeMap<dynamic, int>);
+
+  Expect.equals(3, map.length);
+  Expect.equals(3, map.keys.length);
+  Expect.equals(3, map.values.length);
+
+  Expect.equals("one", map[1]);
+  Expect.equals("two", map[2]);
+  Expect.equals("three", map[3]);
+}
diff --git a/tests/html/html.status b/tests/html/html.status
index 9aa3976..e16c75d 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -308,6 +308,7 @@
 websql_test/supported: Fail
 
 [ $runtime == ff ]
+xhr_test/xhr: Pass, Fail # Issue 11602
 dart_object_local_storage_test: Skip  # sessionStorage NS_ERROR_DOM_NOT_SUPPORTED_ERR
 dromaeo_smoke_test: Pass, Fail # Issue: 8257
 webgl_1_test: Pass, Fail   # Issue 8219
diff --git a/tests/html/indexeddb_1_test.dart b/tests/html/indexeddb_1_test.dart
index 7fb41fb..63b9156 100644
--- a/tests/html/indexeddb_1_test.dart
+++ b/tests/html/indexeddb_1_test.dart
@@ -27,9 +27,8 @@
     }).then((_) {
       return html.window.indexedDB.open(dbName, version: 2,
           onUpgradeNeeded: (e) {
-            // Bug 8265, we're getting the wrong type here.
-            //expect(e.oldVersion, 1);
-            //expect(e.newVersion, 2);
+            expect(e.oldVersion, 1);
+            expect(e.newVersion, 2);
             upgraded = true;
           });
     }).then((_) {
diff --git a/tests/html/safe_dom_test.dart b/tests/html/safe_dom_test.dart
index 5e7ae35..686c4e0 100644
--- a/tests/html/safe_dom_test.dart
+++ b/tests/html/safe_dom_test.dart
@@ -76,8 +76,8 @@
   } else {
     contextElement.innerHtml = html;
     var fragment = new DocumentFragment();;
-    while (contextElement.$dom_firstChild != null) {
-      fragment.append(contextElement.$dom_firstChild);
+    while (contextElement.firstChild != null) {
+      fragment.append(contextElement.firstChild);
     }
     return fragment;
   }
diff --git a/tests/language/allocation_sinking_vm_test.dart b/tests/language/allocation_sinking_vm_test.dart
index 2320df3..89ad287 100644
--- a/tests/language/allocation_sinking_vm_test.dart
+++ b/tests/language/allocation_sinking_vm_test.dart
@@ -103,6 +103,41 @@
   return a.x - a.y;
 }
 
+class WithFinal {
+  final _x;
+  WithFinal(this._x);
+}
+
+testInitialValueForFinalField(x) {
+  new WithFinal(x);
+}
+
+testFinalField() {
+  for (var i = 0; i < 10000; i++) {
+   testInitialValueForFinalField(1);
+  }
+}
+
+class V {
+  var x = 0;
+}
+
+test_vm_field() {
+  var obj;
+  inner() => obj.x = 42;
+  var a = new V();
+  obj = a;
+  var t1 = a.x;
+  var t2 = inner();
+  return a.x + t1 + t2;
+}
+
+testVMField() {
+  Expect.equals(84, test_vm_field());
+  for (var i=0; i<15000; i++) test_vm_field();
+  Expect.equals(84, test_vm_field());
+}
+
 main() {
   var c = new C(new Point(0.1, 0.2));
 
@@ -147,4 +182,7 @@
   final z2 = testIdentity(new F(c.p));
   Expect.equals(z0, z1);
   Expect.equals(z0, z2);
+
+  testFinalField();
+  testVMField();
 }
diff --git a/tests/language/argument_definition2_test.dart b/tests/language/argument_definition2_test.dart
deleted file mode 100644
index cd458f0..0000000
--- a/tests/language/argument_definition2_test.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-
-test1(bool passed, [a = 42]) {
-  if (passed) {
-    Expect.equals(54, a);
-    Expect.isTrue(?a);
-  } else {
-    Expect.equals(42, a);
-    Expect.isFalse(?a);
-  }
-  Expect.isTrue(?passed);
-}
-
-test2() {
-  var closure = (passed, [a = 42]) {
-    if (passed) {
-      Expect.equals(54, a);
-      Expect.isTrue(?a);
-    } else {
-      Expect.equals(42, a);
-      Expect.isFalse(?a);
-    }
-    Expect.isTrue(?passed);
-  };
-  closure(true, 54);
-  closure(false);
-}
-
-class A {
-  test3(bool passed, [a = 42]) {
-    if (passed) {
-      Expect.equals(54, a);
-      Expect.isTrue(?a);
-    } else {
-      Expect.equals(42, a);
-      Expect.isFalse(?a);
-    }
-    Expect.isTrue(?passed);
-  }
-}
-
-
-test4(bool passed, [a]) {
-  if (passed) {
-    Expect.equals(54, a);
-    Expect.isTrue(?a);
-  } else {
-    Expect.equals(null, a);
-    Expect.isFalse(?a);
-  }
-  Expect.isTrue(?passed);
-}
-
-int inscrutable(int x) => x == 0 ? 0 : x | inscrutable(x & (x - 1));
-
-main() {
-  test1(true, 54);
-  test1(false);
-  test2();
-  new A().test3(true, 54);
-  new A().test3(false);
-
-  var things = [test1, test2, new A().test3];
-
-  var closure = things[inscrutable(0)];
-  closure(true, 54);
-  closure(false);
-
-  closure = things[inscrutable(1)];
-  closure();
-
-  closure = things[inscrutable(2)];
-  closure(true, 54);
-  closure(false);
-
-  test4(true, 54);
-  test4(false);
-}
diff --git a/tests/language/argument_definition3_test.dart b/tests/language/argument_definition3_test.dart
deleted file mode 100644
index 0f9a125..0000000
--- a/tests/language/argument_definition3_test.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-
-main() {
-  new Param.test1(false);
-  new Param.test1(true, 42);
-
-  new Param.test2(false);
-  new Param.test2(true, 42);
-
-  new Param.test3(false);
-  new Param.test3(true, 42);
-
-  new Param.test4();
-  new Param.test5();
-
-  new Param.test6(false);
-  new Param.test6(true, 42);
-
-  new Param.test7();
-  new Param.test8();
-}
-
-class Super {
-  var superField;
-  var otherSuperField;
-
-  Super();
-  Super.withParameters(passed, op, value) {
-    Expect.equals(passed, op);
-    Expect.equals(passed ? 42 : 0, value);
-  }
-
-  Super.withOptional(passed, [int a]) : superField = ?a {
-    Expect.equals(passed, ?a);
-    Expect.equals(passed, superField);
-  }
-
-  Super.withUpdate(passed, [int a = 0])
-      : superField = ?a, otherSuperField = a++ {
-    Expect.equals(passed, ?a);
-    Expect.equals(passed, superField);
-    Expect.equals(passed ? 43 : 1, a);
-  }
-}
-
-class Param extends Super {
-  var field;
-  var otherField;
-
-  Param.test1(a_check, [int a]) {
-    Expect.equals(a_check, ?a);
-  }
-
-  Param.test2(passed, [int a]) : field = ?a {
-    Expect.equals(passed, ?a);
-    Expect.equals(passed, field);
-  }
-
-  Param.test3(passed, [int a = 0]) : super.withParameters(passed, ?a, a) {
-    Expect.equals(passed, ?a);
-  }
-
-  Param.test4() : super.withOptional(true, 42);
-  Param.test5() : super.withOptional(false);
-
-  Param.test6(passed, [int a = 0]) : field = ?a, otherField = a++ {
-    Expect.equals(passed, ?a);
-    Expect.equals(passed, field);
-    Expect.equals(passed ? 43 : 1, a);
-  }
-
-  Param.test7() : super.withUpdate(true, 42);
-  Param.test8() : super.withUpdate(false);
-}
diff --git a/tests/language/argument_definition4_test.dart b/tests/language/argument_definition4_test.dart
deleted file mode 100644
index 69ed794..0000000
--- a/tests/language/argument_definition4_test.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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";
-
-test1(bool passed, {a: 42}) {
-  if (passed) {
-    Expect.equals(54, a);
-    Expect.isTrue(?a);
-  } else {
-    Expect.equals(42, a);
-    Expect.isFalse(?a);
-  }
-  Expect.isTrue(?passed);
-}
-
-test2() {
-  var closure = (passed, {a: 42}) {
-    if (passed) {
-      Expect.equals(54, a);
-      Expect.isTrue(?a);
-    } else {
-      Expect.equals(42, a);
-      Expect.isFalse(?a);
-    }
-    Expect.isTrue(?passed);
-  };
-  closure(true, a:54);
-  closure(false);
-}
-
-class A {
-  test3(bool passed, {a: 42}) {
-    if (passed) {
-      Expect.equals(54, a);
-      Expect.isTrue(?a);
-    } else {
-      Expect.equals(42, a);
-      Expect.isFalse(?a);
-    }
-    Expect.isTrue(?passed);
-  }
-}
-
-
-test4(bool passed, {a}) {
-  if (passed) {
-    Expect.equals(54, a);
-    Expect.isTrue(?a);
-  } else {
-    Expect.equals(null, a);
-    Expect.isFalse(?a);
-  }
-  Expect.isTrue(?passed);
-}
-
-int inscrutable(int x) => x == 0 ? 0 : x | inscrutable(x & (x - 1));
-
-main() {
-  test1(true, a:54);
-  test1(false);
-  test2();
-  new A().test3(true, a:54);
-  new A().test3(false);
-
-  var things = [test1, test2, new A().test3];
-
-  var closure = things[inscrutable(0)];
-  closure(true, a:54);
-  closure(false);
-
-  closure = things[inscrutable(1)];
-  closure();
-
-  closure = things[inscrutable(2)];
-  closure(true, a:54);
-  closure(false);
-
-  test4(true, a:54);
-  test4(false);
-}
diff --git a/tests/language/argument_definition5_test.dart b/tests/language/argument_definition5_test.dart
deleted file mode 100644
index ae8af0a..0000000
--- a/tests/language/argument_definition5_test.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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";
-
-var x = "";
-
-test(String str, [onError(String)]) {
-  return (() {
-    try {
-      throw "";
-    } catch(e) {
-      if (?onError) {
-        onError(str);
-      } else {
-        x = "${str} error";
-      }
-    }
-  });
-}
-
-ignoreError(String str) {
-  x = "${str} error ignored";
-}
-
-main() {
-  Expect.equals("", x);
-  test("test")();
-  Expect.equals("test error", x);
-  test("test", ignoreError)();
-  Expect.equals("test error ignored", x);
-}
diff --git a/tests/language/argument_definition6_test.dart b/tests/language/argument_definition6_test.dart
deleted file mode 100644
index 5ac86b4..0000000
--- a/tests/language/argument_definition6_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Regression test for
-// https://code.google.com/p/dart/issues/detail?id=9090.
-// Parameters used to be passed in the wrong order in a constructor in the
-// presence of parameter checks.
-
-import 'package:expect/expect.dart';
-
-class A {
-  A(expect1, expect2, value1, value2, {layers, serviceUrl}) {
-    Expect.equals(expect1, ?layers);
-    Expect.equals(expect2, ?serviceUrl);
-    Expect.equals(value1, layers);
-    Expect.equals(value2, serviceUrl);
-  }
-}
-
-main() {
-  new A(false, false, null, null);
-  new A(true, false, 42, null, layers: 42);
-  new A(false, true, null, 43, serviceUrl: 43);
-  new A(true, true, 42, 43, layers: 42, serviceUrl: 43);
-  new A(true, true, 42, 43, serviceUrl: 43, layers: 42);
-}
diff --git a/tests/language/argument_definition_test.dart b/tests/language/argument_definition_test.dart
index 31d8431d..2fa1f1a 100644
--- a/tests/language/argument_definition_test.dart
+++ b/tests/language/argument_definition_test.dart
@@ -1,78 +1,16 @@
 // 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.
-// Dart test program for testing argument definition test.
+// Dart test program for testing that the argument definition test has been
+// removed.
 
 import "package:expect/expect.dart";
 
-int test(int a, {int b: 2, int c: 3}) {
-  int result = 0;
-  ?b;
-  ?result;  /// 01: compile-time error
-  if (?a) {
-    result += 100;
-  }
-  if (?b) {
-    result += 20;
-  }
-  if (?c) {
-    var b; ?b;  /// 02: compile-time error
-    result += 3;
-  }
-  if ((!?a?!?b:!?c) == (?a??b:?c)) {
-    result += 200;
-  }
-  if (!?a?!?b:!?c == ?a??b:?c) {
-    result += 400;
-  }
-  return result;
+int test(a, {b, c}) {
+  if (?b) return b;  /// 01: compile-time error
+  return a + b + c;
 }
 
-closure_test(int a, {int b: 2, int c: 3}) {
-  var x = 0;
-  return () {
-    int result = 0;
-    ?b;
-    ?result;  /// 03: compile-time error
-    ?x;  /// 04: compile-time error
-    if (?a) {
-      result += 100;
-    }
-    if (?b) {
-      result += 20;
-    }
-    if (?c) {
-      var b; ?b;  /// 05: compile-time error
-      result += 3;
-    }
-    // Equivalent to: (!?c) == ?b.
-    if ((!?a?!?b:!?c) == (?a??b:?c)) {
-      result += 200;
-    }
-    // Equivalent to: (!?c) ? ?b : ?c.
-    if (!?a?!?b:!?c == ?a??b:?c) {
-      result += 400;
-    }
-    return result;
-  };
-}
-
-tl_test([a]) => ?a;
-
 main() {
-  // Use a loop to test optimized version as well.
-  for (int i = 0; i < 1000; i++) {
-    Expect.equals(100, test(1));
-    Expect.equals(720, test(1, b: 2));
-    Expect.equals(523, test(1, b: 2, c: 3));
-    Expect.equals(703, test(1, c: 3));
-
-    Expect.equals(100, closure_test(1)());
-    Expect.equals(720, closure_test(1, b: 2)());
-    Expect.equals(523, closure_test(1, b: 2, c: 3)());
-    Expect.equals(703, closure_test(1, c: 3)());
-
-    Expect.equals(true, tl_test(0));
-    Expect.equals(false, tl_test());
-  }
+  Expect.equals(6, test(1, b: 2, c:3));
 }
diff --git a/tests/language/class_syntax2_test.dart b/tests/language/class_syntax2_test.dart
new file mode 100644
index 0000000..e884c23
--- /dev/null
+++ b/tests/language/class_syntax2_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.
+
+// Regression test for dart2js bug http://dartbug.com/11570.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  var c = new Cool(true);
+  Expect.stringEquals('{}', '${c.thing}');
+
+  c = new Cool(false);
+  Expect.stringEquals('[]', '${c.thing}');
+
+  c = new Cool.alt(true);
+  Expect.stringEquals('{}', '${c.thing}');
+
+  c = new Cool.alt(false);
+  Expect.stringEquals('[]', '${c.thing}');
+}
+
+class Cool {
+  final thing;
+
+  Cool(bool option) : thing = option ? <String, String>{} : <String>[];
+  Cool.alt(bool option) : thing = !option ? <String>[] : <String, String>{};
+}
diff --git a/tests/language/constructor8_test.dart b/tests/language/constructor8_test.dart
index 9f05e14..e11d757 100644
--- a/tests/language/constructor8_test.dart
+++ b/tests/language/constructor8_test.dart
@@ -9,12 +9,6 @@
 class A {
   var b;
 
-  // The parameter check here used to confuse the SSA builder when it
-  // created the call to the constructor body.
-  A([Map a]) : b = ?a {
-    Expect.isTrue(b);
-  }
-
   // The closure in the constructor body used to confuse the SSA builder
   // when it created the call to the constructor body.
   A.withClosure(Map a) {
@@ -27,8 +21,6 @@
 }
 
 main() {
-  new A(null);
-  new A({});
   new A.withClosure(null);
   new A.withClosure({});
 }
diff --git a/tests/language/language.status b/tests/language/language.status
index 34b57d0..e409ff6 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -85,9 +85,6 @@
 type_variable_field_initializer_closure_test: Crash # issue 8847
 
 
-execute_finally10_test: Fail # Issue 430
-execute_finally11_test: Fail # Issue 430
-
 [ $compiler == none && $unchecked ]
 
 # Only checked mode reports an error on type assignment
@@ -405,9 +402,6 @@
 bad_constructor_test/05: Fail
 bad_constructor_test/06: Fail
 argument_definition_test/*: Skip # Not implemented.
-argument_definition2_test: Skip # Not implemented. Fails in minified tests.
-argument_definition3_test: Skip # Not implemented. Fails in minified tests.
-argument_definition4_test: Skip # Not implemented. Fails in minified tests.
 const_var_test: Pass, Fail # Map literals take 2 type arguments.
 map_literal3_test: Fail # Map literals take 2 type arguments.
 class_cycle_negative_test: Fail, OK # Bad test: assumes eager loading.
@@ -508,9 +502,6 @@
 type_variable_field_initializer_closure_test: Crash # VM bug: issue 8847
 
 
-execute_finally10_test: Fail # VM bug: issue 430
-execute_finally11_test: Fail # VM bug: issue 430
-
 bound_closure_equality_test: Fail # Issue 10849
 
 [ $compiler == dart2dart && $minified ]
@@ -570,8 +561,6 @@
 
 
 [ $arch == simarm || $arch == arm ]
-deopt_smi_op_test: Fail
-gc_test: Crash
 stack_overflow_test: Crash, Pass # Passes on HW in release mode.
 stack_overflow_stacktrace_test: Crash, Pass # Passes on HW in release mode.
 
@@ -582,11 +571,6 @@
 
 [ $arch == simmips ]
 arithmetic_test: Crash  # Too far relative branch.
-deopt_smi_op_test: Fail
-gc_test: Crash
-invocation_mirror_test: Fail
-large_implicit_getter_test: Crash
-load_to_load_forwarding_vm_test: Fail
-named_parameters_with_conversions_test: Pass, Crash
+large_implicit_getter_test: Crash  # Too far relative branch.
 stack_overflow_test: Crash
 stack_overflow_stacktrace_test: Crash
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 2d51605..c63c228 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dartanalyzer ]
+argument_definition_test/01: fail  # issue 11565
 abstract_factory_constructor_test/00: fail
 assign_instance_method_negative_test: fail
 assign_static_type_test/06: fail
@@ -71,9 +72,6 @@
 final_variable_assignment_test/04: fail
 first_class_types_constants_test: fail
 for_in2_test: fail
-function_type_alias5_test/00: fail
-function_type_alias5_test/01: fail
-function_type_alias5_test/02: fail
 getter_no_setter2_test/00: fail
 getter_no_setter2_test/03: fail
 getter_no_setter_test/00: fail
@@ -233,6 +231,18 @@
 const_escape_frog_test: fail
 compile_time_constant_test/none: fail
 
+# Test issue 11544, using @TypeName as annotation is not valid
+inferrer_constructor2_test: fail
+inferrer_constructor3_test: fail
+multiple_field_assignment_constructor_test: fail
+
+# Test issue 11545, using not existing constructor name in annotation
+metadata_test: fail
+
+# Test issue 11564, named parameter starts with '_'
+named_parameters_with_object_property_names_test: fail
+
+
 [ $compiler == dartanalyzer && $checked ]
 factory1_test/00: fail
 factory1_test/01: fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 2d90fec..e3d7687 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -27,24 +27,7 @@
 class_literal_test/28: Fail # Class literals are expression now; delete this test.
 class_literal_test/29: Fail # Class literals are expression now; delete this test.
 
-argument_definition2_test: Fail, OK # Depends on ?parameter check.
-argument_definition3_test: Fail, OK # Depends on ?parameter check.
-argument_definition4_test: Fail, OK # Depends on ?parameter check.
-argument_definition5_test: Fail, OK # Depends on ?parameter check.
-argument_definition6_test: Fail, OK # Depends on ?parameter check.
-argument_definition_test/none: Fail, OK # Depends on ?parameter check.
-constructor8_test: Fail, OK # Depends on ?parameter check.
 constructor_initializer_test: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/01: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/02: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/03: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/04: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/05: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/06: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/07: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/08: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/09: Fail, OK # Depends on ?parameter check.
-optional_named_parameters_test/none: Fail, OK # Depends on ?parameter check.
 
 # Fails due to inlining. Not all expected frames are in the trace.
 full_stacktrace1_test: Pass, Fail  # issue 9895
diff --git a/tests/language/load_to_load_forwarding_vm_test.dart b/tests/language/load_to_load_forwarding_vm_test.dart
index 2f0a766..c62b66a 100644
--- a/tests/language/load_to_load_forwarding_vm_test.dart
+++ b/tests/language/load_to_load_forwarding_vm_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 // Test correctness of side effects tracking used by load to load forwarding.
 
+// VMOptions=--optimization-counter-threshold=10
+
 import "package:expect/expect.dart";
 import "dart:typed_data";
 
@@ -206,7 +208,7 @@
 
   final obj = new X(new X(new X(null)));
 
-  for (var i = 0; i < 2000; i++) {
+  for (var i = 0; i < 20; i++) {
     Expect.listEquals([0x02010000, 0x03020100], foo(new A(0, 0)));
     Expect.listEquals([0x02010000, 0x03020100], bar(new A(0, 0), false));
     Expect.listEquals([0x04020000, 0x03020100], bar(new A(0, 0), true));
diff --git a/tests/language/optional_named_parameters_test.dart b/tests/language/optional_named_parameters_test.dart
index 70b770a..770e732 100644
--- a/tests/language/optional_named_parameters_test.dart
+++ b/tests/language/optional_named_parameters_test.dart
@@ -49,11 +49,11 @@
   }
 
   static int F41(int a, {int b: 20, int c, int d: 40}) {
-    return 100*(100*(100*a + b) + (?c ? c : 0)) + d;
+    return 100*(100*(100*a + b) + ((c != null) ? c : 0)) + d;
   }
 
   int f52(int a, {int b: 20, int c, int d: 40}) {
-    return 100*(100*(100*a + b) + (?c ? c : 0)) + d;
+    return 100*(100*(100*a + b) + ((c != null) ? c : 0)) + d;
   }
 
   static void test() {
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 2488346..bedba2b 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -102,6 +102,8 @@
 mirrors/superclass_test: Fail # http://dartbug.com/11142
 mirrors/reflectively_instantiate_uninstantiated_class_test: Fail # http://dartbug.com/11187
 mirrors/reflect_model_test: Fail # http://dartbug.com/11219
+mirrors/parameter_test: Fail # http://dartbug.com/11567
+mirrors/metadata_constructed_constant_test: Fail # http://dartbug.com/11609
 
 [ $compiler == none && $runtime == drt ]
 async/timer_isolate_test: Skip # See Issue 4997
@@ -116,10 +118,16 @@
 
 
 [ $arch == arm || $arch == simarm ]
-*: Skip
+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
 
 [ $arch == mips ]
 *: Skip
 
 [ $arch == simmips ]
-*: Skip
+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/mirrors/constructors_test.dart b/tests/lib/mirrors/constructors_test.dart
index 1a717a7..b42472f 100644
--- a/tests/lib/mirrors/constructors_test.dart
+++ b/tests/lib/mirrors/constructors_test.dart
@@ -8,7 +8,7 @@
 
 import 'package:expect/expect.dart';
 
-import 'reflect_model_test.dart';
+import 'stringify.dart';
 
 class Foo {
 }
@@ -45,4 +45,21 @@
          ' Biz.named: Method(s(Biz.named) in s(Biz), constructor)}',
          bizConstructors);
   print(bizConstructors);
+
+  expect('[]', fooConstructors.values.single.parameters);
+  expect('[]', barConstructors.values.single.parameters);
+  expect('[]', bazConstructors.values.single.parameters);
+  for (var constructor in bizConstructors.values) {
+    expect('[]', constructor.parameters);
+  }
+
+  expect('[s()]',
+         fooConstructors.values.map((m) => m.constructorName).toList());
+  expect('[s()]',
+         barConstructors.values.map((m) => m.constructorName).toList());
+  expect('[s(named)]',
+         bazConstructors.values.map((m) => m.constructorName).toList());
+  expect('[s(), s(named)]',
+         bizConstructors.values.map((m) => m.constructorName).toList()
+             ..sort(compareSymbols));
 }
diff --git a/tests/lib/mirrors/intercepted_class_test.dart b/tests/lib/mirrors/intercepted_class_test.dart
index a17b7e9..2fde1b7 100644
--- a/tests/lib/mirrors/intercepted_class_test.dart
+++ b/tests/lib/mirrors/intercepted_class_test.dart
@@ -8,7 +8,7 @@
 
 import 'dart:mirrors';
 
-import 'reflect_model_test.dart' show stringify, expect;
+import 'stringify.dart' show stringify, expect;
 
 checkClassMirror(ClassMirror cls, String name) {
   expect('s($name)', cls.simpleName);
diff --git a/tests/lib/mirrors/intercepted_object_test.dart b/tests/lib/mirrors/intercepted_object_test.dart
index 26016e1..17c9783 100644
--- a/tests/lib/mirrors/intercepted_object_test.dart
+++ b/tests/lib/mirrors/intercepted_object_test.dart
@@ -8,7 +8,7 @@
 
 import 'dart:mirrors';
 
-import 'reflect_model_test.dart' show stringify, expect;
+import 'stringify.dart' show stringify, expect;
 
 import 'intercepted_class_test.dart' show checkClassMirror;
 
diff --git a/tests/lib/mirrors/metadata_constructed_constant_test.dart b/tests/lib/mirrors/metadata_constructed_constant_test.dart
new file mode 100644
index 0000000..df74ff1
--- /dev/null
+++ b/tests/lib/mirrors/metadata_constructed_constant_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.metadata_constructed_constant_test;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+class ConstructedConstant {
+  final value;
+  const ConstructedConstant(this.value);
+  toString() => 'ConstructedConstant($value)';
+}
+
+class Foo {
+  @ConstructedConstant(StateError)
+  m() {}
+}
+
+main() {
+  var value =
+      reflectClass(Foo).methods[const Symbol("m")].metadata.single.reflectee;
+  Expect.stringEquals('ConstructedConstant($StateError)', '$value');
+}
diff --git a/tests/lib/mirrors/parameter_test.dart b/tests/lib/mirrors/parameter_test.dart
new file mode 100644
index 0000000..3f97939
--- /dev/null
+++ b/tests/lib/mirrors/parameter_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Test of [ParameterMirror].
+library test.parameter_test;
+
+@MirrorsUsed(targets: 'test.parameter_test', override: '*')
+import 'dart:mirrors';
+
+import 'stringify.dart';
+
+class B {
+  B();
+  B.foo(int x);
+  B.bar(int z, x);
+}
+
+main() {
+  var constructors = reflectClass(B).constructors;
+
+  expect('{B: Method(s(B) in s(B), constructor), '
+         'B.bar: Method(s(B.bar) in s(B), constructor), '
+         'B.foo: Method(s(B.foo) in s(B), constructor)}',
+         constructors);
+
+  var unnamedConstructor = constructors[new Symbol('B')];
+
+  expect('[]', unnamedConstructor.parameters);
+  expect('Type(s(B) in s(test.parameter_test), top-level)',
+         unnamedConstructor.returnType);
+
+  var fooConstructor = constructors[new Symbol('B.foo')];
+  expect('[Parameter(s(x) in s(B.foo),'
+         ' type = Type(s(int) in s(dart.core), top-level))]',
+         fooConstructor.parameters);
+  expect('Type(s(B) in s(test.parameter_test), top-level)',
+         fooConstructor.returnType);
+
+  var barConstructor = constructors[new Symbol('B.bar')];
+  expect('[Parameter(s(z) in s(B.bar),'
+         ' type = Type(s(int) in s(dart.core), top-level)), '
+         'Parameter(s(x) in s(B.bar),'
+         ' type = Type(s(dynamic), top-level))]',
+         barConstructor.parameters);
+  expect('Type(s(B) in s(test.parameter_test), top-level)',
+         barConstructor.returnType);
+
+  print(constructors);
+}
diff --git a/tests/lib/mirrors/reflect_model_test.dart b/tests/lib/mirrors/reflect_model_test.dart
index 567651c..e5eabdf 100644
--- a/tests/lib/mirrors/reflect_model_test.dart
+++ b/tests/lib/mirrors/reflect_model_test.dart
@@ -9,67 +9,10 @@
 import 'package:expect/expect.dart';
 
 import 'model.dart';
+import 'stringify.dart';
 
 isNoSuchMethodError(e) => e is NoSuchMethodError;
 
-name(DeclarationMirror mirror) {
-  return (mirror == null) ? '<null>' : stringify(mirror.simpleName);
-}
-
-stringifyMap(Map map) {
-  var buffer = new StringBuffer('{');
-  bool first = true;
-  for (String key in map.keys.map(MirrorSystem.getName).toList()..sort()) {
-    if (!first) buffer.write(', ');
-    first = false;
-    buffer.write(key);
-    buffer.write(': ');
-    buffer.write(stringify(map[new Symbol(key)]));
-  }
-  return (buffer..write('}')).toString();
-}
-
-stringifySymbol(Symbol symbol) => 's(${MirrorSystem.getName(symbol)})';
-
-writeDeclarationOn(DeclarationMirror mirror, StringBuffer buffer) {
-  buffer.write(stringify(mirror.simpleName));
-  if (mirror.owner != null) {
-    buffer.write(' in ');
-    buffer.write(name(mirror.owner));
-  }
-  if (mirror.isPrivate) buffer.write(', private');
-  if (mirror.isTopLevel) buffer.write(', top-level');
-}
-
-stringifyVariable(VariableMirror variable) {
-  var buffer = new StringBuffer('Variable(');
-  writeDeclarationOn(variable, buffer);
-  if (variable.isStatic) buffer.write(', static');
-  if (variable.isFinal) buffer.write(', final');
-  return (buffer..write(')')).toString();
-}
-
-stringifyMethod(MethodMirror method) {
-  var buffer = new StringBuffer('Method(');
-  writeDeclarationOn(method, buffer);
-  if (method.isStatic) buffer.write(', static');
-  if (method.isGetter) buffer.write(', getter');
-  if (method.isSetter) buffer.write(', setter');
-  if (method.isConstructor) buffer.write(', constructor');
-  return (buffer..write(')')).toString();
-}
-
-stringify(value) {
-  if (value is Map) return stringifyMap(value);
-  if (value is VariableMirror) return stringifyVariable(value);
-  if (value is MethodMirror) return stringifyMethod(value);
-  if (value is Symbol) return stringifySymbol(value);
-  if (value == null) return '<null>';
-  throw 'Unexpected value: $value';
-}
-
-expect(expected, actual) => Expect.stringEquals(expected, stringify(actual));
-
 main() {
   var unnamed = new Symbol('');
   var field = new Symbol('field');
diff --git a/tests/lib/mirrors/return_type_test.dart b/tests/lib/mirrors/return_type_test.dart
new file mode 100644
index 0000000..db4ad76
--- /dev/null
+++ b/tests/lib/mirrors/return_type_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Test of [MethodMirror.returnType].
+library test.return_type_test;
+
+@MirrorsUsed(targets: 'test.return_type_test', override: '*')
+import 'dart:mirrors';
+
+import 'stringify.dart';
+
+class B {
+  f() {}
+  int g() {}
+  List h() {}
+  B i() {}
+
+  // TODO(ahe): Test this when dart2js handles parameterized types.
+  // List<int> j() {}
+}
+
+main() {
+  var methods = reflectClass(B).methods;
+
+  expect('{f: Method(s(f) in s(B)), '
+         'g: Method(s(g) in s(B)), '
+         'h: Method(s(h) in s(B)), '
+         'i: Method(s(i) in s(B))}', methods);
+
+  var f = methods[const Symbol('f')];
+  var g = methods[const Symbol('g')];
+  var h = methods[const Symbol('h')];
+  var i = methods[const Symbol('i')];
+
+  expect('Type(s(dynamic), top-level)', f.returnType);
+  expect('Type(s(int) in s(dart.core), top-level)', g.returnType);
+  expect('Type(s(List) in s(dart.core), top-level)', h.returnType);
+  expect('Type(s(B) in s(test.return_type_test), top-level)', i.returnType);
+
+  print(methods);
+}
diff --git a/tests/lib/mirrors/stringify.dart b/tests/lib/mirrors/stringify.dart
new file mode 100644
index 0000000..e8c31a8
--- /dev/null
+++ b/tests/lib/mirrors/stringify.dart
@@ -0,0 +1,109 @@
+// 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.
+
+/// Helper methods for converting a [Mirror] to a [String].
+library test.stringify;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+name(DeclarationMirror mirror) {
+  return (mirror == null) ? '<null>' : stringify(mirror.simpleName);
+}
+
+stringifyMap(Map map) {
+  var buffer = new StringBuffer();
+  bool first = true;
+  for (String key in map.keys.map(MirrorSystem.getName).toList()..sort()) {
+    if (!first) buffer.write(', ');
+    first = false;
+    buffer.write(key);
+    buffer.write(': ');
+    buffer.write(stringify(map[new Symbol(key)]));
+  }
+  return '{$buffer}';
+}
+
+stringifyList(List list) {
+  var buffer = new StringBuffer();
+  bool first = true;
+  for (String value in list.map(stringify)) {
+    if (!first) buffer.write(', ');
+    first = false;
+    buffer.write(value);
+  }
+  return '[$buffer]';
+}
+
+stringifySymbol(Symbol symbol) => 's(${MirrorSystem.getName(symbol)})';
+
+writeDeclarationOn(DeclarationMirror mirror, StringBuffer buffer) {
+  buffer.write(stringify(mirror.simpleName));
+  if (mirror.owner != null) {
+    buffer.write(' in ');
+    buffer.write(name(mirror.owner));
+  }
+  if (mirror.isPrivate) buffer.write(', private');
+  if (mirror.isTopLevel) buffer.write(', top-level');
+}
+
+writeVariableOn(VariableMirror variable, StringBuffer buffer) {
+  writeDeclarationOn(variable, buffer);
+  if (variable.isStatic) buffer.write(', static');
+  if (variable.isFinal) buffer.write(', final');
+}
+
+stringifyVariable(VariableMirror variable) {
+  var buffer = new StringBuffer();
+  writeVariableOn(variable, buffer);
+  return 'Variable($buffer)';
+}
+
+stringifyParameter(ParameterMirror parameter) {
+  var buffer = new StringBuffer();
+  writeVariableOn(parameter, buffer);
+  if (parameter.isOptional) buffer.write(', optional');
+  if (parameter.isNamed) buffer.write(', named');
+  if (parameter.hasDefaultValue) {
+    buffer.write(', value = ${stringify(parameter.defaultValue)}');
+  }
+  // TODO(ahe): Move to writeVariableOn.
+  buffer.write(', type = ${stringifyType(parameter.type)}');
+  return 'Parameter($buffer)';
+}
+
+stringifyType(TypeMirror type) {
+  var buffer = new StringBuffer();
+  writeDeclarationOn(type, buffer);
+  return 'Type($buffer)';
+}
+
+stringifyMethod(MethodMirror method) {
+  var buffer = new StringBuffer();
+  writeDeclarationOn(method, buffer);
+  if (method.isStatic) buffer.write(', static');
+  if (method.isGetter) buffer.write(', getter');
+  if (method.isSetter) buffer.write(', setter');
+  if (method.isConstructor) buffer.write(', constructor');
+  return 'Method($buffer)';
+}
+
+stringify(value) {
+  if (value is Map) return stringifyMap(value);
+  if (value is List) return stringifyList(value);
+  if (value is ParameterMirror) return stringifyParameter(value);
+  if (value is VariableMirror) return stringifyVariable(value);
+  if (value is MethodMirror) return stringifyMethod(value);
+  if (value is Symbol) return stringifySymbol(value);
+  if (value is TypeMirror) return stringifyType(value);
+  if (value == null) return '<null>';
+  throw 'Unexpected value: $value';
+}
+
+expect(expected, actual) => Expect.stringEquals(expected, stringify(actual));
+
+compareSymbols(Symbol a, Symbol b) {
+  return MirrorSystem.getName(a).compareTo(MirrorSystem.getName(b));
+}
diff --git a/tests/standalone/io/file_invalid_arguments_test.dart b/tests/standalone/io/file_invalid_arguments_test.dart
index 3ae9a9c..846e882 100644
--- a/tests/standalone/io/file_invalid_arguments_test.dart
+++ b/tests/standalone/io/file_invalid_arguments_test.dart
@@ -8,127 +8,53 @@
 import "dart:isolate";
 
 void testReadInvalidArgs(arg) {
-  var port = new ReceivePort();
   String filename = getFilename("tests/vm/data/fixed_length_file");
   var file = (new File(filename)).openSync();
-  try {
-    file.readSync(arg);
-    Expect.fail('exception expected');
-  } catch (e) {
-    Expect.isTrue(e is FileException);
-    Expect.isTrue(e.toString().contains('Invalid arguments'));
-  }
+  Expect.throws(() => file.readSync(arg),
+                (e) => e is ArgumentError);
 
-  var errors = 0;
-  var readFuture = file.read(arg);
-  readFuture.then((bytes) {
-    Expect.fail('exception expected');
-  }).catchError((error) {
-    errors++;
-    Expect.isTrue(error is FileException);
-    Expect.isTrue(error.toString().contains('Invalid arguments'));
-    file.close().then((ignore) {
-      Expect.equals(1, errors);
-      port.close();
-    });
-  });
+  Expect.throws(() => file.read(arg),
+                (e) => e is ArgumentError);
 }
 
 void testReadIntoInvalidArgs(buffer, start, end) {
-  var port = new ReceivePort();
   String filename = getFilename("tests/vm/data/fixed_length_file");
   var file = (new File(filename)).openSync();
-  try {
-    file.readIntoSync(buffer, start, end);
-    Expect.fail('exception expected');
-  } catch (e) {
-    Expect.isTrue(e is FileException);
-    Expect.isTrue(e.toString().contains('Invalid arguments'));
-  }
+  Expect.throws(() => file.readIntoSync(buffer, start, end),
+                (e) => e is ArgumentError);
 
-  var errors = 0;
-  var readIntoFuture = file.readInto(buffer, start, end);
-  readIntoFuture.then((bytes) {
-    Expect.fail('exception expected');
-  }).catchError((error) {
-    errors++;
-    Expect.isTrue(error is FileException);
-    Expect.isTrue(error.toString().contains('Invalid arguments'));
-    file.close().then((ignore) {
-      Expect.equals(1, errors);
-      port.close();
-    });
-  });
+  Expect.throws(() => file.readInto(buffer, start, end),
+                (e) => e is ArgumentError);
 }
 
 void testWriteByteInvalidArgs(value) {
-  var port = new ReceivePort();
   String filename = getFilename("tests/vm/data/fixed_length_file");
   var file = (new File("${filename}_out")).openSync(mode: FileMode.WRITE);
-  try {
-    file.writeByteSync(value);
-    Expect.fail('exception expected');
-  } catch (e) {
-    Expect.isTrue(e is FileException);
-    Expect.isTrue(e.toString().contains('Invalid argument'));
-  }
+  Expect.throws(() => file.writeByteSync(value),
+                (e) => e is ArgumentError);
 
-  var writeByteFuture = file.writeByte(value);
-  writeByteFuture.then((ignore) {
-    Expect.fail('exception expected');
-  }).catchError((error) {
-    Expect.isTrue(error is FileException);
-    Expect.isTrue(error.toString().contains('Invalid argument'));
-    file.close().then((ignore) {
-      port.close();
-    });
-  });
+  Expect.throws(() => file.writeByte(value),
+                (e) => e is ArgumentError);
 }
 
 void testWriteFromInvalidArgs(buffer, start, end) {
-  var port = new ReceivePort();
   String filename = getFilename("tests/vm/data/fixed_length_file");
   var file = (new File("${filename}_out")).openSync(mode: FileMode.WRITE);
-  try {
-    file.writeFromSync(buffer, start, end);
-    Expect.fail('exception expected');
-  } catch (e) {
-    Expect.isTrue(e is FileException);
-    Expect.isTrue(e.toString().contains('Invalid arguments'));
-  }
+  Expect.throws(() => file.writeFromSync(buffer, start, end),
+                (e) => e is ArgumentError);
 
-  var writeFromFuture = file.writeFrom(buffer, start, end);
-  writeFromFuture.then((ignore) {
-    Expect.fail('exception expected');
-  }).catchError((error) {
-    Expect.isTrue(error is FileException);
-    Expect.isTrue(error.toString().contains('Invalid arguments'));
-    file.close().then((ignore) {
-      port.close();
-    });
-  });
+  Expect.throws(() => file.writeFrom(buffer, start, end),
+                (e) => e is ArgumentError);
 }
 
 void testWriteStringInvalidArgs(string, encoding) {
-  var port = new ReceivePort();
   String filename = getFilename("tests/vm/data/fixed_length_file");
   var file = new File("${filename}_out").openSync(mode: FileMode.WRITE);
-  try {
-    file.writeStringSync(string, encoding: encoding);
-    Expect.fail('exception expected');
-  } catch (e) {
-    Expect.isTrue(e is FileException);
-  }
+  Expect.throws(() => file.writeStringSync(string, encoding: encoding),
+                (e) => e is ArgumentError);
 
-  var writeStringFuture = file.writeString(string, encoding: encoding);
-  writeStringFuture.then((ignore) {
-    Expect.fail('exception expected');
-  }).catchError((error) {
-    Expect.isTrue(error is FileException);
-    file.close().then((ignore) {
-      port.close();
-    });
-  });
+  Expect.throws(() => file.writeString(string, encoding: encoding),
+                (e) => e is ArgumentError);
 }
 
 Future futureThrows(Future result) {
diff --git a/tests/standalone/io/skipping_dart2js_compilations_helper.dart b/tests/standalone/io/skipping_dart2js_compilations_helper.dart
index 88a26c2..1728e3a 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_helper.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_helper.dart
@@ -5,7 +5,7 @@
 import 'dart:io';
 
 main() {
-  var outputFile = Platform.arguments[0];
+  var outputFile = new Options().arguments[0];
   var file = new File(outputFile);
   file.createSync();
 }
diff --git a/tests/standalone/io/stdout_close_test.dart b/tests/standalone/io/stdout_close_test.dart
new file mode 100644
index 0000000..6587bbc
--- /dev/null
+++ b/tests/standalone/io/stdout_close_test.dart
@@ -0,0 +1,21 @@
+// 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 "dart:io";
+
+void main() {
+  var dir = new Directory('').createTempSync();
+  stdout.close().then((_) {
+    var file = new File('${dir.path}/file');
+    var io = file.openSync(mode: FileMode.WRITE);
+    print("to file");
+    io.closeSync();
+    var content = file.readAsStringSync();
+    file.deleteSync();
+    dir.deleteSync();
+    Expect.equals("", content);
+  });
+}
+
diff --git a/tests/standalone/io/test_runner_exit_code_script.dart b/tests/standalone/io/test_runner_exit_code_script.dart
index 02ca770..1cfe603 100644
--- a/tests/standalone/io/test_runner_exit_code_script.dart
+++ b/tests/standalone/io/test_runner_exit_code_script.dart
@@ -10,7 +10,7 @@
 import "../../../tools/testing/dart/test_options.dart";
 
 main() {
-  var progressType = Platform.arguments[0];
+  var progressType = new Options().arguments[0];
   // Build a progress indicator.
   var startTime = new DateTime.now();
   var progress =
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index fa276c2..79a8522 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -109,7 +109,7 @@
   // Run the test_runner_test if there are no command-line options.
   // Otherwise, run one of the component tests that always pass,
   // fail, or timeout.
-  var arguments = Platform.arguments;
+  var arguments = new Options().arguments;
   if (arguments.isEmpty) {
     testProcessQueue();
   } else {
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index c855cff..afb2a39 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -10,11 +10,6 @@
 package/invalid_uri_test: Fail, OK # Fails intentionally
 
 [ $runtime == vm ]
-# Fails because checked-in dart executable is not up to date.
-io/test_runner_test: Fail
-# Fails because checked-in dart executable is not up to date.
-# Skip this because it is leaving temp directories behind when it fails.
-io/skipping_dart2js_compilations_test: Skip
 io/web_socket_test: Pass, Crash # Issue 11502
 
 [ $runtime == vm ]
@@ -64,8 +59,6 @@
 # package test issue 7392
 package/package1_test: Fail
 package/package_test: Fail
-io/test_runner_test: Fail # Library dart:uri removed.
-io/skipping_dart2js_compilations_test: Skip # Library dart:uri removed.
 
 
 # The dart:io library is created at build time from separate files, and
@@ -100,11 +93,6 @@
 # This is runtime test.
 io/process_exit_negative_test: Skip
 
-# Fails because checked-in dart executable is not up to date.
-io/test_runner_test: fail
-io/skipping_dart2js_compilations_test: fail
-
-
 [ $compiler == dart2analyzer ]
 io/file_constructor_test: fail
 io/http_cookie_date_test: fail
@@ -115,13 +103,7 @@
 io/web_socket_protocol_processor_test: fail
 53bit_overflow_literal_test/01: fail, ok
 
-# Fails because checked-in dart executable is not up to date.
-io/test_runner_test: fail
-io/skipping_dart2js_compilations_test: fail
-
-
 [ $compiler == dart2js ]
-io/test_runner_test: Fail # Import Uri does not work
 number_identity_test: Skip # Bigints and int/double diff. not supported.
 typed_data_test: Skip # dart:typed_data support needed.
 bytedata_test: Skip # dart:typed_data support needed.
@@ -140,7 +122,6 @@
 debugger/*: Skip # Do not run standalone vm debugger tests with dart2js.
 left_shift_bit_and_op_test: Skip # Integers exceed dart2js precision.
 pow_test: Skip # Precision > 53 bits.
-io/skipping_dart2js_compilations_test: Skip # Library dart:uri removed.
 http_launch_test: Skip
 53bit_overflow_test: Skip
 53bit_overflow_literal_test: Skip
@@ -169,12 +150,16 @@
 # Skip until we stabilize language tests.
 *: Skip
 
-[ $arch == arm || $arch == simarm ]
-*: Skip # Many of these tests are still flaky on arm, so skipping until we
-        # actually start working on implementing the needed features.
+[ $arch == arm ]
+*: Skip # Shared libraries problem.
+
+[ $arch == simarm ]
+out_of_memory_test: Crash
 
 [ $arch == mips ]
 *: Skip
 
 [ $arch == simmips ]
-*: Skip
+io/file_fuzz_test: Pass, Timeout
+out_of_memory_test: Crash
+
diff --git a/tests/standalone/typed_data_test.dart b/tests/standalone/typed_data_test.dart
index f8f28aa..3ea844b 100644
--- a/tests/standalone/typed_data_test.dart
+++ b/tests/standalone/typed_data_test.dart
@@ -4,6 +4,8 @@
 //
 // Dart test program for testing typed data.
 
+// VMOptions=--optimization_counter_threshold=10
+
 // Library tag to be able to run in html test framework.
 library TypedDataTest;
 
@@ -319,7 +321,7 @@
 }
 
 main() {
-  for (int i = 0; i < 2000; i++) {
+  for (int i = 0; i < 20; i++) {
     testCreateUint8TypedData();
     testCreateClampedUint8TypedData();
     testTypedDataRange(false);
diff --git a/tools/VERSION b/tools/VERSION
index a18058b2..9bd3426 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 6
-BUILD 1
+BUILD 2
 PATCH 0
diff --git a/tools/bots/android.py b/tools/bots/android.py
index 55732da..39cbb25 100644
--- a/tools/bots/android.py
+++ b/tools/bots/android.py
@@ -51,7 +51,7 @@
     # broken on Android.
     if os.path.exists('./out/lastHooksTargetOS.txt'):
       os.remove('./out/lastHooksTargetOS.txt')
-    targets = ['samples']
+    targets = ['runtime']
     args = [sys.executable, './tools/build.py', '--mode=' + build_info.mode,
             '--os=android'] + targets
     print 'Building Android: %s' % (' '.join(args))
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 1ae2fd1..ab5b51b 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -38,7 +38,6 @@
 # ......isolate/
 # ......json/
 # ......math/
-# ......mdv_observe_impl/
 # ......mirrors/
 # ......utf/
 # ......typed_data/
@@ -204,7 +203,7 @@
                   join('html', 'dart2js'), join('html', 'dartium'),
                   join('html', 'html_common'),
                   join('indexed_db', 'dart2js'), join('indexed_db', 'dartium'),
-                  'json', 'math', 'mdv_observe_impl', 'mirrors', 'typed_data',
+                  'json', 'math', 'mirrors', 'typed_data',
                   join('svg', 'dart2js'), join('svg', 'dartium'),
                   'utf',
                   join('web_audio', 'dart2js'), join('web_audio', 'dartium'),
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index 4d1b866..6bd98a6 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -261,8 +261,8 @@
     ],
 
     'WebGLRenderingContext.getShaderParameter': [
-      "@Creates('int|Null')",
-      "@Returns('int|Null')",
+      "@Creates('int|bool|Null')",
+      "@Returns('int|bool|Null')",
     ],
 
     'WebGLRenderingContext.getTexParameter': [
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index da2a88f..4908556 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -78,6 +78,7 @@
 interface_factories = monitored.Dict('generator.interface_factories', {
 })
 
+
 #
 # Custom native specs for the dart2js dom.
 #
@@ -88,13 +89,36 @@
     # tags here provided there is not conflict in usage (e.g. browser X has tag
     # T and no other browser has tag T).
 
+    'AnalyserNode': 'AnalyserNode,RealtimeAnalyserNode',
+
+    'ChannelMergerNode': 'ChannelMergerNode,AudioChannelMerger',
+    'ChannelSplitterNode': 'ChannelSplitterNode,AudioChannelSplitter',
+
+    'CSSStyleDeclaration':
+        #                    IE                   Firefox
+        'CSSStyleDeclaration,MSStyleCSSProperties,CSS2Properties',
+
     'DOMApplicationCache':
         'ApplicationCache,DOMApplicationCache,OfflineResourceList',
 
+    'HTMLTableCellElement':
+        'HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement',
+
+    'GainNode': 'GainNode,AudioGainNode',
+
+    'IDBOpenDBRequest':
+        'IDBOpenDBRequest,IDBVersionChangeRequest',
+
+    'MouseEvent': 'MouseEvent,DragEvent',
+
     'MutationObserver': 'MutationObserver,WebKitMutationObserver',
 
     'NodeList': 'NodeList,RadioNodeList',
 
+    'OscillatorNode': 'OscillatorNode,Oscillator',
+
+    'PannerNode': 'PannerNode,AudioPannerNode',
+
     'RTCPeerConnection': 'RTCPeerConnection,mozRTCPeerConnection',
 
     'RTCIceCandidate': 'RTCIceCandidate,mozRTCIceCandidate',
@@ -103,6 +127,8 @@
 
     'RTCDataChannel': 'RTCDataChannel,DataChannel',
 
+    'ScriptProcessorNode': 'ScriptProcessorNode,JavaScriptAudioNode',
+
     'TransitionEvent': 'TransitionEvent,WebKitTransitionEvent',
 
     'WebKitCSSKeyframeRule':
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 3d013e4..5e9eef4 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -265,8 +265,6 @@
   'MutationEvent.initMutationEvent',
   'Node.attributes',
   'Node.childNodes',
-  'Node.firstChild',
-  'Node.lastChild',
   'Node.localName',
   'Node.namespaceURI',
   'Node.removeChild',
diff --git a/tools/dom/src/TemplateBindings.dart b/tools/dom/src/TemplateBindings.dart
deleted file mode 100644
index 5f379da..0000000
--- a/tools/dom/src/TemplateBindings.dart
+++ /dev/null
@@ -1,789 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-// This code is a port of Model-Driven-Views:
-// https://github.com/polymer-project/mdv
-// The code mostly comes from src/template_element.js
-
-typedef void _ChangeHandler(value);
-
-/**
- * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
- * but (by design) don't attempt to implement a wide array of specialized
- * behaviors.
- *
- * Enabling these features in MDV is a matter of implementing and registering an
- * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
- * delegation functions which implement specialized behavior. This object is
- * registered with MDV via [TemplateElement.syntax]:
- *
- *
- * HTML:
- *     <template bind syntax="MySyntax">
- *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
- *     </template>
- *
- * Dart:
- *     class MySyntax extends CustomBindingSyntax {
- *       getBinding(model, path, name, node) {
- *         // The magic happens here!
- *       }
- *     }
- *
- *     ...
- *
- *     TemplateElement.syntax['MySyntax'] = new MySyntax();
- *
- * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for more
- * information about Custom Syntax.
- */
-// TODO(jmesserly): if this is just one method, a function type would make it
-// more Dart-friendly.
-@Experimental
-abstract class CustomBindingSyntax {
-  /**
-   * This syntax method allows for a custom interpretation of the contents of
-   * mustaches (`{{` ... `}}`).
-   *
-   * When a template is inserting an instance, it will invoke this method for
-   * each mustache which is encountered. The function is invoked with four
-   * arguments:
-   *
-   * - [model]: The data context for which this instance is being created.
-   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
-   * - [name]: The context in which the mustache occurs. Within element
-   *   attributes, this will be the name of the attribute. Within text,
-   *   this will be 'text'.
-   * - [node]: A reference to the node to which this binding will be created.
-   *
-   * If the method wishes to handle binding, it is required to return an object
-   * which has at least a `value` property that can be observed. If it does,
-   * then MDV will call [Node.bind on the node:
-   *
-   *     node.bind(name, retval, 'value');
-   *
-   * If the 'getBinding' does not wish to override the binding, it should return
-   * null.
-   */
-  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
-  // Normally they are String and Node respectively. But sometimes it will pass
-  // (int name, CompoundBinding node). That seems very confusing; we may want
-  // to change this API.
-  getBinding(model, String path, name, node) => null;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate model than the
-   * one the template would otherwise use when producing an instance.
-   *
-   * When a template is about to create an instance, it will invoke this method
-   * The function is invoked with two arguments:
-   *
-   * - [template]: The template element which is about to create and insert an
-   *   instance.
-   * - [model]: The data context for which this instance is being created.
-   *
-   * The template element will always use the return value of `getInstanceModel`
-   * as the model for the new instance. If the syntax does not wish to override
-   * the value, it should simply return the `model` value it was passed.
-   */
-  getInstanceModel(Element template, model) => model;
-
-  /**
-   * This syntax method allows a syntax to provide an alterate expansion of
-   * the [template] contents. When the template wants to create an instance,
-   * it will call this method with the template element.
-   *
-   * By default this will call `template.createInstance()`.
-   */
-  getInstanceFragment(Element template) => template.createInstance();
-}
-
-/** The callback used in the [CompoundBinding.combinator] field. */
-@Experimental
-typedef Object CompoundBindingCombinator(Map objects);
-
-/** Information about the instantiated template. */
-@Experimental
-class TemplateInstance {
-  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
-  // in cases where script has modified the template instance boundary.
-
-  /** The first node of this template instantiation. */
-  final Node firstNode;
-
-  /**
-   * The last node of this template instantiation.
-   * This could be identical to [firstNode] if the template only expanded to a
-   * single node.
-   */
-  final Node lastNode;
-
-  /** The model used to instantiate the template. */
-  final model;
-
-  TemplateInstance(this.firstNode, this.lastNode, this.model);
-}
-
-/**
- * Model-Driven Views contains a helper object which is useful for the
- * implementation of a Custom Syntax.
- *
- *     var binding = new CompoundBinding((values) {
- *       var combinedValue;
- *       // compute combinedValue based on the current values which are provided
- *       return combinedValue;
- *     });
- *     binding.bind('name1', obj1, path1);
- *     binding.bind('name2', obj2, path2);
- *     //...
- *     binding.bind('nameN', objN, pathN);
- *
- * CompoundBinding is an object which knows how to listen to multiple path
- * values (registered via [bind]) and invoke its [combinator] when one or more
- * of the values have changed and set its [value] property to the return value
- * of the function. When any value has changed, all current values are provided
- * to the [combinator] in the single `values` argument.
- *
- * See [CustomBindingSyntax] for more information.
- */
-// TODO(jmesserly): what is the public API surface here? I just guessed;
-// most of it seemed non-public.
-@Experimental
-class CompoundBinding extends ObservableBase {
-  CompoundBindingCombinator _combinator;
-
-  // TODO(jmesserly): ideally these would be String keys, but sometimes we
-  // use integers.
-  Map<dynamic, StreamSubscription> _bindings = new Map();
-  Map _values = new Map();
-  bool _scheduled = false;
-  bool _disposed = false;
-  Object _value;
-
-  CompoundBinding([CompoundBindingCombinator combinator]) {
-    // TODO(jmesserly): this is a tweak to the original code, it seemed to me
-    // that passing the combinator to the constructor should be equivalent to
-    // setting it via the property.
-    // I also added a null check to the combinator setter.
-    this.combinator = combinator;
-  }
-
-  CompoundBindingCombinator get combinator => _combinator;
-
-  set combinator(CompoundBindingCombinator combinator) {
-    _combinator = combinator;
-    if (combinator != null) _scheduleResolve();
-  }
-
-  static const _VALUE = const Symbol('value');
-
-  get value => _value;
-
-  void set value(newValue) {
-    _value = notifyPropertyChange(_VALUE, _value, newValue);
-  }
-
-  // TODO(jmesserly): remove these workarounds when dart2js supports mirrors!
-  getValueWorkaround(key) {
-    if (key == _VALUE) return value;
-    return null;
-  }
-  setValueWorkaround(key, val) {
-    if (key == _VALUE) value = val;
-  }
-
-  void bind(name, model, String path) {
-    unbind(name);
-
-    _bindings[name] = new PathObserver(model, path).bindSync((value) {
-      _values[name] = value;
-      _scheduleResolve();
-    });
-  }
-
-  void unbind(name, {bool suppressResolve: false}) {
-    var binding = _bindings.remove(name);
-    if (binding == null) return;
-
-    binding.cancel();
-    _values.remove(name);
-    if (!suppressResolve) _scheduleResolve();
-  }
-
-  // TODO(rafaelw): Is this the right processing model?
-  // TODO(rafaelw): Consider having a seperate ChangeSummary for
-  // CompoundBindings so to excess dirtyChecks.
-  void _scheduleResolve() {
-    if (_scheduled) return;
-    _scheduled = true;
-    queueChangeRecords(resolve);
-  }
-
-  void resolve() {
-    if (_disposed) return;
-    _scheduled = false;
-
-    if (_combinator == null) {
-      throw new StateError(
-          'CompoundBinding attempted to resolve without a combinator');
-    }
-
-    value = _combinator(_values);
-  }
-
-  void dispose() {
-    for (var binding in _bindings.values) {
-      binding.cancel();
-    }
-    _bindings.clear();
-    _values.clear();
-
-    _disposed = true;
-    value = null;
-  }
-}
-
-abstract class _InputBinding {
-  final InputElement element;
-  PathObserver binding;
-  StreamSubscription _pathSub;
-  StreamSubscription _eventSub;
-
-  _InputBinding(this.element, model, String path) {
-    binding = new PathObserver(model, path);
-    _pathSub = binding.bindSync(valueChanged);
-    _eventSub = _getStreamForInputType(element).listen(updateBinding);
-  }
-
-  void valueChanged(newValue);
-
-  void updateBinding(e);
-
-  void unbind() {
-    binding = null;
-    _pathSub.cancel();
-    _eventSub.cancel();
-  }
-
-
-  static Stream<Event> _getStreamForInputType(InputElement element) {
-    switch (element.type) {
-      case 'checkbox':
-        return element.onClick;
-      case 'radio':
-      case 'select-multiple':
-      case 'select-one':
-        return element.onChange;
-      default:
-        return element.onInput;
-    }
-  }
-}
-
-class _ValueBinding extends _InputBinding {
-  _ValueBinding(element, model, path) : super(element, model, path);
-
-  void valueChanged(value) {
-    element.value = value == null ? '' : '$value';
-  }
-
-  void updateBinding(e) {
-    binding.value = element.value;
-  }
-}
-
-class _CheckedBinding extends _InputBinding {
-  _CheckedBinding(element, model, path) : super(element, model, path);
-
-  void valueChanged(value) {
-    element.checked = _Bindings._toBoolean(value);
-  }
-
-  void updateBinding(e) {
-    binding.value = element.checked;
-
-    // Only the radio button that is getting checked gets an event. We
-    // therefore find all the associated radio buttons and update their
-    // CheckedBinding manually.
-    if (element is InputElement && element.type == 'radio') {
-      for (var r in _getAssociatedRadioButtons(element)) {
-        var checkedBinding = r._checkedBinding;
-        if (checkedBinding != null) {
-          // Set the value directly to avoid an infinite call stack.
-          checkedBinding.binding.value = false;
-        }
-      }
-    }
-  }
-
-  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
-  // Returns an array containing all radio buttons other than |element| that
-  // have the same |name|, either in the form that |element| belongs to or,
-  // if no form, in the document tree to which |element| belongs.
-  //
-  // This implementation is based upon the HTML spec definition of a
-  // "radio button group":
-  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
-  //
-  static Iterable _getAssociatedRadioButtons(element) {
-    if (!_isNodeInDocument(element)) return [];
-    if (element.form != null) {
-      return element.form.nodes.where((el) {
-        return el != element &&
-            el is InputElement &&
-            el.type == 'radio' &&
-            el.name == element.name;
-      });
-    } else {
-      var radios = element.document.queryAll(
-          'input[type="radio"][name="${element.name}"]');
-      return radios.where((el) => el != element && el.form == null);
-    }
-  }
-
-  // TODO(jmesserly): polyfill document.contains API instead of doing it here
-  static bool _isNodeInDocument(Node node) {
-    // On non-IE this works:
-    // return node.document.contains(node);
-    var document = node.document;
-    if (node == document || node.parentNode == document) return true;
-    return document.documentElement.contains(node);
-  }
-}
-
-class _Bindings {
-  // TODO(jmesserly): not sure what kind of boolean conversion rules to
-  // apply for template data-binding. HTML attributes are true if they're
-  // present. However Dart only treats "true" as true. Since this is HTML we'll
-  // use something closer to the HTML rules: null (missing) and false are false,
-  // everything else is true. See: https://github.com/polymer-project/mdv/issues/59
-  static bool _toBoolean(value) => null != value && false != value;
-
-  static Node _createDeepCloneAndDecorateTemplates(Node node, String syntax) {
-    var clone = node.clone(false); // Shallow clone.
-    if (clone is Element && clone.isTemplate) {
-      TemplateElement.decorate(clone, node);
-      if (syntax != null) {
-        clone.attributes.putIfAbsent('syntax', () => syntax);
-      }
-    }
-
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      clone.append(_createDeepCloneAndDecorateTemplates(c, syntax));
-    }
-    return clone;
-  }
-
-  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
-  static Document _getTemplateContentsOwner(HtmlDocument doc) {
-    if (doc.window == null) {
-      return doc;
-    }
-    var d = doc._templateContentsOwner;
-    if (d == null) {
-      // TODO(arv): This should either be a Document or HTMLDocument depending
-      // on doc.
-      d = doc.implementation.createHtmlDocument('');
-      while (d.$dom_lastChild != null) {
-        d.$dom_lastChild.remove();
-      }
-      doc._templateContentsOwner = d;
-    }
-    return d;
-  }
-
-  static Element _cloneAndSeperateAttributeTemplate(Element templateElement) {
-    var clone = templateElement.clone(false);
-    var attributes = templateElement.attributes;
-    for (var name in attributes.keys.toList()) {
-      switch (name) {
-        case 'template':
-        case 'repeat':
-        case 'bind':
-        case 'ref':
-          clone.attributes.remove(name);
-          break;
-        default:
-          attributes.remove(name);
-          break;
-      }
-    }
-
-    return clone;
-  }
-
-  static void _liftNonNativeChildrenIntoContent(Element templateElement) {
-    var content = templateElement.content;
-
-    if (!templateElement._isAttributeTemplate) {
-      var child;
-      while ((child = templateElement.$dom_firstChild) != null) {
-        content.append(child);
-      }
-      return;
-    }
-
-    // For attribute templates we copy the whole thing into the content and
-    // we move the non template attributes into the content.
-    //
-    //   <tr foo template>
-    //
-    // becomes
-    //
-    //   <tr template>
-    //   + #document-fragment
-    //     + <tr foo>
-    //
-    var newRoot = _cloneAndSeperateAttributeTemplate(templateElement);
-    var child;
-    while ((child = templateElement.$dom_firstChild) != null) {
-      newRoot.append(child);
-    }
-    content.append(newRoot);
-  }
-
-  static void _bootstrapTemplatesRecursivelyFrom(Node node) {
-    void bootstrap(template) {
-      if (!TemplateElement.decorate(template)) {
-        _bootstrapTemplatesRecursivelyFrom(template.content);
-      }
-    }
-
-    // Need to do this first as the contents may get lifted if |node| is
-    // template.
-    // TODO(jmesserly): node is DocumentFragment or Element
-    var descendents = (node as dynamic).queryAll(_allTemplatesSelectors);
-    if (node is Element && (node as Element).isTemplate) bootstrap(node);
-
-    descendents.forEach(bootstrap);
-  }
-
-  static final String _allTemplatesSelectors = 'template, option[template], ' +
-      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
-
-  static void _addBindings(Node node, model, [CustomBindingSyntax syntax]) {
-    if (node is Element) {
-      _addAttributeBindings(node, model, syntax);
-    } else if (node is Text) {
-      _parseAndBind(node, 'text', node.text, model, syntax);
-    }
-
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      _addBindings(c, model, syntax);
-    }
-  }
-
-  static void _addAttributeBindings(Element element, model, syntax) {
-    element.attributes.forEach((name, value) {
-      if (value == '' && (name == 'bind' || name == 'repeat')) {
-        value = '{{}}';
-      }
-      _parseAndBind(element, name, value, model, syntax);
-    });
-  }
-
-  static void _parseAndBind(Node node, String name, String text, model,
-      CustomBindingSyntax syntax) {
-
-    var tokens = _parseMustacheTokens(text);
-    if (tokens.length == 0 || (tokens.length == 1 && tokens[0].isText)) {
-      return;
-    }
-
-    // If this is a custom element, give the .xtag a change to bind.
-    node = _nodeOrCustom(node);
-
-    if (tokens.length == 1 && tokens[0].isBinding) {
-      _bindOrDelegate(node, name, model, tokens[0].value, syntax);
-      return;
-    }
-
-    var replacementBinding = new CompoundBinding();
-    for (var i = 0; i < tokens.length; i++) {
-      var token = tokens[i];
-      if (token.isBinding) {
-        _bindOrDelegate(replacementBinding, i, model, token.value, syntax);
-      }
-    }
-
-    replacementBinding.combinator = (values) {
-      var newValue = new StringBuffer();
-
-      for (var i = 0; i < tokens.length; i++) {
-        var token = tokens[i];
-        if (token.isText) {
-          newValue.write(token.value);
-        } else {
-          var value = values[i];
-          if (value != null) {
-            newValue.write(value);
-          }
-        }
-      }
-
-      return newValue.toString();
-    };
-
-    node.bind(name, replacementBinding, 'value');
-  }
-
-  static void _bindOrDelegate(node, name, model, String path,
-      CustomBindingSyntax syntax) {
-
-    if (syntax != null) {
-      var delegateBinding = syntax.getBinding(model, path, name, node);
-      if (delegateBinding != null) {
-        model = delegateBinding;
-        path = 'value';
-      }
-    }
-
-    node.bind(name, model, path);
-  }
-
-  /**
-   * Gets the [node]'s custom [Element.xtag] if present, otherwise returns
-   * the node. This is used so nodes can override [Node.bind], [Node.unbind],
-   * and [Node.unbindAll] like InputElement does.
-   */
-  // TODO(jmesserly): remove this when we can extend Element for real.
-  static _nodeOrCustom(node) => node is Element ? node.xtag : node;
-
-  static List<_BindingToken> _parseMustacheTokens(String s) {
-    var result = [];
-    var length = s.length;
-    var index = 0, lastIndex = 0;
-    while (lastIndex < length) {
-      index = s.indexOf('{{', lastIndex);
-      if (index < 0) {
-        result.add(new _BindingToken(s.substring(lastIndex)));
-        break;
-      } else {
-        // There is a non-empty text run before the next path token.
-        if (index > 0 && lastIndex < index) {
-          result.add(new _BindingToken(s.substring(lastIndex, index)));
-        }
-        lastIndex = index + 2;
-        index = s.indexOf('}}', lastIndex);
-        if (index < 0) {
-          var text = s.substring(lastIndex - 2);
-          if (result.length > 0 && result.last.isText) {
-            result.last.value += text;
-          } else {
-            result.add(new _BindingToken(text));
-          }
-          break;
-        }
-
-        var value = s.substring(lastIndex, index).trim();
-        result.add(new _BindingToken(value, isBinding: true));
-        lastIndex = index + 2;
-      }
-    }
-    return result;
-  }
-
-  static void _addTemplateInstanceRecord(fragment, model) {
-    if (fragment.$dom_firstChild == null) {
-      return;
-    }
-
-    var instanceRecord = new TemplateInstance(
-        fragment.$dom_firstChild, fragment.$dom_lastChild, model);
-
-    var node = instanceRecord.firstNode;
-    while (node != null) {
-      node._templateInstance = instanceRecord;
-      node = node.nextNode;
-    }
-  }
-
-  static void _removeAllBindingsRecursively(Node node) {
-    _nodeOrCustom(node).unbindAll();
-    for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
-      _removeAllBindingsRecursively(c);
-    }
-  }
-
-  static void _removeChild(Node parent, Node child) {
-    child._templateInstance = null;
-    if (child is Element && (child as Element).isTemplate) {
-      Element childElement = child;
-      // Make sure we stop observing when we remove an element.
-      var templateIterator = childElement._templateIterator;
-      if (templateIterator != null) {
-        templateIterator.abandon();
-        childElement._templateIterator = null;
-      }
-    }
-    child.remove();
-    _removeAllBindingsRecursively(child);
-  }
-}
-
-class _BindingToken {
-  final String value;
-  final bool isBinding;
-
-  _BindingToken(this.value, {this.isBinding: false});
-
-  bool get isText => !isBinding;
-}
-
-class _TemplateIterator {
-  final Element _templateElement;
-  final List<Node> terminators = [];
-  final CompoundBinding inputs;
-  List iteratedValue;
-
-  StreamSubscription _sub;
-  StreamSubscription _valueBinding;
-
-  _TemplateIterator(this._templateElement)
-    : inputs = new CompoundBinding(resolveInputs) {
-
-    _valueBinding = new PathObserver(inputs, 'value').bindSync(valueChanged);
-  }
-
-  static Object resolveInputs(Map values) {
-    if (values.containsKey('if') && !_Bindings._toBoolean(values['if'])) {
-      return null;
-    }
-
-    if (values.containsKey('repeat')) {
-      return values['repeat'];
-    }
-
-    if (values.containsKey('bind')) {
-      return [values['bind']];
-    }
-
-    return null;
-  }
-
-  void valueChanged(value) {
-    clear();
-    if (value is! List) return;
-
-    iteratedValue = value;
-
-    if (value is Observable) {
-      _sub = value.changes.listen(_handleChanges);
-    }
-
-    int len = iteratedValue.length;
-    if (len > 0) {
-      _handleChanges([new ListChangeRecord(0, addedCount: len)]);
-    }
-  }
-
-  Node getTerminatorAt(int index) {
-    if (index == -1) return _templateElement;
-    var terminator = terminators[index];
-    if (terminator is! Element) return terminator;
-
-    var subIterator = terminator._templateIterator;
-    if (subIterator == null) return terminator;
-
-    return subIterator.getTerminatorAt(subIterator.terminators.length - 1);
-  }
-
-  void insertInstanceAt(int index, Node fragment) {
-    var previousTerminator = getTerminatorAt(index - 1);
-    var terminator = fragment.$dom_lastChild;
-    if (terminator == null) terminator = previousTerminator;
-
-    terminators.insert(index, terminator);
-    var parent = _templateElement.parentNode;
-    parent.insertBefore(fragment, previousTerminator.nextNode);
-  }
-
-  void removeInstanceAt(int index) {
-    var previousTerminator = getTerminatorAt(index - 1);
-    var terminator = getTerminatorAt(index);
-    terminators.removeAt(index);
-
-    var parent = _templateElement.parentNode;
-    while (terminator != previousTerminator) {
-      var node = terminator;
-      terminator = node.previousNode;
-      _Bindings._removeChild(parent, node);
-    }
-  }
-
-  void removeAllInstances() {
-    if (terminators.length == 0) return;
-
-    var previousTerminator = _templateElement;
-    var terminator = getTerminatorAt(terminators.length - 1);
-    terminators.length = 0;
-
-    var parent = _templateElement.parentNode;
-    while (terminator != previousTerminator) {
-      var node = terminator;
-      terminator = node.previousNode;
-      _Bindings._removeChild(parent, node);
-    }
-  }
-
-  void clear() {
-    unobserve();
-    removeAllInstances();
-    iteratedValue = null;
-  }
-
-  getInstanceModel(model, syntax) {
-    if (syntax != null) {
-      return syntax.getInstanceModel(_templateElement, model);
-    }
-    return model;
-  }
-
-  getInstanceFragment(syntax) {
-    if (syntax != null) {
-      return syntax.getInstanceFragment(_templateElement);
-    }
-    return _templateElement.createInstance();
-  }
-
-  void _handleChanges(List<ListChangeRecord> splices) {
-    var syntax = TemplateElement.syntax[_templateElement.attributes['syntax']];
-
-    for (var splice in splices) {
-      if (splice is! ListChangeRecord) continue;
-
-      for (int i = 0; i < splice.removedCount; i++) {
-        removeInstanceAt(splice.index);
-      }
-
-      for (var addIndex = splice.index;
-          addIndex < splice.index + splice.addedCount;
-          addIndex++) {
-
-        var model = getInstanceModel(iteratedValue[addIndex], syntax);
-
-        var fragment = getInstanceFragment(syntax);
-
-        _Bindings._addBindings(fragment, model, syntax);
-        _Bindings._addTemplateInstanceRecord(fragment, model);
-
-        insertInstanceAt(addIndex, fragment);
-      }
-    }
-  }
-
-  void unobserve() {
-    if (_sub == null) return;
-    _sub.cancel();
-    _sub = null;
-  }
-
-  void abandon() {
-    unobserve();
-    _valueBinding.cancel();
-    inputs.dispose();
-  }
-}
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index e213565..eae9aa2 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -21,7 +21,6 @@
 import 'dart:isolate';
 import 'dart:json' as json;
 import 'dart:math';
-import 'dart:mdv_observe_impl';
 import 'dart:typed_data';
 // Not actually used, but imported since dart:html can generate these objects.
 import 'dart:svg' as svg;
@@ -49,7 +48,6 @@
 part '$AUXILIARY_DIR/Point.dart';
 part '$AUXILIARY_DIR/ReadyState.dart';
 part '$AUXILIARY_DIR/Rectangle.dart';
-part '$AUXILIARY_DIR/TemplateBindings.dart';
 part '$AUXILIARY_DIR/_HttpRequestUtils.dart';
 part '$AUXILIARY_DIR/Isolates.dart';
 part '$AUXILIARY_DIR/Microtask.dart';
diff --git a/tools/dom/templates/html/dartium/html_dartium.darttemplate b/tools/dom/templates/html/dartium/html_dartium.darttemplate
index 2cdb23b..54903e0 100644
--- a/tools/dom/templates/html/dartium/html_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/html_dartium.darttemplate
@@ -21,7 +21,6 @@
 import 'dart:json' as json;
 import 'dart:math';
 import 'dart:nativewrappers';
-import 'dart:mdv_observe_impl';
 import 'dart:typed_data';
 import 'dart:web_gl' as gl;
 import 'dart:web_sql';
@@ -45,7 +44,6 @@
 part '$AUXILIARY_DIR/Point.dart';
 part '$AUXILIARY_DIR/ReadyState.dart';
 part '$AUXILIARY_DIR/Rectangle.dart';
-part '$AUXILIARY_DIR/TemplateBindings.dart';
 part '$AUXILIARY_DIR/WrappedEvent.dart';
 part '$AUXILIARY_DIR/WrappedList.dart';
 part '$AUXILIARY_DIR/_HttpRequestUtils.dart';
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index c5bf740..8e4757c 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -664,27 +664,6 @@
 $endif
 
 $if DART2JS
-  @Creates('Null') // Set from Dart code; does not instantiate a native type.
-$endif
-  Map<String, StreamSubscription> _attributeBindings;
-
-  // TODO(jmesserly): I'm concerned about adding these to every element.
-  // Conceptually all of these belong on TemplateElement. They are here to
-  // support browsers that don't have <template> yet.
-  // However even in the polyfill they're restricted to certain tags
-  // (see [isTemplate]). So we can probably convert it to a (public) mixin, and
-  // only mix it in to the elements that need it.
-$if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  var _model;
-
-$if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  _TemplateIterator _templateIterator;
-
-$if DART2JS
   @Creates('Null')  // Set from Dart code; does not instantiate a native type.
 $endif
   Element _templateInstanceRef;
@@ -697,124 +676,6 @@
 
   bool _templateIsDecorated;
 
-  // TODO(jmesserly): should path be optional, and default to empty path?
-  // It is used that way in at least one path in JS TemplateElement tests
-  // (see "BindImperative" test in original JS code).
-  @Experimental
-  void bind(String name, model, String path) {
-    _bindElement(this, name, model, path);
-  }
-
-  // TODO(jmesserly): this is static to work around http://dartbug.com/10166
-  // Similar issue for unbind/unbindAll below.
-  static void _bindElement(Element self, String name, model, String path) {
-    if (self._bindTemplate(name, model, path)) return;
-
-    if (self._attributeBindings == null) {
-      self._attributeBindings = new Map<String, StreamSubscription>();
-    }
-
-    self.xtag.attributes.remove(name);
-
-    var changed;
-    if (name.endsWith('?')) {
-      name = name.substring(0, name.length - 1);
-
-      changed = (value) {
-        if (_Bindings._toBoolean(value)) {
-          self.xtag.attributes[name] = '';
-        } else {
-          self.xtag.attributes.remove(name);
-        }
-      };
-    } else {
-      changed = (value) {
-        // TODO(jmesserly): escape value if needed to protect against XSS.
-        // See https://github.com/polymer-project/mdv/issues/58
-        self.xtag.attributes[name] = value == null ? '' : '$value';
-      };
-    }
-
-    self.unbind(name);
-
-    self._attributeBindings[name] =
-        new PathObserver(model, path).bindSync(changed);
-  }
-
-  @Experimental
-  void unbind(String name) {
-    _unbindElement(this, name);
-  }
-
-  static _unbindElement(Element self, String name) {
-    if (self._unbindTemplate(name)) return;
-    if (self._attributeBindings != null) {
-      var binding = self._attributeBindings.remove(name);
-      if (binding != null) binding.cancel();
-    }
-  }
-
-  @Experimental
-  void unbindAll() {
-    _unbindAllElement(this);
-  }
-
-  static void _unbindAllElement(Element self) {
-    self._unbindAllTemplate();
-
-    if (self._attributeBindings != null) {
-      for (var binding in self._attributeBindings.values) {
-        binding.cancel();
-      }
-      self._attributeBindings = null;
-    }
-  }
-
-  // TODO(jmesserly): unlike the JS polyfill, we can't mixin
-  // HTMLTemplateElement at runtime into things that are semantically template
-  // elements. So instead we implement it here with a runtime check.
-  // If the bind succeeds, we return true, otherwise we return false and let
-  // the normal Element.bind logic kick in.
-  bool _bindTemplate(String name, model, String path) {
-    if (isTemplate) {
-      switch (name) {
-        case 'bind':
-        case 'repeat':
-        case 'if':
-          _ensureTemplate();
-          if (_templateIterator == null) {
-            _templateIterator = new _TemplateIterator(this);
-          }
-          _templateIterator.inputs.bind(name, model, path);
-          return true;
-      }
-    }
-    return false;
-  }
-
-  bool _unbindTemplate(String name) {
-    if (isTemplate) {
-      switch (name) {
-        case 'bind':
-        case 'repeat':
-        case 'if':
-          _ensureTemplate();
-          if (_templateIterator != null) {
-            _templateIterator.inputs.unbind(name);
-          }
-          return true;
-      }
-    }
-    return false;
-  }
-
-  void _unbindAllTemplate() {
-    if (isTemplate) {
-      unbind('bind');
-      unbind('repeat');
-      unbind('if');
-    }
-  }
 
   /**
    * Gets the template this node refers to.
@@ -827,7 +688,19 @@
     Element ref = null;
     var refId = attributes['ref'];
     if (refId != null) {
-      ref = document.getElementById(refId);
+      var treeScope = this;
+      while (treeScope.parentNode != null) {
+        treeScope = treeScope.parentNode;
+      }
+
+      // Note: JS code tests that getElementById is present. We can't do that
+      // easily, so instead check for the types known to implement it.
+      if (treeScope is Document ||
+          treeScope is ShadowRoot ||
+          treeScope is svg.SvgSvgElement) {
+
+        ref = treeScope.getElementById(refId);
+      }
     }
 
     return ref != null ? ref : _templateInstanceRef;
@@ -850,38 +723,20 @@
   @Experimental
   DocumentFragment createInstance() {
     _ensureTemplate();
-
-    var template = ref;
-    if (template == null) template = this;
-
-    var instance = _Bindings._createDeepCloneAndDecorateTemplates(
-        template.content, attributes['syntax']);
-
-    if (TemplateElement._instanceCreated != null) {
-      TemplateElement._instanceCreated.add(instance);
-    }
-    return instance;
+    return TemplateElement.mdvPackage(this).createInstance();
   }
 
   /**
    * The data model which is inherited through the tree.
    * This is only supported if [isTemplate] is true.
-   *
-   * Setting this will destructive propagate the value to all descendant nodes,
-   * and reinstantiate all of the nodes expanded by this template.
-   *
-   * Currently this does not support propagation through Shadow DOMs.
    */
   @Experimental
-  get model => _model;
+  get model => TemplateElement.mdvPackage(this).model;
 
   @Experimental
   void set model(value) {
     _ensureTemplate();
-
-    var syntax = TemplateElement.syntax[attributes['syntax']];
-    _model = value;
-    _Bindings._addBindings(this, model, syntax);
+    TemplateElement.mdvPackage(this).model = value;
   }
 
   // TODO(jmesserly): const set would be better
@@ -898,7 +753,8 @@
   };
 
   bool get _isAttributeTemplate => attributes.containsKey('template') &&
-      (localName == 'option' || _TABLE_TAGS.containsKey(localName));
+      (localName == 'option' || localName == 'optgroup' ||
+       _TABLE_TAGS.containsKey(localName));
 
   /**
    * Returns true if this node is a template.
@@ -907,7 +763,7 @@
    * 'template' attribute and this tag supports attribute form for backwards
    * compatibility with existing HTML parsers. The nodes that can use attribute
    * form are table elments (THEAD, TBODY, TFOOT, TH, TR, TD, CAPTION, COLGROUP
-   * and COL) and OPTION.
+   * and COL), OPTION, and OPTGROUP.
    */
   // TODO(jmesserly): this is not a public MDV API, but it seems like a useful
   // place to document which tags our polyfill considers to be templates.
diff --git a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
index a376140..68a3e9f 100644
--- a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -39,65 +39,6 @@
     return e;
   }
 
-$if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  _ValueBinding _valueBinding;
-
-$if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  _CheckedBinding _checkedBinding;
-
-  @Experimental
-  void bind(String name, model, String path) {
-    switch (name) {
-      case 'value':
-        unbind('value');
-        attributes.remove('value');
-        _valueBinding = new _ValueBinding(this, model, path);
-        break;
-      case 'checked':
-        unbind('checked');
-        attributes.remove('checked');
-        _checkedBinding = new _CheckedBinding(this, model, path);
-        break;
-      default:
-        // TODO(jmesserly): this should be "super" (http://dartbug.com/10166).
-        // Similar issue for unbind/unbindAll below.
-        Element._bindElement(this, name, model, path);
-        break;
-    }
-  }
-
-  @Experimental
-  void unbind(String name) {
-    switch (name) {
-      case 'value':
-        if (_valueBinding != null) {
-          _valueBinding.unbind();
-          _valueBinding = null;
-        }
-        break;
-      case 'checked':
-        if (_checkedBinding != null) {
-          _checkedBinding.unbind();
-          _checkedBinding = null;
-        }
-        break;
-      default:
-        Element._unbindElement(this, name);
-        break;
-    }
-  }
-
-  @Experimental
-  void unbindAll() {
-    unbind('value');
-    unbind('checked');
-    Element._unbindAllElement(this);
-  }
-
 $!MEMBERS
 }
 
diff --git a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
index 3ee3646..618df8c 100644
--- a/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLTemplateElement.darttemplate
@@ -6,6 +6,99 @@
 
 part of $LIBRARYNAME;
 
+
+/**
+ * Model-Driven Views (MDV)'s native features enables a wide-range of use cases,
+ * but (by design) don't attempt to implement a wide array of specialized
+ * behaviors.
+ *
+ * Enabling these features in MDV is a matter of implementing and registering an
+ * MDV Custom Syntax. A Custom Syntax is an object which contains one or more
+ * delegation functions which implement specialized behavior. This object is
+ * registered with MDV via [TemplateElement.syntax]:
+ *
+ *
+ * HTML:
+ *     <template bind syntax="MySyntax">
+ *       {{ What!Ever('crazy')->thing^^^I+Want(data) }}
+ *     </template>
+ *
+ * Dart:
+ *     class MySyntax extends CustomBindingSyntax {
+ *       getBinding(model, path, name, node) {
+ *         // The magic happens here!
+ *       }
+ *     }
+ *
+ *     ...
+ *
+ *     TemplateElement.syntax['MySyntax'] = new MySyntax();
+ *
+ * See <https://github.com/polymer-project/mdv/blob/master/docs/syntax.md> for
+ * more information about Custom Syntax.
+ */
+// TODO(jmesserly): if this is just one method, a function type would make it
+// more Dart-friendly.
+@Experimental
+abstract class CustomBindingSyntax {
+  /**
+   * This syntax method allows for a custom interpretation of the contents of
+   * mustaches (`{{` ... `}}`).
+   *
+   * When a template is inserting an instance, it will invoke this method for
+   * each mustache which is encountered. The function is invoked with four
+   * arguments:
+   *
+   * - [model]: The data context for which this instance is being created.
+   * - [path]: The text contents (trimmed of outer whitespace) of the mustache.
+   * - [name]: The context in which the mustache occurs. Within element
+   *   attributes, this will be the name of the attribute. Within text,
+   *   this will be 'text'.
+   * - [node]: A reference to the node to which this binding will be created.
+   *
+   * If the method wishes to handle binding, it is required to return an object
+   * which has at least a `value` property that can be observed. If it does,
+   * then MDV will call [Node.bind on the node:
+   *
+   *     node.bind(name, retval, 'value');
+   *
+   * If the 'getBinding' does not wish to override the binding, it should return
+   * null.
+   */
+  // TODO(jmesserly): I had to remove type annotations from "name" and "node"
+  // Normally they are String and Node respectively. But sometimes it will pass
+  // (int name, CompoundBinding node). That seems very confusing; we may want
+  // to change this API.
+  getBinding(model, String path, name, node) => null;
+
+  /**
+   * This syntax method allows a syntax to provide an alterate model than the
+   * one the template would otherwise use when producing an instance.
+   *
+   * When a template is about to create an instance, it will invoke this method
+   * The function is invoked with two arguments:
+   *
+   * - [template]: The template element which is about to create and insert an
+   *   instance.
+   * - [model]: The data context for which this instance is being created.
+   *
+   * The template element will always use the return value of `getInstanceModel`
+   * as the model for the new instance. If the syntax does not wish to override
+   * the value, it should simply return the `model` value it was passed.
+   */
+  getInstanceModel(Element template, model) => model;
+
+  /**
+   * This syntax method allows a syntax to provide an alterate expansion of
+   * the [template] contents. When the template wants to create an instance,
+   * it will call this method with the template element.
+   *
+   * By default this will call `template.createInstance()`.
+   */
+  getInstanceFragment(Element template) => template.createInstance();
+}
+
+
 @Experimental
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
 $!MEMBERS
@@ -15,24 +108,23 @@
   @Experimental
   DocumentFragment get content => $dom_content;
 
-  static StreamController<DocumentFragment> _instanceCreated;
 
   /**
-   * *Warning*: This is an implementation helper for Model-Driven Views and
-   * should not be used in your code.
+   * The MDV package, if available.
    *
-   * This event is fired whenever a template is instantiated via
-   * [createInstance].
+   * This can be used to initialize MDV support via:
+   *
+   *     import 'dart:html';
+   *     import 'package:mdv/mdv.dart' as mdv;
+   *     main() {
+   *       mdv.initialize();
+   *     }
    */
-  // TODO(rafaelw): This is a hack, and is neccesary for the polyfill
-  // because custom elements are not upgraded during clone()
-  @Experimental
-  static Stream<DocumentFragment> get instanceCreated {
-    if (_instanceCreated == null) {
-      _instanceCreated = new StreamController<DocumentFragment>(sync: true);
-    }
-    return _instanceCreated.stream;
-  }
+  static Function mdvPackage = (node) {
+    throw new UnsupportedError("The MDV package is not available. "
+        "You can enable it with `import 'package:mdv/mdv.dart' as mdv;` and "
+        "`mdv.initialize()`");
+  };
 
   /**
    * Ensures proper API and content model for template elements.
@@ -49,30 +141,111 @@
     // == true check because it starts as a null field.
     if (template._templateIsDecorated == true) return false;
 
-    template._templateIsDecorated = true;
-
     _injectStylesheet();
 
-    // Create content
-    if (template is! TemplateElement) {
-      var doc = _Bindings._getTemplateContentsOwner(template.document);
-      template._templateContent = doc.createDocumentFragment();
+    var templateElement = template;
+    var isNative = templateElement is TemplateElement;
+    var bootstrapContents = isNative;
+    var liftContents = !isNative;
+    var liftRoot = false;
+
+    if (!isNative && templateElement._isAttributeTemplate) {
+      if (instanceRef != null) {
+        // TODO(jmesserly): this is just an assert in MDV.
+        throw new ArgumentError('instanceRef should not be supplied for '
+            'attribute templates.');
+      }
+      templateElement = _extractTemplateFromAttributeTemplate(template);
+      isNative = templateElement is TemplateElement;
+      liftRoot = true;
+     }
+
+    templateElement._templateIsDecorated = true;
+
+    if (!isNative) {
+      var doc = _getTemplateContentsOwner(templateElement.document);
+      templateElement._templateContent = doc.createDocumentFragment();
     }
 
     if (instanceRef != null) {
-      template._templateInstanceRef = instanceRef;
-      return true; // content is empty.
-    }
-
-    if (template is TemplateElement) {
-      bootstrap(template.content);
-    } else {
-      _Bindings._liftNonNativeChildrenIntoContent(template);
+      // template is contained within an instance, its direct content must be
+      // empty
+      templateElement._templateInstanceRef = instanceRef;
+    } else if (liftContents) {
+      _liftNonNativeChildrenIntoContent(templateElement, template, liftRoot);
+    } else if (bootstrapContents) {
+      bootstrap(templateElement.content);
     }
 
     return true;
   }
 
+  // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
+  static Document _getTemplateContentsOwner(HtmlDocument doc) {
+    if (doc.window == null) {
+      return doc;
+    }
+    var d = doc._templateContentsOwner;
+    if (d == null) {
+      // TODO(arv): This should either be a Document or HTMLDocument depending
+      // on doc.
+      d = doc.implementation.createHtmlDocument('');
+      while (d.lastChild != null) {
+        d.lastChild.remove();
+      }
+      doc._templateContentsOwner = d;
+    }
+    return d;
+  }
+
+  // For non-template browsers, the parser will disallow <template> in certain
+  // locations, so we allow "attribute templates" which combine the template
+  // element with the top-level container node of the content, e.g.
+  //
+  //   <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
+  //
+  // becomes
+  //
+  //   <template repeat="{{ foo }}">
+  //   + #document-fragment
+  //     + <tr class="bar">
+  //       + <td>Bar</td>
+  //
+  static Element _extractTemplateFromAttributeTemplate(Element el) {
+    var template = el.document.$dom_createElement('template');
+    el.parentNode.insertBefore(template, el);
+
+    for (var name in el.attributes.keys.toList()) {
+      switch (name) {
+        case 'template':
+          el.attributes.remove(name);
+          break;
+        case 'repeat':
+        case 'bind':
+        case 'ref':
+          template.attributes[name] = el.attributes.remove(name);
+          break;
+      }
+    }
+
+    return template;
+  }
+
+  static void _liftNonNativeChildrenIntoContent(Element template, Element el,
+      bool useRoot) {
+
+    var content = template.content;
+    if (useRoot) {
+      content.append(el);
+      return;
+    }
+
+    var child;
+    while ((child = el.firstChild) != null) {
+      content.append(child);
+    }
+  }
+
   /**
    * This used to decorate recursively all templates from a given node.
    *
@@ -83,24 +256,26 @@
   // TODO(rafaelw): Review whether this is the right public API.
   @Experimental
   static void bootstrap(Node content) {
-    _Bindings._bootstrapTemplatesRecursivelyFrom(content);
+    void _bootstrap(template) {
+      if (!TemplateElement.decorate(template)) {
+        bootstrap(template.content);
+      }
+    }
+
+    // Need to do this first as the contents may get lifted if |node| is
+    // template.
+    // TODO(jmesserly): content is DocumentFragment or Element
+    var descendents = (content as dynamic).queryAll(_allTemplatesSelectors);
+    if (content is Element && (content as Element).isTemplate) {
+      _bootstrap(content);
+    }
+
+    descendents.forEach(_bootstrap);
   }
 
-  /**
-   * Binds all mustaches recursively starting from the [root] node.
-   *
-   * Note: this is not an official Model-Driven-Views API; it is intended to
-   * support binding the [ShadowRoot]'s content to a model.
-   */
-  // TODO(jmesserly): this is needed to avoid two <template> nodes when using
-  // bindings in a custom element's template. See also:
-  // https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
-  // Called from:
-  // https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
-  @Experimental
-  static void bindModel(Node root, model, [CustomBindingSyntax syntax]) {
-    _Bindings._addBindings(root, model, syntax);
-  }
+  static final String _allTemplatesSelectors =
+      'template, option[template], optgroup[template], ' +
+      Element._TABLE_TAGS.keys.map((k) => "$k[template]").join(", ");
 
   static bool _initStyles;
 
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index 02edf51..b17787c 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -34,12 +34,12 @@
   }
 $else
   Node get first {
-    Node result = _this.$dom_firstChild;
+    Node result = _this.firstChild;
     if (result == null) throw new StateError("No elements");
     return result;
   }
   Node get last {
-    Node result = _this.$dom_lastChild;
+    Node result = _this.lastChild;
     if (result == null) throw new StateError("No elements");
     return result;
   }
@@ -47,7 +47,7 @@
     int l = this.length;
     if (l == 0) throw new StateError("No elements");
     if (l > 1) throw new StateError("More than one element");
-    return _this.$dom_firstChild;
+    return _this.firstChild;
   }
 $endif
 
@@ -61,8 +61,7 @@
       if (!identical(otherList._this, _this)) {
         // Optimized route for copying between nodes.
         for (var i = 0, len = otherList.length; i < len; ++i) {
-          // Should use $dom_firstChild, Bug 8886.
-          _this.append(otherList[0]);
+          _this.append(otherList._this.firstChild);
         }
       }
       return;
@@ -120,7 +119,7 @@
     // This implementation of removeWhere/retainWhere is more efficient
     // than the default in ListBase. Child nodes can be removed in constant
     // time.
-    Node child = _this.$dom_firstChild;
+    Node child = _this.firstChild;
     while (child != null) {
       Node nextChild = child.nextNode;
       if (test(child) == removeMatching) {
@@ -179,6 +178,27 @@
   Node operator[](int index) => _this.$dom_childNodes[index];
 }
 
+/** Information about the instantiated template. */
+class TemplateInstance {
+  // TODO(rafaelw): firstNode & lastNode should be read-synchronous
+  // in cases where script has modified the template instance boundary.
+
+  /** The first node of this template instantiation. */
+  final Node firstNode;
+
+  /**
+   * The last node of this template instantiation.
+   * This could be identical to [firstNode] if the template only expanded to a
+   * single node.
+   */
+  final Node lastNode;
+
+  /** The model used to instantiate the template. */
+  final model;
+
+  TemplateInstance(this.firstNode, this.lastNode, this.model);
+}
+
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
   List<Node> get nodes {
     return new _ChildNodeListLazy(this);
@@ -237,8 +257,7 @@
 
       // Optimized route for copying between nodes.
       for (var i = 0, len = otherList.length; i < len; ++i) {
-        // Should use $dom_firstChild, Bug 8886.
-        this.insertBefore(otherList[0], refChild);
+        this.insertBefore(otherList._this.firstChild, refChild);
       }
     } else {
       for (var node in newNodes) {
@@ -258,26 +277,25 @@
    */
   @Experimental
   void bind(String name, model, String path) {
-    // TODO(jmesserly): should we throw instead?
-    window.console.error('Unhandled binding to Node: '
-        '$this $name $model $path');
+    TemplateElement.mdvPackage(this).bind(name, model, path);
   }
 
   /** Unbinds the attribute [name]. */
   @Experimental
-  void unbind(String name) {}
+  void unbind(String name) {
+    TemplateElement.mdvPackage(this).unbind(name);
+  }
 
   /** Unbinds all bound attributes. */
   @Experimental
-  void unbindAll() {}
-
-  TemplateInstance _templateInstance;
+  void unbindAll() {
+    TemplateElement.mdvPackage(this).unbindAll();
+  }
 
   /** Gets the template instance that instantiated this node, if any. */
   @Experimental
   TemplateInstance get templateInstance =>
-      _templateInstance != null ? _templateInstance :
-      (parent != null ? parent.templateInstance : null);
+      TemplateElement.mdvPackage(this).templateInstance;
 
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_Text.darttemplate b/tools/dom/templates/html/impl/impl_Text.darttemplate
index 2675d8b..45fb721 100644
--- a/tools/dom/templates/html/impl/impl_Text.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Text.darttemplate
@@ -9,42 +9,4 @@
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
   factory $CLASSNAME(String data) => document.$dom_createTextNode(data);
 $!MEMBERS
-
-$if DART2JS
-  @Creates('Null')  // Set from Dart code; does not instantiate a native type.
-$endif
-  StreamSubscription _textBinding;
-
-  @Experimental
-  void bind(String name, model, String path) {
-    if (name != 'text') {
-      super.bind(name, model, path);
-      return;
-    }
-
-    unbind('text');
-
-    _textBinding = new PathObserver(model, path).bindSync((value) {
-      text = value == null ? '' : '$value';
-    });
-  }
-
-  @Experimental
-  void unbind(String name) {
-    if (name != 'text') {
-      super.unbind(name);
-      return;
-    }
-
-    if (_textBinding == null) return;
-
-    _textBinding.cancel();
-    _textBinding = null;
-  }
-
-  @Experimental
-  void unbindAll() {
-    unbind('text');
-    super.unbindAll();
-  }
 }
diff --git a/tools/release/version.dart b/tools/release/version.dart
index 8e7af38..cec7a3f 100644
--- a/tools/release/version.dart
+++ b/tools/release/version.dart
@@ -149,21 +149,22 @@
 
   Future<int> getRevision() {
     if (repositoryType == RepositoryType.UNKNOWN) {
-      return new Future.immediate(0);
+      return new Future.value(0);
     }
     var isSvn = repositoryType == RepositoryType.SVN;
     var command = isSvn ? "svn" : "git";
     command = "$command${getExecutableSuffix()}";
     var arguments = isSvn ? ["info"] : ["svn", "info"];
-    ProcessOptions options = new ProcessOptions();
     // Run the command from the root to get the last changed revision for this
     // "branch". Since we have both trunk and bleeding edge in the same
     // repository and since we always build TOT we need this to get the
     // right version number.
     Path toolsDirectory = new Path(_versionFileName).directoryPath;
     Path root = toolsDirectory.join(new Path(".."));
-    options.workingDirectory = root.toNativePath();
-    return Process.run(command, arguments, options).then((result) {
+    var workingDirectory = root.toNativePath();
+    return Process.run(command,
+                       arguments,
+                       workingDirectory: workingDirectory).then((result) {
       if (result.exitCode != 0) {
         return 0;
       }
@@ -201,7 +202,7 @@
       return "$absolutePath" == '/';
     }
 
-    var currentPath = new Path(new Directory.current().path);
+    var currentPath = new Path(Directory.current.path);
     while (true) {
       if (hasDirectory(currentPath, '.svn')) {
         return RepositoryType.SVN;
diff --git a/tools/test.dart b/tools/test.dart
index fc789bf..787a1db 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -238,9 +238,9 @@
       var printFailureSummary = progressIndicator != 'buildbot';
       eventListener.add(new TestFailurePrinter(printFailureSummary, formatter));
     }
-    eventListener.add(new ProgressIndicator.fromName(progressIndicator,
-                                                     startTime,
-                                                     formatter));
+    eventListener.add(progressIndicatorFromName(progressIndicator,
+                                                startTime,
+                                                formatter));
     if (printTiming) {
       eventListener.add(new TimingPrinter(startTime));
     }
@@ -302,7 +302,7 @@
           }
         }
       }
-    }, onDone: completer.complete());
+    }, onDone: completer.complete);
   } else {
     completer.complete();
   }
diff --git a/tools/testing/dart/android.dart b/tools/testing/dart/android.dart
index 328cd07..8f79ab4 100644
--- a/tools/testing/dart/android.dart
+++ b/tools/testing/dart/android.dart
@@ -35,11 +35,8 @@
                           List<String> args,
                           [String stdin = ""]) {
   Future<String> getOutput(Stream<List<int>> stream) {
-    return stream.transform(new StringDecoder())
-        .reduce(new StringBuffer(), (buf, data) {
-          buf.write(data);
-          return buf;
-    }).then((buf) => buf.toString());
+    return stream.transform(new StringDecoder()).toList()
+        .then((data) => data.join(""));
   }
 
   DebugLogger.info("Running: '\$ $executable ${args.join(' ')}'");
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index f3d0acc..c1e696c 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -98,7 +98,7 @@
       return done;
     } else {
       _logEvent("The process is already dead.");
-      return new Future.immediate(true);
+      return new Future.value(true);
     }
   }
 
@@ -171,12 +171,13 @@
    * The binary used to run safari - changing this can be nececcary for
    * testing or using non standard safari installation.
    */
-  const String binary = "/Applications/Safari.app/Contents/MacOS/Safari";
+  static const String binary = "/Applications/Safari.app/Contents/MacOS/Safari";
 
   /**
    * We get the safari version by parsing a version file
    */
-  const String versionFile = "/Applications/Safari.app/Contents/version.plist";
+  static const String versionFile =
+      "/Applications/Safari.app/Contents/version.plist";
 
   /**
    * Directories where safari stores state. We delete these if the deleteCache
@@ -205,7 +206,7 @@
   }
 
   Future<bool> deleteIfExists(Iterator<String> paths) {
-    if (!paths.moveNext()) return new Future.immediate(true);
+    if (!paths.moveNext()) return new Future.value(true);
     Directory directory = new Directory(paths.current);
     return directory.exists().then((exists) {
       if (exists) {
@@ -226,7 +227,7 @@
   // Clears the cache if the static deleteCache flag is set.
   // Returns false if the command to actually clear the cache did not complete.
   Future<bool> clearCache() {
-    if (!deleteCache) return new Future.immediate(true);
+    if (!deleteCache) return new Future.value(true);
     var home = Platform.environment['HOME'];
     Iterator iterator = CACHE_DIRECTORIES.map((s) => "$home/$s").iterator;
     return deleteIfExists(iterator);
@@ -267,7 +268,7 @@
 
   void _createLaunchHTML(var path, var url) {
     var file = new File("${path}/launch.html");
-    var randomFile = file.openSync(FileMode.WRITE);
+    var randomFile = file.openSync(mode: FileMode.WRITE);
     var content = '<script language="JavaScript">location = "$url"</script>';
     randomFile.writeStringSync(content);
     randomFile.close();
@@ -315,7 +316,7 @@
    * The binary used to run chrome - changing this can be nececcary for
    * testing or using non standard chrome installation.
    */
-  const String binary = "google-chrome";
+  static const String binary = "google-chrome";
 
   Future<bool> start(String url) {
     _logEvent("Starting chrome browser on: $url");
@@ -324,7 +325,7 @@
       if (versionResult.exitCode != 0) {
         _logEvent("Failed to chrome get version");
         _logEvent("Make sure $binary is a valid program for running chrome");
-        return new Future.immediate(false);
+        return new Future.value(false);
       }
       version = versionResult.stdout;
       _logEvent("Got version: $version");
@@ -347,12 +348,12 @@
 }
 
 class AndroidChrome extends Browser {
-  const String viewAction = 'android.intent.action.VIEW';
-  const String mainAction = 'android.intent.action.MAIN';
-  const String chromePackage = 'com.android.chrome';
-  const String browserPackage = 'com.android.browser';
-  const String firefoxPackage = 'org.mozilla.firefox';
-  const String turnScreenOnPackage = 'com.google.dart.turnscreenon';
+  static const String viewAction = 'android.intent.action.VIEW';
+  static const String mainAction = 'android.intent.action.MAIN';
+  static const String chromePackage = 'com.android.chrome';
+  static const String browserPackage = 'com.android.browser';
+  static const String firefoxPackage = 'org.mozilla.firefox';
+  static const String turnScreenOnPackage = 'com.google.dart.turnscreenon';
 
   AndroidEmulator _emulator;
   AdbDevice _adbDevice;
@@ -406,7 +407,7 @@
         return _adbDevice.killAll().then((_) => true);
       });
     }
-    return new Future.immediate(true);
+    return new Future.value(true);
   }
 
   String toString() => "chromeOnAndroid";
@@ -417,16 +418,16 @@
    * The binary used to run firefox - changing this can be nececcary for
    * testing or using non standard firefox installation.
    */
-  const String binary = "firefox";
+  static const String binary = "firefox";
 
-  const String enablePopUp =
+  static const String enablePopUp =
       'user_pref("dom.disable_open_during_load", false);';
-  const String disableDefaultCheck =
+  static const String disableDefaultCheck =
       'user_pref("browser.shell.checkDefaultBrowser", false);';
 
   Future _createPreferenceFile(var path) {
     var file = new File("${path.toString()}/user.js");
-    var randomFile = file.openSync(FileMode.WRITE);
+    var randomFile = file.openSync(mode: FileMode.WRITE);
     randomFile.writeStringSync(enablePopUp);
     randomFile.writeStringSync(disableDefaultCheck);
     randomFile.close();
@@ -440,7 +441,7 @@
       if (versionResult.exitCode != 0) {
         _logEvent("Failed to firefox get version");
         _logEvent("Make sure $binary is a valid program for running firefox");
-        return new Future.immediate(false);
+        return new Future.value(false);
       }
       version = versionResult.stdout;
       _logEvent("Got version: $version");
@@ -776,11 +777,11 @@
 
   final String local_ip;
 
-  const String driverPath = "/driver";
-  const String nextTestPath = "/next_test";
-  const String reportPath = "/report";
-  const String waitSignal = "WAIT";
-  const String terminateSignal = "TERMINATE";
+  static const String driverPath = "/driver";
+  static const String nextTestPath = "/next_test";
+  static const String reportPath = "/report";
+  static const String waitSignal = "WAIT";
+  static const String terminateSignal = "TERMINATE";
 
   var testCount = 0;
   var httpServer;
@@ -800,8 +801,8 @@
         DebugLogger.info("Handling request to: ${request.uri.path}");
         if (request.uri.path.startsWith(reportPath)) {
           var browserId = request.uri.path.substring(reportPath.length + 1);
-          var testId = int.parse(request.queryParameters["id"].split("=")[1]);
-
+          var testId = 
+              int.parse(request.uri.queryParameters["id"].split("=")[1]);
           handleReport(request, browserId, testId);
           // handleReport will asynchroniously fetch the data and will handle
           // the closing of the streams.
@@ -932,7 +933,6 @@
               // Don't do anything, we will be killed shortly.
             } else {
               var elapsed = new Date() - start;
-              reportError('Done getting task at: ' + elapsed);
               // TODO(ricow): Do something more clever here.
               if (nextTask != undefined) alert('This is really bad');
               // The task is send to us as:
@@ -940,6 +940,7 @@
               var split = this.responseText.split('#');
               var nextTask = split[0];
               current_id = split[1];
+              reportError('Done getting task : ' + elapsed);
               did_start = false;
               run(nextTask);
             }
diff --git a/tools/testing/dart/http_server.dart b/tools/testing/dart/http_server.dart
index 986bd53..b222d87 100644
--- a/tools/testing/dart/http_server.dart
+++ b/tools/testing/dart/http_server.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:isolate';
-import 'dart:uri';
 import 'test_suite.dart';  // For TestUtils.
 // TODO(efortuna): Rewrite to not use the args library and simply take an
 // expected number of arguments, so test.dart doesn't rely on the args library?
@@ -208,8 +207,11 @@
 
   void _handleWebSocketRequest(HttpRequest request) {
     WebSocketTransformer.upgrade(request).then((websocket) {
+      // We ignore failures to write to the socket, this happens if the browser
+      // closes the connection.
+      websocket.done.catchError((_) {});
       websocket.listen((data) {
-        websocket.send(data);
+        websocket.add(data);
         websocket.close();
       }, onError: (e) {
         DebugLogger.warning('HttpServer: error while echoing to WebSocket', e);
@@ -314,10 +316,10 @@
       var headerOrigin = request.headers.value('Origin');
       var allowedOrigin;
       if (headerOrigin != null) {
-        var origin = new Uri(headerOrigin);
+        var origin = Uri.parse(headerOrigin);
         // Allow loading from http://*:$allowedPort in browsers.
         allowedOrigin =
-          '${origin.scheme}://${origin.domain}:${allowedPort}';
+          '${origin.scheme}://${origin.host}:${allowedPort}';
       } else {
         // IE10 appears to be bugged and is not sending the Origin header
         // when making CORS requests to the same domain but different port.
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index 1af62b2..11e5ce1 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -124,7 +124,7 @@
 
   // Copy all the tests into the output map tests, as multiline strings.
   for (String key in testsAsLines.keys) {
-    tests[key] = testsAsLines[key].join(line_separator).concat(line_separator);
+    tests[key] = testsAsLines[key].join(line_separator) + line_separator;
   }
 }
 
@@ -220,7 +220,7 @@
       final File file = new File.fromPath(multitestFilename);
 
       file.createSync();
-      RandomAccessFile openedFile = file.openSync(FileMode.WRITE);
+      RandomAccessFile openedFile = file.openSync(mode: FileMode.WRITE);
       openedFile.writeStringSync(tests[key]);
       openedFile.closeSync();
       Set<String> outcome = outcomes[key];
diff --git a/tools/testing/dart/record_and_replay.dart b/tools/testing/dart/record_and_replay.dart
index fd5df68..c2ba7c9 100644
--- a/tools/testing/dart/record_and_replay.dart
+++ b/tools/testing/dart/record_and_replay.dart
@@ -41,7 +41,7 @@
   var _cwd;
 
   TestCaseRecorder(this._outputPath) {
-    _cwd  = new Directory.current().path;
+    _cwd  = Directory.current.path;
   }
 
   void nextTestCase(TestCase testCase) {
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index 8c8d7830..b288db5 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -188,7 +188,7 @@
 
   void _appendToFlakyFile(String msg) {
     var file = new File(TestUtils.flakyFileName());
-    var fd = file.openSync(FileMode.APPEND);
+    var fd = file.openSync(mode: FileMode.APPEND);
     fd.writeStringSync(msg);
     fd.closeSync();
   }
@@ -343,7 +343,7 @@
   }
 }
 
-class LineProgressIndicator extends EventListener implements ProgressIndicator {
+class LineProgressIndicator extends EventListener {
   void done(TestCase test) {
     var status = 'pass';
     if (test.lastCommandOutput.unexpectedOutput) {
@@ -395,25 +395,6 @@
 class ProgressIndicator extends EventListener {
   ProgressIndicator(this._startTime);
 
-  factory ProgressIndicator.fromName(String name,
-                                     DateTime startTime,
-                                     Formatter formatter) {
-    switch (name) {
-      case 'compact':
-        return new CompactProgressIndicator(startTime, formatter);
-      case 'line':
-        return new LineProgressIndicator();
-      case 'verbose':
-        return new VerboseProgressIndicator(startTime);
-      case 'status':
-        return new ProgressIndicator(startTime);
-      case 'buildbot':
-        return new BuildbotProgressIndicator(startTime);
-      default:
-        assert(false);
-        break;
-    }
-  }
 
   void testAdded() { _foundTests++; }
 
@@ -542,3 +523,24 @@
     print(_buildSummaryEnd(_failedTests));
   }
 }
+
+
+EventListener progressIndicatorFromName(String name,
+                                        DateTime startTime,
+                                        Formatter formatter) {
+  switch (name) {
+    case 'compact':
+      return new CompactProgressIndicator(startTime, formatter);
+    case 'line':
+      return new LineProgressIndicator();
+    case 'verbose':
+      return new VerboseProgressIndicator(startTime);
+    case 'status':
+      return new ProgressIndicator(startTime);
+    case 'buildbot':
+      return new BuildbotProgressIndicator(startTime);
+    default:
+      assert(false);
+      break;
+  }
+}
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 73c9cba..1cae1d7 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -17,7 +17,6 @@
 // CommandOutput.exitCode in subclasses of CommandOutput.
 import "dart:io" as io;
 import "dart:isolate";
-import "dart:uri";
 import "browser_controller.dart";
 import "http_server.dart" as http_server;
 import "status_file_parser.dart";
@@ -123,7 +122,7 @@
 
   String toString() => commandLine;
 
-  Future<bool> get outputIsUpToDate => new Future.immediate(false);
+  Future<bool> get outputIsUpToDate => new Future.value(false);
   io.Path get expectedOutputFile => null;
   bool get isPixelTest => false;
 }
@@ -141,19 +140,19 @@
       : super(executable, arguments);
 
   Future<bool> get outputIsUpToDate {
-    if (_neverSkipCompilation) return new Future.immediate(false);
+    if (_neverSkipCompilation) return new Future.value(false);
 
     Future<List<Uri>> readDepsFile(String path) {
       var file = new io.File(new io.Path(path).toNativePath());
       if (!file.existsSync()) {
-        return new Future.immediate(null);
+        return new Future.value(null);
       }
       return file.readAsLines().then((List<String> lines) {
         var dependencies = new List<Uri>();
         for (var line in lines) {
           line = line.trim();
           if (line.length > 0) {
-            dependencies.add(new Uri(line));
+            dependencies.add(Uri.parse(line));
           }
         }
         return dependencies;
@@ -164,7 +163,7 @@
       if (dependencies != null) {
         dependencies.addAll(_bootstrapDependencies);
         var jsOutputLastModified = TestUtils.lastModifiedCache.getLastModified(
-            new Uri.fromComponents(scheme: 'file', path: _outputFile));
+            new Uri(scheme: 'file', path: _outputFile));
         if (jsOutputLastModified != null) {
           for (var dependency in dependencies) {
             var dependencyLastModified =
@@ -985,7 +984,6 @@
       return argument;
     }
   }).toList();
-  return;
 }
 
 
@@ -1029,12 +1027,13 @@
         compilationSkipped = true;
         _commandComplete(0);
       } else {
-        var processOptions = _createProcessOptions();
+        var processEnvironment = _createProcessEnvironment();
         var commandArguments = _modifySeleniumTimeout(command.arguments,
                                                       testCase.timeout);
-        Future processFuture = io.Process.start(command.executable,
-                                                commandArguments,
-                                                processOptions);
+        Future processFuture =
+            io.Process.start(command.executable,
+                             commandArguments,
+                             environment: processEnvironment);
         processFuture.then((io.Process process) {
           // Close stdin so that tests that try to block on input will fail.
           process.stdin.close();
@@ -1088,19 +1087,18 @@
     source.listen(destination.addAll);
   }
 
-  io.ProcessOptions _createProcessOptions() {
+  Map<String, String> _createProcessEnvironment() {
     var baseEnvironment = command.environment != null ?
         command.environment : io.Platform.environment;
-    io.ProcessOptions options = new io.ProcessOptions();
-    options.environment = new Map<String, String>.from(baseEnvironment);
-    options.environment['DART_CONFIGURATION'] =
+    var environment = new Map<String, String>.from(baseEnvironment);
+    environment['DART_CONFIGURATION'] =
         TestUtils.configurationDir(testCase.configuration);
 
     for (var excludedEnvironmentVariable in EXCLUDED_ENVIRONMENT_VARIABLES) {
-      options.environment.remove(excludedEnvironmentVariable);
+      environment.remove(excludedEnvironmentVariable);
     }
 
-    return options;
+    return environment;
   }
 }
 
@@ -1160,7 +1158,7 @@
   }
 
   Future terminate() {
-    if (_process == null) return new Future.immediate(true);
+    if (_process == null) return new Future.value(true);
     Completer completer = new Completer();
     Timer killTimer;
     _processExitHandler = (_) {
@@ -1208,7 +1206,7 @@
 
   String _createArgumentsLine(List<String> arguments, int timeout) {
     arguments = _modifySeleniumTimeout(arguments, timeout);
-    return arguments.join(' ').concat('\n');
+    return arguments.join(' ') + '\n';
   }
 
   void _reportResult() {
@@ -1664,7 +1662,7 @@
         io.exit(1);
       });
     }
-    return new Future.immediate(_browserTestRunners[runtime]);
+    return new Future.value(_browserTestRunners[runtime]);
   }
 
   void _startBrowserControllerTest(var test) {
@@ -1763,7 +1761,9 @@
             _numBrowserProcesses--;
           }
           eventFinishedTestCase(test_arg);
-          if (test_arg is BrowserTestCase) test_arg.notifyObservers();
+          if (test_arg is BrowserTestCase) {
+            (test_arg as BrowserTestCase).notifyObservers();
+          }
           oldCallback(test_arg);
           _tryRunTest();
         };
@@ -1790,7 +1790,9 @@
           if (isTestCaseFinished(testCase)) {
             testCase.completed();
             eventFinishedTestCase(testCase);
-            if (testCase is BrowserTestCase) testCase.notifyObservers();
+            if (testCase is BrowserTestCase) {
+              (testCase as BrowserTestCase).notifyObservers();
+            }
           } else {
             _tests.addFirst(testCase);
           }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 1e1e051..41bdf2f 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -17,7 +17,6 @@
 import "dart:async";
 import "dart:io";
 import "dart:isolate";
-import "dart:uri";
 import "drt_updater.dart";
 import "multitest.dart";
 import "status_file_parser.dart";
@@ -49,7 +48,7 @@
  * completes immediately with `null`.
  */
 Future asynchronously(function()) {
-  if (function == null) return new Future.immediate(null);
+  if (function == null) return new Future.value(null);
 
   var completer = new Completer();
   Timer.run(() => completer.complete(function()));
@@ -61,7 +60,7 @@
 // TODO(rnystrom): Copied from web_components. Remove from here when it gets
 // added to dart:core. (See #6626.)
 class FutureGroup {
-  const _FINISHED = -1;
+  static const _FINISHED = -1;
   int _pending = 0;
   Completer<List> _completer = new Completer<List>();
   final List<Future> futures = <Future>[];
@@ -490,7 +489,7 @@
     var snapshotPath = TestUtils.absolutePath(new Path(buildDir).join(
         new Path('dart-sdk/bin/snapshots/'
                  'utils_wrapper.dart.snapshot'))).toString();
-    return [new Uri.fromComponents(scheme: 'file', path: snapshotPath)];
+    return [new Uri(scheme: 'file', path: snapshotPath)];
   }
 
   /**
@@ -540,7 +539,7 @@
     var completer = new Completer();
     var updater = runtimeUpdater(configuration);
     if (updater == null || updater.updated) {
-      return new Future.immediate(null);
+      return new Future.value(null);
     }
 
     assert(updater.isActive);
@@ -590,7 +589,7 @@
     return dir.exists().then((exists) {
       if (!exists) {
         print('Directory containing tests missing: ${suiteDir.toNativePath()}');
-        return new Future.immediate(null);
+        return new Future.value(null);
       } else {
         var group = new FutureGroup();
         enqueueDirectory(dir, group);
@@ -883,7 +882,7 @@
 
   void _createWrapperFile(String dartWrapperFilename, dartLibraryFilename) {
     File file = new File(dartWrapperFilename);
-    RandomAccessFile dartWrapper = file.openSync(FileMode.WRITE);
+    RandomAccessFile dartWrapper = file.openSync(mode: FileMode.WRITE);
 
     var usePackageImport = dartLibraryFilename.segments().contains("pkg");
     var libraryPathComponent = _createUrlPathFromFile(dartLibraryFilename);
@@ -908,7 +907,7 @@
    */
   void enqueueBrowserTest(TestInformation info,
                           String testName,
-                          Object expectations,
+                          expectations,
                           bool isWrappingRequired) {
     // TODO(kustermann/ricow): This method should be refactored.
     Map optionsFromFile = info.optionsFromFile;
@@ -946,7 +945,8 @@
       scriptPath = _createUrlPathFromFile(new Path(scriptPath));
 
       // Create the HTML file for the test.
-      RandomAccessFile htmlTest = new File(htmlPath).openSync(FileMode.WRITE);
+      RandomAccessFile htmlTest =
+          new File(htmlPath).openSync(mode: FileMode.WRITE);
       String content = null;
       Path dir = filePath.directoryPath;
       String nameNoExt = filePath.filenameWithoutExtension;
@@ -999,7 +999,7 @@
 
       // Variables for browser multi-tests.
       List<String> subtestNames = info.optionsFromFile['subtestNames'];
-      TestCase multitestParentTest;
+      BrowserTestCase multitestParentTest;
       int subtestIndex = 0;
       // Construct the command that executes the browser test
       do {
@@ -1729,7 +1729,7 @@
   static String testScriptPath = new Options().script;
   static LastModifiedCache lastModifiedCache = new LastModifiedCache();
   static Path currentWorkingDirectory =
-      new Path(new Directory.current().path);
+      new Path(Directory.current.path);
   /**
    * Creates a directory using a [relativePath] to an existing
    * [base] directory if that [relativePath] does not already exist.
diff --git a/tools/testing/dart/vendored_pkg/args/args.dart b/tools/testing/dart/vendored_pkg/args/args.dart
index 32793dd..6fb0363 100644
--- a/tools/testing/dart/vendored_pkg/args/args.dart
+++ b/tools/testing/dart/vendored_pkg/args/args.dart
@@ -397,6 +397,6 @@
   }
 
   /** Get the names of the options as a [Collection]. */
-  Collection<String> get options => _options.keys.toList();
+  List<String> get options => _options.keys.toList();
 }
 
diff --git a/utils/apidoc/apidoc.gyp b/utils/apidoc/apidoc.gyp
index 67e31b2..f5ddde0 100644
--- a/utils/apidoc/apidoc.gyp
+++ b/utils/apidoc/apidoc.gyp
@@ -85,6 +85,7 @@
             '--package-root=<(PRODUCT_DIR)/packages',
             '--mode=static',
             '--exclude-lib=analyzer_experimental',
+            '--exclude-lib=barback',
             '--exclude-lib=browser',
             '--exclude-lib=dartdoc',
             '--exclude-lib=docgen',