Version 0.4.3.0 .
svn merge -r 20113:20419 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 20422 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@20424 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/.gitignore b/.gitignore
index 894d9fa..293bd10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,7 +42,6 @@
 
 # Compiled python binaries
 *.pyc
-third_party/gsutil/*/gsutilc
 
 # From the Mac OS X Finder
 .DS_Store
diff --git a/client/tools/buildbot_annotated_steps.py b/client/tools/buildbot_annotated_steps.py
index 4ed1ada..c424255 100755
--- a/client/tools/buildbot_annotated_steps.py
+++ b/client/tools/buildbot_annotated_steps.py
@@ -1,9 +1,8 @@
+#!/usr/bin/python
 # 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.
 
-#!/usr/bin/python
-
 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -100,12 +99,6 @@
   # get the latest changed revision from the current repository sub-tree
   version = GetLatestChangedRevision()
 
-  #TODO: debug statements to be removed in the future.
-  print "mode = " + mode
-  print "name = " + name
-  print "version = " + version
-  print "toolsBuildScript = " + os.path.abspath(toolsBuildScript)
-
   utils = GetUtils()
   outdir = GetOutDir(utils, mode)
   cmds = [sys.executable, toolsBuildScript,
@@ -140,9 +133,11 @@
   if buildbot_javahome:
     current_pwd = os.getenv('PWD')
     java_home = os.path.join(current_pwd, buildbot_javahome)
+    java_bin = os.path.join(java_home, 'bin')
     os.environ['JAVA_HOME'] = java_home
-    print 'Setting java home to'
-    print java_home
+    os.environ['PATH'] = '%s;%s' % (java_bin, os.environ['PATH'])
+
+    print 'Setting java home to ', java_home
     sys.stdout.flush()
 
 def ClobberBuilder():
@@ -184,8 +179,6 @@
   return svnRev
 
 def main():
-  print 'main'
-
   if len(sys.argv) == 0:
     print 'Script pathname not known, giving up.'
     return 1
@@ -208,7 +201,18 @@
   # root directory, set JAVA_HOME based on that.
   FixJavaHome()
   if name.startswith('dart-editor'):
+    # TODO(kustermann,ricow): This is a temporary hack until we can safely
+    # enable it on main waterfall. We need to remove this eventually
+    is_fyi = False
+    if name.startswith('dart-editor-fyi'):
+      match = re.search('dart-editor-fyi(.*)', name)
+      name = 'dart-editor' + match.group(1)
+      is_fyi = True
+    # Run the old annotated steps script first.
     status = ProcessTools('release', name, version)
+    # In case we're an FYI builder, run 'tools/bots/editor.py' as well
+    if is_fyi:
+      status = ProcessBot(name, 'editor') or status
   elif name.startswith('pub-'):
     status = ProcessBot(name, 'pub')
   elif name.startswith('vm-android'):
diff --git a/dart.gyp b/dart.gyp
index 860d4464..7f5ec30 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -133,6 +133,44 @@
       ],
     },
     {
+      'target_name': 'editor',
+      'type': 'none',
+      'dependencies': [
+        'editor/build/generated/editor_deps.gyp:editor_deps',
+
+        # This dependency on create_sdk does not mean that the Editor
+        # is rebuilt if the SDK is. It only means that when you build
+        # the Editor, you should also build the SDK. If we wanted to
+        # make sure that the editor is rebuilt when the SDK is, we
+        # should list a *file* in PRODUCT_DIR which the action below
+        # uses as input.
+        # This is the desired behavior as we would otherwise have to
+        # rebuild the editor each time the VM, dart2js, or library
+        # code changes.
+        'create_sdk',
+      ],
+      'actions': [
+        {
+          'action_name': 'create_editor_py',
+          'inputs': [
+            'tools/create_editor.py',
+            '<(SHARED_INTERMEDIATE_DIR)/editor_deps/editor.stamp',
+            '<!@(["python", "tools/list_files.py", "", "editor/tools/features/com.google.dart.tools.deploy.feature_releng"])',
+          ],
+          'outputs': [
+            '<(PRODUCT_DIR)/editor/VERSION',
+          ],
+          'action': [
+            'python',
+            'tools/create_editor.py',
+            '--out', '<(PRODUCT_DIR)/editor',
+            '--build', '<(INTERMEDIATE_DIR)',
+          ],
+          'message': 'Creating editor.',
+        },
+      ],
+    },
+    {
       'target_name': 'samples',
       'type': 'none',
       'dependencies': [
diff --git a/pkg/analyzer_experimental/example/resolver_driver.dart b/pkg/analyzer_experimental/example/resolver_driver.dart
new file mode 100644
index 0000000..e1bcd68
--- /dev/null
+++ b/pkg/analyzer_experimental/example/resolver_driver.dart
@@ -0,0 +1,60 @@
+#!/usr/bin/env dart
+
+// 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:analyzer_experimental/src/generated/java_io.dart';
+import 'package:analyzer_experimental/src/generated/source_io.dart';
+import 'package:analyzer_experimental/src/generated/ast.dart';
+import 'package:analyzer_experimental/src/generated/sdk.dart';
+import 'package:analyzer_experimental/src/generated/element.dart';
+import 'package:analyzer_experimental/src/generated/engine.dart';
+
+import 'dart:io';
+
+main() {
+  print('working dir ${new File('.').fullPathSync()}');
+
+  var args = new Options().arguments;
+  if (args.length != 2) {
+    print('Usage: resolve_driver [path_to_sdk] [file_to_resolve]');
+    exit(0);
+  }
+
+  JavaSystemIO.setProperty("com.google.dart.sdk", args[0]);
+  DartSdk sdk = DartSdk.defaultSdk;
+
+  AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+  context.sourceFactory = new SourceFactory.con2([new DartUriResolver(sdk), new FileUriResolver()]);
+  Source source = new FileBasedSource.con1(context.sourceFactory, new JavaFile(args[1]));
+  //
+  ChangeSet changeSet = new ChangeSet();
+  changeSet.added(source);
+  context.applyChanges(changeSet);
+  LibraryElement libElement = context.getLibraryElement(source);
+  print("libElement: $libElement");
+
+  CompilationUnit resolvedUnit = context.resolve(source, libElement);
+  var visitor = new _ASTVisitor();
+  resolvedUnit.accept(visitor);
+}
+
+class _ASTVisitor extends GeneralizingASTVisitor {
+  visitNode(ASTNode node) {
+    String text = '${node.runtimeType} : <"${node.toString()}">';
+    if (node is SimpleIdentifier) {
+      Element element = node.element;
+      if (element != null) {
+        text += " element: ${element.runtimeType}";
+        LibraryElement library = element.library;
+        if (library != null) {
+          text += " from ${element.library.definingCompilationUnit.source.fullName}";
+        }
+      }
+    }
+    print(text);
+    return super.visitNode(node);
+  }
+}
+
diff --git a/pkg/analyzer_experimental/lib/src/generated/ast.dart b/pkg/analyzer_experimental/lib/src/generated/ast.dart
index b47c576..931fa95 100644
--- a/pkg/analyzer_experimental/lib/src/generated/ast.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/ast.dart
@@ -7415,7 +7415,7 @@
    * Return {@code true} if this method is declared to be an abstract method.
    * @return {@code true} if this method is declared to be an abstract method
    */
-  bool isAbstract() => _modifierKeyword != null && identical(((_modifierKeyword as KeywordToken)).keyword, Keyword.ABSTRACT);
+  bool isAbstract() => _externalKeyword == null && (_body is EmptyFunctionBody);
   /**
    * Return {@code true} if this method declares a getter.
    * @return {@code true} if this method declares a getter
diff --git a/pkg/analyzer_experimental/lib/src/generated/constant.dart b/pkg/analyzer_experimental/lib/src/generated/constant.dart
index 93ddccb..9e82ce9 100644
--- a/pkg/analyzer_experimental/lib/src/generated/constant.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/constant.dart
@@ -363,9 +363,9 @@
    * @param errorCode the error code for the error to be generated
    */
   ErrorResult.con1(ASTNode node, ErrorCode errorCode) {
-    _jtd_constructor_156_impl(node, errorCode);
+    _jtd_constructor_158_impl(node, errorCode);
   }
-  _jtd_constructor_156_impl(ASTNode node, ErrorCode errorCode) {
+  _jtd_constructor_158_impl(ASTNode node, ErrorCode errorCode) {
     _errors.add(new ErrorResult_ErrorData(node, errorCode));
   }
   /**
@@ -375,9 +375,9 @@
    * @param secondResult the second set of results being merged
    */
   ErrorResult.con2(ErrorResult firstResult, ErrorResult secondResult) {
-    _jtd_constructor_157_impl(firstResult, secondResult);
+    _jtd_constructor_159_impl(firstResult, secondResult);
   }
-  _jtd_constructor_157_impl(ErrorResult firstResult, ErrorResult secondResult) {
+  _jtd_constructor_159_impl(ErrorResult firstResult, ErrorResult secondResult) {
     _errors.addAll(firstResult._errors);
     _errors.addAll(secondResult._errors);
   }
diff --git a/pkg/analyzer_experimental/lib/src/generated/element.dart b/pkg/analyzer_experimental/lib/src/generated/element.dart
index 601a3e1..79b1bc9 100644
--- a/pkg/analyzer_experimental/lib/src/generated/element.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/element.dart
@@ -761,6 +761,12 @@
    * @return {@code true} if this method is abstract
    */
   bool isAbstract();
+  /**
+   * Return {@code true} if this method is an operator. The test may be based on the name of the
+   * method, in which case the result will be correct when the name is legal.
+   * @return {@code true} if this method is an operator
+   */
+  bool isOperator();
 }
 /**
  * The interface {@code MultiplyDefinedElement} defines the behavior of pseudo-elements that
@@ -1308,10 +1314,10 @@
   ElementKind get kind => ElementKind.CLASS;
   List<MethodElement> get methods => _methods;
   List<InterfaceType> get mixins => _mixins;
-  ConstructorElement getNamedConstructor(String name23) {
+  ConstructorElement getNamedConstructor(String name24) {
     for (ConstructorElement element in constructors) {
       String elementName = element.name;
-      if (elementName != null && elementName == name23) {
+      if (elementName != null && elementName == name24) {
         return element;
       }
     }
@@ -1700,8 +1706,8 @@
    * Set the source that corresponds to this compilation unit to the given source.
    * @param source the source that corresponds to this compilation unit
    */
-  void set source(Source source5) {
-    this._source = source5;
+  void set source(Source source7) {
+    this._source = source7;
   }
   /**
    * Set the top-level variables contained in this compilation unit to the given variables.
@@ -1944,11 +1950,11 @@
    * Initialize a newly created element to have the given name.
    * @param name the name of this element
    */
-  ElementImpl.con1(Identifier name24) {
-    _jtd_constructor_172_impl(name24);
+  ElementImpl.con1(Identifier name25) {
+    _jtd_constructor_174_impl(name25);
   }
-  _jtd_constructor_172_impl(Identifier name24) {
-    _jtd_constructor_173_impl(name24 == null ? "" : name24.name, name24 == null ? -1 : name24.offset);
+  _jtd_constructor_174_impl(Identifier name25) {
+    _jtd_constructor_175_impl(name25 == null ? "" : name25.name, name25 == null ? -1 : name25.offset);
   }
   /**
    * Initialize a newly created element to have the given name.
@@ -1957,9 +1963,9 @@
    * declaration of this element
    */
   ElementImpl.con2(String name8, int nameOffset2) {
-    _jtd_constructor_173_impl(name8, nameOffset2);
+    _jtd_constructor_175_impl(name8, nameOffset2);
   }
-  _jtd_constructor_173_impl(String name8, int nameOffset2) {
+  _jtd_constructor_175_impl(String name8, int nameOffset2) {
     this._name = name8;
     this._nameOffset = nameOffset2;
     this._modifiers = new Set();
@@ -2012,6 +2018,15 @@
     this._metadata = metadata2;
   }
   /**
+   * Set the offset of the name of this element in the file that contains the declaration of this
+   * element to the given value. This is normally done via the constructor, but this method is
+   * provided to support unnamed constructors.
+   * @param nameOffset the offset to the beginning of the name
+   */
+  void set nameOffset(int nameOffset3) {
+    this._nameOffset = nameOffset3;
+  }
+  /**
    * Set whether this element is synthetic to correspond to the given value.
    * @param isSynthetic {@code true} if the element is synthetic
    */
@@ -2111,9 +2126,9 @@
    * @param element the element whose location is being represented
    */
   ElementLocationImpl.con1(Element element) {
-    _jtd_constructor_174_impl(element);
+    _jtd_constructor_176_impl(element);
   }
-  _jtd_constructor_174_impl(Element element) {
+  _jtd_constructor_176_impl(Element element) {
     List<String> components = new List<String>();
     Element ancestor = element;
     while (ancestor != null) {
@@ -2127,9 +2142,9 @@
    * @param encoding the encoded form of a location
    */
   ElementLocationImpl.con2(String encoding) {
-    _jtd_constructor_175_impl(encoding);
+    _jtd_constructor_177_impl(encoding);
   }
-  _jtd_constructor_175_impl(String encoding) {
+  _jtd_constructor_177_impl(String encoding) {
     this._components = decode(encoding);
   }
   bool operator ==(Object object) {
@@ -2268,9 +2283,9 @@
    * @param name the name of this element
    */
   ExecutableElementImpl.con1(Identifier name) : super.con1(name) {
-    _jtd_constructor_177_impl(name);
+    _jtd_constructor_179_impl(name);
   }
-  _jtd_constructor_177_impl(Identifier name) {
+  _jtd_constructor_179_impl(Identifier name) {
   }
   /**
    * Initialize a newly created executable element to have the given name.
@@ -2279,9 +2294,9 @@
    * declaration of this element
    */
   ExecutableElementImpl.con2(String name, int nameOffset) : super.con2(name, nameOffset) {
-    _jtd_constructor_178_impl(name, nameOffset);
+    _jtd_constructor_180_impl(name, nameOffset);
   }
-  _jtd_constructor_178_impl(String name, int nameOffset) {
+  _jtd_constructor_180_impl(String name, int nameOffset) {
   }
   ElementImpl getChild(String identifier27) {
     for (ExecutableElement function in _functions) {
@@ -2465,18 +2480,18 @@
    * @param name the name of this element
    */
   FieldElementImpl.con1(Identifier name) : super.con1(name) {
-    _jtd_constructor_181_impl(name);
+    _jtd_constructor_183_impl(name);
   }
-  _jtd_constructor_181_impl(Identifier name) {
+  _jtd_constructor_183_impl(Identifier name) {
   }
   /**
    * Initialize a newly created synthetic field element to have the given name.
    * @param name the name of this element
    */
   FieldElementImpl.con2(String name) : super.con2(name) {
-    _jtd_constructor_182_impl(name);
+    _jtd_constructor_184_impl(name);
   }
-  _jtd_constructor_182_impl(String name) {
+  _jtd_constructor_184_impl(String name) {
   }
   accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
   ClassElement get enclosingElement => super.enclosingElement as ClassElement;
@@ -2512,9 +2527,9 @@
    * Initialize a newly created synthetic function element.
    */
   FunctionElementImpl() : super.con2("", -1) {
-    _jtd_constructor_183_impl();
+    _jtd_constructor_185_impl();
   }
-  _jtd_constructor_183_impl() {
+  _jtd_constructor_185_impl() {
     synthetic = true;
   }
   /**
@@ -2522,9 +2537,9 @@
    * @param name the name of this element
    */
   FunctionElementImpl.con1(Identifier name) : super.con1(name) {
-    _jtd_constructor_184_impl(name);
+    _jtd_constructor_186_impl(name);
   }
-  _jtd_constructor_184_impl(Identifier name) {
+  _jtd_constructor_186_impl(Identifier name) {
   }
   accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
   String get identifier => name;
@@ -2751,8 +2766,8 @@
    * Set the source that corresponds to this HTML file to the given source.
    * @param source the source that corresponds to this HTML file
    */
-  void set source(Source source6) {
-    this._source = source6;
+  void set source(Source source8) {
+    this._source = source8;
   }
   void visitChildren(ElementVisitor<Object> visitor) {
     super.visitChildren(visitor);
@@ -3075,8 +3090,8 @@
     visited.add(this);
     for (int index = 0; index < visited.length; index++) {
       LibraryElement library = visited[index];
-      Source source10 = library.definingCompilationUnit.source;
-      if (source10 == htmlLibSource) {
+      Source source12 = library.definingCompilationUnit.source;
+      if (source12 == htmlLibSource) {
         return true;
       }
       for (LibraryElement importedLibrary in library.importedLibraries) {
@@ -3156,9 +3171,9 @@
    * @param name the name of this element
    */
   MethodElementImpl.con1(Identifier name) : super.con1(name) {
-    _jtd_constructor_193_impl(name);
+    _jtd_constructor_195_impl(name);
   }
-  _jtd_constructor_193_impl(Identifier name) {
+  _jtd_constructor_195_impl(Identifier name) {
   }
   /**
    * Initialize a newly created method element to have the given name.
@@ -3167,14 +3182,22 @@
    * declaration of this element
    */
   MethodElementImpl.con2(String name, int nameOffset) : super.con2(name, nameOffset) {
-    _jtd_constructor_194_impl(name, nameOffset);
+    _jtd_constructor_196_impl(name, nameOffset);
   }
-  _jtd_constructor_194_impl(String name, int nameOffset) {
+  _jtd_constructor_196_impl(String name, int nameOffset) {
   }
   accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
   ClassElement get enclosingElement => super.enclosingElement as ClassElement;
   ElementKind get kind => ElementKind.METHOD;
   bool isAbstract() => hasModifier(Modifier.ABSTRACT);
+  bool isOperator() {
+    String name14 = name;
+    if (name14.isEmpty) {
+      return false;
+    }
+    int first = name14.codeUnitAt(0);
+    return !((0x61 <= first && first <= 0x7A) || (0x41 <= first && first <= 0x5A) || first == 0x5F || first == 0x24);
+  }
   bool isStatic() => hasModifier(Modifier.STATIC);
   /**
    * Set whether this method is abstract to correspond to the given value.
@@ -3444,9 +3467,9 @@
    * @param name the name of this element
    */
   PropertyAccessorElementImpl.con1(Identifier name) : super.con1(name) {
-    _jtd_constructor_199_impl(name);
+    _jtd_constructor_201_impl(name);
   }
-  _jtd_constructor_199_impl(Identifier name) {
+  _jtd_constructor_201_impl(Identifier name) {
   }
   /**
    * Initialize a newly created synthetic property accessor element to be associated with the given
@@ -3454,9 +3477,9 @@
    * @param variable the variable with which this access is associated
    */
   PropertyAccessorElementImpl.con2(PropertyInducingElementImpl variable2) : super.con2(variable2.name, -1) {
-    _jtd_constructor_200_impl(variable2);
+    _jtd_constructor_202_impl(variable2);
   }
-  _jtd_constructor_200_impl(PropertyInducingElementImpl variable2) {
+  _jtd_constructor_202_impl(PropertyInducingElementImpl variable2) {
     this._variable = variable2;
     synthetic = true;
   }
@@ -3521,18 +3544,18 @@
    * @param name the name of this element
    */
   PropertyInducingElementImpl.con1(Identifier name) : super.con1(name) {
-    _jtd_constructor_201_impl(name);
+    _jtd_constructor_203_impl(name);
   }
-  _jtd_constructor_201_impl(Identifier name) {
+  _jtd_constructor_203_impl(Identifier name) {
   }
   /**
    * Initialize a newly created synthetic element to have the given name.
    * @param name the name of this element
    */
   PropertyInducingElementImpl.con2(String name) : super.con2(name, -1) {
-    _jtd_constructor_202_impl(name);
+    _jtd_constructor_204_impl(name);
   }
-  _jtd_constructor_202_impl(String name) {
+  _jtd_constructor_204_impl(String name) {
     synthetic = true;
   }
   PropertyAccessorElement get getter => _getter;
@@ -3603,18 +3626,18 @@
    * @param name the name of this element
    */
   TopLevelVariableElementImpl.con1(Identifier name) : super.con1(name) {
-    _jtd_constructor_204_impl(name);
+    _jtd_constructor_206_impl(name);
   }
-  _jtd_constructor_204_impl(Identifier name) {
+  _jtd_constructor_206_impl(Identifier name) {
   }
   /**
    * Initialize a newly created synthetic top-level variable element to have the given name.
    * @param name the name of this element
    */
   TopLevelVariableElementImpl.con2(String name) : super.con2(name) {
-    _jtd_constructor_205_impl(name);
+    _jtd_constructor_207_impl(name);
   }
-  _jtd_constructor_205_impl(String name) {
+  _jtd_constructor_207_impl(String name) {
   }
   accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this);
   ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE;
@@ -3693,9 +3716,9 @@
    * @param name the name of this element
    */
   VariableElementImpl.con1(Identifier name) : super.con1(name) {
-    _jtd_constructor_207_impl(name);
+    _jtd_constructor_209_impl(name);
   }
-  _jtd_constructor_207_impl(Identifier name) {
+  _jtd_constructor_209_impl(Identifier name) {
   }
   /**
    * Initialize a newly created variable element to have the given name.
@@ -3704,9 +3727,9 @@
    * declaration of this element
    */
   VariableElementImpl.con2(String name, int nameOffset) : super.con2(name, nameOffset) {
-    _jtd_constructor_208_impl(name, nameOffset);
+    _jtd_constructor_210_impl(name, nameOffset);
   }
-  _jtd_constructor_208_impl(String name, int nameOffset) {
+  _jtd_constructor_210_impl(String name, int nameOffset) {
   }
   /**
    * Return the result of evaluating this variable's initializer as a compile-time constant
@@ -3899,9 +3922,9 @@
    * @param element the element representing the declaration of the function type
    */
   FunctionTypeImpl.con1(ExecutableElement element) : super(element, element == null ? null : element.name) {
-    _jtd_constructor_259_impl(element);
+    _jtd_constructor_261_impl(element);
   }
-  _jtd_constructor_259_impl(ExecutableElement element) {
+  _jtd_constructor_261_impl(ExecutableElement element) {
   }
   /**
    * Initialize a newly created function type to be declared by the given element and to have the
@@ -3909,9 +3932,9 @@
    * @param element the element representing the declaration of the function type
    */
   FunctionTypeImpl.con2(FunctionTypeAliasElement element) : super(element, element == null ? null : element.name) {
-    _jtd_constructor_260_impl(element);
+    _jtd_constructor_262_impl(element);
   }
-  _jtd_constructor_260_impl(FunctionTypeAliasElement element) {
+  _jtd_constructor_262_impl(FunctionTypeAliasElement element) {
   }
   bool operator ==(Object object) {
     if (object is! FunctionTypeImpl) {
@@ -4200,9 +4223,9 @@
    * @param element the element representing the declaration of the type
    */
   InterfaceTypeImpl.con1(ClassElement element) : super(element, element.name) {
-    _jtd_constructor_261_impl(element);
+    _jtd_constructor_263_impl(element);
   }
-  _jtd_constructor_261_impl(ClassElement element) {
+  _jtd_constructor_263_impl(ClassElement element) {
   }
   /**
    * Initialize a newly created type to have the given name. This constructor should only be used in
@@ -4210,9 +4233,9 @@
    * @param name the name of the type
    */
   InterfaceTypeImpl.con2(String name) : super(null, name) {
-    _jtd_constructor_262_impl(name);
+    _jtd_constructor_264_impl(name);
   }
-  _jtd_constructor_262_impl(String name) {
+  _jtd_constructor_264_impl(String name) {
   }
   bool operator ==(Object object) {
     if (object is! InterfaceTypeImpl) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart
index f782870..02832e5 100644
--- a/pkg/analyzer_experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
@@ -97,8 +97,14 @@
 /**
  * The interface {@code AnalysisContext} defines the behavior of objects that represent a context in
  * which analysis can be performed. The context includes such information as the version of the SDK
- * being analyzed against as well as the package-root used to resolve 'package:' URI's. (The latter
- * is included indirectly through the {@link SourceFactory source factory}.)
+ * being analyzed against as well as the package-root used to resolve 'package:' URI's. (Both of
+ * which are known indirectly through the {@link SourceFactory source factory}.)
+ * <p>
+ * They also represent the state of a given analysis, which includes knowing which sources have been
+ * included in the analysis (either directly or indirectly) and the results of the analysis. Some
+ * analysis results are cached in order to allow the context to balance between memory usage and
+ * performance. TODO(brianwilkerson) Decide how this is reflected in the API: a getFoo() and
+ * getOrComputeFoo() pair of methods, or a single getFoo(boolean).
  * <p>
  * Analysis engine allows for having more than one context. This can be used, for example, to
  * perform one analysis based on the state of files on disk and a separate analysis based on the
@@ -107,34 +113,19 @@
  */
 abstract class AnalysisContext {
   /**
-   * Respond to the given set of changes by removing any cached information that might now be
-   * out-of-date. The result indicates what operations need to be performed as a result of this
-   * change without actually performing those operations.
-   * @param changeSet a description of the changes that have occurred
-   * @return a result (not {@code null}) indicating operations to be performed
+   * Apply the changes specified by the given change set to this context. Any analysis results that
+   * have been invalidated by these changes will be removed.
+   * @param changeSet a description of the changes that are to be applied
    */
-  ChangeResult changed(ChangeSet changeSet);
+  void applyChanges(ChangeSet changeSet);
   /**
-   * Clear any cached information that is dependent on resolution. This method should be invoked if
-   * the assumptions used by resolution have changed but the contents of the file have not changed.
-   * Use {@link #sourceChanged(Source)} and {@link #sourcesDeleted(SourceContainer)} to indicate
-   * when the contents of a file or files have changed.
+   * Create a new context in which analysis can be performed. Any sources in the specified container
+   * will be removed from this context and added to the newly created context.
+   * @param container the container containing sources that should be removed from this context and
+   * added to the returned context
+   * @return the analysis context that was created
    */
-  void clearResolution();
-  /**
-   * Call this method when this context is no longer going to be used. At this point, the receiver
-   * may choose to push some of its information back into the global cache for consumption by
-   * another context for performance.
-   */
-  void discard();
-  /**
-   * Create a new context in which analysis can be performed. Any sources in the specified directory
-   * in the receiver will be removed from the receiver and added to the newly created context.
-   * @param directory the directory (not {@code null}) containing sources that should be removed
-   * from the receiver and added to the returned context
-   * @return the analysis context that was created (not {@code null})
-   */
-  AnalysisContext extractAnalysisContext(SourceContainer container);
+  AnalysisContext extractContext(SourceContainer container);
   /**
    * Return the element referenced by the given location.
    * @param location the reference describing the element to be returned
@@ -142,7 +133,8 @@
    */
   Element getElement(ElementLocation location);
   /**
-   * Return an array containing all of the errors associated with the given source.
+   * Return an array containing all of the errors associated with the given source. The array will
+   * be empty if the source is not known to this context or if there are no errors in the source.
    * @param source the source whose errors are to be returned
    * @return all of the errors associated with the given source
    * @throws AnalysisException if the errors could not be determined because the analysis could not
@@ -150,12 +142,17 @@
    */
   List<AnalysisError> getErrors(Source source);
   /**
-   * Parse and build an element model for the HTML file defined by the given source.
+   * Return the element model corresponding to the HTML file defined by the given source.
    * @param source the source defining the HTML file whose element model is to be returned
    * @return the element model corresponding to the HTML file defined by the given source
    */
   HtmlElement getHtmlElement(Source source);
   /**
+   * Return an array containing all of the sources known to this context that represent HTML files.
+   * @return the sources known to this context that represent HTML files
+   */
+  List<Source> get htmlSources;
+  /**
    * Return the kind of the given source if it is already known, or {@code null} if the kind is not
    * already known.
    * @param source the source whose kind is to be returned
@@ -164,6 +161,22 @@
    */
   SourceKind getKnownKindOf(Source source);
   /**
+   * Return an array containing all of the sources known to this context that represent the defining
+   * compilation unit of a library that can be run within a browser. The sources that are returned
+   * represent libraries that have a 'main' method and are either referenced by an HTML file or
+   * import, directly or indirectly, a client-only library.
+   * @return the sources known to this context that represent the defining compilation unit of a
+   * library that can be run within a browser
+   */
+  List<Source> get launchableClientLibrarySources;
+  /**
+   * Return an array containing all of the sources known to this context that represent the defining
+   * compilation unit of a library that can be run outside of a browser.
+   * @return the sources known to this context that represent the defining compilation unit of a
+   * library that can be run outside of a browser
+   */
+  List<Source> get launchableServerLibrarySources;
+  /**
    * Return the sources for the defining compilation units of any libraries of which the given
    * source is a part. The array will normally contain a single library because most Dart sources
    * are only included in a single library, but it is possible to have a part that is contained in
@@ -186,12 +199,20 @@
    */
   LibraryElement getLibraryElement(Source source);
   /**
-   * Return the element model corresponding to the library defined by the given source, or{@code null} if the element model does not yet exist.
+   * Return the element model corresponding to the library defined by the given source, or{@code null} if the element model does not currently exist or if the analysis could not be
+   * performed.
    * @param source the source defining the library whose element model is to be returned
    * @return the element model corresponding to the library defined by the given source
    */
   LibraryElement getLibraryElementOrNull(Source source);
   /**
+   * Return an array containing all of the sources known to this context that represent the defining
+   * compilation unit of a library.
+   * @return the sources known to this context that represent the defining compilation unit of a
+   * library
+   */
+  List<Source> get librarySources;
+  /**
    * Return the kind of the given source, computing it's kind if it is not already known.
    * @param source the source whose kind is to be returned
    * @return the kind of the given source
@@ -199,33 +220,17 @@
    */
   SourceKind getOrComputeKindOf(Source source);
   /**
-   * Return an array containing all of the parsing errors associated with the given source.
-   * @param source the source whose errors are to be returned
-   * @return all of the parsing errors associated with the given source
-   * @throws AnalysisException if the errors could not be determined because the analysis could not
-   * be performed
-   */
-  List<AnalysisError> getParsingErrors(Source source);
-  /**
-   * Return an array containing all of the resolution errors associated with the given source.
-   * @param source the source whose errors are to be returned
-   * @return all of the resolution errors associated with the given source
-   * @throws AnalysisException if the errors could not be determined because the analysis could not
-   * be performed
-   */
-  List<AnalysisError> getResolutionErrors(Source source);
-  /**
    * Return the source factory used to create the sources that can be analyzed in this context.
    * @return the source factory used to create the sources that can be analyzed in this context
    */
   SourceFactory get sourceFactory;
   /**
-   * Add the sources contained in the specified context to the receiver's collection of sources.
+   * Add the sources contained in the specified context to this context's collection of sources.
    * This method is called when an existing context's pubspec has been removed, and the contained
-   * sources should be reanalyzed as part of the receiver.
-   * @param context the context being merged (not {@code null})
+   * sources should be reanalyzed as part of this context.
+   * @param context the context being merged
    */
-  void mergeAnalysisContext(AnalysisContext context);
+  void mergeContext(AnalysisContext context);
   /**
    * Parse a single source to produce an AST structure. The resulting AST structure may or may not
    * be resolved, and may have a slightly different structure depending upon whether it is resolved.
@@ -244,6 +249,13 @@
    */
   HtmlParseResult parseHtml(Source source);
   /**
+   * Perform the next unit of work required to keep the analysis results up-to-date and return
+   * information about the consequent changes to the analysis results. If there were no results the
+   * returned array will be empty. This method can be long running.
+   * @return an array containing notices of changes to the analysis results
+   */
+  List<ChangeNotice> performAnalysisTask();
+  /**
    * Parse and resolve a single source within the given context to produce a fully resolved AST.
    * @param source the source to be parsed and resolved
    * @param library the library defining the context in which the source file is to be resolved
@@ -252,27 +264,13 @@
    */
   CompilationUnit resolve(Source source, LibraryElement library);
   /**
-   * Scan a single source to produce a token stream.
-   * @param source the source to be scanned
-   * @param errorListener the listener to which errors should be reported
-   * @return the head of the token stream representing the content of the source
-   * @throws AnalysisException if the analysis could not be performed
-   */
-  Token scan(Source source, AnalysisErrorListener errorListener);
-  /**
-   * Scan a single source to produce an HTML token stream.
-   * @param source the source to be scanned
-   * @return the scan result (not {@code null})
-   * @throws AnalysisException if the analysis could not be performed
-   */
-  HtmlScanResult scanHtml(Source source);
-  /**
    * Set the source factory used to create the sources that can be analyzed in this context to the
-   * given source factory.
-   * @param sourceFactory the source factory used to create the sources that can be analyzed in this
+   * given source factory. Clients can safely assume that all analysis results have been
+   * invalidated.
+   * @param factory the source factory used to create the sources that can be analyzed in this
    * context
    */
-  void set sourceFactory(SourceFactory sourceFactory4);
+  void set sourceFactory(SourceFactory factory);
   /**
    * Given a collection of sources with content that has changed, return an {@link Iterable}identifying the sources that need to be resolved.
    * @param changedSources an array of sources (not {@code null}, contains no {@code null}s)
@@ -324,11 +322,83 @@
   }
 }
 /**
- * Instances of {@code ChangeResult} are returned by {@link AnalysisContext#changed(ChangeSet)} to
- * indicate what operations need to be performed as a result of the change.
- * @coverage dart.engine
+ * Instances of the class {@code ChangeNotice} represent a change to the analysis results associated
+ * with a given source.
  */
-class ChangeResult {
+class ChangeNotice {
+  /**
+   * The source for which the result is being reported.
+   */
+  Source _source;
+  /**
+   * The fully resolved AST that changed as a result of the analysis, or {@code null} if the AST was
+   * not changed.
+   */
+  CompilationUnit _compilationUnit;
+  /**
+   * The errors that changed as a result of the analysis, or {@code null} if errors were not
+   * changed.
+   */
+  List<AnalysisError> _errors;
+  /**
+   * The line information associated with the source, or {@code null} if errors were not changed.
+   */
+  LineInfo _lineInfo;
+  /**
+   * An empty array of change notices.
+   */
+  static List<ChangeNotice> EMPTY_ARRAY = new List<ChangeNotice>(0);
+  /**
+   * Initialize a newly created result representing the fact that the errors associated with a
+   * source have changed.
+   * @param source the source for which the result is being reported
+   * @param errors the errors that changed as a result of the analysis
+   * @param the line information associated with the source
+   */
+  ChangeNotice.con1(Source source2, List<AnalysisError> errors2, LineInfo lineInfo3) {
+    _jtd_constructor_127_impl(source2, errors2, lineInfo3);
+  }
+  _jtd_constructor_127_impl(Source source2, List<AnalysisError> errors2, LineInfo lineInfo3) {
+    this._source = source2;
+    this._errors = errors2;
+    this._lineInfo = lineInfo3;
+  }
+  /**
+   * Initialize a newly created result representing the fact that the resolution of a source has
+   * changed.
+   * @param source the source for which the result is being reported
+   * @param compilationUnit the fully resolved AST produced as a result of the analysis
+   */
+  ChangeNotice.con2(Source source3, CompilationUnit compilationUnit9) {
+    _jtd_constructor_128_impl(source3, compilationUnit9);
+  }
+  _jtd_constructor_128_impl(Source source3, CompilationUnit compilationUnit9) {
+    this._source = source3;
+    this._compilationUnit = compilationUnit9;
+  }
+  /**
+   * Return the fully resolved AST that changed as a result of the analysis, or {@code null} if the
+   * AST was not changed.
+   * @return the fully resolved AST that changed as a result of the analysis
+   */
+  CompilationUnit get compilationUnit => _compilationUnit;
+  /**
+   * Return the errors that changed as a result of the analysis, or {@code null} if errors were not
+   * changed.
+   * @return the errors that changed as a result of the analysis
+   */
+  List<AnalysisError> get errors => _errors;
+  /**
+   * Return the line information associated with the source, or {@code null} if errors were not
+   * changed.
+   * @return the line information associated with the source
+   */
+  LineInfo get lineInfo => _lineInfo;
+  /**
+   * Return the source for which the result is being reported.
+   * @return the source for which the result is being reported
+   */
+  Source get source => _source;
 }
 /**
  * Instances of the class {@code ChangeSet} indicate what sources have been added, changed, or
@@ -368,8 +438,8 @@
   /**
    * Record that the specified source has been added and that it has the given content. If the
    * content is non-{@code null}, this has the effect of overriding the default contents of the
-   * source. If the contents are {@code null}, any previous the override is removed so that the
-   * default contents will be used.
+   * source. If the contents are {@code null}, any previous override is removed so that the default
+   * contents will be used.
    * @param source the source that was added
    * @param content the content of the new source
    */
@@ -389,8 +459,8 @@
   /**
    * Record that the specified source has been changed and that it now has the given content. If the
    * content is non-{@code null}, this has the effect of overriding the default contents of the
-   * source. If the contents are {@code null}, any previous the override is removed so that the
-   * default contents will be used.
+   * source. If the contents are {@code null}, any previous override is removed so that the default
+   * contents will be used.
    * @param source the source that was changed
    * @param content the new content of the source
    */
@@ -482,62 +552,43 @@
    */
   Object _cacheLock = new Object();
   /**
-   * The suffix used by sources that contain Dart.
-   */
-  static String _DART_SUFFIX = ".dart";
-  /**
-   * The suffix used by sources that contain HTML.
-   */
-  static String _HTML_SUFFIX = ".html";
-  /**
    * Initialize a newly created analysis context.
    */
   AnalysisContextImpl() : super() {
   }
-  ChangeResult changed(ChangeSet changeSet) {
+  void applyChanges(ChangeSet changeSet) {
     if (changeSet.isEmpty()) {
-      return new ChangeResult();
+      return;
     }
     {
+      List<Source> addedSources = new List<Source>();
       for (MapEntry<Source, String> entry in getMapEntrySet(changeSet.addedWithContent)) {
-        _sourceFactory.setContents(entry.getKey(), entry.getValue());
+        Source source = entry.getKey();
+        _sourceFactory.setContents(source, entry.getValue());
+        addedSources.add(source);
       }
+      List<Source> changedSources = new List<Source>();
       for (MapEntry<Source, String> entry in getMapEntrySet(changeSet.changedWithContent)) {
-        _sourceFactory.setContents(entry.getKey(), entry.getValue());
+        Source source = entry.getKey();
+        _sourceFactory.setContents(source, entry.getValue());
+        changedSources.add(source);
       }
-      for (Source source in changeSet.addedWithContent.keys.toSet()) {
+      List<Source> removedSources = new List<Source>.from(changeSet.removed);
+      for (SourceContainer container in changeSet.removedContainers) {
+        addSourcesInContainer(removedSources, container);
+      }
+      for (Source source in addedSources) {
         sourceAvailable(source);
       }
-      for (Source source in changeSet.changedWithContent.keys.toSet()) {
+      for (Source source in changedSources) {
         sourceChanged(source);
       }
-      for (Source source in changeSet.removed) {
-        sourceDeleted(source);
-      }
-      for (SourceContainer container in changeSet.removedContainers) {
-        sourcesDeleted(container);
+      for (Source source in removedSources) {
+        sourceRemoved(source);
       }
     }
-    return new ChangeResult();
   }
-  void clearResolution() {
-    {
-      _parseCache.clear();
-      _htmlParseCache.clear();
-      _libraryElementCache.clear();
-      _publicNamespaceCache.clear();
-    }
-  }
-  void discard() {
-    {
-      _sourceMap.clear();
-      _parseCache.clear();
-      _htmlParseCache.clear();
-      _libraryElementCache.clear();
-      _publicNamespaceCache.clear();
-    }
-  }
-  AnalysisContext extractAnalysisContext(SourceContainer container) {
+  AnalysisContext extractContext(SourceContainer container) {
     AnalysisContextImpl newContext = AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl;
     List<Source> sourcesToRemove = new List<Source>();
     {
@@ -558,13 +609,18 @@
     throw new UnsupportedOperationException();
   }
   HtmlElement getHtmlElement(Source source) {
+    if (!AnalysisEngine.isHtmlFileName(source.shortName)) {
+      return null;
+    }
     throw new UnsupportedOperationException();
   }
+  List<Source> get htmlSources => getSources(SourceKind.HTML);
   SourceKind getKnownKindOf(Source source) {
-    if (source.fullName.endsWith(_HTML_SUFFIX)) {
+    String name = source.shortName;
+    if (AnalysisEngine.isHtmlFileName(name)) {
       return SourceKind.HTML;
     }
-    if (!source.fullName.endsWith(_DART_SUFFIX)) {
+    if (!AnalysisEngine.isDartFileName(name)) {
       return SourceKind.UNKNOWN;
     }
     {
@@ -578,6 +634,8 @@
     }
     return null;
   }
+  List<Source> get launchableClientLibrarySources => librarySources;
+  List<Source> get launchableServerLibrarySources => librarySources;
   List<Source> getLibrariesContaining(Source source) {
     {
       SourceInfo info = _sourceMap[source];
@@ -588,6 +646,9 @@
     }
   }
   LibraryElement getLibraryElement(Source source) {
+    if (!AnalysisEngine.isDartFileName(source.shortName)) {
+      return null;
+    }
     {
       LibraryElement element = _libraryElementCache[source];
       if (element == null) {
@@ -617,22 +678,13 @@
       return _libraryElementCache[source];
     }
   }
+  List<Source> get librarySources => getSources(SourceKind.LIBRARY);
   SourceKind getOrComputeKindOf(Source source) {
     SourceKind kind = getKnownKindOf(source);
     if (kind != null) {
       return kind;
     }
-    try {
-      if (hasPartOfDirective(parse(source))) {
-        return SourceKind.PART;
-      }
-    } on AnalysisException catch (exception) {
-      return SourceKind.UNKNOWN;
-    }
-    return SourceKind.LIBRARY;
-  }
-  List<AnalysisError> getParsingErrors(Source source) {
-    throw new UnsupportedOperationException();
+    return computeKindOf(source);
   }
   /**
    * Return a namespace containing mappings for all of the public names defined by the given
@@ -641,13 +693,13 @@
    * @return the public namespace of the given library
    */
   Namespace getPublicNamespace(LibraryElement library) {
-    Source source8 = library.definingCompilationUnit.source;
+    Source source10 = library.definingCompilationUnit.source;
     {
-      Namespace namespace = _publicNamespaceCache[source8];
+      Namespace namespace = _publicNamespaceCache[source10];
       if (namespace == null) {
         NamespaceBuilder builder = new NamespaceBuilder();
         namespace = builder.createPublicNamespace(library);
-        _publicNamespaceCache[source8] = namespace;
+        _publicNamespaceCache[source10] = namespace;
       }
       return namespace;
     }
@@ -673,11 +725,8 @@
       return namespace;
     }
   }
-  List<AnalysisError> getResolutionErrors(Source source) {
-    throw new UnsupportedOperationException();
-  }
   SourceFactory get sourceFactory => _sourceFactory;
-  void mergeAnalysisContext(AnalysisContext context) {
+  void mergeContext(AnalysisContext context) {
     {
       for (MapEntry<Source, SourceInfo> entry in getMapEntrySet(((context as AnalysisContextImpl))._sourceMap)) {
         Source newSource = entry.getKey();
@@ -727,6 +776,7 @@
       return result;
     }
   }
+  List<ChangeNotice> performAnalysisTask() => ChangeNotice.EMPTY_ARRAY;
   /**
    * Given a table mapping the source for the libraries represented by the corresponding elements to
    * the elements representing the libraries, record those mappings.
@@ -739,21 +789,16 @@
     }
   }
   CompilationUnit resolve(Source source, LibraryElement library) => parse(source);
-  Token scan(Source source, AnalysisErrorListener errorListener) {
-    AnalysisContextImpl_ScanResult result = internalScan(source, errorListener);
-    return result._token;
-  }
-  HtmlScanResult scanHtml(Source source) {
-    HtmlScanner scanner = new HtmlScanner(source);
-    try {
-      source.getContents(scanner);
-    } on JavaException catch (exception) {
-      throw new AnalysisException.con3(exception);
+  void set sourceFactory(SourceFactory factory) {
+    if (identical(_sourceFactory, factory)) {
+      return;
+    } else if (factory.context != null) {
+      throw new IllegalStateException("Source factories cannot be shared between contexts");
+    } else if (_sourceFactory != null) {
+      _sourceFactory.context = null;
     }
-    return scanner.result;
-  }
-  void set sourceFactory(SourceFactory sourceFactory2) {
-    this._sourceFactory = sourceFactory2;
+    factory.context = this;
+    _sourceFactory = factory;
   }
   Iterable<Source> sourcesToResolve(List<Source> changedSources) {
     List<Source> librarySources = new List<Source>();
@@ -765,6 +810,46 @@
     return librarySources;
   }
   /**
+   * Add all of the sources contained in the given source container to the given list of sources.
+   * <p>
+   * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
+   * @param sources the list to which sources are to be added
+   * @param container the source container containing the sources to be added to the list
+   */
+  void addSourcesInContainer(List<Source> sources, SourceContainer container) {
+    for (Source source in _sourceMap.keys.toSet()) {
+      if (container.contains(source)) {
+        sources.add(source);
+      }
+    }
+  }
+  SourceKind computeKindOf(Source source) {
+    try {
+      if (hasPartOfDirective(parse(source))) {
+        return SourceKind.PART;
+      }
+    } on AnalysisException catch (exception) {
+      return SourceKind.UNKNOWN;
+    }
+    return SourceKind.LIBRARY;
+  }
+  /**
+   * Return an array containing all of the sources known to this context that have the given kind.
+   * @param kind the kind of sources to be returned
+   * @return all of the sources known to this context that have the given kind
+   */
+  List<Source> getSources(SourceKind kind5) {
+    List<Source> sources = new List<Source>();
+    {
+      for (MapEntry<Source, SourceInfo> entry in getMapEntrySet(_sourceMap)) {
+        if (identical(entry.getValue().kind, kind5)) {
+          sources.add(entry.getKey());
+        }
+      }
+    }
+    return new List.from(sources);
+  }
+  /**
    * Return {@code true} if the given compilation unit has a part-of directive.
    * @param unit the compilation unit being tested
    * @return {@code true} if the compilation unit has a part-of directive
@@ -787,6 +872,15 @@
     }
     return result;
   }
+  HtmlScanResult scanHtml(Source source) {
+    HtmlScanner scanner = new HtmlScanner(source);
+    try {
+      source.getContents(scanner);
+    } on JavaException catch (exception) {
+      throw new AnalysisException.con3(exception);
+    }
+    return scanner.result;
+  }
   /**
    * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
    * @param source the source that has been added
@@ -794,7 +888,8 @@
   void sourceAvailable(Source source) {
     SourceInfo existingInfo = _sourceMap[source];
     if (existingInfo == null) {
-      _sourceMap[source] = new SourceInfo.con1(source, getOrComputeKindOf(source));
+      SourceKind kind = computeKindOf(source);
+      _sourceMap[source] = new SourceInfo.con1(source, kind);
     }
   }
   /**
@@ -810,6 +905,11 @@
     _htmlParseCache.remove(source);
     _libraryElementCache.remove(source);
     _publicNamespaceCache.remove(source);
+    SourceKind oldKind = info.kind;
+    SourceKind newKind = computeKindOf(source);
+    if (newKind != oldKind) {
+      info.kind = newKind;
+    }
     for (Source librarySource in info.librarySources) {
       _libraryElementCache.remove(librarySource);
       _publicNamespaceCache.remove(librarySource);
@@ -819,21 +919,19 @@
    * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
    * @param source the source that has been deleted
    */
-  void sourceDeleted(Source source) {
-    _sourceMap.remove(source);
-    sourceChanged(source);
-  }
-  /**
-   * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
-   * @param container the source container specifying the sources that have been deleted
-   */
-  void sourcesDeleted(SourceContainer container) {
-    List<Source> sourcesToRemove = new List<Source>();
-    for (Source source in _sourceMap.keys.toSet()) {
-      if (container.contains(source)) {
-        sourcesToRemove.add(source);
-      }
+  void sourceRemoved(Source source) {
+    SourceInfo info = _sourceMap[source];
+    if (info == null) {
+      return;
     }
+    _parseCache.remove(source);
+    _libraryElementCache.remove(source);
+    _publicNamespaceCache.remove(source);
+    for (Source librarySource in info.librarySources) {
+      _libraryElementCache.remove(librarySource);
+      _publicNamespaceCache.remove(librarySource);
+    }
+    _sourceMap.remove(source);
   }
 }
 /**
@@ -911,11 +1009,11 @@
     }
   }
   void onError(AnalysisError event) {
-    Source source9 = event.source;
-    List<AnalysisError> errorsForSource = _errors[source9];
-    if (_errors[source9] == null) {
+    Source source11 = event.source;
+    List<AnalysisError> errorsForSource = _errors[source11];
+    if (_errors[source11] == null) {
       errorsForSource = new List<AnalysisError>();
-      _errors[source9] = errorsForSource;
+      _errors[source11] = errorsForSource;
     }
     errorsForSource.add(event);
   }
@@ -935,9 +1033,9 @@
    */
   List<Source> _librarySources = null;
   SourceInfo.con1(Source source, SourceKind kind3) {
-    _jtd_constructor_161_impl(source, kind3);
+    _jtd_constructor_163_impl(source, kind3);
   }
-  _jtd_constructor_161_impl(Source source, SourceKind kind3) {
+  _jtd_constructor_163_impl(Source source, SourceKind kind3) {
     this._kind = kind3;
   }
   /**
@@ -945,9 +1043,9 @@
    * @param info the information holder used to initialize this holder
    */
   SourceInfo.con2(SourceInfo info) {
-    _jtd_constructor_162_impl(info);
+    _jtd_constructor_164_impl(info);
   }
-  _jtd_constructor_162_impl(SourceInfo info) {
+  _jtd_constructor_164_impl(SourceInfo info) {
     _kind = info._kind;
     _librarySources = new List<Source>.from(info._librarySources);
   }
diff --git a/pkg/analyzer_experimental/lib/src/generated/error.dart b/pkg/analyzer_experimental/lib/src/generated/error.dart
index 2693822..b8225a1 100644
--- a/pkg/analyzer_experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/error.dart
@@ -122,8 +122,8 @@
    * the default source to be used.
    * @param source the source to be used when reporting errors
    */
-  void set source(Source source7) {
-    this._source = source7 == null ? _defaultSource : source7;
+  void set source(Source source9) {
+    this._source = source9 == null ? _defaultSource : source9;
   }
 }
 /**
@@ -165,11 +165,11 @@
    * @param errorCode the error code to be associated with this error
    * @param arguments the arguments used to build the error message
    */
-  AnalysisError.con1(Source source2, ErrorCode errorCode2, List<Object> arguments) {
-    _jtd_constructor_129_impl(source2, errorCode2, arguments);
+  AnalysisError.con1(Source source4, ErrorCode errorCode2, List<Object> arguments) {
+    _jtd_constructor_131_impl(source4, errorCode2, arguments);
   }
-  _jtd_constructor_129_impl(Source source2, ErrorCode errorCode2, List<Object> arguments) {
-    this._source = source2;
+  _jtd_constructor_131_impl(Source source4, ErrorCode errorCode2, List<Object> arguments) {
+    this._source = source4;
     this._errorCode = errorCode2;
     this._message = JavaString.format(errorCode2.message, arguments);
   }
@@ -181,11 +181,11 @@
    * @param errorCode the error code to be associated with this error
    * @param arguments the arguments used to build the error message
    */
-  AnalysisError.con2(Source source3, int offset2, int length11, ErrorCode errorCode3, List<Object> arguments) {
-    _jtd_constructor_130_impl(source3, offset2, length11, errorCode3, arguments);
+  AnalysisError.con2(Source source5, int offset2, int length11, ErrorCode errorCode3, List<Object> arguments) {
+    _jtd_constructor_132_impl(source5, offset2, length11, errorCode3, arguments);
   }
-  _jtd_constructor_130_impl(Source source3, int offset2, int length11, ErrorCode errorCode3, List<Object> arguments) {
-    this._source = source3;
+  _jtd_constructor_132_impl(Source source5, int offset2, int length11, ErrorCode errorCode3, List<Object> arguments) {
+    this._source = source5;
     this._offset = offset2;
     this._length = length11;
     this._errorCode = errorCode3;
@@ -228,8 +228,8 @@
    * Set the source in which the error occurred to the given source.
    * @param source the source in which the error occurred
    */
-  void set source(Source source4) {
-    this._source = source4;
+  void set source(Source source6) {
+    this._source = source6;
   }
   String toString() {
     JavaStringBuilder builder = new JavaStringBuilder();
@@ -417,7 +417,7 @@
    * 12.11.2 Const: It is a compile-time error if evaluation of a constant object results in an
    * uncaught exception being thrown.
    */
-  static final CompileTimeErrorCode CONST_EVAL_THROWS_EXCEPTION = new CompileTimeErrorCode('CONST_EVAL_THROWS_EXCEPTION', 15, "");
+  static final CompileTimeErrorCode CONST_EVAL_THROWS_EXCEPTION = new CompileTimeErrorCode('CONST_EVAL_THROWS_EXCEPTION', 15, "'const' constructors cannot throw exceptions");
   /**
    * 12.11.2 Const: If <i>T</i> is a parameterized type <i>S&lt;U<sub>1</sub>, &hellip;,
    * U<sub>m</sub>&gt;</i>, let <i>R = S</i>; It is a compile time error if <i>S</i> is not a
@@ -462,7 +462,7 @@
    * 15.3.1 Typedef: It is a compile-time error if any default values are specified in the signature
    * of a function type alias.
    */
-  static final CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS = new CompileTimeErrorCode('DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS', 22, "");
+  static final CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS = new CompileTimeErrorCode('DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS', 22, "Default values aren't allowed in typedefs");
   /**
    * 3.1 Scoping: It is a compile-time error if there is more than one entity with the same name
    * declared in the same scope.
@@ -508,159 +508,178 @@
    * 12.4 Booleans: It is a compile-time error for a class to attempt to extend or implement bool.
    * <p>
    * 12.5 Strings: It is a compile-time error for a class to attempt to extend or implement String.
+   * @param typeName the name of the type that cannot be extended
+   * @see #IMPLEMENTS_DISALLOWED_CLASS
    */
-  static final CompileTimeErrorCode EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS = new CompileTimeErrorCode('EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS', 29, "");
+  static final CompileTimeErrorCode EXTENDS_DISALLOWED_CLASS = new CompileTimeErrorCode('EXTENDS_DISALLOWED_CLASS', 29, "Classes cannot extend '%s'");
+  /**
+   * 12.2 Null: It is a compile-time error for a class to attempt to extend or implement Null.
+   * <p>
+   * 12.3 Numbers: It is a compile-time error for a class to attempt to extend or implement int.
+   * <p>
+   * 12.3 Numbers: It is a compile-time error for a class to attempt to extend or implement double.
+   * <p>
+   * 12.3 Numbers: It is a compile-time error for any type other than the types int and double to
+   * attempt to extend or implement num.
+   * <p>
+   * 12.4 Booleans: It is a compile-time error for a class to attempt to extend or implement bool.
+   * <p>
+   * 12.5 Strings: It is a compile-time error for a class to attempt to extend or implement String.
+   * @param typeName the name of the type that cannot be implemented
+   * @see #EXTENDS_DISALLOWED_CLASS
+   */
+  static final CompileTimeErrorCode IMPLEMENTS_DISALLOWED_CLASS = new CompileTimeErrorCode('IMPLEMENTS_DISALLOWED_CLASS', 30, "Classes cannot implement '%s'");
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile time
    * error if more than one initializer corresponding to a given instance variable appears in
    * <i>k</i>’s list.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS = new CompileTimeErrorCode('FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS', 30, "");
+  static final CompileTimeErrorCode FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS = new CompileTimeErrorCode('FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS', 31, "");
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile time
    * error if <i>k</i>’s initializer list contains an initializer for a final variable <i>f</i>
    * whose declaration includes an initialization expression.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION = new CompileTimeErrorCode('FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION', 31, "");
+  static final CompileTimeErrorCode FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION = new CompileTimeErrorCode('FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION', 32, "");
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile time
    * error if <i>k</i>’s initializer list contains an initializer for a variable that is initialized
    * by means of an initializing formal of <i>k</i>.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER = new CompileTimeErrorCode('FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER', 32, "");
+  static final CompileTimeErrorCode FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER = new CompileTimeErrorCode('FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER', 33, "");
   /**
    * 7.6.1 Generative Constructors: It is a compile-time error if an initializing formal is used by
    * a function other than a non-redirecting generative constructor.
    */
-  static final CompileTimeErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new CompileTimeErrorCode('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 33, "");
+  static final CompileTimeErrorCode FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR = new CompileTimeErrorCode('FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR', 34, "");
   /**
    * 5 Variables: It is a compile-time error if a final instance variable that has been initialized
    * at its point of declaration is also initialized in a constructor.
    */
-  static final CompileTimeErrorCode FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR = new CompileTimeErrorCode('FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR', 34, "");
+  static final CompileTimeErrorCode FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR = new CompileTimeErrorCode('FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR', 35, "");
   /**
    * 5 Variables: It is a compile-time error if a final instance variable that has is initialized by
    * means of an initializing formal of a constructor is also initialized elsewhere in the same
    * constructor.
    */
-  static final CompileTimeErrorCode FINAL_INITIALIZED_MULTIPLE_TIMES = new CompileTimeErrorCode('FINAL_INITIALIZED_MULTIPLE_TIMES', 35, "");
+  static final CompileTimeErrorCode FINAL_INITIALIZED_MULTIPLE_TIMES = new CompileTimeErrorCode('FINAL_INITIALIZED_MULTIPLE_TIMES', 36, "");
   /**
    * 5 Variables: It is a compile-time error if a library, static or local variable <i>v</i> is
    * final and <i>v</i> is not initialized at its point of declaration.
    */
-  static final CompileTimeErrorCode FINAL_NOT_INITIALIZED = new CompileTimeErrorCode('FINAL_NOT_INITIALIZED', 36, "");
+  static final CompileTimeErrorCode FINAL_NOT_INITIALIZED = new CompileTimeErrorCode('FINAL_NOT_INITIALIZED', 37, "");
   /**
    * 7.2 Getters: It is a compile-time error if a class has both a getter and a method with the same
    * name.
    */
-  static final CompileTimeErrorCode GETTER_AND_METHOD_WITH_SAME_NAME = new CompileTimeErrorCode('GETTER_AND_METHOD_WITH_SAME_NAME', 37, "");
+  static final CompileTimeErrorCode GETTER_AND_METHOD_WITH_SAME_NAME = new CompileTimeErrorCode('GETTER_AND_METHOD_WITH_SAME_NAME', 38, "");
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the implements clause of a class includes
    * type dynamic.
    */
-  static final CompileTimeErrorCode IMPLEMENTS_DYNAMIC = new CompileTimeErrorCode('IMPLEMENTS_DYNAMIC', 38, "");
+  static final CompileTimeErrorCode IMPLEMENTS_DYNAMIC = new CompileTimeErrorCode('IMPLEMENTS_DYNAMIC', 39, "");
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the implements clause of a class <i>C</i>
    * includes a type expression that does not denote a class available in the lexical scope of
    * <i>C</i>.
    * @param typeName the name of the interface that was not found
    */
-  static final CompileTimeErrorCode IMPLEMENTS_NON_CLASS = new CompileTimeErrorCode('IMPLEMENTS_NON_CLASS', 39, "Classes can only implement other classes");
+  static final CompileTimeErrorCode IMPLEMENTS_NON_CLASS = new CompileTimeErrorCode('IMPLEMENTS_NON_CLASS', 40, "Classes can only implement other classes");
   /**
    * 7.10 Superinterfaces: It is a compile-time error if a type <i>T</i> appears more than once in
    * the implements clause of a class.
    */
-  static final CompileTimeErrorCode IMPLEMENTS_REPEATED = new CompileTimeErrorCode('IMPLEMENTS_REPEATED', 40, "");
+  static final CompileTimeErrorCode IMPLEMENTS_REPEATED = new CompileTimeErrorCode('IMPLEMENTS_REPEATED', 41, "");
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the interface of a class <i>C</i> is a
    * superinterface of itself.
    */
-  static final CompileTimeErrorCode IMPLEMENTS_SELF = new CompileTimeErrorCode('IMPLEMENTS_SELF', 41, "");
+  static final CompileTimeErrorCode IMPLEMENTS_SELF = new CompileTimeErrorCode('IMPLEMENTS_SELF', 42, "");
   /**
    * 14.1 Imports: It is a compile-time error to import two different libraries with the same name.
    */
-  static final CompileTimeErrorCode IMPORT_DUPLICATED_LIBRARY_NAME = new CompileTimeErrorCode('IMPORT_DUPLICATED_LIBRARY_NAME', 42, "");
+  static final CompileTimeErrorCode IMPORT_DUPLICATED_LIBRARY_NAME = new CompileTimeErrorCode('IMPORT_DUPLICATED_LIBRARY_NAME', 43, "");
   /**
    * 14.1 Imports: It is a compile-time error if the compilation unit found at the specified URI is
    * not a library declaration.
    */
-  static final CompileTimeErrorCode IMPORT_OF_NON_LIBRARY = new CompileTimeErrorCode('IMPORT_OF_NON_LIBRARY', 43, "");
+  static final CompileTimeErrorCode IMPORT_OF_NON_LIBRARY = new CompileTimeErrorCode('IMPORT_OF_NON_LIBRARY', 44, "");
   /**
    * 13.9 Switch: It is a compile-time error if values of the expressions <i>e<sub>k</sub></i> are
    * not instances of the same class <i>C</i>, for all <i>1 &lt;= k &lt;= n</i>.
    */
-  static final CompileTimeErrorCode INCONSITENT_CASE_EXPRESSION_TYPES = new CompileTimeErrorCode('INCONSITENT_CASE_EXPRESSION_TYPES', 44, "");
+  static final CompileTimeErrorCode INCONSITENT_CASE_EXPRESSION_TYPES = new CompileTimeErrorCode('INCONSITENT_CASE_EXPRESSION_TYPES', 45, "");
   /**
    * 7.6.1 Generative Constructors: An initializing formal has the form <i>this.id</i>. It is a
    * compile-time error if <i>id</i> is not the name of an instance variable of the immediately
    * enclosing class.
    */
-  static final CompileTimeErrorCode INITIALIZER_FOR_NON_EXISTANT_FIELD = new CompileTimeErrorCode('INITIALIZER_FOR_NON_EXISTANT_FIELD', 45, "");
+  static final CompileTimeErrorCode INITIALIZER_FOR_NON_EXISTANT_FIELD = new CompileTimeErrorCode('INITIALIZER_FOR_NON_EXISTANT_FIELD', 46, "");
   /**
    * TODO(brianwilkerson) Remove this when we have decided on how to report errors in compile-time
    * constants. Until then, this acts as a placeholder for more informative errors.
    */
-  static final CompileTimeErrorCode INVALID_CONSTANT = new CompileTimeErrorCode('INVALID_CONSTANT', 46, "");
+  static final CompileTimeErrorCode INVALID_CONSTANT = new CompileTimeErrorCode('INVALID_CONSTANT', 47, "");
   /**
    * 7.6 Constructors: It is a compile-time error if the name of a constructor is not a constructor
    * name.
    */
-  static final CompileTimeErrorCode INVALID_CONSTRUCTOR_NAME = new CompileTimeErrorCode('INVALID_CONSTRUCTOR_NAME', 47, "");
+  static final CompileTimeErrorCode INVALID_CONSTRUCTOR_NAME = new CompileTimeErrorCode('INVALID_CONSTRUCTOR_NAME', 48, "");
   /**
    * 7.6.2 Factories: It is a compile-time error if <i>M</i> is not the name of the immediately
    * enclosing class.
    */
-  static final CompileTimeErrorCode INVALID_FACTORY_NAME_NOT_A_CLASS = new CompileTimeErrorCode('INVALID_FACTORY_NAME_NOT_A_CLASS', 48, "");
+  static final CompileTimeErrorCode INVALID_FACTORY_NAME_NOT_A_CLASS = new CompileTimeErrorCode('INVALID_FACTORY_NAME_NOT_A_CLASS', 49, "");
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
    * instance member <i>m2</i>, the signature of <i>m2</i> explicitly specifies a default value for
    * a formal parameter <i>p</i> and the signature of <i>m1</i> specifies a different default value
    * for <i>p</i>.
    */
-  static final CompileTimeErrorCode INVALID_OVERRIDE_DEFAULT_VALUE = new CompileTimeErrorCode('INVALID_OVERRIDE_DEFAULT_VALUE', 49, "");
+  static final CompileTimeErrorCode INVALID_OVERRIDE_DEFAULT_VALUE = new CompileTimeErrorCode('INVALID_OVERRIDE_DEFAULT_VALUE', 50, "");
   /**
    * 7.1: It is a compile-time error if an instance method <i>m1</i> overrides an instance member
    * <i>m2</i> and <i>m1</i> does not declare all the named parameters declared by <i>m2</i>.
    */
-  static final CompileTimeErrorCode INVALID_OVERRIDE_NAMED = new CompileTimeErrorCode('INVALID_OVERRIDE_NAMED', 50, "");
+  static final CompileTimeErrorCode INVALID_OVERRIDE_NAMED = new CompileTimeErrorCode('INVALID_OVERRIDE_NAMED', 51, "");
   /**
    * 7.1 Instance Methods: It is a compile-time error if an instance method m1 overrides an instance
    * member <i>m2</i> and <i>m1</i> has fewer optional positional parameters than <i>m2</i>.
    */
-  static final CompileTimeErrorCode INVALID_OVERRIDE_POSITIONAL = new CompileTimeErrorCode('INVALID_OVERRIDE_POSITIONAL', 51, "");
+  static final CompileTimeErrorCode INVALID_OVERRIDE_POSITIONAL = new CompileTimeErrorCode('INVALID_OVERRIDE_POSITIONAL', 52, "");
   /**
    * 7.1 Instance Methods: It is a compile-time error if an instance method <i>m1</i> overrides an
    * instance member <i>m2</i> and <i>m1</i> has a different number of required parameters than
    * <i>m2</i>.
    */
-  static final CompileTimeErrorCode INVALID_OVERRIDE_REQUIRED = new CompileTimeErrorCode('INVALID_OVERRIDE_REQUIRED', 52, "");
+  static final CompileTimeErrorCode INVALID_OVERRIDE_REQUIRED = new CompileTimeErrorCode('INVALID_OVERRIDE_REQUIRED', 53, "");
   /**
    * 12.10 This: It is a compile-time error if this appears in a top-level function or variable
    * initializer, in a factory constructor, or in a static method or variable initializer, or in the
    * initializer of an instance variable.
    */
-  static final CompileTimeErrorCode INVALID_REFERENCE_TO_THIS = new CompileTimeErrorCode('INVALID_REFERENCE_TO_THIS', 53, "");
+  static final CompileTimeErrorCode INVALID_REFERENCE_TO_THIS = new CompileTimeErrorCode('INVALID_REFERENCE_TO_THIS', 54, "");
   /**
    * 12.7 Maps: It is a compile-time error if the first type argument to a map literal is not
    * String.
    */
-  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_FOR_KEY = new CompileTimeErrorCode('INVALID_TYPE_ARGUMENT_FOR_KEY', 54, "");
+  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_FOR_KEY = new CompileTimeErrorCode('INVALID_TYPE_ARGUMENT_FOR_KEY', 55, "");
   /**
    * 12.6 Lists: It is a compile time error if the type argument of a constant list literal includes
    * a type parameter.
    */
-  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_LIST = new CompileTimeErrorCode('INVALID_TYPE_ARGUMENT_IN_CONST_LIST', 55, "");
+  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_LIST = new CompileTimeErrorCode('INVALID_TYPE_ARGUMENT_IN_CONST_LIST', 56, "");
   /**
    * 12.7 Maps: It is a compile time error if the type arguments of a constant map literal include a
    * type parameter.
    */
-  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_MAP = new CompileTimeErrorCode('INVALID_TYPE_ARGUMENT_IN_CONST_MAP', 56, "");
+  static final CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_MAP = new CompileTimeErrorCode('INVALID_TYPE_ARGUMENT_IN_CONST_MAP', 57, "");
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile-time
    * error if <i>k</i>'s initializer list contains an initializer for a variable that is not an
    * instance variable declared in the immediately surrounding class.
    */
-  static final CompileTimeErrorCode INVALID_VARIABLE_IN_INITIALIZER = new CompileTimeErrorCode('INVALID_VARIABLE_IN_INITIALIZER', 57, "");
+  static final CompileTimeErrorCode INVALID_VARIABLE_IN_INITIALIZER = new CompileTimeErrorCode('INVALID_VARIABLE_IN_INITIALIZER', 58, "");
   /**
    * 13.13 Break: It is a compile-time error if no such statement <i>s<sub>E</sub></i> exists within
    * the innermost function in which <i>s<sub>b</sub></i> occurs.
@@ -669,7 +688,7 @@
    * <i>s<sub>E</sub></i> exists within the innermost function in which <i>s<sub>c</sub></i> occurs.
    * @param labelName the name of the unresolvable label
    */
-  static final CompileTimeErrorCode LABEL_IN_OUTER_SCOPE = new CompileTimeErrorCode('LABEL_IN_OUTER_SCOPE', 58, "Cannot reference label '%s' declared in an outer method");
+  static final CompileTimeErrorCode LABEL_IN_OUTER_SCOPE = new CompileTimeErrorCode('LABEL_IN_OUTER_SCOPE', 59, "Cannot reference label '%s' declared in an outer method");
   /**
    * 13.13 Break: It is a compile-time error if no such statement <i>s<sub>E</sub></i> exists within
    * the innermost function in which <i>s<sub>b</sub></i> occurs.
@@ -678,47 +697,47 @@
    * <i>s<sub>E</sub></i> exists within the innermost function in which <i>s<sub>c</sub></i> occurs.
    * @param labelName the name of the unresolvable label
    */
-  static final CompileTimeErrorCode LABEL_UNDEFINED = new CompileTimeErrorCode('LABEL_UNDEFINED', 59, "Cannot reference undefined label '%s'");
+  static final CompileTimeErrorCode LABEL_UNDEFINED = new CompileTimeErrorCode('LABEL_UNDEFINED', 60, "Cannot reference undefined label '%s'");
   /**
    * 7 Classes: It is a compile time error if a class <i>C</i> declares a member with the same name
    * as <i>C</i>.
    */
-  static final CompileTimeErrorCode MEMBER_WITH_CLASS_NAME = new CompileTimeErrorCode('MEMBER_WITH_CLASS_NAME', 60, "");
+  static final CompileTimeErrorCode MEMBER_WITH_CLASS_NAME = new CompileTimeErrorCode('MEMBER_WITH_CLASS_NAME', 61, "");
   /**
    * 9 Mixins: It is a compile-time error if a declared or derived mixin explicitly declares a
    * constructor.
    */
-  static final CompileTimeErrorCode MIXIN_DECLARES_CONSTRUCTOR = new CompileTimeErrorCode('MIXIN_DECLARES_CONSTRUCTOR', 61, "");
+  static final CompileTimeErrorCode MIXIN_DECLARES_CONSTRUCTOR = new CompileTimeErrorCode('MIXIN_DECLARES_CONSTRUCTOR', 62, "");
   /**
    * 9 Mixins: It is a compile-time error if a mixin is derived from a class whose superclass is not
    * Object.
    */
-  static final CompileTimeErrorCode MIXIN_INHERITS_FROM_NOT_OBJECT = new CompileTimeErrorCode('MIXIN_INHERITS_FROM_NOT_OBJECT', 62, "");
+  static final CompileTimeErrorCode MIXIN_INHERITS_FROM_NOT_OBJECT = new CompileTimeErrorCode('MIXIN_INHERITS_FROM_NOT_OBJECT', 63, "");
   /**
    * 9.1 Mixin Application: It is a compile-time error if <i>M</i> does not denote a class or mixin
    * available in the immediately enclosing scope.
    * @param typeName the name of the mixin that was not found
    */
-  static final CompileTimeErrorCode MIXIN_OF_NON_CLASS = new CompileTimeErrorCode('MIXIN_OF_NON_CLASS', 63, "Classes can only mixin other classes");
+  static final CompileTimeErrorCode MIXIN_OF_NON_CLASS = new CompileTimeErrorCode('MIXIN_OF_NON_CLASS', 64, "Classes can only mixin other classes");
   /**
    * 9.1 Mixin Application: If <i>M</i> is a class, it is a compile time error if a well formed
    * mixin cannot be derived from <i>M</i>.
    */
-  static final CompileTimeErrorCode MIXIN_OF_NON_MIXIN = new CompileTimeErrorCode('MIXIN_OF_NON_MIXIN', 64, "");
+  static final CompileTimeErrorCode MIXIN_OF_NON_MIXIN = new CompileTimeErrorCode('MIXIN_OF_NON_MIXIN', 65, "");
   /**
    * 9 Mixins: It is a compile-time error if a declared or derived mixin refers to super.
    */
-  static final CompileTimeErrorCode MIXIN_REFERENCES_SUPER = new CompileTimeErrorCode('MIXIN_REFERENCES_SUPER', 65, "");
+  static final CompileTimeErrorCode MIXIN_REFERENCES_SUPER = new CompileTimeErrorCode('MIXIN_REFERENCES_SUPER', 66, "");
   /**
    * 9.1 Mixin Application: It is a compile-time error if <i>S</i> does not denote a class available
    * in the immediately enclosing scope.
    */
-  static final CompileTimeErrorCode MIXIN_WITH_NON_CLASS_SUPERCLASS = new CompileTimeErrorCode('MIXIN_WITH_NON_CLASS_SUPERCLASS', 66, "");
+  static final CompileTimeErrorCode MIXIN_WITH_NON_CLASS_SUPERCLASS = new CompileTimeErrorCode('MIXIN_WITH_NON_CLASS_SUPERCLASS', 67, "");
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. Then <i>k</i> may
    * include at most one superinitializer in its initializer list or a compile time error occurs.
    */
-  static final CompileTimeErrorCode MULTIPLE_SUPER_INITIALIZERS = new CompileTimeErrorCode('MULTIPLE_SUPER_INITIALIZERS', 67, "");
+  static final CompileTimeErrorCode MULTIPLE_SUPER_INITIALIZERS = new CompileTimeErrorCode('MULTIPLE_SUPER_INITIALIZERS', 68, "");
   /**
    * 12.11.1 New: It is a compile time error if <i>S</i> is not a generic type with <i>m</i> type
    * parameters.
@@ -726,12 +745,12 @@
    * @param argumentCount the number of type arguments provided
    * @param parameterCount the number of type parameters that were declared
    */
-  static final CompileTimeErrorCode NEW_WITH_INVALID_TYPE_PARAMETERS = new CompileTimeErrorCode('NEW_WITH_INVALID_TYPE_PARAMETERS', 68, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
+  static final CompileTimeErrorCode NEW_WITH_INVALID_TYPE_PARAMETERS = new CompileTimeErrorCode('NEW_WITH_INVALID_TYPE_PARAMETERS', 69, "The type '%s' is declared with %d type parameters, but %d type arguments were given");
   /**
    * 13.2 Expression Statements: It is a compile-time error if a non-constant map literal that has
    * no explicit type arguments appears in a place where a statement is expected.
    */
-  static final CompileTimeErrorCode NON_CONST_MAP_AS_EXPRESSION_STATEMENT = new CompileTimeErrorCode('NON_CONST_MAP_AS_EXPRESSION_STATEMENT', 69, "");
+  static final CompileTimeErrorCode NON_CONST_MAP_AS_EXPRESSION_STATEMENT = new CompileTimeErrorCode('NON_CONST_MAP_AS_EXPRESSION_STATEMENT', 70, "");
   /**
    * 13.9 Switch: Given a switch statement of the form <i>switch (e) { label<sub>11</sub> &hellip;
    * label<sub>1j1</sub> case e<sub>1</sub>: s<sub>1</sub> &hellip; label<sub>n1</sub> &hellip;
@@ -741,116 +760,116 @@
    * s<sub>n</sub>}</i>, it is a compile-time error if the expressions <i>e<sub>k</sub></i> are not
    * compile-time constants, for all <i>1 &lt;= k &lt;= n</i>.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_CASE_EXPRESSION = new CompileTimeErrorCode('NON_CONSTANT_CASE_EXPRESSION', 70, "Case expressions must be constant");
+  static final CompileTimeErrorCode NON_CONSTANT_CASE_EXPRESSION = new CompileTimeErrorCode('NON_CONSTANT_CASE_EXPRESSION', 71, "Case expressions must be constant");
   /**
    * 6.2.2 Optional Formals: It is a compile-time error if the default value of an optional
    * parameter is not a compile-time constant.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_DEFAULT_VALUE = new CompileTimeErrorCode('NON_CONSTANT_DEFAULT_VALUE', 71, "Default values of an optional parameter must be constant");
+  static final CompileTimeErrorCode NON_CONSTANT_DEFAULT_VALUE = new CompileTimeErrorCode('NON_CONSTANT_DEFAULT_VALUE', 72, "Default values of an optional parameter must be constant");
   /**
    * 12.6 Lists: It is a compile time error if an element of a constant list literal is not a
    * compile-time constant.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_LIST_ELEMENT = new CompileTimeErrorCode('NON_CONSTANT_LIST_ELEMENT', 72, "'const' lists must have all constant values");
+  static final CompileTimeErrorCode NON_CONSTANT_LIST_ELEMENT = new CompileTimeErrorCode('NON_CONSTANT_LIST_ELEMENT', 73, "'const' lists must have all constant values");
   /**
    * 12.7 Maps: It is a compile time error if either a key or a value of an entry in a constant map
    * literal is not a compile-time constant.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_MAP_KEY = new CompileTimeErrorCode('NON_CONSTANT_MAP_KEY', 73, "The keys in a 'const' map must be constant");
+  static final CompileTimeErrorCode NON_CONSTANT_MAP_KEY = new CompileTimeErrorCode('NON_CONSTANT_MAP_KEY', 74, "The keys in a 'const' map must be constant");
   /**
    * 12.7 Maps: It is a compile time error if either a key or a value of an entry in a constant map
    * literal is not a compile-time constant.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_MAP_VALUE = new CompileTimeErrorCode('NON_CONSTANT_MAP_VALUE', 74, "The values in a 'const' map must be constant");
+  static final CompileTimeErrorCode NON_CONSTANT_MAP_VALUE = new CompileTimeErrorCode('NON_CONSTANT_MAP_VALUE', 75, "The values in a 'const' map must be constant");
   /**
    * 7.6.3 Constant Constructors: Any expression that appears within the initializer list of a
    * constant constructor must be a potentially constant expression, or a compile-time error occurs.
    */
-  static final CompileTimeErrorCode NON_CONSTANT_VALUE_IN_INITIALIZER = new CompileTimeErrorCode('NON_CONSTANT_VALUE_IN_INITIALIZER', 75, "");
+  static final CompileTimeErrorCode NON_CONSTANT_VALUE_IN_INITIALIZER = new CompileTimeErrorCode('NON_CONSTANT_VALUE_IN_INITIALIZER', 76, "");
   /**
    * 7.9 Superclasses: It is a compile-time error to specify an extends clause for class Object.
    */
-  static final CompileTimeErrorCode OBJECT_CANNOT_EXTEND_ANOTHER_CLASS = new CompileTimeErrorCode('OBJECT_CANNOT_EXTEND_ANOTHER_CLASS', 76, "");
+  static final CompileTimeErrorCode OBJECT_CANNOT_EXTEND_ANOTHER_CLASS = new CompileTimeErrorCode('OBJECT_CANNOT_EXTEND_ANOTHER_CLASS', 77, "");
   /**
    * 7.1.1 Operators: It is a compile-time error to declare an optional parameter in an operator.
    */
-  static final CompileTimeErrorCode OPTIONAL_PARAMETER_IN_OPERATOR = new CompileTimeErrorCode('OPTIONAL_PARAMETER_IN_OPERATOR', 77, "");
+  static final CompileTimeErrorCode OPTIONAL_PARAMETER_IN_OPERATOR = new CompileTimeErrorCode('OPTIONAL_PARAMETER_IN_OPERATOR', 78, "");
   /**
    * 8 Interfaces: It is a compile-time error if an interface member <i>m1</i> overrides an
    * interface member <i>m2</i> and <i>m1</i> does not declare all the named parameters declared by
    * <i>m2</i> in the same order.
    */
-  static final CompileTimeErrorCode OVERRIDE_MISSING_NAMED_PARAMETERS = new CompileTimeErrorCode('OVERRIDE_MISSING_NAMED_PARAMETERS', 78, "");
+  static final CompileTimeErrorCode OVERRIDE_MISSING_NAMED_PARAMETERS = new CompileTimeErrorCode('OVERRIDE_MISSING_NAMED_PARAMETERS', 79, "");
   /**
    * 8 Interfaces: It is a compile-time error if an interface member <i>m1</i> overrides an
    * interface member <i>m2</i> and <i>m1</i> has a different number of required parameters than
    * <i>m2</i>.
    */
-  static final CompileTimeErrorCode OVERRIDE_MISSING_REQUIRED_PARAMETERS = new CompileTimeErrorCode('OVERRIDE_MISSING_REQUIRED_PARAMETERS', 79, "");
+  static final CompileTimeErrorCode OVERRIDE_MISSING_REQUIRED_PARAMETERS = new CompileTimeErrorCode('OVERRIDE_MISSING_REQUIRED_PARAMETERS', 80, "");
   /**
    * 14.3 Parts: It is a compile time error if the contents of the URI are not a valid part
    * declaration.
    */
-  static final CompileTimeErrorCode PART_OF_NON_PART = new CompileTimeErrorCode('PART_OF_NON_PART', 80, "");
+  static final CompileTimeErrorCode PART_OF_NON_PART = new CompileTimeErrorCode('PART_OF_NON_PART', 81, "");
   /**
    * 14.1 Imports: It is a compile-time error if the current library declares a top-level member
    * named <i>p</i>.
    */
-  static final CompileTimeErrorCode PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER = new CompileTimeErrorCode('PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER', 81, "");
+  static final CompileTimeErrorCode PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER = new CompileTimeErrorCode('PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER', 82, "");
   /**
    * 6.2.2 Optional Formals: It is a compile-time error if the name of a named optional parameter
    * begins with an ‘_’ character.
    */
-  static final CompileTimeErrorCode PRIVATE_OPTIONAL_PARAMETER = new CompileTimeErrorCode('PRIVATE_OPTIONAL_PARAMETER', 82, "");
+  static final CompileTimeErrorCode PRIVATE_OPTIONAL_PARAMETER = new CompileTimeErrorCode('PRIVATE_OPTIONAL_PARAMETER', 83, "");
   /**
    * 12.1 Constants: It is a compile-time error if the value of a compile-time constant expression
    * depends on itself.
    */
-  static final CompileTimeErrorCode RECURSIVE_COMPILE_TIME_CONSTANT = new CompileTimeErrorCode('RECURSIVE_COMPILE_TIME_CONSTANT', 83, "");
+  static final CompileTimeErrorCode RECURSIVE_COMPILE_TIME_CONSTANT = new CompileTimeErrorCode('RECURSIVE_COMPILE_TIME_CONSTANT', 84, "");
   /**
    * 7.6.2 Factories: It is a compile-time error if a redirecting factory constructor redirects to
    * itself, either directly or indirectly via a sequence of redirections.
    */
-  static final CompileTimeErrorCode RECURSIVE_FACTORY_REDIRECT = new CompileTimeErrorCode('RECURSIVE_FACTORY_REDIRECT', 84, "");
+  static final CompileTimeErrorCode RECURSIVE_FACTORY_REDIRECT = new CompileTimeErrorCode('RECURSIVE_FACTORY_REDIRECT', 85, "");
   /**
    * 15.3.1 Typedef: It is a compile-time error if a typedef refers to itself via a chain of
    * references that does not include a class type.
    */
-  static final CompileTimeErrorCode RECURSIVE_FUNCTION_TYPE_ALIAS = new CompileTimeErrorCode('RECURSIVE_FUNCTION_TYPE_ALIAS', 85, "");
+  static final CompileTimeErrorCode RECURSIVE_FUNCTION_TYPE_ALIAS = new CompileTimeErrorCode('RECURSIVE_FUNCTION_TYPE_ALIAS', 86, "");
   /**
    * 8.1 Superinterfaces: It is a compile-time error if an interface is a superinterface of itself.
    */
-  static final CompileTimeErrorCode RECURSIVE_INTERFACE_INHERITANCE = new CompileTimeErrorCode('RECURSIVE_INTERFACE_INHERITANCE', 86, "");
+  static final CompileTimeErrorCode RECURSIVE_INTERFACE_INHERITANCE = new CompileTimeErrorCode('RECURSIVE_INTERFACE_INHERITANCE', 87, "");
   /**
    * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with the const modifier but
    * <i>k’</i> is not a constant constructor.
    */
-  static final CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR = new CompileTimeErrorCode('REDIRECT_TO_NON_CONST_CONSTRUCTOR', 87, "");
+  static final CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR = new CompileTimeErrorCode('REDIRECT_TO_NON_CONST_CONSTRUCTOR', 88, "");
   /**
    * 13.3 Local Variable Declaration: It is a compile-time error if <i>e</i> refers to the name
    * <i>v</i> or the name <i>v=</i>.
    */
-  static final CompileTimeErrorCode REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER = new CompileTimeErrorCode('REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER', 88, "");
+  static final CompileTimeErrorCode REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER = new CompileTimeErrorCode('REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER', 89, "");
   /**
    * 16.1.1 Reserved Words: A reserved word may not be used as an identifier; it is a compile-time
    * error if a reserved word is used where an identifier is expected.
    */
-  static final CompileTimeErrorCode RESERVED_WORD_AS_IDENTIFIER = new CompileTimeErrorCode('RESERVED_WORD_AS_IDENTIFIER', 89, "");
+  static final CompileTimeErrorCode RESERVED_WORD_AS_IDENTIFIER = new CompileTimeErrorCode('RESERVED_WORD_AS_IDENTIFIER', 90, "");
   /**
    * 13.11 Return: It is a compile-time error if a return statement of the form <i>return e;</i>
    * appears in a generative constructor.
    */
-  static final CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode('RETURN_IN_GENERATIVE_CONSTRUCTOR', 90, "");
+  static final CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR = new CompileTimeErrorCode('RETURN_IN_GENERATIVE_CONSTRUCTOR', 91, "");
   /**
    * 6.1 Function Declarations: It is a compile-time error to preface a function declaration with
    * the built-in identifier static.
    */
-  static final CompileTimeErrorCode STATIC_TOP_LEVEL_FUNCTION = new CompileTimeErrorCode('STATIC_TOP_LEVEL_FUNCTION', 91, "");
+  static final CompileTimeErrorCode STATIC_TOP_LEVEL_FUNCTION = new CompileTimeErrorCode('STATIC_TOP_LEVEL_FUNCTION', 92, "");
   /**
    * 5 Variables: It is a compile-time error to preface a top level variable declaration with the
    * built-in identifier static.
    */
-  static final CompileTimeErrorCode STATIC_TOP_LEVEL_VARIABLE = new CompileTimeErrorCode('STATIC_TOP_LEVEL_VARIABLE', 92, "");
+  static final CompileTimeErrorCode STATIC_TOP_LEVEL_VARIABLE = new CompileTimeErrorCode('STATIC_TOP_LEVEL_VARIABLE', 93, "");
   /**
    * 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
    * <i>super.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>, &hellip;
@@ -859,17 +878,17 @@
    * initializer list, in class Object, in a factory constructor, or in a static method or variable
    * initializer.
    */
-  static final CompileTimeErrorCode SUPER_IN_INVALID_CONTEXT = new CompileTimeErrorCode('SUPER_IN_INVALID_CONTEXT', 93, "");
+  static final CompileTimeErrorCode SUPER_IN_INVALID_CONTEXT = new CompileTimeErrorCode('SUPER_IN_INVALID_CONTEXT', 94, "");
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It is a compile-time
    * error if a generative constructor of class Object includes a superinitializer.
    */
-  static final CompileTimeErrorCode SUPER_INITIALIZER_IN_OBJECT = new CompileTimeErrorCode('SUPER_INITIALIZER_IN_OBJECT', 94, "");
+  static final CompileTimeErrorCode SUPER_INITIALIZER_IN_OBJECT = new CompileTimeErrorCode('SUPER_INITIALIZER_IN_OBJECT', 95, "");
   /**
    * 12.8 Throw: It is a compile-time error if an expression of the form throw; is not enclosed
    * within a on-catch clause.
    */
-  static final CompileTimeErrorCode THROW_WITHOUT_VALUE_OUTSIDE_ON = new CompileTimeErrorCode('THROW_WITHOUT_VALUE_OUTSIDE_ON', 95, "");
+  static final CompileTimeErrorCode THROW_WITHOUT_VALUE_OUTSIDE_ON = new CompileTimeErrorCode('THROW_WITHOUT_VALUE_OUTSIDE_ON', 96, "");
   /**
    * 12.11 Instance Creation: It is a compile-time error if a constructor of a non-generic type
    * invoked by a new expression or a constant object expression is passed any type arguments.
@@ -878,14 +897,14 @@
    * <i>G&lt;T<sub>1</sub>, &hellip;, T<sub>n</sub>&gt;</i> and <i>G</i> is not a generic type with
    * <i>n</i> type parameters.
    */
-  static final CompileTimeErrorCode TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS = new CompileTimeErrorCode('TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS', 96, "");
+  static final CompileTimeErrorCode TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS = new CompileTimeErrorCode('TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS', 97, "");
   /**
    * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
    * and let <i>S</i> be the superclass of <i>C</i>. Let <i>k</i> be a generative constructor. It is
    * a compile-time error if class <i>S</i> does not declare a generative constructor named <i>S</i>
    * (respectively <i>S.id</i>)
    */
-  static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 97, "");
+  static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 98, "");
   /**
    * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. Each final instance
    * variable <i>f</i> declared in the immediately enclosing class must have an initializer in
@@ -897,7 +916,7 @@
    * </ol>
    * or a compile-time error occurs.
    */
-  static final CompileTimeErrorCode UNINITIALIZED_FINAL_FIELD = new CompileTimeErrorCode('UNINITIALIZED_FINAL_FIELD', 98, "");
+  static final CompileTimeErrorCode UNINITIALIZED_FINAL_FIELD = new CompileTimeErrorCode('UNINITIALIZED_FINAL_FIELD', 99, "");
   /**
    * 14.1 Imports: It is a compile-time error if <i>x</i> is not a compile-time constant, or if
    * <i>x</i> involves string interpolation.
@@ -908,7 +927,7 @@
    * 14.5 URIs: It is a compile-time error if the string literal <i>x</i> that describes a URI is
    * not a compile-time constant, or if <i>x</i> involves string interpolation.
    */
-  static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode('URI_WITH_INTERPOLATION', 99, "URIs cannot use string interpolation");
+  static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode('URI_WITH_INTERPOLATION', 100, "URIs cannot use string interpolation");
   /**
    * 7.1.1 Operators: It is a compile-time error if the arity of the user-declared operator []= is
    * not 2. It is a compile time error if the arity of a user-declared operator with one of the
@@ -916,12 +935,12 @@
    * It is a compile time error if the arity of the user-declared operator - is not 0 or 1. It is a
    * compile time error if the arity of the user-declared operator ~ is not 0.
    */
-  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR', 100, "");
+  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR', 101, "");
   /**
    * 7.3 Setters: It is a compile-time error if a setter’s formal parameter list does not include
    * exactly one required formal parameter <i>p</i>.
    */
-  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER', 101, "");
+  static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER', 102, "");
   /**
    * 12.11 Instance Creation: It is a compile-time error if a constructor of a generic type with
    * <i>n</i> type parameters invoked by a new expression or a constant object expression is passed
@@ -931,8 +950,8 @@
    * <i>G&lt;T<sub>1</sub>, &hellip;, T<sub>n</sub>&gt;</i> and <i>G</i> is not a generic type with
    * <i>n</i> type parameters.
    */
-  static final CompileTimeErrorCode WRONG_NUMBER_OF_TYPE_ARGUMENTS = new CompileTimeErrorCode('WRONG_NUMBER_OF_TYPE_ARGUMENTS', 102, "");
-  static final List<CompileTimeErrorCode> values = [AMBIGUOUS_EXPORT, AMBIGUOUS_IMPORT, ARGUMENT_DEFINITION_TEST_NON_PARAMETER, BUILT_IN_IDENTIFIER_AS_TYPE, BUILT_IN_IDENTIFIER_AS_TYPE_NAME, BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME, BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME, CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, COMPILE_TIME_CONSTANT_RAISES_EXCEPTION, COMPILE_TIME_CONSTANT_RAISES_EXCEPTION_DIVIDE_BY_ZERO, CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD, CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD, CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, CONST_FORMAL_PARAMETER, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, CONST_EVAL_THROWS_EXCEPTION, CONST_WITH_INVALID_TYPE_PARAMETERS, CONST_WITH_NON_CONST, CONST_WITH_NON_CONSTANT_ARGUMENT, CONST_WITH_NON_TYPE, CONST_WITH_TYPE_PARAMETERS, CONST_WITH_UNDEFINED_CONSTRUCTOR, DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, DUPLICATE_DEFINITION, DUPLICATE_MEMBER_NAME, DUPLICATE_MEMBER_NAME_INSTANCE_STATIC, DUPLICATE_NAMED_ARGUMENT, EXPORT_OF_NON_LIBRARY, EXTENDS_NON_CLASS, EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS, FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION, FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER, FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR, FINAL_INITIALIZED_MULTIPLE_TIMES, FINAL_NOT_INITIALIZED, GETTER_AND_METHOD_WITH_SAME_NAME, IMPLEMENTS_DYNAMIC, IMPLEMENTS_NON_CLASS, IMPLEMENTS_REPEATED, IMPLEMENTS_SELF, IMPORT_DUPLICATED_LIBRARY_NAME, IMPORT_OF_NON_LIBRARY, INCONSITENT_CASE_EXPRESSION_TYPES, INITIALIZER_FOR_NON_EXISTANT_FIELD, INVALID_CONSTANT, INVALID_CONSTRUCTOR_NAME, INVALID_FACTORY_NAME_NOT_A_CLASS, INVALID_OVERRIDE_DEFAULT_VALUE, INVALID_OVERRIDE_NAMED, INVALID_OVERRIDE_POSITIONAL, INVALID_OVERRIDE_REQUIRED, INVALID_REFERENCE_TO_THIS, INVALID_TYPE_ARGUMENT_FOR_KEY, INVALID_TYPE_ARGUMENT_IN_CONST_LIST, INVALID_TYPE_ARGUMENT_IN_CONST_MAP, INVALID_VARIABLE_IN_INITIALIZER, LABEL_IN_OUTER_SCOPE, LABEL_UNDEFINED, MEMBER_WITH_CLASS_NAME, MIXIN_DECLARES_CONSTRUCTOR, MIXIN_INHERITS_FROM_NOT_OBJECT, MIXIN_OF_NON_CLASS, MIXIN_OF_NON_MIXIN, MIXIN_REFERENCES_SUPER, MIXIN_WITH_NON_CLASS_SUPERCLASS, MULTIPLE_SUPER_INITIALIZERS, NEW_WITH_INVALID_TYPE_PARAMETERS, NON_CONST_MAP_AS_EXPRESSION_STATEMENT, NON_CONSTANT_CASE_EXPRESSION, NON_CONSTANT_DEFAULT_VALUE, NON_CONSTANT_LIST_ELEMENT, NON_CONSTANT_MAP_KEY, NON_CONSTANT_MAP_VALUE, NON_CONSTANT_VALUE_IN_INITIALIZER, OBJECT_CANNOT_EXTEND_ANOTHER_CLASS, OPTIONAL_PARAMETER_IN_OPERATOR, OVERRIDE_MISSING_NAMED_PARAMETERS, OVERRIDE_MISSING_REQUIRED_PARAMETERS, PART_OF_NON_PART, PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, PRIVATE_OPTIONAL_PARAMETER, RECURSIVE_COMPILE_TIME_CONSTANT, RECURSIVE_FACTORY_REDIRECT, RECURSIVE_FUNCTION_TYPE_ALIAS, RECURSIVE_INTERFACE_INHERITANCE, REDIRECT_TO_NON_CONST_CONSTRUCTOR, REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER, RESERVED_WORD_AS_IDENTIFIER, RETURN_IN_GENERATIVE_CONSTRUCTOR, STATIC_TOP_LEVEL_FUNCTION, STATIC_TOP_LEVEL_VARIABLE, SUPER_IN_INVALID_CONTEXT, SUPER_INITIALIZER_IN_OBJECT, THROW_WITHOUT_VALUE_OUTSIDE_ON, TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS, UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, UNINITIALIZED_FINAL_FIELD, URI_WITH_INTERPOLATION, WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR, WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, WRONG_NUMBER_OF_TYPE_ARGUMENTS];
+  static final CompileTimeErrorCode WRONG_NUMBER_OF_TYPE_ARGUMENTS = new CompileTimeErrorCode('WRONG_NUMBER_OF_TYPE_ARGUMENTS', 103, "");
+  static final List<CompileTimeErrorCode> values = [AMBIGUOUS_EXPORT, AMBIGUOUS_IMPORT, ARGUMENT_DEFINITION_TEST_NON_PARAMETER, BUILT_IN_IDENTIFIER_AS_TYPE, BUILT_IN_IDENTIFIER_AS_TYPE_NAME, BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME, BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME, CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, COMPILE_TIME_CONSTANT_RAISES_EXCEPTION, COMPILE_TIME_CONSTANT_RAISES_EXCEPTION_DIVIDE_BY_ZERO, CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD, CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD, CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, CONST_FORMAL_PARAMETER, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, CONST_EVAL_THROWS_EXCEPTION, CONST_WITH_INVALID_TYPE_PARAMETERS, CONST_WITH_NON_CONST, CONST_WITH_NON_CONSTANT_ARGUMENT, CONST_WITH_NON_TYPE, CONST_WITH_TYPE_PARAMETERS, CONST_WITH_UNDEFINED_CONSTRUCTOR, DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, DUPLICATE_DEFINITION, DUPLICATE_MEMBER_NAME, DUPLICATE_MEMBER_NAME_INSTANCE_STATIC, DUPLICATE_NAMED_ARGUMENT, EXPORT_OF_NON_LIBRARY, EXTENDS_NON_CLASS, EXTENDS_DISALLOWED_CLASS, IMPLEMENTS_DISALLOWED_CLASS, FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION, FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER, FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR, FINAL_INITIALIZED_MULTIPLE_TIMES, FINAL_NOT_INITIALIZED, GETTER_AND_METHOD_WITH_SAME_NAME, IMPLEMENTS_DYNAMIC, IMPLEMENTS_NON_CLASS, IMPLEMENTS_REPEATED, IMPLEMENTS_SELF, IMPORT_DUPLICATED_LIBRARY_NAME, IMPORT_OF_NON_LIBRARY, INCONSITENT_CASE_EXPRESSION_TYPES, INITIALIZER_FOR_NON_EXISTANT_FIELD, INVALID_CONSTANT, INVALID_CONSTRUCTOR_NAME, INVALID_FACTORY_NAME_NOT_A_CLASS, INVALID_OVERRIDE_DEFAULT_VALUE, INVALID_OVERRIDE_NAMED, INVALID_OVERRIDE_POSITIONAL, INVALID_OVERRIDE_REQUIRED, INVALID_REFERENCE_TO_THIS, INVALID_TYPE_ARGUMENT_FOR_KEY, INVALID_TYPE_ARGUMENT_IN_CONST_LIST, INVALID_TYPE_ARGUMENT_IN_CONST_MAP, INVALID_VARIABLE_IN_INITIALIZER, LABEL_IN_OUTER_SCOPE, LABEL_UNDEFINED, MEMBER_WITH_CLASS_NAME, MIXIN_DECLARES_CONSTRUCTOR, MIXIN_INHERITS_FROM_NOT_OBJECT, MIXIN_OF_NON_CLASS, MIXIN_OF_NON_MIXIN, MIXIN_REFERENCES_SUPER, MIXIN_WITH_NON_CLASS_SUPERCLASS, MULTIPLE_SUPER_INITIALIZERS, NEW_WITH_INVALID_TYPE_PARAMETERS, NON_CONST_MAP_AS_EXPRESSION_STATEMENT, NON_CONSTANT_CASE_EXPRESSION, NON_CONSTANT_DEFAULT_VALUE, NON_CONSTANT_LIST_ELEMENT, NON_CONSTANT_MAP_KEY, NON_CONSTANT_MAP_VALUE, NON_CONSTANT_VALUE_IN_INITIALIZER, OBJECT_CANNOT_EXTEND_ANOTHER_CLASS, OPTIONAL_PARAMETER_IN_OPERATOR, OVERRIDE_MISSING_NAMED_PARAMETERS, OVERRIDE_MISSING_REQUIRED_PARAMETERS, PART_OF_NON_PART, PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, PRIVATE_OPTIONAL_PARAMETER, RECURSIVE_COMPILE_TIME_CONSTANT, RECURSIVE_FACTORY_REDIRECT, RECURSIVE_FUNCTION_TYPE_ALIAS, RECURSIVE_INTERFACE_INHERITANCE, REDIRECT_TO_NON_CONST_CONSTRUCTOR, REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER, RESERVED_WORD_AS_IDENTIFIER, RETURN_IN_GENERATIVE_CONSTRUCTOR, STATIC_TOP_LEVEL_FUNCTION, STATIC_TOP_LEVEL_VARIABLE, SUPER_IN_INVALID_CONTEXT, SUPER_INITIALIZER_IN_OBJECT, THROW_WITHOUT_VALUE_OUTSIDE_ON, TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS, UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, UNINITIALIZED_FINAL_FIELD, URI_WITH_INTERPOLATION, WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR, WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, WRONG_NUMBER_OF_TYPE_ARGUMENTS];
   final String __name;
   final int __ordinal;
   int get ordinal => __ordinal;
diff --git a/pkg/analyzer_experimental/lib/src/generated/html.dart b/pkg/analyzer_experimental/lib/src/generated/html.dart
index 1114485..f3c33b8 100644
--- a/pkg/analyzer_experimental/lib/src/generated/html.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/html.dart
@@ -42,10 +42,10 @@
    * @param offset the offset from the beginning of the file to the first character in the token
    */
   Token.con1(TokenType type, int offset) {
-    _jtd_constructor_147_impl(type, offset);
+    _jtd_constructor_149_impl(type, offset);
   }
-  _jtd_constructor_147_impl(TokenType type, int offset) {
-    _jtd_constructor_148_impl(type, offset, type.lexeme);
+  _jtd_constructor_149_impl(TokenType type, int offset) {
+    _jtd_constructor_150_impl(type, offset, type.lexeme);
   }
   /**
    * Initialize a newly created token.
@@ -54,9 +54,9 @@
    * @param value the lexeme represented by this token (not {@code null})
    */
   Token.con2(TokenType type4, int offset3, String value7) {
-    _jtd_constructor_148_impl(type4, offset3, value7);
+    _jtd_constructor_150_impl(type4, offset3, value7);
   }
-  _jtd_constructor_148_impl(TokenType type4, int offset3, String value7) {
+  _jtd_constructor_150_impl(TokenType type4, int offset3, String value7) {
     this._type = type4;
     this._value = value7;
     this._offset = offset3;
diff --git a/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart b/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
index f4c632b..c01a787 100644
--- a/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
@@ -75,15 +75,17 @@
   }
 }
 class InstrumentationBuilder_8 implements InstrumentationBuilder {
-  InstrumentationBuilder data(String name, int value) => this;
-  InstrumentationBuilder data2(String name, String value) => this;
-  InstrumentationBuilder data3(String name, List<String> value) => this;
+  InstrumentationBuilder data(String name, bool value) => this;
+  InstrumentationBuilder data2(String name, int value) => this;
+  InstrumentationBuilder data3(String name, String value) => this;
+  InstrumentationBuilder data4(String name, List<String> value) => this;
   InstrumentationLevel get instrumentationLevel => InstrumentationLevel.OFF;
   void log() {
   }
-  InstrumentationBuilder metric(String name, int value) => this;
-  InstrumentationBuilder metric2(String name, String value) => this;
-  InstrumentationBuilder metric3(String name, List<String> value) => this;
+  InstrumentationBuilder metric(String name, bool value) => this;
+  InstrumentationBuilder metric2(String name, int value) => this;
+  InstrumentationBuilder metric3(String name, String value) => this;
+  InstrumentationBuilder metric4(String name, List<String> value) => this;
 }
 class InstrumentationLogger_9 implements InstrumentationLogger {
   InstrumentationBuilder createBuilder(String name) => Instrumentation._NULL_INSTRUMENTATION_BUILDER;
@@ -104,7 +106,7 @@
    * @param value the value of the data to be collected
    * @return this builder
    */
-  InstrumentationBuilder data(String name, int value);
+  InstrumentationBuilder data(String name, bool value);
   /**
    * Append the given data to the data being collected by this builder. The information is declared
    * to potentially contain data that is either user identifiable or contains user intellectual
@@ -113,7 +115,7 @@
    * @param value the value of the data to be collected
    * @return this builder
    */
-  InstrumentationBuilder data2(String name, String value);
+  InstrumentationBuilder data2(String name, int value);
   /**
    * Append the given data to the data being collected by this builder. The information is declared
    * to potentially contain data that is either user identifiable or contains user intellectual
@@ -122,7 +124,16 @@
    * @param value the value of the data to be collected
    * @return this builder
    */
-  InstrumentationBuilder data3(String name, List<String> value);
+  InstrumentationBuilder data3(String name, String value);
+  /**
+   * Append the given data to the data being collected by this builder. The information is declared
+   * to potentially contain data that is either user identifiable or contains user intellectual
+   * property (but is not guaranteed to contain either).
+   * @param name the name used to identify the data
+   * @param value the value of the data to be collected
+   * @return this builder
+   */
+  InstrumentationBuilder data4(String name, List<String> value);
   /**
    * Answer the {@link InstrumentationLevel} of this {@code InstrumentationBuilder}.
    * @return one of {@link InstrumentationLevel#EVERYTHING}, {@link InstrumentationLevel#METRICS},{@link InstrumentationLevel#OFF}
@@ -142,7 +153,7 @@
    * @param value the value of the data to be collected
    * @return this builder
    */
-  InstrumentationBuilder metric(String name, int value);
+  InstrumentationBuilder metric(String name, bool value);
   /**
    * Append the given metric to the data being collected by this builder. The information is
    * declared to contain only metrics data (data that is not user identifiable and does not contain
@@ -151,7 +162,7 @@
    * @param value the value of the data to be collected
    * @return this builder
    */
-  InstrumentationBuilder metric2(String name, String value);
+  InstrumentationBuilder metric2(String name, int value);
   /**
    * Append the given metric to the data being collected by this builder. The information is
    * declared to contain only metrics data (data that is not user identifiable and does not contain
@@ -160,7 +171,16 @@
    * @param value the value of the data to be collected
    * @return this builder
    */
-  InstrumentationBuilder metric3(String name, List<String> value);
+  InstrumentationBuilder metric3(String name, String value);
+  /**
+   * Append the given metric to the data being collected by this builder. The information is
+   * declared to contain only metrics data (data that is not user identifiable and does not contain
+   * user intellectual property).
+   * @param name the name used to identify the data
+   * @param value the value of the data to be collected
+   * @return this builder
+   */
+  InstrumentationBuilder metric4(String name, List<String> value);
 }
 /**
  * The instrumentation recording level representing (1) recording {@link #EVERYTHING} recording of
diff --git a/pkg/analyzer_experimental/lib/src/generated/java_core.dart b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
index 1170ca1..877ce04 100644
--- a/pkg/analyzer_experimental/lib/src/generated/java_core.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
@@ -408,6 +408,10 @@
   return a.toLowerCase() == b.toLowerCase();
 }
 
+bool javaBooleanOr(bool a, bool b) {
+  return a || b;
+}
+
 class JavaStringBuilder {
   StringBuffer sb = new StringBuffer();
   String toString() => sb.toString();
diff --git a/pkg/analyzer_experimental/lib/src/generated/parser.dart b/pkg/analyzer_experimental/lib/src/generated/parser.dart
index b23627d..ee8a24c 100644
--- a/pkg/analyzer_experimental/lib/src/generated/parser.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/parser.dart
@@ -1732,6 +1732,16 @@
     return new ContinueStatement.full(continueKeyword, label, semicolon);
   }
   /**
+   * Parse a declared identifier declaration.
+   * @param commentAndMetadata the metadata to be associated with the directive
+   * @return the declared identifier that was parsed
+   */
+  DeclaredIdentifier parseDeclaredIdentifier(CommentAndMetadata commentAndMetadata) {
+    FinalConstVarOrType finalConstVarOrType = parseFinalConstVarOrType(false);
+    SimpleIdentifier identifier = parseSimpleIdentifier();
+    return new DeclaredIdentifier.full(commentAndMetadata.comment, commentAndMetadata.metadata, finalConstVarOrType.keyword, finalConstVarOrType.type, identifier);
+  }
+  /**
    * Parse a directive.
    * <pre>
    * directive ::=
@@ -2151,7 +2161,7 @@
    * | declaredIdentifier 'in' expression
    * | identifier 'in' expression
    * forInitializerStatement ::=
-   * variableDeclarationList ';'
+   * localVariableDeclaration ';'
    * | expression? ';'
    * </pre>
    * @return the for statement that was parsed
@@ -2165,6 +2175,7 @@
       VariableDeclarationList variableList = null;
       Expression initialization = null;
       if (!matches5(TokenType.SEMICOLON)) {
+        CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
         if (matchesIdentifier() && matches3(peek(), Keyword.IN)) {
           List<VariableDeclaration> variables = new List<VariableDeclaration>();
           SimpleIdentifier variableName = parseSimpleIdentifier();
@@ -2188,7 +2199,7 @@
             if (variable.initializer != null) {
               reportError4(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, []);
             }
-            loopVariable = new DeclaredIdentifier.full(null, null, variableList.keyword, variableList.type, variable.name);
+            loopVariable = new DeclaredIdentifier.full(commentAndMetadata.comment, commentAndMetadata.metadata, variableList.keyword, variableList.type, variable.name);
           }
           Token inKeyword = expect(Keyword.IN);
           Expression iterator = parseExpression2();
@@ -4766,9 +4777,9 @@
    * @param message the message template used to create the message to be displayed for the error
    */
   ParserErrorCode.con1(String ___name, int ___ordinal, ErrorSeverity severity2, String message2) {
-    _jtd_constructor_269_impl(___name, ___ordinal, severity2, message2);
+    _jtd_constructor_271_impl(___name, ___ordinal, severity2, message2);
   }
-  _jtd_constructor_269_impl(String ___name, int ___ordinal, ErrorSeverity severity2, String message2) {
+  _jtd_constructor_271_impl(String ___name, int ___ordinal, ErrorSeverity severity2, String message2) {
     __name = ___name;
     __ordinal = ___ordinal;
     this._severity = severity2;
@@ -4779,10 +4790,10 @@
    * @param message the message template used to create the message to be displayed for the error
    */
   ParserErrorCode.con2(String ___name, int ___ordinal, String message) {
-    _jtd_constructor_270_impl(___name, ___ordinal, message);
+    _jtd_constructor_272_impl(___name, ___ordinal, message);
   }
-  _jtd_constructor_270_impl(String ___name, int ___ordinal, String message) {
-    _jtd_constructor_269_impl(___name, ___ordinal, ErrorSeverity.ERROR, message);
+  _jtd_constructor_272_impl(String ___name, int ___ordinal, String message) {
+    _jtd_constructor_271_impl(___name, ___ordinal, ErrorSeverity.ERROR, message);
   }
   ErrorSeverity get errorSeverity => _severity;
   String get message => _message;
@@ -5097,10 +5108,10 @@
   Object visitFormalParameterList(FormalParameterList node) {
     String groupEnd = null;
     _writer.print('(');
-    NodeList<FormalParameter> parameters13 = node.parameters;
-    int size7 = parameters13.length;
+    NodeList<FormalParameter> parameters14 = node.parameters;
+    int size7 = parameters14.length;
     for (int i = 0; i < size7; i++) {
-      FormalParameter parameter = parameters13[i];
+      FormalParameter parameter = parameters14[i];
       if (i > 0) {
         _writer.print(", ");
       }
diff --git a/pkg/analyzer_experimental/lib/src/generated/resolver.dart b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
index aba27db..002d360 100644
--- a/pkg/analyzer_experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
@@ -55,14 +55,14 @@
    * @return the compilation unit element that was built
    * @throws AnalysisException if the analysis could not be performed
    */
-  CompilationUnitElementImpl buildCompilationUnit2(Source source13, CompilationUnit unit) {
+  CompilationUnitElementImpl buildCompilationUnit2(Source source15, CompilationUnit unit) {
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
     unit.accept(builder);
-    CompilationUnitElementImpl element = new CompilationUnitElementImpl(source13.shortName);
+    CompilationUnitElementImpl element = new CompilationUnitElementImpl(source15.shortName);
     element.accessors = holder.accessors;
     element.functions = holder.functions;
-    element.source = source13;
+    element.source = source15;
     element.typeAliases = holder.typeAliases;
     element.types = holder.types;
     element.topLevelVariables = holder.topLevelVariables;
@@ -176,7 +176,12 @@
     element.const2 = node.constKeyword != null;
     _currentHolder.addConstructor(element);
     node.element = element;
-    if (constructorName != null) {
+    if (constructorName == null) {
+      Identifier returnType4 = node.returnType;
+      if (returnType4 != null) {
+        element.nameOffset = returnType4.offset;
+      }
+    } else {
       constructorName.element = element;
     }
     return null;
@@ -392,13 +397,12 @@
         nameOfMethod = "unary-";
       }
       MethodElementImpl element = new MethodElementImpl.con2(nameOfMethod, methodName.offset);
-      sc.Token keyword = node.modifierKeyword;
-      element.abstract = matches(keyword, sc.Keyword.ABSTRACT);
+      element.abstract = node.isAbstract();
       element.functions = holder.functions;
       element.labels = holder.labels;
       element.localVariables = holder.localVariables;
       element.parameters = holder.parameters;
-      element.static = matches(keyword, sc.Keyword.STATIC);
+      element.static = node.isStatic();
       _currentHolder.addMethod(element);
       methodName.element = element;
     } else {
@@ -750,9 +754,9 @@
    * @param unit the AST structure representing the HTML
    * @throws AnalysisException if the analysis could not be performed
    */
-  HtmlElementImpl buildHtmlElement2(Source source14, ht.HtmlUnit unit) {
-    HtmlElementImpl result = new HtmlElementImpl(_context, source14.shortName);
-    result.source = source14;
+  HtmlElementImpl buildHtmlElement2(Source source16, ht.HtmlUnit unit) {
+    HtmlElementImpl result = new HtmlElementImpl(_context, source16.shortName);
+    result.source = source16;
     _htmlElement = result;
     unit.accept(this);
     _htmlElement = null;
@@ -969,12 +973,12 @@
     }
     ClassElement classElement = ((type13 as InterfaceType)).element;
     ConstructorElement constructor;
-    SimpleIdentifier name14 = node.name;
-    if (name14 == null) {
+    SimpleIdentifier name15 = node.name;
+    if (name15 == null) {
       constructor = classElement.unnamedConstructor;
     } else {
-      constructor = classElement.getNamedConstructor(name14.name);
-      name14.element = constructor;
+      constructor = classElement.getNamedConstructor(name15.name);
+      name15.element = constructor;
     }
     node.element = constructor;
     return null;
@@ -1051,8 +1055,8 @@
           if (getter != null) {
             FunctionType getterType = getter.type;
             if (getterType != null) {
-              Type2 returnType4 = getterType.returnType;
-              if (!isExecutableType(returnType4)) {
+              Type2 returnType5 = getterType.returnType;
+              if (!isExecutableType(returnType5)) {
                 _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]);
               }
             }
@@ -1069,8 +1073,8 @@
           ClassElement targetClass = targetType.element as ClassElement;
           PropertyAccessorElement accessor = lookUpGetterInType(targetClass, methodName2.name);
           if (accessor != null) {
-            Type2 returnType5 = accessor.type.returnType.substitute2(((targetType as InterfaceType)).typeArguments, TypeVariableTypeImpl.getTypes(targetClass.typeVariables));
-            if (!isExecutableType(returnType5)) {
+            Type2 returnType6 = accessor.type.returnType.substitute2(((targetType as InterfaceType)).typeArguments, TypeVariableTypeImpl.getTypes(targetClass.typeVariables));
+            if (!isExecutableType(returnType6)) {
               _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]);
               return null;
             }
@@ -1102,8 +1106,8 @@
         PropertyAccessorElement getter3 = ((element as PropertyInducingElement)).getter;
         FunctionType getterType = getter3.type;
         if (getterType != null) {
-          Type2 returnType6 = getterType.returnType;
-          if (!isExecutableType(returnType6)) {
+          Type2 returnType7 = getterType.returnType;
+          if (!isExecutableType(returnType7)) {
             _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName2, [methodName2.name]);
           }
         }
@@ -1375,11 +1379,11 @@
    * @param name the name being searched for
    * @return the parameter with the given name
    */
-  ParameterElement findNamedParameter(List<ParameterElement> parameters, String name25) {
+  ParameterElement findNamedParameter(List<ParameterElement> parameters, String name26) {
     for (ParameterElement parameter in parameters) {
       if (identical(parameter.parameterKind, ParameterKind.NAMED)) {
         String parameteName = parameter.name;
-        if (parameteName != null && parameteName == name25) {
+        if (parameteName != null && parameteName == name26) {
           return parameter;
         }
       }
@@ -1755,10 +1759,10 @@
     List<ParameterElement> parameters11 = invokedMethod.parameters;
     for (Expression argument in argumentList.arguments) {
       if (argument is NamedExpression) {
-        SimpleIdentifier name15 = ((argument as NamedExpression)).name.label;
-        ParameterElement parameter = findNamedParameter(parameters11, name15.name);
+        SimpleIdentifier name16 = ((argument as NamedExpression)).name.label;
+        ParameterElement parameter = findNamedParameter(parameters11, name16.name);
         if (parameter != null) {
-          recordResolution(name15, parameter);
+          recordResolution(name16, parameter);
         }
       }
     }
@@ -2206,10 +2210,10 @@
    * @param analysisContext the analysis context in which the library is being analyzed
    */
   LibraryResolver.con1(AnalysisContextImpl analysisContext) {
-    _jtd_constructor_237_impl(analysisContext);
+    _jtd_constructor_239_impl(analysisContext);
   }
-  _jtd_constructor_237_impl(AnalysisContextImpl analysisContext) {
-    _jtd_constructor_238_impl(analysisContext, null);
+  _jtd_constructor_239_impl(AnalysisContextImpl analysisContext) {
+    _jtd_constructor_240_impl(analysisContext, null);
   }
   /**
    * Initialize a newly created library resolver to resolve libraries within the given context.
@@ -2217,9 +2221,9 @@
    * @param errorListener the listener to which analysis errors will be reported
    */
   LibraryResolver.con2(AnalysisContextImpl analysisContext2, AnalysisErrorListener additionalAnalysisErrorListener) {
-    _jtd_constructor_238_impl(analysisContext2, additionalAnalysisErrorListener);
+    _jtd_constructor_240_impl(analysisContext2, additionalAnalysisErrorListener);
   }
-  _jtd_constructor_238_impl(AnalysisContextImpl analysisContext2, AnalysisErrorListener additionalAnalysisErrorListener) {
+  _jtd_constructor_240_impl(AnalysisContextImpl analysisContext2, AnalysisErrorListener additionalAnalysisErrorListener) {
     this._analysisContext = analysisContext2;
     this._recordingErrorListener = new RecordingErrorListener();
     if (additionalAnalysisErrorListener == null) {
@@ -3184,7 +3188,7 @@
   Object visitAssignmentExpression(AssignmentExpression node) {
     sc.TokenType operator11 = node.operator.type;
     if (operator11 != sc.TokenType.EQ) {
-      return recordReturnType(node, node.element);
+      return recordReturnType(node, node.element, null);
     }
     return recordType(node, getType(node.rightHandSide));
   }
@@ -3233,7 +3237,7 @@
       }
       break;
     }
-    return recordReturnType(node, node.element);
+    return recordReturnType(node, node.element, null);
   }
   /**
    * The Dart Language Specification, 12.4: <blockquote>The static type of a boolean literal is{@code bool}.</blockquote>
@@ -3323,17 +3327,22 @@
    * If <i>F</i> is not a function type, the static type of <i>i</i> is dynamic. Otherwise the
    * static type of <i>i</i> is the declared return type of <i>F</i>.</blockquote>
    */
-  Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) => recordReturnType(node, node.element);
+  Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) => recordReturnType(node, node.element, null);
   /**
    * The Dart Language Specification, 12.29: <blockquote>An assignable expression of the form
    * <i>e<sub>1</sub>[e<sub>2</sub>]</i> is evaluated as a method invocation of the operator method
    * <i>[]</i> on <i>e<sub>1</sub></i> with argument <i>e<sub>2</sub></i>.</blockquote>
    */
   Object visitIndexExpression(IndexExpression node) {
-    if (node.inSetterContext()) {
-      return recordArgumentType(node, node.element);
+    Type2 type = getType(node.realTarget);
+    List<Type2> typeArgs = null;
+    if (type is InterfaceType) {
+      typeArgs = ((type as InterfaceType)).typeArguments;
     }
-    return recordReturnType(node, node.element);
+    if (node.inSetterContext()) {
+      return recordArgumentType(node, node.element, typeArgs);
+    }
+    return recordReturnType(node, node.element, typeArgs);
   }
   /**
    * The Dart Language Specification, 12.11.1: <blockquote>The static type of a new expression of
@@ -3436,7 +3445,7 @@
    * <i>i</i> is dynamic. Otherwise the static type of <i>i</i> is the declared return type of
    * <i>F</i>.</blockquote>
    */
-  Object visitMethodInvocation(MethodInvocation node) => recordReturnType(node, node.methodName.element);
+  Object visitMethodInvocation(MethodInvocation node) => recordReturnType(node, node.methodName.element, null);
   Object visitNamedExpression(NamedExpression node) => recordType(node, getType(node.expression));
   /**
    * The Dart Language Specification, 12.2: <blockquote>The static type of {@code null} is bottom.
@@ -3504,7 +3513,7 @@
     if (identical(operator13, sc.TokenType.BANG)) {
       return recordType(node, _typeProvider.boolType);
     }
-    return recordReturnType(node, node.element);
+    return recordReturnType(node, node.element, null);
   }
   /**
    * The Dart Language Specification, 12.13: <blockquote> Property extraction allows for a member of
@@ -3673,11 +3682,11 @@
    * @return the return type that was computed
    */
   Type2 computeReturnType(FunctionDeclaration node) {
-    TypeName returnType7 = node.returnType;
-    if (returnType7 == null) {
+    TypeName returnType8 = node.returnType;
+    if (returnType8 == null) {
       return computeReturnType2(node.functionExpression);
     }
-    return returnType7.type;
+    return returnType8.type;
   }
   /**
    * Given a function expression, compute the return type of the function. The return type of
@@ -3757,12 +3766,20 @@
    * represented by the given element.
    * @param expression the node whose type is to be recorded
    * @param element the element representing the method invoked by the given node
+   * @param typeArguments the array of {@link Type}s to perform a substitution on the parameter
+   * types from the type in the passed {@link Element}, or <code>null</code>
    */
-  Object recordArgumentType(IndexExpression expression, MethodElement element) {
+  Object recordArgumentType(IndexExpression expression, MethodElement element, List<Type2> typeArguments10) {
     if (element != null) {
       List<ParameterElement> parameters12 = element.parameters;
       if (parameters12 != null && parameters12.length == 2) {
-        return recordType(expression, parameters12[1].type);
+        ClassElement classElement = parameters12[1].getAncestor(ClassElement);
+        List<Type2> typeParameters = classElement == null ? null : classElement.type.typeArguments;
+        if (typeArguments10 == null || typeParameters == null || typeArguments10.length != typeParameters.length) {
+          return recordType(expression, parameters12[1].type);
+        } else {
+          return recordType(expression, parameters12[1].type.substitute2(typeArguments10, typeParameters));
+        }
       }
     }
     return recordType(expression, _dynamicType);
@@ -3772,26 +3789,34 @@
    * represented by the given element.
    * @param expression the node whose type is to be recorded
    * @param element the element representing the method or function invoked by the given node
+   * @param typeArguments the array of {@link Type}s to perform a substitution on the parameter
+   * types from the type in the passed {@link Element}, or <code>null</code>
    */
-  Object recordReturnType(Expression expression, Element element) {
+  Object recordReturnType(Expression expression, Element element, List<Type2> typeArguments11) {
     if (element is PropertyAccessorElement) {
       FunctionType propertyType = ((element as PropertyAccessorElement)).type;
       if (propertyType != null) {
-        Type2 returnType8 = propertyType.returnType;
-        if (returnType8 is FunctionType) {
-          Type2 innerReturnType = ((returnType8 as FunctionType)).returnType;
+        Type2 returnType9 = propertyType.returnType;
+        if (returnType9 is FunctionType) {
+          Type2 innerReturnType = ((returnType9 as FunctionType)).returnType;
           if (innerReturnType != null) {
             return recordType(expression, innerReturnType);
           }
         }
-        if (returnType8 != null) {
-          return recordType(expression, returnType8);
+        if (returnType9 != null) {
+          return recordType(expression, returnType9);
         }
       }
     } else if (element is ExecutableElement) {
       FunctionType type17 = ((element as ExecutableElement)).type;
       if (type17 != null) {
-        return recordType(expression, type17.returnType);
+        ClassElement classElement = element.getAncestor(ClassElement);
+        List<Type2> typeParameters = classElement == null ? null : classElement.type.typeArguments;
+        if (typeArguments11 == null || typeParameters == null || typeArguments11.length != typeParameters.length) {
+          return recordType(expression, type17.returnType);
+        } else {
+          return recordType(expression, type17.returnType.substitute2(typeArguments11, typeParameters));
+        }
       }
     } else if (element is VariableElement) {
       Type2 variableType = ((element as VariableElement)).type;
@@ -3821,7 +3846,7 @@
    * @param returnType the return type of the function, or {@code null} if no type was declared
    * @param parameters the elements representing the parameters to the function
    */
-  void setTypeInformation(FunctionTypeImpl functionType, Type2 returnType11, FormalParameterList parameterList) {
+  void setTypeInformation(FunctionTypeImpl functionType, Type2 returnType12, FormalParameterList parameterList) {
     List<Type2> normalParameterTypes = new List<Type2>();
     List<Type2> optionalParameterTypes = new List<Type2>();
     LinkedHashMap<String, Type2> namedParameterTypes = new LinkedHashMap<String, Type2>();
@@ -3842,7 +3867,7 @@
     functionType.normalParameterTypes = new List.from(normalParameterTypes);
     functionType.optionalParameterTypes = new List.from(optionalParameterTypes);
     functionType.namedParameterTypes = namedParameterTypes;
-    functionType.returnType = returnType11;
+    functionType.returnType = returnType12;
   }
   get thisType_J2DAccessor => _thisType;
   set thisType_J2DAccessor(__v) => _thisType = __v;
@@ -3894,6 +3919,11 @@
    */
   InterfaceType get mapType;
   /**
+   * Return the type representing the built-in type 'num'.
+   * @return the type representing the built-in type 'num'
+   */
+  InterfaceType get numType;
+  /**
    * Return the type representing the built-in type 'Object'.
    * @return the type representing the built-in type 'Object'
    */
@@ -3953,6 +3983,10 @@
    */
   InterfaceType _mapType;
   /**
+   * The type representing the built-in type 'num'.
+   */
+  InterfaceType _numType;
+  /**
    * The type representing the built-in type 'Object'.
    */
   InterfaceType _objectType;
@@ -3983,6 +4017,7 @@
   InterfaceType get intType => _intType;
   InterfaceType get listType => _listType;
   InterfaceType get mapType => _mapType;
+  InterfaceType get numType => _numType;
   InterfaceType get objectType => _objectType;
   InterfaceType get stackTraceType => _stackTraceType;
   InterfaceType get stringType => _stringType;
@@ -4016,6 +4051,7 @@
     _intType = getType(namespace, "int");
     _listType = getType(namespace, "List");
     _mapType = getType(namespace, "Map");
+    _numType = getType(namespace, "num");
     _objectType = getType(namespace, "Object");
     _stackTraceType = getType(namespace, "StackTrace");
     _stringType = getType(namespace, "String");
@@ -4485,17 +4521,17 @@
    * @return the type specified by the type name
    */
   InterfaceType resolveType(TypeName typeName, ErrorCode undefinedError, ErrorCode nonTypeError, ErrorCode nonInterfaceType) {
-    Identifier name16 = typeName.name;
-    Element element = nameScope.lookup(name16, definingLibrary);
+    Identifier name17 = typeName.name;
+    Element element = nameScope.lookup(name17, definingLibrary);
     if (element == null) {
-      reportError(undefinedError, name16, [name16.name]);
+      reportError(undefinedError, name17, [name17.name]);
     } else if (element is ClassElement) {
       Type2 classType = ((element as ClassElement)).type;
       typeName.type = classType;
       if (classType is InterfaceType) {
         return classType as InterfaceType;
       }
-      reportError(nonInterfaceType, name16, [name16.name]);
+      reportError(nonInterfaceType, name17, [name17.name]);
     } else if (element is MultiplyDefinedElement) {
       List<Element> elements = ((element as MultiplyDefinedElement)).conflictingElements;
       InterfaceType type = getType(elements);
@@ -4503,7 +4539,7 @@
         typeName.type = type;
       }
     } else {
-      reportError(nonTypeError, name16, [name16.name]);
+      reportError(nonTypeError, name17, [name17.name]);
     }
     return null;
   }
@@ -4548,7 +4584,7 @@
    * @param returnType the return type of the function, or {@code null} if no type was declared
    * @param parameters the elements representing the parameters to the function
    */
-  void setTypeInformation(FunctionTypeImpl functionType, TypeName returnType12, List<ParameterElement> parameters) {
+  void setTypeInformation(FunctionTypeImpl functionType, TypeName returnType13, List<ParameterElement> parameters) {
     List<Type2> normalParameterTypes = new List<Type2>();
     List<Type2> optionalParameterTypes = new List<Type2>();
     LinkedHashMap<String, Type2> namedParameterTypes = new LinkedHashMap<String, Type2>();
@@ -4573,10 +4609,10 @@
     if (!namedParameterTypes.isEmpty) {
       functionType.namedParameterTypes = namedParameterTypes;
     }
-    if (returnType12 == null) {
+    if (returnType13 == null) {
       functionType.returnType = _dynamicType;
     } else {
-      functionType.returnType = returnType12.type;
+      functionType.returnType = returnType13.type;
     }
   }
 }
@@ -4669,8 +4705,8 @@
   void defineParameters(ExecutableElement functionElement) {
     Scope parameterScope = enclosingScope;
     if (functionElement.enclosingElement is ExecutableElement) {
-      String name17 = functionElement.name;
-      if (name17 != null && !name17.isEmpty) {
+      String name18 = functionElement.name;
+      if (name18 != null && !name18.isEmpty) {
         parameterScope.define(functionElement);
       }
     }
@@ -4738,10 +4774,10 @@
    * @param onSwitchMember {@code true} if this label is associated with a {@code switch} member
    */
   LabelScope.con1(LabelScope outerScope, bool onSwitchStatement, bool onSwitchMember) {
-    _jtd_constructor_248_impl(outerScope, onSwitchStatement, onSwitchMember);
+    _jtd_constructor_250_impl(outerScope, onSwitchStatement, onSwitchMember);
   }
-  _jtd_constructor_248_impl(LabelScope outerScope, bool onSwitchStatement, bool onSwitchMember) {
-    _jtd_constructor_249_impl(outerScope, EMPTY_LABEL, new LabelElementImpl(_EMPTY_LABEL_IDENTIFIER, onSwitchStatement, onSwitchMember));
+  _jtd_constructor_250_impl(LabelScope outerScope, bool onSwitchStatement, bool onSwitchMember) {
+    _jtd_constructor_251_impl(outerScope, EMPTY_LABEL, new LabelElementImpl(_EMPTY_LABEL_IDENTIFIER, onSwitchStatement, onSwitchMember));
   }
   /**
    * Initialize a newly created scope to represent the given label.
@@ -4750,9 +4786,9 @@
    * @param element the element to which the label resolves
    */
   LabelScope.con2(LabelScope outerScope2, String label4, LabelElement element19) {
-    _jtd_constructor_249_impl(outerScope2, label4, element19);
+    _jtd_constructor_251_impl(outerScope2, label4, element19);
   }
-  _jtd_constructor_249_impl(LabelScope outerScope2, String label4, LabelElement element19) {
+  _jtd_constructor_251_impl(LabelScope outerScope2, String label4, LabelElement element19) {
     this._outerScope = outerScope2;
     this._label = label4;
     this._element = element19;
@@ -5009,9 +5045,9 @@
    * @param element the element to be added
    */
   void addIfPublic(Map<String, Element> definedNames, Element element) {
-    String name18 = element.name;
-    if (name18 != null && !Scope.isPrivateName(name18)) {
-      definedNames[name18] = element;
+    String name19 = element.name;
+    if (name19 != null && !Scope.isPrivateName(name19)) {
+      definedNames[name19] = element;
     }
   }
   /**
@@ -5353,11 +5389,11 @@
    * compile time constant.
    * @param parameters the list of parameters to be validated
    */
-  void validateDefaultValues(FormalParameterList parameters14) {
-    if (parameters14 == null) {
+  void validateDefaultValues(FormalParameterList parameters15) {
+    if (parameters15 == null) {
       return;
     }
-    for (FormalParameter parameter in parameters14.parameters) {
+    for (FormalParameter parameter in parameters15.parameters) {
       if (parameter is DefaultFormalParameter) {
         DefaultFormalParameter defaultParameter = parameter as DefaultFormalParameter;
         Expression defaultValue2 = defaultParameter.defaultValue;
@@ -5395,15 +5431,26 @@
    */
   TypeProvider _typeProvider;
   /**
+   * This is set to <code>true</code> iff the visitor is currently visiting children nodes of a{@link ConstructorDeclaration} and the constructor is 'const'.
+   * @see #visitConstructorDeclaration(ConstructorDeclaration)
+   */
+  bool _isEnclosingConstructorConst = false;
+  /**
    * The method or function that we are currently visiting, or {@code null} if we are not inside a
    * method or function.
    */
   ExecutableElement _currentFunction;
+  /**
+   * A list of types used by the {@link CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS} and{@link CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS} error codes.
+   */
+  List<InterfaceType> _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT;
   ErrorVerifier(ErrorReporter errorReporter, LibraryElement currentLibrary, TypeProvider typeProvider) {
     this._errorReporter = errorReporter;
     this._currentLibrary = currentLibrary;
     this._typeProvider = typeProvider;
+    _isEnclosingConstructorConst = false;
     _dynamicType = typeProvider.dynamicType;
+    _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = <InterfaceType> [typeProvider.numType, typeProvider.intType, typeProvider.doubleType, typeProvider.boolType, typeProvider.stringType];
   }
   Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
     checkForArgumentDefinitionTestNonParameter(node);
@@ -5433,10 +5480,12 @@
     ExecutableElement previousFunction = _currentFunction;
     try {
       _currentFunction = node.element;
+      _isEnclosingConstructorConst = node.constKeyword != null;
       checkForConstConstructorWithNonFinalField(node);
       checkForConflictingConstructorNameAndMember(node);
       return super.visitConstructorDeclaration(node);
     } finally {
+      _isEnclosingConstructorConst = false;
       _currentFunction = previousFunction;
     }
   }
@@ -5444,6 +5493,10 @@
     checkForNonBoolCondition(node.condition);
     return super.visitDoStatement(node);
   }
+  Object visitExtendsClause(ExtendsClause node) {
+    checkForExtendsDisallowedClass(node);
+    return super.visitExtendsClause(node);
+  }
   Object visitFieldFormalParameter(FieldFormalParameter node) {
     checkForConstFormalParameter(node);
     return super.visitFieldFormalParameter(node);
@@ -5468,12 +5521,17 @@
   }
   Object visitFunctionTypeAlias(FunctionTypeAlias node) {
     checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
+    checkForDefaultValueInFunctionTypeAlias(node);
     return super.visitFunctionTypeAlias(node);
   }
   Object visitIfStatement(IfStatement node) {
     checkForNonBoolCondition(node.condition);
     return super.visitIfStatement(node);
   }
+  Object visitImplementsClause(ImplementsClause node) {
+    checkForImplementsDisallowedClass(node);
+    return super.visitImplementsClause(node);
+  }
   Object visitInstanceCreationExpression(InstanceCreationExpression node) {
     ConstructorName constructorName4 = node.constructorName;
     TypeName typeName = constructorName4.type;
@@ -5507,6 +5565,10 @@
     checkForCaseExpressionTypeImplementsEquals(node);
     return super.visitSwitchStatement(node);
   }
+  Object visitThrowExpression(ThrowExpression node) {
+    checkForConstEvalThrowsException(node);
+    return super.visitThrowExpression(node);
+  }
   Object visitTypeParameter(TypeParameter node) {
     checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME);
     return super.visitTypeParameter(node);
@@ -5603,19 +5665,19 @@
     ConstructorElement constructorElement = node.element;
     SimpleIdentifier constructorName = node.name;
     if (constructorName != null && constructorElement != null && !constructorName.isSynthetic()) {
-      String name20 = constructorName.name;
+      String name21 = constructorName.name;
       ClassElement classElement = constructorElement.enclosingElement;
       List<FieldElement> fields3 = classElement.fields;
       for (FieldElement field in fields3) {
-        if (field.name == name20) {
-          _errorReporter.reportError(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD, node, [name20]);
+        if (field.name == name21) {
+          _errorReporter.reportError(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD, node, [name21]);
           return true;
         }
       }
       List<MethodElement> methods3 = classElement.methods;
       for (MethodElement method in methods3) {
-        if (method.name == name20) {
-          _errorReporter.reportError(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD, node, [name20]);
+        if (method.name == name21) {
+          _errorReporter.reportError(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD, node, [name21]);
           return true;
         }
       }
@@ -5630,7 +5692,7 @@
    * @see CompileTimeErrorCode#CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
    */
   bool checkForConstConstructorWithNonFinalField(ConstructorDeclaration node) {
-    if (node.constKeyword == null) {
+    if (!_isEnclosingConstructorConst) {
       return false;
     }
     ConstructorElement constructorElement = node.element;
@@ -5647,6 +5709,20 @@
     return false;
   }
   /**
+   * This verifies that the passed throw expression is not enclosed in a 'const' constructor
+   * declaration.
+   * @param node the throw expression expression to evaluate
+   * @return return <code>true</code> if and only if an error code is generated on the passed node
+   * @see CompileTimeErrorCode#CONST_EVAL_THROWS_EXCEPTION
+   */
+  bool checkForConstEvalThrowsException(ThrowExpression node) {
+    if (_isEnclosingConstructorConst) {
+      _errorReporter.reportError(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node, []);
+      return true;
+    }
+    return false;
+  }
+  /**
    * This verifies that the passed normal formal parameter is not 'const'.
    * @param node the normal formal parameter to evaluate
    * @return return <code>true</code> if and only if an error code is generated on the passed node
@@ -5691,13 +5767,90 @@
    * @see CompileTimeErrorCode#CONST_WITH_NON_CONST
    */
   bool checkForConstWithNonConst(InstanceCreationExpression node) {
-    if (node.isConst() && !node.element.isConst()) {
+    ConstructorElement constructorElement = node.element;
+    if (node.isConst() && constructorElement != null && !constructorElement.isConst()) {
       _errorReporter.reportError(CompileTimeErrorCode.CONST_WITH_NON_CONST, node, []);
       return true;
     }
     return false;
   }
   /**
+   * This verifies that there are no default parameters in the passed function type alias.
+   * @param node the function type alias to evaluate
+   * @return return <code>true</code> if and only if an error code is generated on the passed node
+   * @see CompileTimeErrorCode#DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS
+   */
+  bool checkForDefaultValueInFunctionTypeAlias(FunctionTypeAlias node) {
+    bool result = false;
+    FormalParameterList formalParameterList = node.parameters;
+    NodeList<FormalParameter> parameters13 = formalParameterList.parameters;
+    for (FormalParameter formalParameter in parameters13) {
+      if (formalParameter is DefaultFormalParameter) {
+        DefaultFormalParameter defaultFormalParameter = formalParameter as DefaultFormalParameter;
+        if (defaultFormalParameter.defaultValue != null) {
+          _errorReporter.reportError(CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, node, []);
+          result = true;
+        }
+      }
+    }
+    return result;
+  }
+  /**
+   * This verifies that the passed extends clause does not extend classes such as num or String.
+   * @param node the extends clause to test
+   * @return return <code>true</code> if and only if an error code is generated on the passed node
+   * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
+   */
+  bool checkForExtendsDisallowedClass(ExtendsClause extendsClause) => checkForExtendsOrImplementsDisallowedClass(extendsClause.superclass, CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS);
+  /**
+   * This verifies that the passed type name does not extend or implement classes such as 'num' or
+   * 'String'.
+   * @param node the type name to test
+   * @return return <code>true</code> if and only if an error code is generated on the passed node
+   * @see #checkForExtendsDisallowedClass(ExtendsClause)
+   * @see #checkForImplementsDisallowedClass(ImplementsClause)
+   * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
+   * @see CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS
+   */
+  bool checkForExtendsOrImplementsDisallowedClass(TypeName typeName, ErrorCode errorCode) {
+    if (typeName.isSynthetic()) {
+      return false;
+    }
+    Type2 superType = typeName.type;
+    for (InterfaceType disallowedType in _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT) {
+      if (superType == disallowedType) {
+        if (superType == _typeProvider.numType) {
+          ASTNode grandParent = typeName.parent.parent;
+          if (grandParent is ClassDeclaration) {
+            ClassElement classElement = ((grandParent as ClassDeclaration)).element;
+            Type2 classType = classElement.type;
+            if (classType != null && (classType == _typeProvider.intType || classType == _typeProvider.doubleType)) {
+              return false;
+            }
+          }
+        }
+        _errorReporter.reportError(errorCode, typeName, [disallowedType.name]);
+        return true;
+      }
+    }
+    return false;
+  }
+  /**
+   * This verifies that the passed implements clause does not implement classes such as 'num' or
+   * 'String'.
+   * @param node the implements clause to test
+   * @return return <code>true</code> if and only if an error code is generated on the passed node
+   * @see CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS
+   */
+  bool checkForImplementsDisallowedClass(ImplementsClause implementsClause) {
+    bool result = false;
+    for (TypeName type in implementsClause.interfaces) {
+      result = javaBooleanOr(result, checkForExtendsOrImplementsDisallowedClass(type, CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS));
+      ;
+    }
+    return result;
+  }
+  /**
    * This verifies that the passed assignment expression represents a valid assignment.
    * @param node the assignment expression to evaluate
    * @return return <code>true</code> if and only if an error code is generated on the passed node
diff --git a/pkg/analyzer_experimental/lib/src/generated/scanner.dart b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
index 269367d..9afb79d 100644
--- a/pkg/analyzer_experimental/lib/src/generated/scanner.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
@@ -255,10 +255,10 @@
    * @param syntax the lexeme for the keyword
    */
   Keyword.con1(String ___name, int ___ordinal, String syntax) {
-    _jtd_constructor_276_impl(___name, ___ordinal, syntax);
+    _jtd_constructor_278_impl(___name, ___ordinal, syntax);
   }
-  _jtd_constructor_276_impl(String ___name, int ___ordinal, String syntax) {
-    _jtd_constructor_277_impl(___name, ___ordinal, syntax, false);
+  _jtd_constructor_278_impl(String ___name, int ___ordinal, String syntax) {
+    _jtd_constructor_279_impl(___name, ___ordinal, syntax, false);
   }
   /**
    * Initialize a newly created keyword to have the given syntax. The keyword is a pseudo-keyword if
@@ -267,9 +267,9 @@
    * @param isPseudoKeyword {@code true} if this keyword is a pseudo-keyword
    */
   Keyword.con2(String ___name, int ___ordinal, String syntax2, bool isPseudoKeyword) {
-    _jtd_constructor_277_impl(___name, ___ordinal, syntax2, isPseudoKeyword);
+    _jtd_constructor_279_impl(___name, ___ordinal, syntax2, isPseudoKeyword);
   }
-  _jtd_constructor_277_impl(String ___name, int ___ordinal, String syntax2, bool isPseudoKeyword) {
+  _jtd_constructor_279_impl(String ___name, int ___ordinal, String syntax2, bool isPseudoKeyword) {
     __name = ___name;
     __ordinal = ___ordinal;
     this._syntax = syntax2;
@@ -1654,15 +1654,15 @@
    */
   int _precedence = 0;
   TokenClass.con1(String ___name, int ___ordinal) {
-    _jtd_constructor_286_impl(___name, ___ordinal);
+    _jtd_constructor_288_impl(___name, ___ordinal);
   }
-  _jtd_constructor_286_impl(String ___name, int ___ordinal) {
-    _jtd_constructor_287_impl(___name, ___ordinal, 0);
+  _jtd_constructor_288_impl(String ___name, int ___ordinal) {
+    _jtd_constructor_289_impl(___name, ___ordinal, 0);
   }
   TokenClass.con2(String ___name, int ___ordinal, int precedence2) {
-    _jtd_constructor_287_impl(___name, ___ordinal, precedence2);
+    _jtd_constructor_289_impl(___name, ___ordinal, precedence2);
   }
-  _jtd_constructor_287_impl(String ___name, int ___ordinal, int precedence2) {
+  _jtd_constructor_289_impl(String ___name, int ___ordinal, int precedence2) {
     __name = ___name;
     __ordinal = ___ordinal;
     this._precedence = precedence2;
@@ -1788,15 +1788,15 @@
    */
   String _lexeme;
   TokenType.con1(String ___name, int ___ordinal) {
-    _jtd_constructor_288_impl(___name, ___ordinal);
+    _jtd_constructor_290_impl(___name, ___ordinal);
   }
-  _jtd_constructor_288_impl(String ___name, int ___ordinal) {
-    _jtd_constructor_289_impl(___name, ___ordinal, TokenClass.NO_CLASS, null);
+  _jtd_constructor_290_impl(String ___name, int ___ordinal) {
+    _jtd_constructor_291_impl(___name, ___ordinal, TokenClass.NO_CLASS, null);
   }
   TokenType.con2(String ___name, int ___ordinal, TokenClass tokenClass2, String lexeme2) {
-    _jtd_constructor_289_impl(___name, ___ordinal, tokenClass2, lexeme2);
+    _jtd_constructor_291_impl(___name, ___ordinal, tokenClass2, lexeme2);
   }
-  _jtd_constructor_289_impl(String ___name, int ___ordinal, TokenClass tokenClass2, String lexeme2) {
+  _jtd_constructor_291_impl(String ___name, int ___ordinal, TokenClass tokenClass2, String lexeme2) {
     __name = ___name;
     __ordinal = ___ordinal;
     this._tokenClass = tokenClass2 == null ? TokenClass.NO_CLASS : tokenClass2;
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk.dart b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
index b8855c6..116f6ed 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
@@ -261,15 +261,15 @@
         if (argument is SimpleStringLiteral) {
           library.path = ((argument as SimpleStringLiteral)).value;
         } else if (argument is NamedExpression) {
-          String name19 = ((argument as NamedExpression)).name.label.name;
+          String name20 = ((argument as NamedExpression)).name.label.name;
           Expression expression15 = ((argument as NamedExpression)).expression;
-          if (name19 == _CATEGORY) {
+          if (name20 == _CATEGORY) {
             library.category = ((expression15 as SimpleStringLiteral)).value;
-          } else if (name19 == _IMPLEMENTATION) {
+          } else if (name20 == _IMPLEMENTATION) {
             library.implementation = ((expression15 as BooleanLiteral)).value;
-          } else if (name19 == _DOCUMENTED) {
+          } else if (name20 == _DOCUMENTED) {
             library.documented = ((expression15 as BooleanLiteral)).value;
-          } else if (name19 == _PLATFORMS) {
+          } else if (name20 == _PLATFORMS) {
             if (expression15 is SimpleIdentifier) {
               String identifier = ((expression15 as SimpleIdentifier)).name;
               if (identifier == _VM_PLATFORM) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/source.dart b/pkg/analyzer_experimental/lib/src/generated/source.dart
index e99a657..9c5ca55 100644
--- a/pkg/analyzer_experimental/lib/src/generated/source.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/source.dart
@@ -5,6 +5,7 @@
 
 import 'dart:uri';
 import 'java_core.dart';
+import 'engine.dart' show AnalysisContext;
 
 /**
  * Instances of the class {@code SourceFactory} resolve possibly relative URI's against an existing{@link Source source}.
@@ -12,6 +13,10 @@
  */
 class SourceFactory {
   /**
+   * The analysis context that this source factory is associated with.
+   */
+  AnalysisContext _context;
+  /**
    * The resolvers used to resolve absolute URI's.
    */
   List<UriResolver> _resolvers;
@@ -25,9 +30,9 @@
    * @param resolvers the resolvers used to resolve absolute URI's
    */
   SourceFactory.con1(ContentCache contentCache2, List<UriResolver> resolvers2) {
-    _jtd_constructor_300_impl(contentCache2, resolvers2);
+    _jtd_constructor_302_impl(contentCache2, resolvers2);
   }
-  _jtd_constructor_300_impl(ContentCache contentCache2, List<UriResolver> resolvers2) {
+  _jtd_constructor_302_impl(ContentCache contentCache2, List<UriResolver> resolvers2) {
     this._contentCache = contentCache2;
     this._resolvers = resolvers2;
   }
@@ -36,10 +41,10 @@
    * @param resolvers the resolvers used to resolve absolute URI's
    */
   SourceFactory.con2(List<UriResolver> resolvers) {
-    _jtd_constructor_301_impl(resolvers);
+    _jtd_constructor_303_impl(resolvers);
   }
-  _jtd_constructor_301_impl(List<UriResolver> resolvers) {
-    _jtd_constructor_300_impl(new ContentCache(), resolvers);
+  _jtd_constructor_303_impl(List<UriResolver> resolvers) {
+    _jtd_constructor_302_impl(new ContentCache(), resolvers);
   }
   /**
    * Return a source object representing the given absolute URI, or {@code null} if the URI is not a
@@ -65,6 +70,11 @@
    */
   Source fromEncoding(String encoding) => forUri(encoding);
   /**
+   * Return the analysis context that this source factory is associated with.
+   * @return the analysis context that this source factory is associated with
+   */
+  AnalysisContext get context => _context;
+  /**
    * Return a source object representing the URI that results from resolving the given (possibly
    * relative) contained URI against the URI associated with an existing source object, or{@code null} if either the contained URI is invalid or if it cannot be resolved against the
    * source object's URI.
@@ -74,7 +84,7 @@
    */
   Source resolveUri(Source containingSource, String containedUri) {
     try {
-      return resolveUri2(containingSource, new Uri.fromComponents(path: containedUri));
+      return resolveUri2(containingSource, new Uri(containedUri));
     } on URISyntaxException catch (exception) {
       return null;
     }
@@ -90,6 +100,16 @@
     _contentCache.setContents(source, contents);
   }
   /**
+   * Set the analysis context that this source factory is associated with to the given context.
+   * <p>
+   * <b>Note:</b> This method should only be invoked by{@link AnalysisContextImpl#setSourceFactory(SourceFactory)} and is only public out of
+   * necessity.
+   * @param context the analysis context that this source factory is associated with
+   */
+  void set context(AnalysisContext context2) {
+    this._context = context2;
+  }
+  /**
    * Return the contents of the given source, or {@code null} if this factory does not override the
    * contents of the source.
    * <p>
@@ -174,6 +194,11 @@
    */
   bool exists();
   /**
+   * Return the analysis context in which this source is defined.
+   * @return the analysis context in which this source is defined
+   */
+  AnalysisContext get context;
+  /**
    * Get the contents of this source and pass it to the given receiver. Exactly one of the methods
    * defined on the receiver will be invoked unless an exception is thrown. The method that will be
    * invoked depends on which of the possible representations of the contents is the most efficient.
diff --git a/pkg/analyzer_experimental/lib/src/generated/source_io.dart b/pkg/analyzer_experimental/lib/src/generated/source_io.dart
index d57574f..470a12b 100644
--- a/pkg/analyzer_experimental/lib/src/generated/source_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/source_io.dart
@@ -8,7 +8,8 @@
 import 'dart:uri';
 import 'java_core.dart';
 import 'java_io.dart';
-import 'package:analyzer_experimental/src/generated/sdk.dart' show DartSdk;
+import 'sdk.dart' show DartSdk;
+import 'engine.dart' show AnalysisContext;
 export 'source.dart';
 
 /**
@@ -36,10 +37,10 @@
    * @param file the file represented by this source
    */
   FileBasedSource.con1(SourceFactory factory, JavaFile file) {
-    _jtd_constructor_296_impl(factory, file);
+    _jtd_constructor_298_impl(factory, file);
   }
-  _jtd_constructor_296_impl(SourceFactory factory, JavaFile file) {
-    _jtd_constructor_297_impl(factory, file, false);
+  _jtd_constructor_298_impl(SourceFactory factory, JavaFile file) {
+    _jtd_constructor_299_impl(factory, file, false);
   }
   /**
    * Initialize a newly created source object.
@@ -48,15 +49,16 @@
    * @param inSystemLibrary {@code true} if this source is in one of the system libraries
    */
   FileBasedSource.con2(SourceFactory factory2, JavaFile file3, bool inSystemLibrary2) {
-    _jtd_constructor_297_impl(factory2, file3, inSystemLibrary2);
+    _jtd_constructor_299_impl(factory2, file3, inSystemLibrary2);
   }
-  _jtd_constructor_297_impl(SourceFactory factory2, JavaFile file3, bool inSystemLibrary2) {
+  _jtd_constructor_299_impl(SourceFactory factory2, JavaFile file3, bool inSystemLibrary2) {
     this._factory = factory2;
     this._file = file3;
     this._inSystemLibrary = inSystemLibrary2;
   }
   bool operator ==(Object object) => object != null && identical(this.runtimeType, object.runtimeType) && _file == ((object as FileBasedSource))._file;
   bool exists() => _file.exists();
+  AnalysisContext get context => _factory.context;
   void getContents(Source_ContentReceiver receiver) {
     {
       String contents = _factory.getContents(this);
@@ -133,6 +135,9 @@
       return null;
     }
     JavaFile resolvedFile = _sdk.mapDartUri(uri.toString());
+    if (resolvedFile == null) {
+      return null;
+    }
     return new FileBasedSource.con2(factory, resolvedFile, true);
   }
 }
@@ -216,19 +221,19 @@
    * @param directory the directory (not {@code null})
    */
   DirectoryBasedSourceContainer.con1(JavaFile directory) {
-    _jtd_constructor_294_impl(directory);
+    _jtd_constructor_296_impl(directory);
   }
-  _jtd_constructor_294_impl(JavaFile directory) {
-    _jtd_constructor_295_impl(directory.getPath());
+  _jtd_constructor_296_impl(JavaFile directory) {
+    _jtd_constructor_297_impl(directory.getPath());
   }
   /**
    * Construct a container representing the specified path and containing any sources whose{@link Source#getFullName()} starts with the specified path.
    * @param path the path (not {@code null} and not empty)
    */
   DirectoryBasedSourceContainer.con2(String path3) {
-    _jtd_constructor_295_impl(path3);
+    _jtd_constructor_297_impl(path3);
   }
-  _jtd_constructor_295_impl(String path3) {
+  _jtd_constructor_297_impl(String path3) {
     this._path = appendFileSeparator(path3);
   }
   bool contains(Source source) => source.fullName.startsWith(_path);
diff --git a/pkg/analyzer_experimental/pubspec.yaml b/pkg/analyzer_experimental/pubspec.yaml
index de2c719..5cd79cb 100644
--- a/pkg/analyzer_experimental/pubspec.yaml
+++ b/pkg/analyzer_experimental/pubspec.yaml
@@ -4,5 +4,6 @@
 description: Experimental static analyzer for Dart.
 homepage: http://www.dartlang.org
 dependencies:
-  unittest: any
   args: any
+dev_dependencies:
+  unittest: any
diff --git a/pkg/analyzer_experimental/test/generated/ast_test.dart b/pkg/analyzer_experimental/test/generated/ast_test.dart
index 68db34a..fec113d 100644
--- a/pkg/analyzer_experimental/test/generated/ast_test.dart
+++ b/pkg/analyzer_experimental/test/generated/ast_test.dart
@@ -357,9 +357,9 @@
    * @return the type name that was created
    */
   static TypeName typeName(ClassElement element55, List<TypeName> arguments) {
-    SimpleIdentifier name21 = identifier2(element55.name);
-    name21.element = element55;
-    TypeName typeName = typeName2(name21, arguments);
+    SimpleIdentifier name22 = identifier2(element55.name);
+    name22.element = element55;
+    TypeName typeName = typeName2(name22, arguments);
     typeName.type = element55.type;
     return typeName;
   }
diff --git a/pkg/analyzer_experimental/test/generated/element_test.dart b/pkg/analyzer_experimental/test/generated/element_test.dart
index f8712ad..62f3f6e 100644
--- a/pkg/analyzer_experimental/test/generated/element_test.dart
+++ b/pkg/analyzer_experimental/test/generated/element_test.dart
@@ -1159,7 +1159,7 @@
   }
   static LocalVariableElementImpl localVariableElement(Identifier name) => new LocalVariableElementImpl(name);
   static LocalVariableElementImpl localVariableElement2(String name) => new LocalVariableElementImpl(ASTFactory.identifier2(name));
-  static MethodElementImpl methodElement(String methodName, Type2 returnType13, List<Type2> argumentTypes) {
+  static MethodElementImpl methodElement(String methodName, Type2 returnType14, List<Type2> argumentTypes) {
     MethodElementImpl method = new MethodElementImpl.con1(ASTFactory.identifier2(methodName));
     int count = argumentTypes.length;
     List<ParameterElement> parameters = new List<ParameterElement>(count);
@@ -1172,7 +1172,7 @@
     method.parameters = parameters;
     FunctionTypeImpl methodType = new FunctionTypeImpl.con1(method);
     methodType.normalParameterTypes = argumentTypes;
-    methodType.returnType = returnType13;
+    methodType.returnType = returnType14;
     method.type = methodType;
     return method;
   }
@@ -1466,8 +1466,8 @@
   }
   void test_getReturnType() {
     FunctionTypeImpl type = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier2("f")));
-    Type2 returnType9 = type.returnType;
-    JUnitTestCase.assertEquals(VoidTypeImpl.instance, returnType9);
+    Type2 returnType10 = type.returnType;
+    JUnitTestCase.assertEquals(VoidTypeImpl.instance, returnType10);
   }
   void test_getTypeArguments() {
     FunctionTypeImpl type = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier2("f")));
@@ -1670,8 +1670,8 @@
     FunctionTypeImpl type = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier2("f")));
     Type2 expectedType = new InterfaceTypeImpl.con1(new ClassElementImpl(ASTFactory.identifier2("C")));
     type.returnType = expectedType;
-    Type2 returnType10 = type.returnType;
-    JUnitTestCase.assertEquals(expectedType, returnType10);
+    Type2 returnType11 = type.returnType;
+    JUnitTestCase.assertEquals(expectedType, returnType11);
   }
   void test_setTypeArguments() {
     FunctionTypeImpl type = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier2("f")));
diff --git a/pkg/analyzer_experimental/test/generated/parser_test.dart b/pkg/analyzer_experimental/test/generated/parser_test.dart
index 41eae27..01613ab 100644
--- a/pkg/analyzer_experimental/test/generated/parser_test.dart
+++ b/pkg/analyzer_experimental/test/generated/parser_test.dart
@@ -263,10 +263,10 @@
   }
   void test_parseArgument_named() {
     NamedExpression expression = ParserTestCase.parse6("parseArgument", "n: x", []);
-    Label name22 = expression.name;
-    JUnitTestCase.assertNotNull(name22);
-    JUnitTestCase.assertNotNull(name22.label);
-    JUnitTestCase.assertNotNull(name22.colon);
+    Label name23 = expression.name;
+    JUnitTestCase.assertNotNull(name23);
+    JUnitTestCase.assertNotNull(name23.label);
+    JUnitTestCase.assertNotNull(name23.colon);
     JUnitTestCase.assertNotNull(expression.expression);
   }
   void test_parseArgument_unnamed() {
@@ -1356,6 +1356,28 @@
     JUnitTestCase.assertNull(statement.label);
     JUnitTestCase.assertNotNull(statement.semicolon);
   }
+  void test_parseDeclaredIdentifier_const() {
+    DeclaredIdentifier declaredIdentifier = ParserTestCase.parse("parseDeclaredIdentifier", <Object> [emptyCommentAndMetadata()], "const A a");
+    JUnitTestCase.assertNotNull(declaredIdentifier.keyword);
+    JUnitTestCase.assertTrue(declaredIdentifier.isConst());
+    JUnitTestCase.assertNotNull(declaredIdentifier.type);
+  }
+  void test_parseDeclaredIdentifier_final() {
+    DeclaredIdentifier declaredIdentifier = ParserTestCase.parse("parseDeclaredIdentifier", <Object> [emptyCommentAndMetadata()], "final A a");
+    JUnitTestCase.assertNotNull(declaredIdentifier.keyword);
+    JUnitTestCase.assertTrue(declaredIdentifier.isFinal());
+    JUnitTestCase.assertNotNull(declaredIdentifier.type);
+  }
+  void test_parseDeclaredIdentifier_type() {
+    DeclaredIdentifier declaredIdentifier = ParserTestCase.parse("parseDeclaredIdentifier", <Object> [emptyCommentAndMetadata()], "A a");
+    JUnitTestCase.assertNull(declaredIdentifier.keyword);
+    JUnitTestCase.assertNotNull(declaredIdentifier.type);
+  }
+  void test_parseDeclaredIdentifier_var() {
+    DeclaredIdentifier declaredIdentifier = ParserTestCase.parse("parseDeclaredIdentifier", <Object> [emptyCommentAndMetadata()], "var a");
+    JUnitTestCase.assertNotNull(declaredIdentifier.keyword);
+    JUnitTestCase.assertNull(declaredIdentifier.type);
+  }
   void test_parseDirective_export() {
     ExportDirective directive = ParserTestCase.parse("parseDirective", <Object> [emptyCommentAndMetadata()], "export 'lib/lib.dart';");
     JUnitTestCase.assertNotNull(directive.keyword);
@@ -1779,11 +1801,12 @@
     JUnitTestCase.assertNotNull(statement.rightParenthesis);
     JUnitTestCase.assertNotNull(statement.body);
   }
-  void test_parseForStatement_each_noType() {
-    ForEachStatement statement = ParserTestCase.parse6("parseForStatement", "for (element in list) {}", []);
+  void test_parseForStatement_each_noType_metadata() {
+    ForEachStatement statement = ParserTestCase.parse6("parseForStatement", "for (@A var element in list) {}", []);
     JUnitTestCase.assertNotNull(statement.forKeyword);
     JUnitTestCase.assertNotNull(statement.leftParenthesis);
     JUnitTestCase.assertNotNull(statement.loopVariable);
+    EngineTestCase.assertSize(1, statement.loopVariable.metadata);
     JUnitTestCase.assertNotNull(statement.inKeyword);
     JUnitTestCase.assertNotNull(statement.iterator);
     JUnitTestCase.assertNotNull(statement.rightParenthesis);
@@ -4393,6 +4416,22 @@
         final __test = new SimpleParserTest();
         runJUnitTest(__test, __test.test_parseContinueStatement_noLabel);
       });
+      _ut.test('test_parseDeclaredIdentifier_const', () {
+        final __test = new SimpleParserTest();
+        runJUnitTest(__test, __test.test_parseDeclaredIdentifier_const);
+      });
+      _ut.test('test_parseDeclaredIdentifier_final', () {
+        final __test = new SimpleParserTest();
+        runJUnitTest(__test, __test.test_parseDeclaredIdentifier_final);
+      });
+      _ut.test('test_parseDeclaredIdentifier_type', () {
+        final __test = new SimpleParserTest();
+        runJUnitTest(__test, __test.test_parseDeclaredIdentifier_type);
+      });
+      _ut.test('test_parseDeclaredIdentifier_var', () {
+        final __test = new SimpleParserTest();
+        runJUnitTest(__test, __test.test_parseDeclaredIdentifier_var);
+      });
       _ut.test('test_parseDirective_export', () {
         final __test = new SimpleParserTest();
         runJUnitTest(__test, __test.test_parseDirective_export);
@@ -4541,9 +4580,9 @@
         final __test = new SimpleParserTest();
         runJUnitTest(__test, __test.test_parseForStatement_each_identifier);
       });
-      _ut.test('test_parseForStatement_each_noType', () {
+      _ut.test('test_parseForStatement_each_noType_metadata', () {
         final __test = new SimpleParserTest();
-        runJUnitTest(__test, __test.test_parseForStatement_each_noType);
+        runJUnitTest(__test, __test.test_parseForStatement_each_noType_metadata);
       });
       _ut.test('test_parseForStatement_each_type', () {
         final __test = new SimpleParserTest();
@@ -8229,6 +8268,7 @@
   'parseConstructorFieldInitializer_0': new MethodTrampoline(0, (Parser target) => target.parseConstructorFieldInitializer()),
   'parseConstructorName_0': new MethodTrampoline(0, (Parser target) => target.parseConstructorName()),
   'parseContinueStatement_0': new MethodTrampoline(0, (Parser target) => target.parseContinueStatement()),
+  'parseDeclaredIdentifier_1': new MethodTrampoline(1, (Parser target, arg0) => target.parseDeclaredIdentifier(arg0)),
   'parseDirective_1': new MethodTrampoline(1, (Parser target, arg0) => target.parseDirective(arg0)),
   'parseDocumentationComment_0': new MethodTrampoline(0, (Parser target) => target.parseDocumentationComment()),
   'parseDoStatement_0': new MethodTrampoline(0, (Parser target) => target.parseDoStatement()),
diff --git a/pkg/analyzer_experimental/test/generated/resolver_test.dart b/pkg/analyzer_experimental/test/generated/resolver_test.dart
index e1343b4..963a3e9 100644
--- a/pkg/analyzer_experimental/test/generated/resolver_test.dart
+++ b/pkg/analyzer_experimental/test/generated/resolver_test.dart
@@ -577,13 +577,13 @@
     _listener.assertNoErrors();
   }
   void test_visitSimpleFormalParameter_type() {
-    InterfaceType intType8 = _typeProvider.intType;
-    ClassElement intElement = intType8.element;
+    InterfaceType intType9 = _typeProvider.intType;
+    ClassElement intElement = intType9.element;
     FormalParameter node = ASTFactory.simpleFormalParameter4(ASTFactory.typeName(intElement, []), "p");
     SimpleIdentifier identifier18 = node.identifier;
     ParameterElementImpl element = new ParameterElementImpl(identifier18);
     identifier18.element = element;
-    JUnitTestCase.assertSame(intType8, resolve5(node, [intElement]));
+    JUnitTestCase.assertSame(intType9, resolve5(node, [intElement]));
     _listener.assertNoErrors();
   }
   void test_visitTypeName_noParameters_noArguments() {
@@ -921,12 +921,6 @@
     assertErrors([CompileTimeErrorCode.COMPILE_TIME_CONSTANT_RAISES_EXCEPTION]);
     verify([source]);
   }
-  void fail_constEvalThrowsException() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class C {", "  const C() { throw null; }", "}", "f() { return const C(); }"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
-    verify([source]);
-  }
   void fail_constWithNonConstantArgument() {
     Source source = addSource("/test.dart", EngineTestCase.createSource(["class T {", "  T(a) {};", "}", "f(p) { return const T(p); }"]));
     resolve(source, []);
@@ -951,12 +945,6 @@
     assertErrors([CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]);
     verify([source]);
   }
-  void fail_defaultValueInFunctionTypeAlias() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["typedef F([x = 0]);"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
-    verify([source]);
-  }
   void fail_duplicateDefinition() {
     Source source = addSource("/test.dart", EngineTestCase.createSource(["f() {", "  int m = 0;", "  m(a) {}", "}"]));
     resolve(source, []);
@@ -988,76 +976,16 @@
     assertErrors([CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY]);
     verify([source]);
   }
-  void fail_extendsOrImplementsDisallowedClass_extends_bool() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends bool {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_extends_double() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends double {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_extends_int() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends int {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
   void fail_extendsOrImplementsDisallowedClass_extends_null() {
     Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends Null {}"]));
     resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_extends_num() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends num {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_extends_String() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends String {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_implements_bool() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements bool {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_implements_double() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements double {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_implements_int() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements int {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
+    assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
     verify([source]);
   }
   void fail_extendsOrImplementsDisallowedClass_implements_null() {
     Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements Null {}"]));
     resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_implements_num() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements num {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
-    verify([source]);
-  }
-  void fail_extendsOrImplementsDisallowedClass_implements_String() {
-    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements String {}"]));
-    resolve(source, []);
-    assertErrors([CompileTimeErrorCode.EXTENDS_OR_IMPLEMENTS_DISALLOWED_CLASS]);
+    assertErrors([CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
     verify([source]);
   }
   void fail_fieldInitializedByMultipleInitializers() {
@@ -1652,6 +1580,12 @@
     assertErrors([CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD]);
     verify([source]);
   }
+  void test_constEvalThrowsException() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class C {", "  const C() { throw null; }", "}", "f() { return const C(); }"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+    verify([source]);
+  }
   void test_constFormalParameter_fieldFormalParameter() {
     Source source = addSource("/test.dart", EngineTestCase.createSource(["class A {", "  var x;", "  A(const this.x) {}", "}"]));
     resolve(source, []);
@@ -1682,6 +1616,12 @@
     assertErrors([CompileTimeErrorCode.CONST_WITH_NON_CONST]);
     verify([source]);
   }
+  void test_defaultValueInFunctionTypeAlias() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["typedef F([x = 0]);"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
+    verify([source]);
+  }
   void test_duplicateMemberError() {
     Source librarySource = addSource("/lib.dart", EngineTestCase.createSource(["library lib;", "", "part 'a.dart';", "part 'b.dart';"]));
     Source sourceA = addSource("/a.dart", EngineTestCase.createSource(["part of lib;", "", "class A {}"]));
@@ -1696,6 +1636,66 @@
     assertErrors([CompileTimeErrorCode.EXTENDS_NON_CLASS]);
     verify([source]);
   }
+  void test_extendsOrImplementsDisallowedClass_extends_bool() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends bool {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_extends_double() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends double {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_extends_int() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends int {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_extends_num() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends num {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_extends_String() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A extends String {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_implements_bool() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements bool {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_implements_double() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements double {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_implements_int() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements int {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_implements_num() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements num {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
+  void test_extendsOrImplementsDisallowedClass_implements_String() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["class A implements String {}"]));
+    resolve(source, []);
+    assertErrors([CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS]);
+    verify([source]);
+  }
   void test_implementsNonClass() {
     Source source = addSource("/test.dart", EngineTestCase.createSource(["int A;", "class B implements A {}"]));
     resolve(source, []);
@@ -1797,6 +1797,10 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_constConstructorWithNonFinalField);
       });
+      _ut.test('test_constEvalThrowsException', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_constEvalThrowsException);
+      });
       _ut.test('test_constFormalParameter_fieldFormalParameter', () {
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_constFormalParameter_fieldFormalParameter);
@@ -1817,6 +1821,10 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_constWithNonConst);
       });
+      _ut.test('test_defaultValueInFunctionTypeAlias', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_defaultValueInFunctionTypeAlias);
+      });
       _ut.test('test_duplicateMemberError', () {
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_duplicateMemberError);
@@ -1825,6 +1833,46 @@
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_extendsNonClass);
       });
+      _ut.test('test_extendsOrImplementsDisallowedClass_extends_String', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_extends_String);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_extends_bool', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_extends_bool);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_extends_double', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_extends_double);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_extends_int', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_extends_int);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_extends_num', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_extends_num);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_implements_String', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_implements_String);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_implements_bool', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_implements_bool);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_implements_double', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_implements_double);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_implements_int', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_implements_int);
+      });
+      _ut.test('test_extendsOrImplementsDisallowedClass_implements_num', () {
+        final __test = new CompileTimeErrorCodeTest();
+        runJUnitTest(__test, __test.test_extendsOrImplementsDisallowedClass_implements_num);
+      });
       _ut.test('test_implementsNonClass', () {
         final __test = new CompileTimeErrorCodeTest();
         runJUnitTest(__test, __test.test_implementsNonClass);
@@ -3314,10 +3362,10 @@
    * structures that are expected to have been resolved have an element associated with them.
    */
   ResolutionVerifier() {
-    _jtd_constructor_317_impl();
+    _jtd_constructor_319_impl();
   }
-  _jtd_constructor_317_impl() {
-    _jtd_constructor_318_impl(null);
+  _jtd_constructor_319_impl() {
+    _jtd_constructor_320_impl(null);
   }
   /**
    * Initialize a newly created verifier to verify that all of the identifiers in the visited AST
@@ -3328,9 +3376,9 @@
    * therefore not cause the test to fail
    */
   ResolutionVerifier.con1(Set<ASTNode> knownExceptions2) {
-    _jtd_constructor_318_impl(knownExceptions2);
+    _jtd_constructor_320_impl(knownExceptions2);
   }
-  _jtd_constructor_318_impl(Set<ASTNode> knownExceptions2) {
+  _jtd_constructor_320_impl(Set<ASTNode> knownExceptions2) {
     this._knownExceptions = knownExceptions2;
   }
   /**
@@ -3526,17 +3574,6 @@
     JUnitTestCase.fail("Not yet tested");
     _listener.assertNoErrors();
   }
-  void fail_visitIndexExpression_typeParameters() {
-    InterfaceType intType6 = _typeProvider.intType;
-    InterfaceType listType2 = _typeProvider.listType;
-    MethodElement methodElement = getMethod(listType2, "[]");
-    SimpleIdentifier identifier = ASTFactory.identifier2("list");
-    identifier.staticType = listType2.substitute5(<Type2> [intType6]);
-    IndexExpression indexExpression2 = ASTFactory.indexExpression(identifier, ASTFactory.integer(0));
-    indexExpression2.element = methodElement;
-    JUnitTestCase.assertSame(intType6, analyze(indexExpression2));
-    _listener.assertNoErrors();
-  }
   void fail_visitMethodInvocation() {
     JUnitTestCase.fail("Not yet tested");
     _listener.assertNoErrors();
@@ -3577,9 +3614,9 @@
     _listener.assertNoErrors();
   }
   void test_visitAssignmentExpression_simple() {
-    InterfaceType intType7 = _typeProvider.intType;
-    Expression node = ASTFactory.assignmentExpression(resolvedVariable(intType7, "i"), TokenType.EQ, resolvedInteger(0));
-    JUnitTestCase.assertSame(intType7, analyze(node));
+    InterfaceType intType6 = _typeProvider.intType;
+    Expression node = ASTFactory.assignmentExpression(resolvedVariable(intType6, "i"), TokenType.EQ, resolvedInteger(0));
+    JUnitTestCase.assertSame(intType6, analyze(node));
     _listener.assertNoErrors();
   }
   void test_visitBinaryExpression_equals() {
@@ -3767,20 +3804,43 @@
     _listener.assertNoErrors();
   }
   void test_visitIndexExpression_getter() {
-    InterfaceType listType3 = _typeProvider.listType;
-    SimpleIdentifier identifier = resolvedVariable(listType3, "a");
+    InterfaceType listType2 = _typeProvider.listType;
+    SimpleIdentifier identifier = resolvedVariable(listType2, "a");
     IndexExpression node = ASTFactory.indexExpression(identifier, resolvedInteger(2));
-    node.element = listType3.element.methods[0];
-    JUnitTestCase.assertSame(listType3.typeArguments[0], analyze(node));
+    node.element = listType2.element.methods[0];
+    JUnitTestCase.assertSame(listType2.typeArguments[0], analyze(node));
     _listener.assertNoErrors();
   }
   void test_visitIndexExpression_setter() {
-    InterfaceType listType4 = _typeProvider.listType;
-    SimpleIdentifier identifier = resolvedVariable(listType4, "a");
+    InterfaceType listType3 = _typeProvider.listType;
+    SimpleIdentifier identifier = resolvedVariable(listType3, "a");
     IndexExpression node = ASTFactory.indexExpression(identifier, resolvedInteger(2));
-    node.element = listType4.element.methods[1];
+    node.element = listType3.element.methods[1];
     ASTFactory.assignmentExpression(node, TokenType.EQ, ASTFactory.integer(0));
-    JUnitTestCase.assertSame(listType4.typeArguments[0], analyze(node));
+    JUnitTestCase.assertSame(listType3.typeArguments[0], analyze(node));
+    _listener.assertNoErrors();
+  }
+  void test_visitIndexExpression_typeParameters() {
+    InterfaceType intType7 = _typeProvider.intType;
+    InterfaceType listType4 = _typeProvider.listType;
+    MethodElement methodElement = getMethod(listType4, "[]");
+    SimpleIdentifier identifier = ASTFactory.identifier2("list");
+    identifier.staticType = listType4.substitute5(<Type2> [intType7]);
+    IndexExpression indexExpression2 = ASTFactory.indexExpression(identifier, ASTFactory.integer(0));
+    indexExpression2.element = methodElement;
+    JUnitTestCase.assertSame(intType7, analyze(indexExpression2));
+    _listener.assertNoErrors();
+  }
+  void test_visitIndexExpression_typeParameters_inSetterContext() {
+    InterfaceType intType8 = _typeProvider.intType;
+    InterfaceType listType5 = _typeProvider.listType;
+    MethodElement methodElement = getMethod(listType5, "[]=");
+    SimpleIdentifier identifier = ASTFactory.identifier2("list");
+    identifier.staticType = listType5.substitute5(<Type2> [intType8]);
+    IndexExpression indexExpression3 = ASTFactory.indexExpression(identifier, ASTFactory.integer(0));
+    indexExpression3.element = methodElement;
+    ASTFactory.assignmentExpression(indexExpression3, TokenType.EQ, ASTFactory.integer(0));
+    JUnitTestCase.assertSame(intType8, analyze(indexExpression3));
     _listener.assertNoErrors();
   }
   void test_visitInstanceCreationExpression_named() {
@@ -4126,14 +4186,14 @@
    * @param body the body of the function
    * @return a resolved function expression
    */
-  FunctionExpression resolvedFunctionExpression(FormalParameterList parameters15, FunctionBody body) {
-    for (FormalParameter parameter in parameters15.parameters) {
+  FunctionExpression resolvedFunctionExpression(FormalParameterList parameters16, FunctionBody body) {
+    for (FormalParameter parameter in parameters16.parameters) {
       ParameterElementImpl element = new ParameterElementImpl(parameter.identifier);
       element.parameterKind = parameter.kind;
       element.type = _typeProvider.dynamicType;
       parameter.identifier.element = element;
     }
-    FunctionExpression node = ASTFactory.functionExpression2(parameters15, body);
+    FunctionExpression node = ASTFactory.functionExpression2(parameters16, body);
     FunctionElementImpl element = new FunctionElementImpl.con1(null);
     element.type = new FunctionTypeImpl.con1(element);
     node.element = element;
@@ -4301,6 +4361,14 @@
         final __test = new StaticTypeAnalyzerTest();
         runJUnitTest(__test, __test.test_visitIndexExpression_setter);
       });
+      _ut.test('test_visitIndexExpression_typeParameters', () {
+        final __test = new StaticTypeAnalyzerTest();
+        runJUnitTest(__test, __test.test_visitIndexExpression_typeParameters);
+      });
+      _ut.test('test_visitIndexExpression_typeParameters_inSetterContext', () {
+        final __test = new StaticTypeAnalyzerTest();
+        runJUnitTest(__test, __test.test_visitIndexExpression_typeParameters_inSetterContext);
+      });
       _ut.test('test_visitInstanceCreationExpression_named', () {
         final __test = new StaticTypeAnalyzerTest();
         runJUnitTest(__test, __test.test_visitInstanceCreationExpression_named);
@@ -4802,6 +4870,12 @@
     assertNoErrors();
     verify([source]);
   }
+  void test_defaultValueInFunctionTypeAlias() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["typedef F([x]);"]));
+    resolve(source, []);
+    assertErrors([]);
+    verify([source]);
+  }
   void test_duplicateDefinition_getter() {
     Source source = addSource("/test.dart", EngineTestCase.createSource(["bool get a => true;"]));
     resolve(source, []);
@@ -4838,6 +4912,18 @@
     assertNoErrors();
     verify([source]);
   }
+  void test_indexExpression_typeParameters() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["f() {", "  List<int> a;", "  a[0];", "  List<List<int>> b;", "  b[0][0];", "  List<List<List<int>>> c;", "  c[0][0][0];", "}"]));
+    resolve(source, []);
+    assertNoErrors();
+    verify([source]);
+  }
+  void test_indexExpression_typeParameters_invalidAssignmentWarning() {
+    Source source = addSource("/test.dart", EngineTestCase.createSource(["f() {", "  List<List<int>> b;", "  b[0][0] = 'hi';", "}"]));
+    resolve(source, []);
+    assertErrors([StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+    verify([source]);
+  }
   void test_invalidAssignment() {
     Source source = addSource("/test.dart", EngineTestCase.createSource(["f() {", "  var x;", "  var y;", "  x = y;", "}"]));
     resolve(source, []);
@@ -5038,6 +5124,10 @@
         final __test = new SimpleResolverTest();
         runJUnitTest(__test, __test.test_constConstructorWithNonFinalField_syntheticField);
       });
+      _ut.test('test_defaultValueInFunctionTypeAlias', () {
+        final __test = new SimpleResolverTest();
+        runJUnitTest(__test, __test.test_defaultValueInFunctionTypeAlias);
+      });
       _ut.test('test_duplicateDefinition_getter', () {
         final __test = new SimpleResolverTest();
         runJUnitTest(__test, __test.test_duplicateDefinition_getter);
@@ -5062,6 +5152,14 @@
         final __test = new SimpleResolverTest();
         runJUnitTest(__test, __test.test_getterAndSetterWithDifferentTypes);
       });
+      _ut.test('test_indexExpression_typeParameters', () {
+        final __test = new SimpleResolverTest();
+        runJUnitTest(__test, __test.test_indexExpression_typeParameters);
+      });
+      _ut.test('test_indexExpression_typeParameters_invalidAssignmentWarning', () {
+        final __test = new SimpleResolverTest();
+        runJUnitTest(__test, __test.test_indexExpression_typeParameters_invalidAssignmentWarning);
+      });
       _ut.test('test_invalidAssignment', () {
         final __test = new SimpleResolverTest();
         runJUnitTest(__test, __test.test_invalidAssignment);
diff --git a/pkg/analyzer_experimental/test/generated/test_support.dart b/pkg/analyzer_experimental/test/generated/test_support.dart
index 7312a7c..4ca21f2 100644
--- a/pkg/analyzer_experimental/test/generated/test_support.dart
+++ b/pkg/analyzer_experimental/test/generated/test_support.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer_experimental/src/generated/error.dart';
 import 'package:analyzer_experimental/src/generated/scanner.dart';
 import 'package:analyzer_experimental/src/generated/element.dart' show InterfaceType, MethodElement, PropertyAccessorElement;
+import 'package:analyzer_experimental/src/generated/engine.dart' show AnalysisContext;
 import 'package:unittest/unittest.dart' as _ut;
 
 /**
@@ -44,17 +45,17 @@
    * Initialize a newly created error listener to collect errors.
    */
   GatheringErrorListener() : super() {
-    _jtd_constructor_315_impl();
+    _jtd_constructor_317_impl();
   }
-  _jtd_constructor_315_impl() {
+  _jtd_constructor_317_impl() {
   }
   /**
    * Initialize a newly created error listener to collect errors.
    */
   GatheringErrorListener.con1(String rawSource2) {
-    _jtd_constructor_316_impl(rawSource2);
+    _jtd_constructor_318_impl(rawSource2);
   }
-  _jtd_constructor_316_impl(String rawSource2) {
+  _jtd_constructor_318_impl(String rawSource2) {
     this._rawSource = rawSource2;
     this._markedSource = rawSource2;
   }
@@ -274,15 +275,15 @@
     writer.print(expectedErrors.length);
     writer.print(" errors:");
     for (AnalysisError error in expectedErrors) {
-      Source source11 = error.source;
-      LineInfo lineInfo = _lineInfoMap[source11];
+      Source source13 = error.source;
+      LineInfo lineInfo = _lineInfoMap[source13];
       writer.println();
       if (lineInfo == null) {
         int offset10 = error.offset;
-        writer.printf("  %s %s (%d..%d)", [source11 == null ? "" : source11.shortName, error.errorCode, offset10, offset10 + error.length]);
+        writer.printf("  %s %s (%d..%d)", [source13 == null ? "" : source13.shortName, error.errorCode, offset10, offset10 + error.length]);
       } else {
         LineInfo_Location location = lineInfo.getLocation(error.offset);
-        writer.printf("  %s %s (%d, %d/%d)", [source11 == null ? "" : source11.shortName, error.errorCode, location.lineNumber, location.columnNumber, error.length]);
+        writer.printf("  %s %s (%d, %d/%d)", [source13 == null ? "" : source13.shortName, error.errorCode, location.lineNumber, location.columnNumber, error.length]);
       }
     }
     writer.println();
@@ -290,15 +291,15 @@
     writer.print(_errors.length);
     writer.print(" errors:");
     for (AnalysisError error in _errors) {
-      Source source12 = error.source;
-      LineInfo lineInfo = _lineInfoMap[source12];
+      Source source14 = error.source;
+      LineInfo lineInfo = _lineInfoMap[source14];
       writer.println();
       if (lineInfo == null) {
         int offset11 = error.offset;
-        writer.printf("  %s %s (%d..%d): %s", [source12 == null ? "" : source12.shortName, error.errorCode, offset11, offset11 + error.length, error.message]);
+        writer.printf("  %s %s (%d..%d): %s", [source14 == null ? "" : source14.shortName, error.errorCode, offset11, offset11 + error.length, error.message]);
       } else {
         LineInfo_Location location = lineInfo.getLocation(error.offset);
-        writer.printf("  %s %s (%d, %d/%d): %s", [source12 == null ? "" : source12.shortName, error.errorCode, location.lineNumber, location.columnNumber, error.length, error.message]);
+        writer.printf("  %s %s (%d, %d/%d): %s", [source14 == null ? "" : source14.shortName, error.errorCode, location.lineNumber, location.columnNumber, error.length, error.message]);
       }
     }
     JUnitTestCase.fail(writer.toString());
@@ -608,6 +609,9 @@
   bool operator ==(Object object) {
     return this == object;
   }
+  AnalysisContext get context {
+    throw new UnsupportedOperationException();
+  }
   void getContents(Source_ContentReceiver receiver) {
     throw new UnsupportedOperationException();
   }
diff --git a/pkg/args/pubspec.yaml b/pkg/args/pubspec.yaml
index 959c189..14802e7 100644
--- a/pkg/args/pubspec.yaml
+++ b/pkg/args/pubspec.yaml
@@ -6,7 +6,5 @@
  Libraries for defining parsers for parsing raw command-line arguments into
  a set of options and values using GNU and POSIX style options.
 
-
-dependencies:
-  unittest:
-    sdk: unittest
+dev_dependencies:
+  unittest: any
diff --git a/pkg/http/pubspec.yaml b/pkg/http/pubspec.yaml
index d41e64ad..66cd21a 100644
--- a/pkg/http/pubspec.yaml
+++ b/pkg/http/pubspec.yaml
@@ -2,6 +2,5 @@
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: A composable, Future-based API for making HTTP requests.
-dependencies:
-  unittest:
-    sdk: unittest
+dev_dependencies:
+  unittest: any
diff --git a/pkg/intl/lib/date_format.dart b/pkg/intl/lib/date_format.dart
index a0d964f..88b54d66 100644
--- a/pkg/intl/lib/date_format.dart
+++ b/pkg/intl/lib/date_format.dart
@@ -558,7 +558,7 @@
   /** Parse the template pattern and return a list of field objects.*/
   List parsePattern(String pattern) {
     if (pattern == null) return null;
-    return _reverse(_parsePatternHelper(pattern));
+    return _parsePatternHelper(pattern).reversed.toList();
   }
 
   /** Recursive helper for parsing the template pattern. */
@@ -584,15 +584,4 @@
       }
     }
   }
-
-  /** Polyfill for missing library function. */
-  List _reverse(List list) {
-    // TODO(alanknight): Use standardized list reverse when implemented.
-    // See Issue 2804.
-    var result = new List();
-    for (var i = list.length-1; i >= 0; i--) {
-      result.addLast(list[i]);
-    }
-    return result;
-  }
 }
diff --git a/pkg/intl/lib/generate_localized.dart b/pkg/intl/lib/generate_localized.dart
index 84ba5c9..0961d38 100644
--- a/pkg/intl/lib/generate_localized.dart
+++ b/pkg/intl/lib/generate_localized.dart
@@ -19,6 +19,28 @@
 import 'package:pathos/path.dart' as path;
 
 /**
+ * If the import path following package: is something else, modify the
+ * [intlImportPath] variable to change the import directives in the generated
+ * code.
+ */
+var intlImportPath = 'intl';
+
+/**
+ * If the path to the generated files is something other than the current
+ * directory, update the [generatedImportPath] variable to change the import
+ * directives in the generated code.
+ */
+var generatedImportPath = '';
+
+/**
+ * Given a base file, return the file prefixed with the path to import it.
+ * By default, that is in the current directory, but if [generatedImportPath]
+ * has been set, then use that as a prefix.
+ */
+String importForGeneratedFile(String file) =>
+    generatedImportPath.isEmpty ? file : "$generatedImportPath/$file";
+
+/**
  * A list of all the locales for which we have translations. Code that does
  * the reading of translations should add to this.
  */
@@ -96,8 +118,8 @@
  */
 
 library messages_${locale.replaceAll('-','_')};
-import 'package:intl/intl.dart';
-import 'package:intl/message_lookup_by_library.dart';
+import 'package:$intlImportPath/intl.dart';
+import 'package:$intlImportPath/message_lookup_by_library.dart';
 
 final messages = new MessageLookup();
 
@@ -114,7 +136,9 @@
   var output = new StringBuffer();
   output.write(mainPrologue);
   for (var each in allLocales) {
-    output.write("import 'messages_$each.dart' as ${asLibraryName(each)};\n");
+    var baseFile = 'messages_$each.dart';
+    var file = importForGeneratedFile(baseFile);
+    output.write("import '$file' as ${asLibraryName(each)};\n");
   }
   output.write(
     "\nMessageLookupByLibrary _findExact(localeName) {\n"
@@ -131,7 +155,7 @@
  * Constant string used in [generateMainImportFile] for the beginning of the
  * file.
  */
-const mainPrologue = """
+var mainPrologue = """
 /**
  * DO NOT EDIT. This is code generated via pkg/intl/generate_localized.dart
  * This is a library that looks up messages for specific locales by
@@ -141,9 +165,9 @@
 library messages_all;
 
 import 'dart:async';
-import 'package:intl/message_lookup_by_library.dart';
-import 'package:intl/src/intl_helpers.dart';
-import 'package:intl/intl.dart';
+import 'package:$intlImportPath/message_lookup_by_library.dart';
+import 'package:$intlImportPath/src/intl_helpers.dart';
+import 'package:$intlImportPath/intl.dart';
 
 """;
 
diff --git a/pkg/intl/pubspec.yaml b/pkg/intl/pubspec.yaml
index a568a3a..616a4b4 100644
--- a/pkg/intl/pubspec.yaml
+++ b/pkg/intl/pubspec.yaml
@@ -4,6 +4,7 @@
 homepage: http://www.dartlang.org
 documentation: http://api.dartlang.org/docs/pkg/intl
 dependencies:
-  unittest: any
   analyzer_experimental: any
   pathos: any
+dev_dependencies:
+  unittest: any
diff --git a/pkg/intl/test/data_directory.dart b/pkg/intl/test/data_directory.dart
index 9cf6253..de16e00 100644
--- a/pkg/intl/test/data_directory.dart
+++ b/pkg/intl/test/data_directory.dart
@@ -13,6 +13,7 @@
  */
 library data_directory;
 
+import "dart:io";
 import "package:pathos/path.dart" as path;
 
 String get dataDirectory {
@@ -40,8 +41,16 @@
   if (foundIntlDir) {
     return path.joinAll(pathUpToIntl);
   } else {
-    return path.join(path.current, 'pkg', 'intl');
+    if (new Directory(path.join(path.current, 'pkg', 'intl')).existsSync()) {
+      return path.join(path.current, 'pkg', 'intl');
+    }
+    if (new Directory(
+        path.join(path.current, '..', 'pkg', 'intl')).existsSync()) {
+      return path.join(path.current, '..', 'pkg', 'intl');
+    }
   }
+  throw new UnsupportedError(
+      'Cannot find ${path.join('pkg','intl')} directory.');
 }
 
 String get datesRelativeToIntl => path.join('lib', 'src', 'data', 'dates');
\ No newline at end of file
diff --git a/pkg/intl/test/message_extraction/message_extraction_test.dart b/pkg/intl/test/message_extraction/message_extraction_test.dart
index 0b00fdb..92aa3e6 100644
--- a/pkg/intl/test/message_extraction/message_extraction_test.dart
+++ b/pkg/intl/test/message_extraction/message_extraction_test.dart
@@ -55,20 +55,21 @@
   test("Test round trip message extraction, translation, code generation, "
       "and printing", () {
     deleteGeneratedFiles();
-    extractMessages(null).then((result) {
+    return extractMessages(null).then((result) {
       return generateTranslationFiles(result);
     }).then((result) {
       return generateCodeFromTranslation(result);
     }).then((result) {
       return runGeneratedCode(result);
-    }).then(verifyResult);
+    }).then(verifyResult)
+    .whenComplete(deleteGeneratedFiles);
   });
 }
 
 void deleteGeneratedFiles() {
   var files = [dir('intl_messages.json'), dir('translation_fr.json'),
-      dir('messages_fr.dart'), dir('message_de_DE.dart'),
-      dir('messages_all.dart')];
+      dir('messages_fr.dart'), dir('messages_de_DE.dart'),
+      dir('translation_de_DE.json'), dir('messages_all.dart')];
   files.map((name) => new File(name)).forEach((x) {
     if (x.existsSync()) x.deleteSync();});
 }
@@ -124,7 +125,7 @@
 Future<ProcessResult> runGeneratedCode(ProcessResult previousResult) =>
     run(previousResult, ['sample_with_messages.dart']);
 
-void verifyResult(results) {
+verifyResult(results) {
   var lineIterator;
   verify(String s) {
     lineIterator.moveNext();
diff --git a/pkg/intl/tool/generate_locale_data_files.dart b/pkg/intl/tool/generate_locale_data_files.dart
index a6fe140..76ff2bd 100644
--- a/pkg/intl/tool/generate_locale_data_files.dart
+++ b/pkg/intl/tool/generate_locale_data_files.dart
@@ -19,6 +19,7 @@
 import 'dart:io';
 import 'dart:json' as json;
 import '../test/data_directory.dart';
+import 'package:pathos/path.dart' as path;
 
 main() {
   initializeDateFormatting("en_IGNORED", null);
@@ -28,22 +29,23 @@
 }
 
 void writeLocaleList() {
-  var file = new File('${dataDirectory}localeList.dart');
+  var file = new File(path.join(dataDirectory, 'localeList.dart'));
   var output = file.openWrite();
-  output.addString(
+  output.write(
       '// Copyright (c) 2012, the Dart project authors.  Please see the '
       'AUTHORS file\n// for details. All rights reserved. Use of this source'
       'code is governed by a\n// BSD-style license that can be found in the'
       ' LICENSE file.\n\n'
+      'part of date_symbol_data_json;\n\n'
       '/// Hard-coded list of all available locales for dates.\n');
-  output.addString('final availableLocalesForDateFormatting = const [');
+  output.write('final availableLocalesForDateFormatting = const [');
   List<String> allLocales = DateFormat.allLocalesWithSymbols();
   allLocales.forEach((locale) {
-    output.addString('"$locale"');
+    output.write('"$locale"');
     if (locale == allLocales.last) {
-      output.addString('];');
+      output.write('];');
     } else {
-      output.addString(',\n    ');
+      output.write(',\n    ');
     }
   });
   output.close();
@@ -60,19 +62,19 @@
 }
 
 void writeSymbols(locale, symbols) {
-  var file = new File('${dataDirectory}symbols/${locale}.json');
+  var file = new File(path.join(dataDirectory, 'symbols', '${locale}.json'));
   var output = file.openWrite();
   writeToJSON(symbols, output);
   output.close();
 }
 
 void writePatterns(locale, patterns) {
-  var file = new File('${dataDirectory}patterns/${locale}.json');
+  var file = new File(path.join(dataDirectory, 'patterns', '${locale}.json'));
   var output = file.openWrite();
-  output.addString(json.stringify(patterns));
+  output.write(json.stringify(patterns));
   output.close();
 }
 
 void writeToJSON(dynamic data, IOSink out) {
-  out.addString(json.stringify(data.serializeToMap()));
+  out.write(json.stringify(data.serializeToMap()));
 }
diff --git a/pkg/logging/pubspec.yaml b/pkg/logging/pubspec.yaml
index 6e6a540..16c4428 100644
--- a/pkg/logging/pubspec.yaml
+++ b/pkg/logging/pubspec.yaml
@@ -8,7 +8,6 @@
  Logger and java.util.logging.Logger.
 
 dependencies:
-  meta:
-    sdk: meta
-  unittest:
-    sdk: unittest
+  meta: any
+dev_dependencies:
+  unittest: any
diff --git a/pkg/oauth2/lib/oauth2.dart b/pkg/oauth2/lib/oauth2.dart
index 4dfaadd..7fdb205 100644
--- a/pkg/oauth2/lib/oauth2.dart
+++ b/pkg/oauth2/lib/oauth2.dart
@@ -56,7 +56,7 @@
 ///       // If the OAuth2 credentials have already been saved from a previous
 ///       // run, we just want to reload them.
 ///       if (exists) {
-///         return credentialsFile.readAsText().then((json) {
+///         return credentialsFile.readAsString().then((json) {
 ///           var credentials = new oauth2.Credentials.fromJson(json);
 ///           return new oauth2.Client(identifier, secret, credentials);
 ///         });
diff --git a/pkg/oauth2/pubspec.yaml b/pkg/oauth2/pubspec.yaml
index ae3d11d..f531f46 100644
--- a/pkg/oauth2/pubspec.yaml
+++ b/pkg/oauth2/pubspec.yaml
@@ -6,7 +6,6 @@
   behalf of a user, and making authorized HTTP requests with the user's
   OAuth2 credentials.
 dependencies:
-  unittest:
-    sdk: unittest
-  http:
-    sdk: http
+  http: any
+dev_dependencies:
+  unittest: any
diff --git a/pkg/pkg.status b/pkg/pkg.status
index e919f3d..b90eaa1 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -12,11 +12,19 @@
 # Skip non-test files ending with "_test".
 scheduled_test/lib/*: Skip
 
+scheduled_test/test/scheduled_test_test: Pass, Slow # Issue 9231
+
 # WebDriver tests have 3rd party dependencies (we need to run
 # selenium_standalone.jar), so we skip these in our automated
 # testing.
 webdriver/test/webdriver_test: Skip
 
+[$compiler == none && $runtime == vm]
+intl/test/date_time_format_file_even_test: Pass, Crash # Issue 9342
+intl/test/date_time_format_file_odd_test: Pass, Crash # Issue 9342
+intl/test/date_time_format_local_even_test: Pass, Crash # Issue 9342
+intl/test/date_time_format_local_odd_test: Pass, Crash # Issue 9342
+
 [$compiler == dart2dart]
 *: Skip
 
@@ -29,6 +37,9 @@
 # Issue 8440 forces us to use pathos in the scheduled_test tests, which would
 # otherwise be dart2js-compatible.
 scheduled_test/test/*: Skip
+source_maps/test/vlq_test: Fail # A VLQ test checks for large numbers that
+                                # overflow in JS (numbers slightly larger than
+                                # 32 bits where we do bitwise operations).
 
 # Skip tests that use local file access if we're running in any browser
 [ $runtime == opera || $runtime == ff || $runtime == ie9 || $runtime == dartium || $runtime == chrome || $runtime == safari || $runtime == drt  || $runtime == jsshell]
@@ -57,6 +68,9 @@
 [ $runtime == ie9 ]
 intl/test/date_time_format_http_request_test: Fail # Issue 8983
 
+[ $runtime == safari ]
+fixnum/test/int_64_test: Pass, Fail # Bug in JSC.
+
 # Skip browser-specific Intl tests on VM
 [ $runtime == vm ]
 intl/test/find_default_locale_browser_test: Skip
@@ -74,7 +88,8 @@
 [ $compiler == dart2js ]
 # Skip intl_message tests that use mirrors on dart2js until it's been
 # implemented there.
-serialization/test/serialization_test: Skip
+serialization/test/serialization_test: Skip # Issue 6490
+serialization/test/no_library_test: Skip # Issue 6490
 analyzer_experimental/test/generated/ast_test: Skip
 analyzer_experimental/test/generated/element_test: Skip
 analyzer_experimental/test/generated/parser_test: Skip
@@ -112,3 +127,8 @@
 
 [ $arch == simmips ]
 *: Skip
+
+# Skip serialization test that explicitly has no library declaration in the
+# test on Dartium, which requires all tests to have a library.
+[ $runtime == dartium || $runtime == drt ]
+serialization/test/no_library_test: Skip # Expected Failure
diff --git a/pkg/scheduled_test/lib/descriptor.dart b/pkg/scheduled_test/lib/descriptor.dart
index b8baeca..f832b9a 100644
--- a/pkg/scheduled_test/lib/descriptor.dart
+++ b/pkg/scheduled_test/lib/descriptor.dart
@@ -6,9 +6,9 @@
 /// the purpose of creating or validating it as part of a scheduled test.
 ///
 /// You can use [dir] and [file] to define a filesystem structure. Then, you can
-/// call [Entry.create] to schedule a task that will create that structure on
-/// the physical filesystem, or [Entry.validate] to schedule an assertion that
-/// that structure exists. For example:
+/// call [Descriptor.create] to schedule a task that will create that structure
+/// on the physical filesystem, or [Descriptor.validate] to schedule an
+/// assertion that that structure exists. For example:
 ///
 ///     import 'package:scheduled_test/descriptor.dart' as d;
 ///     import 'package:scheduled_test/scheduled_test.dart';
@@ -67,17 +67,19 @@
 import '../../../pkg/pathos/lib/path.dart' as path;
 
 import 'scheduled_test.dart';
-import 'src/descriptor/async.dart';
-import 'src/descriptor/directory.dart';
-import 'src/descriptor/entry.dart';
-import 'src/descriptor/file.dart';
-import 'src/descriptor/nothing.dart';
+import 'src/descriptor/async_descriptor.dart';
+import 'src/descriptor/descriptor.dart';
+import 'src/descriptor/directory_descriptor.dart';
+import 'src/descriptor/file_descriptor.dart';
+import 'src/descriptor/nothing_descriptor.dart';
+import 'src/descriptor/pattern_descriptor.dart';
 
-export 'src/descriptor/async.dart';
-export 'src/descriptor/directory.dart';
-export 'src/descriptor/entry.dart';
-export 'src/descriptor/file.dart';
-export 'src/descriptor/nothing.dart';
+export 'src/descriptor/async_descriptor.dart';
+export 'src/descriptor/descriptor.dart';
+export 'src/descriptor/directory_descriptor.dart';
+export 'src/descriptor/file_descriptor.dart';
+export 'src/descriptor/nothing_descriptor.dart';
+export 'src/descriptor/pattern_descriptor.dart';
 
 /// The root path for descriptors. Top-level descriptors will be created and
 /// validated at this path. Defaults to the current working directory.
@@ -90,21 +92,39 @@
 }
 String _defaultRoot;
 
-/// Creates a new text [File] descriptor with [name] and [contents].
-File file(Pattern name, [String contents='']) => new File(name, contents);
+/// Creates a new text [FileDescriptor] with [name] and [contents].
+FileDescriptor file(String name, [String contents='']) =>
+  new FileDescriptor(name, contents);
 
-/// Creates a new binary [File] descriptor with [name] and [contents].
-File binaryFile(Pattern name, List<int> contents) =>
-    new File.binary(name, contents);
+/// Creates a new binary [FileDescriptor] descriptor with [name] and [contents].
+FileDescriptor binaryFile(String name, List<int> contents) =>
+  new FileDescriptor.binary(name, contents);
 
-/// Creates a new [Directory] descriptor with [name] and [contents].
-Directory dir(Pattern name, [Iterable<Entry> contents]) =>
-    new Directory(name, contents == null ? <Entry>[] : contents);
+/// Creates a new [DirectoryDescriptor] descriptor with [name] and [contents].
+DirectoryDescriptor dir(String name, [Iterable<Descriptor> contents]) =>
+   new DirectoryDescriptor(name, contents == null? <Descriptor>[] : contents);
 
 /// Creates a new descriptor wrapping a [Future]. This descriptor forwards all
 /// asynchronous operations to the result of [future].
-Async async(Future<Entry> future) => new Async(future);
+AsyncDescriptor async(Future<Descriptor> future) =>
+  new AsyncDescriptor(future);
 
-/// Creates a new [Nothing] descriptor that asserts that no entry named [name]
-/// exists.
-Nothing nothing(Pattern name) => new Nothing(name);
+/// Creates a new [NothingDescriptor] descriptor that asserts that no entry
+/// named [name] exists.
+NothingDescriptor nothing(String name) => new NothingDescriptor(name);
+
+/// Creates a new [PatternDescriptor] descriptor that asserts than an entry with
+/// a name matching [pattern] exists, and matches the [Descriptor] returned
+/// by [fn].
+PatternDescriptor pattern(Pattern name, EntryCreator fn) =>
+  new PatternDescriptor(name, fn);
+
+/// A convenience method for creating a [PatternDescriptor] descriptor that
+/// constructs a [FileDescriptor] descriptor.
+PatternDescriptor filePattern(Pattern name, [String contents='']) =>
+  pattern(name, (realName) => file(realName, contents));
+
+/// A convenience method for creating a [PatternDescriptor] descriptor that
+/// constructs a [DirectoryDescriptor] descriptor.
+PatternDescriptor dirPattern(Pattern name, [Iterable<Descriptor> contents]) =>
+  pattern(name, (realName) => dir(realName, contents));
diff --git a/pkg/scheduled_test/lib/scheduled_process.dart b/pkg/scheduled_test/lib/scheduled_process.dart
index 0e277da..57af0b6 100644
--- a/pkg/scheduled_test/lib/scheduled_process.dart
+++ b/pkg/scheduled_test/lib/scheduled_process.dart
@@ -21,10 +21,13 @@
 /// If the test fails, this will automatically print out any stdout and stderr
 /// from the process to aid debugging.
 class ScheduledProcess {
-  // A description of the process. Used for error reporting.
+  /// A description of the process. Used for error reporting.
   String get description => _description;
   String _description;
 
+  /// Whether a description was passed explicitly by the user.
+  bool _explicitDescription;
+
   /// The encoding used for the process's input and output streams.
   final Encoding _encoding;
 
@@ -78,7 +81,9 @@
   /// containing a mix of strings and [Future]s.
   ScheduledProcess.start(executable, arguments,
       {options, String description, Encoding encoding: Encoding.UTF_8})
-      : _encoding = encoding {
+      : _encoding = encoding,
+        _explicitDescription = description != null,
+        _description = description {
     assert(currentSchedule.state == ScheduleState.SET_UP);
 
     _updateDescription(executable, arguments);
@@ -105,6 +110,7 @@
   /// Updates [_description] to reflect [executable] and [arguments], which are
   /// the same values as in [start].
   void _updateDescription(executable, arguments) {
+    if (_explicitDescription) return;
     if (executable is Future) {
       _description = "future process";
     } else if (arguments is Future || arguments.any((e) => e is Future)) {
diff --git a/pkg/scheduled_test/lib/src/descriptor/async.dart b/pkg/scheduled_test/lib/src/descriptor/async.dart
deleted file mode 100644
index c33a68c..0000000
--- a/pkg/scheduled_test/lib/src/descriptor/async.dart
+++ /dev/null
@@ -1,42 +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.
-
-library descriptor.async;
-
-import 'dart:async';
-import 'dart:io' as io;
-
-import '../../descriptor.dart' as descriptor;
-import '../../scheduled_test.dart';
-import '../utils.dart';
-import 'utils.dart';
-
-/// A descriptor that wraps a [Future<Entry>] and forwards all asynchronous
-/// operations to the result of the future. It's designed for use when the
-/// full filesystem description isn't known when initializing the schedule.
-///
-/// Async descriptors don't support [load], since their names aren't
-/// synchronously available.
-class Async extends descriptor.Entry {
-  /// The [Future] that will complete to the [Entry] this descriptor is
-  /// wrapping.
-  final Future<descriptor.Entry> future;
-
-  Async(this.future)
-      : super('<async descriptor>');
-
-  Future create([String parent]) =>
-    schedule(() => future.then((entry) => entry.create(parent)));
-
-  Future validate([String parent]) =>
-    schedule(() => future.then((entry) => entry.validate(parent)));
-
-  Stream<List<int>> load(String path) => errorStream("Async descriptors don't "
-      "support load().");
-
-  Stream<List<int>> read() => errorStream("Async descriptors don't support "
-      "read().");
-
-  String describe() => "async descriptor";
-}
diff --git a/pkg/scheduled_test/lib/src/descriptor/async_descriptor.dart b/pkg/scheduled_test/lib/src/descriptor/async_descriptor.dart
new file mode 100644
index 0000000..79092dc
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/async_descriptor.dart
@@ -0,0 +1,43 @@
+// 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 descriptor.async;
+
+import 'dart:async';
+import 'dart:io' as io;
+
+import '../../descriptor.dart';
+import '../../scheduled_test.dart';
+import '../utils.dart';
+
+/// A descriptor that wraps a [Future<Descriptor>] and forwards all asynchronous
+/// operations to the result of the future. It's designed for use when the full
+/// filesystem description isn't known when initializing the schedule.
+///
+/// [AsyncDescriptor]s don't support [load], since their names aren't
+/// synchronously available.
+class AsyncDescriptor extends Descriptor {
+  /// The [Future] that will complete to the [Descriptor] this descriptor is
+  /// wrapping.
+  final Future<Descriptor> future;
+
+  AsyncDescriptor(this.future)
+      : super('<async descriptor>');
+
+  Future create([String parent]) =>
+    schedule(() => future.then((entry) => entry.create(parent)));
+
+  Future validate([String parent]) => schedule(() => validateNow(parent));
+
+  Future validateNow([String parent]) =>
+    future.then((entry) => entry.validateNow(parent));
+
+  Stream<List<int>> load(String path) => errorStream("AsyncDescriptors don't "
+      "support load().");
+
+  Stream<List<int>> read() => errorStream("AsyncDescriptors don't support "
+      "read().");
+
+  String describe() => "async descriptor";
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/entry.dart b/pkg/scheduled_test/lib/src/descriptor/descriptor.dart
similarity index 67%
rename from pkg/scheduled_test/lib/src/descriptor/entry.dart
rename to pkg/scheduled_test/lib/src/descriptor/descriptor.dart
index 9605a1c..1d3a14a 100644
--- a/pkg/scheduled_test/lib/src/descriptor/entry.dart
+++ b/pkg/scheduled_test/lib/src/descriptor/descriptor.dart
@@ -7,19 +7,15 @@
 import 'dart:async';
 
 import '../utils.dart';
-import 'utils.dart';
 
 /// The base class for various declarative descriptions of filesystem entries.
 /// All asynchronous operations on descriptors are [schedule]d unless otherwise
 /// noted.
-abstract class Entry {
-  /// The name of this entry. For most operations, this must be a [String];
-  /// however, if the entry will only be used for validation, it may be a
-  /// non-[String] [Pattern]. In this case, there must be only one entry
-  /// matching it in the physical filesystem for validation to succeed.
-  final Pattern name;
+abstract class Descriptor {
+  /// The name of this entry.
+  final String name;
 
-  Entry(this.name);
+  Descriptor(this.name);
 
   /// Schedules the creation of the described entry within the [parent]
   /// directory. Returns a [Future] that completes after the creation is done.
@@ -35,6 +31,10 @@
   /// [parent] defaults to [defaultRoot].
   Future validate([String parent]);
 
+  /// An unscheduled version of [validate]. This is useful if validation errors
+  /// need to be caught, since otherwise they'd be registered by the schedule.
+  Future validateNow([String parent]);
+
   /// Treats [this] as an in-memory filesystem and returns a stream of the
   /// contents of the child entry located at [path]. This only works if [this]
   /// is a directory entry. This operation is not [schedule]d.
@@ -45,7 +45,7 @@
   /// All errors in loading the file will be passed through the returned
   /// [Stream].
   Stream<List<int>> load(String pathToLoad) => errorStream("Can't load "
-      "'$pathToLoad' from within $nameDescription: not a directory.");
+      "'$pathToLoad' from within '$name': not a directory.");
 
   /// Returns the contents of [this] as a stream. This only works if [this] is a
   /// file entry. This operation is not [schedule]d.
@@ -54,17 +54,6 @@
   /// [Stream].
   Stream<List<int>> read();
 
-  /// Asserts that the name of the descriptor is a [String] and returns it.
-  String get stringName {
-    if (name is String) return name;
-    throw 'Pattern $nameDescription must be a string.';
-  }
-
-  /// Returns a human-readable description of [name], for error reporting. For
-  /// string names, this will just be the name in quotes; for regular
-  /// expressions, it will use JavaScript-style `/.../` notation.
-  String get nameDescription => describePattern(name);
-
   /// Returns a detailed tree-style description of [this].
   String describe();
 }
diff --git a/pkg/scheduled_test/lib/src/descriptor/directory.dart b/pkg/scheduled_test/lib/src/descriptor/directory.dart
deleted file mode 100644
index 594fb56..0000000
--- a/pkg/scheduled_test/lib/src/descriptor/directory.dart
+++ /dev/null
@@ -1,96 +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.
-
-library descriptor.file;
-
-import 'dart:async';
-import 'dart:io' as io;
-
-import '../../../../../pkg/pathos/lib/path.dart' as path;
-
-import '../../descriptor.dart' as descriptor;
-import '../../scheduled_test.dart';
-import '../utils.dart';
-import 'utils.dart';
-
-/// A path builder to ensure that [load] uses POSIX paths.
-final path.Builder _path = new path.Builder(style: path.Style.posix);
-
-/// A descriptor describing a directory containing multiple files.
-class Directory extends descriptor.Entry {
-  /// The entries contained within this directory.
-  final Iterable<descriptor.Entry> contents;
-
-  Directory(Pattern name, this.contents)
-      : super(name);
-
-  Future create([String parent]) => schedule(() {
-    if (parent == null) parent = descriptor.defaultRoot;
-    var fullPath = path.join(parent, stringName);
-    return new io.Directory(fullPath).create(recursive: true).then((_) {
-      return Future.wait(
-          contents.map((entry) => entry.create(fullPath)).toList());
-    });
-  }, 'creating directory:\n${describe()}');
-
-  Future validate([String parent]) => schedule(() {
-    if (parent == null) parent = descriptor.defaultRoot;
-    var fullPath = entryMatchingPattern('Directory', parent, name);
-    return Future.wait(
-        contents.map((entry) => entry.validate(fullPath)).toList());
-  }, 'validating directory:\n${describe()}');
-
-  Stream<List<int>> load(String pathToLoad) {
-    return futureStream(new Future.immediate(null).then((_) {
-      if (_path.isAbsolute(pathToLoad)) {
-        throw "Can't load absolute path '$pathToLoad'.";
-      }
-
-      var split = _path.split(_path.normalize(pathToLoad));
-      if (split.isEmpty || split.first == '.' || split.first == '..') {
-        throw "Can't load '$pathToLoad' from within $nameDescription.";
-      }
-
-      var matchingEntries = contents.where((entry) =>
-          entry.stringName == split.first).toList();
-
-      if (matchingEntries.length == 0) {
-        throw "Couldn't find an entry named '${split.first}' within "
-            "$nameDescription.";
-      } else if (matchingEntries.length > 1) {
-        throw "Found multiple entries named '${split.first}' within "
-            "$nameDescription.";
-      } else {
-        var remainingPath = split.sublist(1);
-        if (remainingPath.isEmpty) {
-          return matchingEntries.first.read();
-        } else {
-          return matchingEntries.first.load(_path.joinAll(remainingPath));
-        }
-      }
-    }));
-  }
-
-  Stream<List<int>> read() => errorStream("Can't read the contents of "
-      "$nameDescription: is a directory.");
-
-  String describe() {
-    var description = name;
-    if (name is! String) description = 'directory matching $nameDescription';
-    if (contents.isEmpty) return description;
-
-    var buffer = new StringBuffer();
-    buffer.writeln(description);
-    for (var entry in contents.take(contents.length - 1)) {
-      var entryString = prefixLines(entry.describe(), prefix: '|   ')
-          .replaceFirst('|   ', '|-- ');
-      buffer.writeln(entryString);
-    }
-
-    var lastEntryString = prefixLines(contents.last.describe(), prefix: '    ')
-        .replaceFirst('    ', "'-- ");
-    buffer.write(lastEntryString);
-    return buffer.toString();
-  }
-}
diff --git a/pkg/scheduled_test/lib/src/descriptor/directory_descriptor.dart b/pkg/scheduled_test/lib/src/descriptor/directory_descriptor.dart
new file mode 100644
index 0000000..690f92f
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/directory_descriptor.dart
@@ -0,0 +1,130 @@
+// 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 descriptor.file;
+
+import 'dart:async';
+import 'dart:io';
+
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+
+import '../../descriptor.dart';
+import '../../scheduled_test.dart';
+import '../utils.dart';
+
+/// A path builder to ensure that [load] uses POSIX paths.
+final path.Builder _path = new path.Builder(style: path.Style.posix);
+
+/// A descriptor describing a directory containing multiple files.
+class DirectoryDescriptor extends Descriptor {
+  /// The entries contained within this directory. This is intentionally
+  /// mutable.
+  final List<Descriptor> contents;
+
+  DirectoryDescriptor(String name, Iterable<Descriptor> contents)
+      : super(name),
+        contents = contents.toList();
+
+  Future create([String parent]) => schedule(() {
+    if (parent == null) parent = defaultRoot;
+    var fullPath = path.join(parent, name);
+    return new Directory(fullPath).create(recursive: true).then((_) {
+      return Future.wait(
+          contents.map((entry) => entry.create(fullPath)).toList());
+    });
+  }, 'creating directory:\n${describe()}');
+
+  Future validate([String parent]) => schedule(() => validateNow(parent),
+      'validating directory:\n${describe()}');
+
+  Future validateNow([String parent]) {
+    if (parent == null) parent = defaultRoot;
+    var fullPath = path.join(parent, name);
+    if (!new Directory(fullPath).existsSync()) {
+      throw "Directory not found: '$fullPath'.";
+    }
+
+    return Future.wait(contents.map((entry) {
+      return new Future.of(() => entry.validateNow(fullPath))
+          .then((_) => null)
+          .catchError((e) => e.error);
+    })).then((results) {
+      var errors = results.where((e) => e != null);
+      if (errors.isEmpty) return;
+      throw _DirectoryValidationError.merge(errors);
+    });
+  }
+
+  Stream<List<int>> load(String pathToLoad) {
+    return futureStream(new Future.immediate(null).then((_) {
+      if (_path.isAbsolute(pathToLoad)) {
+        throw "Can't load absolute path '$pathToLoad'.";
+      }
+
+      var split = _path.split(_path.normalize(pathToLoad));
+      if (split.isEmpty || split.first == '.' || split.first == '..') {
+        throw "Can't load '$pathToLoad' from within '$name'.";
+      }
+
+      var matchingEntries = contents.where((entry) =>
+          entry.name == split.first).toList();
+
+      if (matchingEntries.length == 0) {
+        throw "Couldn't find an entry named '${split.first}' within '$name'.";
+      } else if (matchingEntries.length > 1) {
+        throw "Found multiple entries named '${split.first}' within '$name'.";
+      } else {
+        var remainingPath = split.sublist(1);
+        if (remainingPath.isEmpty) {
+          return matchingEntries.first.read();
+        } else {
+          return matchingEntries.first.load(_path.joinAll(remainingPath));
+        }
+      }
+    }));
+  }
+
+  Stream<List<int>> read() => errorStream("Can't read the contents of '$name': "
+      "is a directory.");
+
+  String describe() {
+    if (contents.isEmpty) return name;
+
+    var buffer = new StringBuffer();
+    buffer.writeln(name);
+    for (var entry in contents.take(contents.length - 1)) {
+      var entryString = prefixLines(entry.describe(), prefix: '|   ')
+          .replaceFirst('|   ', '|-- ');
+      buffer.writeln(entryString);
+    }
+
+    var lastEntryString = prefixLines(contents.last.describe(), prefix: '    ')
+        .replaceFirst('    ', "'-- ");
+    buffer.write(lastEntryString);
+    return buffer.toString();
+  }
+}
+
+/// A class for formatting errors thrown by [DirectoryDescriptor].
+class _DirectoryValidationError {
+  final Collection<String> errors;
+
+  /// Flatten nested [_DirectoryValidationError]s in [errors] to create a single
+  /// list of errors.
+  static _DirectoryValidationError merge(Iterable errors) {
+    return new _DirectoryValidationError(errors.expand((error) {
+      if (error is _DirectoryValidationError) return error.errors;
+      return [error];
+    }));
+  }
+
+  _DirectoryValidationError(Iterable errors)
+      : errors = errors.map((e) => e.toString()).toList();
+
+  String toString() {
+    if (errors.length == 1) return errors.single;
+    return errors.map((e) => prefixLines(e, prefix: '  ', firstPrefix: '* '))
+        .join('\n');
+  }
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/file.dart b/pkg/scheduled_test/lib/src/descriptor/file.dart
deleted file mode 100644
index 15b9ef4..0000000
--- a/pkg/scheduled_test/lib/src/descriptor/file.dart
+++ /dev/null
@@ -1,107 +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.
-
-library descriptor.file;
-
-import 'dart:async';
-import 'dart:io' as io;
-import 'dart:math' as math;
-import 'dart:utf';
-
-import '../../../../../pkg/pathos/lib/path.dart' as path;
-
-import '../../descriptor.dart' as descriptor;
-import '../../scheduled_test.dart';
-import '../utils.dart';
-import 'utils.dart';
-
-/// A descriptor describing a single file.
-class File extends descriptor.Entry {
-  /// Whether this descriptor describes a binary file. This is only used when
-  /// displaying error messages.
-  final bool isBinary;
-
-  /// The contents of the file, in bytes.
-  final List<int> contents;
-
-  /// The contents of the file as a String. Assumes UTF-8 encoding.
-  String get textContents => new String.fromCharCodes(contents);
-
-  File.binary(Pattern name, List<int> contents)
-      : this._(name, contents, true);
-
-  File(Pattern name, String contents)
-      : this._(name, encodeUtf8(contents), false);
-
-  File._(Pattern name, this.contents, this.isBinary)
-      : super(name);
-
-  Future create([String parent]) => schedule(() {
-    if (parent == null) parent = descriptor.defaultRoot;
-    return new io.File(path.join(parent, stringName)).writeAsBytes(contents);
-  }, 'creating file $nameDescription');
-
-  Future validate([String parent]) => schedule(() {
-    if (parent == null) parent = descriptor.defaultRoot;
-    var fullPath = entryMatchingPattern('File', parent, name);
-    return new io.File(fullPath).readAsBytes()
-        .then((actualContents) {
-      if (orderedIterableEquals(contents, actualContents)) return;
-      if (isBinary) {
-        // TODO(nweiz): show a hex dump here if the data is small enough.
-        throw "File $nameDescription didn't contain the expected binary "
-            "data.";
-      }
-      var description = nameDescription;
-      if (name is! String) {
-        description = "'${path.basename(fullPath)}' (matching $description)";
-      }
-      throw _textMismatchMessage(description, textContents,
-          new String.fromCharCodes(actualContents));;
-    });
-  }, 'validating file $nameDescription');
-
-  Stream<List<int>> read() => new Future.immediate(contents).asStream();
-
-  String describe() {
-    if (name is String) return name;
-    return 'file matching $nameDescription';
-  }
-}
-
-String _textMismatchMessage(String description, String expected,
-    String actual) {
-  final expectedLines = expected.split('\n');
-  final actualLines = actual.split('\n');
-
-  var results = [];
-
-  // Compare them line by line to see which ones match.
-  var length = math.max(expectedLines.length, actualLines.length);
-  for (var i = 0; i < length; i++) {
-    if (i >= actualLines.length) {
-      // Missing output.
-      results.add('? ${expectedLines[i]}');
-    } else if (i >= expectedLines.length) {
-      // Unexpected extra output.
-      results.add('X ${actualLines[i]}');
-    } else {
-      var expectedLine = expectedLines[i];
-      var actualLine = actualLines[i];
-
-      if (expectedLine != actualLine) {
-        // Mismatched lines.
-        results.add('X $actualLine');
-      } else {
-        // Matched lines.
-        results.add('| $actualLine');
-      }
-    }
-  }
-
-  return "File $description should contain:\n"
-    "${prefixLines(expected)}\n"
-    "but actually contained:\n"
-    "${results.join('\n')}";
-}
diff --git a/pkg/scheduled_test/lib/src/descriptor/file_descriptor.dart b/pkg/scheduled_test/lib/src/descriptor/file_descriptor.dart
new file mode 100644
index 0000000..ffcf567
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/file_descriptor.dart
@@ -0,0 +1,104 @@
+// 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 descriptor.file;
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:math' as math;
+import 'dart:utf';
+
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+
+import '../../descriptor.dart';
+import '../../scheduled_test.dart';
+import '../utils.dart';
+
+/// A descriptor describing a single file.
+class FileDescriptor extends Descriptor {
+  /// Whether this descriptor describes a binary file. This is only used when
+  /// displaying error messages.
+  final bool isBinary;
+
+  /// The contents of the file, in bytes.
+  final List<int> contents;
+
+  /// The contents of the file as a String. Assumes UTF-8 encoding.
+  String get textContents => new String.fromCharCodes(contents);
+
+  FileDescriptor.binary(String name, List<int> contents)
+      : this._(name, contents, true);
+
+  FileDescriptor(String name, String contents)
+      : this._(name, encodeUtf8(contents), false);
+
+  FileDescriptor._(String name, this.contents, this.isBinary)
+      : super(name);
+
+  Future create([String parent]) => schedule(() {
+    if (parent == null) parent = defaultRoot;
+    return new File(path.join(parent, name)).writeAsBytes(contents);
+  }, "creating file '$name'");
+
+  Future validate([String parent]) =>
+    schedule(() => validateNow(parent), "validating file '$name'");
+
+  Future validateNow([String parent]) {
+    if (parent == null) parent = defaultRoot;
+    var fullPath = path.join(parent, name);
+    if (!new File(fullPath).existsSync()) {
+      throw "File not found: '$fullPath'.";
+    }
+
+    return new File(fullPath).readAsBytes()
+        .then((actualContents) {
+      if (orderedIterableEquals(contents, actualContents)) return;
+      if (isBinary) {
+        // TODO(nweiz): show a hex dump here if the data is small enough.
+        throw "File '$name' didn't contain the expected binary data.";
+      }
+      throw _textMismatchMessage(textContents,
+          new String.fromCharCodes(actualContents));
+    });
+  }
+
+  Stream<List<int>> read() => new Future.immediate(contents).asStream();
+
+  String describe() => name;
+
+  String _textMismatchMessage(String expected, String actual) {
+    final expectedLines = expected.split('\n');
+    final actualLines = actual.split('\n');
+
+    var results = [];
+
+    // Compare them line by line to see which ones match.
+    var length = math.max(expectedLines.length, actualLines.length);
+    for (var i = 0; i < length; i++) {
+      if (i >= actualLines.length) {
+        // Missing output.
+        results.add('? ${expectedLines[i]}');
+      } else if (i >= expectedLines.length) {
+        // Unexpected extra output.
+        results.add('X ${actualLines[i]}');
+      } else {
+        var expectedLine = expectedLines[i];
+        var actualLine = actualLines[i];
+
+        if (expectedLine != actualLine) {
+          // Mismatched lines.
+          results.add('X $actualLine');
+        } else {
+          // Matched lines.
+          results.add('| $actualLine');
+        }
+      }
+    }
+
+    return "File '$name' should contain:\n"
+        "${prefixLines(expected)}\n"
+        "but actually contained:\n"
+        "${results.join('\n')}";
+  }
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/nothing.dart b/pkg/scheduled_test/lib/src/descriptor/nothing.dart
deleted file mode 100644
index 9a1f1b4..0000000
--- a/pkg/scheduled_test/lib/src/descriptor/nothing.dart
+++ /dev/null
@@ -1,60 +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.
-
-library descriptor.async;
-
-import 'dart:async';
-import 'dart:io';
-
-import '../../../../../pkg/pathos/lib/path.dart' as path;
-
-import '../../descriptor.dart' as descriptor;
-import '../../scheduled_test.dart';
-import '../utils.dart';
-import 'utils.dart';
-
-/// A descriptor that validates that no file exists with the given name.
-/// Creating this descriptor is a no-op and loading from it is invalid.
-class Nothing extends descriptor.Entry {
-  Nothing(Pattern name)
-      : super(name);
-
-  Future create([String parent]) => new Future.immediate(null);
-
-  Future validate([String parent]) => schedule(() {
-    if (parent == null) parent = descriptor.defaultRoot;
-    if (name is String) {
-      var fullPath = path.join(parent, name);
-      if (new File(fullPath).existsSync()) {
-        throw "Expected nothing to exist at '$fullPath', but found a file.";
-      } else if (new Directory(fullPath).existsSync()) {
-        throw "Expected nothing to exist at '$fullPath', but found a "
-            "directory.";
-      } else {
-        return;
-      }
-    }
-
-    return new Directory(parent).list().toList().then((entries) {
-      var matchingEntries = entries
-          .map((entry) => entry is File ? entry.fullPathSync() : entry.path)
-          .where((entry) => path.basename(entry).contains(name))
-          .toList();
-      matchingEntries.sort();
-
-      if (matchingEntries.length == 0) return;
-      throw "Expected nothing to exist in '$parent' matching $nameDescription, "
-              "but found:\n"
-          "${matchingEntries.map((entry) => '* $entry').join('\n')}";
-    });
-  }, "validating $nameDescription doesn't exist");
-
-  Stream<List<int>> load(String pathToLoad) => errorStream("Nothing "
-      "descriptors don't support load().");
-
-  Stream<List<int>> read() => errorStream("Nothing descriptors don't support "
-      "read().");
-
-  String describe() => "nothing at $nameDescription";
-}
diff --git a/pkg/scheduled_test/lib/src/descriptor/nothing_descriptor.dart b/pkg/scheduled_test/lib/src/descriptor/nothing_descriptor.dart
new file mode 100644
index 0000000..00fa706
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/nothing_descriptor.dart
@@ -0,0 +1,47 @@
+// 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 descriptor.async;
+
+import 'dart:async';
+import 'dart:io';
+
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+
+import '../../descriptor.dart';
+import '../../scheduled_test.dart';
+import '../utils.dart';
+
+/// A descriptor that validates that no file exists with the given name.
+/// Creating this descriptor is a no-op and loading from it is invalid.
+class NothingDescriptor extends Descriptor {
+  NothingDescriptor(String name)
+      : super(name);
+
+  Future create([String parent]) => new Future.immediate(null);
+
+  Future validate([String parent]) => schedule(() => validateNow(parent),
+      "validating '$name' doesn't exist");
+
+  Future validateNow([String parent]) => new Future.of(() {
+    if (parent == null) parent = defaultRoot;
+    var fullPath = path.join(parent, name);
+    if (new File(fullPath).existsSync()) {
+      throw "Expected nothing to exist at '$fullPath', but found a file.";
+    } else if (new Directory(fullPath).existsSync()) {
+      throw "Expected nothing to exist at '$fullPath', but found a "
+          "directory.";
+    } else {
+      return;
+    }
+  });
+
+  Stream<List<int>> load(String pathToLoad) => errorStream("Nothing "
+      "descriptors don't support load().");
+
+  Stream<List<int>> read() => errorStream("Nothing descriptors don't support "
+      "read().");
+
+  String describe() => "nothing at '$name'";
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/pattern_descriptor.dart b/pkg/scheduled_test/lib/src/descriptor/pattern_descriptor.dart
new file mode 100644
index 0000000..1cea5f5
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/pattern_descriptor.dart
@@ -0,0 +1,121 @@
+// 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 descriptor.pattern;
+
+import 'dart:async';
+import 'dart:io';
+
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+
+import '../../descriptor.dart';
+import '../../scheduled_test.dart';
+import '../utils.dart';
+
+/// A function that takes a name for a [Descriptor] and returns a [Descriptor].
+/// This is used for [PatternDescriptor]s, where the name isn't known
+/// ahead-of-time.
+typedef Descriptor EntryCreator(String name);
+
+/// A descriptor that matches filesystem entities by [Pattern] rather than
+/// by [String]. It's used only for validation.
+///
+/// This class takes an [EntryCreator], which should return a [Descriptor] that
+/// will be used to validate the concrete filesystem entities that match the
+/// [pattern].
+class PatternDescriptor extends Descriptor {
+  /// The [Pattern] this matches filenames against. Note that the pattern must
+  /// match the entire basename of the file.
+  final Pattern pattern;
+
+  /// The function used to generate the [Descriptor] for filesystem entities
+  /// matching [pattern].
+  final EntryCreator _fn;
+
+  PatternDescriptor(Pattern pattern, this._fn)
+      : super('$pattern'),
+        pattern = pattern;
+
+  /// Validates that there is some filesystem entity in [parent] that matches
+  /// [pattern] and the child entry. This finds all entities in [parent]
+  /// matching [pattern], then passes each of their names to the [EntityCreator]
+  /// and validates the result. If exactly one succeeds, [this] is considered
+  /// valid.
+  Future validate([String parent]) => schedule(() => validateNow(parent),
+      "validating ${describe()}");
+
+  Future validateNow([String parent]) {
+    if (parent == null) parent = defaultRoot;
+    // TODO(nweiz): make sure this works with symlinks.
+    var matchingEntries = new Directory(parent).listSync()
+        .map((entry) => entry is File ? entry.fullPathSync() : entry.path)
+        .where((entry) => fullMatch(path.basename(entry), pattern))
+        .toList();
+    matchingEntries.sort();
+
+    if (matchingEntries.isEmpty) {
+      throw "No entry found in '$parent' matching ${_patternDescription}.";
+    }
+
+    return Future.wait(matchingEntries.map((entry) {
+      var descriptor = _fn(path.basename(entry));
+      return descriptor.validateNow(parent).then((_) {
+        return new Pair(null, descriptor.describe());
+      }).catchError((e) {
+        return new Pair(e.error.toString(), descriptor.describe());
+      });
+    })).then((results) {
+      var matches = results.where((result) => result.first == null).toList();
+      // If exactly one entry matching [pattern] validated, we're happy.
+      if (matches.length == 1) return;
+
+      // If more than one entry matching [pattern] validated, that's bad.
+      if (matches.length > 1) {
+        var resultString = matches.map((result) {
+          return prefixLines(result.last, firstPrefix: '* ', prefix: '  ');
+        }).join('\n');
+
+        throw "Multiple valid entries found in '$parent' matching "
+                "$_patternDescription:\n"
+            "$resultString";
+      }
+
+      // If no entries matching [pattern] validated, that's also bad.
+      var resultString = results.map((result) {
+        return prefixLines(
+            "Caught error\n"
+            "${prefixLines(result.first)}\n"
+            "while validating\n"
+            "${prefixLines(result.last)}",
+            firstPrefix: '* ', prefix: '  ');
+      }).join('\n');
+
+      throw "No valid entries found in '$parent' matching "
+              "$_patternDescription:\n"
+          "$resultString";
+    });
+  }
+
+  String describe() => "entry matching $_patternDescription";
+
+  String get _patternDescription {
+    if (pattern is String) return "'$pattern'";
+    if (pattern is! RegExp) return '$pattern';
+
+    var regExp = pattern as RegExp;
+    var flags = new StringBuffer();
+    if (!regExp.isCaseSensitive) flags.write('i');
+    if (regExp.isMultiLine) flags.write('m');
+    return '/${regExp.pattern}/$flags';
+  }
+
+  Future create([String parent]) => new Future.immediateError(
+      new UnsupportedError("Pattern descriptors don't support create()."));
+
+  Stream<List<int>> load(String pathToLoad) => errorStream(
+      new UnsupportedError("Pattern descriptors don't support load()."));
+
+  Stream<List<int>> read() => errorStream(new UnsupportedError("Pattern "
+      "descriptors don't support read()."));
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/utils.dart b/pkg/scheduled_test/lib/src/descriptor/utils.dart
deleted file mode 100644
index c53b429..0000000
--- a/pkg/scheduled_test/lib/src/descriptor/utils.dart
+++ /dev/null
@@ -1,54 +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.
-
-library descriptor.utils;
-
-import 'dart:io';
-
-import '../../../../../pkg/pathos/lib/path.dart' as path;
-
-/// Returns a single filesystem entry within [parent] whose name matches
-/// [pattern]. If [pattern] is a string, looks for an exact match; otherwise,
-/// looks for an entry that contains [pattern].
-///
-/// If there are no entries in [parent] matching [pattern], or more than one,
-/// this will throw an exception.
-///
-/// [type] is used for error reporting. It should be capitalized.
-String entryMatchingPattern(String type, String parent, Pattern pattern) {
-  if (pattern is String) {
-    var fullPath = path.join(parent, pattern);
-    if (new File(fullPath).existsSync() || new Directory(fullPath).existsSync()) {
-      return fullPath;
-    }
-    throw "$type not found: '$fullPath'.";
-  }
-
-  var matchingEntries = new Directory(parent).listSync()
-      .map((entry) => entry is File ? entry.fullPathSync() : entry.path)
-      .where((entry) => path.basename(entry).contains(pattern))
-      .toList();
-  matchingEntries.sort();
-
-  if (matchingEntries.length == 0) {
-    throw "No entry found in '$parent' matching ${describePattern(pattern)}.";
-  } else if (matchingEntries.length > 1) {
-    throw "Multiple entries found in '$parent' matching "
-          "${describePattern(pattern)}:\n"
-      "${matchingEntries.map((entry) => '* $entry').join('\n')}";
-  } else {
-    return matchingEntries.first;
-  }
-}
-
-/// Returns a human-readable description of [pattern].
-String describePattern(Pattern pattern) {
-  if (pattern is String) return "'$pattern'";
-  if (pattern is! RegExp) return '$pattern';
-
-  var flags = new StringBuffer();
-  if (!pattern.isCaseSensitive) flags.write('i');
-  if (pattern.isMultiLine) flags.write('m');
-  return '/${pattern.pattern}/$flags';
-}
diff --git a/pkg/scheduled_test/lib/src/schedule.dart b/pkg/scheduled_test/lib/src/schedule.dart
index 1e97ecc..977fc3f7 100644
--- a/pkg/scheduled_test/lib/src/schedule.dart
+++ b/pkg/scheduled_test/lib/src/schedule.dart
@@ -13,6 +13,7 @@
 import 'schedule_error.dart';
 import 'substitute_future.dart';
 import 'task.dart';
+import 'utils.dart';
 import 'value_future.dart';
 
 /// The schedule of tasks to run for a single test. This has three separate task
@@ -86,7 +87,10 @@
   TaskQueue _currentQueue;
 
   /// The time to wait before terminating a task queue for inactivity. Defaults
-  /// to 30 seconds. This can be set to `null` to disable timeouts entirely.
+  /// to 5 seconds. This can be set to `null` to disable timeouts entirely. Note
+  /// that the timeout is the maximum time a task is allowed between
+  /// interactions with the schedule, *not* the maximum time an entire test is
+  /// allowed. See also [heartbeat].
   ///
   /// If a task queue times out, an error will be raised that can be handled as
   /// usual in the [onException] and [onComplete] queues. If [onException] times
@@ -96,7 +100,7 @@
   /// If a task times out and then later completes with an error, that error
   /// cannot be handled. The user will still be notified of it.
   Duration get timeout => _timeout;
-  Duration _timeout = new Duration(seconds: 30);
+  Duration _timeout = new Duration(seconds: 5);
   set timeout(Duration duration) {
     _timeout = duration;
     heartbeat();
@@ -554,14 +558,11 @@
   String generateTree([Task highlight]) {
     assert(highlight == null || highlight.queue == this);
     return _contents.map((task) {
-      var lines = task.toString().split("\n");
-      var firstLine = task == highlight ?
-          "> ${lines.first}" : "* ${lines.first}";
-      lines = new List.from(lines.skip(1).map((line) => "| $line"));
-      lines.insertRange(0, 1, firstLine);
+      var taskString = prefixLines(task.toString(),
+          firstPrefix: task == highlight ? "> " : "* ");
 
       if (task == highlight && !task.children.isEmpty) {
-        for (var child in task.children) {
+        var childrenString = task.children.map((child) {
           var prefix = ">";
           if (child.state == TaskState.ERROR) {
             prefix = "X";
@@ -569,13 +570,13 @@
             prefix = "*";
           }
 
-          var childLines = child.toString().split("\n");
-          lines.add("  $prefix ${childLines.first}");
-          lines.addAll(childLines.skip(1).map((line) => "  | $line"));
-        }
+          return prefixLines(child.toString(),
+              firstPrefix: "  $prefix ", prefix: "  | ");
+        }).join('\n');
+        taskString = '$taskString\n$childrenString';
       }
 
-      return lines.join("\n");
+      return taskString;
     }).join("\n");
   }
 }
diff --git a/pkg/scheduled_test/lib/src/schedule_error.dart b/pkg/scheduled_test/lib/src/schedule_error.dart
index 7f1856b..a1f8a96 100644
--- a/pkg/scheduled_test/lib/src/schedule_error.dart
+++ b/pkg/scheduled_test/lib/src/schedule_error.dart
@@ -48,6 +48,14 @@
       error = error.error;
     }
 
+    if (stackTrace == null) {
+      try {
+        throw '';
+      } catch (_, thrownStackTrace) {
+        stackTrace = thrownStackTrace;
+      }
+    }
+
     return new ScheduleError(schedule, error, stackTrace, cause);
   }
 
diff --git a/pkg/scheduled_test/lib/src/utils.dart b/pkg/scheduled_test/lib/src/utils.dart
index 898b72e..57c341d 100644
--- a/pkg/scheduled_test/lib/src/utils.dart
+++ b/pkg/scheduled_test/lib/src/utils.dart
@@ -30,9 +30,19 @@
       onError: (e) => completer.completeError(e));
 }
 
-/// Prepends each line in [text] with [prefix].
-String prefixLines(String text, {String prefix: '| '}) =>
-  text.split('\n').map((line) => '$prefix$line').join('\n');
+/// Prepends each line in [text] with [prefix]. If [firstPrefix] is passed, the
+/// first line is prefixed with that instead.
+String prefixLines(String text, {String prefix: '| ', String firstPrefix}) {
+  var lines = text.split('\n');
+  if (firstPrefix == null) {
+    return lines.map((line) => '$prefix$line').join('\n');
+  }
+
+  var firstLine = "$firstPrefix${lines.first}";
+  lines = lines.skip(1).map((line) => '$prefix$line').toList();
+  lines.insert(0, firstLine);
+  return lines.join('\n');
+}
 
 /// Returns a [Future] that completes after pumping the event queue [times]
 /// times. By default, this should pump the event queue enough times to allow
@@ -82,24 +92,22 @@
 /// Returns a [Future] that will complete to the first element of [stream].
 /// Unlike [Stream.first], this is safe to use with single-subscription streams.
 Future streamFirst(Stream stream) {
-  // TODO(nweiz): remove this when issue 8512 is fixed.
-  var cancelled = false;
+  var stackTrace;
+  try {
+    throw '';
+  } catch (_, thrownStackTrace) {
+    stackTrace = thrownStackTrace;
+  }
+
   var completer = new Completer();
   var subscription;
   subscription = stream.listen((value) {
-    if (!cancelled) {
-      cancelled = true;
-      subscription.cancel();
-      completer.complete(value);
-    }
+    subscription.cancel();
+    completer.complete(value);
   }, onError: (e) {
-    if (!cancelled) {
-      completer.completeError(e.error, e.stackTrace);
-    }
+    completer.completeError(e.error, e.stackTrace);
   }, onDone: () {
-    if (!cancelled) {
-      completer.completeError(new StateError("No elements"));
-    }
+    completer.completeError(new StateError("No elements"), stackTrace);
   }, unsubscribeOnError: true);
   return completer.future;
 }
@@ -167,3 +175,10 @@
     return map;
   });
 }
+
+/// Returns whether [pattern] matches all of [string].
+bool fullMatch(String string, Pattern pattern) {
+  var matches = pattern.allMatches(string);
+  if (matches.isEmpty) return false;
+  return matches.first.start == 0 && matches.first.end == string.length;
+}
diff --git a/pkg/scheduled_test/test/descriptor_test.dart b/pkg/scheduled_test/test/descriptor_test.dart
index d203bbe..ff0efe5 100644
--- a/pkg/scheduled_test/test/descriptor_test.dart
+++ b/pkg/scheduled_test/test/descriptor_test.dart
@@ -45,26 +45,6 @@
     });
   });
 
-  expectTestsPass('file().create() with a RegExp name fails', () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      d.file(new RegExp(r'name\.txt'), 'contents').create();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.map((e) => e.error), equals([
-        r"Pattern /name\.txt/ must be a string."
-      ]), verbose: true);
-    });
-  }, passing: ['test 2']);
-
   expectTestsPass('file().validate() completes successfully if the filesystem '
       'matches the descriptor', () {
     test('test', () {
@@ -128,107 +108,6 @@
     });
   }, passing: ['test 2']);
 
-  expectTestsPass('file().validate() with a RegExp completes successfully if '
-      'the filesystem matches the descriptor', () {
-    test('test', () {
-      scheduleSandbox();
-
-      schedule(() {
-        return new File(path.join(sandbox, 'name.txt'))
-            .writeAsString('contents');
-      });
-
-      d.file(new RegExp(r'na..\.txt'), 'contents').validate();
-    });
-  });
-
-  expectTestsPass("file().validate() with a RegExp fails if there's a file "
-      "with the wrong contents", () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      schedule(() {
-        return new File(path.join(sandbox, 'name.txt'))
-            .writeAsString('some\nwrongtents');
-      });
-
-      d.file(new RegExp(r'na..\.txt'), 'some\ncontents\nand stuff').validate();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.map((e) => e.error), equals([
-        "File 'name.txt' (matching /na..\\.txt/) should contain:\n"
-        "| some\n"
-        "| contents\n"
-        "| and stuff\n"
-        "but actually contained:\n"
-        "| some\n"
-        "X wrongtents\n"
-        "? and stuff"
-      ]), verbose: true);
-    });
-  }, passing: ['test 2']);
-
-  expectTestsPass("file().validate() with a RegExp fails if there's no "
-      "file", () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      d.file(new RegExp(r'na..\.txt'), 'contents').validate();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(1));
-      expect(errors.first.error,
-          matches(r"^No entry found in '[^']+' matching /na\.\.\\\.txt/\.$"));
-    });
-  }, passing: ['test 2']);
-
-  expectTestsPass("file().validate() with a RegExp fails if there are multiple "
-      "matching files", () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      schedule(() {
-        return Future.wait([
-          new File(path.join(sandbox, 'name.txt')).writeAsString('contents'),
-          new File(path.join(sandbox, 'nape.txt')).writeAsString('contents'),
-          new File(path.join(sandbox, 'nail.txt')).writeAsString('contents')
-        ]);
-      });
-
-      d.file(new RegExp(r'na..\.txt'), 'contents').validate();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(1));
-      expect(errors.first.error,
-          matches(
-              r"^Multiple entries found in '[^']+' matching /na\.\.\\\.txt/:\n"
-              r"\* .*[\\/]nail\.txt\n"
-              r"\* .*[\\/]name\.txt\n"
-              r"\* .*[\\/]nape\.txt"));
-    });
-  }, passing: ['test 2']);
-
   expectTestsPass("file().read() returns the contents of the file as a stream",
       () {
     test('test', () {
@@ -251,13 +130,6 @@
     });
   });
 
-  expectTestsPass("file().describe() with a RegExp describes the file", () {
-    test('test', () {
-      expect(d.file(new RegExp(r'na..\.txt'), 'contents').describe(),
-          equals(r'file matching /na..\.txt/'));
-    });
-  });
-
   expectTestsPass('binaryFile().create() creates a file', () {
     test('test', () {
       scheduleSandbox();
@@ -355,26 +227,6 @@
     });
   });
 
-  expectTestsPass("directory().create() with a RegExp name fails", () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      d.dir(new RegExp('dir')).create();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.map((e) => e.error), equals([
-        "Pattern /dir/ must be a string."
-      ]), verbose: true);
-    });
-  }, passing: ['test 2']);
-
   expectTestsPass("directory().validate() completes successfully if the "
       "filesystem matches the descriptor", () {
     test('test', () {
@@ -443,7 +295,7 @@
     test('test 2', () {
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
       expect(errors.length, equals(1));
-      expect(errors.first.error,
+      expect(errors.first.error.toString(),
           matches(r"^Directory not found: '[^']+[\\/]dir[\\/]subdir'\.$"));
     });
   }, passing: ['test 2']);
@@ -485,11 +337,58 @@
     test('test 2', () {
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
       expect(errors.length, equals(1));
-      expect(errors.first.error,
+      expect(errors.first.error.toString(),
           matches(r"^File not found: '[^']+[\\/]dir[\\/]file2\.txt'\.$"));
     });
   }, passing: ['test 2']);
 
+  expectTestsPass("directory().validate() fails if multiple children aren't "
+      "found or have the wrong contents", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      schedule(() {
+        var dirPath = path.join(sandbox, 'dir');
+        var subdirPath = path.join(dirPath, 'subdir');
+        return new Directory(subdirPath).create(recursive: true).then((_) {
+          return Future.wait([
+            new File(path.join(dirPath, 'file1.txt'))
+                .writeAsString('contents1'),
+            new File(path.join(subdirPath, 'subfile2.txt'))
+                .writeAsString('subwrongtents2')
+          ]);
+        });
+      });
+
+      d.dir('dir', [
+        d.dir('subdir', [
+          d.file('subfile1.txt', 'subcontents1'),
+          d.file('subfile2.txt', 'subcontents2')
+        ]),
+        d.file('file1.txt', 'contents1'),
+        d.file('file2.txt', 'contents2')
+      ]).validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.length, equals(1));
+      expect(errors.first.error.toString(), matches(
+          r"^\* File not found: '[^']+[\\/]dir[\\/]subdir[\\/]subfile1\.txt'\."
+              r"\n"
+          r"\* File 'subfile2\.txt' should contain:\n"
+          r"  \| subcontents2\n"
+          r"  but actually contained:\n"
+          r"  X subwrongtents2\n"
+          r"\* File not found: '[^']+[\\/]dir[\\/]file2\.txt'\.$"));
+    });
+  }, passing: ['test 2']);
+
   expectTestsPass("directory().validate() fails if a file has the wrong "
       "contents", () {
     var errors;
@@ -529,7 +428,7 @@
 
     test('test 2', () {
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.map((e) => e.error), equals([
+      expect(errors.map((e) => e.error.toString()), equals([
         "File 'subfile1.txt' should contain:\n"
         "| subcontents1\n"
         "but actually contained:\n"
@@ -538,161 +437,6 @@
     });
   }, passing: ['test 2']);
 
-  expectTestsPass("directory().validate() with a RegExp completes successfully "
-      "if the filesystem matches the descriptor", () {
-    test('test', () {
-      scheduleSandbox();
-
-      schedule(() {
-        var dirPath = path.join(sandbox, 'dir');
-        var subdirPath = path.join(dirPath, 'subdir');
-        return new Directory(subdirPath).create(recursive: true).then((_) {
-          return Future.wait([
-            new File(path.join(dirPath, 'file1.txt'))
-                .writeAsString('contents1'),
-            new File(path.join(dirPath, 'file2.txt'))
-                .writeAsString('contents2'),
-            new File(path.join(subdirPath, 'subfile1.txt'))
-                .writeAsString('subcontents1'),
-            new File(path.join(subdirPath, 'subfile2.txt'))
-                .writeAsString('subcontents2')
-          ]);
-        });
-      });
-
-      d.dir(new RegExp('d.r'), [
-        d.dir('subdir', [
-          d.file('subfile1.txt', 'subcontents1'),
-          d.file('subfile2.txt', 'subcontents2')
-        ]),
-        d.file('file1.txt', 'contents1'),
-        d.file('file2.txt', 'contents2')
-      ]).validate();
-    });
-  });
-
-  expectTestsPass("directory().validate() with a RegExp fails if there's a dir "
-      "with the wrong contents", () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      schedule(() {
-        var dirPath = path.join(sandbox, 'dir');
-        var subdirPath = path.join(dirPath, 'subdir');
-        return new Directory(subdirPath).create(recursive: true).then((_) {
-          return Future.wait([
-            new File(path.join(dirPath, 'file1.txt'))
-                .writeAsString('contents1'),
-            new File(path.join(subdirPath, 'subfile1.txt'))
-                .writeAsString('subcontents1'),
-            new File(path.join(subdirPath, 'subfile2.txt'))
-                .writeAsString('subcontents2')
-          ]);
-        });
-      });
-
-      d.dir(new RegExp('d.r'), [
-        d.dir('subdir', [
-          d.file('subfile1.txt', 'subcontents1'),
-          d.file('subfile2.txt', 'subcontents2')
-        ]),
-        d.file('file1.txt', 'contents1'),
-        d.file('file2.txt', 'contents2')
-      ]).validate();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(1));
-      expect(errors.first.error,
-          matches(r"^File not found: '[^']+[\\/]dir[\\/]file2\.txt'\.$"));
-    });
-  }, passing: ['test 2']);
-
-  expectTestsPass("directory().validate() with a RegExp fails if there's no "
-      "dir", () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      d.dir(new RegExp('d.r'), [
-        d.dir('subdir', [
-          d.file('subfile1.txt', 'subcontents1'),
-          d.file('subfile2.txt', 'subcontents2')
-        ]),
-        d.file('file1.txt', 'contents1'),
-        d.file('file2.txt', 'contents2')
-      ]).validate();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(1));
-      expect(errors.first.error,
-          matches(r"^No entry found in '[^']+' matching /d\.r/\.$"));
-    });
-  }, passing: ['test 2']);
-
-  expectTestsPass("directory().validate() with a RegExp fails if there are "
-      "multiple matching dirs", () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      schedule(() {
-        return Future.wait(['dir', 'dar', 'dor'].map((dir) {
-          var dirPath = path.join(sandbox, dir);
-          var subdirPath = path.join(dirPath, 'subdir');
-          return new Directory(subdirPath).create(recursive: true).then((_) {
-            return Future.wait([
-              new File(path.join(dirPath, 'file1.txt'))
-                  .writeAsString('contents1'),
-              new File(path.join(dirPath, 'file2.txt'))
-                  .writeAsString('contents2'),
-              new File(path.join(subdirPath, 'subfile1.txt'))
-                  .writeAsString('subcontents1'),
-              new File(path.join(subdirPath, 'subfile2.txt'))
-                  .writeAsString('subcontents2')
-            ]);
-          });
-        }));
-      });
-
-      d.dir(new RegExp('d.r'), [
-        d.dir('subdir', [
-          d.file('subfile1.txt', 'subcontents1'),
-          d.file('subfile2.txt', 'subcontents2')
-        ]),
-        d.file('file1.txt', 'contents1'),
-        d.file('file2.txt', 'contents2')
-      ]).validate();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(1));
-      expect(errors.first.error,
-          matches(
-              r"^Multiple entries found in '[^']+' matching /d\.r/:\n"
-              r"\* .*[\\/]dar\n"
-              r"\* .*[\\/]dir\n"
-              r"\* .*[\\/]dor"));
-    });
-  }, passing: ['test 2']);
-
   expectTestsPass("directory().load() loads a file", () {
     test('test', () {
       var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
@@ -762,16 +506,6 @@
     });
   });
 
-  expectTestsPass("directory().load() fails to load a file with a RegExp name",
-      () {
-    test('test', () {
-      var dir = d.dir('dir', [d.file(new RegExp(r'name\.txt'), 'contents')]);
-
-      expect(dir.load('name.txt').toList(),
-          throwsA(equals(r"Pattern /name\.txt/ must be a string.")));
-    });
-  });
-
   expectTestsPass("directory().load() fails to load a file that doesn't exist",
       () {
     test('test', () {
@@ -802,15 +536,13 @@
     test('test', () {
       var dir = d.dir('dir', [
         d.file('file1.txt', 'contents1'),
-        d.file('file2.txt', 'contents2'),
-        d.file(new RegExp(r're\.txt'), 're-contents')
+        d.file('file2.txt', 'contents2')
       ]);
 
       expect(dir.describe(), equals(
           "dir\n"
           "|-- file1.txt\n"
-          "|-- file2.txt\n"
-          "'-- file matching /re\\.txt/"));
+          "'-- file2.txt"));
     });
   });
 
@@ -841,21 +573,6 @@
     });
   });
 
-  expectTestsPass("directory().describe() with a RegExp describes the "
-      "directory", () {
-    test('test', () {
-      var dir = d.dir(new RegExp(r'd.r'), [
-        d.file('file1.txt', 'contents1'),
-        d.file('file2.txt', 'contents2')
-      ]);
-
-      expect(dir.describe(), equals(
-          "directory matching /d.r/\n"
-          "|-- file1.txt\n"
-          "'-- file2.txt"));
-    });
-  });
-
   expectTestsPass("directory().describe() with no contents returns the "
       "directory name", () {
     test('test', () {
@@ -976,7 +693,7 @@
 
       expect(d.async(new Future.immediate(d.file('name.txt')))
               .load('path').toList(),
-          throwsA(equals("Async descriptors don't support load().")));
+          throwsA(equals("AsyncDescriptors don't support load().")));
     });
   });
 
@@ -985,7 +702,7 @@
       scheduleSandbox();
 
       expect(d.async(new Future.immediate(d.file('name.txt'))).read().toList(),
-          throwsA(equals("Async descriptors don't support read().")));
+          throwsA(equals("AsyncDescriptors don't support read().")));
     });
   });
 
@@ -1015,15 +732,6 @@
     });
   });
 
-  expectTestsPass("nothing().validate() with a RegExp succeeds if nothing's "
-      "there", () {
-    test('test', () {
-      scheduleSandbox();
-
-      d.nothing(new RegExp('f.o')).validate();
-    });
-  });
-
   expectTestsPass("nothing().validate() fails if there's a file", () {
     var errors;
     test('test 1', () {
@@ -1068,33 +776,6 @@
     });
   }, passing: ['test 2']);
 
-  expectTestsPass("nothing().validate() with a RegExp fails if there are "
-      "multiple entries", () {
-    var errors;
-    test('test 1', () {
-      scheduleSandbox();
-
-      currentSchedule.onException.schedule(() {
-        errors = currentSchedule.errors;
-      });
-
-      d.dir('foo').create();
-      d.file('faa', 'contents').create();
-      d.file('not-foo', 'contents').create();
-      d.nothing(new RegExp(r'^f..$')).validate();
-    });
-
-    test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(1));
-      expect(errors.first.error,
-          matches(r"^Expected nothing to exist in '[^']+' matching "
-                  r"/\^f\.\.\$/, but found:\n"
-              r"\* .*[\\/]faa\n"
-              r"\* .*[\\/]foo$"));
-    });
-  }, passing: ['test 2']);
-
   expectTestsPass("nothing().load() fails", () {
     test('test', () {
       scheduleSandbox();
@@ -1112,6 +793,156 @@
           throwsA(equals("Nothing descriptors don't support read().")));
     });
   });
+
+  expectTestsPass("pattern().validate() succeeds if there's a file matching "
+      "the pattern and the child entry", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.file('foo', 'blap').create();
+
+      d.filePattern(new RegExp(r'f..'), 'blap').validate();
+    });
+  });
+
+  expectTestsPass("pattern().validate() succeeds if there's a dir matching "
+      "the pattern and the child entry", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.dir('foo', [
+        d.file('bar', 'baz')
+      ]).create();
+
+      d.dirPattern(new RegExp(r'f..'), [
+        d.file('bar', 'baz')
+      ]).validate();
+    });
+  });
+
+  expectTestsPass("pattern().validate() succeeds if there's multiple files "
+      "matching the pattern but only one matching the child entry", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.file('foo', 'blap').create();
+      d.file('fee', 'blak').create();
+      d.file('faa', 'blut').create();
+
+      d.filePattern(new RegExp(r'f..'), 'blap').validate();
+    });
+  });
+
+  expectTestsPass("pattern().validate() fails if there's no file matching the "
+      "pattern", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.filePattern(new RegExp(r'f..'), 'bar').validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.length, equals(1));
+      expect(errors.first.error,
+          matches(r"^No entry found in '[^']+' matching /f\.\./\.$"));
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("pattern().validate() fails if there's a file matching the "
+      "pattern but not the entry", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.file('foo', 'bap').create();
+      d.filePattern(new RegExp(r'f..'), 'bar').validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.length, equals(1));
+      expect(errors.first.error,
+          matches(r"^Caught error\n"
+              r"| File 'foo' should contain:\n"
+              r"| | bar\n"
+              r"| but actually contained:\n"
+              r"| X bap\n"
+              r"while validating\n"
+              r"| foo$"));
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("pattern().validate() fails if there's a dir matching the "
+      "pattern but not the entry", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.dir('foo', [
+        d.file('bar', 'bap')
+      ]).create();
+
+      d.dirPattern(new RegExp(r'f..'), [
+        d.file('bar', 'baz')
+      ]).validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.length, equals(1));
+      expect(errors.first.error,
+          matches(r"^Caught error\n"
+              r"| File 'bar' should contain:\n"
+              r"| | baz\n"
+              r"| but actually contained:\n"
+              r"| X bap"
+              r"while validating\n"
+              r"| foo\n"
+              r"| '-- bar$"));
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("pattern().validate() fails if there's multiple files "
+      "matching the pattern and the child entry", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.file('foo', 'bar').create();
+      d.file('fee', 'bar').create();
+      d.file('faa', 'bar').create();
+      d.filePattern(new RegExp(r'f..'), 'bar').validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.length, equals(1));
+      expect(errors.first.error, matches(
+              r"^Multiple valid entries found in '[^']+' matching "
+                  r"\/f\.\./:\n"
+              r"\* faa\n"
+              r"\* fee\n"
+              r"\* foo$"));
+    });
+  }, passing: ['test 2']);
 }
 
 void scheduleSandbox() {
diff --git a/pkg/scheduled_test/test/scheduled_server_test.dart b/pkg/scheduled_test/test/scheduled_server_test.dart
index 5fc7812..aeb654f 100644
--- a/pkg/scheduled_test/test/scheduled_server_test.dart
+++ b/pkg/scheduled_test/test/scheduled_server_test.dart
@@ -35,10 +35,18 @@
 
     test('test 2', () {
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(2));
+      // TODO(nweiz): There can be three errors due to issue 9151. The
+      // HttpParserException is reported without a stack trace, and so when it's
+      // wrapped twice it registers as a different exception each time (because
+      // it's given an ad-hoc stack trace). Always expect two exceptions when
+      // issue 9151 is fixed.
+      expect(errors.length, inInclusiveRange(2, 3));
       expect(errors[0].error, equals("'scheduled server 0' received GET /hello "
           "when no more requests were expected."));
       expect(errors[1].error, new isInstanceOf<HttpParserException>());
+      if (errors.length > 2) {
+        expect(errors[2].error, new isInstanceOf<HttpParserException>());
+      }
     });
   }, passing: ['test 2']);
 
@@ -99,11 +107,19 @@
     });
 
     test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(2));
+      // TODO(nweiz): There can be three errors due to issue 9151. The
+      // HttpParserException is reported without a stack trace, and so when it's
+      // wrapped twice it registers as a different exception each time (because
+      // it's given an ad-hoc stack trace). Always expect two exceptions when
+      // issue 9151 is fixed.
+      expect(errors.length, inInclusiveRange(2, 3));
       expect(errors[0].error, equals("'scheduled server 0' received GET /hello "
           "earlier than expected."));
       expect(errors[1].error, new isInstanceOf<HttpParserException>());
+      if (errors.length > 2) {
+        expect(errors[2].error, new isInstanceOf<HttpParserException>());
+      }
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
     });
   }, passing: ['test 2']);
 
@@ -147,11 +163,18 @@
     });
 
     test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(2));
+      // TODO(nweiz): There can be three errors due to issue 9151. The
+      // HttpParserException is reported without a stack trace, and so when it's
+      // wrapped twice it registers as a different exception each time (because
+      // it's given an ad-hoc stack trace). Always expect two exceptions when
+      // issue 9151 is fixed.
+      expect(errors.length, inInclusiveRange(2, 3));
       expect(errors[0].error, equals("'scheduled server 0' expected GET "
           "/goodbye, but got GET /hello."));
       expect(errors[1].error, new isInstanceOf<HttpParserException>());
+      if (errors.length > 2) {
+        expect(errors[2].error, new isInstanceOf<HttpParserException>());
+      }
     });
   }, passing: ['test 2']);
 
@@ -173,11 +196,18 @@
     });
 
     test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(2));
+      // TODO(nweiz): There can be three errors due to issue 9151. The
+      // HttpParserException is reported without a stack trace, and so when it's
+      // wrapped twice it registers as a different exception each time (because
+      // it's given an ad-hoc stack trace). Always expect two exceptions when
+      // issue 9151 is fixed.
+      expect(errors.length, inInclusiveRange(2, 3));
       expect(errors[0].error, equals("'scheduled server 0' expected GET "
           "/hello, but got HEAD /hello."));
       expect(errors[1].error, new isInstanceOf<HttpParserException>());
+      if (errors.length > 2) {
+        expect(errors[2].error, new isInstanceOf<HttpParserException>());
+      }
     });
   }, passing: ['test 2']);
 
@@ -271,11 +301,18 @@
     });
 
     test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(2));
+      // TODO(nweiz): There can be three errors due to issue 9151. The
+      // HttpParserException is reported without a stack trace, and so when it's
+      // wrapped twice it registers as a different exception each time (because
+      // it's given an ad-hoc stack trace). Always expect two exceptions when
+      // issue 9151 is fixed.
+      expect(errors.length, inInclusiveRange(2, 3));
       expect(errors[0].error, equals("'scheduled server 0' received GET "
           "/hello/3 when no more requests were expected."));
       expect(errors[1].error, new isInstanceOf<HttpParserException>());
+      if (errors.length > 2) {
+        expect(errors[2].error, new isInstanceOf<HttpParserException>());
+      }
     });
   }, passing: ['test 2']);
 
@@ -296,10 +333,17 @@
     });
 
     test('test 2', () {
-      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
-      expect(errors.length, equals(2));
+      // TODO(nweiz): There can be three errors due to issue 9151. The
+      // HttpParserException is reported without a stack trace, and so when it's
+      // wrapped twice it registers as a different exception each time (because
+      // it's given an ad-hoc stack trace). Always expect two exceptions when
+      // issue 9151 is fixed.
+      expect(errors.length, inInclusiveRange(2, 3));
       expect(errors[0].error, equals('oh no'));
       expect(errors[1].error, new isInstanceOf<HttpParserException>());
+      if (errors.length > 2) {
+        expect(errors[2].error, new isInstanceOf<HttpParserException>());
+      }
     });
   }, passing: ['test 2']);
 }
diff --git a/pkg/scheduled_test/test/utils.dart b/pkg/scheduled_test/test/utils.dart
index 8f0bd23..7750e8a 100644
--- a/pkg/scheduled_test/test/utils.dart
+++ b/pkg/scheduled_test/test/utils.dart
@@ -4,6 +4,7 @@
 
 library test_utils;
 
+import 'dart:io';
 import 'dart:async';
 
 import '../lib/src/utils.dart';
diff --git a/pkg/serialization/lib/src/polyfill_identity_set.dart b/pkg/serialization/lib/src/polyfill_identity_set.dart
deleted file mode 100644
index 56a7865..0000000
--- a/pkg/serialization/lib/src/polyfill_identity_set.dart
+++ /dev/null
@@ -1,306 +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.
-
-// TODO(alanknight): Replace with proper identity collection. Issue 4161
-library identity_set;
-
-import 'dart:collection';
-
-// Hash map implementation with open addressing and quadratic probing.
-class IdentityMap<K, V> implements HashMap<K, V> {
-
-  // The [_keys] list contains the keys inserted in the map.
-  // The [_keys] list must be a raw list because it
-  // will contain both elements of type K, and the [_DELETED_KEY] of type
-  // [_DeletedKeySentinel].
-  // The alternative of declaring the [_keys] list as of type Object
-  // does not work, because the HashSetIterator constructor would fail:
-  //  HashSetIterator(HashSet<E> set)
-  //    : _nextValidIndex = -1,
-  //      _entries = set_._backingMap._keys {
-  //    _advance();
-  //  }
-  // With K being type int, for example, it would fail because
-  // List<Object> is not assignable to type List<int> of entries.
-  List _keys;
-
-  // The values inserted in the map. For a filled entry index in this
-  // list, there is always the corresponding key in the [keys_] list
-  // at the same entry index.
-  List<V> _values;
-
-  // The load limit is the number of entries we allow until we double
-  // the size of the lists.
-  int _loadLimit;
-
-  // The current number of entries in the map. Will never be greater
-  // than [_loadLimit].
-  int _numberOfEntries;
-
-  // The current number of deleted entries in the map.
-  int _numberOfDeleted;
-
-  // The sentinel when a key is deleted from the map.
-  static const _DeletedKeySentinel _DELETED_KEY = const _DeletedKeySentinel();
-
-  // The initial capacity of a hash map.
-  static const int _INITIAL_CAPACITY = 8;  // must be power of 2
-
-  IdentityMap() {
-    _numberOfEntries = 0;
-    _numberOfDeleted = 0;
-    _loadLimit = _computeLoadLimit(_INITIAL_CAPACITY);
-    _keys = new List(_INITIAL_CAPACITY);
-    _values = new List<V>(_INITIAL_CAPACITY);
-  }
-
-  factory IdentityMap.from(Map<K, V> other) {
-    Map<K, V> result = new IdentityMap<K, V>();
-    other.forEach((K key, V value) { result[key] = value; });
-    return result;
-  }
-
-  static int _computeLoadLimit(int capacity) {
-    return (capacity * 3) ~/ 4;
-  }
-
-  static int _firstProbe(int hashCode, int length) {
-    return hashCode & (length - 1);
-  }
-
-  static int _nextProbe(int currentProbe, int numberOfProbes, int length) {
-    return (currentProbe + numberOfProbes) & (length - 1);
-  }
-
-  int _probeForAdding(K key) {
-    if (key == null) throw new ArgumentError(null);
-    int hash = _firstProbe(key.hashCode, _keys.length);
-    int numberOfProbes = 1;
-    int initialHash = hash;
-    // insertionIndex points to a slot where a key was deleted.
-    int insertionIndex = -1;
-    while (true) {
-      // [existingKey] can be either of type [K] or [_DeletedKeySentinel].
-      Object existingKey = _keys[hash];
-      if (existingKey == null) {
-        // We are sure the key is not already in the set.
-        // If the current slot is empty and we didn't find any
-        // insertion slot before, return this slot.
-        if (insertionIndex < 0) return hash;
-        // If we did find an insertion slot before, return it.
-        return insertionIndex;
-      } else if (identical(existingKey, key)) {
-        // The key is already in the map. Return its slot.
-        return hash;
-      } else if ((insertionIndex < 0) &&
-                 (identical(existingKey, _DELETED_KEY))) {
-        // The slot contains a deleted element. Because previous calls to this
-        // method may not have had this slot deleted, we must continue iterate
-        // to find if there is a slot with the given key.
-        insertionIndex = hash;
-      }
-
-      // We did not find an insertion slot. Look at the next one.
-      hash = _nextProbe(hash, numberOfProbes++, _keys.length);
-      // _ensureCapacity has guaranteed the following cannot happen.
-      // assert(hash != initialHash);
-    }
-  }
-
-  int _probeForLookup(K key) {
-    if (key == null) throw new ArgumentError(null);
-    int hash = _firstProbe(key.hashCode, _keys.length);
-    int numberOfProbes = 1;
-    int initialHash = hash;
-    while (true) {
-      // [existingKey] can be either of type [K] or [_DeletedKeySentinel].
-      Object existingKey = _keys[hash];
-      // If the slot does not contain anything (in particular, it does not
-      // contain a deleted key), we know the key is not in the map.
-      if (existingKey == null) return -1;
-      // The key is in the map, return its index.
-      if (identical(existingKey, key)) return hash;
-      // Go to the next probe.
-      hash = _nextProbe(hash, numberOfProbes++, _keys.length);
-      // _ensureCapacity has guaranteed the following cannot happen.
-      // assert(hash != initialHash);
-    }
-  }
-
-  void _ensureCapacity() {
-    int newNumberOfEntries = _numberOfEntries + 1;
-    // Test if adding an element will reach the load limit.
-    if (newNumberOfEntries >= _loadLimit) {
-      _grow(_keys.length * 2);
-      return;
-    }
-
-    // Make sure that we don't have poor performance when a map
-    // contains lots of deleted entries: we _grow if
-    // there are more deleted entried than free entries.
-    int capacity = _keys.length;
-    int numberOfFreeOrDeleted = capacity - newNumberOfEntries;
-    int numberOfFree = numberOfFreeOrDeleted - _numberOfDeleted;
-    // assert(numberOfFree > 0);
-    if (_numberOfDeleted > numberOfFree) {
-      _grow(_keys.length);
-    }
-  }
-
-  static bool _isPowerOfTwo(int x) {
-    return ((x & (x - 1)) == 0);
-  }
-
-  void _grow(int newCapacity) {
-    assert(_isPowerOfTwo(newCapacity));
-    int capacity = _keys.length;
-    _loadLimit = _computeLoadLimit(newCapacity);
-    List oldKeys = _keys;
-    List<V> oldValues = _values;
-    _keys = new List(newCapacity);
-    _values = new List<V>(newCapacity);
-    for (int i = 0; i < capacity; i++) {
-      // [key] can be either of type [K] or [_DeletedKeySentinel].
-      Object key = oldKeys[i];
-      // If there is no key, we don't need to deal with the current slot.
-      if (key == null || identical(key, _DELETED_KEY)) {
-        continue;
-      }
-      V value = oldValues[i];
-      // Insert the {key, value} pair in their new slot.
-      int newIndex = _probeForAdding(key);
-      _keys[newIndex] = key;
-      _values[newIndex] = value;
-    }
-    _numberOfDeleted = 0;
-  }
-
-  void clear() {
-    _numberOfEntries = 0;
-    _numberOfDeleted = 0;
-    int length = _keys.length;
-    for (int i = 0; i < length; i++) {
-      _keys[i] = null;
-      _values[i] = null;
-    }
-  }
-
-  void operator []=(K key, V value) {
-    _ensureCapacity();
-    int index = _probeForAdding(key);
-    if ((_keys[index] == null) || (identical(_keys[index], _DELETED_KEY))) {
-      _numberOfEntries++;
-    }
-    _keys[index] = key;
-    _values[index] = value;
-  }
-
-  V operator [](K key) {
-    int index = _probeForLookup(key);
-    if (index < 0) return null;
-    return _values[index];
-  }
-
-  V putIfAbsent(K key, V ifAbsent()) {
-    int index = _probeForLookup(key);
-    if (index >= 0) return _values[index];
-
-    V value = ifAbsent();
-    this[key] = value;
-    return value;
-  }
-
-  V remove(K key) {
-    int index = _probeForLookup(key);
-    if (index >= 0) {
-      _numberOfEntries--;
-      V value = _values[index];
-      _values[index] = null;
-      // Set the key to the sentinel to not break the probing chain.
-      _keys[index] = _DELETED_KEY;
-      _numberOfDeleted++;
-      return value;
-    }
-    return null;
-  }
-
-  bool get isEmpty {
-    return _numberOfEntries == 0;
-  }
-
-  int get length {
-    return _numberOfEntries;
-  }
-
-  void forEach(void f(K key, V value)) {
-    int length = _keys.length;
-    for (int i = 0; i < length; i++) {
-      var key = _keys[i];
-      if ((key != null) && (!identical(key, _DELETED_KEY))) {
-        f(key, _values[i]);
-      }
-    }
-  }
-
-
-  Collection<K> get keys {
-    List<K> list = new List<K>(length);
-    int i = 0;
-    forEach((K key, V value) {
-      list[i++] = key;
-    });
-    return list;
-  }
-
-  Collection<V> get values {
-    List<V> list = new List<V>(length);
-    int i = 0;
-    forEach((K key, V value) {
-      list[i++] = value;
-    });
-    return list;
-  }
-
-  bool containsKey(K key) {
-    return (_probeForLookup(key) != -1);
-  }
-
-  bool containsValue(V value) {
-    int length = _values.length;
-    for (int i = 0; i < length; i++) {
-      var key = _keys[i];
-      if ((key != null) && (!identical(key, _DELETED_KEY))) {
-        if (_values[i] == value) return true;
-      }
-    }
-    return false;
-  }
-
-  String toString() {
-    return Maps.mapToString(this);
-  }
-}
-
-
-/**
- * A singleton sentinel used to represent when a key is deleted from the map.
- * We can't use [: const Object() :] as a sentinel because it would end up
- * canonicalized and then we cannot distinguish the deleted key from the
- * canonicalized [: Object() :].
- */
-class _DeletedKeySentinel {
-  const _DeletedKeySentinel();
-}
-
-
-/**
- * This class represents a pair of two objects, used by LinkedHashMap
- * to store a {key, value} in a list.
- */
-class _KeyValuePair<K, V> {
-  _KeyValuePair(this.key, this.value) {}
-
-  final K key;
-  V value;
-}
\ No newline at end of file
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index 408d40b..01b3b05 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -398,8 +398,9 @@
     var qualifiedName = r.resolveReference(state.first);
     var lookupFull = r.objectNamed(qualifiedName, (x) => null);
     if (lookupFull != null) return lookupFull;
-    var lib = qualifiedName.substring(0, qualifiedName.indexOf("."));
-    var type = qualifiedName.substring(qualifiedName.indexOf(".") + 1);
+    var separatorIndex = qualifiedName.lastIndexOf(".");
+    var lib = qualifiedName.substring(0, separatorIndex);
+    var type = qualifiedName.substring(separatorIndex + 1);
     var lookup = r.objectNamed(type, (x) => null);
     if (lookup != null) return lookup;
     var libMirror = currentMirrorSystem().libraries[lib];
@@ -541,6 +542,7 @@
   Iterator get iterator => _inflated.iterator;
   indexOf(x, [pos = 0]) => _inflated.toList().indexOf(x);
   lastIndexOf(x, [pos]) => _inflated.toList().lastIndexOf(x);
+  sublist(start, [end]) => _inflated.sublist(start, end);
 
   Map<int, dynamic> asMap() => IterableMixinWorkaround.asMapList(this);
 
diff --git a/pkg/serialization/pubspec.yaml b/pkg/serialization/pubspec.yaml
index c3ab332..e66e029 100644
--- a/pkg/serialization/pubspec.yaml
+++ b/pkg/serialization/pubspec.yaml
@@ -4,6 +4,5 @@
 documentation: http://api.dartlang.org/docs/pkg/serialization
 description: >
   Provide a serialization facility for Dart objects.
-dependencies:
-  unittest:
-    sdk: unittest
+dev_dependencies:
+  unittest: any
diff --git a/pkg/serialization/test/no_library_test.dart b/pkg/serialization/test/no_library_test.dart
new file mode 100644
index 0000000..30c1067
--- /dev/null
+++ b/pkg/serialization/test/no_library_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:serialization/serialization.dart';
+import 'package:unittest/unittest.dart';
+
+class Thing {
+  var name;
+}
+
+void main() {
+
+  test("Serializing something without a library directive", () {
+    var thing = new Thing()..name = 'testThing';
+    var s = new Serialization()
+      ..addRuleFor(thing);
+    var serialized = s.write(thing);
+    var newThing = s.read(serialized);
+    expect(thing.name, newThing.name);
+  });
+}
\ No newline at end of file
diff --git a/pkg/source_maps/README.md b/pkg/source_maps/README.md
new file mode 100644
index 0000000..df182d9
--- /dev/null
+++ b/pkg/source_maps/README.md
@@ -0,0 +1,27 @@
+Source Maps
+===========
+
+This project implements a Dart pub package to work with source maps. The
+implementation is based on the [source map version 3 spec][spec] which was
+originated from the [Closure Compiler][closure] and has been implemented in
+Chrome and Firefox.
+
+In this package we provide:
+  * Data types defining file locations and spans: these are not part of the
+    original source map specification. These data types are great for tracking
+    source locations on source maps, but they can also be used by tools to
+    reporting useful error messages that include on source locations.
+  * A builder that creates a source map programatically and produces the encoded
+    source map format.
+  * A parser that reads the source map format and provides APIs to read the
+    mapping information.
+
+Some upcoming features we are planning to add to this package are:
+  * A printer that lets you generate code, but record source map information in
+    the process.
+  * A tool that can compose source maps together. This would be useful for
+    instance, if you have 2 tools that produce source maps and you call one with
+    the result of the other.
+
+[closure]: http://code.google.com/p/closure-compiler/wiki/SourceMaps
+[spec]: https://docs.google.com/a/google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
diff --git a/pkg/source_maps/lib/builder.dart b/pkg/source_maps/lib/builder.dart
new file mode 100644
index 0000000..ad80fa0
--- /dev/null
+++ b/pkg/source_maps/lib/builder.dart
@@ -0,0 +1,146 @@
+// 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.
+
+/// Contains a builder object useful for creating source maps programatically.
+library source_maps.builder;
+
+// TODO(sigmund): add a builder for multi-section mappings.
+
+import 'dart:json' as json;
+import 'dart:collection';
+
+import 'span.dart';
+import 'src/vlq.dart';
+
+/// Builds a source map given a set of mappings.
+class SourceMapBuilder {
+
+  final List<Entry> _entries = <Entry>[];
+
+  /// Indices associated with file urls that will be part of the source map. We
+  /// use a linked hash-map so that `_urls.keys[_urls[u]] == u`
+  final Map<String, int> _urls = new LinkedHashMap<String, int>();
+
+  /// Indices associated with identifiers that will be part of the source map.
+  /// We use a linked hash-map so that `_names.keys[_names[n]] == n`
+  final Map<String, int> _names = new LinkedHashMap<String, int>();
+
+  /// Adds an entry mapping the [targetOffset] to [source].
+  void addFromOffset(Location source,
+      SourceFile targetFile, int targetOffset, String identifier) {
+    if (targetFile == null) {
+      throw new ArgumentError('targetFile cannot be null');
+    }
+    _entries.add(new Entry(source,
+          new FileLocation(targetFile, targetOffset), identifier));
+  }
+
+  /// Adds an entry mapping [target] to [source].
+  void addSpan(Span source, Span target) {
+    var name = source.isIdentifier ? source.text : null;
+    _entries.add(new Entry(source.start, target.start, name));
+  }
+
+  void addLocation(Location source, Location target, String identifier) {
+    _entries.add(new Entry(source, target, identifier));
+  }
+
+  /// Encodes all mappings added to this builder as a json map.
+  Map build(String fileUrl) {
+    var buff = new StringBuffer();
+    var line = 0;
+    var column = 0;
+    var srcLine = 0;
+    var srcColumn = 0;
+    var srcUrlId = 0;
+    var srcNameId = 0;
+    var first = true;
+
+    // The encoding needs to be sorted by the target offsets.
+    _entries.sort();
+    for (var entry in _entries) {
+      int nextLine = entry.target.line;
+      if (nextLine > line) {
+        for (int i = line; i < nextLine; ++i) {
+          buff.write(';');
+        }
+        line = nextLine;
+        column = 0;
+        first = true;
+      }
+
+      if (!first) buff.write(',');
+      first = false;
+      column = _append(buff, column, entry.target.column);
+
+      if (entry.source == null) continue;
+
+      srcUrlId = _append(buff, srcUrlId,
+          _indexOf(_urls, entry.source.sourceUrl));
+      srcLine = _append(buff, srcLine, entry.source.line);
+      srcColumn = _append(buff, srcColumn, entry.source.column);
+
+      if (entry.identifierName == null) continue;
+      srcNameId = _append(buff, srcNameId,
+          _indexOf(_names, entry.identifierName));
+    }
+
+    var result = {
+      'version': 3,
+      'sourceRoot': '',
+      'sources': _urls.keys.toList(),
+      'names' : _names.keys.toList(),
+      'mappings' : buff.toString()
+    };
+    if (fileUrl != null) {
+      result['file'] = fileUrl;
+    }
+    return result;
+  }
+
+  /// Encodes all mappings added to this builder as a json string.
+  String toJson(String fileUrl) => json.stringify(build(fileUrl));
+
+  /// Get the index of [value] in [map], or create one if it doesn't exist.
+  int _indexOf(Map<String, int> map, String value) {
+    return map.putIfAbsent(value, () {
+      int index = map.length;
+      map[value] = index;
+      return index;
+    });
+  }
+
+  /// Appends to [buff] a VLQ encoding of [newValue] using the difference
+  /// between [oldValue] and [newValue]
+  static int _append(StringBuffer buff, int oldValue, int newValue) {
+    buff.writeAll(encodeVlq(newValue - oldValue));
+    return newValue;
+  }
+}
+
+/// An entry in the source map builder.
+class Entry implements Comparable {
+  /// Span denoting the original location in the input source file
+  final Location source;
+
+  /// Span indicating the corresponding location in the target file.
+  final Location target;
+
+  /// An identifier name, when this location is the start of an identifier.
+  final String identifierName;
+
+  Entry(this.source, this.target, this.identifierName);
+
+  /// Implements [Comparable] to ensure that entries are ordered by their
+  /// location in the target file. We sort primarily by the target offset
+  /// because source map files are encoded by printing each mapping in order as
+  /// they appear in the target file.
+  int compareTo(Entry other) {
+    int res = target.compareTo(other.target);
+    if (res != 0) return res;
+    res = source.sourceUrl.compareTo(other.source.sourceUrl);
+    if (res != 0) return res;
+    return source.compareTo(other.source);
+  }
+}
diff --git a/pkg/source_maps/lib/parser.dart b/pkg/source_maps/lib/parser.dart
new file mode 100644
index 0000000..3849913
--- /dev/null
+++ b/pkg/source_maps/lib/parser.dart
@@ -0,0 +1,391 @@
+// 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.
+
+/// Contains the top-level function to parse source maps version 3.
+library source_maps.parser;
+
+import 'dart:json' as json;
+
+import 'span.dart';
+import 'src/utils.dart';
+import 'src/vlq.dart';
+
+/// Parses a source map directly from a json string.
+// TODO(sigmund): evaluate whether other maps should have the json parsed, or
+// the string represenation.
+Mapping parse(String jsonMap, {Map<String, Map> otherMaps}) =>
+  parseJson(json.parse(jsonMap), otherMaps: otherMaps);
+
+/// Parses a source map directly from a json map object.
+Mapping parseJson(Map map, {Map<String, Map> otherMaps}) {
+  if (map['version'] != 3) {
+    throw new ArgumentError(
+        'unexpected source map version: ${map["version"]}. '
+        'Only version 3 is supported.');
+  }
+
+  // TODO(sigmund): relax this? dart2js doesn't generate the file entry.
+  if (!map.containsKey('file')) {
+    throw new ArgumentError('missing "file" in source map');
+  }
+
+  if (map.containsKey('sections')) {
+    if (map.containsKey('mappings') || map.containsKey('sources') ||
+        map.containsKey('names')) {
+      throw new FormatException('map containing "sections" '
+          'cannot contain "mappings", "sources", or "names".');
+    }
+    return new MultiSectionMapping.fromJson(map['sections'], otherMaps);
+  }
+  return new SingleMapping.fromJson(map);
+}
+
+
+/// A mapping parsed our of a source map.
+abstract class Mapping {
+  Span spanFor(int line, int column, {Map<String, SourceFile> files});
+
+  Span spanForLocation(Location loc, {Map<String, SourceFile> files}) {
+    return spanFor(loc.line, loc.column, files: files);
+  }
+}
+
+/// A meta-level map containing sections.
+class MultiSectionMapping extends Mapping {
+  /// For each section, the start line offset.
+  final List<int> _lineStart = <int>[];
+
+  /// For each section, the start column offset.
+  final List<int> _columnStart = <int>[];
+
+  /// For each section, the actual source map information, which is not adjusted
+  /// for offsets.
+  final List<Mapping> _maps = <Mapping>[];
+
+  /// Creates a section mapping from json.
+  MultiSectionMapping.fromJson(List sections, Map<String, Map> otherMaps) {
+    for (var section in sections) {
+      var offset = section['offset'];
+      if (offset == null) throw new FormatException('section missing offset');
+
+      var line = section['offset']['line'];
+      if (line == null) throw new FormatException('offset missing line');
+
+      var column = section['offset']['column'];
+      if (column == null) throw new FormatException('offset missing column');
+
+      _lineStart.add(line);
+      _columnStart.add(column);
+
+      var url = section['url'];
+      var map = section['map'];
+
+      if (url != null && map != null) {
+        throw new FormatException("section can't use both url and map entries");
+      } else if (url != null) {
+        if (otherMaps == null || otherMaps[url] == null) {
+          throw new FormatException(
+              'section contains refers to $url, but no map was '
+              'given for it. Make sure a map is passed in "otherMaps"');
+        }
+        _maps.add(parseJson(otherMaps[url], otherMaps: otherMaps));
+      } else if (map != null) {
+        _maps.add(parseJson(map, otherMaps: otherMaps));
+      } else {
+        throw new FormatException('section missing url or map');
+      }
+    }
+    if (_lineStart.length == 0) {
+      throw new FormatException('expected at least one section');
+    }
+  }
+
+  int _indexFor(line, column) {
+    for(int i = 0; i < _lineStart.length; i++) {
+      if (line < _lineStart[i]) return i - 1;
+      if (line == _lineStart[i] && column < _columnStart[i]) return i - 1;
+    }
+    return _lineStart.length - 1;
+  }
+
+  Span spanFor(int line, int column, {Map<String, SourceFile> files}) {
+    int index = _indexFor(line, column);
+    return _maps[index].spanFor(
+        line - _lineStart[index], column - _columnStart[index], files: files);
+  }
+
+  String toString() {
+    var buff = new StringBuffer("$runtimeType : [");
+    for (int i = 0; i < _lineStart.length; i++) {
+      buff..write('(')
+          ..write(_lineStart[i])
+          ..write(',')
+          ..write(_columnStart[i])
+          ..write(':')
+          ..write(_maps[i])
+          ..write(')');
+    }
+    buff.write(']');
+    return buff.toString();
+  }
+}
+
+/// A map containing direct source mappings.
+// TODO(sigmund): integrate mapping and sourcemap builder?
+class SingleMapping extends Mapping {
+  /// Url of the target file.
+  final String targetUrl;
+
+  /// Source urls used in the mapping, indexed by id.
+  final List<String> urls;
+
+  /// Source names used in the mapping, indexed by id.
+  final List<String> names;
+
+  /// Entries indicating the beginning of each span.
+  final List<TargetLineEntry> lines = <TargetLineEntry>[];
+
+  SingleMapping.fromJson(Map map)
+      : targetUrl = map['file'],
+        // TODO(sigmund): add support for 'sourceRoot'
+        urls = map['sources'],
+        names = map['names'] {
+    int line = 0;
+    int column = 0;
+    int srcUrlId = 0;
+    int srcLine = 0;
+    int srcColumn = 0;
+    int srcNameId = 0;
+    var tokenizer = new _MappingTokenizer(map['mappings']);
+    var entries = <TargetEntry>[];
+
+    while (tokenizer.hasTokens) {
+      if (tokenizer.nextKind.isNewLine) {
+        if (!entries.isEmpty) {
+          lines.add(new TargetLineEntry(line, entries));
+          entries = <TargetEntry>[];
+        }
+        line++;
+        column = 0;
+        tokenizer._consumeNewLine();
+        continue;
+      }
+
+      // Decode the next entry, using the previous encountered values to
+      // decode the relative values.
+      //
+      // We expect 1, 4, or 5 values. If present, values are expected in the
+      // following order:
+      //   0: the starting column in the current line of the generated file
+      //   1: the id of the original source file
+      //   2: the starting line in the original source
+      //   3: the starting column in the original source
+      //   4: the id of the original symbol name
+      // The values are relative to the previous encountered values.
+      if (tokenizer.nextKind.isNewSegment) throw _segmentError(0, line);
+      column += tokenizer._consumeValue();
+      if (!tokenizer.nextKind.isValue) {
+        entries.add(new TargetEntry(column));
+      } else {
+        srcUrlId += tokenizer._consumeValue();
+        if (srcUrlId >= urls.length) {
+          throw new StateError(
+              'Invalid source url id. $targetUrl, $line, $srcUrlId');
+        }
+        if (!tokenizer.nextKind.isValue) throw _segmentError(2, line);
+        srcLine += tokenizer._consumeValue();
+        if (!tokenizer.nextKind.isValue) throw _segmentError(3, line);
+        srcColumn += tokenizer._consumeValue();
+        if (!tokenizer.nextKind.isValue) {
+          entries.add(new TargetEntry(column, srcUrlId, srcLine, srcColumn));
+        } else {
+          srcNameId += tokenizer._consumeValue();
+          if (srcNameId >= names.length) {
+            throw new StateError(
+                'Invalid name id: $targetUrl, $line, $srcNameId');
+          }
+          entries.add(
+              new TargetEntry(column, srcUrlId, srcLine, srcColumn, srcNameId));
+        }
+      }
+      if (tokenizer.nextKind.isNewSegment) tokenizer._consumeNewSegment();
+    }
+    if (!entries.isEmpty) {
+      lines.add(new TargetLineEntry(line, entries));
+    }
+  }
+
+  _segmentError(int seen, int line) => new StateError(
+      'Invalid entry in sourcemap, expected 1, 4, or 5'
+      ' values, but got $seen.\ntargeturl: $targetUrl, line: $line');
+
+  /// Returns [TargetLineEntry] which includes the location in the target [line]
+  /// number. In particular, the resulting entry is the last entry whose line
+  /// number is lower or equal to [line].
+  TargetLineEntry _findLine(int line) {
+    int index = binarySearch(lines, (e) => e.line > line);
+    return (index <= 0) ? null : lines[index - 1];
+  }
+
+  /// Returns [TargetEntry] which includes the location denoted by
+  /// [line], [column]. If [lineEntry] corresponds to [line], then this will be
+  /// the last entry whose column is lower or equal than [column]. If
+  /// [lineEntry] corresponds to a line prior to [line], then the result will be
+  /// the very last entry on that line.
+  TargetEntry _findColumn(int line, int column, TargetLineEntry lineEntry) {
+    if (lineEntry == null || lineEntry.entries.length == 0) return null;
+    if (lineEntry.line != line) return lineEntry.entries.last;
+    var entries = lineEntry.entries;
+    int index = binarySearch(entries, (e) => e.column > column);
+    return (index <= 0) ? null : entries[index - 1];
+  }
+
+  Span spanFor(int line, int column, {Map<String, SourceFile> files}) {
+    var lineEntry = _findLine(line);
+    var entry = _findColumn(line, column, _findLine(line));
+    if (entry == null) return null;
+    var url = urls[entry.sourceUrlId];
+    if (files != null && files[url] != null) {
+      var file = files[url];
+      var start = file.getOffset(entry.sourceLine, entry.sourceColumn);
+      if (entry.sourceNameId != null) {
+        var text = names[entry.sourceNameId];
+        return new FileSpan(files[url], start, start + text.length, true);
+      } else {
+        return new FileSpan(files[url], start);
+      }
+    } else {
+      // Offset and other context is not available.
+      if (entry.sourceNameId != null) {
+        return new FixedSpan(url, 0, entry.sourceLine, entry.sourceColumn,
+            text: names[entry.sourceNameId], isIdentifier: true);
+      } else {
+        return new FixedSpan(url, 0, entry.sourceLine, entry.sourceColumn);
+      }
+    }
+  }
+
+  String toString() {
+    return (new StringBuffer("$runtimeType : [")
+        ..write('targetUrl: ')
+        ..write(targetUrl)
+        ..write(', urls: ')
+        ..write(urls)
+        ..write(', names: ')
+        ..write(names)
+        ..write(', lines: ')
+        ..write(lines)
+        ..write(']')).toString();
+  }
+
+  String get debugString {
+    var buff = new StringBuffer();
+    for (var lineEntry in lines) {
+      var line = lineEntry.line;
+      for (var entry in lineEntry.entries) {
+        buff..write(targetUrl)
+            ..write(': ')
+            ..write(line)
+            ..write(':')
+            ..write(entry.column)
+            ..write('   -->   ')
+            ..write(urls[entry.sourceUrlId])
+            ..write(': ')
+            ..write(entry.sourceLine)
+            ..write(':')
+            ..write(entry.sourceColumn);
+        if (entry.sourceNameId != null) {
+          buff..write(' (')
+              ..write(names[entry.sourceNameId])
+              ..write(')');
+        }
+        buff.write('\n');
+      }
+    }
+    return buff.toString();
+  }
+}
+
+/// A line entry read from a source map.
+class TargetLineEntry {
+  final int line;
+  List<TargetEntry> entries = <TargetEntry>[];
+  TargetLineEntry(this.line, this.entries);
+
+  String toString() => '$runtimeType: $line $entries';
+}
+
+/// A target segment entry read from a source map
+class TargetEntry {
+  final int column;
+  final int sourceUrlId;
+  final int sourceLine;
+  final int sourceColumn;
+  final int sourceNameId;
+  TargetEntry(this.column, [this.sourceUrlId, this.sourceLine,
+      this.sourceColumn, this.sourceNameId]);
+
+  String toString() => '$runtimeType: '
+      '($column, $sourceUrlId, $sourceLine, $sourceColumn, $sourceNameId)';
+}
+
+/** A character iterator over a string that can peek one character ahead. */
+class _MappingTokenizer implements Iterator<String> {
+  final String _internal;
+  final int _length;
+  int index = -1;
+  _MappingTokenizer(String internal)
+      : _internal = internal,
+        _length = internal.length;
+
+  // Iterator API is used by decodeVlq to consume VLQ entries.
+  bool moveNext() => ++index < _length;
+  String get current =>
+      (index >= 0 && index < _length) ?  _internal[index] : null;
+
+  bool get hasTokens => index < _length - 1 && _length > 0;
+
+  _TokenKind get nextKind {
+    if (!hasTokens) return _TokenKind.EOF;
+    var next = _internal[index + 1];
+    if (next == ';') return _TokenKind.LINE;
+    if (next == ',') return _TokenKind.SEGMENT;
+    return _TokenKind.VALUE;
+  }
+
+  int _consumeValue() => decodeVlq(this);
+  void _consumeNewLine() { ++index; }
+  void _consumeNewSegment() { ++index; }
+
+  // Print the state of the iterator, with colors indicating the current
+  // position.
+  String toString() {
+    var buff = new StringBuffer();
+    for (int i = 0; i < index; i++) {
+      buff.write(_internal[i]);
+    }
+    buff.write('');
+    buff.write(current == null ? '' : current);
+    buff.write('');
+    for (int i = index + 1; i < _internal.length; i++) {
+      buff.write(_internal[i]);
+    }
+    buff.write(' ($index)');
+    return buff.toString();
+  }
+}
+
+class _TokenKind {
+  static const _TokenKind LINE = const _TokenKind(isNewLine: true);
+  static const _TokenKind SEGMENT = const _TokenKind(isNewSegment: true);
+  static const _TokenKind EOF = const _TokenKind(isEof: true);
+  static const _TokenKind VALUE = const _TokenKind();
+  final bool isNewLine;
+  final bool isNewSegment;
+  final bool isEof;
+  bool get isValue => !isNewLine && !isNewSegment && !isEof;
+
+  const _TokenKind(
+      {this.isNewLine: false, this.isNewSegment: false, this.isEof: false});
+}
diff --git a/pkg/source_maps/lib/printer.dart b/pkg/source_maps/lib/printer.dart
new file mode 100644
index 0000000..333aadc
--- /dev/null
+++ b/pkg/source_maps/lib/printer.dart
@@ -0,0 +1,89 @@
+// 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.
+
+/// Contains a code printer that generates code by recording the source maps.
+library source_maps.printer;
+
+import 'dart:utf' show stringToCodepoints;
+import 'builder.dart';
+import 'span.dart';
+
+const int _LF = 10;
+const int _CR = 13;
+
+/// A printer that keeps track of offset locations and records source maps
+/// locations.
+class Printer {
+  final String filename;
+  final StringBuffer _buff = new StringBuffer();
+  final SourceMapBuilder _maps = new SourceMapBuilder();
+  String get text => _buff.toString();
+  String get map => _maps.toJson(filename);
+
+  /// Current source location mapping.
+  Location _loc;
+
+  /// Current line in the buffer;
+  int _line = 0;
+
+  /// Current column in the buffer.
+  int _column = 0;
+
+  Printer(this.filename);
+
+  /// Add [str] contents to the output, tracking new lines to track correct
+  /// positions for span locations. When [projectMarks] is true, this method
+  /// adds a source map location on each new line, projecting that every new
+  /// line in the target file (printed here) corresponds to a new line in the
+  /// source file.
+  void add(String str, {projectMarks: false}) {
+    var chars = stringToCodepoints(str);
+    var length = chars.length;
+    for (int i = 0; i < length; i++) {
+      var c = chars[i];
+      if (c == _LF || (c == _CR && (i + 1 == length || chars[i + 1] != _LF))) {
+        // Return not followed by line-feed is treated as a new line.
+        _line++;
+        _column = 0;
+        if (projectMarks && _loc != null) {
+          if (_loc is FixedLocation) {
+            mark(new FixedLocation(0, _loc.sourceUrl, _loc.line + 1, 0));
+          } else if (_loc is FileLocation) {
+            var file = (_loc as FileLocation).file;
+            mark(new FileLocation(file, file.getOffset(_loc.line + 1, 0)));
+          }
+        }
+      } else {
+        _column++;
+      }
+    }
+    _buff.write(str);
+  }
+
+
+  /// Append a [total] number of spaces in the target file. Typically used for
+  /// formatting indentation.
+  void addSpaces(int total) {
+    for (int i = 0; i < total; i++) _buff.write(' ');
+    _column += total;
+  }
+
+  /// Marks that the current point in the target file corresponds to the [mark]
+  /// in the source file, which can be either a [Location] or a [Span]. When the
+  /// mark is an identifier's Span, this also records the name of the identifier
+  /// in the source map information.
+  void mark(mark) {
+    var loc;
+    var identifier = null;
+    if (mark is Location) {
+      loc = mark;
+    } else if (mark is Span) {
+      loc = mark.start;
+      if (mark.isIdentifier) identifier = mark.text;
+    }
+    _maps.addLocation(loc,
+        new FixedLocation(_buff.length, null, _line, _column), identifier);
+    _loc = loc;
+  }
+}
diff --git a/pkg/source_maps/lib/source_maps.dart b/pkg/source_maps/lib/source_maps.dart
new file mode 100644
index 0000000..4e24dea
--- /dev/null
+++ b/pkg/source_maps/lib/source_maps.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Source maps library.
+///
+/// Create a source map using [SourceMapBuilder]. For example:
+///     var json = (new SourceMapBuilder()
+///         ..add(inputSpan1, outputSpan1)
+///         ..add(inputSpan2, outputSpan2)
+///         ..add(inputSpan3, outputSpan3)
+///         .toJson(outputFile);
+///
+/// Use the [Span] and [SourceFile] classes to specify span locations.
+///
+/// Parse a source map using [parse], and call `spanFor` on the returned mapping
+/// object. For example:
+///     var mapping = parse(json);
+///     mapping.spanFor(outputSpan1.line, outputSpan1.column)
+library source_maps;
+
+export "builder.dart";
+export "parser.dart";
+export "printer.dart";
+export "span.dart";
diff --git a/pkg/source_maps/lib/span.dart b/pkg/source_maps/lib/span.dart
new file mode 100644
index 0000000..1982994
--- /dev/null
+++ b/pkg/source_maps/lib/span.dart
@@ -0,0 +1,330 @@
+// 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.
+
+/// Dart classes representing the souce spans and source files.
+library source_maps.span;
+
+import 'dart:utf' show stringToCodepoints, codepointsToString;
+import 'dart:math' show min;
+
+import 'src/utils.dart';
+
+/// A simple class that describe a segment of source text.
+abstract class Span implements Comparable {
+  /// The start location of this span.
+  final Location start;
+
+  /// The end location of this span, exclusive.
+  final Location end;
+
+  /// Url of the source (typically a file) containing this span.
+  String get sourceUrl => start.sourceUrl;
+
+  /// The length of this span, in characters.
+  int get length => end.offset - start.offset;
+
+  /// The source text for this span, if available.
+  String get text;
+
+  /// Whether [text] corresponds to an identifier symbol.
+  final bool isIdentifier;
+
+  Span(this.start, this.end, bool isIdentifier)
+      : isIdentifier = isIdentifier != null ? isIdentifier : false {
+    _checkRange();
+  }
+
+  /// Creates a new span that is the union of two existing spans [start] and
+  /// [end]. Note that the resulting span might contain some positions that were
+  /// not in either of the original spans if [start] and [end] are disjoint.
+  Span.union(Span start, Span end)
+      : start = start.start, end = end.end, isIdentifier = false {
+    _checkRange();
+  }
+
+  void _checkRange() {
+    if (start.offset < 0) throw new ArgumentError('start $start must be >= 0');
+    if (end.offset < start.offset) {
+      throw new ArgumentError('end $end must be >= start $start');
+    }
+  }
+
+  /// Compares two spans. If the spans are not in the same source, this method
+  /// generates an error.
+  int compareTo(Span other) {
+    int d = start.compareTo(other.start);
+    return d == 0 ? end.compareTo(other.end) : d;
+  }
+
+  /// Gets the location in standard printed form `filename:line:column`, where
+  /// line and column are adjusted by 1 to match the convention in editors.
+  String get formatLocation => start.formatString;
+
+  String getLocationMessage(String message,
+      {bool useColors: false, String color}) {
+    return '$formatLocation: $message';
+  }
+
+  bool operator ==(Span other) =>
+    sourceUrl == other.sourceUrl && start == other.start && end == other.end;
+
+  String toString() => '<$runtimeType: $start $end $formatLocation $text>';
+}
+
+/// A location in the source text
+abstract class Location implements Comparable {
+  /// Url of the source containing this span.
+  String get sourceUrl;
+
+  /// The offset of this location, 0-based.
+  final int offset;
+
+  /// The 0-based line in the source of this location.
+  int get line;
+
+  /// The 0-based column in the source of this location.
+  int get column;
+
+  Location(this.offset);
+
+  /// Compares two locations. If the locations are not in the same source, this
+  /// method generates an error.
+  int compareTo(Location other) {
+    if (sourceUrl != other.sourceUrl) {
+      throw new ArgumentError('can only compare locations of the same source');
+    }
+    return offset - other.offset;
+  }
+
+  String toString() => '(Location $offset)';
+  String get formatString => '$sourceUrl:${line + 1}:${column + 1}';
+}
+
+/// Implementation of [Location] with fixed values given at allocation time.
+class FixedLocation extends Location {
+  final String sourceUrl;
+  final int line;
+  final int column;
+
+  FixedLocation(int offset, this.sourceUrl, this.line, this.column)
+      : super(offset);
+}
+
+/// Implementation of [Span] where all the values are given at allocation time.
+class FixedSpan extends Span {
+  /// The source text for this span, if available.
+  final String text;
+
+  /// Creates a span which starts and end in the same line.
+  FixedSpan(String sourceUrl, int start, int line, int column,
+            {String text: '', bool isIdentifier: false})
+      : text = text, super(new FixedLocation(start, sourceUrl, line, column),
+            new FixedLocation(start + text.length, sourceUrl, line,
+                column + text.length),
+            isIdentifier);
+}
+
+/// [Location] with values computed from an underling [SourceFile].
+class FileLocation extends Location {
+  /// The source file containing this location.
+  final SourceFile file;
+
+  String get sourceUrl => file.url;
+  int get line => file.getLine(offset);
+  int get column => file.getColumn(line, offset);
+
+  FileLocation(this.file, int offset): super(offset);
+}
+
+/// [Span] where values are computed from an underling [SourceFile].
+class FileSpan extends Span {
+  /// The source file containing this span.
+  final SourceFile file;
+
+  /// The source text for this span, if available.
+  String get text => file.getText(start.offset, end.offset);
+
+  factory FileSpan(SourceFile file, int start,
+      [int end, bool isIdentifier = false]) {
+    var startLoc = new FileLocation(file, start);
+    var endLoc = end == null ? startLoc : new FileLocation(file, end);
+    return new FileSpan.locations(startLoc, endLoc, isIdentifier);
+  }
+
+  FileSpan.locations(FileLocation start, FileLocation end,
+      bool isIdentifier)
+      : file = start.file, super(start, end, isIdentifier);
+
+  /// Creates a new span that is the union of two existing spans [start] and
+  /// [end]. Note that the resulting span might contain some positions that were
+  /// not in either of the original spans if [start] and [end] are disjoint.
+  FileSpan.union(FileSpan start, FileSpan end)
+      : file = start.file, super.union(start, end) {
+    if (start.file != end.file) {
+      throw new ArgumentError('start and end must be from the same file');
+    }
+  }
+
+  String getLocationMessage(String message,
+      {bool useColors: false, String color}) {
+    return file.getLocationMessage(message, start.offset, end.offset,
+        useColors: useColors, color: color);
+  }
+}
+
+// Constants to determine end-of-lines.
+const int _LF = 10;
+const int _CR = 13;
+
+// Color constants used for generating messages.
+const String _RED_COLOR = '\u001b[31m';
+const String _NO_COLOR = '\u001b[0m';
+
+/// Stores information about a source file, to permit computation of the line
+/// and column. Also contains a nice default error message highlighting the code
+/// location.
+class SourceFile {
+  /// Url where the source file is located.
+  final String url;
+  final List<int> _lineStarts;
+  final List<int> _decodedChars;
+
+  SourceFile(this.url, this._lineStarts, this._decodedChars);
+
+  SourceFile.text(this.url, String text)
+      : _lineStarts = <int>[0],
+        _decodedChars = stringToCodepoints(text) {
+    for (int i = 0; i < _decodedChars.length; i++) {
+      var c = _decodedChars[i];
+      if (c == _CR) {
+        // Return not followed by newline is treated as a newline
+        int j = i + 1;
+        if (j >= _decodedChars.length || _decodedChars[j] != _LF) {
+          c = _LF;
+        }
+      }
+      if (c == _LF) _lineStarts.add(i + 1);
+    }
+  }
+
+  /// Returns a span in this [SourceFile] with the given offsets.
+  Span span(int start, [int end, bool isIdentifier = false]) =>
+      new FileSpan(this, start, end, isIdentifier);
+
+  /// Returns a location in this [SourceFile] with the given offset.
+  Location location(int offset) => new FileLocation(this, offset);
+
+  /// Gets the 0-based line corresponding to an offset.
+  int getLine(int offset) {
+    return binarySearch(_lineStarts, (o) => o > offset) - 1;
+  }
+
+  /// Gets the 0-based column corresponding to an offset.
+  int getColumn(int line, int offset) {
+    return offset - _lineStarts[line];
+  }
+
+  /// Get the offset for a given line and column
+  int getOffset(int line, int column) {
+    return _lineStarts[min(line, _lineStarts.length - 1)] + column;
+  }
+
+  /// Gets the text at the given offsets.
+  String getText(int start, [int end]) {
+    return codepointsToString(_decodedChars.sublist(start, end));
+  }
+
+  /// Create a pretty string representation from a span.
+  String getLocationMessage(String message, int start, int end,
+      {bool useColors: false, String color}) {
+    // TODO(jmesserly): it would be more useful to pass in an object that
+    // controls how the errors are printed. This method is a bit too smart.
+    var line = getLine(start);
+    var column = getColumn(line, start);
+
+    var src = url == null ? '' : url;
+    var msg = '$src:${line + 1}:${column + 1}: $message';
+
+    if (_decodedChars == null) {
+      // We don't have any text to include, so exit.
+      return msg;
+    }
+
+    var buf = new StringBuffer(msg);
+    buf.write('\n');
+    var textLine;
+
+    // +1 for 0-indexing, +1 again to avoid the last line
+    if ((line + 2) < _lineStarts.length) {
+      textLine = getText(_lineStarts[line], _lineStarts[line + 1]);
+    } else {
+      textLine = getText(_lineStarts[line]);
+      textLine = '$textLine\n';
+    }
+
+    int toColumn = min(column + end - start, textLine.length);
+    if (useColors) {
+      if (color == null) {
+        color = _RED_COLOR;
+      }
+      buf.write(textLine.substring(0, column));
+      buf.write(color);
+      buf.write(textLine.substring(column, toColumn));
+      buf.write(_NO_COLOR);
+      buf.write(textLine.substring(toColumn));
+    } else {
+      buf.write(textLine);
+    }
+
+    int i = 0;
+    for (; i < column; i++) {
+      buf.write(' ');
+    }
+
+    if (useColors) buf.write(color);
+    for (; i < toColumn; i++) {
+      buf.write('^');
+    }
+    if (useColors) buf.write(_NO_COLOR);
+    return buf.toString();
+  }
+}
+
+/// A convenience type to treat a code segment as if it were a separate
+/// [SourceFile]. A [SourceFileSegment] shifts all locations by an offset, which
+/// allows you to set source-map locations based on the locations relative to
+/// the start of the segment, but that get translated to absolute locations in
+/// the original source file.
+class SourceFileSegment extends SourceFile {
+  final int _baseOffset;
+  final int _baseLine;
+  final int _baseColumn;
+
+  SourceFileSegment(String url, String textSegment, Location startOffset)
+      : _baseOffset = startOffset.offset,
+        _baseLine = startOffset.line,
+        _baseColumn = startOffset.column,
+        super.text(url, textSegment);
+
+  Span span(int start, [int end, bool isIdentifier = false]) =>
+      super.span(start + _baseOffset,
+          end == null ? null : end + _baseOffset, isIdentifier);
+
+  Location location(int offset) => super.location(offset + _baseOffset);
+
+  int getLine(int offset) =>
+      super.getLine(offset - _baseOffset) + _baseLine;
+
+  int getColumn(int line, int offset) {
+    var col = super.getColumn(line - _baseLine, offset - _baseOffset);
+    return line == _baseLine ? col + _baseColumn : col;
+  }
+
+  int getOffset(int line, int column) =>
+      super.getOffset(line - _baseLine,
+         line == _baseLine ? column - _baseColumn : column) + _baseOffset;
+
+  String getText(int start, [int end]) =>
+      super.getText(start - _baseOffset, end - _baseOffset);
+}
diff --git a/pkg/source_maps/lib/src/utils.dart b/pkg/source_maps/lib/src/utils.dart
new file mode 100644
index 0000000..78f098e
--- /dev/null
+++ b/pkg/source_maps/lib/src/utils.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Utilities that shouldn't be in this package.
+library source_maps.utils;
+
+/// Find the first entry in a sorted [list] that matches a monotonic predicate.
+/// Given a result `n`, that all items before `n` will not match, `n` matches,
+/// and all items after `n` match too. The result is -1 when there are no
+/// items, 0 when all items match, and list.length when none does.
+// TODO(sigmund): remove this function after dartbug.com/5624 is fixed.
+int binarySearch(List list, bool matches(item)) {
+  if (list.length == 0) return -1;
+  if (matches(list.first)) return 0;
+  if (!matches(list.last)) return list.length;
+
+  int min = 0;
+  int max = list.length - 1;
+  while (min < max) {
+    var half = min + ((max - min) ~/ 2);
+    if (matches(list[half])) {
+      max = half;
+    } else {
+      min = half + 1;
+    }
+  }
+  return max;
+}
diff --git a/pkg/source_maps/lib/src/vlq.dart b/pkg/source_maps/lib/src/vlq.dart
new file mode 100644
index 0000000..e4ab4eb
--- /dev/null
+++ b/pkg/source_maps/lib/src/vlq.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.
+
+
+/// Utilities to encode and decode VLQ values used in source maps.
+///
+/// Sourcemaps are encoded with variable length numbers as base64 encoded
+/// strings with the least significant digit coming first. Each base64 digit
+/// encodes a 5-bit value (0-31) and a continuation bit. Signed values can be
+/// represented by using the least significant bit of the value as the sign bit.
+///
+/// For more details see the source map [version 3 documentation][spec].
+/// [spec]: https://docs.google.com/a/google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
+library source_maps.src.vlq;
+
+import 'dart:math';
+
+const int VLQ_BASE_SHIFT = 5;
+
+const int VLQ_BASE_MASK = (1 << 5) - 1;
+
+const int VLQ_CONTINUATION_BIT = 1 << 5;
+
+const int VLQ_CONTINUATION_MASK = 1 << 5;
+
+const String BASE64_DIGITS =
+    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+
+final Map<String, int> _digits = () {
+  var map = <String, int>{};
+  for (int i = 0; i < 64; i++) {
+    map[BASE64_DIGITS[i]] = i;
+  }
+  return map;
+}();
+
+final int MAX_INT32 = pow(2, 31) - 1;
+final int MIN_INT32 = -pow(2, 31);
+
+/// Creates the VLQ encoding of [value] as a sequence of characters
+Iterable<String> encodeVlq(int value) {
+  if (value < MIN_INT32 || value > MAX_INT32) {
+    throw new ArgumentError('expected 32 bit int, got: $value');
+  }
+  var res = <String>[];
+  int signBit = 0;
+  if (value < 0) {
+    signBit = 1;
+    value = -value;
+  }
+  value = (value << 1) | signBit;
+  do {
+    int digit = value & VLQ_BASE_MASK;
+    value >>= VLQ_BASE_SHIFT;
+    if (value > 0) {
+      digit |= VLQ_CONTINUATION_BIT;
+    }
+    res.add(BASE64_DIGITS[digit]);
+  } while (value > 0);
+  return res;
+}
+
+/// Decodes a value written as a sequence of VLQ characters. The first input
+/// character will be `chars.current` after calling `chars.moveNext` once. The
+/// iterator is advanced until a stop character is found (a character without
+/// the [VLQ_CONTINUATION_BIT]).
+int decodeVlq(Iterator<String> chars) {
+  int result = 0;
+  bool stop = false;
+  int shift = 0;
+  while (!stop) {
+    if (!chars.moveNext()) throw new StateError('incomplete VLQ value');
+    var char = chars.current;
+    if (!_digits.containsKey(char)) {
+      throw new FormatException('invalid character in VLQ encoding: $char');
+    }
+    var digit = _digits[char];
+    stop = (digit & VLQ_CONTINUATION_BIT) == 0;
+    digit &= VLQ_BASE_MASK;
+    result += (digit << shift);
+    shift += VLQ_BASE_SHIFT;
+  }
+
+  // Result uses the least significant bit as a sign bit. We convert it into a
+  // two-complement value. For example,
+  //   2 (10 binary) becomes 1
+  //   3 (11 binary) becomes -1
+  //   4 (100 binary) becomes 2
+  //   5 (101 binary) becomes -2
+  //   6 (110 binary) becomes 3
+  //   7 (111 binary) becomes -3
+  bool negate = (result & 1) == 1;
+  result = result >> 1;
+  result = negate ? -result : result;
+
+  // TODO(sigmund): can we detect this earlier?
+  if (result < MIN_INT32 || result > MAX_INT32) {
+    throw new FormatException(
+        'expected an encoded 32 bit int, but we got: $result');
+  }
+  return result;
+}
diff --git a/pkg/source_maps/pubspec.yaml b/pkg/source_maps/pubspec.yaml
new file mode 100644
index 0000000..a559b58
--- /dev/null
+++ b/pkg/source_maps/pubspec.yaml
@@ -0,0 +1,6 @@
+name: source_maps
+author: "Dart Team <misc@dartlang.org>"
+homepage: https://github.com/dart-lang/source-maps
+description: Library to programmatically manipulate source map files.
+dev_dependencies:
+  unittest: any
diff --git a/pkg/source_maps/test/builder_test.dart b/pkg/source_maps/test/builder_test.dart
new file mode 100644
index 0000000..7bf2ee4
--- /dev/null
+++ b/pkg/source_maps/test/builder_test.dart
@@ -0,0 +1,32 @@
+// 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.source_maps_test;
+
+import 'dart:json' as json;
+import 'package:unittest/unittest.dart';
+import 'package:source_maps/source_maps.dart';
+import 'common.dart';
+
+main() {
+  test('builder - with span', () {
+    var map = (new SourceMapBuilder()
+        ..addSpan(inputVar1, outputVar1)
+        ..addSpan(inputFunction, outputFunction)
+        ..addSpan(inputVar2, outputVar2)
+        ..addSpan(inputExpr, outputExpr))
+        .build(output.url);
+    expect(map, equals(EXPECTED_MAP));
+  });
+
+  test('builder - with location', () {
+    var str = (new SourceMapBuilder()
+        ..addLocation(inputVar1.start, outputVar1.start, 'longVar1')
+        ..addLocation(inputFunction.start, outputFunction.start, 'longName')
+        ..addLocation(inputVar2.start, outputVar2.start, 'longVar2')
+        ..addLocation(inputExpr.start, outputExpr.start, null))
+        .toJson(output.url);
+    expect(str, json.stringify(EXPECTED_MAP));
+  });
+}
diff --git a/pkg/source_maps/test/common.dart b/pkg/source_maps/test/common.dart
new file mode 100644
index 0000000..661979b
--- /dev/null
+++ b/pkg/source_maps/test/common.dart
@@ -0,0 +1,97 @@
+// 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.
+
+/// Common input/output used by builder, parser and end2end tests
+library test.common;
+
+import 'package:source_maps/source_maps.dart';
+import 'package:unittest/unittest.dart';
+
+/// Content of the source file
+const String INPUT = '''
+/** this is a comment. */
+int longVar1 = 3;
+
+// this is a comment too
+int longName(int longVar2) {
+  return longVar1 + longVar2;
+}
+''';
+var input = new SourceFile.text('input.dart', INPUT);
+
+/// A span in the input file
+Span ispan(int start, int end, [bool isIdentifier = false]) =>
+    new FileSpan(input, start, end, isIdentifier);
+
+Span inputVar1 = ispan(30, 38, true);
+Span inputFunction = ispan(74, 82, true);
+Span inputVar2 = ispan(87, 95, true);
+Span inputExpr = ispan(108, 127);
+
+/// Content of the target file
+const String OUTPUT = '''
+var x = 3;
+f(y) => x + y;
+''';
+var output = new SourceFile.text('output.dart', OUTPUT);
+
+/// A span in the output file
+Span ospan(int start, int end, [bool isIdentifier = false]) =>
+    new FileSpan(output, start, end, isIdentifier);
+
+Span outputVar1 = ospan(4, 5, true);
+Span outputFunction = ospan(11, 12, true);
+Span outputVar2 = ospan(13, 14, true);
+Span outputExpr = ospan(19, 24);
+
+/// Expected output mapping when recording the following four mappings:
+///      inputVar1       <=   outputVar1
+///      inputFunction   <=   outputFunction
+///      inputVar2       <=   outputVar2
+///      inputExpr       <=   outputExpr
+///
+/// This mapping is stored in the tests so we can independently test the builder
+/// and parser algorithms without relying entirely on end2end tests.
+const Map<String, dynamic> EXPECTED_MAP = const {
+    'version': 3,
+    'sourceRoot': '',
+    'sources': const ['input.dart'],
+    'names': const ['longVar1','longName','longVar2'],
+    'mappings': 'IACIA;AAGAC,EAAaC,MACR',
+    'file': 'output.dart'
+};
+
+check(Span outputSpan, Mapping mapping, Span inputSpan, bool realOffsets) {
+  var line = outputSpan.start.line;
+  var column = outputSpan.start.column;
+  var files = realOffsets ? {'input.dart': input} : null; 
+  var span = mapping.spanFor(line, column, files: files);
+  var span2 = mapping.spanForLocation(outputSpan.start, files: files);
+
+  // Both mapping APIs are equivalent.
+  expect(span.start.offset, span2.start.offset);
+  expect(span.start.line, span2.start.line);
+  expect(span.start.column, span2.start.column);
+  expect(span.end.offset, span2.end.offset);
+  expect(span.end.line, span2.end.line);
+  expect(span.end.column, span2.end.column);
+
+  // Mapping matches our input location (modulo using real offsets)
+  expect(span.start.line, inputSpan.start.line);
+  expect(span.start.column, inputSpan.start.column);
+  expect(span.sourceUrl, inputSpan.sourceUrl);
+  expect(span.start.offset, realOffsets ? inputSpan.start.offset : 0);
+
+  // Mapping includes the identifier, if any
+  if (inputSpan.isIdentifier) {
+    expect(span.end.line, inputSpan.end.line);
+    expect(span.end.column, inputSpan.end.column);
+    expect(span.end.offset, span.start.offset + inputSpan.text.length);
+    if (realOffsets) expect(span.end.offset, inputSpan.end.offset);
+  } else {
+    expect(span.end.offset, span.start.offset);
+    expect(span.end.line, span.start.line);
+    expect(span.end.column, span.start.column);
+  }
+}
diff --git a/pkg/source_maps/test/end2end_test.dart b/pkg/source_maps/test/end2end_test.dart
new file mode 100644
index 0000000..5ea958a
--- /dev/null
+++ b/pkg/source_maps/test/end2end_test.dart
@@ -0,0 +1,106 @@
+// 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.end2end_test;
+
+import 'package:unittest/unittest.dart';
+import 'package:source_maps/source_maps.dart';
+import 'common.dart';
+
+main() {
+  test('end-to-end setup', () {
+    expect(inputVar1.text, 'longVar1');
+    expect(inputFunction.text, 'longName');
+    expect(inputVar2.text, 'longVar2');
+    expect(inputExpr.text, 'longVar1 + longVar2');
+
+    expect(outputVar1.text, 'x');
+    expect(outputFunction.text, 'f');
+    expect(outputVar2.text, 'y');
+    expect(outputExpr.text, 'x + y');
+  });
+
+  test('build + parse', () {
+    var map = (new SourceMapBuilder()
+        ..addSpan(inputVar1, outputVar1)
+        ..addSpan(inputFunction, outputFunction)
+        ..addSpan(inputVar2, outputVar2)
+        ..addSpan(inputExpr, outputExpr))
+        .build(output.url);
+    var mapping = parseJson(map);
+    check(outputVar1, mapping, inputVar1, false);
+    check(outputVar2, mapping, inputVar2, false);
+    check(outputFunction, mapping, inputFunction, false);
+    check(outputExpr, mapping, inputExpr, false);
+  });
+
+  test('build + parse with file', () {
+    var json = (new SourceMapBuilder()
+        ..addSpan(inputVar1, outputVar1)
+        ..addSpan(inputFunction, outputFunction)
+        ..addSpan(inputVar2, outputVar2)
+        ..addSpan(inputExpr, outputExpr))
+        .toJson(output.url);
+    var mapping = parse(json);
+    check(outputVar1, mapping, inputVar1, true);
+    check(outputVar2, mapping, inputVar2, true);
+    check(outputFunction, mapping, inputFunction, true);
+    check(outputExpr, mapping, inputExpr, true);
+  });
+
+  test('printer projecting marks + parse', () {
+    var out = INPUT.replaceAll('long', '_s');
+    var file = new SourceFile.text('output2.dart', out);
+    var printer = new Printer('output2.dart');
+    printer.mark(ispan(0, 0));
+
+    bool first = true;
+    var segments = INPUT.split('long');
+    expect(segments.length, 6);
+    printer.add(segments[0], projectMarks: true);
+    printer.mark(inputVar1);
+    printer.add('_s');
+    printer.add(segments[1], projectMarks: true);
+    printer.mark(inputFunction);
+    printer.add('_s');
+    printer.add(segments[2], projectMarks: true);
+    printer.mark(inputVar2);
+    printer.add('_s');
+    printer.add(segments[3], projectMarks: true);
+    printer.mark(inputExpr);
+    printer.add('_s');
+    printer.add(segments[4], projectMarks: true);
+    printer.add('_s');
+    printer.add(segments[5], projectMarks: true);
+
+    expect(printer.text, out);
+
+    var mapping = parse(printer.map);
+    checkHelper(Span inputSpan, int adjustment) {
+      var start = inputSpan.start.offset - adjustment;
+      var end = (inputSpan.end.offset - adjustment) - 2;
+      var span = new FileSpan(file, start, end, inputSpan.isIdentifier);
+      check(span, mapping, inputSpan, true);
+    }
+
+    checkHelper(inputVar1, 0);
+    checkHelper(inputFunction, 2);
+    checkHelper(inputVar2, 4);
+    checkHelper(inputExpr, 6);
+
+    // We projected correctly lines that have no mappings
+    check(new FileSpan(file, 66, 66, false), mapping, ispan(45, 45), true);
+    check(new FileSpan(file, 63, 64, false), mapping, ispan(45, 45), true);
+    check(new FileSpan(file, 68, 68, false), mapping, ispan(70, 70), true);
+    check(new FileSpan(file, 71, 71, false), mapping, ispan(70, 70), true);
+
+    // Start of the last line
+    var oOffset = out.length - 2;
+    var iOffset = INPUT.length - 2;
+    check(new FileSpan(file, oOffset, oOffset, false), mapping,
+        ispan(iOffset, iOffset), true);
+    check(new FileSpan(file, oOffset + 1, oOffset + 1, false), mapping,
+        ispan(iOffset, iOffset), true);
+  });
+}
diff --git a/pkg/source_maps/test/parser_test.dart b/pkg/source_maps/test/parser_test.dart
new file mode 100644
index 0000000..1c32cbd
--- /dev/null
+++ b/pkg/source_maps/test/parser_test.dart
@@ -0,0 +1,36 @@
+// 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.parser_test;
+
+import 'dart:json' as json;
+import 'package:unittest/unittest.dart';
+import 'package:source_maps/source_maps.dart';
+import 'common.dart';
+
+main() {
+  test('parse', () {
+    var mapping = parseJson(EXPECTED_MAP);
+    check(outputVar1, mapping, inputVar1, false);
+    check(outputVar2, mapping, inputVar2, false);
+    check(outputFunction, mapping, inputFunction, false);
+    check(outputExpr, mapping, inputExpr, false);
+  });
+
+  test('parse + json', () {
+    var mapping = parse(json.stringify(EXPECTED_MAP));
+    check(outputVar1, mapping, inputVar1, false);
+    check(outputVar2, mapping, inputVar2, false);
+    check(outputFunction, mapping, inputFunction, false);
+    check(outputExpr, mapping, inputExpr, false);
+  });
+
+  test('parse with file', () {
+    var mapping = parseJson(EXPECTED_MAP);
+    check(outputVar1, mapping, inputVar1, true);
+    check(outputVar2, mapping, inputVar2, true);
+    check(outputFunction, mapping, inputFunction, true);
+    check(outputExpr, mapping, inputExpr, true);
+  });
+}
diff --git a/pkg/source_maps/test/printer_test.dart b/pkg/source_maps/test/printer_test.dart
new file mode 100644
index 0000000..d038ad5
--- /dev/null
+++ b/pkg/source_maps/test/printer_test.dart
@@ -0,0 +1,82 @@
+// 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.printer_test;
+
+import 'dart:json' as json;
+import 'package:unittest/unittest.dart';
+import 'package:source_maps/printer.dart';
+import 'package:source_maps/span.dart';
+import 'common.dart';
+
+main() {
+  test('printer', () {
+    var printer = new Printer('output.dart');
+    printer..add('var ')
+           ..mark(inputVar1)
+           ..add('x = 3;\n')
+           ..mark(inputFunction)
+           ..add('f(')
+           ..mark(inputVar2)
+           ..add('y) => ')
+           ..mark(inputExpr)
+           ..add('x + y;\n');
+    expect(printer.text, OUTPUT);
+    expect(printer.map, json.stringify(EXPECTED_MAP));
+  });
+
+  test('printer projecting marks', () {
+    var out = INPUT.replaceAll('long', '_s');
+    var printer = new Printer('output2.dart');
+
+    var segments = INPUT.split('long');
+    expect(segments.length, 6);
+    printer..mark(ispan(0, 0))
+        ..add(segments[0], projectMarks: true)
+        ..mark(inputVar1)
+        ..add('_s')
+        ..add(segments[1], projectMarks: true)
+        ..mark(inputFunction)
+        ..add('_s')
+        ..add(segments[2], projectMarks: true)
+        ..mark(inputVar2)
+        ..add('_s')
+        ..add(segments[3], projectMarks: true)
+        ..mark(inputExpr)
+        ..add('_s')
+        ..add(segments[4], projectMarks: true)
+        ..add('_s')
+        ..add(segments[5], projectMarks: true);
+
+    expect(printer.text, out);
+    // 8 new lines in the source map:
+    expect(printer.map.split(';').length, 8);
+
+    asFixed(Span s) => new FixedSpan(s.sourceUrl,
+        s.start.offset, s.start.line, s.start.column,
+        text: s.text, isIdentifier: s.isIdentifier);
+
+    // The result is the same if we use fixed positions
+    var printer2 = new Printer('output2.dart');
+    printer2..mark(new FixedSpan('input.dart', 0, 0, 0))
+        ..add(segments[0], projectMarks: true)
+        ..mark(asFixed(inputVar1))
+        ..add('_s')
+        ..add(segments[1], projectMarks: true)
+        ..mark(asFixed(inputFunction))
+        ..add('_s')
+        ..add(segments[2], projectMarks: true)
+        ..mark(asFixed(inputVar2))
+        ..add('_s')
+        ..add(segments[3], projectMarks: true)
+        ..mark(asFixed(inputExpr))
+        ..add('_s')
+        ..add(segments[4], projectMarks: true)
+        ..add('_s')
+        ..add(segments[5], projectMarks: true);
+
+    expect(printer2.text, out);
+    expect(printer2.map, printer.map);
+  });
+}
diff --git a/pkg/source_maps/test/run.dart b/pkg/source_maps/test/run.dart
new file mode 100755
index 0000000..9a19785
--- /dev/null
+++ b/pkg/source_maps/test/run.dart
@@ -0,0 +1,38 @@
+#!/usr/bin/env dart
+// 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.run;
+
+import 'package:unittest/compact_vm_config.dart';
+import 'package:unittest/unittest.dart';
+import 'dart:io' show Options;
+
+import 'builder_test.dart' as builder_test;
+import 'end2end_test.dart' as end2end_test;
+import 'parser_test.dart' as parser_test;
+import 'printer_test.dart' as printer_test;
+import 'span_test.dart' as span_test;
+import 'utils_test.dart' as utils_test;
+import 'vlq_test.dart' as vlq_test;
+
+main() {
+  var args = new Options().arguments;
+  var pattern = new RegExp(args.length > 0 ? args[0] : '.');
+  useCompactVMConfiguration();
+
+  void addGroup(testFile, testMain) {
+    if (pattern.hasMatch(testFile)) {
+      group(testFile.replaceAll('_test.dart', ':'), testMain);
+    }
+  }
+
+  addGroup('builder_test.dart', builder_test.main);
+  addGroup('end2end_test.dart', end2end_test.main);
+  addGroup('parser_test.dart', parser_test.main);
+  addGroup('printer_test.dart', printer_test.main);
+  addGroup('span_test.dart', span_test.main);
+  addGroup('utils_test.dart', utils_test.main);
+  addGroup('vlq_test.dart', vlq_test.main);
+}
diff --git a/pkg/source_maps/test/span_test.dart b/pkg/source_maps/test/span_test.dart
new file mode 100644
index 0000000..8f61b58
--- /dev/null
+++ b/pkg/source_maps/test/span_test.dart
@@ -0,0 +1,215 @@
+// 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.span_test;
+
+import 'package:unittest/unittest.dart';
+import 'package:source_maps/span.dart';
+
+const String TEST_FILE = '''
++23456789_
+ +       _123456789_123456789_123456789_123456789_123456789_123456789_123456789_
+  +                _123456789_1
+123+56789_123456789_1234567
+1234+6789_1234
+12345+789_123456789_12345
+123456+89_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+1234567+9_123456789_123456789_123456789_123456789_123456789_123456789_123
+12345678+_123456789_123456789_123456789_123456789_1
+123456789+123456789_123456789_12345678
+123456789_+23456789_123456789_123456789_123
+123456789_1+3456789_123456789
+''';
+
+List<int> newLines = TEST_FILE.split('\n').map((s) => s.length).toList();
+
+main() {
+  var file = new SourceFile.text('file', TEST_FILE);
+  span(int start, int end) => file.span(start, end);
+  loc(int offset) => file.location(offset);
+
+  test('validate test input', () {
+    expect(newLines,
+      const [10, 80, 31, 27, 14, 25, 79, 73, 51, 38, 43, 29, 0]);
+  });
+
+  test('get line and column', () {
+    line(int n) => file.getLine(n);
+    col(int n) => file.getColumn(file.getLine(n), n);
+
+    expect(line(8), 0);
+    expect(line(10), 0);
+    expect(line(11), 1);
+    expect(line(12), 1);
+    expect(line(91), 1);
+    expect(line(92), 2);
+    expect(line(93), 2);
+    expect(col(11), 0);
+    expect(col(12), 1);
+    expect(col(91), 80);
+    expect(col(92), 0);
+    expect(col(93), 1);
+
+    int j = 0;
+    int lineOffset = 0;
+    for (int i = 0; i < TEST_FILE.length; i++) {
+      if (i > lineOffset + newLines[j]) {
+        lineOffset += newLines[j] + 1;
+        j++;
+      }
+      expect(line(i), j, reason: 'position: $i');
+      expect(col(i), i - lineOffset, reason: 'position: $i');
+    }
+  });
+
+  test('get text', () {
+    // fifth line (including 4 new lines), columns 2 .. 11
+    var line = 10 + 80 + 31 + 27 + 4;
+    expect(file.getText(line + 2, line + 11), '34+6789_1');
+  });
+
+  test('get location message', () {
+    // fifth line (including 4 new lines), columns 2 .. 11
+    var line = 10 + 80 + 31 + 27 + 4;
+    expect(file.getLocationMessage('the message', line + 2, line + 11),
+        'file:5:3: the message\n'
+        '1234+6789_1234\n'
+        '  ^^^^^^^^^');
+  });
+
+  test('get location message - no file url', () {
+    var line = 10 + 80 + 31 + 27 + 4;
+    expect(new SourceFile.text(null, TEST_FILE).getLocationMessage(
+        'the message', line + 2, line + 11),
+        ':5:3: the message\n'
+        '1234+6789_1234\n'
+        '  ^^^^^^^^^');
+  });
+
+  test('location getters', () {
+    expect(loc(8).line, 0);
+    expect(loc(8).column, 8);
+    expect(loc(9).line, 0);
+    expect(loc(9).column, 9);
+    expect(loc(8).formatString, 'file:1:9');
+    expect(loc(12).line, 1);
+    expect(loc(12).column, 1);
+    expect(loc(95).line, 2);
+    expect(loc(95).column, 3);
+  });
+
+  test('location compare', () {
+    var list = [9, 8, 11, 14, 6, 6, 1, 1].map((n) => loc(n)).toList();
+    list.sort();
+    var lastOffset = 0;
+    for (var location in list) {
+      expect(location.offset, greaterThanOrEqualTo(lastOffset));
+      lastOffset = location.offset;
+    }
+  });
+
+  test('span getters', () {
+    expect(span(8, 9).start.line, 0);
+    expect(span(8, 9).start.column, 8);
+    expect(span(8, 9).end.line, 0);
+    expect(span(8, 9).end.column, 9);
+    expect(span(8, 9).text, '9');
+    expect(span(8, 9).isIdentifier, false);
+    expect(span(8, 9).formatLocation, 'file:1:9');
+
+    var line = 10 + 80 + 31 + 27 + 4;
+    expect(span(line + 2, line + 11).getLocationMessage('the message'),
+        'file:5:3: the message\n'
+        '1234+6789_1234\n'
+        '  ^^^^^^^^^');
+
+    expect(span(12, 95).start.line, 1);
+    expect(span(12, 95).start.column, 1);
+    expect(span(12, 95).end.line, 2);
+    expect(span(12, 95).end.column, 3);
+    expect(span(12, 95).text,
+        '+       _123456789_123456789_123456789_123456789_123456789_1234567'
+        '89_123456789_\n  +');
+    expect(span(12, 95).formatLocation, 'file:2:2');
+  });
+
+  test('span union', () {
+    var union = new FileSpan.union(span(8, 9), span(12, 95));
+    expect(union.start.offset, 8);
+    expect(union.start.line, 0);
+    expect(union.start.column, 8);
+    expect(union.end.offset, 95);
+    expect(union.end.line, 2);
+    expect(union.end.column, 3);
+    expect(union.text,
+        '9_\n'
+        ' +       _123456789_123456789_123456789_123456789_123456789_'
+        '123456789_123456789_\n  +');
+    expect(union.formatLocation, 'file:1:9');
+  });
+
+  test('span compare', () {
+    var list = [span(9, 10), span(8, 9), span(11, 12), span(14, 19),
+        span(6, 12), span(6, 8), span(1, 9), span(1, 2)];
+    list.sort();
+    var lastStart = 0;
+    var lastEnd = 0;
+    for (var span in list) {
+      expect(span.start.offset, greaterThanOrEqualTo(lastStart));
+      if (span.start.offset == lastStart) {
+        expect(span.end.offset, greaterThanOrEqualTo(lastEnd));
+      }
+      lastStart = span.start.offset;
+      lastEnd = span.end.offset;
+    }
+  });
+
+  test('file segment', () {
+    var segment = new SourceFileSegment('file',
+        TEST_FILE.substring(12), loc(12));
+    sline(int n) => segment.getLine(n);
+    scol(int n) => segment.getColumn(segment.getLine(n), n);
+
+    line(int n) => file.getLine(n);
+    col(int n) => file.getColumn(file.getLine(n), n);
+
+    int j = 0;
+    int lineOffset = 0;
+    for (int i = 12; i < TEST_FILE.length; i++) {
+      if (i > lineOffset + newLines[j]) {
+        lineOffset += newLines[j] + 1;
+        j++;
+      }
+      expect(segment.location(i - 12).offset, i);
+      expect(segment.location(i - 12).line, line(i));
+      expect(segment.location(i - 12).column, col(i));
+      expect(segment.span(i - 12).start.offset, i);
+      expect(segment.span(i - 12).start.line, line(i));
+      expect(segment.span(i - 12).start.column, col(i));
+
+      expect(sline(i), line(i));
+      expect(scol(i), col(i));
+    }
+  });
+
+  test('span isIdentifier defaults to false', () {
+    var start = new TestLocation(0);
+    var end = new TestLocation(1);
+    expect(new TestSpan(start, end).isIdentifier, false);
+    expect(file.span(8, 9, null).isIdentifier, false);
+    expect(new FixedSpan('', 8, 1, 8, isIdentifier: null).isIdentifier, false);
+  });
+}
+
+class TestSpan extends Span {
+  TestSpan(Location start, Location end) : super(start, end, null);
+  get text => null;
+}
+
+class TestLocation extends Location {
+  String get sourceUrl => '';
+  TestLocation(int offset) : super(offset);
+  get line => 0;
+  get column => 0;
+}
diff --git a/pkg/source_maps/test/utils_test.dart b/pkg/source_maps/test/utils_test.dart
new file mode 100644
index 0000000..79a7de7
--- /dev/null
+++ b/pkg/source_maps/test/utils_test.dart
@@ -0,0 +1,54 @@
+// 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.
+
+/// Tests for the binary search utility algorithm.
+library test.utils_test;
+
+import 'package:unittest/unittest.dart';
+import 'package:source_maps/src/utils.dart';
+
+main() {
+  group('binary search', () {
+    test('empty', () {
+      expect(binarySearch([], (x) => true), -1);
+    });
+
+    test('single element', () {
+      expect(binarySearch([1], (x) => true), 0);
+      expect(binarySearch([1], (x) => false), 1);
+    });
+
+    test('no matches', () {
+      var list = [1, 2, 3, 4, 5, 6, 7];
+      expect(binarySearch(list, (x) => false), list.length);
+    });
+
+    test('all match', () {
+      var list = [1, 2, 3, 4, 5, 6, 7];
+      expect(binarySearch(list, (x) => true), 0);
+    });
+
+    test('compare with linear search', () {
+      for (int size = 0; size < 100; size++) {
+        var list = [];
+        for (int i = 0; i < size; i++) {
+          list.add(i);
+        }
+        for (int pos = 0; pos <= size; pos++) {
+          expect(binarySearch(list, (x) => x >= pos),
+              _linearSearch(list, (x) => x >= pos));
+        }
+      }
+    });
+  });
+}
+
+_linearSearch(list, predicate) {
+  if (list.length == 0) return -1;
+  for (int i = 0; i < list.length; i++) {
+    if (predicate(list[i])) return i;
+  }
+  return list.length;
+}
+
diff --git a/pkg/source_maps/test/vlq_test.dart b/pkg/source_maps/test/vlq_test.dart
new file mode 100644
index 0000000..0abdc47
--- /dev/null
+++ b/pkg/source_maps/test/vlq_test.dart
@@ -0,0 +1,59 @@
+// 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.vlq_test;
+
+import 'dart:math';
+import 'package:unittest/unittest.dart';
+import 'package:source_maps/src/vlq.dart';
+
+main() {
+  test('encode and decode - simple values', () {
+    expect(encodeVlq(1).join(''), 'C');
+    expect(encodeVlq(2).join(''), 'E');
+    expect(encodeVlq(3).join(''), 'G');
+    expect(encodeVlq(100).join(''), 'oG');
+    expect(decodeVlq('C'.split('').iterator), 1);
+    expect(decodeVlq('E'.split('').iterator), 2);
+    expect(decodeVlq('G'.split('').iterator), 3);
+    expect(decodeVlq('oG'.split('').iterator), 100);
+  });
+
+  test('encode and decode', () {
+    for (int i = -10000; i < 10000; i++) {
+      _checkEncodeDecode(i);
+    }
+  });
+
+  test('only 32-bit ints allowed', () {
+    var max_int = pow(2, 31) - 1;
+    var min_int = -pow(2, 31);
+    _checkEncodeDecode(max_int - 1);
+    _checkEncodeDecode(min_int + 1);
+    _checkEncodeDecode(max_int);
+    _checkEncodeDecode(min_int);
+
+    expect(encodeVlq(min_int).join(''), 'hgggggE');
+    expect(decodeVlq('hgggggE'.split('').iterator), min_int);
+
+    expect(() => encodeVlq(max_int + 1), throws);
+    expect(() => encodeVlq(max_int + 2), throws);
+    expect(() => encodeVlq(min_int - 1), throws);
+    expect(() => encodeVlq(min_int - 2), throws);
+
+
+    // if we allowed more than 32 bits, these would be the expected encodings
+    // for the large numbers above.
+    expect(() => decodeVlq('ggggggE'.split('').iterator), throws);
+    expect(() => decodeVlq('igggggE'.split('').iterator), throws);
+    expect(() => decodeVlq('jgggggE'.split('').iterator), throws);
+    expect(() => decodeVlq('lgggggE'.split('').iterator), throws);
+  });
+}
+
+_checkEncodeDecode(int value) {
+  var encoded = encodeVlq(value);
+  expect(decodeVlq(encoded.iterator), value);
+  expect(decodeVlq(encoded.join('').split('').iterator), value);
+}
diff --git a/pkg/unittest/lib/src/test_case.dart b/pkg/unittest/lib/src/test_case.dart
index 7eb835f..f8eb233 100644
--- a/pkg/unittest/lib/src/test_case.dart
+++ b/pkg/unittest/lib/src/test_case.dart
@@ -82,9 +82,8 @@
     var f = testFunction();
     --_callbackFunctionsOutstanding;
     if (f is Future) {
-      f.then((_) => _finishTest())
+      return f.then((_) => _finishTest())
        .catchError((e) => fail("${e.error}"));
-      return f;
     } else {
       _finishTest();
       return null;
diff --git a/pkg/unittest/pubspec.yaml b/pkg/unittest/pubspec.yaml
index 07be11a..f9051e3 100644
--- a/pkg/unittest/pubspec.yaml
+++ b/pkg/unittest/pubspec.yaml
@@ -5,6 +5,5 @@
 description: >
  A library for writing dart unit tests.
 dependencies:
-  meta:
-    sdk: meta
+  meta: any
 
diff --git a/pkg/unittest/test/unittest_test.dart b/pkg/unittest/test/unittest_test.dart
index c6ab7a0..e0127bd 100644
--- a/pkg/unittest/test/unittest_test.dart
+++ b/pkg/unittest/test/unittest_test.dart
@@ -19,8 +19,8 @@
 var actual; // actual test results (from buildStatusString in config.onDone)
 var _testconfig; // test configuration to capture onDone
 
-_defer(void fn()) {
-  return (new Future.immediate(null)).then((_) => guardAsync(fn));
+Future _defer(void fn()) {
+  return new Future.of(fn);
 }
 
 String buildStatusString(int passed, int failed, int errors,
@@ -154,80 +154,42 @@
       });
     } else if (testName == 'async setup/teardown test') {
       group('good setup/good teardown', () {
-        setUp(() { 
-          var completer = new Completer();
-          _defer(() {
-            completer.complete(0);
-          });
-          return completer.future;
+        setUp(() {
+          return new Future.immediate(0);
         });
         tearDown(() {
-          var completer = new Completer();
-          _defer(() {
-            completer.complete(0);
-          });
-          return completer.future;
+          return new Future.immediate(0);
         });
         test('foo1', (){});
       });
       group('good setup/bad teardown', () {
-        setUp(() { 
-          var completer = new Completer();
-          _defer(() {
-            completer.complete(0);
-          });
-          return completer.future;
+        setUp(() {
+          return new Future.immediate(0);
         });
         tearDown(() {
-          var completer = new Completer();
-          _defer(() {
-            //throw "Failed to complete tearDown";
-            completer.completeError(
-                new AsyncError("Failed to complete tearDown"));
-          });
-          return completer.future;
+          return new Future.immediateError("Failed to complete tearDown");
         });
         test('foo2', (){});
       });
       group('bad setup/good teardown', () {
-        setUp(() { 
-          var completer = new Completer();
-          _defer(() {
-            //throw "Failed to complete setUp";
-            completer.completeError(new AsyncError("Failed to complete setUp"));
-          });
-          return completer.future;
+        setUp(() {
+          return new Future.immediateError("Failed to complete setUp");
         });
         tearDown(() {
-          var completer = new Completer();
-          _defer(() {
-            completer.complete(0);
-          });
-          return completer.future;
+          return new Future.immediate(0);
         });
         test('foo3', (){});
       });
       group('bad setup/bad teardown', () {
-        setUp(() { 
-          var completer = new Completer();
-          _defer(() {
-            //throw "Failed to complete setUp";
-            completer.completeError(new AsyncError("Failed to complete setUp"));
-          });
-          return completer.future;
+        setUp(() {
+          return new Future.immediateError("Failed to complete setUp");
         });
         tearDown(() {
-          var completer = new Completer();
-          _defer(() {
-            //throw "Failed to complete tearDown";
-            completer.completeError(
-                new AsyncError("Failed to complete tearDown"));
-          });
-          return completer.future;
+          return new Future.immediateError("Failed to complete tearDown");
         });
         test('foo4', (){});
       });
-      // The next test is just to make sure we make steady progress 
+      // The next test is just to make sure we make steady progress
       // through the tests.
       test('post groups', () {});
     } else if (testName == 'test returning future') {
@@ -390,7 +352,7 @@
                  'been marked as pass.:testTwo:'),
     buildStatusString(2, 1, 0,
         'testOne::testTwo:Expected: false but: was <true>.:testThree'),
-    buildStatusString(2, 0, 3, 
+    buildStatusString(2, 0, 3,
         'good setup/good teardown foo1::'
         'good setup/bad teardown foo2:good setup/bad teardown '
         'foo2: Test teardown failed: Failed to complete tearDown:'
diff --git a/pkg/yaml/pubspec.yaml b/pkg/yaml/pubspec.yaml
index 7c944d2..4b17267 100644
--- a/pkg/yaml/pubspec.yaml
+++ b/pkg/yaml/pubspec.yaml
@@ -2,6 +2,5 @@
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: A parser for YAML.
-dependencies:
-  unittest:
-    sdk: unittest
+dev_dependencies:
+  unittest: any
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 0dbc958..33be02e 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -23,7 +23,7 @@
   V(Directory_CreateTemp, 1)                                                   \
   V(Directory_Delete, 2)                                                       \
   V(Directory_Rename, 2)                                                       \
-  V(Directory_List, 2)                                                         \
+  V(Directory_List, 3)                                                         \
   V(Directory_NewServicePort, 0)                                               \
   V(File_Open, 2)                                                              \
   V(File_Exists, 1)                                                            \
@@ -42,12 +42,14 @@
   V(File_Flush, 1)                                                             \
   V(File_Create, 1)                                                            \
   V(File_CreateLink, 2)                                                        \
+  V(File_LinkTarget, 1)                                                        \
   V(File_Delete, 1)                                                            \
   V(File_Directory, 1)                                                         \
   V(File_FullPath, 1)                                                          \
   V(File_OpenStdio, 1)                                                         \
   V(File_GetStdioHandleType, 1)                                                \
   V(File_GetType, 2)                                                           \
+  V(File_AreIdentical, 2)                                                      \
   V(File_NewServicePort, 0)                                                    \
   V(Logger_PrintString, 1)
 
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 9d2ac70..7dd8534 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -25,6 +25,7 @@
 
 const char* DartUtils::kIdFieldName = "_id";
 
+uint8_t DartUtils::magic_number[] = { 0xf5, 0xf5, 0xdc, 0xdc };
 
 static bool IsWindowsHost() {
 #if defined(TARGET_OS_WINDOWS)
@@ -187,31 +188,46 @@
 }
 
 
-Dart_Handle DartUtils::ReadStringFromFile(const char* filename) {
+static const uint8_t* ReadFile(const char* filename,
+                               intptr_t* file_len,
+                               const char** error_msg) {
   File* file = File::Open(filename, File::kRead);
   if (file == NULL) {
     const char* format = "Unable to open file: %s";
     intptr_t len = snprintf(NULL, 0, format, filename);
     // TODO(iposva): Allocate from the zone instead of leaking error string
     // here. On the other hand the binary is about the exit anyway.
-    char* error_msg = reinterpret_cast<char*>(malloc(len + 1));
-    snprintf(error_msg, len + 1, format, filename);
-    return Dart_Error(error_msg);
+    char* msg = reinterpret_cast<char*>(malloc(len + 1));
+    snprintf(msg, len + 1, format, filename);
+    *error_msg = msg;
+    return NULL;
   }
-  intptr_t len = file->Length();
-  uint8_t* text_buffer = reinterpret_cast<uint8_t*>(malloc(len));
+  *file_len = file->Length();
+  uint8_t* text_buffer = reinterpret_cast<uint8_t*>(malloc(*file_len));
   if (text_buffer == NULL) {
     delete file;
-    return Dart_Error("Unable to allocate buffer");
+    *error_msg = "Unable to allocate buffer";
+    return NULL;
   }
-  if (!file->ReadFully(text_buffer, len)) {
+  if (!file->ReadFully(text_buffer, *file_len)) {
     delete file;
     free(text_buffer);
-    return Dart_Error("Unable to fully read contents");
+    *error_msg = "Unable to fully read contents";
+    return NULL;
   }
   delete file;
+  return text_buffer;
+}
+
+
+Dart_Handle DartUtils::ReadStringFromFile(const char* filename) {
+  const char* error_msg = NULL;
+  intptr_t len;
+  const uint8_t* text_buffer = ReadFile(filename, &len, &error_msg);
+  if (text_buffer == NULL) {
+    return Dart_Error(error_msg);
+  }
   Dart_Handle str = Dart_NewStringFromUTF8(text_buffer, len);
-  free(text_buffer);
   return str;
 }
 
@@ -325,16 +341,27 @@
 }
 
 
-static Dart_Handle ReadSource(Dart_Handle script_uri,
-                              Dart_Handle builtin_lib) {
-  Dart_Handle script_path = DartUtils::FilePathFromUri(script_uri, builtin_lib);
-  if (Dart_IsError(script_path)) {
-    return script_path;
+const uint8_t* DartUtils::SniffForMagicNumber(const uint8_t* text_buffer,
+                                              intptr_t* buffer_len,
+                                              bool* is_snapshot) {
+  intptr_t len = sizeof(magic_number);
+  for (intptr_t i = 0; i < len; i++) {
+    if (text_buffer[i] != magic_number[i]) {
+      *is_snapshot = false;
+      return text_buffer;
+    }
   }
-  const char* script_path_cstr;
-  Dart_StringToCString(script_path, &script_path_cstr);
-  Dart_Handle source = DartUtils::ReadStringFromFile(script_path_cstr);
-  return source;
+  *is_snapshot = true;
+  ASSERT(*buffer_len > len);
+  *buffer_len -= len;
+  return text_buffer + len;
+}
+
+
+void DartUtils::WriteMagicNumber(File* file) {
+  // Write a magic number and version information into the snapshot file.
+  bool bytes_written = file->WriteFully(magic_number, sizeof(magic_number));
+  ASSERT(bytes_written);
 }
 
 
@@ -345,11 +372,27 @@
   if (Dart_IsError(resolved_script_uri)) {
     return resolved_script_uri;
   }
-  Dart_Handle source = ReadSource(resolved_script_uri, builtin_lib);
-  if (Dart_IsError(source)) {
-    return source;
+  Dart_Handle script_path = DartUtils::FilePathFromUri(resolved_script_uri,
+                                                       builtin_lib);
+  if (Dart_IsError(script_path)) {
+    return script_path;
   }
-  return Dart_LoadEmbeddedScript(resolved_script_uri, source, 0, 0);
+  const char* script_path_cstr;
+  Dart_StringToCString(script_path, &script_path_cstr);
+  const char* error_msg = NULL;
+  intptr_t len;
+  const uint8_t* text_buffer = ReadFile(script_path_cstr, &len, &error_msg);
+  if (text_buffer == NULL) {
+    return Dart_Error(error_msg);
+  }
+  bool is_snapshot = false;
+  text_buffer = SniffForMagicNumber(text_buffer, &len, &is_snapshot);
+  if (is_snapshot) {
+    return Dart_LoadScriptFromSnapshot(text_buffer, len);
+  } else {
+    Dart_Handle source = Dart_NewStringFromUTF8(text_buffer, len);
+    return Dart_LoadScript(resolved_script_uri, source, 0, 0);
+  }
 }
 
 
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 35b7866..da7653e 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -10,6 +10,9 @@
 #include "include/dart_api.h"
 #include "platform/globals.h"
 
+// Forward declarations.
+class File;
+
 /* Handles error handles returned from Dart API functions.  If a value
  * is an error, uses Dart_PropagateError to throw it to the enclosing
  * Dart activation.  Otherwise, returns the original handle.
@@ -157,6 +160,18 @@
                                 Dart_Handle url,
                                 Dart_Handle builtin_lib);
 
+  // Sniffs the specified text_buffer to see if it contains the magic number
+  // representing a script snapshot. If the text_buffer is a script snapshot
+  // the return value is an updated pointer to the text_buffer pointing past
+  // the magic number value. The 'buffer_len' parameter is also appropriately
+  // adjusted.
+  static const uint8_t* SniffForMagicNumber(const uint8_t* text_buffer,
+                                            intptr_t* buffer_len,
+                                            bool* is_snapshot);
+
+  // Write a magic number to indicate a script snapshot file.
+  static void WriteMagicNumber(File* file);
+
   // Global state that stores the original working directory..
   static const char* original_working_directory;
 
@@ -175,6 +190,8 @@
 
   static const char* kIdFieldName;
 
+  static uint8_t magic_number[];
+
  private:
   static const char* GetCanonicalPath(const char* reference_dir,
                                       const char* filename);
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 1493b2d..c218595 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -117,6 +117,9 @@
   Dart_Handle recursive = Dart_GetNativeArgument(args, 1);
   // Create the list to hold the directory listing here, and pass it to the
   // SyncDirectoryListing object, which adds elements to it.
+  Dart_Handle follow_links = Dart_GetNativeArgument(args, 2);
+  // Create the list to hold the directory listing here, and pass it to the
+  // SyncDirectoryListing object, which adds elements to it.
   Dart_Handle results =
       Dart_New(DartUtils::GetDartClass(DartUtils::kCoreLibURL, "List"),
                Dart_Null(),
@@ -125,6 +128,7 @@
   SyncDirectoryListing sync_listing(results);
   Directory::List(DartUtils::GetStringValue(path),
                   DartUtils::GetBooleanValue(recursive),
+                  DartUtils::GetBooleanValue(follow_links),
                   &sync_listing);
   Dart_SetReturnValue(args, results);
   Dart_ExitScope();
@@ -194,13 +198,17 @@
 
 static CObject* DirectoryListRequest(const CObjectArray& request,
                                      Dart_Port response_port) {
-  if (request.Length() == 3 && request[1]->IsString() && request[2]->IsBool()) {
+  if (request.Length() == 4 &&
+      request[1]->IsString() &&
+      request[2]->IsBool() &&
+      request[3]->IsBool()) {
     AsyncDirectoryListing* dir_listing =
         new AsyncDirectoryListing(response_port);
     CObjectString path(request[1]);
     CObjectBool recursive(request[2]);
+    CObjectBool follow_links(request[3]);
     bool completed = Directory::List(
-        path.CString(), recursive.Value(), dir_listing);
+        path.CString(), recursive.Value(), follow_links.Value(), dir_listing);
     delete dir_listing;
     CObjectArray* response = new CObjectArray(CObject::NewArray(2));
     response->SetAt(
@@ -315,6 +323,12 @@
 }
 
 
+bool AsyncDirectoryListing::HandleLink(char* link_name) {
+  CObjectArray* response = NewResponse(kListLink, link_name);
+  return Dart_PostCObject(response_port_, response->AsApiCObject());
+}
+
+
 bool AsyncDirectoryListing::HandleError(const char* dir_name) {
   CObject* err = CObject::NewOSError();
   CObjectArray* response = new CObjectArray(CObject::NewArray(3));
@@ -332,6 +346,14 @@
   return true;
 }
 
+bool SyncDirectoryListing::HandleLink(char* link_name) {
+  Dart_Handle link_name_dart = DartUtils::NewString(link_name);
+  Dart_Handle link =
+      Dart_New(link_class_, Dart_Null(), 1, &link_name_dart);
+  Dart_Invoke(results_, add_string_, 1, &link);
+  return true;
+}
+
 bool SyncDirectoryListing::HandleFile(char* file_name) {
   Dart_Handle file_name_dart = DartUtils::NewString(file_name);
   Dart_Handle file =
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index 87bea9f..331b4c4 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -16,6 +16,7 @@
   virtual ~DirectoryListing() {}
   virtual bool HandleDirectory(char* dir_name) = 0;
   virtual bool HandleFile(char* file_name) = 0;
+  virtual bool HandleLink(char* file_name) = 0;
   virtual bool HandleError(const char* dir_name) = 0;
 };
 
@@ -25,8 +26,9 @@
   enum Response {
     kListFile = 0,
     kListDirectory = 1,
-    kListError = 2,
-    kListDone = 3
+    kListLink = 2,
+    kListError = 3,
+    kListDone = 4
   };
 
   explicit AsyncDirectoryListing(Dart_Port response_port)
@@ -34,6 +36,7 @@
   virtual ~AsyncDirectoryListing() {}
   virtual bool HandleDirectory(char* dir_name);
   virtual bool HandleFile(char* file_name);
+  virtual bool HandleLink(char* file_name);
   virtual bool HandleError(const char* dir_name);
 
  private:
@@ -53,10 +56,13 @@
         DartUtils::GetDartClass(DartUtils::kIOLibURL, "Directory");
     file_class_ =
         DartUtils::GetDartClass(DartUtils::kIOLibURL, "File");
+    link_class_ =
+        DartUtils::GetDartClass(DartUtils::kIOLibURL, "Link");
   }
   virtual ~SyncDirectoryListing() {}
   virtual bool HandleDirectory(char* dir_name);
   virtual bool HandleFile(char* file_name);
+  virtual bool HandleLink(char* file_name);
   virtual bool HandleError(const char* dir_name);
 
  private:
@@ -64,6 +70,7 @@
   Dart_Handle add_string_;
   Dart_Handle directory_class_;
   Dart_Handle file_class_;
+  Dart_Handle link_class_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(SyncDirectoryListing);
 };
@@ -90,6 +97,7 @@
 
   static bool List(const char* path,
                    bool recursive,
+                   bool follow_links,
                    DirectoryListing* listing);
   static ExistsResult Exists(const char* path);
   static char* Current();
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index fd58c81..9a2d166 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -57,6 +57,7 @@
 // Forward declarations.
 static bool ListRecursively(PathBuffer* path,
                             bool recursive,
+                            bool follow_links,
                             DirectoryListing* listing);
 static bool DeleteRecursively(PathBuffer* path);
 
@@ -70,14 +71,16 @@
 static bool HandleDir(char* dir_name,
                       PathBuffer* path,
                       bool recursive,
+                      bool follow_links,
                       DirectoryListing *listing) {
   if (strcmp(dir_name, ".") == 0) return true;
   if (strcmp(dir_name, "..") == 0) return true;
   if (!path->Add(dir_name)) {
     PostError(listing, path->data);
     return false;
+  }
   return listing->HandleDirectory(path->data) &&
-      (!recursive || ListRecursively(path, recursive, listing));
+      (!recursive || ListRecursively(path, recursive, follow_links, listing));
 }
 
 
@@ -92,8 +95,20 @@
 }
 
 
+static bool HandleLink(char* link_name,
+                       PathBuffer* path,
+                       DirectoryListing *listing) {
+  if (!path->Add(link_name)) {
+    PostError(listing, path->data);
+    return false;
+  }
+  return listing->HandleLink(path->data);
+}
+
+
 static bool ListRecursively(PathBuffer* path,
                             bool recursive,
+                            bool follow_links,
                             DirectoryListing *listing) {
   if (!path->Add(File::PathSeparator())) {
     PostError(listing, path->data);
@@ -124,6 +139,7 @@
         success = HandleDir(entry.d_name,
                             path,
                             recursive,
+                            follow_links,
                             listing) && success;
         break;
       case DT_REG:
@@ -132,6 +148,14 @@
                              listing) && success;
         break;
       case DT_LNK:
+        if (!follow_links) {
+          success = HandleLink(entry.d_name,
+                               path,
+                               listing) && success;
+          break;
+        }
+        // Else fall through to next case.
+        // Fall through.
       case DT_UNKNOWN: {
         // On some file systems the entry type is not determined by
         // readdir_r. For those and for links we use stat to determine
@@ -142,7 +166,12 @@
           success = false;
           break;
         }
-        int stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
+        int stat_success;
+        if (follow_links) {
+          stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
+        } else {
+          stat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info));
+        }
         if (stat_success == -1) {
           success = false;
           PostError(listing, path->data);
@@ -153,13 +182,18 @@
           success = HandleDir(entry.d_name,
                               path,
                               recursive,
+                              follow_links,
                               listing) && success;
         } else if (S_ISREG(entry_info.st_mode)) {
           success = HandleFile(entry.d_name,
                                path,
                                listing) && success;
+        } else if (S_ISLNK(entry_info.st_mode)) {
+          ASSERT(!follow_links);
+          success = HandleLink(entry.d_name,
+                               path,
+                               listing) && success;
         }
-        ASSERT(!S_ISLNK(entry_info.st_mode));
         break;
       }
       default:
@@ -282,13 +316,14 @@
 
 bool Directory::List(const char* dir_name,
                      bool recursive,
+                     bool follow_links,
                      DirectoryListing *listing) {
   PathBuffer path;
   if (!path.Add(dir_name)) {
     PostError(listing, dir_name);
     return false;
   }
-  return ListRecursively(&path, recursive, listing);
+  return ListRecursively(&path, recursive, follow_links, listing);
 }
 
 
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index 30cc860..f6ad163 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -57,6 +57,7 @@
 // Forward declarations.
 static bool ListRecursively(PathBuffer* path,
                             bool recursive,
+                            bool follow_links,
                             DirectoryListing* listing);
 static bool DeleteRecursively(PathBuffer* path);
 
@@ -70,6 +71,7 @@
 static bool HandleDir(char* dir_name,
                       PathBuffer* path,
                       bool recursive,
+                      bool follow_links,
                       DirectoryListing *listing) {
   if (strcmp(dir_name, ".") == 0) return true;
   if (strcmp(dir_name, "..") == 0) return true;
@@ -78,7 +80,7 @@
     return false;
   }
   return listing->HandleDirectory(path->data) &&
-      (!recursive || ListRecursively(path, recursive, listing));
+      (!recursive || ListRecursively(path, recursive, follow_links, listing));
 }
 
 
@@ -93,8 +95,20 @@
 }
 
 
+static bool HandleLink(char* link_name,
+                       PathBuffer* path,
+                       DirectoryListing *listing) {
+  if (!path->Add(link_name)) {
+    PostError(listing, path->data);
+    return false;
+  }
+  return listing->HandleLink(path->data);
+}
+
+
 static bool ListRecursively(PathBuffer* path,
                             bool recursive,
+                            bool follow_links,
                             DirectoryListing *listing) {
   if (!path->Add(File::PathSeparator())) {
     PostError(listing, path->data);
@@ -125,6 +139,7 @@
         success = HandleDir(entry.d_name,
                             path,
                             recursive,
+                            follow_links,
                             listing) && success;
         break;
       case DT_REG:
@@ -133,6 +148,14 @@
                              listing) && success;
         break;
       case DT_LNK:
+        if (!follow_links) {
+          success = HandleLink(entry.d_name,
+                               path,
+                               listing) && success;
+          break;
+        }
+        // Else fall through to next case.
+        // Fall through.
       case DT_UNKNOWN: {
         // On some file systems the entry type is not determined by
         // readdir_r. For those and for links we use stat to determine
@@ -143,7 +166,12 @@
           success = false;
           break;
         }
-        int stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
+        int stat_success;
+        if (follow_links) {
+          stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
+        } else {
+          stat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info));
+        }
         if (stat_success == -1) {
           success = false;
           PostError(listing, path->data);
@@ -154,13 +182,18 @@
           success = HandleDir(entry.d_name,
                               path,
                               recursive,
+                              follow_links,
                               listing) && success;
         } else if (S_ISREG(entry_info.st_mode)) {
           success = HandleFile(entry.d_name,
                                path,
                                listing) && success;
+        } else if (S_ISLNK(entry_info.st_mode)) {
+          ASSERT(!follow_links);
+          success = HandleLink(entry.d_name,
+                               path,
+                               listing) && success;
         }
-        ASSERT(!S_ISLNK(entry_info.st_mode));
         break;
       }
       default:
@@ -283,13 +316,14 @@
 
 bool Directory::List(const char* dir_name,
                      bool recursive,
+                     bool follow_links,
                      DirectoryListing *listing) {
   PathBuffer path;
   if (!path.Add(dir_name)) {
     PostError(listing, dir_name);
     return false;
   }
-  return ListRecursively(&path, recursive, listing);
+  return ListRecursively(&path, recursive, follow_links, listing);
 }
 
 
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
index 4685479..d66a809 100644
--- a/runtime/bin/directory_macos.cc
+++ b/runtime/bin/directory_macos.cc
@@ -57,6 +57,7 @@
 // Forward declarations.
 static bool ListRecursively(PathBuffer* path,
                             bool recursive,
+                            bool follow_links,
                             DirectoryListing* listing);
 static bool DeleteRecursively(PathBuffer* path);
 
@@ -70,6 +71,7 @@
 static bool HandleDir(char* dir_name,
                       PathBuffer* path,
                       bool recursive,
+                      bool follow_links,
                       DirectoryListing *listing) {
   if (strcmp(dir_name, ".") == 0) return true;
   if (strcmp(dir_name, "..") == 0) return true;
@@ -78,7 +80,7 @@
     return false;
   }
   return listing->HandleDirectory(path->data) &&
-      (!recursive || ListRecursively(path, recursive, listing));
+      (!recursive || ListRecursively(path, recursive, follow_links, listing));
 }
 
 
@@ -93,8 +95,20 @@
 }
 
 
+static bool HandleLink(char* link_name,
+                       PathBuffer* path,
+                       DirectoryListing *listing) {
+  if (!path->Add(link_name)) {
+    PostError(listing, path->data);
+    return false;
+  }
+  return listing->HandleLink(path->data);
+}
+
+
 static bool ListRecursively(PathBuffer* path,
                             bool recursive,
+                            bool follow_links,
                             DirectoryListing *listing) {
   if (!path->Add(File::PathSeparator())) {
     PostError(listing, path->data);
@@ -125,6 +139,7 @@
         success = HandleDir(entry.d_name,
                             path,
                             recursive,
+                            follow_links,
                             listing) && success;
         break;
       case DT_REG:
@@ -133,6 +148,14 @@
                              listing) && success;
         break;
       case DT_LNK:
+        if (!follow_links) {
+          success = HandleLink(entry.d_name,
+                               path,
+                               listing) && success;
+          break;
+        }
+        // Else fall through to next case.
+        // Fall through.
       case DT_UNKNOWN: {
         // On some file systems the entry type is not determined by
         // readdir_r. For those and for links we use stat to determine
@@ -143,7 +166,12 @@
           success = false;
           break;
         }
-        int stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
+        int stat_success;
+        if (follow_links) {
+          stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info));
+        } else {
+          stat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info));
+        }
         if (stat_success == -1) {
           success = false;
           PostError(listing, path->data);
@@ -154,13 +182,18 @@
           success = HandleDir(entry.d_name,
                               path,
                               recursive,
+                              follow_links,
                               listing) && success;
         } else if (S_ISREG(entry_info.st_mode)) {
           success = HandleFile(entry.d_name,
                                path,
                                listing) && success;
+        } else if (S_ISLNK(entry_info.st_mode)) {
+          ASSERT(!follow_links);
+          success = HandleLink(entry.d_name,
+                               path,
+                               listing) && success;
         }
-        ASSERT(!S_ISLNK(entry_info.st_mode));
         break;
       }
       default:
@@ -283,13 +316,14 @@
 
 bool Directory::List(const char* dir_name,
                      bool recursive,
+                     bool follow_links,
                      DirectoryListing *listing) {
   PathBuffer path;
   if (!path.Add(dir_name)) {
     PostError(listing, dir_name);
     return false;
   }
-  return ListRecursively(&path, recursive, listing);
+  return ListRecursively(&path, recursive, follow_links, listing);
 }
 
 
diff --git a/runtime/bin/directory_patch.dart b/runtime/bin/directory_patch.dart
index cb844f7..4b6ce1f 100644
--- a/runtime/bin/directory_patch.dart
+++ b/runtime/bin/directory_patch.dart
@@ -11,7 +11,7 @@
       native "Directory_Delete";
   /* patch */ static _rename(String path, String newPath)
       native "Directory_Rename";
-  /* patch */ static List _list(String path, bool recursive)
+  /* patch */ static List _list(String path, bool recursive, bool followLinks)
       native "Directory_List";
   /* patch */ static SendPort _newServicePort()
       native "Directory_NewServicePort";
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index 97a2207..857739a 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -52,6 +52,7 @@
 // Forward declarations.
 static bool ListRecursively(PathBuffer* path,
                             bool recursive,
+                            bool follow_links,
                             DirectoryListing* listing);
 static bool DeleteRecursively(PathBuffer* path);
 
@@ -67,6 +68,7 @@
 static bool HandleDir(wchar_t* dir_name,
                       PathBuffer* path,
                       bool recursive,
+                      bool follow_links,
                       DirectoryListing* listing) {
   if (wcscmp(dir_name, L".") == 0) return true;
   if (wcscmp(dir_name, L"..") == 0) return true;
@@ -77,7 +79,8 @@
   char* utf8_path = StringUtils::WideToUtf8(path->data);
   bool ok = listing->HandleDirectory(utf8_path);
   free(utf8_path);
-  return ok && (!recursive || ListRecursively(path, recursive, listing));
+  return ok &&
+      (!recursive || ListRecursively(path, recursive, follow_links, listing));
 }
 
 
@@ -95,15 +98,33 @@
 }
 
 
+static bool HandleLink(wchar_t* link_name,
+                       PathBuffer* path,
+                       DirectoryListing* listing) {
+  if (!path->Add(link_name)) {
+    PostError(listing, path->data);
+    return false;
+  }
+  char* utf8_path = StringUtils::WideToUtf8(path->data);
+  bool ok = listing->HandleLink(utf8_path);
+  free(utf8_path);
+  return ok;
+}
+
+
 static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data,
                         PathBuffer* path,
                         bool recursive,
+                        bool follow_links,
                         DirectoryListing* listing) {
   DWORD attributes = find_file_data->dwFileAttributes;
-  if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+  if (!follow_links && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
+    return HandleLink(find_file_data->cFileName, path, listing);
+  } else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
     return HandleDir(find_file_data->cFileName,
                      path,
                      recursive,
+                     follow_links,
                      listing);
   } else {
     return HandleFile(find_file_data->cFileName, path, listing);
@@ -113,6 +134,7 @@
 
 static bool ListRecursively(PathBuffer* path,
                             bool recursive,
+                            bool follow_links,
                             DirectoryListing* listing) {
   if (!path->Add(L"\\*")) {
     PostError(listing, path->data);
@@ -134,6 +156,7 @@
   bool success = HandleEntry(&find_file_data,
                              path,
                              recursive,
+                             follow_links,
                              listing);
 
   while ((FindNextFileW(find_handle, &find_file_data) != 0)) {
@@ -141,6 +164,7 @@
     success = HandleEntry(&find_file_data,
                           path,
                           recursive,
+                          follow_links,
                           listing) && success;
   }
 
@@ -250,6 +274,7 @@
 
 bool Directory::List(const char* dir_name,
                      bool recursive,
+                     bool follow_links,
                      DirectoryListing* listing) {
   const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
   PathBuffer path;
@@ -258,7 +283,7 @@
     return false;
   }
   free(const_cast<wchar_t*>(system_name));
-  return ListRecursively(&path, recursive, listing);
+  return ListRecursively(&path, recursive, follow_links, listing);
 }
 
 
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index cb193a6..3ed6e3f 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -20,6 +20,8 @@
 #include "platform/thread.h"
 
 
+static const int kBufferSize = 32 * 1024;
+
 static const int kInfinityTimeout = -1;
 static const int kTimeoutId = -1;
 static const int kShutdownId = -2;
@@ -234,7 +236,7 @@
   ScopedLock lock(this);
   ASSERT(type_ != kListenSocket);
   ASSERT(pending_read_ == NULL);
-  IOBuffer* buffer = IOBuffer::AllocateReadBuffer(1024);
+  IOBuffer* buffer = IOBuffer::AllocateReadBuffer(kBufferSize);
   if (SupportsOverlappedIO()) {
     ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
 
@@ -491,7 +493,7 @@
   if (SupportsOverlappedIO()) {
     if (pending_write_ != NULL) return 0;
     if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
-    if (num_bytes > 4096) num_bytes = 4096;
+    if (num_bytes > kBufferSize) num_bytes = kBufferSize;
     pending_write_ = IOBuffer::AllocateWriteBuffer(num_bytes);
     pending_write_->Write(buffer, num_bytes);
     if (!IssueWrite()) return -1;
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index f457dd9..5c54ed8 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -439,8 +439,32 @@
       Dart_SetReturnValue(args, err);
     }
   } else  {
-    OSError os_error(-1, "Invalid argument", OSError::kUnknown);
-    Dart_Handle err = DartUtils::NewDartOSError(&os_error);
+    Dart_Handle err = DartUtils::NewDartArgumentError(
+        "Non-string argument to Link.create");
+    if (Dart_IsError(err)) Dart_PropagateError(err);
+    Dart_SetReturnValue(args, err);
+  }
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(File_LinkTarget)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  if (Dart_IsString(Dart_GetNativeArgument(args, 0))) {
+    const char* name =
+        DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
+    char* target = File::LinkTarget(name);
+    if (target == NULL) {
+      Dart_Handle err = DartUtils::NewDartOSError();
+      if (Dart_IsError(err)) Dart_PropagateError(err);
+      Dart_SetReturnValue(args, err);
+    } else {
+      Dart_SetReturnValue(args, DartUtils::NewString(target));
+      free(target);
+    }
+  } else {
+    Dart_Handle err = DartUtils::NewDartArgumentError(
+        "Non-string argument to Link.target");
     if (Dart_IsError(err)) Dart_PropagateError(err);
     Dart_SetReturnValue(args, err);
   }
@@ -531,8 +555,34 @@
     File::Type type = File::GetType(str, follow_links);
     Dart_SetReturnValue(args, Dart_NewInteger(static_cast<int>(type)));
   } else  {
-    OSError os_error(-1, "Invalid argument", OSError::kUnknown);
-    Dart_Handle err = DartUtils::NewDartOSError(&os_error);
+    Dart_Handle err = DartUtils::NewDartArgumentError(
+        "Non-string argument to FileSystemEntity.type");
+    if (Dart_IsError(err)) Dart_PropagateError(err);
+    Dart_SetReturnValue(args, err);
+  }
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(File_AreIdentical)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  if (Dart_IsString(Dart_GetNativeArgument(args, 0)) &&
+      Dart_IsString(Dart_GetNativeArgument(args, 1))) {
+    const char* path_1 =
+        DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
+    const char* path_2 =
+        DartUtils::GetStringValue(Dart_GetNativeArgument(args, 1));
+    File::Identical result = File::AreIdentical(path_1, path_2);
+    if (result == File::kError) {
+      Dart_Handle err = DartUtils::NewDartOSError();
+      if (Dart_IsError(err)) Dart_PropagateError(err);
+      Dart_SetReturnValue(args, err);
+    } else {
+      Dart_SetReturnValue(args, Dart_NewBoolean(result == File::kIdentical));
+    }
+  } else  {
+    Dart_Handle err = DartUtils::NewDartArgumentError(
+        "Non-string argument to FileSystemEntity.identical");
     if (Dart_IsError(err)) Dart_PropagateError(err);
     Dart_SetReturnValue(args, err);
   }
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index dab7a9c..a4c6d4b 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -43,6 +43,12 @@
     kDoesNotExist = 3
   };
 
+  enum Identical {
+    kIdentical = 0,
+    kDifferent = 1,
+    kError = 2
+  };
+
   enum StdioHandleType {
     kTerminal = 0,
     kPipe = 1,
@@ -127,12 +133,14 @@
   static bool Delete(const char* path);
   static off_t LengthFromPath(const char* path);
   static time_t LastModified(const char* path);
+  static char* LinkTarget(const char* pathname);
   static bool IsAbsolutePath(const char* path);
   static char* GetCanonicalPath(const char* path);
   static char* GetContainingDirectory(char* path);
   static const char* PathSeparator();
   static const char* StringEscapedPathSeparator();
   static Type GetType(const char* path, bool follow_links);
+  static Identical AreIdentical(const char* file_1, const char* file_2);
   static StdioHandleType GetStdioHandleType(int fd);
 
   static FileOpenMode DartModeToFileMode(DartFileOpenMode mode);
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index bdb8ac1..21dcaa9 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -192,6 +192,25 @@
 }
 
 
+char* File::LinkTarget(const char* pathname) {
+  struct stat link_stats;
+  if (lstat(pathname, &link_stats) != 0) return NULL;
+  if (!S_ISLNK(link_stats.st_mode)) {
+    errno = ENOENT;
+    return NULL;
+  }
+  size_t target_size = link_stats.st_size;
+  char* target_name = reinterpret_cast<char*>(malloc(target_size + 1));
+  size_t read_size = readlink(pathname, target_name, target_size + 1);
+  if (read_size != target_size) {
+    free(target_name);
+    return NULL;
+  }
+  target_name[target_size] = '\0';
+  return target_name;
+}
+
+
 bool File::IsAbsolutePath(const char* pathname) {
   return (pathname != NULL && pathname[0] == '/');
 }
@@ -268,4 +287,18 @@
   return File::kDoesNotExist;
 }
 
+
+File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
+  struct stat file_1_info;
+  struct stat file_2_info;
+  if (TEMP_FAILURE_RETRY(lstat(file_1, &file_1_info)) == -1 ||
+      TEMP_FAILURE_RETRY(lstat(file_2, &file_2_info)) == -1) {
+    return File::kError;
+  }
+  return (file_1_info.st_ino == file_2_info.st_ino &&
+          file_1_info.st_dev == file_2_info.st_dev) ?
+      File::kIdentical :
+      File::kDifferent;
+}
+
 #endif  // defined(TARGET_OS_ANDROID)
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index abbe9cc..ceac630 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -193,6 +193,25 @@
 }
 
 
+char* File::LinkTarget(const char* pathname) {
+  struct stat link_stats;
+  if (lstat(pathname, &link_stats) != 0) return NULL;
+  if (!S_ISLNK(link_stats.st_mode)) {
+    errno = ENOENT;
+    return NULL;
+  }
+  size_t target_size = link_stats.st_size;
+  char* target_name = reinterpret_cast<char*>(malloc(target_size + 1));
+  size_t read_size = readlink(pathname, target_name, target_size + 1);
+  if (read_size != target_size) {
+    free(target_name);
+    return NULL;
+  }
+  target_name[target_size] = '\0';
+  return target_name;
+}
+
+
 bool File::IsAbsolutePath(const char* pathname) {
   return (pathname != NULL && pathname[0] == '/');
 }
@@ -269,4 +288,18 @@
   return File::kDoesNotExist;
 }
 
+
+File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
+  struct stat file_1_info;
+  struct stat file_2_info;
+  if (TEMP_FAILURE_RETRY(lstat(file_1, &file_1_info)) == -1 ||
+      TEMP_FAILURE_RETRY(lstat(file_2, &file_2_info)) == -1) {
+    return File::kError;
+  }
+  return (file_1_info.st_ino == file_2_info.st_ino &&
+          file_1_info.st_dev == file_2_info.st_dev) ?
+      File::kIdentical :
+      File::kDifferent;
+}
+
 #endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 9d32457..301424b 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -195,6 +195,25 @@
 }
 
 
+char* File::LinkTarget(const char* pathname) {
+  struct stat link_stats;
+  if (lstat(pathname, &link_stats) != 0) return NULL;
+  if (!S_ISLNK(link_stats.st_mode)) {
+    errno = ENOENT;
+    return NULL;
+  }
+  size_t target_size = link_stats.st_size;
+  char* target_name = reinterpret_cast<char*>(malloc(target_size + 1));
+  size_t read_size = readlink(pathname, target_name, target_size + 1);
+  if (read_size != target_size) {
+    free(target_name);
+    return NULL;
+  }
+  target_name[target_size] = '\0';
+  return target_name;
+}
+
+
 bool File::IsAbsolutePath(const char* pathname) {
   return (pathname != NULL && pathname[0] == '/');
 }
@@ -277,4 +296,18 @@
   return File::kDoesNotExist;
 }
 
+
+File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
+  struct stat file_1_info;
+  struct stat file_2_info;
+  if (TEMP_FAILURE_RETRY(lstat(file_1, &file_1_info)) == -1 ||
+      TEMP_FAILURE_RETRY(lstat(file_2, &file_2_info)) == -1) {
+    return File::kError;
+  }
+  return (file_1_info.st_ino == file_2_info.st_ino &&
+          file_1_info.st_dev == file_2_info.st_dev) ?
+      File::kIdentical :
+      File::kDifferent;
+}
+
 #endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index 194813b..e1e1bfa 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -11,6 +11,7 @@
   /* patch */ static _create(String path) native "File_Create";
   /* patch */ static _createLink(String path, String target)
       native "File_CreateLink";
+  /* patch */ static _linkTarget(String path) native "File_LinkTarget";
   /* patch */ static _delete(String path) native "File_Delete";
   /* patch */ static _directory(String path) native "File_Directory";
   /* patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
diff --git a/runtime/bin/file_system_entity_patch.dart b/runtime/bin/file_system_entity_patch.dart
index 267ab1b..2815ba6 100644
--- a/runtime/bin/file_system_entity_patch.dart
+++ b/runtime/bin/file_system_entity_patch.dart
@@ -5,4 +5,6 @@
 patch class FileSystemEntity {
   /* patch */ static int _getType(String path, bool followLinks)
       native "File_GetType";
+  /* patch */ static bool _identical(String path1, String path2)
+      native "File_AreIdentical";
 }
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index b23049d..8e618d3 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -167,6 +167,7 @@
             USHORT  SubstituteNameLength;
             USHORT  PrintNameOffset;
             USHORT  PrintNameLength;
+            ULONG   Flags;
             WCHAR   PathBuffer[1];
         } SymbolicLinkReparseBuffer;
 
@@ -279,6 +280,103 @@
 }
 
 
+char* File::LinkTarget(const char* pathname) {
+  const wchar_t* name = StringUtils::Utf8ToWide(pathname);
+  HANDLE dir_handle = CreateFileW(
+      name,
+      GENERIC_READ,
+      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+      NULL,
+      OPEN_EXISTING,
+      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
+      NULL);
+  free(const_cast<wchar_t*>(name));
+  if (dir_handle == INVALID_HANDLE_VALUE) {
+    return NULL;
+  }
+
+  int buffer_size =
+      sizeof REPARSE_DATA_BUFFER + 2 * (MAX_PATH + 1) * sizeof WCHAR;
+  REPARSE_DATA_BUFFER* buffer =
+      static_cast<REPARSE_DATA_BUFFER*>(calloc(buffer_size, 1));
+  DWORD received_bytes;  // Value is not used.
+  int result = DeviceIoControl(
+      dir_handle,
+      FSCTL_GET_REPARSE_POINT,
+      NULL,
+      0,
+      buffer,
+      buffer_size,
+      &received_bytes,
+      NULL);
+  if (result == 0) {
+    DWORD error = GetLastError();
+    CloseHandle(dir_handle);
+    free(buffer);
+    SetLastError(error);
+    return NULL;
+  }
+  if (CloseHandle(dir_handle) == 0) {
+    DWORD error = GetLastError();
+    free(buffer);
+    SetLastError(error);
+    return NULL;
+  }
+
+  wchar_t* target;
+  size_t target_offset;
+  size_t target_length;
+  if (buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
+    target = buffer->MountPointReparseBuffer.PathBuffer;
+    target_offset = buffer->MountPointReparseBuffer.SubstituteNameOffset;
+    target_length = buffer->MountPointReparseBuffer.SubstituteNameLength;
+  } else if (buffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
+    target = buffer->SymbolicLinkReparseBuffer.PathBuffer;
+    target_offset = buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset;
+    target_length = buffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
+  } else {  // Not a junction or a symbolic link.
+    free(buffer);
+    SetLastError(ERROR_NOT_A_REPARSE_POINT);
+    return NULL;
+  }
+
+  target_offset /= sizeof(wchar_t);  // Offset and length are in bytes.
+  target_length /= sizeof(wchar_t);
+  target += target_offset;
+  // Remove "\??\" from beginning of target.
+  if (target_length > 4 && wcsncmp(L"\\??\\", target, 4) == 0) {
+    target += 4;
+    target_length -=4;
+  }
+  int utf8_length = WideCharToMultiByte(CP_UTF8,
+                                        0,
+                                        target,
+                                        target_length,
+                                        NULL,
+                                        0,
+                                        NULL,
+                                        NULL);
+  char* utf8_target = reinterpret_cast<char*>(malloc(utf8_length + 1));
+  if (0 == WideCharToMultiByte(CP_UTF8,
+                               0,
+                               target,
+                               target_length,
+                               utf8_target,
+                               utf8_length,
+                               NULL,
+                               NULL)) {
+    DWORD error = GetLastError();
+    free(buffer);
+    free(utf8_target);
+    SetLastError(error);
+    return NULL;
+  }
+  utf8_target[utf8_length] = '\0';
+  free(buffer);
+  return utf8_target;
+}
+
+
 time_t File::LastModified(const char* name) {
   struct _stat st;
   const wchar_t* system_name = StringUtils::Utf8ToWide(name);
@@ -416,4 +514,45 @@
   }
 }
 
+
+File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
+  BY_HANDLE_FILE_INFORMATION file_info[2];
+  const char* file_names[2] = { file_1, file_2 };
+  for (int i = 0; i < 2; ++i) {
+    const wchar_t* wide_name = StringUtils::Utf8ToWide(file_names[i]);
+    HANDLE file_handle = CreateFileW(
+        wide_name,
+        0,
+        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+        NULL,
+        OPEN_EXISTING,
+        FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
+        NULL);
+    if (file_handle == INVALID_HANDLE_VALUE) {
+      DWORD error = GetLastError();
+      free(const_cast<wchar_t*>(wide_name));
+      SetLastError(error);
+      return File::kError;
+    }
+    free(const_cast<wchar_t*>(wide_name));
+    int result = GetFileInformationByHandle(file_handle, &file_info[i]);
+    if (result == 0) {
+      DWORD error = GetLastError();
+      CloseHandle(file_handle);
+      SetLastError(error);
+      return File::kError;
+    }
+    if (CloseHandle(file_handle) == 0) {
+      return File::kError;
+    }
+  }
+  if (file_info[0].dwVolumeSerialNumber == file_info[1].dwVolumeSerialNumber &&
+      file_info[0].nFileIndexHigh == file_info[1].nFileIndexHigh &&
+      file_info[0].nFileIndexLow == file_info[1].nFileIndexLow) {
+    return kIdentical;
+  } else {
+    return kDifferent;
+  }
+}
+
 #endif  // defined(TARGET_OS_WINDOWS)
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 091cb69..05833ba 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -335,7 +335,7 @@
   if (Dart_IsError(source)) {
     return source;
   }
-  return Dart_LoadScript(resolved_script_uri, source);
+  return Dart_LoadScript(resolved_script_uri, source, 0, 0);
 }
 
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 6f29afa..988f78a 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -29,7 +29,6 @@
 
 
 // Global state that stores a pointer to the application script snapshot.
-static bool use_script_snapshot = false;
 static bool generate_script_snapshot = false;
 static File* snapshot_file = NULL;
 
@@ -154,25 +153,6 @@
 }
 
 
-static bool ProcessUseScriptSnapshotOption(const char* filename) {
-  if (filename != NULL && strlen(filename) != 0) {
-    use_script_snapshot = true;
-    if (generate_script_snapshot) {
-      Log::PrintErr("Incompatible options specified --generate-script-snapshot "
-                    "and --use-script-snapshot\n");
-      return false;
-    }
-    snapshot_file = File::Open(filename, File::kRead);
-    if (snapshot_file == NULL) {
-      Log::PrintErr("Unable to open file %s for reading the snapshot\n",
-                    filename);
-      return false;
-    }
-  }
-  return true;
-}
-
-
 static bool ProcessVmStatsOption(const char* port) {
   ASSERT(port != NULL);
   if (*port == '\0') {
@@ -216,11 +196,6 @@
                     " dart\n");
       return false;
     }
-    if (use_script_snapshot) {
-      Log::PrintErr("Incompatible options specified --use-script-snapshot "
-                    "and --generate-script-snapshot\n");
-      return false;
-    }
     snapshot_file = File::Open(filename, File::kWriteTruncate);
     if (snapshot_file == NULL) {
       Log::PrintErr("Unable to open file %s for writing the snapshot\n",
@@ -249,7 +224,6 @@
   { "--break_at=", ProcessBreakpointOption },
   { "--compile_all", ProcessCompileAllOption },
   { "--debug", ProcessDebugOption },
-  { "--use-script-snapshot=", ProcessUseScriptSnapshotOption },
   { "--generate-script-snapshot=", ProcessGenScriptSnapshotOption },
   { "--stats-root=", ProcessVmStatsRootOption },
   { "--stats", ProcessVmStatsOption },
@@ -476,54 +450,23 @@
   CHECK_RESULT(result);
 
   // Load the specified application script into the newly created isolate.
-  Dart_Handle library;
-  if (use_script_snapshot) {
-    if (snapshot_file == NULL) {
-      use_script_snapshot = false;
-      *error = strdup("Invalid script snapshot file name specified");
-      Dart_ExitScope();
-      Dart_ShutdownIsolate();
-      return false;
-    }
-    size_t len = snapshot_file->Length();
-    uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(len));
-    if (buffer == NULL) {
-      delete snapshot_file;
-      snapshot_file = NULL;
-      use_script_snapshot = false;
-      *error = strdup("Unable to read contents of script snapshot file");
-      Dart_ExitScope();
-      Dart_ShutdownIsolate();
-      return false;
-    }
-    // Prepare for script loading by setting up the 'print' and 'timer'
-    // closures and setting up 'package root' for URI resolution.
-    Dart_Handle builtin_lib =
-        Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
-    DartUtils::PrepareForScriptLoading(package_root, builtin_lib);
 
-    snapshot_file->ReadFully(buffer, len);
-    library = Dart_LoadScriptFromSnapshot(buffer);
-    free(buffer);
-    delete snapshot_file;
-    snapshot_file = NULL;
-    use_script_snapshot = false;  // No further usage of script snapshots.
-  } else {
-    // Prepare builtin and its dependent libraries for use to resolve URIs.
-    Dart_Handle uri_url = DartUtils::NewString(DartUtils::kUriLibURL);
-    Dart_Handle uri_lib = Dart_LookupLibrary(uri_url);
-    CHECK_RESULT(uri_lib);
-    Dart_Handle builtin_lib =
-        Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
-    CHECK_RESULT(builtin_lib);
+  // Prepare builtin and its dependent libraries for use to resolve URIs.
+  // The builtin library is part of the core snapshot and would already be
+  // available here in the case of script snapshot loading.
+  Dart_Handle uri_url = DartUtils::NewString(DartUtils::kUriLibURL);
+  Dart_Handle uri_lib = Dart_LookupLibrary(uri_url);
+  CHECK_RESULT(uri_lib);
+  Dart_Handle builtin_lib =
+      Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary);
+  CHECK_RESULT(builtin_lib);
 
-    // Prepare for script loading by setting up the 'print' and 'timer'
-    // closures and setting up 'package root' for URI resolution.
-    result = DartUtils::PrepareForScriptLoading(package_root, builtin_lib);
-    CHECK_RESULT(result);
+  // Prepare for script loading by setting up the 'print' and 'timer'
+  // closures and setting up 'package root' for URI resolution.
+  result = DartUtils::PrepareForScriptLoading(package_root, builtin_lib);
+  CHECK_RESULT(result);
 
-    library = DartUtils::LoadScript(script_uri, builtin_lib);
-  }
+  Dart_Handle library = DartUtils::LoadScript(script_uri, builtin_lib);
   CHECK_RESULT(library);
   if (!Dart_IsLibrary(library)) {
     char errbuf[256];
@@ -825,6 +768,9 @@
       return kErrorExitCode;  // Indicates we encountered an error.
     }
 
+    // Write the magic number to indicate file is a script snapshot.
+    DartUtils::WriteMagicNumber(snapshot_file);
+
     // Now write the snapshot out to specified file.
     bool bytes_written = snapshot_file->WriteFully(buffer, size);
     ASSERT(bytes_written);
diff --git a/runtime/embedders/openglui/common/vm_glue.cc b/runtime/embedders/openglui/common/vm_glue.cc
index b014d1d..1fde06c 100644
--- a/runtime/embedders/openglui/common/vm_glue.cc
+++ b/runtime/embedders/openglui/common/vm_glue.cc
@@ -191,7 +191,7 @@
 
   Dart_Handle url = CheckError(Dart_NewStringFromCString(main_script_));
   Dart_Handle source = LoadSourceFromFile(main_script_);
-  CheckError(Dart_LoadScript(url, source));
+  CheckError(Dart_LoadScript(url, source, 0, 0));
 
   Dart_ExitScope();
   Dart_ExitIsolate();
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 96ca096..c9375ca 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -327,11 +327,14 @@
  *
  * Provided for convenience.
  */
-#define DART_CHECK_VALID(handle)                                        \
-  if (Dart_IsError((handle))) {                                         \
-    _Dart_ReportErrorHandle(__FILE__, __LINE__,                       \
-                              #handle, Dart_GetError(handle));          \
-  }
+#define DART_CHECK_VALID(handle)                                               \
+  {                                                                            \
+    Dart_Handle __handle = handle;                                             \
+    if (Dart_IsError((__handle))) {                                            \
+      _Dart_ReportErrorHandle(__FILE__, __LINE__,                              \
+                              #handle, Dart_GetError(__handle));               \
+    }                                                                          \
+  }                                                                            \
 
 
 /**
@@ -2354,15 +2357,6 @@
 DART_EXPORT Dart_Handle Dart_SetLibraryTagHandler(
     Dart_LibraryTagHandler handler);
 
-
-/**
- * Loads the root script for the current isolate.
- *
- * TODO(turnidge): Document.
- */
-DART_EXPORT Dart_Handle Dart_LoadScript(Dart_Handle url,
-                                        Dart_Handle source);
-
 /**
  * Loads the root script for the current isolate. The script can be
  * embedded in another file, for example in an html file.
@@ -2375,8 +2369,7 @@
  * \col_offset is the number of characters before the first character
  *   in the first line of the Dart script.
  */
-DART_EXPORT Dart_Handle Dart_LoadEmbeddedScript(
-                                        Dart_Handle url,
+DART_EXPORT Dart_Handle Dart_LoadScript(Dart_Handle url,
                                         Dart_Handle source,
                                         intptr_t line_offset,
                                         intptr_t col_offset);
@@ -2385,11 +2378,13 @@
  * Loads the root script for current isolate from a snapshot.
  *
  * \param buffer A buffer which contains a snapshot of the script.
+ * \param length Length of the passed in buffer.
  *
  * \return If no error occurs, the Library object corresponding to the root
  *   script is returned. Otherwise an error handle is returned.
  */
-DART_EXPORT Dart_Handle Dart_LoadScriptFromSnapshot(const uint8_t* buffer);
+DART_EXPORT Dart_Handle Dart_LoadScriptFromSnapshot(const uint8_t* buffer,
+                                                    intptr_t buffer_len);
 
 /**
  * Gets the library for the root script for the current isolate.
diff --git a/runtime/lib/byte_array.cc b/runtime/lib/byte_array.cc
index 08e0bc8..4a806a6 100644
--- a/runtime/lib/byte_array.cc
+++ b/runtime/lib/byte_array.cc
@@ -252,12 +252,12 @@
 
 
 DEFINE_NATIVE_ENTRY(ByteArray_getFloat32x4, 2) {
-  UNALIGNED_GETTER(ByteArray, Float32x4, simd_value_t);
+  UNALIGNED_GETTER(ByteArray, Float32x4, simd128_value_t);
 }
 
 
 DEFINE_NATIVE_ENTRY(ByteArray_setFloat32x4, 3) {
-  UNALIGNED_SETTER(ByteArray, Float32x4, value, simd_value_t);
+  UNALIGNED_SETTER(ByteArray, Float32x4, value, simd128_value_t);
 }
 
 
@@ -621,7 +621,8 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
   intptr_t len = length.Value();
   LengthCheck(len, Float32x4Array::kMaxElements);
-  simd_value_t* bytes = OS::AllocateAlignedArray<simd_value_t>(len, kAlignment);
+  simd128_value_t* bytes =
+      OS::AllocateAlignedArray<simd128_value_t>(len, kAlignment);
   const ExternalFloat32x4Array& obj =
       ExternalFloat32x4Array::Handle(ExternalFloat32x4Array::New(bytes, len));
   obj.AddFinalizer(bytes, PeerFinalizer);
@@ -630,12 +631,12 @@
 
 
 DEFINE_NATIVE_ENTRY(Float32x4Array_getIndexed, 2) {
-  GETTER(Float32x4Array, Float32x4, simd_value_t);
+  GETTER(Float32x4Array, Float32x4, simd128_value_t);
 }
 
 
 DEFINE_NATIVE_ENTRY(Float32x4Array_setIndexed, 3) {
-  SETTER(Float32x4Array, Float32x4, value, simd_value_t);
+  SETTER(Float32x4Array, Float32x4, value, simd128_value_t);
 }
 
 
@@ -816,12 +817,12 @@
 // ExternalFloat32x4Array
 
 DEFINE_NATIVE_ENTRY(ExternalFloat32x4Array_getIndexed, 2) {
-  GETTER(ExternalFloat32x4Array, Float32x4, simd_value_t);
+  GETTER(ExternalFloat32x4Array, Float32x4, simd128_value_t);
 }
 
 
 DEFINE_NATIVE_ENTRY(ExternalFloat32x4Array_setIndexed, 3) {
-  SETTER(ExternalFloat32x4Array, Float32x4, value, simd_value_t);
+  SETTER(ExternalFloat32x4Array, Float32x4, value, simd128_value_t);
 }
 
 
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 081ba83..8e6d905 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -3,4 +3,4 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "dart:math";
-import "dart:scalarlist";
+import "dart:typeddata";
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index a521a63..144e9c9 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -2,6 +2,63 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+class _CloseToken {
+  /// This token is sent from [IsolateSink]s to [IsolateStream]s to ask them to
+  /// close themselves.
+  const _CloseToken();
+}
+
+patch bool _isCloseToken(var object) {
+  // TODO(floitsch): can we compare against const _CloseToken()?
+  return object is _CloseToken;
+}
+
+patch class MessageBox {
+  /* patch */ MessageBox.oneShot() : this._oneShot(new ReceivePort());
+  MessageBox._oneShot(ReceivePort receivePort)
+      : stream = new IsolateStream._fromOriginalReceivePortOneShot(receivePort),
+        sink = new _IsolateSink._fromPort(receivePort.toSendPort());
+
+  /* patch */ MessageBox() : this._(new ReceivePort());
+  MessageBox._(ReceivePort receivePort)
+      : stream = new IsolateStream._fromOriginalReceivePort(receivePort),
+        sink = new _IsolateSink._fromPort(receivePort.toSendPort());
+}
+
+class _IsolateSink implements IsolateSink {
+  bool _isClosed = false;
+  final SendPort _port;
+  _IsolateSink._fromPort(this._port);
+
+  void add(dynamic message) {
+    _port.send(message);
+  }
+
+  void addError(AsyncError errorEvent) {
+    throw new UnimplementedError("signalError on isolate streams");
+  }
+
+  void close() {
+    if (_isClosed) return;
+    add(const _CloseToken());
+    _isClosed = true;
+  }
+
+  bool operator==(var other) {
+    return other is IsolateSink && _port == other._port;
+  }
+
+  int get hashCode => _port.hashCode + 499;
+}
+
+patch IsolateSink streamSpawnFunction(
+    void topLevelFunction(),
+    [bool unhandledExceptionCallback(IsolateUnhandledException e)]) {
+  SendPort sendPort = spawnFunction(topLevelFunction,
+                                    unhandledExceptionCallback);
+  return new _IsolateSink._fromPort(sendPort);
+}
+
 patch class ReceivePort {
   /* patch */ factory ReceivePort() {
     return new _ReceivePortImpl();
@@ -131,7 +188,7 @@
   }
 
   /* patch */ static spawnFunction(void topLevelFunction(),
-      [bool UnhandledExceptionCallback(IsolateUnhandledException e)]) 
+      [bool unhandledExceptionCallback(IsolateUnhandledException e)])
       native "isolate_spawnFunction";
 
   /* patch */ static spawnUri(String uri) native "isolate_spawnUri";
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index c01084b..d17d82e 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.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 "dart:scalarlist";
+import "dart:typeddata";
 
 // A VM patch of the dart:math library.
 patch num pow(num x, num exponent) {
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index c282b7a..9a06b24 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -215,8 +215,7 @@
 
 
 DEFINE_NATIVE_ENTRY(StringBuffer_createStringFromUint16Array, 3) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Uint16Array, codeUnits,
-                               arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(TypedData, codeUnits, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Bool, isLatin1, arguments->NativeArgAt(2));
   intptr_t array_length = codeUnits.Length();
@@ -231,7 +230,7 @@
       : String::Handle(TwoByteString::New(length_value, Heap::kNew));
   NoGCScope no_gc;
 
-  uint16_t* data_position = reinterpret_cast<uint16_t*>(codeUnits.ByteAddr(0));
+  uint16_t* data_position = reinterpret_cast<uint16_t*>(codeUnits.DataAddr(0));
   String::Copy(result, 0, data_position, length_value);
   return result.raw();
 }
diff --git a/runtime/lib/typeddata.dart b/runtime/lib/typeddata.dart
index cf049d7..ab40008 100644
--- a/runtime/lib/typeddata.dart
+++ b/runtime/lib/typeddata.dart
@@ -228,12 +228,12 @@
 patch class ByteData {
   /* patch */ factory ByteData(int length) {
     var list = new _Uint8Array(length);
-    return new _ByteDataView(list.buffer);
+    return new _ByteDataView(list.buffer, 0, length);
   }
 
   /* patch */ factory ByteData.transferable(int length) {
     var list = new _Uint8Array.transferable(length);
-    return new _ByteDataView(list.buffer);
+    return new _ByteDataView(list.buffer, 0, length);
   }
 
   /* patch */ factory ByteData.view(ByteBuffer buffer,
diff --git a/runtime/platform/assert.h b/runtime/platform/assert.h
index d92897d..3b5f32e 100644
--- a/runtime/platform/assert.h
+++ b/runtime/platform/assert.h
@@ -267,6 +267,9 @@
 
 #define DEBUG_ASSERT(cond)
 
+#endif  // if defined(DEBUG)
+
+
 // The COMPILE_ASSERT macro can be used to verify that a compile time
 // expression is true. For example, you could use it to verify the
 // size of a static array:
@@ -290,8 +293,6 @@
   typedef CompileAssert<(static_cast<bool>(expr))>      \
   msg[static_cast<bool>(expr) ? 1 : -1]
 
-#endif  // if defined(DEBUG)
-
 
 #if defined(TESTING)
 #define EXPECT(condition)                                                      \
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index f06f04c..2d566bb 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -72,6 +72,45 @@
 #error Automatic target os detection failed.
 #endif
 
+struct simd128_value_t {
+  float storage[4];
+  simd128_value_t& readFrom(const float* v) {
+    storage[0] = v[0];
+    storage[1] = v[1];
+    storage[2] = v[2];
+    storage[3] = v[3];
+    return *this;
+  }
+  simd128_value_t& readFrom(const uint32_t* v) {
+    const float* vv = reinterpret_cast<const float*>(v);
+    storage[0] = vv[0];
+    storage[1] = vv[1];
+    storage[2] = vv[2];
+    storage[3] = vv[3];
+    return *this;
+  }
+  simd128_value_t& readFrom(const simd128_value_t* v) {
+    *this = *v;
+    return *this;
+  }
+  void writeTo(float* v) {
+    v[0] = storage[0];
+    v[1] = storage[1];
+    v[2] = storage[2];
+    v[3] = storage[3];
+  }
+  void writeTo(uint32_t* v) {
+    float* vv = reinterpret_cast<float*>(v);
+    vv[0] = storage[0];
+    vv[1] = storage[1];
+    vv[2] = storage[2];
+    vv[3] = storage[3];
+  }
+  void writeTo(simd128_value_t* v) {
+    *v = *this;
+  }
+};
+
 // Processor architecture detection.  For more info on what's defined, see:
 //   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
 //   http://www.agner.org/optimize/calling_conventions.pdf
@@ -79,47 +118,23 @@
 #if defined(_M_X64) || defined(__x86_64__)
 #define HOST_ARCH_X64 1
 #define ARCH_IS_64_BIT 1
-#include <xmmintrin.h>  // NOLINT
 #define kFpuRegisterSize 16
-typedef __m128 fpu_register_t;
-typedef __m128 simd_value_t;
-// Unaligned load.
-#define simd_value_safe_load(addr)                                             \
-  _mm_loadu_ps(reinterpret_cast<const float*>(addr))
-// Unaligned store.
-#define simd_value_safe_store(addr, value)                                     \
-  _mm_storeu_ps(reinterpret_cast<float*>(addr), value)
+typedef simd128_value_t fpu_register_t;
 #elif defined(_M_IX86) || defined(__i386__)
 #define HOST_ARCH_IA32 1
 #define ARCH_IS_32_BIT 1
-#include <xmmintrin.h>  // NOLINT
 #define kFpuRegisterSize 16
-typedef __m128 fpu_register_t;
-typedef __m128 simd_value_t;
-// Unaligned load.
-#define simd_value_safe_load(addr)                                             \
-  _mm_loadu_ps(reinterpret_cast<const float*>(addr))
-// Unaligned store.
-#define simd_value_safe_store(addr, value)                                     \
-  _mm_storeu_ps(reinterpret_cast<float*>(addr), value)
+typedef simd128_value_t fpu_register_t;
 #elif defined(__ARMEL__)
 #define HOST_ARCH_ARM 1
 #define ARCH_IS_32_BIT 1
 #define kFpuRegisterSize 8
 typedef double fpu_register_t;
-// TODO(johnmccutchan): ARM simd type.
-typedef struct {
-  uint32_t data_[4];
-} simd_value_t;
 #elif defined(__MIPSEL__)
 #define HOST_ARCH_MIPS 1
 #define ARCH_IS_32_BIT 1
 #define kFpuRegisterSize 8
 typedef double fpu_register_t;
-// TODO(johnmccutchan): MIPS simd type.
-typedef struct {
-  uint32_t data_[4];
-} simd_value_t;
 #else
 #error Architecture was not detected as supported by Dart.
 #endif
@@ -215,7 +230,7 @@
 const int kWordSize = sizeof(word);
 const int kDoubleSize = sizeof(double);  // NOLINT
 const int kFloatSize = sizeof(float);  // NOLINT
-const int kSimd128Size = 16;
+const int kSimd128Size = sizeof(simd128_value_t);  // NOLINT
 #ifdef ARCH_IS_32_BIT
 const int kWordSizeLog2 = 2;
 const uword kUwordMax = kMaxUint32;
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index acd74eb..a86de87 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -2,11 +2,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-cc/New: Crash # Issue 6958.
-cc/TypeVariableReflection: Crash # Issue 6958.
-cc/LibraryGetClassNames: Fail # Issue 6958.
-cc/ImportLibrary5: Fail # Issue 6958.
-
 # These tests are expected to crash on all platforms.
 cc/ArrayNew_Overflow_Crash: Crash
 cc/AllocGeneric_Overflow: Crash
@@ -74,6 +69,7 @@
 # Tests needing type check support.
 cc/DartStaticResolve: Crash
 cc/DartDynamicResolve: Crash
+cc/FindCodeObject: Crash
 
 [ $arch == mips ]
 *: Skip
diff --git a/runtime/tools/gyp/find_mac_sdk.py b/runtime/tools/gyp/find_mac_sdk.py
new file mode 100755
index 0000000..baf6279
--- /dev/null
+++ b/runtime/tools/gyp/find_mac_sdk.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# 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 is a copy of Chromium's src/build/mac/find_sdk.py.
+# Revision 180337.
+
+import os
+import re
+import subprocess
+import sys
+
+"""Prints the lowest locally available SDK version greater than or equal to a
+given minimum sdk version to standard output.
+
+Usage:
+  python find_sdk.py 10.6  # Ignores SDKs < 10.6
+"""
+
+from optparse import OptionParser
+
+
+def parse_version(version_str):
+  """'10.6' => [10, 6]"""
+  return map(int, re.findall(r'(\d+)', version_str))
+
+
+def main():
+  parser = OptionParser()
+  parser.add_option("--verify",
+                    action="store_true", dest="verify", default=False,
+                    help="return the sdk argument and warn if it doesn't exist")
+  parser.add_option("--sdk_path",
+                    action="store", type="string", dest="sdk_path", default="",
+                    help="user-specified SDK path; bypasses verification")
+  (options, args) = parser.parse_args()
+  min_sdk_version = args[0]
+
+  job = subprocess.Popen(['xcode-select', '-print-path'],
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+  out, err = job.communicate()
+  if job.returncode != 0:
+    print >>sys.stderr, out
+    print >>sys.stderr, err
+    raise Exception(('Error %d running xcode-select, you might have to run '
+      '|sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer| '
+      'if you are using Xcode 4.') % job.returncode)
+  # The Developer folder moved in Xcode 4.3.
+  xcode43_sdk_path = os.path.join(
+      out.rstrip(), 'Platforms/MacOSX.platform/Developer/SDKs')
+  if os.path.isdir(xcode43_sdk_path):
+    sdk_dir = xcode43_sdk_path
+  else:
+    sdk_dir = os.path.join(out.rstrip(), 'SDKs')
+  sdks = [re.findall('^MacOSX(10\.\d+)\.sdk$', s) for s in os.listdir(sdk_dir)]
+  sdks = [s[0] for s in sdks if s]  # [['10.5'], ['10.6']] => ['10.5', '10.6']
+  sdks = [s for s in sdks  # ['10.5', '10.6'] => ['10.6']
+          if parse_version(s) >= parse_version(min_sdk_version)]
+  if not sdks:
+    raise Exception('No %s+ SDK found' % min_sdk_version)
+  best_sdk = sorted(sdks, key=parse_version)[0]
+
+  if options.verify and best_sdk != min_sdk_version and not options.sdk_path:
+    print >>sys.stderr, ''
+    print >>sys.stderr, '                                           vvvvvvv'
+    print >>sys.stderr, ''
+    print >>sys.stderr, \
+        'This build requires the %s SDK, but it was not found on your system.' \
+        % min_sdk_version
+    print >>sys.stderr, \
+        'Either install it, or explicitly set mac_sdk in your GYP_DEFINES.'
+    print >>sys.stderr, ''
+    print >>sys.stderr, '                                           ^^^^^^^'
+    print >>sys.stderr, ''
+    return min_sdk_version
+
+  return best_sdk
+
+
+if __name__ == '__main__':
+  if sys.platform != 'darwin':
+    raise Exception("This script only runs on Mac")
+  print main()
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index af41d08..023a05a 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1262,6 +1262,9 @@
 
 
 void Assembler::LoadObject(Register rd, const Object& object) {
+  // Since objects in the VM heap are never relocated, test instead
+  // if (object.IsSmi() || object.InVMHeap()) {
+  // and modify the decoding code in CallPattern to understand movt, movw.
   if (object.IsNull() ||
       object.IsSmi() ||
       (object.raw() == Bool::True().raw()) ||
@@ -1282,6 +1285,13 @@
 }
 
 
+void Assembler::CompareObject(Register rn, const Object& object) {
+  ASSERT(rn != IP);
+  LoadObject(IP, object);
+  cmp(rn, ShifterOperand(IP));
+}
+
+
 void Assembler::Bind(Label* label) {
   ASSERT(!label->IsBound());
   int bound_pc = buffer_.Size();
@@ -1919,6 +1929,8 @@
 
 
 int32_t Assembler::AddObject(const Object& obj) {
+  ASSERT(obj.IsNotTemporaryScopedHandle());
+  ASSERT(obj.IsOld());
   if (object_pool_.IsNull()) {
     // The object pool cannot be used in the vm isolate.
     ASSERT(Isolate::Current() != Dart::vm_isolate());
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 67e385a..199b80c 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -555,6 +555,7 @@
   void Drop(intptr_t stack_elements);
   void LoadObject(Register rd, const Object& object);
   void PushObject(const Object& object);
+  void CompareObject(Register rn, const Object& object);
   void LoadWordFromPoolOffset(Register rd, int32_t offset);
   void LoadFromOffset(LoadOperandType type,
                       Register reg,
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 2acf8ce..8d0221c 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -1850,6 +1850,26 @@
 
 
 // Destroys the value register.
+void Assembler::StoreIntoObjectFilterNoSmi(Register object,
+                                           Register value,
+                                           Label* no_update) {
+  COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) &&
+                 (kOldObjectAlignmentOffset == 0), young_alignment);
+
+  // Write-barrier triggers if the value is in the new space (has bit set) and
+  // the object is in the old space (has bit cleared).
+  // To check that we could compute value & ~object and skip the write barrier
+  // if the bit is not set. However we can't destroy the object.
+  // However to preserve the object we compute negated expression
+  // ~value | object instead and skip the write barrier if the bit is set.
+  notl(value);
+  orl(value, object);
+  testl(value, Immediate(kNewObjectAlignmentOffset));
+  j(NOT_ZERO, no_update, Assembler::kNearJump);
+}
+
+
+// Destroys the value register.
 void Assembler::StoreIntoObjectFilter(Register object,
                                       Register value,
                                       Label* no_update) {
@@ -1872,12 +1892,17 @@
 
 void Assembler::StoreIntoObject(Register object,
                                 const Address& dest,
-                                Register value) {
+                                Register value,
+                                bool can_value_be_smi) {
   ASSERT(object != value);
   TraceStoreIntoObject(object, dest, value);
   movl(dest, value);
   Label done;
-  StoreIntoObjectFilter(object, value, &done);
+  if (can_value_be_smi) {
+    StoreIntoObjectFilter(object, value, &done);
+  } else {
+    StoreIntoObjectFilterNoSmi(object, value, &done);
+  }
   // A store buffer update is required.
   if (value != EAX) pushl(EAX);  // Preserve EAX.
   leal(EAX, dest);
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 07088a4..d147296 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -611,7 +611,8 @@
 
   void StoreIntoObject(Register object,  // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
-                       Register value);  // Value we are storing.
+                       Register value,  // Value we are storing.
+                       bool can_value_be_smi = true);
 
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
@@ -790,6 +791,11 @@
 
   void StoreIntoObjectFilter(Register object, Register value, Label* no_update);
 
+  // Shorter filtering sequence that assumes that value is not a smi.
+  void StoreIntoObjectFilterNoSmi(Register object,
+                                  Register value,
+                                  Label* no_update);
+
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(Assembler);
 };
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index f74e06e..88bd937 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -22,6 +22,40 @@
   }
 }
 
+
+void Assembler::Bind(Label* label) {
+  ASSERT(!label->IsBound());
+  int bound_pc = buffer_.Size();
+  while (label->IsLinked()) {
+    int32_t position = label->Position();
+    int32_t next = buffer_.Load<int32_t>(position);
+    // Reletive destination from an instruction after the branch.
+    int32_t dest = bound_pc - (position + Instr::kInstrSize);
+    int32_t encoded = Assembler::EncodeBranchOffset(dest, next);
+    buffer_.Store<int32_t>(position, encoded);
+    label->position_ = Assembler::DecodeBranchOffset(next);
+  }
+  label->BindTo(bound_pc);
+  delay_slot_available_ = false;
+}
+
+
+int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t instr) {
+  ASSERT(Utils::IsAligned(offset, 4));
+  ASSERT(Utils::IsInt(18, offset));
+
+  // Properly preserve only the bits supported in the instruction.
+  offset >>= 2;
+  offset &= kBranchOffsetMask;
+  return (instr & ~kBranchOffsetMask) | offset;
+}
+
+
+int Assembler::DecodeBranchOffset(int32_t instr) {
+  // Sign-extend, left-shift by 2.
+  return (((instr & kBranchOffsetMask) << 16) >> 14);
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 67ad01f..ed85493 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -147,9 +147,7 @@
     UNIMPLEMENTED();
   }
 
-  void Bind(Label* label) {
-    UNIMPLEMENTED();
-  }
+  void Bind(Label* label);
 
   // Misc. functionality
   int CodeSize() const { return buffer_.Size(); }
@@ -224,7 +222,7 @@
     return this;
   }
 
-  // CPU instructions.
+  // CPU instructions in alphabetical order.
   void addiu(Register rt, Register rs, const Immediate& imm) {
     ASSERT(Utils::IsInt(16, imm.value()));
     uint16_t imm_value = static_cast<uint16_t>(imm.value());
@@ -245,6 +243,101 @@
     EmitIType(ANDI, rs, rt, imm_value);
   }
 
+  // Unconditional branch.
+  void b(Label* l) {
+    beq(R0, R0, l);
+  }
+
+  // Branch if equal.
+  void beq(Register rs, Register rt, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitBranch(BEQ, rs, rt, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if equal, likely taken.
+  // Delay slot executed only when branch taken.
+  void beql(Register rs, Register rt, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitBranch(BEQL, rs, rt, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if rs >= 0.
+  void bgez(Register rs, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitRegImmBranch(BGEZ, rs, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if rs >= 0, likely taken.
+  // Delay slot executed only when branch taken.
+  void bgezl(Register rs, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitRegImmBranch(BGEZL, rs, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if rs > 0.
+  void bgtz(Register rs, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitBranch(BGTZ, rs, R0, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if rs > 0, likely taken.
+  // Delay slot executed only when branch taken.
+  void bgtzl(Register rs, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitBranch(BGTZL, rs, R0, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if rs <= 0.
+  void blez(Register rs, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitBranch(BLEZ, rs, R0, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if rs <= 0, likely taken.
+  // Delay slot executed only when branch taken.
+  void blezl(Register rs, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitBranch(BLEZL, rs, R0, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if rs < 0.
+  void bltz(Register rs, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitRegImmBranch(BLTZ, rs, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if rs < 0, likely taken.
+  // Delay slot executed only when branch taken.
+  void bltzl(Register rs, Label* l) {
+    ASSERT(!in_delay_slot_);
+    EmitRegImmBranch(BLTZL, rs, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if not equal.
+  void bne(Register rs, Register rt, Label* l) {
+    ASSERT(!in_delay_slot_);  // Jump within a delay slot is not supported.
+    EmitBranch(BNE, rs, rt, l);
+    EmitBranchDelayNop();
+  }
+
+  // Branch if not equal, likely taken.
+  // Delay slot executed only when branch taken.
+  void bnel(Register rs, Register rt, Label* l) {
+    ASSERT(!in_delay_slot_);  // Jump within a delay slot is not supported.
+    EmitBranch(BNEL, rs, rt, l);
+    EmitBranchDelayNop();
+  }
+
   void break_(int32_t code) {
     ASSERT(Utils::IsUint(20, code));
     Emit(SPECIAL << kOpcodeShift |
@@ -268,6 +361,18 @@
     EmitRType(SPECIAL, rs, rt, R0, 0, DIVU);
   }
 
+  void jalr(Register rs, Register rd = RA) {
+    ASSERT(rs != rd);
+    ASSERT(!in_delay_slot_);  // Jump within a delay slot is not supported.
+    EmitRType(SPECIAL, rs, R0, rd, 0, JALR);
+    EmitBranchDelayNop();
+  }
+
+  void jr(Register rs) {
+    ASSERT(!in_delay_slot_);  // Jump within a delay slot is not supported.
+    EmitRType(SPECIAL, rs, R0, R0, 0, JR);
+    EmitBranchDelayNop();
+  }
 
   void lb(Register rt, const Address& addr) {
     EmitLoadStore(LB, rt, addr);
@@ -303,19 +408,44 @@
     EmitRType(SPECIAL, R0, R0, rd, 0, MFLO);
   }
 
+  void mov(Register rd, Register rs) {
+    or_(rd, rs, ZR);
+  }
+
+  void movn(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, MOVN);
+  }
+
+  void movz(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ);
+  }
+
+  void mult(Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, R0, 0, MULT);
+  }
+
+  void multu(Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, R0, 0, MULTU);
+  }
+
+  void nop() {
+    Emit(Instr::kNopInstruction);
+  }
+
+  void nor(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, NOR);
+  }
+
+  void or_(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, OR);
+  }
+
   void ori(Register rt, Register rs, const Immediate& imm) {
     ASSERT(Utils::IsUint(16, imm.value()));
     uint16_t imm_value = static_cast<uint16_t>(imm.value());
     EmitIType(ORI, rs, rt, imm_value);
   }
 
-  void jr(Register rs) {
-    ASSERT(!in_delay_slot_);  // Jump within a delay slot is not supported.
-    EmitRType(SPECIAL, rs, R0, R0, 0, JR);
-    Emit(Instr::kNopInstruction);  // Branch delay NOP.
-    delay_slot_available_ = true;
-  }
-
   void sb(Register rt, const Address& addr) {
     EmitLoadStore(SB, rt, addr);
   }
@@ -324,18 +454,62 @@
     EmitLoadStore(SH, rt, addr);
   }
 
-  void sw(Register rt, const Address& addr) {
-    EmitLoadStore(SW, rt, addr);
-  }
-
   void sll(Register rd, Register rt, int sa) {
     EmitRType(SPECIAL, R0, rt, rd, sa, SLL);
   }
 
-  // Macros.
+  void sllv(Register rd, Register rt, Register rs) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, SLLV);
+  }
+
+  void slt(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, SLT);
+  }
+
+  void sltu(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, SLTU);
+  }
+
+  void sra(Register rd, Register rt, int sa) {
+    EmitRType(SPECIAL, R0, rt, rd, sa, SRA);
+  }
+
+  void srav(Register rd, Register rt, Register rs) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, SRAV);
+  }
+
+  void srl(Register rd, Register rt, int sa) {
+    EmitRType(SPECIAL, R0, rt, rd, sa, SRL);
+  }
+
+  void srlv(Register rd, Register rt, Register rs) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, SRLV);
+  }
+
+  void sub(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, SUB);
+  }
+
+  void subu(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, SUBU);
+  }
+
+  void sw(Register rt, const Address& addr) {
+    EmitLoadStore(SW, rt, addr);
+  }
+
+  void xor_(Register rd, Register rs, Register rt) {
+    EmitRType(SPECIAL, rs, rt, rd, 0, XOR);
+  }
+
+  // Macros in alphabetical order.
   void LoadImmediate(Register rd, int32_t value) {
-    lui(rd, Immediate((value >> 16) & 0xffff));
-    ori(rd, rd, Immediate(value & 0xffff));
+    if (Utils::IsInt(16, value)) {
+      addiu(rd, ZR, Immediate(value));
+    } else {
+      lui(rd, Immediate((value >> 16) & 0xffff));
+      ori(rd, rd, Immediate(value & 0xffff));
+    }
   }
 
  private:
@@ -419,6 +593,40 @@
          func << kFunctionShift);
   }
 
+  void EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
+    if (label->IsBound()) {
+      // Reletive destination from an instruction after the branch.
+      int32_t dest = label->Position() - (buffer_.Size() + Instr::kInstrSize);
+      uint16_t dest_off = EncodeBranchOffset(dest, 0);
+      EmitIType(b, rs, rt, dest_off);
+    } else {
+      int position = buffer_.Size();
+      EmitIType(b, rs, rt, label->position_);
+      label->LinkTo(position);
+    }
+  }
+
+  void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) {
+    if (label->IsBound()) {
+      // Reletive destination from an instruction after the branch.
+      int32_t dest = label->Position() - (buffer_.Size() + Instr::kInstrSize);
+      uint16_t dest_off = EncodeBranchOffset(dest, 0);
+      EmitRegImmType(REGIMM, rs, b, dest_off);
+    } else {
+      int position = buffer_.Size();
+      EmitRegImmType(REGIMM, rs, b, label->position_);
+      label->LinkTo(position);
+    }
+  }
+
+  static int32_t EncodeBranchOffset(int32_t offset, int32_t instr);
+  static int DecodeBranchOffset(int32_t instr);
+
+  void EmitBranchDelayNop() {
+    Emit(Instr::kNopInstruction);  // Branch delay NOP.
+    delay_slot_available_ = true;
+  }
+
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(Assembler);
 };
diff --git a/runtime/vm/assembler_mips_test.cc b/runtime/vm/assembler_mips_test.cc
index 82287ff..cf122b4 100644
--- a/runtime/vm/assembler_mips_test.cc
+++ b/runtime/vm/assembler_mips_test.cc
@@ -14,6 +14,17 @@
 
 #define __ assembler->
 
+ASSEMBLER_TEST_GENERATE(Simple, assembler) {
+  __ LoadImmediate(V0, 42);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Simple, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
 
 ASSEMBLER_TEST_GENERATE(Addiu, assembler) {
   __ addiu(V0, ZR, Immediate(42));
@@ -322,13 +333,670 @@
 }
 
 
-ASSEMBLER_TEST_GENERATE(Simple, assembler) {
+ASSEMBLER_TEST_GENERATE(Sll, assembler) {
+  __ LoadImmediate(R1, 21);
+  __ sll(V0, R1, 1);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Sll, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Srl, assembler) {
+  __ LoadImmediate(R1, 84);
+  __ srl(V0, R1, 1);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Srl, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(LShifting, assembler) {
+  __ LoadImmediate(R1, 1);
+  __ sll(R1, R1, 31);
+  __ srl(V0, R1, 31);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(LShifting, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(RShifting, assembler) {
+  __ LoadImmediate(R1, 1);
+  __ sll(R1, R1, 31);
+  __ sra(V0, R1, 31);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(RShifting, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Sllv, assembler) {
+  __ LoadImmediate(R1, 21);
+  __ LoadImmediate(R2, 1);
+  __ sllv(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Sllv, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Srlv, assembler) {
+  __ LoadImmediate(R1, 84);
+  __ LoadImmediate(R2, 1);
+  __ srlv(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Srlv, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(LShiftingV, assembler) {
+  __ LoadImmediate(R1, 1);
+  __ LoadImmediate(R2, 31);
+  __ sllv(R1, R1, R2);
+  __ srlv(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(LShiftingV, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(RShiftingV, assembler) {
+  __ LoadImmediate(R1, 1);
+  __ LoadImmediate(R2, 31);
+  __ sllv(R1, R1, R2);
+  __ srav(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(RShiftingV, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Mult_pos, assembler) {
+  __ LoadImmediate(R1, 6);
+  __ LoadImmediate(R2, 7);
+  __ mult(R1, R2);
+  __ mflo(V0);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Mult_pos, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Mult_neg, assembler) {
+  __ LoadImmediate(R1, -6);
+  __ LoadImmediate(R2, 7);
+  __ mult(R1, R2);
+  __ mflo(V0);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Mult_neg, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Mult_neg_hi, assembler) {
+  __ LoadImmediate(R1, -6);
+  __ LoadImmediate(R2, 7);
+  __ mult(R1, R2);
+  __ mfhi(V0);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Mult_neg_hi, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Multu_lo, assembler) {
+  __ LoadImmediate(R1, 6);
+  __ LoadImmediate(R2, 7);
+  __ multu(R1, R2);
+  __ mflo(V0);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Multu_lo, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Multu_hi, assembler) {
+  __ LoadImmediate(R1, 65536);
+  __ LoadImmediate(R2, 65536);
+  __ multu(R1, R2);
+  __ mfhi(V0);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Multu_hi, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Subu, assembler) {
+  __ LoadImmediate(R1, 737);
+  __ LoadImmediate(R2, 695);
+  __ subu(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Subu, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Or, assembler) {
+  __ LoadImmediate(R1, 34);
+  __ LoadImmediate(R2, 8);
+  __ or_(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Or, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Nor, assembler) {
+  __ LoadImmediate(R1, -47);
+  __ LoadImmediate(R2, -60);
+  __ nor(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Nor, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Xor, assembler) {
+  __ LoadImmediate(R1, 51);
+  __ LoadImmediate(R2, 25);
+  __ xor_(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Xor, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Slt, assembler) {
+  __ LoadImmediate(R1, -1);
+  __ LoadImmediate(R2, 0);
+  __ slt(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Slt, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Sltu, assembler) {
+  __ LoadImmediate(R1, -1);
+  __ LoadImmediate(R2, 0);
+  __ sltu(V0, R1, R2);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Sltu, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Movz, assembler) {
+  __ LoadImmediate(R1, 42);
+  __ LoadImmediate(R2, 23);
+  __ slt(R3, R1, R2);
+  __ movz(V0, R1, R3);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Movz, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Movn, assembler) {
+  __ LoadImmediate(R1, 42);
+  __ LoadImmediate(R2, 23);
+  __ slt(R3, R2, R1);
+  __ movn(V0, R1, R3);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Movn, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Jr_delay, assembler) {
   __ jr(RA);
   __ delay_slot()->ori(V0, ZR, Immediate(42));
 }
 
 
-ASSEMBLER_TEST_RUN(Simple, test) {
+ASSEMBLER_TEST_RUN(Jr_delay, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Beq_backward, assembler) {
+  Label l;
+
+  __ LoadImmediate(R1, 0);
+  __ LoadImmediate(R2, 1);
+  __ Bind(&l);
+  __ addiu(R1, R1, Immediate(1));
+  __ beq(R1, R2, &l);
+  __ ori(V0, R1, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Beq_backward, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(2, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Beq_backward_delay, assembler) {
+  Label l;
+
+  __ LoadImmediate(R1, 0);
+  __ LoadImmediate(R2, 1);
+  __ Bind(&l);
+  __ addiu(R1, R1, Immediate(1));
+  __ beq(R1, R2, &l);
+  __ delay_slot()->addiu(R1, R1, Immediate(1));
+  __ ori(V0, R1, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Beq_backward_delay, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Beq_forward_taken, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 1);
+  __ LoadImmediate(R6, 1);
+
+  __ LoadImmediate(V0, 42);
+  __ beq(R5, R6, &l);
+  __ LoadImmediate(V0, 0);
+  __ Bind(&l);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Beq_forward_taken, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Beq_forward_not_taken, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 0);
+  __ LoadImmediate(R6, 1);
+
+  __ LoadImmediate(V0, 42);
+  __ beq(R5, R6, &l);
+  __ LoadImmediate(V0, 0);
+  __ Bind(&l);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Beq_forward_not_taken, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Beq_forward_taken2, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 1);
+  __ LoadImmediate(R6, 1);
+
+  __ LoadImmediate(V0, 42);
+  __ beq(R5, R6, &l);
+  __ nop();
+  __ nop();
+  __ LoadImmediate(V0, 0);
+  __ Bind(&l);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Beq_forward_taken2, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Beq_forward_taken_delay, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 1);
+  __ LoadImmediate(R6, 1);
+
+  __ LoadImmediate(V0, 42);
+  __ beq(R5, R6, &l);
+  __ delay_slot()->ori(V0, V0, Immediate(1));
+  __ LoadImmediate(V0, 0);
+  __ Bind(&l);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Beq_forward_taken_delay, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(43, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Beq_forward_not_taken_delay, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 0);
+  __ LoadImmediate(R6, 1);
+
+  __ LoadImmediate(V0, 42);
+  __ beq(R5, R6, &l);
+  __ delay_slot()->ori(V0, V0, Immediate(1));
+  __ addiu(V0, V0, Immediate(1));
+  __ Bind(&l);
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Beq_forward_not_taken_delay, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(44, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Beql_backward_delay, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 0);
+  __ LoadImmediate(R6, 1);
+  __ Bind(&l);
+  __ addiu(R5, R5, Immediate(1));
+  __ beql(R5, R6, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Beql_backward_delay, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Bgez, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 3);
+  __ Bind(&l);
+  __ bgez(R5, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(-1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Bgez, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Bgezl, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 3);
+  __ Bind(&l);
+  __ bgezl(R5, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(-1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Bgezl, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Blez, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, -3);
+  __ Bind(&l);
+  __ blez(R5, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Blez, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(2, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Blezl, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, -3);
+  __ Bind(&l);
+  __ blezl(R5, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Blezl, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Bgtz, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 3);
+  __ Bind(&l);
+  __ bgtz(R5, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(-1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Bgtz, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Bgtzl, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 3);
+  __ Bind(&l);
+  __ bgtzl(R5, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(-1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Bgtzl, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Bltz, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, -3);
+  __ Bind(&l);
+  __ bltz(R5, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Bltz, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Bltzl, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, -3);
+  __ Bind(&l);
+  __ bltzl(R5, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Bltzl, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Bne, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 3);
+  __ Bind(&l);
+  __ bne(R5, R0, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(-1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Bne, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Bnel, assembler) {
+  Label l;
+
+  __ LoadImmediate(R5, 3);
+  __ Bind(&l);
+  __ bnel(R5, R0, &l);
+  __ delay_slot()->addiu(R5, R5, Immediate(-1));
+  __ ori(V0, R5, Immediate(0));
+  __ jr(RA);
+}
+
+
+ASSEMBLER_TEST_RUN(Bnel, test) {
+  typedef int (*SimpleCode)();
+  EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Jalr_delay, assembler) {
+  __ mov(R2, RA);
+  __ jalr(R2, RA);
+  __ delay_slot()->ori(V0, ZR, Immediate(42));
+}
+
+
+ASSEMBLER_TEST_RUN(Jalr_delay, test) {
   typedef int (*SimpleCode)();
   EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
 }
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 0d621b1..49acf4a 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -1690,6 +1690,14 @@
 }
 
 
+void Assembler::notl(Register reg) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRegisterREX(reg, REX_NONE);
+  EmitUint8(0xF7);
+  EmitUint8(0xD0 | (reg & 7));
+}
+
+
 void Assembler::notq(Register reg) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitRegisterREX(reg, REX_W);
@@ -2008,6 +2016,26 @@
 
 
 // Destroys the value register.
+void Assembler::StoreIntoObjectFilterNoSmi(Register object,
+                                           Register value,
+                                           Label* no_update) {
+  COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) &&
+                 (kOldObjectAlignmentOffset == 0), young_alignment);
+
+  // Write-barrier triggers if the value is in the new space (has bit set) and
+  // the object is in the old space (has bit cleared).
+  // To check that we could compute value & ~object and skip the write barrier
+  // if the bit is not set. However we can't destroy the object.
+  // However to preserve the object we compute negated expression
+  // ~value | object instead and skip the write barrier if the bit is set.
+  notl(value);
+  orl(value, object);
+  testl(value, Immediate(kNewObjectAlignmentOffset));
+  j(NOT_ZERO, no_update, Assembler::kNearJump);
+}
+
+
+// Destroys the value register.
 void Assembler::StoreIntoObjectFilter(Register object,
                                       Register value,
                                       Label* no_update) {
@@ -2030,11 +2058,16 @@
 
 void Assembler::StoreIntoObject(Register object,
                                 const Address& dest,
-                                Register value) {
+                                Register value,
+                                bool can_value_be_smi) {
   ASSERT(object != value);
   movq(dest, value);
   Label done;
-  StoreIntoObjectFilter(object, value, &done);
+  if (can_value_be_smi) {
+    StoreIntoObjectFilter(object, value, &done);
+  } else {
+    StoreIntoObjectFilterNoSmi(object, value, &done);
+  }
   // A store buffer update is required.
   if (value != RAX) pushq(RAX);
   leaq(RAX, dest);
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index aa6c21b..d14c02d 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -533,6 +533,7 @@
 
   void negl(Register reg);
   void negq(Register reg);
+  void notl(Register reg);
   void notq(Register reg);
 
   void enter(const Immediate& imm);
@@ -632,7 +633,8 @@
   // Destroys value.
   void StoreIntoObject(Register object,  // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
-                       Register value);  // Value we are storing.
+                       Register value,  // Value we are storing.
+                       bool can_value_be_smi = true);
 
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
@@ -821,6 +823,11 @@
 
   void StoreIntoObjectFilter(Register object, Register value, Label* no_update);
 
+  // Shorter filtering sequence that assumes that value is not a smi.
+  void StoreIntoObjectFilterNoSmi(Register object,
+                                  Register value,
+                                  Label* no_update);
+
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(Assembler);
 };
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc
index ba99591..1287571 100644
--- a/runtime/vm/assembler_x64_test.cc
+++ b/runtime/vm/assembler_x64_test.cc
@@ -2025,6 +2025,20 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(TestNotInt32, assembler) {
+  __ movq(RAX, Immediate(0x0));
+  __ notl(RAX);
+  __ ret();
+}
+
+
+ASSEMBLER_TEST_RUN(TestNotInt32, test) {
+  typedef int (*TestNot)();
+  unsigned int res = reinterpret_cast<TestNot>(test->entry())();
+  EXPECT_EQ(0xFFFFFFFF, res);
+}
+
+
 ASSEMBLER_TEST_GENERATE(XorpdZeroing, assembler) {
   __ pushq(RAX);
   __ movsd(Address(RSP, 0), XMM0);
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 48faa6b..400f1fa 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1372,6 +1372,7 @@
 
 
 void ClassFinalizer::FinalizeClass(const Class& cls) {
+  HANDLESCOPE(Isolate::Current());
   if (cls.is_finalized()) {
     return;
   }
@@ -1445,6 +1446,32 @@
     interface_type ^= interface_types.At(i);
     interface_type = FinalizeType(cls, interface_type, kCanonicalizeWellFormed);
     interface_types.SetAt(i, interface_type);
+
+    // Check whether the interface is duplicated. We need to wait with
+    // this check until the super type and interface types are finalized,
+    // so that we can use Type::Equals() for the test.
+    ASSERT(interface_type.IsFinalized());
+    ASSERT(super_type.IsFinalized());
+    if (interface_type.Equals(super_type)) {
+      const Script& script = Script::Handle(cls.script());
+      ReportError(script, cls.token_pos(),
+                  "super type '%s' may not be listed in "
+                  "implements clause of class '%s'",
+                  String::Handle(super_type.Name()).ToCString(),
+                  String::Handle(cls.Name()).ToCString());
+    }
+    AbstractType& seen_interf = AbstractType::Handle();
+    for (intptr_t j = 0; j < i; j++) {
+      seen_interf ^= interface_types.At(j);
+      if (interface_type.Equals(seen_interf)) {
+        const Script& script = Script::Handle(cls.script());
+        ReportError(script, cls.token_pos(),
+                    "interface '%s' appears twice in "
+                    "implements clause of class '%s'",
+                    String::Handle(interface_type.Name()).ToCString(),
+                    String::Handle(cls.Name()).ToCString());
+      }
+    }
   }
   // Mark as finalized before resolving type parameter upper bounds and member
   // types in order to break cycles.
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index b1f11df..daafa597 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1380,7 +1380,8 @@
 }
 
 
-static void DeoptimizeAt(const Code& optimized_code, uword pc) {
+void DeoptimizeAt(const Code& optimized_code, uword pc) {
+  ASSERT(optimized_code.is_optimized());
   intptr_t deopt_reason = kDeoptUnknown;
   const DeoptInfo& deopt_info =
       DeoptInfo::Handle(optimized_code.GetDeoptInfoAtPc(pc, &deopt_reason));
@@ -1449,11 +1450,13 @@
 
 // Copy saved registers into the isolate buffer.
 static void CopySavedRegisters(uword saved_registers_address) {
-  double* fpu_registers_copy = new double[kNumberOfFpuRegisters];
+  fpu_register_t* fpu_registers_copy =
+      new fpu_register_t[kNumberOfFpuRegisters];
   ASSERT(fpu_registers_copy != NULL);
   for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
-    fpu_registers_copy[i] = *reinterpret_cast<double*>(saved_registers_address);
-    saved_registers_address += kDoubleSize;
+    fpu_registers_copy[i] =
+        *reinterpret_cast<fpu_register_t*>(saved_registers_address);
+    saved_registers_address += kFpuRegisterSize;
   }
   Isolate::Current()->set_deopt_fpu_registers_copy(fpu_registers_copy);
 
@@ -1505,7 +1508,8 @@
 
   // All registers have been saved below last-fp.
   const uword last_fp = saved_registers_address +
-      kNumberOfCpuRegisters * kWordSize + kNumberOfFpuRegisters * kDoubleSize;
+                        kNumberOfCpuRegisters * kWordSize +
+                        kNumberOfFpuRegisters * kFpuRegisterSize;
   CopySavedRegisters(saved_registers_address);
 
   // Get optimized code and frame that need to be deoptimized.
@@ -1607,7 +1611,7 @@
 
   intptr_t* frame_copy = isolate->deopt_frame_copy();
   intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy();
-  double* fpu_registers_copy = isolate->deopt_fpu_registers_copy();
+  fpu_register_t* fpu_registers_copy = isolate->deopt_fpu_registers_copy();
 
   intptr_t deopt_reason = kDeoptUnknown;
   const DeoptInfo& deopt_info = DeoptInfo::Handle(
@@ -1633,42 +1637,17 @@
 
 // This is the last step in the deoptimization, GC can occur.
 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterializeDoubles, 0) {
-  DeferredDouble* deferred_double = Isolate::Current()->DetachDeferredDoubles();
+  DeferredObject* deferred_object = Isolate::Current()->DetachDeferredObjects();
 
-  while (deferred_double != NULL) {
-    DeferredDouble* current = deferred_double;
-    deferred_double = deferred_double->next();
+  while (deferred_object != NULL) {
+    DeferredObject* current = deferred_object;
+    deferred_object  = deferred_object->next();
 
-    RawDouble** slot = current->slot();
-    *slot = Double::New(current->value());
-
-    if (FLAG_trace_deoptimization_verbose) {
-      OS::PrintErr("materializing double at %"Px": %g\n",
-                reinterpret_cast<uword>(current->slot()),
-                current->value());
-    }
+    current->Materialize();
 
     delete current;
   }
 
-  DeferredMint* deferred_mint = Isolate::Current()->DetachDeferredMints();
-
-  while (deferred_mint != NULL) {
-    DeferredMint* current = deferred_mint;
-    deferred_mint = deferred_mint->next();
-
-    RawMint** slot = current->slot();
-    ASSERT(!Smi::IsValid64(current->value()));
-    *slot = Mint::New(current->value());
-
-    if (FLAG_trace_deoptimization_verbose) {
-      OS::PrintErr("materializing mint at %"Px": %"Pd64"\n",
-                reinterpret_cast<uword>(current->slot()),
-                current->value());
-    }
-
-    delete current;
-  }
   // Since this is the only step where GC can occur during deoptimization,
   // use it to report the source line where deoptimization occured.
   if (FLAG_trace_deoptimization) {
@@ -1733,4 +1712,17 @@
   return remainder;
 }
 
+
+// Update global type feedback recorded for a field recording the assignment
+// of the given value.
+//   Arg0: Field object;
+//   Arg1: Value that is being stored.
+DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) {
+  ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count());
+  const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
+  const Object& value = Object::Handle(arguments.ArgAt(1));
+
+  field.UpdateCid(Class::Handle(value.clazz()).id());
+}
+
 }  // namespace dart
diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h
index 7946dc2..82ecc2d 100644
--- a/runtime/vm/code_generator.h
+++ b/runtime/vm/code_generator.h
@@ -50,6 +50,8 @@
 DECLARE_RUNTIME_ENTRY(TraceFunctionExit);
 DECLARE_RUNTIME_ENTRY(DeoptimizeMaterializeDoubles);
 DECLARE_RUNTIME_ENTRY(UpdateICDataTwoArgs);
+DECLARE_RUNTIME_ENTRY(UpdateFieldCid);
+
 
 #define DEOPT_REASONS(V)                                                       \
   V(Unknown)                                                                   \
@@ -75,6 +77,7 @@
   V(DoubleToSmi)                                                               \
   V(Int32Load)                                                                 \
   V(Uint32Load)                                                                \
+  V(GuardField)                                                                \
   V(NumReasons)                                                                \
 
 enum DeoptReasonId {
@@ -92,6 +95,7 @@
     const ICData& ic_data,
     const Array& arguments_descriptor);
 
+void DeoptimizeAt(const Code& optimized_code, uword pc);
 void DeoptimizeAll();
 void DeoptimizeIfOwner(const GrowableArray<intptr_t>& classes);
 
diff --git a/runtime/vm/code_patcher.cc b/runtime/vm/code_patcher.cc
index c353cac..986ade4 100644
--- a/runtime/vm/code_patcher.cc
+++ b/runtime/vm/code_patcher.cc
@@ -28,6 +28,7 @@
 void CodePatcher::PatchEntry(const Code& code) {
   const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
                                                 PcDescriptors::kEntryPatch);
+  ASSERT(patch_addr != 0);
   JumpPattern jmp_entry(patch_addr);
   ASSERT(!jmp_entry.IsValid());
   const uword patch_buffer = code.GetPatchCodePc();
@@ -47,6 +48,7 @@
 void CodePatcher::RestoreEntry(const Code& code) {
   const uword patch_addr = code.GetPcForDeoptId(Isolate::kNoDeoptId,
                                                 PcDescriptors::kEntryPatch);
+  ASSERT(patch_addr != 0);
   JumpPattern jmp_entry(patch_addr);
   ASSERT(jmp_entry.IsValid());
   const uword jump_target = jmp_entry.TargetAddress();
diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc
index cd21ef2..2bd3f1b 100644
--- a/runtime/vm/code_patcher_ia32.cc
+++ b/runtime/vm/code_patcher_ia32.cc
@@ -93,7 +93,7 @@
 
 
 // The expected pattern of a dart static call:
-//  mov EDX, arguments_descriptor_array
+//  mov EDX, arguments_descriptor_array (optional in polymorphic calls)
 //  call target_address
 //  <- return address
 class StaticCall : public ValueObject {
@@ -108,8 +108,7 @@
     uint8_t* code_bytes =
         reinterpret_cast<uint8_t*>(
             return_address - (kNumInstructions * kInstructionSize));
-    return (code_bytes[0] == 0xBA) &&
-           (code_bytes[1 * kInstructionSize] == 0xE8);
+    return (code_bytes[0] == 0xE8);
   }
 
   uword target() const {
@@ -124,7 +123,7 @@
     CPU::FlushICache(call_address(), kInstructionSize);
   }
 
-  static const int kNumInstructions = 2;
+  static const int kNumInstructions = 1;
   static const int kInstructionSize = 5;  // All instructions have same length.
 
  private:
@@ -133,7 +132,7 @@
   }
 
   uword call_address() const {
-    return start_ + 1 * kInstructionSize;
+    return start_;
   }
 
   uword start_;
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc
index 5be92be..1f2cebe 100644
--- a/runtime/vm/code_patcher_x64.cc
+++ b/runtime/vm/code_patcher_x64.cc
@@ -86,7 +86,7 @@
 
 
 // The expected pattern of a dart static call:
-//  mov R10, arguments_descriptor_array (10 bytes)
+//  mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls)
 //  mov R11, target_address (10 bytes)
 //  call R11  (3 bytes)
 //  <- return address
@@ -95,28 +95,27 @@
   explicit StaticCall(uword return_address)
       : start_(return_address - kCallPatternSize) {
     ASSERT(IsValid(return_address));
-    ASSERT((kCallPatternSize - 10) == Assembler::kCallExternalLabelSize);
+    ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize);
   }
 
-  static const int kCallPatternSize = 23;
+  static const int kCallPatternSize = 13;
 
   static bool IsValid(uword return_address) {
     uint8_t* code_bytes =
         reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
-    return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
-           (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) &&
-           (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) &&
-           (code_bytes[22] == 0xD3);
+    return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBB) &&
+           (code_bytes[10] == 0x41) && (code_bytes[11] == 0xFF) &&
+           (code_bytes[12] == 0xD3);
   }
 
   uword target() const {
-    return *reinterpret_cast<uword*>(start_ + 10 + 2);
+    return *reinterpret_cast<uword*>(start_ + 2);
   }
 
   void set_target(uword target) const {
-    uword* target_addr = reinterpret_cast<uword*>(start_ + 10 + 2);
+    uword* target_addr = reinterpret_cast<uword*>(start_ + 2);
     *target_addr = target;
-    CPU::FlushICache(start_ + 10, 2 + 8);
+    CPU::FlushICache(start_, 2 + 8);
   }
 
  private:
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index d993415..a0e412e 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -167,6 +167,8 @@
       FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
     }
 
+    const ZoneGrowableArray<Field*>* guarded_fields = NULL;
+
     if (optimized) {
       TimerScope timer(FLAG_compiler_stats,
                        &CompilerStats::graphoptimizer_timer,
@@ -193,6 +195,8 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
       }
 
+      guarded_fields = flow_graph->FieldDependencies();
+
       // Propagate types and eliminate more type tests.
       if (FLAG_propagate_types) {
         FlowGraphTypePropagator propagator(flow_graph);
@@ -221,6 +225,8 @@
 
       // Propagate types and eliminate even more type tests.
       if (FLAG_propagate_types) {
+        // Recompute types after constant propagation to infer more precise
+        // types for uses that were previously reached by now eliminated phis.
         FlowGraphTypePropagator propagator(flow_graph);
         propagator.Propagate();
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
@@ -303,6 +309,7 @@
       graph_compiler.FinalizeExceptionHandlers(code);
       graph_compiler.FinalizeComments(code);
       graph_compiler.FinalizeStaticCallTargetsTable(code);
+
       if (optimized) {
         CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
         function.SetCode(code);
@@ -310,6 +317,11 @@
           OS::Print("--> patching entry %#"Px"\n",
                     Code::Handle(function.unoptimized_code()).EntryPoint());
         }
+
+        for (intptr_t i = 0; i < guarded_fields->length(); i++) {
+          const Field& field = *(*guarded_fields)[i];
+          field.RegisterDependentCode(code);
+        }
       } else {
         function.set_unoptimized_code(code);
         function.SetCode(code);
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index aba778d..95a0799 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -174,6 +174,8 @@
   kInstrBits = 26,
   kBreakCodeShift = 5,
   kBreakCodeBits = 20,
+
+  kBranchOffsetMask = 0x0000ffff,
 };
 
 
@@ -253,7 +255,7 @@
   MFLO = 18,
   MTLO = 19,
   MULT = 24,
-  MUTLU = 25,
+  MULTU = 25,
   DIV = 26,
   DIVU = 27,
   ADD = 32,
@@ -366,6 +368,10 @@
     return static_cast<SpecialFunction>(Bits(kFunctionShift, kFunctionBits));
   }
 
+  inline RtRegImm RegImmFnField() const {
+    return static_cast<RtRegImm>(Bits(kRtShift, kRtBits));
+  }
+
   inline bool IsBreakPoint() {
     return (OpcodeField() == SPECIAL) && (FunctionField() == BREAK);
   }
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 4ed5a7d..2333523 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -2074,8 +2074,7 @@
   Isolate* isolate = Isolate::Current();
   // Lookup the class ArgumentError in dart:core.
   const String& lib_url = String::Handle(String::New("dart:core"));
-  const String& class_name =
-      String::Handle(String::New("ArgumentError"));
+  const String& class_name = String::Handle(String::New("ArgumentError"));
   const Library& lib =
       Library::Handle(isolate, Library::LookupLibrary(lib_url));
   if (lib.IsNull()) {
@@ -2093,9 +2092,10 @@
                              lib_url.ToCString()));
     return ApiError::New(message);
   }
-  String& dot_name = String::Handle(String::New("."));
   Object& result = Object::Handle(isolate);
-  result = ResolveConstructor(CURRENT_FUNC, cls, class_name, dot_name, 1);
+  String& dot_name = String::Handle(String::New("."));
+  String& constr_name = String::Handle(String::Concat(class_name, dot_name));
+  result = ResolveConstructor(CURRENT_FUNC, cls, class_name, constr_name, 1);
   if (result.IsError()) return result.raw();
   ASSERT(result.IsFunction());
   Function& constructor = Function::Handle(isolate);
@@ -2329,9 +2329,6 @@
 static Dart_TypedData_Type GetType(intptr_t class_id) {
   Dart_TypedData_Type type;
   switch (class_id) {
-    case kByteArrayCid :
-      type = kByteData;
-      break;
     case kTypedDataInt8ArrayCid :
     case kExternalTypedDataInt8ArrayCid :
       type = kInt8;
@@ -2386,20 +2383,77 @@
 
 DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object) {
   intptr_t class_id = Api::ClassId(object);
-  if (!RawObject::IsTypedDataClassId(class_id)) {
-    return kInvalid;
+  if (RawObject::IsTypedDataClassId(class_id)) {
+    return GetType(class_id);
   }
-  return GetType(class_id);
+  Isolate* isolate = Isolate::Current();
+  const Library& lib =
+      Library::Handle(isolate->object_store()->typeddata_library());
+  const Class& cls =
+      Class::Handle(isolate,
+                    lib.LookupClassAllowPrivate(Symbols::_ByteDataView()));
+  if (isolate->class_table()->At(class_id) == cls.raw()) {
+    return kByteData;
+  }
+  return kInvalid;
 }
 
 
 DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfExternalTypedData(
     Dart_Handle object) {
   intptr_t class_id = Api::ClassId(object);
-  if (!RawObject::IsExternalTypedDataClassId(class_id)) {
-    return kInvalid;
+  if (RawObject::IsExternalTypedDataClassId(class_id)) {
+    return GetType(class_id);
   }
-  return GetType(class_id);
+  Isolate* isolate = Isolate::Current();
+  const Library& lib =
+      Library::Handle(isolate->object_store()->typeddata_library());
+  const Class& cls =
+      Class::Handle(isolate,
+                    lib.LookupClassAllowPrivate(Symbols::_ByteDataView()));
+  if (isolate->class_table()->At(class_id) == cls.raw()) {
+    return kByteData;
+  }
+  return kInvalid;
+}
+
+
+static RawObject* GetByteDataConstructor(Isolate* isolate,
+                                         const String& constructor_name,
+                                         intptr_t num_args) {
+  const Library& lib =
+      Library::Handle(isolate->object_store()->typeddata_library());
+  ASSERT(!lib.IsNull());
+  const Class& cls =
+      Class::Handle(isolate, lib.LookupClassAllowPrivate(Symbols::ByteData()));
+  ASSERT(!cls.IsNull());
+  return ResolveConstructor(CURRENT_FUNC,
+                            cls,
+                            Symbols::ByteData(),
+                            constructor_name,
+                            num_args);
+}
+
+
+static Dart_Handle NewByteData(Isolate* isolate, intptr_t length) {
+  CHECK_LENGTH(length, TypedData::MaxElements(kTypedDataInt8ArrayCid));
+  Object& result = Object::Handle(isolate);
+  result = GetByteDataConstructor(isolate, Symbols::ByteDataDot(), 1);
+  ASSERT(!result.IsNull());
+  ASSERT(result.IsFunction());
+  const Function& factory = Function::Cast(result);
+  ASSERT(!factory.IsConstructor());
+
+  // Create the argument list.
+  const Array& args = Array::Handle(isolate, Array::New(2));
+  // Factories get type arguments.
+  args.SetAt(0, TypeArguments::Handle(isolate));
+  args.SetAt(1, Smi::Handle(isolate, Smi::New(length)));
+
+  // Invoke the constructor and return the new object.
+  result = DartEntry::InvokeFunction(factory, args);
+  ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
+  return Api::NewHandle(isolate, result.raw());
 }
 
 
@@ -2426,6 +2480,47 @@
 }
 
 
+static Dart_Handle NewExternalByteData(Isolate* isolate,
+                                       void* data,
+                                       intptr_t length,
+                                       void* peer,
+                                       Dart_WeakPersistentHandleFinalizer cb) {
+  Dart_Handle ext_data = NewExternalTypedData(kExternalTypedDataUint8ArrayCid,
+                                              data,
+                                              length,
+                                              peer,
+                                              cb);
+  if (::Dart_IsError(ext_data)) {
+    return ext_data;
+  }
+  Object& result = Object::Handle(isolate);
+  result = GetByteDataConstructor(isolate, Symbols::ByteDataDotview(), 3);
+  ASSERT(!result.IsNull());
+  ASSERT(result.IsFunction());
+  const Function& factory = Function::Cast(result);
+  ASSERT(!factory.IsConstructor());
+
+  // Create the argument list.
+  const intptr_t num_args = 3;
+  const Array& args = Array::Handle(isolate, Array::New(num_args + 1));
+  // Factories get type arguments.
+  args.SetAt(0, TypeArguments::Handle(isolate));
+  const ExternalTypedData& array =
+      Api::UnwrapExternalTypedDataHandle(isolate, ext_data);
+  args.SetAt(1, array);
+  Smi& smi = Smi::Handle(isolate);
+  smi = Smi::New(0);
+  args.SetAt(2, smi);
+  smi = Smi::New(length);
+  args.SetAt(3, smi);
+
+  // Invoke the constructor and return the new object.
+  result = DartEntry::InvokeFunction(factory, args);
+  ASSERT(result.IsNull() || result.IsInstance() || result.IsError());
+  return Api::NewHandle(isolate, result.raw());
+}
+
+
 DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type,
                                           intptr_t length) {
   Isolate* isolate = Isolate::Current();
@@ -2433,8 +2528,7 @@
   CHECK_CALLBACK_STATE(isolate);
   switch (type) {
     case kByteData :
-      // TODO(asiva): Add a new ByteArray::New() method.
-      break;
+      return NewByteData(isolate, length);
     case kInt8 :
       return NewTypedData(isolate, kTypedDataInt8ArrayCid, length);
     case kUint8 :
@@ -2480,8 +2574,7 @@
   CHECK_CALLBACK_STATE(isolate);
   switch (type) {
     case kByteData :
-      // TODO(asiva): Allocate external ByteData object.
-      break;
+      return NewExternalByteData(isolate, data, length, peer, callback);
     case kInt8 :
       return NewExternalTypedData(kExternalTypedDataInt8ArrayCid,
                                   data,
@@ -3462,10 +3555,9 @@
 static RawObject* ResolveConstructor(const char* current_func,
                                      const Class& cls,
                                      const String& class_name,
-                                     const String& dotted_name,
+                                     const String& constr_name,
                                      int num_args) {
   // The constructor must be present in the interface.
-  String& constr_name = String::Handle(String::Concat(class_name, dotted_name));
   const Function& constructor =
       Function::Handle(cls.LookupFunctionAllowPrivate(constr_name));
   if (constructor.IsNull() ||
@@ -3550,17 +3642,26 @@
   }
 
   // Resolve the constructor.
-  result = ResolveConstructor(
-      "Dart_New", cls, base_constructor_name, dot_name, number_of_arguments);
+  String& constr_name =
+      String::Handle(String::Concat(base_constructor_name, dot_name));
+  result = ResolveConstructor("Dart_New",
+                              cls,
+                              base_constructor_name,
+                              constr_name,
+                              number_of_arguments);
   if (result.IsError()) {
     return Api::NewHandle(isolate, result.raw());
   }
-  // TODO(turnidge): Support redirecting factories.
   ASSERT(result.IsFunction());
   Function& constructor = Function::Handle(isolate);
   constructor ^= result.raw();
 
   Instance& new_object = Instance::Handle(isolate);
+  if (constructor.IsRedirectingFactory()) {
+    Type& type = Type::Handle(constructor.RedirectionType());
+    cls = type.type_class();
+    constructor = constructor.RedirectionTarget();
+  }
   if (constructor.IsConstructor()) {
     // Create the new object.
     new_object = Instance::New(cls);
@@ -4247,44 +4348,9 @@
 
 
 DART_EXPORT Dart_Handle Dart_LoadScript(Dart_Handle url,
-                                        Dart_Handle source) {
-  TIMERSCOPE(time_script_loading);
-  Isolate* isolate = Isolate::Current();
-  DARTSCOPE(isolate);
-  const String& url_str = Api::UnwrapStringHandle(isolate, url);
-  if (url_str.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, url, String);
-  }
-  const String& source_str = Api::UnwrapStringHandle(isolate, source);
-  if (source_str.IsNull()) {
-    RETURN_TYPE_ERROR(isolate, source, String);
-  }
-  Library& library =
-      Library::Handle(isolate, isolate->object_store()->root_library());
-  if (!library.IsNull()) {
-    const String& library_url = String::Handle(isolate, library.url());
-    return Api::NewError("%s: A script has already been loaded from '%s'.",
-                         CURRENT_FUNC, library_url.ToCString());
-  }
-  CHECK_CALLBACK_STATE(isolate);
-
-  library = Library::New(url_str);
-  library.set_debuggable(true);
-  library.Register();
-  isolate->object_store()->set_root_library(library);
-
-  const Script& script = Script::Handle(
-      isolate, Script::New(url_str, source_str, RawScript::kScriptTag));
-  Dart_Handle result;
-  CompileSource(isolate, library, script, &result);
-  return result;
-}
-
-
-DART_EXPORT Dart_Handle Dart_LoadEmbeddedScript(Dart_Handle url,
-                                                Dart_Handle source,
-                                                intptr_t line_offset,
-                                                intptr_t col_offset) {
+                                        Dart_Handle source,
+                                        intptr_t line_offset,
+                                        intptr_t col_offset) {
   TIMERSCOPE(time_script_loading);
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
@@ -4327,7 +4393,8 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_LoadScriptFromSnapshot(const uint8_t* buffer) {
+DART_EXPORT Dart_Handle Dart_LoadScriptFromSnapshot(const uint8_t* buffer,
+                                                    intptr_t buffer_len) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
   TIMERSCOPE(time_script_loading);
@@ -4339,6 +4406,11 @@
     return Api::NewError("%s expects parameter 'buffer' to be a script type"
                          " snapshot.", CURRENT_FUNC);
   }
+  if (snapshot->length() != buffer_len) {
+    return Api::NewError("%s: 'buffer_len' of %"Pd" is not equal to %d which"
+                         " is the expected length in the snapshot.",
+                         CURRENT_FUNC, buffer_len, snapshot->length());
+  }
   Library& library =
       Library::Handle(isolate, isolate->object_store()->root_library());
   if (!library.IsNull()) {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index efca65a..b86ab17 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -885,6 +885,117 @@
 }
 
 
+static int kLength = 16;
+
+static void ByteDataNativeFunction(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle byte_data = Dart_NewTypedData(kByteData, kLength);
+  EXPECT_VALID(byte_data);
+  EXPECT_EQ(kByteData, Dart_GetTypeOfTypedData(byte_data));
+  Dart_SetReturnValue(args, byte_data);
+  Dart_ExitScope();
+}
+
+
+static Dart_NativeFunction ByteDataNativeResolver(Dart_Handle name,
+                                                  int arg_count) {
+  return &ByteDataNativeFunction;
+}
+
+
+TEST_CASE(ByteDataAccess) {
+  const char* kScriptChars =
+      "import 'dart:typeddata';\n"
+      "ByteData createByteData() native 'CreateByteData';"
+      "ByteData main() {"
+      "  var length = 16;"
+      "  var a = createByteData();"
+      "  Expect.equals(length, a.lengthInBytes);"
+      "  for (int i = 0; i < length; i+=1) {"
+      "    a.setInt8(i, 0x42);"
+      "  }"
+      "  for (int i = 0; i < length; i+=2) {"
+      "    Expect.equals(0x4242, a.getInt16(i));"
+      "  }"
+      "  return a;"
+      "}\n";
+  // Create a test library and Load up a test script in it.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+
+  Dart_Handle result = Dart_SetNativeResolver(lib, &ByteDataNativeResolver);
+  EXPECT_VALID(result);
+
+  // Invoke 'main' function.
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+}
+
+
+static const intptr_t kExtLength = 16;
+static int8_t data[kExtLength] = { 0x41, 0x42, 0x41, 0x42,
+                                   0x41, 0x42, 0x41, 0x42,
+                                   0x41, 0x42, 0x41, 0x42,
+                                   0x41, 0x42, 0x41, 0x42, };
+
+static void ExternalByteDataNativeFunction(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle external_byte_data = Dart_NewExternalTypedData(kByteData,
+                                                             data,
+                                                             16,
+                                                             NULL, NULL);
+  EXPECT_VALID(external_byte_data);
+  EXPECT_EQ(kByteData, Dart_GetTypeOfTypedData(external_byte_data));
+  Dart_SetReturnValue(args, external_byte_data);
+  Dart_ExitScope();
+}
+
+
+static Dart_NativeFunction ExternalByteDataNativeResolver(Dart_Handle name,
+                                                          int arg_count) {
+  return &ExternalByteDataNativeFunction;
+}
+
+
+TEST_CASE(ExternalByteDataAccess) {
+  // TODO(asiva): Once we have getInt16LE and getInt16BE support use the
+  // appropriate getter instead of the host endian format used now.
+  const char* kScriptChars =
+      "import 'dart:typeddata';\n"
+      "ByteData createExternalByteData() native 'CreateExternalByteData';"
+      "ByteData main() {"
+      "  var length = 16;"
+      "  var a = createExternalByteData();"
+      "  Expect.equals(length, a.lengthInBytes);"
+      "  for (int i = 0; i < length; i+=2) {"
+      "    Expect.equals(0x4241, a.getInt16(i));"
+      "  }"
+      "  for (int i = 0; i < length; i+=2) {"
+      "    a.setInt8(i, 0x24);"
+      "    a.setInt8(i + 1, 0x28);"
+      "  }"
+      "  for (int i = 0; i < length; i+=2) {"
+      "    Expect.equals(0x2824, a.getInt16(i));"
+      "  }"
+      "  return a;"
+      "}\n";
+  // Create a test library and Load up a test script in it.
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+
+  Dart_Handle result = Dart_SetNativeResolver(lib,
+                                              &ExternalByteDataNativeResolver);
+  EXPECT_VALID(result);
+
+  // Invoke 'main' function.
+  result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT_VALID(result);
+
+  for (intptr_t i = 0; i < kExtLength; i+=2) {
+    EXPECT_EQ(0x24, data[i]);
+    EXPECT_EQ(0x28, data[i+1]);
+  }
+}
+
+
 TEST_CASE(TypedDataDirectAccess) {
   Dart_Handle str = Dart_NewStringFromCString("junk");
   Dart_Handle byte_array = Dart_NewTypedData(kUint8, 10);
@@ -3281,7 +3392,7 @@
 
 TEST_CASE(New) {
   const char* kScriptChars =
-      "class MyClass implements MyInterface {\n"
+      "class MyClass {\n"
       "  MyClass() : foo = 7 {}\n"
       "  MyClass.named(value) : foo = value {}\n"
       "  MyClass._hidden(value) : foo = -value {}\n"
@@ -3294,43 +3405,24 @@
       "  factory MyClass.nullo() {\n"
       "    return null;\n"
       "  }\n"
-      "  factory MyInterface.multiply(value) {  // won't get called.\n"
-      "    return new MyClass.named(value * 1000);\n"
-      "  }\n"
-      "  factory MyInterface2.unused(value) {\n"
-      "    return new MyClass2(-value);\n"
-      "  }\n"
-      "  factory MyInterface2.multiply(value) {\n"
-      "    return new MyClass2(value * 10000);\n"
-      "  }\n"
       "  var foo;\n"
       "}\n"
       "\n"
-      "class MyClass2 implements MyInterface2 {\n"
-      "  MyClass2(value) : bar = value {}\n"
-      "  var bar;\n"
+      "abstract class MyExtraHop {\n"
+      "  factory MyExtraHop.hop(value) = MyClass.named;\n"
       "}\n"
       "\n"
-      "interface MyInterface default MyClass {\n"
-      "  MyInterface.named(value);\n"
-      "  MyInterface.multiply(value);\n"
+      "abstract class MyInterface {\n"
+      "  factory MyInterface.named(value) = MyExtraHop.hop;\n"
+      "  factory MyInterface.multiply(value) = MyClass.multiply;\n"
       "  MyInterface.notfound(value);\n"
-      "}\n"
-      "\n"
-      "interface MyInterface2 default MyClass {\n"
-      "  MyInterface2.multiply(value);\n"
-      "  MyInterface2.notfound(value);\n"
       "}\n";
 
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
   Dart_Handle cls = Dart_GetClass(lib, NewString("MyClass"));
   EXPECT_VALID(cls);
-  Dart_Handle cls2 = Dart_GetClass(lib, NewString("MyClass2"));
-  EXPECT_VALID(cls2);
   Dart_Handle intf = Dart_GetClass(lib, NewString("MyInterface"));
   EXPECT_VALID(intf);
-  Dart_Handle intf2 = Dart_GetClass(lib, NewString("MyInterface2"));
-  EXPECT_VALID(intf2);
   Dart_Handle args[1];
   args[0] = Dart_NewInteger(11);
   Dart_Handle bad_args[1];
@@ -3433,19 +3525,7 @@
   result = Dart_New(cls, NewString("exception"), 1, args);
   EXPECT_ERROR(result, "ConstructorDeath");
 
-  // MyInterface has default class MyClass.
-  //
-  // MyClass *implements* MyInterface.
-  //
-  // Therefore the constructor call:
-  //
-  //   MyInterface.foo()
-  //
-  // Becomes:
-  //
-  //   MyClass.foo() from the class MyClass.
-
-  // Invoke an interface constructor.
+  // Invoke two-hop redirecting factory constructor.
   result = Dart_New(intf, NewString("named"), 1, args);
   EXPECT_VALID(result);
   EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
@@ -3455,8 +3535,7 @@
   EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
   EXPECT_EQ(11, int_value);
 
-  // Invoke an interface constructor which in turn calls a factory
-  // constructor.
+  // Invoke one-hop redirecting factory constructor.
   result = Dart_New(intf, NewString("multiply"), 1, args);
   EXPECT_VALID(result);
   EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
@@ -3466,53 +3545,16 @@
   EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
   EXPECT_EQ(1100, int_value);
 
-  // Invoke a constructor that is missing in the interface but present
-  // in the default class.
+  // Invoke a constructor that is missing in the interface.
   result = Dart_New(intf, Dart_Null(), 0, NULL);
   EXPECT_ERROR(result,
                "Dart_New: could not find constructor 'MyInterface.'.");
 
-  // Invoke a constructor that is present in the interface but missing
-  // in the default class.
+  // Invoke abstract constructor that is present in the interface.
   result = Dart_New(intf, NewString("notfound"), 1, args);
-  EXPECT_ERROR(result,
-               "Dart_New: could not find constructor 'MyClass.notfound'.");
-
-  // MyInterface2 has default class MyClass.
-  //
-  // MyClass *does not implement* MyInterface2.
-  //
-  // Therefore the constructor call:
-  //
-  //   new MyInterface2.foo()
-  //
-  // Becomes:
-  //
-  //   new MyInterface2.foo() from the class MyClass.
-
-  // Invoke an interface constructor which in turn calls a factory
-  // constructor.
-  result = Dart_New(intf2, NewString("multiply"), 1, args);
   EXPECT_VALID(result);
-  EXPECT_VALID(Dart_ObjectIsType(result, cls2, &instanceof));
-  EXPECT(instanceof);
-  int_value = 0;
-  Dart_Handle bar = Dart_GetField(result, NewString("bar"));
-  EXPECT_VALID(Dart_IntegerToInt64(bar, &int_value));
-  EXPECT_EQ(110000, int_value);
-
-  // Invoke a constructor that is missing in the interface but present
-  // in the default class.
-  result = Dart_New(intf2, NewString("unused"), 1, args);
-  EXPECT_ERROR(result,
-               "Dart_New: could not find constructor 'MyInterface2.unused'.");
-
-  // Invoke a constructor that is present in the interface but missing
-  // in the default class.
-  result = Dart_New(intf2, NewString("notfound"), 1, args);
-  EXPECT_ERROR(result,
-               "Dart_New: could not find factory 'MyInterface2.notfound' "
-               "in class 'MyClass'.");
+  EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+  EXPECT(!instanceof);
 }
 
 
@@ -4769,7 +4811,7 @@
 
 TEST_CASE(TypeVariableReflection) {
   const char* kScriptChars =
-      "interface UpperBound {}\n"
+      "abstract class UpperBound {}\n"
       "class GenericClass<U, T extends UpperBound> {\n"
       "  T func1() { return null; }\n"
       "  U func2() { return null; }\n"
@@ -4915,37 +4957,37 @@
   result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
 
-  result = Dart_LoadScript(Dart_Null(), source);
+  result = Dart_LoadScript(Dart_Null(), source, 0, 0);
   EXPECT(Dart_IsError(result));
   EXPECT_STREQ("Dart_LoadScript expects argument 'url' to be non-null.",
                Dart_GetError(result));
 
-  result = Dart_LoadScript(Dart_True(), source);
+  result = Dart_LoadScript(Dart_True(), source, 0, 0);
   EXPECT(Dart_IsError(result));
   EXPECT_STREQ("Dart_LoadScript expects argument 'url' to be of type String.",
                Dart_GetError(result));
 
-  result = Dart_LoadScript(error, source);
+  result = Dart_LoadScript(error, source, 0, 0);
   EXPECT(Dart_IsError(result));
   EXPECT_STREQ("incoming error", Dart_GetError(result));
 
-  result = Dart_LoadScript(url, Dart_Null());
+  result = Dart_LoadScript(url, Dart_Null(), 0, 0);
   EXPECT(Dart_IsError(result));
   EXPECT_STREQ("Dart_LoadScript expects argument 'source' to be non-null.",
                Dart_GetError(result));
 
-  result = Dart_LoadScript(url, Dart_True());
+  result = Dart_LoadScript(url, Dart_True(), 0, 0);
   EXPECT(Dart_IsError(result));
   EXPECT_STREQ(
       "Dart_LoadScript expects argument 'source' to be of type String.",
       Dart_GetError(result));
 
-  result = Dart_LoadScript(url, error);
+  result = Dart_LoadScript(url, error, 0, 0);
   EXPECT(Dart_IsError(result));
   EXPECT_STREQ("incoming error", Dart_GetError(result));
 
   // Load a script successfully.
-  result = Dart_LoadScript(url, source);
+  result = Dart_LoadScript(url, source, 0, 0);
   EXPECT_VALID(result);
 
   result = Dart_Invoke(result, NewString("main"), 0, NULL);
@@ -4956,7 +4998,7 @@
   EXPECT_EQ(12345, value);
 
   // Further calls to LoadScript are errors.
-  result = Dart_LoadScript(url, source);
+  result = Dart_LoadScript(url, source, 0, 0);
   EXPECT(Dart_IsError(result));
   EXPECT_STREQ("Dart_LoadScript: "
                "A script has already been loaded from 'dart:test-lib'.",
@@ -4977,7 +5019,7 @@
   // Load a script.
   Dart_Handle url = NewString(TestCase::url());
   Dart_Handle source = NewString(kScriptChars);
-  EXPECT_VALID(Dart_LoadScript(url, source));
+  EXPECT_VALID(Dart_LoadScript(url, source, 0, 0));
 
   root_lib = Dart_RootLibrary();
   Dart_Handle lib_name = Dart_LibraryName(root_lib);
@@ -5033,7 +5075,7 @@
   Dart_Handle source = NewString(kScriptChars);
   Dart_Handle result = Dart_SetLibraryTagHandler(import_library_handler);
   EXPECT_VALID(result);
-  result = Dart_LoadScript(url, source);
+  result = Dart_LoadScript(url, source, 0, 0);
   EXPECT(Dart_IsError(result));
   EXPECT(strstr(Dart_GetError(result), "unexpected token ')'"));
 }
@@ -5052,7 +5094,7 @@
   Dart_Handle source = NewString(kScriptChars);
   Dart_Handle result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
-  result = Dart_LoadScript(url, source);
+  result = Dart_LoadScript(url, source, 0, 0);
   EXPECT_VALID(result);
 
   url = NewString("library1_dart");
@@ -5158,10 +5200,10 @@
       "\n"
       "class A {}\n"
       "class B {}\n"
-      "interface C {}\n"
+      "abstract class C {}\n"
       "class _A {}\n"
       "class _B {}\n"
-      "interface _C {}\n"
+      "abstract class _C {}\n"
       "\n"
       "_compare(String a, String b) => a.compareTo(b);\n"
       "sort(list) => list.sort(_compare);\n";
@@ -5750,7 +5792,7 @@
 
   Dart_Handle script_url = NewString("theScript");
   source = NewString(kScriptChars);
-  Dart_Handle test_script = Dart_LoadScript(script_url, source);
+  Dart_Handle test_script = Dart_LoadScript(script_url, source, 0, 0);
   EXPECT_VALID(test_script);
 
   // Make sure that we can compile all of the patched code.
@@ -5842,7 +5884,7 @@
   Dart_Handle source = NewString(kScriptChars);
   result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
-  Dart_Handle lib = Dart_LoadScript(url, source);
+  Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
   EXPECT_VALID(lib);
   EXPECT(Dart_IsLibrary(lib));
   Dart_Handle cls = Dart_GetClass(lib, NewString("Test"));
@@ -5925,7 +5967,7 @@
   Dart_Handle source = NewString(kScriptChars);
   result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
-  result = Dart_LoadScript(url, source);
+  result = Dart_LoadScript(url, source, 0, 0);
 
   url = NewString("library1_dart");
   source = NewString(kLibrary1Chars);
@@ -5961,7 +6003,7 @@
   Dart_Handle source = NewString(kScriptChars);
   result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
-  result = Dart_LoadScript(url, source);
+  result = Dart_LoadScript(url, source, 0, 0);
   EXPECT_VALID(result);
 
   url = NewString("library2_dart");
@@ -5998,7 +6040,7 @@
   Dart_Handle source = NewString(kScriptChars);
   result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
-  result = Dart_LoadScript(url, source);
+  result = Dart_LoadScript(url, source, 0, 0);
   EXPECT_VALID(result);
 
   url = NewString("library2_dart");
@@ -6017,13 +6059,13 @@
 TEST_CASE(ImportLibrary5) {
   const char* kScriptChars =
       "import 'lib.dart';\n"
-      "interface Y {\n"
+      "abstract class Y {\n"
       "  void set handler(void callback(List<int> x));\n"
       "}\n"
       "void main() {}\n";
   const char* kLibraryChars =
       "library lib.dart;\n"
-      "interface X {\n"
+      "abstract class X {\n"
       "  void set handler(void callback(List<int> x));\n"
       "}\n";
   Dart_Handle result;
@@ -6033,7 +6075,7 @@
   Dart_Handle source = NewString(kScriptChars);
   result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
-  result = Dart_LoadScript(url, source);
+  result = Dart_LoadScript(url, source, 0, 0);
 
   url = NewString("lib.dart");
   source = NewString(kLibraryChars);
@@ -6169,7 +6211,7 @@
   Dart_Handle source = NewString(kScriptChars);
   Dart_Handle result = Dart_SetLibraryTagHandler(TestCase::library_handler);
   EXPECT_VALID(result);
-  Dart_Handle lib = Dart_LoadScript(url, source);
+  Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
   EXPECT_VALID(lib);
   Dart_ExitScope();
   return true;
@@ -6302,7 +6344,7 @@
     Dart_Handle source = NewString(kScriptChars);
     Dart_Handle result = Dart_SetLibraryTagHandler(TestCase::library_handler);
     EXPECT_VALID(result);
-    lib = Dart_LoadScript(url, source);
+    lib = Dart_LoadScript(url, source, 0, 0);
     EXPECT_VALID(lib);
     result = Dart_SetNativeResolver(lib, &IsolateInterruptTestNativeLookup);
     DART_CHECK_VALID(result);
@@ -6570,7 +6612,7 @@
   Dart_Handle source = NewString(kScriptChars);
   result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
-  Dart_Handle lib = Dart_LoadScript(url, source);
+  Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
   EXPECT_VALID(lib);
   EXPECT(Dart_IsLibrary(lib));
   result = Dart_SetNativeResolver(lib, &MyNativeClosureResolver);
@@ -6708,7 +6750,7 @@
   Dart_Handle source = NewString(kScriptChars);
   result = Dart_SetLibraryTagHandler(library_handler);
   EXPECT_VALID(result);
-  Dart_Handle lib = Dart_LoadScript(url, source);
+  Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
   EXPECT_VALID(lib);
   EXPECT(Dart_IsLibrary(lib));
   result = Dart_SetNativeResolver(lib, &MyStaticNativeClosureResolver);
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 180a43c..ab1e060 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -267,7 +267,10 @@
 
   // Reading of regular dart instances is not supported.
   if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
-    return AllocateDartCObjectUnsupported();
+    intptr_t object_id = SerializedHeaderData::decode(value);
+    Dart_CObject* object = AllocateDartCObjectUnsupported();
+    AddBackRef(object_id, object, kIsNotDeserialized);
+    return object;
   }
   ASSERT((class_header & kSmiTagMask) != 0);
   intptr_t object_id = SerializedHeaderData::decode(value);
@@ -310,7 +313,9 @@
                                                      intptr_t object_id) {
   switch (class_id) {
     case kClassCid: {
-      return AllocateDartCObjectUnsupported();
+      Dart_CObject* object = AllocateDartCObjectUnsupported();
+      AddBackRef(object_id, object, kIsDeserialized);
+      return object;
     }
     case kTypeArgumentsCid: {
       // TODO(sjesse): Remove this when message serialization format is
@@ -467,7 +472,9 @@
     }
     default:
       // Everything else not supported.
-      return AllocateDartCObjectUnsupported();
+      Dart_CObject* value = AllocateDartCObjectUnsupported();
+      AddBackRef(object_id, value, kIsDeserialized);
+      return value;
   }
 }
 
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index dd814b7..652d942 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -29,6 +29,12 @@
                                                      current_(buffer),
                                                      end_(buffer + size)  {}
 
+  void SetStream(const uint8_t* buffer, intptr_t size) {
+    buffer_ = buffer;
+    current_ = buffer;
+    end_ = buffer + size;
+  }
+
   template<int N, typename T>
   class Raw { };
 
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index 9b6d5e3..3d61b7b 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -1050,7 +1050,7 @@
   // Load a script.
   Dart_Handle url = NewString(TestCase::url());
   Dart_Handle source = NewString(kScriptChars);
-  EXPECT_VALID(Dart_LoadScript(url, source));
+  EXPECT_VALID(Dart_LoadScript(url, source, 0, 0));
 
   lib_list = Dart_GetLibraryURLs();
   EXPECT_VALID(lib_list);
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index b153b8c..f505590 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -170,6 +170,78 @@
 };
 
 
+class DeoptFloat32x4StackSlotInstr : public DeoptInstr {
+ public:
+  explicit DeoptFloat32x4StackSlotInstr(intptr_t from_index)
+      : stack_slot_index_(from_index) {
+    ASSERT(stack_slot_index_ >= 0);
+  }
+
+  virtual intptr_t from_index() const { return stack_slot_index_; }
+  virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; }
+
+  virtual const char* ToCString() const {
+    const char* format = "f32x4s%"Pd"";
+    intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_);
+    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+    OS::SNPrint(chars, len + 1, format, stack_slot_index_);
+    return chars;
+  }
+
+  void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
+    intptr_t from_index =
+       deopt_context->from_frame_size() - stack_slot_index_ - 1;
+    simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>(
+        deopt_context->GetFromFrameAddressAt(from_index));
+    intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
+    *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
+    Isolate::Current()->DeferFloat32x4Materialization(
+        *from_addr, reinterpret_cast<RawFloat32x4**>(to_addr));
+  }
+
+ private:
+  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr);
+};
+
+
+class DeoptUint32x4StackSlotInstr : public DeoptInstr {
+ public:
+  explicit DeoptUint32x4StackSlotInstr(intptr_t from_index)
+      : stack_slot_index_(from_index) {
+    ASSERT(stack_slot_index_ >= 0);
+  }
+
+  virtual intptr_t from_index() const { return stack_slot_index_; }
+  virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; }
+
+  virtual const char* ToCString() const {
+    const char* format = "ui32x4s%"Pd"";
+    intptr_t len = OS::SNPrint(NULL, 0, format, stack_slot_index_);
+    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+    OS::SNPrint(chars, len + 1, format, stack_slot_index_);
+    return chars;
+  }
+
+  void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
+    intptr_t from_index =
+       deopt_context->from_frame_size() - stack_slot_index_ - 1;
+    simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>(
+        deopt_context->GetFromFrameAddressAt(from_index));
+    intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
+    *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
+    Isolate::Current()->DeferUint32x4Materialization(
+        *from_addr, reinterpret_cast<RawUint32x4**>(to_addr));
+  }
+
+ private:
+  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4StackSlotInstr);
+};
+
+
 // Deoptimization instruction creating return address using function and
 // deopt-id stored at 'object_table_index'. Uses the deopt-after
 // continuation point.
@@ -205,7 +277,9 @@
     function ^= deopt_context->ObjectAt(object_table_index_);
     const Code& code =
         Code::Handle(deopt_context->isolate(), function.unoptimized_code());
+    ASSERT(!code.IsNull());
     uword continue_at_pc = code.GetDeoptAfterPcAtDeoptId(deopt_id_);
+    ASSERT(continue_at_pc != 0);
     intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
     *to_addr = continue_at_pc;
   }
@@ -260,7 +334,9 @@
     function ^= deopt_context->ObjectAt(object_table_index_);
     const Code& code =
         Code::Handle(deopt_context->isolate(), function.unoptimized_code());
+    ASSERT(!code.IsNull());
     uword continue_at_pc = code.GetDeoptBeforePcAtDeoptId(deopt_id_);
+    ASSERT(continue_at_pc != 0);
     intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
     *to_addr = continue_at_pc;
 
@@ -413,6 +489,72 @@
 };
 
 
+// Deoptimization instruction moving an XMM register.
+class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr {
+ public:
+  explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int)
+      : reg_(static_cast<FpuRegister>(reg_as_int)) {}
+
+  virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
+  virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; }
+
+  virtual const char* ToCString() const {
+    const char* format = "%s(f32x4)";
+    intptr_t len =
+        OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_));
+    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+    OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_));
+    return chars;
+  }
+
+  void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
+    simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_);
+    intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
+    *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
+    Isolate::Current()->DeferFloat32x4Materialization(
+        value, reinterpret_cast<RawFloat32x4**>(to_addr));
+  }
+
+ private:
+  const FpuRegister reg_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr);
+};
+
+
+// Deoptimization instruction moving an XMM register.
+class DeoptUint32x4FpuRegisterInstr: public DeoptInstr {
+ public:
+  explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int)
+      : reg_(static_cast<FpuRegister>(reg_as_int)) {}
+
+  virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); }
+  virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; }
+
+  virtual const char* ToCString() const {
+    const char* format = "%s(f32x4)";
+    intptr_t len =
+        OS::SNPrint(NULL, 0, format, Assembler::FpuRegisterName(reg_));
+    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+    OS::SNPrint(chars, len + 1, format, Assembler::FpuRegisterName(reg_));
+    return chars;
+  }
+
+  void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) {
+    simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_);
+    intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index);
+    *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0);
+    Isolate::Current()->DeferUint32x4Materialization(
+        value, reinterpret_cast<RawUint32x4**>(to_addr));
+  }
+
+ private:
+  const FpuRegister reg_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptUint32x4FpuRegisterInstr);
+};
+
+
 // Deoptimization instruction creating a PC marker for the code of
 // function at 'object_table_index'.
 class DeoptPcMarkerInstr : public DeoptInstr {
@@ -447,7 +589,7 @@
     // function occurring in the optimized frame.
     function.set_deoptimization_counter(function.deoptimization_counter() + 1);
     if (FLAG_trace_deoptimization) {
-      OS::PrintErr("Deoptimizing inlined %s (count %d)\n",
+      OS::PrintErr("Deoptimizing %s (count %d)\n",
           function.ToFullyQualifiedCString(),
           function.deoptimization_counter());
     }
@@ -581,7 +723,10 @@
   ASSERT(func != NULL);
   *func ^= object_table.At(ret_after_instr->object_table_index());
   const Code& code = Code::Handle(func->unoptimized_code());
-  return code.GetDeoptAfterPcAtDeoptId(ret_after_instr->deopt_id());
+  ASSERT(!code.IsNull());
+  uword res = code.GetDeoptAfterPcAtDeoptId(ret_after_instr->deopt_id());
+  ASSERT(res != 0);
+  return res;
 }
 
 
@@ -591,12 +736,20 @@
     case kStackSlot: return new DeoptStackSlotInstr(from_index);
     case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index);
     case kInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index);
+    case kFloat32x4StackSlot:
+        return new DeoptFloat32x4StackSlotInstr(from_index);
+    case kUint32x4StackSlot:
+        return new DeoptUint32x4StackSlotInstr(from_index);
     case kRetAfterAddress: return new DeoptRetAfterAddressInstr(from_index);
     case kRetBeforeAddress: return new DeoptRetBeforeAddressInstr(from_index);
     case kConstant: return new DeoptConstantInstr(from_index);
     case kRegister: return new DeoptRegisterInstr(from_index);
     case kFpuRegister: return new DeoptFpuRegisterInstr(from_index);
     case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index);
+    case kFloat32x4FpuRegister:
+        return new DeoptFloat32x4FpuRegisterInstr(from_index);
+    case kUint32x4FpuRegister:
+        return new DeoptUint32x4FpuRegisterInstr(from_index);
     case kPcMarker: return new DeoptPcMarkerInstr(from_index);
     case kCallerFp: return new DeoptCallerFpInstr();
     case kCallerPc: return new DeoptCallerPcInstr();
@@ -664,6 +817,9 @@
 void DeoptInfoBuilder::AddReturnAddressBefore(const Function& function,
                                               intptr_t deopt_id,
                                               intptr_t to_index) {
+  // Check that deopt_id exists.
+  ASSERT(Code::Handle(function.unoptimized_code()).
+      GetDeoptBeforePcAtDeoptId(deopt_id) != 0);
   const intptr_t object_table_index = FindOrAddObjectInTable(function);
   ASSERT(to_index == instructions_.length());
   instructions_.Add(new DeoptRetBeforeAddressInstr(object_table_index,
@@ -691,22 +847,23 @@
 
 
 void DeoptInfoBuilder::AddCopy(const Location& from_loc,
-                               const Value& from_value,
                                const intptr_t to_index) {
   DeoptInstr* deopt_instr = NULL;
   if (from_loc.IsConstant()) {
     intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant());
     deopt_instr = new DeoptConstantInstr(object_table_index);
   } else if (from_loc.IsRegister()) {
+    ASSERT(from_loc.representation() == kTagged);
     deopt_instr = new DeoptRegisterInstr(from_loc.reg());
   } else if (from_loc.IsFpuRegister()) {
-    if (from_loc.representation() == Location::kDouble) {
+    if (from_loc.representation() == kUnboxedDouble) {
       deopt_instr = new DeoptFpuRegisterInstr(from_loc.fpu_reg());
     } else {
-      ASSERT(from_loc.representation() == Location::kMint);
+      ASSERT(from_loc.representation() == kUnboxedMint);
       deopt_instr = new DeoptInt64FpuRegisterInstr(from_loc.fpu_reg());
     }
   } else if (from_loc.IsStackSlot()) {
+    ASSERT(from_loc.representation() == kTagged);
     intptr_t from_index = (from_loc.stack_index() < 0) ?
         from_loc.stack_index() + num_args_ :
         from_loc.stack_index() + num_args_ - kFirstLocalSlotIndex + 1;
@@ -715,16 +872,17 @@
     intptr_t from_index = (from_loc.stack_index() < 0) ?
         from_loc.stack_index() + num_args_ :
         from_loc.stack_index() + num_args_ - kFirstLocalSlotIndex + 1;
-    if (from_loc.representation() == Location::kDouble) {
+    if (from_loc.representation() == kUnboxedDouble) {
       deopt_instr = new DeoptDoubleStackSlotInstr(from_index);
     } else {
-      ASSERT(from_loc.representation() == Location::kMint);
+      ASSERT(from_loc.representation() == kUnboxedMint);
       deopt_instr = new DeoptInt64StackSlotInstr(from_index);
     }
   } else {
     UNREACHABLE();
   }
   ASSERT(to_index == instructions_.length());
+  ASSERT(deopt_instr != NULL);
   instructions_.Add(deopt_instr);
 }
 
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 134d33d..7967aa9 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -53,11 +53,16 @@
   }
 
   double FpuRegisterValue(FpuRegister reg) const {
-    return fpu_registers_copy_[reg];
+    return *reinterpret_cast<double*>(&fpu_registers_copy_[reg]);
   }
 
   int64_t FpuRegisterValueAsInt64(FpuRegister reg) const {
-    return (reinterpret_cast<int64_t*>(fpu_registers_copy_))[reg];
+    return *reinterpret_cast<int64_t*>(&fpu_registers_copy_[reg]);
+  }
+
+  simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const {
+    const float* address = reinterpret_cast<float*>(&fpu_registers_copy_[reg]);
+    return simd128_value_t().readFrom(address);
   }
 
   Isolate* isolate() const { return isolate_; }
@@ -73,7 +78,7 @@
   intptr_t* from_frame_;
   intptr_t from_frame_size_;
   intptr_t* registers_copy_;
-  double* fpu_registers_copy_;
+  fpu_register_t* fpu_registers_copy_;
   const intptr_t num_args_;
   const DeoptReasonId deopt_reason_;
   intptr_t caller_fp_;
@@ -96,9 +101,13 @@
     kRegister,
     kFpuRegister,
     kInt64FpuRegister,
+    kFloat32x4FpuRegister,
+    kUint32x4FpuRegister,
     kStackSlot,
     kDoubleStackSlot,
     kInt64StackSlot,
+    kFloat32x4StackSlot,
+    kUint32x4StackSlot,
     kPcMarker,
     kCallerFp,
     kCallerPc,
@@ -165,9 +174,7 @@
                              intptr_t to_index);
 
   // Copy from optimized frame to unoptimized.
-  void AddCopy(const Location& from_loc,
-               const Value& from_value,
-               intptr_t to_index);
+  void AddCopy(const Location& from_loc, intptr_t to_index);
   void AddPcMarker(const Function& function, intptr_t to_index);
   void AddCallerFp(intptr_t to_index);
   void AddCallerPc(intptr_t to_index);
diff --git a/runtime/vm/disassembler.h b/runtime/vm/disassembler.h
index 9958b20..1f2a22c 100644
--- a/runtime/vm/disassembler.h
+++ b/runtime/vm/disassembler.h
@@ -60,51 +60,50 @@
   // Disassemble instructions between start and end.
   // (The assumption is that start is at a valid instruction).
   // Return true if all instructions were successfully decoded, false otherwise.
-  static bool Disassemble(uword start,
+  static void Disassemble(uword start,
                           uword end,
                           DisassemblyFormatter* formatter,
                           const Code::Comments& comments);
 
-  static bool Disassemble(uword start,
+  static void Disassemble(uword start,
                           uword end,
                           DisassemblyFormatter* formatter) {
-    return Disassemble(start, end, formatter, Code::Comments::New(0));
+    Disassemble(start, end, formatter, Code::Comments::New(0));
   }
 
-  static bool Disassemble(uword start,
+  static void Disassemble(uword start,
                           uword end,
                           const Code::Comments& comments) {
     DisassembleToStdout stdout_formatter;
-    return Disassemble(start, end, &stdout_formatter, comments);
+    Disassemble(start, end, &stdout_formatter, comments);
   }
 
-  static bool Disassemble(uword start, uword end) {
+  static void Disassemble(uword start, uword end) {
     DisassembleToStdout stdout_formatter;
-    return Disassemble(start, end, &stdout_formatter);
+    Disassemble(start, end, &stdout_formatter);
   }
 
   // Disassemble instructions in a memory region.
-  static bool DisassembleMemoryRegion(const MemoryRegion& instructions,
+  static void DisassembleMemoryRegion(const MemoryRegion& instructions,
                                       DisassemblyFormatter* formatter) {
     uword start = instructions.start();
     uword end = instructions.end();
-    return Disassemble(start, end, formatter);
+    Disassemble(start, end, formatter);
   }
 
-  static bool DisassembleMemoryRegion(const MemoryRegion& instructions) {
+  static void DisassembleMemoryRegion(const MemoryRegion& instructions) {
     uword start = instructions.start();
     uword end = instructions.end();
-    return Disassemble(start, end);
+    Disassemble(start, end);
   }
 
   // Decodes one instruction.
   // Writes a hexadecimal representation into the hex_buffer and a
   // human-readable representation into the human_buffer.
   // Writes the length of the decoded instruction in bytes in out_instr_len.
-  // Returns false if the instruction could not be decoded.
-  static bool DecodeInstruction(char* hex_buffer, intptr_t hex_size,
+  static void DecodeInstruction(char* hex_buffer, intptr_t hex_size,
                                 char* human_buffer, intptr_t human_size,
-                                int *out_instr_len, uword pc);
+                                int* out_instr_len, uword pc);
 
  private:
   static const int kHexadecimalBufferSize = 32;
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index 6cecb45..067f069 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -15,8 +15,7 @@
   ARMDecoder(char* buffer, size_t buffer_size)
       : buffer_(buffer),
         buffer_size_(buffer_size),
-        buffer_pos_(0),
-        decode_failure_(false) {
+        buffer_pos_(0) {
     buffer_[buffer_pos_] = '\0';
   }
 
@@ -26,9 +25,6 @@
   // Returns true if the instruction was successfully decoded, false otherwise.
   void InstructionDecode(uword pc);
 
-  void set_decode_failure(bool b) { decode_failure_ = b; }
-  bool decode_failure() const { return decode_failure_; }
-
  private:
   // Bottleneck functions to print into the out_buffer.
   void Print(const char* str);
@@ -71,8 +67,6 @@
   size_t buffer_size_;  // The size of the character buffer.
   size_t buffer_pos_;  // Current character position in buffer.
 
-  bool decode_failure_;  // Set to true when a failure to decode is detected.
-
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(ARMDecoder);
 };
@@ -579,7 +573,6 @@
 // which will just print "unknown" of the instruction bits.
 void ARMDecoder::Unknown(Instr* instr) {
   Format(instr, "unknown");
-  set_decode_failure(true);
 }
 
 
@@ -1267,9 +1260,9 @@
 }
 
 
-bool Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
-                                    char* human_buffer, intptr_t human_size,
-                                    int* out_instr_size, uword pc) {
+void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
+                                     char* human_buffer, intptr_t human_size,
+                                     int* out_instr_size, uword pc) {
   ARMDecoder decoder(human_buffer, human_size);
   decoder.InstructionDecode(pc);
   int32_t instruction_bits = Instr::At(pc)->InstructionBits();
@@ -1277,16 +1270,14 @@
   if (out_instr_size) {
     *out_instr_size = Instr::kInstrSize;
   }
-  return !decoder.decode_failure();
 }
 
 
-bool Disassembler::Disassemble(uword start,
+void Disassembler::Disassemble(uword start,
                                uword end,
                                DisassemblyFormatter* formatter,
                                const Code::Comments& comments) {
   ASSERT(formatter != NULL);
-  bool success = true;
   char hex_buffer[kHexadecimalBufferSize];  // Instruction in hexadecimal form.
   char human_buffer[kUserReadableBufferSize];  // Human-readable instruction.
   uword pc = start;
@@ -1301,12 +1292,10 @@
       comment_finger++;
     }
     int instruction_length;
-    bool res = DecodeInstruction(hex_buffer, sizeof(hex_buffer),
-                                 human_buffer, sizeof(human_buffer),
-                                 &instruction_length, pc);
-    if (!res) {
-      success = false;
-    }
+    DecodeInstruction(hex_buffer, sizeof(hex_buffer),
+                      human_buffer, sizeof(human_buffer),
+                      &instruction_length, pc);
+
     formatter->ConsumeInstruction(hex_buffer,
                                   sizeof(hex_buffer),
                                   human_buffer,
@@ -1314,8 +1303,6 @@
                                   pc);
     pc += instruction_length;
   }
-
-  return success;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc
index 9aa3a49..f17d0c7 100644
--- a/runtime/vm/disassembler_ia32.cc
+++ b/runtime/vm/disassembler_ia32.cc
@@ -1744,9 +1744,9 @@
 }
 
 
-bool Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
-                                    char* human_buffer, intptr_t human_size,
-                                    int* out_instr_len, uword pc) {
+void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
+                                     char* human_buffer, intptr_t human_size,
+                                     int* out_instr_len, uword pc) {
   ASSERT(hex_size > 0);
   ASSERT(human_size > 0);
   X86Decoder decoder(human_buffer, human_size);
@@ -1763,11 +1763,10 @@
   if (out_instr_len) {
     *out_instr_len = instruction_length;
   }
-  return true;
 }
 
 
-bool Disassembler::Disassemble(uword start,
+void Disassembler::Disassemble(uword start,
                                uword end,
                                DisassemblyFormatter* formatter,
                                const Code::Comments& comments) {
@@ -1799,7 +1798,7 @@
     pc += instruction_length;
   }
 
-  return true;
+  return;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
index d7a83c0..ff74333 100644
--- a/runtime/vm/disassembler_mips.cc
+++ b/runtime/vm/disassembler_mips.cc
@@ -15,8 +15,7 @@
   MIPSDecoder(char* buffer, size_t buffer_size)
       : buffer_(buffer),
         buffer_size_(buffer_size),
-        buffer_pos_(0),
-        decode_failure_(false) {
+        buffer_pos_(0) {
     buffer_[buffer_pos_] = '\0';
   }
 
@@ -26,9 +25,6 @@
   // Returns true if the instruction was successfully decoded, false otherwise.
   void InstructionDecode(Instr* instr);
 
-  void set_decode_failure(bool b) { decode_failure_ = b; }
-  bool decode_failure() const { return decode_failure_; }
-
  private:
   // Bottleneck functions to print into the out_buffer.
   void Print(const char* str);
@@ -43,6 +39,7 @@
 
   void DecodeSpecial(Instr* instr);
   void DecodeSpecial2(Instr* instr);
+  void DecodeRegImm(Instr* instr);
 
   // Convenience functions.
   char* get_buffer() const { return buffer_; }
@@ -53,8 +50,6 @@
   size_t buffer_size_;  // The size of the character buffer.
   size_t buffer_pos_;  // Current character position in buffer.
 
-  bool decode_failure_;  // Set to true when a failure to decode is detected.
-
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(MIPSDecoder);
 };
@@ -143,6 +138,16 @@
       }
       return 4;
     }
+    case 'd': {
+      ASSERT(STRING_STARTS_WITH(format, "dest"));
+      int off = instr->SImmField() << 2;
+      uword destination = reinterpret_cast<uword>(instr) + off;
+      buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
+                                 remaining_size_in_buffer(),
+                                 "%#"Px"",
+                                 destination);
+      return 4;
+    }
     case 'i': {
       ASSERT(STRING_STARTS_WITH(format, "imm"));
       if (format[3] == 'u') {
@@ -202,7 +207,6 @@
 // which will just print "unknown" of the instruction bits.
 void MIPSDecoder::Unknown(Instr* instr) {
   Format(instr, "unknown");
-  set_decode_failure(true);
 }
 
 
@@ -229,6 +233,14 @@
       Format(instr, "divu 'rs, 'rt");
       break;
     }
+    case JALR: {
+      Format(instr, "jalr'hint 'rd, 'rs");
+      break;
+    }
+    case JR: {
+      Format(instr, "jr'hint 'rs");
+      break;
+    }
     case MFHI: {
       Format(instr, "mfhi 'rd");
       break;
@@ -237,6 +249,38 @@
       Format(instr, "mflo 'rd");
       break;
     }
+    case MOVN: {
+      Format(instr, "movn 'rd, 'rs, 'rt");
+      break;
+    }
+    case MOVZ: {
+      Format(instr, "movz 'rd, 'rs, 'rt");
+      break;
+    }
+    case MULT: {
+      Format(instr, "mult 'rs, 'rt");
+      break;
+    }
+    case MULTU: {
+      Format(instr, "multu 'rs, 'rt");
+      break;
+    }
+    case NOR: {
+      Format(instr, "nor 'rd, 'rs, 'rt");
+      break;
+    }
+    case OR: {
+      if (instr->RsField() == 0 && instr->RtField() == 0) {
+        Format(instr, "mov 'rd, 0");
+      } else if (instr->RsField() == R0) {
+        Format(instr, "mov 'rd, 'rt");
+      } else if (instr->RtField() == R0) {
+        Format(instr, "mov 'rd, 'rs");
+      } else {
+        Format(instr, "or 'rd, 'rs, 'rt");
+      }
+      break;
+    }
     case SLL: {
       if ((instr->RdField() == R0) &&
           (instr->RtField() == R0) &&
@@ -247,8 +291,56 @@
       }
       break;
     }
-    case JR: {
-      Format(instr, "jr'hint 'rs");
+    case SLLV: {
+      Format(instr, "sllv 'rd, 'rt, 'rs");
+      break;
+    }
+    case SLT: {
+      Format(instr, "slt 'rd, 'rs, 'rt");
+      break;
+    }
+    case SLTU: {
+      Format(instr, "sltu 'rd, 'rs, 'rt");
+      break;
+    }
+    case SRA: {
+      if (instr->RsField() == 0) {
+        Format(instr, "sra 'rd, 'rt, 'sa");
+      } else {
+        Unknown(instr);
+      }
+      break;
+    }
+    case SRAV: {
+      Format(instr, "srav 'rd, 'rt, 'rs");
+      break;
+    }
+    case SRL: {
+      if (instr->RsField() == 0) {
+        Format(instr, "srl 'rd, 'rt, 'sa");
+      } else {
+        Unknown(instr);
+      }
+      break;
+    }
+    case SRLV: {
+      if (instr->SaField() == 0) {
+        Format(instr, "srlv 'rd, 'rt, 'rs");
+      } else {
+        Unknown(instr);
+      }
+      break;
+    }
+    case SUB: {
+      Format(instr, "sub 'rd, 'rs, 'rt");
+      break;
+    }
+    case SUBU: {
+      Format(instr, "subu 'rd, 'rs, 'rt");
+      break;
+    }
+    case XOR: {
+      Format(instr, "xor 'rd, 'rs, 'rt");
       break;
     }
     default: {
@@ -278,6 +370,33 @@
 }
 
 
+void MIPSDecoder::DecodeRegImm(Instr* instr) {
+  ASSERT(instr->OpcodeField() == REGIMM);
+  switch (instr->RegImmFnField()) {
+    case BGEZ: {
+      Format(instr, "bgez 'rs, 'dest");
+      break;
+    }
+    case BGEZL: {
+      Format(instr, "bgezl 'rs, 'dest");
+      break;
+    }
+    case BLTZ: {
+      Format(instr, "bltz 'rs, 'dest");
+      break;
+    }
+    case BLTZL: {
+      Format(instr, "bltzl 'rs, 'dest");
+      break;
+    }
+    default: {
+      Unknown(instr);
+      break;
+    }
+  }
+}
+
+
 void MIPSDecoder::InstructionDecode(Instr* instr) {
   switch (instr->OpcodeField()) {
     case SPECIAL: {
@@ -288,6 +407,10 @@
       DecodeSpecial2(instr);
       break;
     }
+    case REGIMM: {
+      DecodeRegImm(instr);
+      break;
+    }
     case ADDIU: {
       Format(instr, "addiu 'rt, 'rs, 'imms");
       break;
@@ -296,6 +419,38 @@
       Format(instr, "andi 'rt, 'rs, 'immu");
       break;
     }
+    case BEQ: {
+      Format(instr, "beq 'rs, 'rt, 'dest");
+      break;
+    }
+    case BEQL: {
+      Format(instr, "beql 'rs, 'rt, 'dest");
+      break;
+    }
+    case BGTZ: {
+      Format(instr, "bgtz 'rs, 'dest");
+      break;
+    }
+    case BGTZL: {
+      Format(instr, "bgtzl 'rs, 'dest");
+      break;
+    }
+    case BLEZ: {
+      Format(instr, "blez 'rs, 'dest");
+      break;
+    }
+    case BLEZL: {
+      Format(instr, "blezl 'rs, 'dest");
+      break;
+    }
+    case BNE: {
+      Format(instr, "bne 'rs, 'rt, 'dest");
+      break;
+    }
+    case BNEL: {
+      Format(instr, "bnel 'rs, 'rt, 'dest");
+      break;
+    }
     case LB: {
       Format(instr, "lb 'rt, 'imms('rs)");
       break;
@@ -340,9 +495,9 @@
 }
 
 
-bool Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
-                                    char* human_buffer, intptr_t human_size,
-                                    int *out_instr_len, uword pc) {
+void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
+                                     char* human_buffer, intptr_t human_size,
+                                     int* out_instr_len, uword pc) {
   MIPSDecoder decoder(human_buffer, human_size);
   Instr* instr = Instr::At(pc);
   decoder.InstructionDecode(instr);
@@ -350,16 +505,14 @@
   if (out_instr_len) {
     *out_instr_len = Instr::kInstrSize;
   }
-  return !decoder.decode_failure();
 }
 
 
-bool Disassembler::Disassemble(uword start,
+void Disassembler::Disassemble(uword start,
                                uword end,
                                DisassemblyFormatter* formatter,
                                const Code::Comments& comments) {
   ASSERT(formatter != NULL);
-  bool success = true;
   char hex_buffer[kHexadecimalBufferSize];  // Instruction in hexadecimal form.
   char human_buffer[kUserReadableBufferSize];  // Human-readable instruction.
   uword pc = start;
@@ -374,12 +527,10 @@
       comment_finger++;
     }
     int instruction_length;
-    bool res = DecodeInstruction(hex_buffer, sizeof(hex_buffer),
-                                 human_buffer, sizeof(human_buffer),
-                                 &instruction_length, pc);
-    if (!res) {
-      success = false;
-    }
+    DecodeInstruction(hex_buffer, sizeof(hex_buffer),
+                      human_buffer, sizeof(human_buffer),
+                      &instruction_length, pc);
+
     formatter->ConsumeInstruction(hex_buffer,
                                   sizeof(hex_buffer),
                                   human_buffer,
@@ -388,7 +539,7 @@
     pc += instruction_length;
   }
 
-  return success;
+  return;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc
index c1e442f..e17c4f0 100644
--- a/runtime/vm/disassembler_x64.cc
+++ b/runtime/vm/disassembler_x64.cc
@@ -1865,9 +1865,9 @@
 }
 
 
-bool Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
-                                    char* human_buffer, intptr_t human_size,
-                                    int* out_instr_len, uword pc) {
+void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size,
+                                     char* human_buffer, intptr_t human_size,
+                                     int* out_instr_len, uword pc) {
   ASSERT(hex_size > 0);
   ASSERT(human_size > 0);
   DisassemblerX64 decoder(human_buffer, human_size);
@@ -1884,11 +1884,10 @@
   if (out_instr_len) {
     *out_instr_len = instruction_length;
   }
-  return true;
 }
 
 
-bool Disassembler::Disassemble(uword start,
+void Disassembler::Disassemble(uword start,
                                uword end,
                                DisassemblyFormatter* formatter,
                                const Code::Comments& comments) {
@@ -1920,7 +1919,7 @@
     pc += instruction_length;
   }
 
-  return true;
+  return;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
index 8453b7b..7bb1e9f 100644
--- a/runtime/vm/find_code_object_test.cc
+++ b/runtime/vm/find_code_object_test.cc
@@ -13,19 +13,23 @@
 
 namespace dart {
 
-// Compiler only implemented on IA32 and x64 now.
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
+// Compiler only implemented on IA32, X64, and ARM.
+#if defined(TARGET_ARCH_IA32) ||                                               \
+    defined(TARGET_ARCH_X64) ||                                                \
+    defined(TARGET_ARCH_ARM)
 
 TEST_CASE(FindCodeObject) {
 #if defined(TARGET_ARCH_IA32)
   const int kLoopCount = 50000;
-#else
+#elif defined(TARGET_ARCH_X64)
   const int kLoopCount = 25000;
+#else
+  const int kLoopCount = 20000;
 #endif
   const int kScriptSize = 512 * KB;
   const int kNumFunctions = 1024;
   char scriptChars[kScriptSize];
-  String& url = String::Handle(String::New("dart-test:FincCodeObject"));
+  String& url = String::Handle(String::New("dart-test:FindCodeObject"));
   String& source = String::Handle();
   Script& script = Script::Handle();
   Library& lib = Library::Handle();
@@ -152,6 +156,6 @@
   EXPECT(Code::LookupCode(pc) == code.raw());
 }
 
-#endif  // TARGET_ARCH_IA32 || TARGET_ARCH_X64
+#endif  // TARGET_ARCH_IA32 || TARGET_ARCH_X64 || TARGET_ARCH_ARM
 
 }  // namespace dart
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index fe14079..9f8e9a5 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -696,4 +696,39 @@
 }
 
 
+const ZoneGrowableArray<Field*>* FlowGraph::FieldDependencies() const {
+  ZoneGrowableArray<Field*>* result = new ZoneGrowableArray<Field*>(10);
+
+  for (intptr_t i = 1; i < reverse_postorder().length(); i++) {
+    BlockEntryInstr* entry = reverse_postorder()[i];
+    for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
+      LoadFieldInstr* load_field = it.Current()->AsLoadField();
+      if (load_field == NULL) {
+        continue;
+      }
+
+      Field* field = load_field->field();
+      if ((field == NULL) ||
+          (field->guarded_cid() == kDynamicCid) ||
+          (field->guarded_cid() == kIllegalCid)) {
+        continue;
+      }
+
+      bool found = false;
+      for (intptr_t j = 0; j < result->length(); j++) {
+        if ((*result)[j]->raw() == field->raw()) {
+          found = true;
+          break;
+        }
+      }
+
+      if (!found) {
+        result->Add(field);
+      }
+    }
+  }
+
+  return result;
+}
+
 }  // namespace dart
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 14c298a..a3c0235 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -141,6 +141,11 @@
   bool VerifyUseLists();
 #endif  // DEBUG
 
+  // Return all instance fields that are loaded in the graph and
+  // have non-generic type feedback attached to them that can
+  // potentially affect optimizations.
+  const ZoneGrowableArray<Field*>* FieldDependencies() const;
+
  private:
   friend class BranchSimplifier;
   friend class ConstantPropagator;
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 02704b2..5024030 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -63,7 +63,7 @@
 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph)
   : flow_graph_(flow_graph),
     reaching_defs_(flow_graph),
-    mint_values_(NULL),
+    value_representations_(flow_graph.max_virtual_register_number()),
     block_order_(flow_graph.reverse_postorder()),
     postorder_(flow_graph.postorder()),
     live_out_(block_order_.length()),
@@ -77,6 +77,9 @@
     blocked_fpu_registers_(),
     cpu_spill_slot_count_(0) {
   for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL);
+  for (intptr_t i = 0; i < vreg_count_; i++) {
+    value_representations_.Add(kNoRepresentation);
+  }
 
   // All registers are marked as "not blocked" (array initialized to false).
   // Mark the unavailable ones as "blocked" (true).
@@ -385,8 +388,8 @@
 
 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) {
   if (live_ranges_[vreg] == NULL) {
-    Location::Representation rep =
-        mint_values_->Contains(vreg) ? Location::kMint : Location::kDouble;
+    Representation rep = value_representations_[vreg];
+    ASSERT(rep != kNoRepresentation);
     live_ranges_[vreg] = new LiveRange(vreg, rep);
   }
   return live_ranges_[vreg];
@@ -394,7 +397,8 @@
 
 
 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() {
-  Location::Representation ignored = Location::kDouble;
+  // Representation does not matter for temps.
+  Representation ignored = kNoRepresentation;
   LiveRange* range = new LiveRange(kTempVirtualRegister, ignored);
 #if defined(DEBUG)
   temporaries_.Add(range);
@@ -413,7 +417,7 @@
   }
 
   if (blocking_ranges[loc.register_code()] == NULL) {
-    Location::Representation ignored = Location::kDouble;
+    Representation ignored = kNoRepresentation;
     LiveRange* range = new LiveRange(kNoVirtualRegister, ignored);
     blocking_ranges[loc.register_code()] = range;
     range->set_assigned_location(loc);
@@ -506,6 +510,19 @@
 }
 
 
+// Returns true if all uses of the given range have Any allocation policy.
+static bool HasOnlyUnconstrainedUses(LiveRange* range) {
+  UsePosition* use = range->first_use();
+  while (use != NULL) {
+    if (!use->location_slot()->Equals(Location::Any())) {
+      return false;
+    }
+    use = use->next();
+  }
+  return true;
+}
+
+
 void FlowGraphAllocator::BuildLiveRanges() {
   const intptr_t block_count = postorder_.length();
   ASSERT(postorder_.Last()->IsGraphEntry());
@@ -528,6 +545,10 @@
       current_interference_set =
           new BitVector(flow_graph_.max_virtual_register_number());
       ASSERT(loop_header->backedge_interference() == NULL);
+      // All values flowing into the loop header are live at the back-edge and
+      // can interfere with phi moves.
+      current_interference_set->AddAll(
+          live_in_[loop_header->entry()->postorder_number()]);
       loop_header->set_backedge_interference(
           current_interference_set);
     }
@@ -824,13 +845,30 @@
   LocationSummary* locs = current->locs();
 
   Definition* def = current->AsDefinition();
-  if ((def != NULL) &&
-      (def->AsConstant() != NULL) &&
-      ((def->ssa_temp_index() == -1) ||
-       (GetLiveRange(def->ssa_temp_index())->first_use() == NULL))) {
+  if ((def != NULL) && (def->AsConstant() != NULL)) {
+    LiveRange* range = (def->ssa_temp_index() != -1) ?
+        GetLiveRange(def->ssa_temp_index()) : NULL;
+
     // Drop definitions of constants that have no uses.
-    locs->set_out(Location::NoLocation());
-    return;
+    if ((range == NULL) || (range->first_use() == NULL)) {
+      locs->set_out(Location::NoLocation());
+      return;
+    }
+
+    // If this constant has only unconstrained uses convert them all
+    // to use the constant directly and drop this definition.
+    // TODO(vegorov): improve allocation when we have enough registers to keep
+    // constants used in the loop in them.
+    if (HasOnlyUnconstrainedUses(range)) {
+      const Object& value = def->AsConstant()->value();
+      range->set_assigned_location(Location::Constant(value));
+      range->set_spill_slot(Location::Constant(value));
+      range->finger()->Initialize(range);
+      ConvertAllUses(range);
+
+      locs->set_out(Location::NoLocation());
+      return;
+    }
   }
 
   const intptr_t pos = current->lifetime_position();
@@ -953,7 +991,7 @@
     }
 
     for (intptr_t reg = 0; reg < kNumberOfFpuRegisters; reg++) {
-      Location::Representation ignored = Location::kDouble;
+      Representation ignored = kNoRepresentation;
       BlockLocation(
           Location::FpuRegisterLocation(static_cast<FpuRegister>(reg), ignored),
           pos,
@@ -1592,7 +1630,7 @@
   LiveRange* parent = GetLiveRange(range->vreg());
   if (parent->spill_slot().IsInvalid()) {
     AllocateSpillSlotFor(parent);
-    if (register_kind_ == Location::kRegister) {
+    if (range->representation() == kTagged) {
       MarkAsObjectAtSafepoints(parent);
     }
   }
@@ -1705,7 +1743,7 @@
                           hint.Name(),
                           unallocated->vreg(),
                           free_until));
-  } else if (free_until != kMaxPosition) {
+  } else {
     for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
       if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) {
         candidate = reg;
@@ -1715,6 +1753,23 @@
     }
   }
 
+  ASSERT(0 <= kMaxPosition);
+  if (free_until != kMaxPosition) {
+    for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
+      if (blocked_registers_[reg] || (reg == candidate)) continue;
+      const intptr_t intersection =
+          FirstIntersectionWithAllocated(reg, unallocated);
+      if (intersection > free_until) {
+        candidate = reg;
+        free_until = intersection;
+        if (free_until == kMaxPosition) break;
+      }
+    }
+  }
+
+  // All registers are blocked by active ranges.
+  if (free_until <= unallocated->Start()) return false;
+
   // We have a very good candidate (either hinted to us or completely free).
   // If we are in a loop try to reduce number of moves on the back edge by
   // searching for a candidate that does not interfere with phis on the back
@@ -1748,7 +1803,7 @@
       TRACE_ALLOC(OS::Print(
           "considering %s for v%"Pd": has interference on the back edge"
           " {loop [%"Pd", %"Pd")}\n",
-          MakeRegisterLocation(candidate, Location::kDouble).Name(),
+          MakeRegisterLocation(candidate, kUnboxedDouble).Name(),
           unallocated->vreg(),
           loop_header->entry()->start_pos(),
           loop_header->last_block()->end_pos()));
@@ -1766,7 +1821,7 @@
           free_until = intersection;
           TRACE_ALLOC(OS::Print(
               "found %s for v%"Pd" with no interference on the back edge\n",
-              MakeRegisterLocation(candidate, Location::kDouble).Name(),
+              MakeRegisterLocation(candidate, kUnboxedDouble).Name(),
               candidate));
           break;
         }
@@ -1774,25 +1829,8 @@
     }
   }
 
-  ASSERT(0 <= kMaxPosition);
-  if (free_until != kMaxPosition) {
-    for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
-      if (blocked_registers_[reg] || (reg == candidate)) continue;
-      const intptr_t intersection =
-          FirstIntersectionWithAllocated(reg, unallocated);
-      if (intersection > free_until) {
-        candidate = reg;
-        free_until = intersection;
-        if (free_until == kMaxPosition) break;
-      }
-    }
-  }
-
-  // All registers are blocked by active ranges.
-  if (free_until <= unallocated->Start()) return false;
-
   TRACE_ALLOC(OS::Print("assigning free register "));
-  TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
+  TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print());
   TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg()));
 
   if (free_until != kMaxPosition) {
@@ -1895,7 +1933,7 @@
   }
 
   TRACE_ALLOC(OS::Print("assigning blocked register "));
-  TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
+  TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print());
   TRACE_ALLOC(OS::Print(" to live range v%"Pd" until %"Pd"\n",
                         unallocated->vreg(), blocked_at));
 
@@ -2397,21 +2435,34 @@
 
 
 void FlowGraphAllocator::CollectRepresentations() {
-  mint_values_ = new BitVector(flow_graph_.max_virtual_register_number());
+  // Parameters.
+  GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
+  for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
+    Definition* def = (*graph_entry->initial_definitions())[i];
+    value_representations_[def->ssa_temp_index()] = def->representation();
+  }
 
   for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
        !it.Done();
        it.Advance()) {
     BlockEntryInstr* block = it.Current();
-    // TODO(fschneider): Support unboxed mint representation for phis.
+    // Phis.
+    if (block->IsJoinEntry()) {
+      JoinEntryInstr* join = block->AsJoinEntry();
+      for (PhiIterator it(join); !it.Done(); it.Advance()) {
+        PhiInstr* phi = it.Current();
+        if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
+          value_representations_[phi->ssa_temp_index()] = phi->representation();
+        }
+      }
+    }
+    // Normal instructions.
     for (ForwardInstructionIterator instr_it(block);
          !instr_it.Done();
          instr_it.Advance()) {
-      Definition* defn = instr_it.Current()->AsDefinition();
-      if ((defn != NULL) &&
-          (defn->ssa_temp_index() >= 0) &&
-          (defn->representation() == kUnboxedMint)) {
-        mint_values_->Add(defn->ssa_temp_index());
+      Definition* def = instr_it.Current()->AsDefinition();
+      if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
+        value_representations_[def->ssa_temp_index()] = def->representation();
       }
     }
   }
diff --git a/runtime/vm/flow_graph_allocator.h b/runtime/vm/flow_graph_allocator.h
index b191758..526db56 100644
--- a/runtime/vm/flow_graph_allocator.h
+++ b/runtime/vm/flow_graph_allocator.h
@@ -227,7 +227,7 @@
 
   MoveOperands* AddMoveAt(intptr_t pos, Location to, Location from);
 
-  Location MakeRegisterLocation(intptr_t reg, Location::Representation rep) {
+  Location MakeRegisterLocation(intptr_t reg, Representation rep) {
     return Location::MachineRegisterLocation(register_kind_, reg, rep);
   }
 
@@ -237,9 +237,8 @@
 
   ReachingDefs reaching_defs_;
 
-  // Set of SSA values that have unboxed mint representation. Indexed
-  // by SSA temp index.
-  BitVector* mint_values_;
+  // Representation for SSA values indexed by SSA temp index.
+  GrowableArray<Representation> value_representations_;
 
   const GrowableArray<BlockEntryInstr*>& block_order_;
   const GrowableArray<BlockEntryInstr*>& postorder_;
@@ -527,7 +526,7 @@
 // LiveRange represents a sequence of UseIntervals for a given SSA value.
 class LiveRange : public ZoneAllocated {
  public:
-  explicit LiveRange(intptr_t vreg, Location::Representation rep)
+  explicit LiveRange(intptr_t vreg, Representation rep)
     : vreg_(vreg),
       representation_(rep),
       assigned_location_(),
@@ -546,7 +545,7 @@
   static LiveRange* MakeTemp(intptr_t pos, Location* location_slot);
 
   intptr_t vreg() const { return vreg_; }
-  Location::Representation representation() const { return representation_; }
+  Representation representation() const { return representation_; }
   LiveRange* next_sibling() const { return next_sibling_; }
   UsePosition* first_use() const { return uses_; }
   void set_first_use(UsePosition* use) { uses_ = use; }
@@ -618,7 +617,7 @@
 
  private:
   LiveRange(intptr_t vreg,
-            Location::Representation rep,
+            Representation rep,
             UsePosition* uses,
             UseInterval* first_use_interval,
             UseInterval* last_use_interval,
@@ -639,7 +638,7 @@
   }
 
   const intptr_t vreg_;
-  Location::Representation representation_;
+  Representation representation_;
   Location assigned_location_;
   Location spill_slot_;
 
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 9f4072f..7eb6581 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2589,8 +2589,20 @@
                                        type,
                                        dst_name);
   }
-  StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
-      node->field(), for_instance.value(), store_value, kEmitStoreBarrier);
+
+  store_value = Bind(BuildStoreExprTemp(store_value));
+  GuardFieldInstr* guard =
+      new GuardFieldInstr(store_value,
+                          node->field(),
+                          Isolate::Current()->GetNextDeoptId());
+  AddInstruction(guard);
+
+  store_value = Bind(BuildLoadExprTemp());
+  StoreInstanceFieldInstr* store =
+      new StoreInstanceFieldInstr(node->field(),
+                                  for_instance.value(),
+                                  store_value,
+                                  kEmitStoreBarrier);
   ReturnDefinition(store);
 }
 
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index c4228e8..37eff8b5 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -79,7 +79,7 @@
   for (intptr_t i = current->Length() - 1;
        i >= current->fixed_parameter_count();
        i--) {
-    builder->AddCopy(current->LocationAt(i), *current->ValueAt(i), slot_ix++);
+    builder->AddCopy(current->LocationAt(i), slot_ix++);
   }
 
   // PC marker and caller FP.
@@ -98,15 +98,14 @@
     // The values of outgoing arguments can be changed from the inlined call so
     // we must read them from the previous environment.
     for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
-      builder->AddCopy(previous->LocationAt(i), *previous->ValueAt(i),
-                       slot_ix++);
+      builder->AddCopy(previous->LocationAt(i), slot_ix++);
     }
 
     // Set the locals, note that outgoing arguments are not in the environment.
     for (intptr_t i = current->Length() - 1;
          i >= current->fixed_parameter_count();
          i--) {
-      builder->AddCopy(current->LocationAt(i), *current->ValueAt(i), slot_ix++);
+      builder->AddCopy(current->LocationAt(i), slot_ix++);
     }
 
     // PC marker and caller FP.
@@ -125,7 +124,7 @@
 
   // For the outermost environment, set the incoming arguments.
   for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
-    builder->AddCopy(previous->LocationAt(i), *previous->ValueAt(i), slot_ix++);
+    builder->AddCopy(previous->LocationAt(i), slot_ix++);
   }
 
   const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
@@ -237,7 +236,10 @@
   for (intptr_t i = block_order().length() - 1; i >= 1; --i) {
     BlockEntryInstr* block = block_order()[i];
 
-    CompactBlock(block);
+    // Unoptimized code must emit all possible deoptimization points.
+    if (is_optimizing()) {
+      CompactBlock(block);
+    }
 
     if (!WasCompacted(block)) {
       BlockInfo* block_info = block_info_[block->postorder_number()];
@@ -413,12 +415,11 @@
         //
         // FPU registers have the highest register number at the highest
         // address (i.e., first in the stackmap).
+        const intptr_t kFpuRegisterSpillFactor = kFpuRegisterSize / kWordSize;
         for (intptr_t i = kNumberOfFpuRegisters - 1; i >= 0; --i) {
           FpuRegister reg = static_cast<FpuRegister>(i);
           if (regs->ContainsFpuRegister(reg)) {
-            for (intptr_t j = 0;
-                 j < FlowGraphAllocator::kDoubleSpillSlotFactor;
-                 ++j) {
+            for (intptr_t j = 0; j < kFpuRegisterSpillFactor; ++j) {
               bitmap->Set(bitmap->Length(), false);
             }
           }
@@ -560,8 +561,10 @@
       ASSERT(sequence_node.NodeAt(1)->IsReturnNode());
       const StoreInstanceFieldNode& store_node =
           *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode();
-      GenerateInlinedSetter(store_node.field().Offset());
-      return true;
+      if (store_node.field().guarded_cid() == kDynamicCid) {
+        GenerateInlinedSetter(store_node.field().Offset());
+        return true;
+      }
     }
   }
   // Even if an intrinsified version of the function was successfully
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 9b2bb20..7fb6ecb 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -166,8 +166,229 @@
 }
 
 
+// Input parameters:
+//   R4: arguments descriptor array.
 void FlowGraphCompiler::CopyParameters() {
-  UNIMPLEMENTED();
+  __ Comment("Copy parameters");
+  const Function& function = parsed_function().function();
+  LocalScope* scope = parsed_function().node_sequence()->scope();
+  const int num_fixed_params = function.num_fixed_parameters();
+  const int num_opt_pos_params = function.NumOptionalPositionalParameters();
+  const int num_opt_named_params = function.NumOptionalNamedParameters();
+  const int num_params =
+      num_fixed_params + num_opt_pos_params + num_opt_named_params;
+  ASSERT(function.NumParameters() == num_params);
+  ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex);
+
+  // Check that min_num_pos_args <= num_pos_args <= max_num_pos_args,
+  // where num_pos_args is the number of positional arguments passed in.
+  const int min_num_pos_args = num_fixed_params;
+  const int max_num_pos_args = num_fixed_params + num_opt_pos_params;
+
+  __ ldr(R8, FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
+  // Check that min_num_pos_args <= num_pos_args.
+  Label wrong_num_arguments;
+  __ CompareImmediate(R8, Smi::RawValue(min_num_pos_args));
+  __ b(&wrong_num_arguments, LT);
+  // Check that num_pos_args <= max_num_pos_args.
+  __ CompareImmediate(R8, Smi::RawValue(max_num_pos_args));
+  __ b(&wrong_num_arguments, GT);
+
+  // Copy positional arguments.
+  // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied
+  // to fp[kFirstLocalSlotIndex - i].
+
+  __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+  // Since R7 and R8 are Smi, use LSL 1 instead of LSL 2.
+  // Let R7 point to the last passed positional argument, i.e. to
+  // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)].
+  __ sub(R7, R7, ShifterOperand(R8));
+  __ add(R7, FP, ShifterOperand(R7, LSL, 1));
+  __ add(R7, R7, ShifterOperand(kLastParamSlotIndex * kWordSize));
+
+  // Let R6 point to the last copied positional argument, i.e. to
+  // fp[kFirstLocalSlotIndex - (num_pos_args - 1)].
+  __ AddImmediate(R6, FP, (kFirstLocalSlotIndex + 1) * kWordSize);
+  __ sub(R6, R6, ShifterOperand(R8, LSL, 1));  // R8 is a Smi.
+  __ SmiUntag(R8);
+  Label loop, loop_condition;
+  __ b(&loop_condition);
+  // We do not use the final allocation index of the variable here, i.e.
+  // scope->VariableAt(i)->index(), because captured variables still need
+  // to be copied to the context that is not yet allocated.
+  const Address argument_addr(R7, R8, LSL, 2);
+  const Address copy_addr(R6, R8, LSL, 2);
+  __ Bind(&loop);
+  __ ldr(IP, argument_addr);
+  __ str(IP, copy_addr);
+  __ Bind(&loop_condition);
+  __ subs(R8, R8, ShifterOperand(1));
+  __ b(&loop, PL);
+
+  // Copy or initialize optional named arguments.
+  Label all_arguments_processed;
+  if (num_opt_named_params > 0) {
+    // Start by alphabetically sorting the names of the optional parameters.
+    LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
+    int* opt_param_position = new int[num_opt_named_params];
+    for (int pos = num_fixed_params; pos < num_params; pos++) {
+      LocalVariable* parameter = scope->VariableAt(pos);
+      const String& opt_param_name = parameter->name();
+      int i = pos - num_fixed_params;
+      while (--i >= 0) {
+        LocalVariable* param_i = opt_param[i];
+        const intptr_t result = opt_param_name.CompareTo(param_i->name());
+        ASSERT(result != 0);
+        if (result > 0) break;
+        opt_param[i + 1] = opt_param[i];
+        opt_param_position[i + 1] = opt_param_position[i];
+      }
+      opt_param[i + 1] = parameter;
+      opt_param_position[i + 1] = pos;
+    }
+    // Generate code handling each optional parameter in alphabetical order.
+    __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+    __ ldr(R8,
+           FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
+    __ SmiUntag(R8);
+    // Let R7 point to the first passed argument, i.e. to
+    // fp[kLastParamSlotIndex + num_args - 1 - 0]; num_args (R7) is Smi.
+    __ add(R7, FP, ShifterOperand(R7, LSL, 1));
+    __ AddImmediate(R7, R7, (kLastParamSlotIndex - 1) * kWordSize);
+    // Let R6 point to the entry of the first named argument.
+    __ add(R6, R4, ShifterOperand(
+        ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag));
+    for (int i = 0; i < num_opt_named_params; i++) {
+      Label load_default_value, assign_optional_parameter;
+      const int param_pos = opt_param_position[i];
+      // Check if this named parameter was passed in.
+      // Load R5 with the name of the argument.
+      __ ldr(R5, Address(R6, ArgumentsDescriptor::name_offset()));
+      ASSERT(opt_param[i]->name().IsSymbol());
+      __ CompareObject(R5, opt_param[i]->name());
+      __ b(&load_default_value, NE);
+      // Load R5 with passed-in argument at provided arg_pos, i.e. at
+      // fp[kLastParamSlotIndex + num_args - 1 - arg_pos].
+      __ ldr(R5, Address(R6, ArgumentsDescriptor::position_offset()));
+      // R5 is arg_pos as Smi.
+      // Point to next named entry.
+      __ add(R6, R6, ShifterOperand(ArgumentsDescriptor::named_entry_size()));
+      __ rsb(R5, R5, ShifterOperand(0));
+      Address argument_addr(R7, R5, LSL, 1);  // R5 is a negative Smi.
+      __ ldr(R5, argument_addr);
+      __ b(&assign_optional_parameter);
+      __ Bind(&load_default_value);
+      // Load R5 with default argument.
+      const Object& value = Object::ZoneHandle(
+          parsed_function().default_parameter_values().At(
+              param_pos - num_fixed_params));
+      __ LoadObject(R5, value);
+      __ Bind(&assign_optional_parameter);
+      // Assign R5 to fp[kFirstLocalSlotIndex - param_pos].
+      // We do not use the final allocation index of the variable here, i.e.
+      // scope->VariableAt(i)->index(), because captured variables still need
+      // to be copied to the context that is not yet allocated.
+      const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
+      const Address param_addr(FP, computed_param_pos * kWordSize);
+      __ str(R5, param_addr);
+    }
+    delete[] opt_param;
+    delete[] opt_param_position;
+    // Check that R6 now points to the null terminator in the array descriptor.
+    __ ldr(R5, Address(R6, 0));
+    __ CompareImmediate(R5, reinterpret_cast<int32_t>(Object::null()));
+    __ b(&all_arguments_processed, EQ);
+  } else {
+    ASSERT(num_opt_pos_params > 0);
+    __ ldr(R8,
+           FieldAddress(R4, ArgumentsDescriptor::positional_count_offset()));
+    __ SmiUntag(R8);
+    for (int i = 0; i < num_opt_pos_params; i++) {
+      Label next_parameter;
+      // Handle this optional positional parameter only if k or fewer positional
+      // arguments have been passed, where k is param_pos, the position of this
+      // optional parameter in the formal parameter list.
+      const int param_pos = num_fixed_params + i;
+      __ CompareImmediate(R8, param_pos);
+      __ b(&next_parameter, GT);
+      // Load R5 with default argument.
+      const Object& value = Object::ZoneHandle(
+          parsed_function().default_parameter_values().At(i));
+      __ LoadObject(R5, value);
+      // Assign R5 to fp[kFirstLocalSlotIndex - param_pos].
+      // We do not use the final allocation index of the variable here, i.e.
+      // scope->VariableAt(i)->index(), because captured variables still need
+      // to be copied to the context that is not yet allocated.
+      const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
+      const Address param_addr(FP, computed_param_pos * kWordSize);
+      __ str(R5, param_addr);
+      __ Bind(&next_parameter);
+    }
+    __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+    __ SmiUntag(R7);
+    // Check that R8 equals R7, i.e. no named arguments passed.
+    __ cmp(R8, ShifterOperand(R7));
+    __ b(&all_arguments_processed, EQ);
+  }
+
+  __ 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(
+      function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
+  const int kNumArgsChecked = 1;
+  const ICData& ic_data = ICData::ZoneHandle(
+      ICData::New(function, name, Isolate::kNoDeoptId, kNumArgsChecked));
+  __ LoadObject(R5, 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).
+  // R5 : ic-data.
+  // R4 : arguments descriptor array.
+  __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel());
+  if (is_optimizing()) {
+    stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
+                                      empty_stack_bitmap,
+                                      0);  // No registers.
+  }
+  // The noSuchMethod call may return.
+  __ LeaveDartFrame();
+  __ Ret();
+
+  __ Bind(&all_arguments_processed);
+  // Nullify originally passed arguments only after they have been copied and
+  // checked, otherwise noSuchMethod would not see their original values.
+  // This step can be skipped in case we decide that formal parameters are
+  // implicitly final, since garbage collecting the unmodified value is not
+  // an issue anymore.
+
+  // R4 : arguments descriptor array.
+  __ ldr(R8, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+  __ SmiUntag(R8);
+  __ add(R7, FP, ShifterOperand(kLastParamSlotIndex * kWordSize));
+  const Address original_argument_addr(R7, R8, LSL, 2);
+  __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
+  Label null_args_loop, null_args_loop_condition;
+  __ b(&null_args_loop_condition);
+  __ Bind(&null_args_loop);
+  __ str(IP, original_argument_addr);
+  __ Bind(&null_args_loop_condition);
+  __ subs(R8, R8, ShifterOperand(1));
+  __ b(&null_args_loop, PL);
 }
 
 
@@ -235,6 +456,13 @@
 }
 
 
+// Input parameters:
+//   LR: return address.
+//   SP: address of last argument.
+//   FP: caller's frame pointer.
+//   PP: caller's pool pointer.
+//   R5: ic-data.
+//   R4: arguments descriptor array.
 void FlowGraphCompiler::CompileGraph() {
   InitCompiler();
   if (TryIntrinsify()) {
@@ -254,15 +482,6 @@
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
 
-  // For optimized code, keep a bitmap of the frame in order to build
-  // stackmaps for GC safepoints in the prologue.
-  LocationSummary* prologue_locs = NULL;
-  if (is_optimizing()) {
-    // Spill slots are allocated but not initialized.
-    prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall);
-    prologue_locs->stack_bitmap()->SetLength(StackSize());
-  }
-
   // We check the number of passed arguments when we have to copy them due to
   // the presence of optional parameters.
   // No such checking code is generated if only fixed parameters are declared,
@@ -444,7 +663,14 @@
                                          intptr_t deopt_id,
                                          intptr_t token_pos,
                                          LocationSummary* locs) {
-  UNIMPLEMENTED();
+  __ LoadObject(R5, ic_data);
+  __ LoadObject(R4, arguments_descriptor);
+  GenerateDartCall(deopt_id,
+                   token_pos,
+                   target_label,
+                   PcDescriptors::kIcCall,
+                   locs);
+  __ Drop(argument_count);
 }
 
 
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 76f89b84..b9e8bb4 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -630,6 +630,11 @@
       AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
                            assert->deopt_id(),
                            assert->token_pos());
+    } else if (instr->IsGuardField()) {
+      GuardFieldInstr* guard = instr->AsGuardField();
+      AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
+                           guard->deopt_id(),
+                           Scanner::kDummyTokenIndex);
     }
     AllocateRegistersLocally(instr);
   }
@@ -731,13 +736,15 @@
     __ movl(ECX,
             FieldAddress(EDX, ArgumentsDescriptor::positional_count_offset()));
     __ SmiUntag(ECX);
-    // Let EBX point to the first passed argument, i.e. to fp[1 + argc - 0].
-    __ leal(EBX, Address(EBP, EBX, TIMES_2, kWordSize));  // EBX is Smi.
+    // Let EBX point to the first passed argument, i.e. to
+    // fp[kLastParamSlotIndex + num_args - 1 - 0]; num_args (EBX) is Smi.
+    __ leal(EBX,
+            Address(EBP, EBX, TIMES_2, (kLastParamSlotIndex - 1) * kWordSize));
     // Let EDI point to the entry of the first named argument.
     __ leal(EDI,
             FieldAddress(EDX, ArgumentsDescriptor::first_named_entry_offset()));
     for (int i = 0; i < num_opt_named_params; i++) {
-      Label load_default_value, assign_optional_parameter, next_parameter;
+      Label load_default_value, assign_optional_parameter;
       const int param_pos = opt_param_position[i];
       // Check if this named parameter was passed in.
       // Load EAX with the name of the argument.
@@ -746,7 +753,7 @@
       __ CompareObject(EAX, opt_param[i]->name());
       __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
       // Load EAX with passed-in argument at provided arg_pos, i.e. at
-      // fp[1 + argc - arg_pos].
+      // fp[kLastParamSlotIndex + num_args - 1 - arg_pos].
       __ movl(EAX, Address(EDI, ArgumentsDescriptor::position_offset()));
       // EAX is arg_pos as Smi.
       // Point to next named entry.
@@ -767,9 +774,8 @@
       // scope->VariableAt(i)->index(), because captured variables still need
       // to be copied to the context that is not yet allocated.
       const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
-      const Address param_addr(EBP, (computed_param_pos * kWordSize));
+      const Address param_addr(EBP, computed_param_pos * kWordSize);
       __ movl(param_addr, EAX);
-      __ Bind(&next_parameter);
     }
     delete[] opt_param;
     delete[] opt_param_position;
@@ -783,13 +789,13 @@
     __ SmiUntag(ECX);
     for (int i = 0; i < num_opt_pos_params; i++) {
       Label next_parameter;
-      // Handle this optional positonal parameter only if k or fewer positional
+      // Handle this optional positional parameter only if k or fewer positional
       // arguments have been passed, where k is param_pos, the position of this
       // optional parameter in the formal parameter list.
       const int param_pos = num_fixed_params + i;
       __ cmpl(ECX, Immediate(param_pos));
       __ j(GREATER, &next_parameter, Assembler::kNearJump);
-      // Load RAX with default argument.
+      // Load EAX with default argument.
       const Object& value = Object::ZoneHandle(
           parsed_function().default_parameter_values().At(i));
       __ LoadObject(EAX, value);
@@ -798,7 +804,7 @@
       // scope->VariableAt(i)->index(), because captured variables still need
       // to be copied to the context that is not yet allocated.
       const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
-      const Address param_addr(EBP, (computed_param_pos * kWordSize));
+      const Address param_addr(EBP, computed_param_pos * kWordSize);
       __ movl(param_addr, EAX);
       __ Bind(&next_parameter);
     }
@@ -857,7 +863,8 @@
   __ SmiUntag(ECX);
   Label null_args_loop, null_args_loop_condition;
   __ jmp(&null_args_loop_condition, Assembler::kNearJump);
-  const Address original_argument_addr(EBP, ECX, TIMES_4, 2 * kWordSize);
+  const Address original_argument_addr(
+      EBP, ECX, TIMES_4, kLastParamSlotIndex * kWordSize);
   __ Bind(&null_args_loop);
   __ movl(original_argument_addr, raw_null);
   __ Bind(&null_args_loop_condition);
@@ -943,15 +950,6 @@
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
 
-  // For optimized code, keep a bitmap of the frame in order to build
-  // stackmaps for GC safepoints in the prologue.
-  LocationSummary* prologue_locs = NULL;
-  if (is_optimizing()) {
-    // Spill slots are allocated but not initialized.
-    prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall);
-    prologue_locs->stack_bitmap()->SetLength(StackSize());
-  }
-
   // We check the number of passed arguments when we have to copy them due to
   // the presence of optional parameters.
   // No such checking code is generated if only fixed parameters are declared,
@@ -1332,22 +1330,23 @@
 }
 
 
+// This function must be in sync with FlowGraphCompiler::RecordSafepoint.
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
   // TODO(vegorov): consider saving only caller save (volatile) registers.
   const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count();
   if (xmm_regs_count > 0) {
-    __ subl(ESP, Immediate(xmm_regs_count * kDoubleSize));
+    __ subl(ESP, Immediate(xmm_regs_count * kFpuRegisterSize));
     // Store XMM registers with the lowest register number at the lowest
     // address.
     intptr_t offset = 0;
     for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
       XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
       if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) {
-        __ movsd(Address(ESP, offset), xmm_reg);
-        offset += kDoubleSize;
+        __ movups(Address(ESP, offset), xmm_reg);
+        offset += kFpuRegisterSize;
       }
     }
-    ASSERT(offset == (xmm_regs_count * kDoubleSize));
+    ASSERT(offset == (xmm_regs_count * kFpuRegisterSize));
   }
 
   // Store general purpose registers with the highest register number at the
@@ -1378,11 +1377,11 @@
     for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
       XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
       if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) {
-        __ movsd(xmm_reg, Address(ESP, offset));
-        offset += kDoubleSize;
+        __ movups(xmm_reg, Address(ESP, offset));
+        offset += kFpuRegisterSize;
       }
     }
-    ASSERT(offset == (xmm_regs_count * kDoubleSize));
+    ASSERT(offset == (xmm_regs_count * kFpuRegisterSize));
     __ addl(ESP, Immediate(offset));
   }
 }
@@ -1390,8 +1389,8 @@
 
 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
                                         Register class_id_reg,
-                                        intptr_t arg_count,
-                                        const Array& arg_names,
+                                        intptr_t argument_count,
+                                        const Array& argument_names,
                                         Label* deopt,
                                         intptr_t deopt_id,
                                         intptr_t token_index,
@@ -1401,6 +1400,12 @@
   const intptr_t len = ic_data.NumberOfChecks();
   GrowableArray<CidTarget> sorted(len);
   SortICDataByCount(ic_data, &sorted);
+  ASSERT(class_id_reg != EDX);
+  ASSERT(len > 0);  // Why bother otherwise.
+  const Array& arguments_descriptor =
+      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
+                                                 argument_names));
+  __ LoadObject(EDX, arguments_descriptor);
   for (intptr_t i = 0; i < len; i++) {
     const bool is_last_check = (i == (len - 1));
     Label next_test;
@@ -1410,12 +1415,16 @@
     } else {
       assembler()->j(NOT_EQUAL, &next_test);
     }
-    GenerateStaticCall(deopt_id,
-                       token_index,
-                       *sorted[i].target,
-                       arg_count,
-                       arg_names,
-                       locs);
+    // Do not use the code from the function, but let the code be patched so
+    // that we can record the outgoing edges to other code.
+    GenerateDartCall(deopt_id,
+                     token_index,
+                     &StubCode::CallStaticFunctionLabel(),
+                     PcDescriptors::kFuncCall,
+                     locs);
+    const Function& function = *sorted[i].target;
+    AddStaticCallTarget(function);
+    __ Drop(argument_count);
     if (!is_last_check) {
       assembler()->jmp(&match_found);
     }
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 30c751c..d67ef15 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -626,6 +626,11 @@
       AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
                            assert->deopt_id(),
                            assert->token_pos());
+    } else if (instr->IsGuardField()) {
+      GuardFieldInstr* guard = instr->AsGuardField();
+      AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
+                           guard->deopt_id(),
+                           Scanner::kDummyTokenIndex);
     }
     AllocateRegistersLocally(instr);
   }
@@ -729,13 +734,15 @@
     __ movq(RCX,
             FieldAddress(R10, ArgumentsDescriptor::positional_count_offset()));
     __ SmiUntag(RCX);
-    // Let RBX point to the first passed argument, i.e. to fp[1 + argc - 0].
-    __ leaq(RBX, Address(RBP, RBX, TIMES_4, kWordSize));  // RBX is Smi.
+    // Let RBX point to the first passed argument, i.e. to
+    // fp[kLastParamSlotIndex + num_args - 1]; num_args (RBX) is Smi.
+    __ leaq(RBX,
+            Address(RBP, RBX, TIMES_4, (kLastParamSlotIndex - 1) * kWordSize));
     // Let RDI point to the entry of the first named argument.
     __ leaq(RDI,
             FieldAddress(R10, ArgumentsDescriptor::first_named_entry_offset()));
     for (int i = 0; i < num_opt_named_params; i++) {
-      Label load_default_value, assign_optional_parameter, next_parameter;
+      Label load_default_value, assign_optional_parameter;
       const int param_pos = opt_param_position[i];
       // Check if this named parameter was passed in.
       // Load RAX with the name of the argument.
@@ -744,7 +751,7 @@
       __ CompareObject(RAX, opt_param[i]->name());
       __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
       // Load RAX with passed-in argument at provided arg_pos, i.e. at
-      // fp[1 + argc - arg_pos].
+      // fp[kLastParamSlotIndex + num_args - 1 - arg_pos].
       __ movq(RAX, Address(RDI, ArgumentsDescriptor::position_offset()));
       // RAX is arg_pos as Smi.
       // Point to next named entry.
@@ -765,9 +772,8 @@
       // scope->VariableAt(i)->index(), because captured variables still need
       // to be copied to the context that is not yet allocated.
       const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
-      const Address param_addr(RBP, (computed_param_pos * kWordSize));
+      const Address param_addr(RBP, computed_param_pos * kWordSize);
       __ movq(param_addr, RAX);
-      __ Bind(&next_parameter);
     }
     delete[] opt_param;
     delete[] opt_param_position;
@@ -781,7 +787,7 @@
     __ SmiUntag(RCX);
     for (int i = 0; i < num_opt_pos_params; i++) {
       Label next_parameter;
-      // Handle this optional positonal parameter only if k or fewer positional
+      // Handle this optional positional parameter only if k or fewer positional
       // arguments have been passed, where k is param_pos, the position of this
       // optional parameter in the formal parameter list.
       const int param_pos = num_fixed_params + i;
@@ -796,7 +802,7 @@
       // scope->VariableAt(i)->index(), because captured variables still need
       // to be copied to the context that is not yet allocated.
       const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
-      const Address param_addr(RBP, (computed_param_pos * kWordSize));
+      const Address param_addr(RBP, computed_param_pos * kWordSize);
       __ movq(param_addr, RAX);
       __ Bind(&next_parameter);
     }
@@ -855,7 +861,8 @@
   __ SmiUntag(RCX);
   Label null_args_loop, null_args_loop_condition;
   __ jmp(&null_args_loop_condition, Assembler::kNearJump);
-  const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize);
+  const Address original_argument_addr(
+      RBP, RCX, TIMES_8, kLastParamSlotIndex * kWordSize);
   __ Bind(&null_args_loop);
   __ movq(original_argument_addr, raw_null);
   __ Bind(&null_args_loop_condition);
@@ -942,15 +949,6 @@
   const int num_copied_params = parsed_function().num_copied_params();
   const int num_locals = parsed_function().num_stack_locals();
 
-  // For optimized code, keep a bitmap of the frame in order to build
-  // stackmaps for GC safepoints in the prologue.
-  LocationSummary* prologue_locs = NULL;
-  if (is_optimizing()) {
-    // Spill slots are allocated but not initialized.
-    prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall);
-    prologue_locs->stack_bitmap()->SetLength(StackSize());
-  }
-
   // We check the number of passed arguments when we have to copy them due to
   // the presence of optional parameters.
   // No such checking code is generated if only fixed parameters are declared,
@@ -1332,22 +1330,23 @@
 }
 
 
+// This function must be in sync with FlowGraphCompiler::RecordSafepoint.
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
   // TODO(vegorov): consider saving only caller save (volatile) registers.
   const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count();
   if (xmm_regs_count > 0) {
-    __ subq(RSP, Immediate(xmm_regs_count * kDoubleSize));
+    __ subq(RSP, Immediate(xmm_regs_count * kFpuRegisterSize));
     // Store XMM registers with the lowest register number at the lowest
     // address.
     intptr_t offset = 0;
     for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
       XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
       if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) {
-        __ movsd(Address(RSP, offset), xmm_reg);
-        offset += kDoubleSize;
+        __ movups(Address(RSP, offset), xmm_reg);
+        offset += kFpuRegisterSize;
       }
     }
-    ASSERT(offset == (xmm_regs_count * kDoubleSize));
+    ASSERT(offset == (xmm_regs_count * kFpuRegisterSize));
   }
 
   // Store general purpose registers with the highest register number at the
@@ -1378,11 +1377,11 @@
     for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
       XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
       if (locs->live_registers()->ContainsFpuRegister(xmm_reg)) {
-        __ movsd(xmm_reg, Address(RSP, offset));
-        offset += kDoubleSize;
+        __ movups(xmm_reg, Address(RSP, offset));
+        offset += kFpuRegisterSize;
       }
     }
-    ASSERT(offset == (xmm_regs_count * kDoubleSize));
+    ASSERT(offset == (xmm_regs_count * kFpuRegisterSize));
     __ addq(RSP, Immediate(offset));
   }
 }
@@ -1390,8 +1389,8 @@
 
 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
                                         Register class_id_reg,
-                                        intptr_t arg_count,
-                                        const Array& arg_names,
+                                        intptr_t argument_count,
+                                        const Array& argument_names,
                                         Label* deopt,
                                         intptr_t deopt_id,
                                         intptr_t token_index,
@@ -1401,6 +1400,12 @@
   const intptr_t len = ic_data.NumberOfChecks();
   GrowableArray<CidTarget> sorted(len);
   SortICDataByCount(ic_data, &sorted);
+  ASSERT(class_id_reg != R10);
+  ASSERT(len > 0);  // Why bother otherwise.
+  const Array& arguments_descriptor =
+      Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
+                                                 argument_names));
+  __ LoadObject(R10, arguments_descriptor);
   for (intptr_t i = 0; i < len; i++) {
     const bool is_last_check = (i == (len - 1));
     Label next_test;
@@ -1410,12 +1415,16 @@
     } else {
       assembler()->j(NOT_EQUAL, &next_test);
     }
-    GenerateStaticCall(deopt_id,
-                       token_index,
-                       *sorted[i].target,
-                       arg_count,
-                       arg_names,
-                       locs);
+    // Do not use the code from the function, but let the code be patched so
+    // that we can record the outgoing edges to other code.
+    GenerateDartCall(deopt_id,
+                     token_index,
+                     &StubCode::CallStaticFunctionLabel(),
+                     PcDescriptors::kFuncCall,
+                     locs);
+    const Function& function = *sorted[i].target;
+    AddStaticCallTarget(function);
+    __ Drop(argument_count);
     if (!is_last_check) {
       assembler()->jmp(&match_found);
     }
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 5de4224..91552ab 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -37,6 +37,8 @@
 DEFINE_FLAG(int, inlining_hotness, 10,
     "Inline only hotter calls, in percents (0 .. 100); "
     "default 10%: calls above-equal 10% of max-count are inlined.");
+DEFINE_FLAG(bool, inline_recursive, true,
+    "Inline recursive calls.");
 
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -393,7 +395,7 @@
     }
 
     // Abort if this is a recursive occurrence.
-    if (IsCallRecursive(function, call)) {
+    if (!FLAG_inline_recursive && IsCallRecursive(function, call)) {
       function.set_is_inlinable(false);
       TRACE_INLINING(OS::Print("     Bailout: recursive function\n"));
       return false;
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 345f228..9e6ee4e 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -375,7 +375,7 @@
     Value* use = it.Current();
     const Representation to_rep =
         use->instruction()->RequiredInputRepresentation(use->use_index());
-    if (from_rep == to_rep) {
+    if (from_rep == to_rep || to_rep == kNoRepresentation) {
       continue;
     }
 
@@ -688,6 +688,13 @@
     *array = elements;
     return kArrayCid;
   }
+  if (RawObject::IsExternalTypedDataClassId(class_id)) {
+    LoadUntaggedInstr* elements =
+        new LoadUntaggedInstr(new Value(*array),
+                              ExternalTypedData::data_offset());
+    InsertBefore(call, elements, NULL, Definition::kValue);
+    *array = elements;
+  }
   return class_id;
 }
 
@@ -709,13 +716,6 @@
         value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
       }
       break;
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -730,8 +730,6 @@
         return false;
       }
       break;
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid: {
       if (!CanUnboxInt32()) return false;
@@ -750,8 +748,6 @@
       }
       break;
     }
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid:
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid: {
       // Check that value is always double.
@@ -772,58 +768,6 @@
 }
 
 
-bool FlowGraphOptimizer::TryInlineByteArraySetIndexed(InstanceCallInstr* call) {
-  const intptr_t class_id = ReceiverClassId(call);
-  ICData& value_check = ICData::ZoneHandle();
-  switch (class_id) {
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid: {
-      // Check that value is always smi.
-      value_check = ICData::New(Function::Handle(),
-                                String::Handle(),
-                                Isolate::kNoDeoptId,
-                                1);
-      value_check.AddReceiverCheck(kSmiCid, Function::Handle());
-      break;
-    }
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
-      if (!CanUnboxInt32()) return false;
-
-      // We don't have ICData for the value stored, so we optimistically assume
-      // smis first. If we ever deoptimized here, we require to unbox the value
-      // before storing to handle the mint case, too.
-      if (call->ic_data()->deopt_reason() == kDeoptUnknown) {
-        value_check = ICData::New(Function::Handle(),
-                                  String::Handle(),
-                                  Isolate::kNoDeoptId,
-                                  1);
-        value_check.AddReceiverCheck(kSmiCid, Function::Handle());
-      }
-      break;
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid: {
-      // Check that value is always double.
-      value_check = ICData::New(Function::Handle(),
-                                String::Handle(),
-                                Isolate::kNoDeoptId,
-                                1);
-      value_check.AddReceiverCheck(kDoubleCid, Function::Handle());
-      break;
-    }
-    default:
-      return false;
-  }
-  BuildStoreIndexed(call, value_check, class_id);
-  return true;
-}
-
-
 void FlowGraphOptimizer::BuildStoreIndexed(InstanceCallInstr* call,
                                            const ICData& value_check,
                                            intptr_t class_id) {
@@ -855,15 +799,6 @@
         type_args = load_type_args;
         break;
       }
-      case kInt8ArrayCid:
-      case kUint8ArrayCid:
-      case kUint8ClampedArrayCid:
-      case kExternalUint8ArrayCid:
-      case kExternalUint8ClampedArrayCid:
-      case kInt16ArrayCid:
-      case kUint16ArrayCid:
-      case kInt32ArrayCid:
-      case kUint32ArrayCid:
       case kTypedDataInt8ArrayCid:
       case kTypedDataUint8ArrayCid:
       case kTypedDataUint8ClampedArrayCid:
@@ -875,8 +810,6 @@
       case kTypedDataUint32ArrayCid:
         ASSERT(value_type.IsIntType());
         // Fall through.
-      case kFloat32ArrayCid:
-      case kFloat64ArrayCid:
       case kTypedDataFloat32ArrayCid:
       case kTypedDataFloat64ArrayCid: {
         type_args = instantiator = flow_graph_->constant_null();
@@ -941,15 +874,6 @@
     case kArrayCid:
     case kImmutableArrayCid:
     case kGrowableObjectArrayCid:
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid:
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
     case kTypedDataInt8ArrayCid:
@@ -960,8 +884,6 @@
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid:
       break;
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid: {
         if (!CanUnboxInt32()) return false;
@@ -1269,6 +1191,14 @@
       field.Offset(),
       AbstractType::ZoneHandle(field.type()),
       field.is_final());
+  if (field.guarded_cid() != kIllegalCid) {
+    if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) {
+      load->set_result_cid(field.guarded_cid());
+    }
+    load->set_field(&Field::ZoneHandle(field.raw()));
+  }
+  load->set_field_name(String::Handle(field.name()).ToCString());
+
   // Discard the environment from the original instruction because the load
   // can't deoptimize.
   call->RemoveEnvironment();
@@ -1361,8 +1291,6 @@
     case MethodRecognizer::kObjectArrayLength:
     case MethodRecognizer::kImmutableArrayLength:
       return Array::length_offset();
-    case MethodRecognizer::kByteArrayBaseLength:
-      return ByteArray::length_offset();
     case MethodRecognizer::kTypedDataLength:
       // .length is defined in _TypedList which is the base class for internal
       // and external typed data.
@@ -1405,7 +1333,6 @@
   switch (recognized_kind) {
     case MethodRecognizer::kObjectArrayLength:
     case MethodRecognizer::kImmutableArrayLength:
-    case MethodRecognizer::kByteArrayBaseLength:
     case MethodRecognizer::kTypedDataLength:
     case MethodRecognizer::kGrowableArrayLength: {
       if (!ic_data.HasOneTarget()) {
@@ -1415,7 +1342,6 @@
       const bool is_immutable =
           (recognized_kind == MethodRecognizer::kObjectArrayLength) ||
           (recognized_kind == MethodRecognizer::kImmutableArrayLength) ||
-          (recognized_kind == MethodRecognizer::kByteArrayBaseLength) ||
           (recognized_kind == MethodRecognizer::kTypedDataLength);
       InlineArrayLengthGetter(call,
                               OffsetForLengthGetter(recognized_kind),
@@ -1504,15 +1430,17 @@
 
 static bool IsSupportedByteArrayViewCid(intptr_t cid) {
   switch (cid) {
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid:
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
       return true;
     default:
       return false;
@@ -1535,38 +1463,6 @@
   MethodRecognizer::Kind recognized_kind =
       MethodRecognizer::RecognizeKind(target);
 
-  // Byte array access.
-  switch (recognized_kind) {
-    case MethodRecognizer::kFloat32ArrayGetIndexed:
-    case MethodRecognizer::kFloat64ArrayGetIndexed:
-    case MethodRecognizer::kInt8ArrayGetIndexed:
-    case MethodRecognizer::kUint8ArrayGetIndexed:
-    case MethodRecognizer::kUint8ClampedArrayGetIndexed:
-    case MethodRecognizer::kExternalUint8ArrayGetIndexed:
-    case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
-    case MethodRecognizer::kInt16ArrayGetIndexed:
-    case MethodRecognizer::kUint16ArrayGetIndexed:
-    case MethodRecognizer::kInt32ArrayGetIndexed:
-    case MethodRecognizer::kUint32ArrayGetIndexed:
-      return TryReplaceWithLoadIndexed(call);
-
-    case MethodRecognizer::kFloat32ArraySetIndexed:
-    case MethodRecognizer::kFloat64ArraySetIndexed:
-    case MethodRecognizer::kInt8ArraySetIndexed:
-    case MethodRecognizer::kUint8ArraySetIndexed:
-    case MethodRecognizer::kUint8ClampedArraySetIndexed:
-    case MethodRecognizer::kExternalUint8ArraySetIndexed:
-    case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
-    case MethodRecognizer::kInt16ArraySetIndexed:
-    case MethodRecognizer::kUint16ArraySetIndexed:
-    case MethodRecognizer::kInt32ArraySetIndexed:
-    case MethodRecognizer::kUint32ArraySetIndexed:
-      return TryInlineByteArraySetIndexed(call);
-
-    default:
-      break;
-  }
-
   if ((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) &&
       (ic_data.NumberOfChecks() == 1) &&
       ((class_ids[0] == kOneByteStringCid) ||
@@ -1655,39 +1551,55 @@
     switch (recognized_kind) {
       // ByteArray getters.
       case MethodRecognizer::kByteArrayBaseGetInt8:
-        return BuildByteArrayViewLoad(call, class_ids[0], kInt8ArrayCid);
+        return BuildByteArrayViewLoad(
+            call, class_ids[0], kTypedDataInt8ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetUint8:
-        return BuildByteArrayViewLoad(call, class_ids[0], kUint8ArrayCid);
+        return BuildByteArrayViewLoad(
+            call, class_ids[0], kTypedDataUint8ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetInt16:
-        return BuildByteArrayViewLoad(call, class_ids[0], kInt16ArrayCid);
+        return BuildByteArrayViewLoad(
+            call, class_ids[0], kTypedDataInt16ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetUint16:
-        return BuildByteArrayViewLoad(call, class_ids[0], kUint16ArrayCid);
+        return BuildByteArrayViewLoad(
+            call, class_ids[0], kTypedDataUint16ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetInt32:
-        return BuildByteArrayViewLoad(call, class_ids[0], kInt32ArrayCid);
+        return BuildByteArrayViewLoad(
+            call, class_ids[0], kTypedDataInt32ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetUint32:
-        return BuildByteArrayViewLoad(call, class_ids[0], kUint32ArrayCid);
+        return BuildByteArrayViewLoad(
+            call, class_ids[0], kTypedDataUint32ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetFloat32:
-        return BuildByteArrayViewLoad(call, class_ids[0], kFloat32ArrayCid);
+        return BuildByteArrayViewLoad(
+            call, class_ids[0], kTypedDataFloat32ArrayCid);
       case MethodRecognizer::kByteArrayBaseGetFloat64:
-        return BuildByteArrayViewLoad(call, class_ids[0], kFloat64ArrayCid);
+        return BuildByteArrayViewLoad(
+            call, class_ids[0], kTypedDataFloat64ArrayCid);
 
       // ByteArray setters.
       case MethodRecognizer::kByteArrayBaseSetInt8:
-        return BuildByteArrayViewStore(call, class_ids[0], kInt8ArrayCid);
+        return BuildByteArrayViewStore(
+            call, class_ids[0], kTypedDataInt8ArrayCid);
       case MethodRecognizer::kByteArrayBaseSetUint8:
-        return BuildByteArrayViewStore(call, class_ids[0], kUint8ArrayCid);
+        return BuildByteArrayViewStore(
+            call, class_ids[0], kTypedDataUint8ArrayCid);
       case MethodRecognizer::kByteArrayBaseSetInt16:
-        return BuildByteArrayViewStore(call, class_ids[0], kInt16ArrayCid);
+        return BuildByteArrayViewStore(
+            call, class_ids[0], kTypedDataInt16ArrayCid);
       case MethodRecognizer::kByteArrayBaseSetUint16:
-        return BuildByteArrayViewStore(call, class_ids[0], kUint16ArrayCid);
+        return BuildByteArrayViewStore(
+            call, class_ids[0], kTypedDataUint16ArrayCid);
       case MethodRecognizer::kByteArrayBaseSetInt32:
-        return BuildByteArrayViewStore(call, class_ids[0], kInt32ArrayCid);
+        return BuildByteArrayViewStore(
+            call, class_ids[0], kTypedDataInt32ArrayCid);
       case MethodRecognizer::kByteArrayBaseSetUint32:
-        return BuildByteArrayViewStore(call, class_ids[0], kUint32ArrayCid);
+        return BuildByteArrayViewStore(
+            call, class_ids[0], kTypedDataUint32ArrayCid);
       case MethodRecognizer::kByteArrayBaseSetFloat32:
-        return BuildByteArrayViewStore(call, class_ids[0], kFloat32ArrayCid);
+        return BuildByteArrayViewStore(
+            call, class_ids[0], kTypedDataFloat32ArrayCid);
       case MethodRecognizer::kByteArrayBaseSetFloat64:
-        return BuildByteArrayViewStore(call, class_ids[0], kFloat64ArrayCid);
+        return BuildByteArrayViewStore(
+            call, class_ids[0], kTypedDataFloat64ArrayCid);
       default:
         // Unsupported method.
         return false;
@@ -1701,10 +1613,8 @@
     InstanceCallInstr* call,
     intptr_t receiver_cid,
     intptr_t view_cid) {
-  PrepareByteArrayViewOp(call, receiver_cid, view_cid);
-
   Definition* array = call->ArgumentAt(0);
-  Definition* byte_index = call->ArgumentAt(1);
+  PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
 
   // Optimistically build a smi-checked load for Int32 and Uint32
   // loads on ia32 like we do for normal array loads, and only revert to
@@ -1714,6 +1624,7 @@
       call->ic_data()->deopt_reason() == kDeoptUnknown) {
     deopt_id = call->deopt_id();
   }
+  Definition* byte_index = call->ArgumentAt(1);
   LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array),
                                                     new Value(byte_index),
                                                     1,  // Index scale.
@@ -1728,16 +1639,17 @@
     InstanceCallInstr* call,
     intptr_t receiver_cid,
     intptr_t view_cid) {
-  PrepareByteArrayViewOp(call, receiver_cid, view_cid);
+  Definition* array = call->ArgumentAt(0);
+  PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
   ICData& value_check = ICData::ZoneHandle();
   switch (view_cid) {
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid: {
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid: {
       // Check that value is always smi.
       value_check = ICData::New(Function::Handle(),
                                 String::Handle(),
@@ -1746,8 +1658,8 @@
       value_check.AddReceiverCheck(kSmiCid, Function::Handle());
       break;
     }
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid:
       // We don't have ICData for the value stored, so we optimistically assume
       // smis first. If we ever deoptimized here, we require to unbox the value
       // before storing to handle the mint case, too.
@@ -1759,8 +1671,8 @@
         value_check.AddReceiverCheck(kSmiCid, Function::Handle());
       }
       break;
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid: {
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid: {
       // Check that value is always double.
       value_check = ICData::New(Function::Handle(),
                                 String::Handle(),
@@ -1775,7 +1687,6 @@
       return NULL;
   }
 
-  Definition* array = call->ArgumentAt(0);
   Definition* index = call->ArgumentAt(1);
   Definition* stored_value = call->ArgumentAt(2);
   if (!value_check.IsNull()) {
@@ -1783,20 +1694,6 @@
                   call);
   }
   StoreBarrierType needs_store_barrier = kNoStoreBarrier;
-
-
-  // result = index + bytesPerElement.
-  intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid);
-  ConstantInstr* bytes_per_element =
-      new ConstantInstr(Smi::Handle(Smi::New(element_size)));
-  InsertBefore(call, bytes_per_element, NULL, Definition::kValue);
-  BinarySmiOpInstr* result =
-      new BinarySmiOpInstr(Token::kADD,
-                           call,
-                           new Value(index),
-                           new Value(bytes_per_element));
-  InsertBefore(call, result, call->env(), Definition::kValue);
-
   StoreIndexedInstr* array_op = new StoreIndexedInstr(new Value(array),
                                                       new Value(index),
                                                       new Value(stored_value),
@@ -1804,9 +1701,7 @@
                                                       1,  // Index scale
                                                       view_cid,
                                                       call->deopt_id());
-  call->ReplaceUsesWith(result);  // Fix uses of the call's return value.
   ReplaceCall(call, array_op);
-  array_op->ClearSSATempIndex();  // Store has no uses.
   return true;
 }
 
@@ -1814,14 +1709,14 @@
 void FlowGraphOptimizer::PrepareByteArrayViewOp(
     InstanceCallInstr* call,
     intptr_t receiver_cid,
-    intptr_t view_cid) {
-  Definition* array = call->ArgumentAt(0);
+    intptr_t view_cid,
+    Definition** array) {
   Definition* byte_index = call->ArgumentAt(1);
 
   AddReceiverCheck(call);
   const bool is_immutable = true;
   LoadFieldInstr* length = new LoadFieldInstr(
-      new Value(array),
+      new Value(*array),
       CheckArrayBoundInstr::LengthOffsetFor(receiver_cid),
       Type::ZoneHandle(Type::SmiType()),
       is_immutable);
@@ -1850,6 +1745,15 @@
                                         call),
                call->env(),
                Definition::kEffect);
+
+  // Insert load of elements for external typed arrays.
+  if (RawObject::IsExternalTypedDataClassId(receiver_cid)) {
+    LoadUntaggedInstr* elements =
+        new LoadUntaggedInstr(new Value(*array),
+                              ExternalTypedData::data_offset());
+    InsertBefore(call, elements, NULL, Definition::kValue);
+    *array = elements;
+  }
 }
 
 
@@ -2056,6 +1960,17 @@
                  Definition::kEffect);
     needs_store_barrier = kNoStoreBarrier;
   }
+
+  if (field.guarded_cid() != kDynamicCid) {
+    InsertBefore(instr,
+                 new GuardFieldInstr(new Value(instr->ArgumentAt(1)),
+                                     field,
+                                     instr->deopt_id()),
+                 instr->env(),
+                 Definition::kEffect);
+  }
+
+  // Field guard was detached.
   StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
       field,
       new Value(instr->ArgumentAt(0)),
@@ -3824,6 +3739,7 @@
 
 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { }
 
+void ConstantPropagator::VisitGuardField(GuardFieldInstr* instr) { }
 
 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { }
 
@@ -4090,6 +4006,11 @@
 }
 
 
+void ConstantPropagator::VisitLoadUntagged(LoadUntaggedInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
+
 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) {
   if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) &&
       (instr->value()->definition()->IsCreateArray())) {
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index fa6fab8..a0cad62 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -39,8 +39,6 @@
 
   void SelectRepresentations();
 
-  void PropagateSminess();
-
   void InferSmiRanges();
 
   virtual void VisitStaticCall(StaticCallInstr* instr);
@@ -68,7 +66,6 @@
                             Definition** array,
                             Definition** index);
   bool TryReplaceWithStoreIndexed(InstanceCallInstr* call);
-  bool TryInlineByteArraySetIndexed(InstanceCallInstr* call);
   void BuildStoreIndexed(InstanceCallInstr* call,
                          const ICData& value_check,
                          intptr_t class_id);
@@ -95,7 +92,8 @@
                                intptr_t view_cid);
   void PrepareByteArrayViewOp(InstanceCallInstr* call,
                               intptr_t receiver_cid,
-                              intptr_t view_cid);
+                              intptr_t view_cid,
+                              Definition** array);
 
   // Insert a check of 'to_check' determined by 'unary_checks'.  If the
   // check fails it will deoptimize to 'deopt_id' using the deoptimization
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 09d6171..2e2fcd5 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -20,6 +20,7 @@
 FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph)
     : FlowGraphVisitor(flow_graph->reverse_postorder()),
       flow_graph_(flow_graph),
+      visited_blocks_(new BitVector(flow_graph->reverse_postorder().length())),
       types_(flow_graph->current_ssa_temp_index()),
       in_worklist_(new BitVector(flow_graph->current_ssa_temp_index())),
       asserts_(NULL),
@@ -74,10 +75,22 @@
       for (Value::Iterator it(def->input_use_list());
            !it.Done();
            it.Advance()) {
-        Definition* use_defn = it.Current()->instruction()->AsDefinition();
+        Instruction* instr = it.Current()->instruction();
+
+        Definition* use_defn = instr->AsDefinition();
         if (use_defn != NULL) {
           AddToWorklist(use_defn);
         }
+
+        // If the value flow into a branch recompute type constrained by the
+        // branch (if any). This ensures that correct non-nullable type will
+        // flow downwards from the branch on the comparison with the null
+        // constant.
+        BranchInstr* branch = instr->AsBranch();
+        if (branch != NULL) {
+          ConstrainedCompileType* constrained_type = branch->constrained_type();
+          if (constrained_type != NULL) constrained_type->Update();
+        }
       }
     }
   }
@@ -89,6 +102,11 @@
 
 
 void FlowGraphTypePropagator::PropagateRecursive(BlockEntryInstr* block) {
+  if (visited_blocks_->Contains(block->postorder_number())) {
+    return;
+  }
+  visited_blocks_->Add(block->postorder_number());
+
   const intptr_t rollback_point = rollback_.length();
 
   if (FLAG_enable_type_checks) {
@@ -119,10 +137,50 @@
     }
   }
 
+  HandleBranchOnNull(block);
+
   for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
     PropagateRecursive(block->dominated_blocks()[i]);
   }
 
+  RollbackTo(rollback_point);
+}
+
+
+void FlowGraphTypePropagator::HandleBranchOnNull(BlockEntryInstr* block) {
+  BranchInstr* branch = block->last_instruction()->AsBranch();
+  if (branch == NULL) {
+    return;
+  }
+
+  StrictCompareInstr* compare = branch->comparison()->AsStrictCompare();
+  if ((compare == NULL) || !compare->right()->BindsToConstantNull()) {
+    return;
+  }
+
+  const intptr_t rollback_point = rollback_.length();
+
+  Definition* defn = compare->left()->definition();
+
+  if (compare->kind() == Token::kEQ_STRICT) {
+    branch->set_constrained_type(MarkNonNullable(defn));
+    PropagateRecursive(branch->false_successor());
+
+    SetCid(defn, kNullCid);
+    PropagateRecursive(branch->true_successor());
+  } else if (compare->kind() == Token::kNE_STRICT) {
+    branch->set_constrained_type(MarkNonNullable(defn));
+    PropagateRecursive(branch->true_successor());
+
+    SetCid(defn, kNullCid);
+    PropagateRecursive(branch->false_successor());
+  }
+
+  RollbackTo(rollback_point);
+}
+
+
+void FlowGraphTypePropagator::RollbackTo(intptr_t rollback_point) {
   for (intptr_t i = rollback_.length() - 1; i >= rollback_point; i--) {
     types_[rollback_[i].index()] = rollback_[i].type();
   }
@@ -151,9 +209,22 @@
 
 void FlowGraphTypePropagator::SetCid(Definition* def, intptr_t cid) {
   CompileType* current = TypeOf(def);
-  if (current->ToCid() == cid) return;
+  if (current->IsNone() || (current->ToCid() != cid)) {
+    SetTypeOf(def, ZoneCompileType::Wrap(CompileType::FromCid(cid)));
+  }
+}
 
-  SetTypeOf(def, ZoneCompileType::Wrap(CompileType::FromCid(cid)));
+
+ConstrainedCompileType* FlowGraphTypePropagator::MarkNonNullable(
+    Definition* def) {
+  CompileType* current = TypeOf(def);
+  if (current->is_nullable()) {
+    ConstrainedCompileType* constrained_type =
+        new NotNullConstrainedCompileType(current);
+    SetTypeOf(def, constrained_type->ToCompileType());
+    return constrained_type;
+  }
+  return NULL;
 }
 
 
@@ -196,6 +267,24 @@
 }
 
 
+void FlowGraphTypePropagator::VisitGuardField(GuardFieldInstr* guard) {
+  const intptr_t cid = guard->field().guarded_cid();
+  if ((cid == kIllegalCid) || (cid == kDynamicCid)) {
+    return;
+  }
+
+  Definition* def = guard->value()->definition();
+  CompileType* current = TypeOf(def);
+  if (current->IsNone() ||
+      (current->ToCid() != cid) ||
+      (current->is_nullable() && !guard->field().is_nullable())) {
+    const bool is_nullable =
+        guard->field().is_nullable() && current->is_nullable();
+    SetTypeOf(def, ZoneCompileType::Wrap(CompileType(is_nullable, cid, NULL)));
+  }
+}
+
+
 void FlowGraphTypePropagator::AddToWorklist(Definition* defn) {
   if (defn->ssa_temp_index() == -1) {
     return;
@@ -774,6 +863,11 @@
 }
 
 
+CompileType LoadUntaggedInstr::ComputeType() const {
+  return CompileType::Dynamic();
+}
+
+
 CompileType LoadFieldInstr::ComputeType() const {
   // Type may be null if the field is a VM field, e.g. context parent.
   // Keep it as null for debug purposes and do not return dynamic in production
@@ -786,6 +880,11 @@
     return CompileType::FromAbstractType(type());
   }
 
+  if (field_ != NULL) {
+    return CompileType::CreateNullable(field_->is_nullable(),
+                                       field_->guarded_cid());
+  }
+
   return CompileType::FromCid(result_cid_);
 }
 
diff --git a/runtime/vm/flow_graph_type_propagator.h b/runtime/vm/flow_graph_type_propagator.h
index f01dc5f..9b6e02d 100644
--- a/runtime/vm/flow_graph_type_propagator.h
+++ b/runtime/vm/flow_graph_type_propagator.h
@@ -18,12 +18,16 @@
 
  private:
   void PropagateRecursive(BlockEntryInstr* block);
+  void HandleBranchOnNull(BlockEntryInstr* block);
+
+  void RollbackTo(intptr_t rollback_point);
 
   void VisitValue(Value* value);
 
   virtual void VisitJoinEntry(JoinEntryInstr* instr);
   virtual void VisitCheckSmi(CheckSmiInstr* instr);
   virtual void VisitCheckClass(CheckClassInstr* instr);
+  virtual void VisitGuardField(GuardFieldInstr* instr);
 
   // Current reaching type of the definition. Valid only during dominator tree
   // traversal.
@@ -35,6 +39,8 @@
   // Mark definition as having given class id in all dominated instructions.
   void SetCid(Definition* value, intptr_t cid);
 
+  ConstrainedCompileType* MarkNonNullable(Definition* value);
+
   void AddToWorklist(Definition* defn);
   Definition* RemoveLastFromWorklist();
 
@@ -44,6 +50,8 @@
 
   FlowGraph* flow_graph_;
 
+  BitVector* visited_blocks_;
+
   // Mapping between SSA values and their current reaching types. Valid
   // only during dominator tree traversal.
   GrowableArray<CompileType*> types_;
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 74bc99b..cb6b005 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -172,7 +172,11 @@
 
 
 void Instruction::PrintTo(BufferFormatter* f) const {
-  f->Print("%s:%"Pd"(", DebugName(), GetDeoptId());
+  if (GetDeoptId() != Isolate::kNoDeoptId) {
+    f->Print("%s:%"Pd"(", DebugName(), GetDeoptId());
+  } else {
+    f->Print("%s(", DebugName());
+  }
   PrintOperandsTo(f);
   f->Print(")");
 }
@@ -191,7 +195,11 @@
   if (is_used()) {
     if (HasSSATemp() || (temp_index() != -1)) f->Print(" <- ");
   }
-  f->Print("%s:%"Pd"(", DebugName(), GetDeoptId());
+  if (GetDeoptId() != Isolate::kNoDeoptId) {
+    f->Print("%s:%"Pd"(", DebugName(), GetDeoptId());
+  } else {
+    f->Print("%s(", DebugName());
+  }
   PrintOperandsTo(f);
   f->Print(")");
   if (range_ != NULL) {
@@ -395,6 +403,22 @@
 }
 
 
+void GuardFieldInstr::PrintOperandsTo(BufferFormatter* f) const {
+  const char* expected = "?";
+  if (field().guarded_cid() != kIllegalCid) {
+    const Class& cls = Class::Handle(
+            Isolate::Current()->class_table()->At(field().guarded_cid()));
+    expected = String::Handle(cls.Name()).ToCString();
+  }
+
+  f->Print("%s [%s %s], ",
+           String::Handle(field().name()).ToCString(),
+           field().is_nullable() ? "nullable" : "non-nullable",
+           expected);
+  value()->PrintTo(f);
+}
+
+
 void StoreInstanceFieldInstr::PrintOperandsTo(BufferFormatter* f) const {
   f->Print("%s {%"Pd"}, ",
            String::Handle(field().name()).ToCString(),
@@ -481,7 +505,26 @@
 
 void LoadFieldInstr::PrintOperandsTo(BufferFormatter* f) const {
   value()->PrintTo(f);
-  f->Print(", %"Pd", immutable=%d", offset_in_bytes(), immutable_);
+  f->Print(", %"Pd, offset_in_bytes());
+
+  if (field_name_ != NULL) {
+    f->Print(" {%s}", field_name_);
+  }
+
+  if (field() != NULL) {
+    const char* expected = "?";
+    if (field()->guarded_cid() != kIllegalCid) {
+      const Class& cls = Class::Handle(
+            Isolate::Current()->class_table()->At(field()->guarded_cid()));
+      expected = String::Handle(cls.Name()).ToCString();
+    }
+
+    f->Print(" [%s %s]",
+             field()->is_nullable() ? "nullable" : "non-nullable",
+             expected);
+  }
+
+  f->Print(", immutable=%d", immutable_);
 }
 
 
@@ -573,6 +616,9 @@
 void CheckClassInstr::PrintOperandsTo(BufferFormatter* f) const {
   value()->PrintTo(f);
   PrintICData(f, unary_checks());
+  if (null_check()) {
+    f->Print(" nullcheck");
+  }
 }
 
 
@@ -676,7 +722,11 @@
     parallel_move()->PrintTo(f);
     f->Print(" ");
   }
-  f->Print("goto:%"Pd" %"Pd"", GetDeoptId(), successor()->block_id());
+  if (GetDeoptId() != Isolate::kNoDeoptId) {
+    f->Print("goto:%"Pd" %"Pd"", GetDeoptId(), successor()->block_id());
+  } else {
+    f->Print("goto: %"Pd"", successor()->block_id());
+  }
 }
 
 
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 9f87020..058b3ca 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -69,7 +69,8 @@
 CheckClassInstr::CheckClassInstr(Value* value,
                                  intptr_t deopt_id,
                                  const ICData& unary_checks)
-    : unary_checks_(unary_checks) {
+    : unary_checks_(unary_checks),
+      null_check_(false) {
   ASSERT(unary_checks.IsZoneHandle());
   // Expected useful check data.
   ASSERT(!unary_checks_.IsNull());
@@ -109,6 +110,16 @@
 }
 
 
+bool GuardFieldInstr::AttributesEqual(Instruction* other) const {
+  return field().raw() == other->AsGuardField()->field().raw();
+}
+
+
+bool GuardFieldInstr::AffectedBySideEffect() const {
+  return false;
+}
+
+
 bool CheckArrayBoundInstr::AttributesEqual(Instruction* other) const {
   CheckArrayBoundInstr* other_check = other->AsCheckArrayBound();
   ASSERT(other_check != NULL);
@@ -271,8 +282,7 @@
   // List of libraries where methods can be recognized.
   return (library.raw() == Library::CoreLibrary())
       || (library.raw() == Library::MathLibrary())
-      || (library.raw() == Library::TypedDataLibrary())
-      || (library.raw() == Library::ScalarlistLibrary());
+      || (library.raw() == Library::TypedDataLibrary());
 }
 
 
@@ -591,7 +601,9 @@
 
 
 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked)
-    : comparison_(comparison), is_checked_(is_checked) {
+    : comparison_(comparison),
+      is_checked_(is_checked),
+      constrained_type_(NULL) {
   for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
     comparison->InputAt(i)->set_instruction(this);
   }
@@ -1112,7 +1124,6 @@
   switch (recognized_kind()) {
     case MethodRecognizer::kObjectArrayLength:
     case MethodRecognizer::kImmutableArrayLength:
-    case MethodRecognizer::kByteArrayBaseLength:
     case MethodRecognizer::kTypedDataLength:
     case MethodRecognizer::kStringBaseLength:
       return true;
@@ -1135,20 +1146,6 @@
       return MethodRecognizer::kImmutableArrayLength;
     case kGrowableObjectArrayCid:
       return MethodRecognizer::kGrowableArrayLength;
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
-    case kInt64ArrayCid:
-    case kUint64ArrayCid:
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid:
-      return MethodRecognizer::kByteArrayBaseLength;
     default:
       UNREACHABLE();
       return MethodRecognizer::kUnknown;
@@ -1160,17 +1157,17 @@
   switch (cid) {
     case kArrayCid:
     case kImmutableArrayCid:
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
-    case kInt64ArrayCid:
-    case kUint64ArrayCid:
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid:
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid:
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
       return true;
     default:
       return false;
@@ -1314,6 +1311,25 @@
 }
 
 
+Instruction* GuardFieldInstr::Canonicalize(FlowGraphOptimizer* optimizer) {
+  if (field().guarded_cid() == kDynamicCid) {
+    return NULL;  // Nothing to guard.
+  }
+
+  if (field().is_nullable() && value()->Type()->IsNull()) {
+    return NULL;
+  }
+
+  const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid()
+                                             : value()->Type()->ToCid();
+  if (field().guarded_cid() == cid) {
+    return NULL;  // Value is guaranteed to have this cid.
+  }
+
+  return this;
+}
+
+
 Instruction* CheckSmiInstr::Canonicalize(FlowGraphOptimizer* optimizer) {
   return (value()->Type()->ToCid() == kSmiCid) ?  NULL : this;
 }
@@ -1930,8 +1946,7 @@
     return;
   }
   if ((range_ == NULL) &&
-      (recognized_kind() == MethodRecognizer::kByteArrayBaseLength ||
-       recognized_kind() == MethodRecognizer::kTypedDataLength)) {
+      (recognized_kind() == MethodRecognizer::kTypedDataLength)) {
     range_ = new Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
     return;
   }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index ea7ef86..d11cc84 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -38,47 +38,22 @@
   V(_ObjectArray, get:length, ObjectArrayLength, 405297088)                    \
   V(_ImmutableArray, get:length, ImmutableArrayLength, 433698233)              \
   V(_TypedList, get:length, TypedDataLength, 231908172)                        \
-  V(_ByteArrayBase, get:length, ByteArrayBaseLength, 1098081765)               \
-  V(_ByteArrayBase, _getInt8, ByteArrayBaseGetInt8, 261365835)                 \
-  V(_ByteArrayBase, _getUint8, ByteArrayBaseGetUint8, 261365835)               \
-  V(_ByteArrayBase, _getInt16, ByteArrayBaseGetInt16, 261365835)               \
-  V(_ByteArrayBase, _getUint16, ByteArrayBaseGetUint16, 261365835)             \
-  V(_ByteArrayBase, _getInt32, ByteArrayBaseGetInt32, 261365835)               \
-  V(_ByteArrayBase, _getUint32, ByteArrayBaseGetUint32, 261365835)             \
-  V(_ByteArrayBase, _getFloat32, ByteArrayBaseGetFloat32, 434247298)           \
-  V(_ByteArrayBase, _getFloat64, ByteArrayBaseGetFloat64, 434247298)           \
-  V(_ByteArrayBase, _setInt8, ByteArrayBaseSetInt8, 501962848)                 \
-  V(_ByteArrayBase, _setUint8, ByteArrayBaseSetUint8, 501962848)               \
-  V(_ByteArrayBase, _setInt16, ByteArrayBaseSetInt16, 501962848)               \
-  V(_ByteArrayBase, _setUint16, ByteArrayBaseSetUint16, 501962848)             \
-  V(_ByteArrayBase, _setInt32, ByteArrayBaseSetInt32, 501962848)               \
-  V(_ByteArrayBase, _setUint32, ByteArrayBaseSetUint32, 501962848)             \
-  V(_ByteArrayBase, _setFloat32, ByteArrayBaseSetFloat32, 864506525)           \
-  V(_ByteArrayBase, _setFloat64, ByteArrayBaseSetFloat64, 864506525)           \
-  V(_Float32Array, _getIndexed, Float32ArrayGetIndexed, 734006846)             \
-  V(_Float64Array, _getIndexed, Float64ArrayGetIndexed, 498074772)             \
-  V(_Int8Array, _getIndexed, Int8ArrayGetIndexed, 712069760)                   \
-  V(_Uint8Array, _getIndexed, Uint8ArrayGetIndexed, 535849990)                 \
-  V(_Uint8ClampedArray, _getIndexed, Uint8ClampedArrayGetIndexed, 873344956)   \
-  V(_ExternalUint8Array, _getIndexed, ExternalUint8ArrayGetIndexed, 402720239) \
-  V(_ExternalUint8ClampedArray, _getIndexed,                                   \
-    ExternalUint8ClampedArrayGetIndexed, 682839007)                            \
-  V(_Int16Array, _getIndexed, Int16ArrayGetIndexed, 313999108)                 \
-  V(_Uint16Array, _getIndexed, Uint16ArrayGetIndexed, 539701175)               \
-  V(_Int32Array, _getIndexed, Int32ArrayGetIndexed, 655321526)                 \
-  V(_Uint32Array, _getIndexed, Uint32ArrayGetIndexed, 1060443550)              \
-  V(_Float32Array, _setIndexed, Float32ArraySetIndexed, 1040992157)            \
-  V(_Float64Array, _setIndexed, Float64ArraySetIndexed, 330158324)             \
-  V(_Int8Array, _setIndexed, Int8ArraySetIndexed, 680713569)                   \
-  V(_Uint8Array, _setIndexed, Uint8ArraySetIndexed, 785627791)                 \
-  V(_Uint8ClampedArray, _setIndexed, Uint8ClampedArraySetIndexed, 464766374)   \
-  V(_ExternalUint8Array, _setIndexed, ExternalUint8ArraySetIndexed, 159706697) \
-  V(_ExternalUint8ClampedArray, _setIndexed,                                   \
-    ExternalUint8ClampedArraySetIndexed, 335716123)                            \
-  V(_Int16Array, _setIndexed, Int16ArraySetIndexed, 12169534)                  \
-  V(_Uint16Array, _setIndexed, Uint16ArraySetIndexed, 36054302)                \
-  V(_Int32Array, _setIndexed, Int32ArraySetIndexed, 306194131)                 \
-  V(_Uint32Array, _setIndexed, Uint32ArraySetIndexed, 410753485)               \
+  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 380843687)                     \
+  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 380843687)                   \
+  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 380843687)                   \
+  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 380843687)                 \
+  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 380843687)                   \
+  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 380843687)                 \
+  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 979971573)               \
+  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 979971573)               \
+  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 287047804)                     \
+  V(_TypedList, _setUint8, ByteArrayBaseSetUint8, 287047804)                   \
+  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 287047804)                   \
+  V(_TypedList, _setUint16, ByteArrayBaseSetUint16, 287047804)                 \
+  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 287047804)                   \
+  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 287047804)                 \
+  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 1032541114)              \
+  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 1032541114)              \
   V(_GrowableObjectArray, get:length, GrowableArrayLength, 725548050)          \
   V(_GrowableObjectArray, get:_capacity, GrowableArrayCapacity, 725548050)     \
   V(_StringBase, get:length, StringBaseLength, 320803993)                      \
@@ -144,6 +119,8 @@
     return *this;
   }
 
+  bool is_nullable() const { return is_nullable_; }
+
   // Return type such that concrete value's type in runtime is guaranteed to
   // be subtype of it.
   const AbstractType* ToAbstractType();
@@ -178,6 +155,14 @@
   // abstract type. The pair is assumed to be coherent.
   static CompileType Create(intptr_t cid, const AbstractType& type);
 
+  CompileType CopyNonNullable() const {
+    return CompileType(kNonNullable, cid_, type_);
+  }
+
+  static CompileType CreateNullable(bool is_nullable, intptr_t cid) {
+    return CompileType(is_nullable, cid, NULL);
+  }
+
   // Create a new CompileType representing given abstract type. By default
   // values as assumed to be nullable.
   static CompileType FromAbstractType(const AbstractType& type,
@@ -238,16 +223,51 @@
  public:
   static CompileType* Wrap(const CompileType& type) {
     ZoneCompileType* zone_type = new ZoneCompileType(type);
-    return &zone_type->type_;
+    return zone_type->ToCompileType();
   }
 
- private:
+  CompileType* ToCompileType() {
+    return &type_;
+  }
+
+ protected:
   explicit ZoneCompileType(const CompileType& type) : type_(type) { }
 
   CompileType type_;
 };
 
 
+// ConstrainedCompileType represents a compile type that is computed from
+// another compile type.
+class ConstrainedCompileType : public ZoneCompileType {
+ public:
+  // Recompute compile type.
+  virtual void Update() = 0;
+
+ protected:
+  explicit ConstrainedCompileType(const CompileType& type)
+      : ZoneCompileType(type) { }
+};
+
+
+// NotNullConstrainedCompileType represents not-null constraint applied to
+// the source compile type. Result is non-nullable version of the incomming
+// compile type. It is used to represent compile type propagated downwards
+// from strict comparison with the null constant.
+class NotNullConstrainedCompileType : public ConstrainedCompileType {
+ public:
+  explicit NotNullConstrainedCompileType(CompileType* source)
+      : ConstrainedCompileType(source->CopyNonNullable()), source_(source) { }
+
+  virtual void Update() {
+    type_ = source_->CopyNonNullable();
+  }
+
+ private:
+  CompileType* source_;
+};
+
+
 class Value : public ZoneAllocated {
  public:
   // A forward iterator that allows removing the current value from the
@@ -350,13 +370,6 @@
 };
 
 
-enum Representation {
-  kTagged,
-  kUnboxedDouble,
-  kUnboxedMint
-};
-
-
 // An embedded container with N elements of type T.  Used (with partial
 // specialization for N=0) because embedded arrays cannot have size 0.
 template<typename T, intptr_t N>
@@ -453,6 +466,7 @@
   M(AllocateObjectWithBoundsCheck)                                             \
   M(LoadField)                                                                 \
   M(StoreVMField)                                                              \
+  M(LoadUntagged)                                                          \
   M(InstantiateTypeArguments)                                                  \
   M(ExtractConstructorTypeArguments)                                           \
   M(ExtractConstructorInstantiator)                                            \
@@ -484,6 +498,7 @@
   M(Constraint)                                                                \
   M(StringFromCharCode)                                                        \
   M(InvokeMathCFunction)                                                       \
+  M(GuardField)                                                                \
 
 
 #define FORWARD_DECLARATION(type) class type##Instr;
@@ -733,6 +748,7 @@
   friend class UnaryMintOpInstr;
   friend class MathSqrtInstr;
   friend class CheckClassInstr;
+  friend class GuardFieldInstr;
   friend class CheckSmiInstr;
   friend class CheckArrayBoundInstr;
   friend class CheckEitherNonSmiInstr;
@@ -743,6 +759,7 @@
   friend class FlowGraphOptimizer;
   friend class LoadIndexedInstr;
   friend class StoreIndexedInstr;
+  friend class StoreInstanceFieldInstr;
 
   virtual void RawSetInputAt(intptr_t i, Value* value) = 0;
 
@@ -1796,12 +1813,26 @@
 
   virtual void PrintTo(BufferFormatter* f) const;
 
+  // Set compile type constrained by the comparison of this branch.
+  // FlowGraphPropagator propagates it downwards into either true or false
+  // successor.
+  void set_constrained_type(ConstrainedCompileType* type) {
+    constrained_type_ = type;
+  }
+
+  // Return compile type constrained by the comparison of this branch.
+  ConstrainedCompileType* constrained_type() const {
+    return constrained_type_;
+  }
+
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value);
 
   ComparisonInstr* comparison_;
   const bool is_checked_;
 
+  ConstrainedCompileType* constrained_type_;
+
   DISALLOW_COPY_AND_ASSIGN(BranchInstr);
 };
 
@@ -2776,11 +2807,17 @@
                           Value* instance,
                           Value* value,
                           StoreBarrierType emit_store_barrier)
-      : field_(field), emit_store_barrier_(emit_store_barrier) {
+      : field_(field),
+        emit_store_barrier_(emit_store_barrier) {
     SetInputAt(0, instance);
     SetInputAt(1, value);
   }
 
+  void SetDeoptId(intptr_t deopt_id) {
+    ASSERT(CanDeoptimize());
+    deopt_id_ = deopt_id;
+  }
+
   DECLARE_INSTRUCTION(StoreInstanceField)
   virtual CompileType* ComputeInitialType() const;
 
@@ -2800,6 +2837,13 @@
   virtual bool HasSideEffect() const { return true; }
 
  private:
+  bool CanValueBeSmi() const {
+    const intptr_t cid = value()->Type()->ToNullableCid();
+    // Write barrier is skipped for nullable and non-nullable smis.
+    ASSERT(cid != kSmiCid);
+    return (cid == kDynamicCid);
+  }
+
   const Field& field_;
   const StoreBarrierType emit_store_barrier_;
 
@@ -2807,6 +2851,43 @@
 };
 
 
+class GuardFieldInstr : public TemplateInstruction<1> {
+ public:
+  GuardFieldInstr(Value* value,
+                  const Field& field,
+                  intptr_t deopt_id)
+    : field_(field) {
+    deopt_id_ = deopt_id;
+    SetInputAt(0, value);
+  }
+
+  DECLARE_INSTRUCTION(GuardField)
+
+  virtual intptr_t ArgumentCount() const { return 0; }
+
+  virtual bool CanDeoptimize() const { return true; }
+
+  virtual bool HasSideEffect() const { return false; }
+
+  virtual bool AttributesEqual(Instruction* other) const;
+
+  virtual bool AffectedBySideEffect() const;
+
+  Value* value() const { return inputs_[0]; }
+
+  virtual Instruction* Canonicalize(FlowGraphOptimizer* optimizer);
+
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+  const Field& field() const { return field_; }
+
+ private:
+  const Field& field_;
+
+  DISALLOW_COPY_AND_ASSIGN(GuardFieldInstr);
+};
+
+
 class LoadStaticFieldInstr : public TemplateDefinition<0> {
  public:
   explicit LoadStaticFieldInstr(const Field& field) : field_(field) {}
@@ -2875,6 +2956,17 @@
   DECLARE_INSTRUCTION(LoadIndexed)
   virtual CompileType ComputeType() const;
 
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx == 0 || idx == 1);
+    // The array may be tagged or untagged (for external arrays).
+    if (idx == 0) return kNoRepresentation;
+    return kTagged;
+  }
+
+  bool IsExternal() const {
+    return array()->definition()->representation() == kUntagged;
+  }
+
   Value* array() const { return inputs_[0]; }
   Value* index() const { return inputs_[1]; }
   intptr_t index_scale() const { return index_scale_; }
@@ -2969,6 +3061,10 @@
 
   virtual Representation RequiredInputRepresentation(intptr_t idx) const;
 
+  bool IsExternal() const {
+    return array()->definition()->representation() == kUntagged;
+  }
+
   virtual intptr_t DeoptimizationTarget() const {
     // Direct access since this instruction cannot deoptimize, and the deopt-id
     // was inherited from another instruction that could deoptimize.
@@ -3190,6 +3286,39 @@
 };
 
 
+class LoadUntaggedInstr : public TemplateDefinition<1> {
+ public:
+  explicit LoadUntaggedInstr(Value* object, intptr_t offset) : offset_(offset) {
+    SetInputAt(0, object);
+  }
+
+  virtual Representation representation() const {
+    return kUntagged;
+  }
+  DECLARE_INSTRUCTION(LoadUntagged)
+  virtual CompileType ComputeType() const;
+
+  Value* object() const { return inputs_[0]; }
+  intptr_t offset() const { return offset_; }
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual bool HasSideEffect() const { return false; }
+
+  virtual bool AttributesEqual(Instruction* other) const { return true; }
+
+  // This instruction must not be moved without the indexed access that
+  // depends on it (e.g. out of loops). GC may cause collect
+  // the array while the external data-array is still accessed.
+  virtual bool AffectedBySideEffect() const { return true; }
+
+ private:
+  intptr_t offset_;
+
+  DISALLOW_COPY_AND_ASSIGN(LoadUntaggedInstr);
+};
+
+
 class LoadFieldInstr : public TemplateDefinition<1> {
  public:
   LoadFieldInstr(Value* value,
@@ -3200,7 +3329,9 @@
         type_(type),
         result_cid_(kDynamicCid),
         immutable_(immutable),
-        recognized_kind_(MethodRecognizer::kUnknown) {
+        recognized_kind_(MethodRecognizer::kUnknown),
+        field_name_(NULL),
+        field_(NULL) {
     ASSERT(type.IsZoneHandle());  // May be null if field is not an instance.
     SetInputAt(0, value);
   }
@@ -3241,6 +3372,12 @@
 
   static bool IsFixedLengthArrayCid(intptr_t cid);
 
+  void set_field_name(const char* name) { field_name_ = name; }
+  const char* field_name() const { return field_name_; }
+
+  Field* field() const { return field_; }
+  void set_field(Field* field) { field_ = field; }
+
  private:
   const intptr_t offset_in_bytes_;
   const AbstractType& type_;
@@ -3249,6 +3386,9 @@
 
   MethodRecognizer::Kind recognized_kind_;
 
+  const char* field_name_;
+  Field* field_;
+
   DISALLOW_COPY_AND_ASSIGN(LoadFieldInstr);
 };
 
@@ -4233,9 +4373,15 @@
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
+  void set_null_check(bool flag) { null_check_ = flag; }
+
+  bool null_check() const { return null_check_; }
+
  private:
   const ICData& unary_checks_;
 
+  bool null_check_;
+
   DISALLOW_COPY_AND_ASSIGN(CheckClassInstr);
 };
 
@@ -4445,11 +4591,6 @@
     return locations_[index];
   }
 
-  Location* LocationSlotAt(intptr_t index) const {
-    ASSERT((index >= 0) && (index < values_.length()));
-    return &locations_[index];
-  }
-
   // The use index is the index in the flattened environment.
   Value* ValueAtUseIndex(intptr_t index) const {
     const Environment* env = this;
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 636596d..ed7e3d0 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -34,13 +34,30 @@
 
 
 LocationSummary* PushArgumentInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps= 0;
+  LocationSummary* locs =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, Location::AnyOrConstant(value()));
+  return locs;
 }
 
 
 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
+  // where PushArgument is handled by BindInstr::EmitNativeCode.
+  if (compiler->is_optimizing()) {
+    Location value = locs()->in(0);
+    if (value.IsRegister()) {
+      __ Push(value.reg());
+    } else if (value.IsConstant()) {
+      __ PushObject(value.constant());
+    } else {
+      ASSERT(value.IsStackSlot());
+      __ ldr(IP, value.ToStackSlotAddress());
+      __ Push(IP);
+    }
+  }
 }
 
 
@@ -106,13 +123,17 @@
 
 
 LocationSummary* StoreLocalInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  return LocationSummary::Make(1,
+                               Location::SameAsFirstInput(),
+                               LocationSummary::kNoCall);
 }
 
 
 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register value = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  ASSERT(result == value);  // Assert that register assignment is correct.
+  __ str(value, Address(FP, local().index() * kWordSize));
 }
 
 
@@ -133,8 +154,15 @@
 
 
 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 3;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+  summary->set_in(0, Location::RegisterLocation(R0));  // Value.
+  summary->set_in(1, Location::RegisterLocation(R1));  // Instantiator.
+  summary->set_in(2, Location::RegisterLocation(R2));  // Type arguments.
+  summary->set_out(Location::RegisterLocation(R0));
+  return summary;
 }
 
 
@@ -250,6 +278,17 @@
 }
 
 
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
 CompileType LoadIndexedInstr::ComputeType() const {
   UNIMPLEMENTED();
   return CompileType::Dynamic();
@@ -291,6 +330,17 @@
 }
 
 
+LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
   UNIMPLEMENTED();
   return NULL;
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index dc963bb..f5f21ef 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -13,6 +13,7 @@
 #include "vm/locations.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
+#include "vm/stack_frame.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 
@@ -422,6 +423,25 @@
 }
 
 
+static void LoadValueCid(FlowGraphCompiler* compiler,
+                         Register value_cid_reg,
+                         Register value_reg,
+                         Label* value_is_smi = NULL) {
+  Label done;
+  if (value_is_smi == NULL) {
+    __ movl(value_cid_reg, Immediate(kSmiCid));
+  }
+  __ testl(value_reg, Immediate(kSmiTagMask));
+  if (value_is_smi == NULL) {
+    __ j(ZERO, &done, Assembler::kNearJump);
+  } else {
+    __ j(ZERO, value_is_smi);
+  }
+  __ LoadClassId(value_cid_reg, value_reg);
+  __ Bind(&done);
+}
+
+
 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
                                           const ICData& orig_ic_data,
                                           LocationSummary* locs,
@@ -436,20 +456,9 @@
   Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
   Register left = locs->in(0).reg();
   Register right = locs->in(1).reg();
-  __ testl(left, Immediate(kSmiTagMask));
   Register temp = locs->temp(0).reg();
-  if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) {
-    Label done, load_class_id;
-    __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump);
-    __ movl(temp, Immediate(kSmiCid));
-    __ jmp(&done, Assembler::kNearJump);
-    __ Bind(&load_class_id);
-    __ LoadClassId(temp, left);
-    __ Bind(&done);
-  } else {
-    __ j(ZERO, deopt);  // Smi deopts.
-    __ LoadClassId(temp, left);
-  }
+  LoadValueCid(compiler, temp, left,
+               (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
   // 'temp' contains class-id of the left argument.
   ObjectStore* object_store = Isolate::Current()->object_store();
   Condition cond = TokenKindToSmiCondition(kind);
@@ -949,13 +958,8 @@
     // Load class into EDI. Since this is a call, any register except
     // the fixed input registers would be ok.
     ASSERT((left != EDI) && (right != EDI));
-    Label done;
     const intptr_t kNumArguments = 2;
-    __ movl(EDI, Immediate(kSmiCid));
-    __ testl(left, Immediate(kSmiTagMask));
-    __ j(ZERO, &done);
-    __ LoadClassId(EDI, left);
-    __ Bind(&done);
+    LoadValueCid(compiler, EDI, left);
     compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
                               EDI,  // Class id register.
                               kNumArguments,
@@ -1094,25 +1098,34 @@
 }
 
 
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, Location::RequiresRegister());
+  locs->set_out(Location::RequiresRegister());
+  return locs;
+}
+
+
+void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register object = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  __ movl(result, FieldAddress(object, offset()));
+}
+
+
 CompileType LoadIndexedInstr::ComputeType() const {
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
       return CompileType::Dynamic();
 
-    case kFloat32ArrayCid :
-    case kFloat64ArrayCid :
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
       return CompileType::FromCid(kDoubleCid);
 
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -1124,8 +1137,6 @@
     case kTwoByteStringCid:
       return CompileType::FromCid(kSmiCid);
 
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       // Result can be Smi or Mint when boxed.
@@ -1145,13 +1156,6 @@
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -1162,15 +1166,11 @@
     case kOneByteStringCid:
     case kTwoByteStringCid:
       return kTagged;
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       // Instruction can deoptimize if we optimistically assumed that the result
       // fits into Smi.
       return CanDeoptimize() ? kTagged : kUnboxedMint;
-    case kFloat32ArrayCid :
-    case kFloat64ArrayCid :
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
       return kUnboxedDouble;
@@ -1213,34 +1213,23 @@
   Register array = locs()->in(0).reg();
   Location index = locs()->in(1);
 
-  if ((class_id() == kExternalUint8ArrayCid) ||
-      (class_id() == kExternalUint8ClampedArrayCid) ||
-      (class_id() == kExternalTypedDataUint8ArrayCid) ||
-      (class_id() == kExternalTypedDataUint8ClampedArrayCid)) {
-    Register result = locs()->out().reg();
-    const Address& element_address = index.IsRegister()
+  Address element_address(kNoRegister, 0);
+  if (IsExternal()) {
+    element_address = index.IsRegister()
         ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
-            index_scale(), result, index.reg())
+            index_scale(), array, index.reg())
         : FlowGraphCompiler::ExternalElementAddressForIntIndex(
-            index_scale(), result, Smi::Cast(index.constant()).Value());
-    ASSERT(index_scale() == 1);
-    if (index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
-    __ movl(result,
-            FieldAddress(array, ExternalUint8Array::data_offset()));
-    __ movzxb(result, element_address);
-    __ SmiTag(result);
-    return;
+            index_scale(), array, Smi::Cast(index.constant()).Value());
+  } else {
+    ASSERT(this->array()->definition()->representation() == kTagged);
+    element_address = index.IsRegister()
+        ? FlowGraphCompiler::ElementAddressForRegIndex(
+            class_id(), index_scale(), array, index.reg())
+        : FlowGraphCompiler::ElementAddressForIntIndex(
+            class_id(), index_scale(), array,
+            Smi::Cast(index.constant()).Value());
   }
 
-  FieldAddress element_address = index.IsRegister()
-      ? FlowGraphCompiler::ElementAddressForRegIndex(
-          class_id(), index_scale(), array, index.reg())
-      : FlowGraphCompiler::ElementAddressForIntIndex(
-          class_id(), index_scale(), array,
-          Smi::Cast(index.constant()).Value());
-
   if ((representation() == kUnboxedDouble) ||
       (representation() == kUnboxedMint)) {
     XmmRegister result = locs()->out().fpu_reg();
@@ -1248,23 +1237,19 @@
       __ SmiUntag(index.reg());
     }
     switch (class_id()) {
-      case kInt32ArrayCid:
       case kTypedDataInt32ArrayCid:
         __ movss(result, element_address);
         __ pmovsxdq(result, result);
         break;
-      case kUint32ArrayCid:
       case kTypedDataUint32ArrayCid:
         __ xorpd(result, result);
         __ movss(result, element_address);
         break;
-      case kFloat32ArrayCid:
       case kTypedDataFloat32ArrayCid:
         // Load single precision float and promote to double.
         __ movss(result, element_address);
         __ cvtss2sd(result, locs()->out().fpu_reg());
         break;
-      case kFloat64ArrayCid:
       case kTypedDataFloat64ArrayCid:
         __ movsd(result, element_address);
         break;
@@ -1277,33 +1262,29 @@
     __ SmiUntag(index.reg());
   }
   switch (class_id()) {
-    case kInt8ArrayCid:
     case kTypedDataInt8ArrayCid:
       ASSERT(index_scale() == 1);
       __ movsxb(result, element_address);
       __ SmiTag(result);
       break;
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
     case kOneByteStringCid:
       ASSERT(index_scale() == 1);
       __ movzxb(result, element_address);
       __ SmiTag(result);
       break;
-    case kInt16ArrayCid:
     case kTypedDataInt16ArrayCid:
       __ movsxw(result, element_address);
       __ SmiTag(result);
       break;
-    case kUint16ArrayCid:
     case kTypedDataUint16ArrayCid:
     case kTwoByteStringCid:
       __ movzxw(result, element_address);
       __ SmiTag(result);
       break;
-    case kInt32ArrayCid:
     case kTypedDataInt32ArrayCid: {
         Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptInt32Load);
         __ movl(result, element_address);
@@ -1313,7 +1294,6 @@
         __ SmiTag(result);
       }
       break;
-    case kUint32ArrayCid:
     case kTypedDataUint32ArrayCid: {
         Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptUint32Load);
         __ movl(result, element_address);
@@ -1333,17 +1313,12 @@
 
 Representation StoreIndexedInstr::RequiredInputRepresentation(
     intptr_t idx) const {
-  if ((idx == 0) || (idx == 1)) return kTagged;
+  // Array can be a Dart object or a pointer to external data.
+  if (idx == 0)  return kNoRepresentation;  // Flexible input representation.
+  if (idx == 1) return kTagged;  // Index is a smi.
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kExternalUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
@@ -1352,15 +1327,11 @@
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid:
       return kTagged;
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       return value()->IsSmiValue() ? kTagged : kUnboxedMint;
-    case kFloat32ArrayCid :
-    case kFloat64ArrayCid :
-    case kTypedDataFloat32ArrayCid :
-    case kTypedDataFloat64ArrayCid :
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
       return kUnboxedDouble;
     default:
       UNIMPLEMENTED();
@@ -1394,16 +1365,8 @@
                         ? Location::WritableRegister()
                         : Location::RegisterOrConstant(value()));
       break;
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
-      // Need temp register to load the external array's data array.
-      locs->AddTemp(Location::RequiresRegister());
-      // Fall through.
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -1411,15 +1374,11 @@
       // EBX, ECX, EDX) instead of using a fixed register.
       locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX));
       break;
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid:
       // Writable register because the value must be untagged before storing.
       locs->set_in(2, Location::WritableRegister());
       break;
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       // Mints are stored in XMM registers. For smis, use a writable register
@@ -1428,12 +1387,10 @@
                       ? Location::WritableRegister()
                       : Location::RequiresFpuRegister());
       break;
-    case kFloat32ArrayCid:
     case kTypedDataFloat32ArrayCid:
       // Need temp register for float-to-double conversion.
       locs->AddTemp(Location::RequiresFpuRegister());
       // Fall through.
-    case kFloat64ArrayCid:
     case kTypedDataFloat64ArrayCid:
       // TODO(srdjan): Support Float64 constants.
       locs->set_in(2, Location::RequiresFpuRegister());
@@ -1451,19 +1408,14 @@
   Location index = locs()->in(1);
 
   Address element_address(kNoRegister, 0);
-  if ((class_id() == kExternalUint8ArrayCid) ||
-      (class_id() == kExternalUint8ClampedArrayCid) ||
-      (class_id() == kExternalTypedDataUint8ArrayCid) ||
-      (class_id() == kExternalTypedDataUint8ClampedArrayCid)) {
-    Register temp = locs()->temp(0).reg();
+  if (IsExternal()) {
     element_address = index.IsRegister()
         ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
-            index_scale(), temp, index.reg())
+            index_scale(), array, index.reg())
         : FlowGraphCompiler::ExternalElementAddressForIntIndex(
-            index_scale(), temp, Smi::Cast(index.constant()).Value());
-    __ movl(temp,
-            FieldAddress(array, ExternalUint8Array::data_offset()));
+            index_scale(), array, Smi::Cast(index.constant()).Value());
   } else {
+    ASSERT(this->array()->definition()->representation() == kTagged);
     element_address = index.IsRegister()
         ? FlowGraphCompiler::ElementAddressForRegIndex(
           class_id(), index_scale(), array, index.reg())
@@ -1488,9 +1440,6 @@
         __ StoreIntoObjectNoBarrier(array, element_address, value);
       }
       break;
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kExternalUint8ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
@@ -1504,8 +1453,6 @@
         __ movb(element_address, AL);
       }
       break;
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ClampedArrayCid:
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid: {
       if (locs()->in(2).IsConstant()) {
@@ -1536,8 +1483,6 @@
       }
       break;
     }
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid: {
       Register value = locs()->in(2).reg();
@@ -1545,8 +1490,6 @@
       __ movw(element_address, value);
       break;
     }
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       if (value()->IsSmiValue()) {
@@ -1559,14 +1502,12 @@
       __ movss(element_address, locs()->in(2).fpu_reg());
       }
       break;
-    case kFloat32ArrayCid:
     case kTypedDataFloat32ArrayCid:
       // Convert to single precision.
       __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg());
       // Store.
       __ movss(element_address, locs()->temp(0).fpu_reg());
       break;
-    case kFloat64ArrayCid:
     case kTypedDataFloat64ArrayCid:
       __ movsd(element_address, locs()->in(2).fpu_reg());
       break;
@@ -1576,6 +1517,154 @@
 }
 
 
+LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  if ((value()->Type()->ToCid() == kDynamicCid) &&
+      (field().guarded_cid() != kSmiCid)) {
+    summary->AddTemp(Location::RequiresRegister());
+  }
+  if (field().guarded_cid() == kIllegalCid) {
+    summary->AddTemp(Location::RequiresRegister());
+  }
+  return summary;
+}
+
+
+void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const intptr_t field_cid = field().guarded_cid();
+  const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
+
+  if (field_cid == kDynamicCid) {
+    ASSERT(!compiler->is_optimizing());
+    return;  // Nothing to emit.
+  }
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+
+  Register value_reg = locs()->in(0).reg();
+
+  Register value_cid_reg = ((value_cid == kDynamicCid) &&
+      (field_cid != kSmiCid)) ? locs()->temp(0).reg() : kNoRegister;
+
+  Register field_reg = (field_cid == kIllegalCid) ?
+      locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
+
+  Label ok, fail_label;
+
+  Label* deopt = compiler->is_optimizing() ?
+      compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
+
+  Label* fail = (deopt != NULL) ? deopt : &fail_label;
+
+  const bool ok_is_fall_through = (deopt != NULL);
+
+  if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
+    if (!compiler->is_optimizing()) {
+      // Currently we can't have different location summaries for optimized
+      // and non-optimized code. So instead we manually pick up a register
+      // that is known to be free because we know how non-optimizing compiler
+      // allocates registers.
+      field_reg = EBX;
+      ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
+    }
+
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
+
+    FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
+    FieldAddress field_nullability_operand(
+        field_reg, Field::is_nullable_offset());
+
+    if (value_cid == kDynamicCid) {
+      if (value_cid_reg == kNoRegister) {
+        ASSERT(!compiler->is_optimizing());
+        value_cid_reg = EDX;
+        ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
+      }
+
+      LoadValueCid(compiler, value_cid_reg, value_reg);
+
+      __ cmpl(value_cid_reg, field_cid_operand);
+      __ j(EQUAL, &ok);
+      __ cmpl(value_cid_reg, field_nullability_operand);
+    } else if (value_cid == kNullCid) {
+      __ cmpl(field_nullability_operand, Immediate(value_cid));
+    } else {
+      __ cmpl(field_cid_operand, Immediate(value_cid));
+    }
+    __ j(EQUAL, &ok);
+
+    __ cmpl(field_cid_operand, Immediate(kIllegalCid));
+    __ j(NOT_EQUAL, fail);
+
+    if (value_cid == kDynamicCid) {
+      __ movl(field_cid_operand, value_cid_reg);
+      __ movl(field_nullability_operand, value_cid_reg);
+    } else {
+      __ movl(field_cid_operand, Immediate(value_cid));
+      __ movl(field_nullability_operand, Immediate(value_cid));
+    }
+
+    if (!ok_is_fall_through) {
+      __ jmp(&ok);
+    }
+  } else {
+    if (value_cid == kDynamicCid) {
+      // Field's guarded class id is fixed by value's class id is not known.
+      __ testl(value_reg, Immediate(kSmiTagMask));
+
+      if (field_cid != kSmiCid) {
+        __ j(ZERO, fail);
+        __ LoadClassId(value_cid_reg, value_reg);
+        __ cmpl(value_cid_reg, Immediate(field_cid));
+      }
+
+      if (field().is_nullable() && (field_cid != kNullCid)) {
+        __ j(EQUAL, &ok);
+        const Immediate& raw_null =
+            Immediate(reinterpret_cast<intptr_t>(Object::null()));
+        __ cmpl(value_reg, raw_null);
+      }
+
+      if (ok_is_fall_through) {
+        __ j(NOT_EQUAL, fail);
+      } else {
+        __ j(EQUAL, &ok);
+      }
+    } else {
+      // Both value's and field's class id is known.
+      if ((value_cid != field_cid) && (value_cid != nullability)) {
+        if (ok_is_fall_through) {
+          __ jmp(fail);
+        }
+      } else {
+        // Nothing to emit.
+        ASSERT(!compiler->is_optimizing());
+        return;
+      }
+    }
+  }
+
+  if (deopt == NULL) {
+    ASSERT(!compiler->is_optimizing());
+    __ Bind(fail);
+
+    __ cmpl(FieldAddress(field_reg, Field::guarded_cid_offset()),
+            Immediate(kDynamicCid));
+    __ j(EQUAL, &ok);
+
+    __ pushl(field_reg);
+    __ pushl(value_reg);
+    __ CallRuntime(kUpdateFieldCidRuntimeEntry);
+    __ Drop(2);  // Drop the field and the value.
+  }
+
+  __ Bind(&ok);
+}
+
+
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   const intptr_t num_temps =  0;
@@ -1594,7 +1683,9 @@
   if (ShouldEmitStoreBarrier()) {
     Register value_reg = locs()->in(1).reg();
     __ StoreIntoObject(instance_reg,
-        FieldAddress(instance_reg, field().Offset()), value_reg);
+                       FieldAddress(instance_reg, field().Offset()),
+                       value_reg,
+                       CanValueBeSmi());
   } else {
     if (locs()->in(1).IsConstant()) {
       __ StoreIntoObjectNoBarrier(
@@ -2272,7 +2363,11 @@
       case Token::kMUL: {
         // Keep left value tagged and untag right value.
         const intptr_t value = Smi::Cast(constant).Value();
-        __ imull(left, Immediate(value));
+        if (value == 2) {
+          __ shll(left, Immediate(1));
+        } else {
+          __ imull(left, Immediate(value));
+        }
         if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
@@ -2809,11 +2904,11 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
       new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
-  result->set_in(0, Location::FpuRegisterLocation(XMM1, Location::kDouble));
+  result->set_in(0, Location::FpuRegisterLocation(XMM1, kUnboxedDouble));
   if (InputCount() == 2) {
-    result->set_in(1, Location::FpuRegisterLocation(XMM2, Location::kDouble));
+    result->set_in(1, Location::FpuRegisterLocation(XMM2, kUnboxedDouble));
   }
-  result->set_out(Location::FpuRegisterLocation(XMM1, Location::kDouble));
+  result->set_out(Location::FpuRegisterLocation(XMM1, kUnboxedDouble));
   return result;
 }
 
@@ -2860,17 +2955,8 @@
   __ movl(EAX,
       Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize));
 
-  Label done;
-  if (ic_data().GetReceiverClassIdAt(0) == kSmiCid) {
-    __ movl(EDI, Immediate(kSmiCid));
-    __ testl(EAX, Immediate(kSmiTagMask));
-    __ j(ZERO, &done, Assembler::kNearJump);
-  } else {
-    __ testl(EAX, Immediate(kSmiTagMask));
-    __ j(ZERO, deopt);
-  }
-  __ LoadClassId(EDI, EAX);
-  __ Bind(&done);
+  LoadValueCid(compiler, EDI, EAX,
+               (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
 
   compiler->EmitTestAndCall(ic_data(),
                             EDI,  // Class id register.
@@ -2896,16 +2982,28 @@
 
 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 1;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_temp(0, Location::RequiresRegister());
+  if (!null_check()) {
+    summary->AddTemp(Location::RequiresRegister());
+  }
   return summary;
 }
 
 
 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (null_check()) {
+    Label* deopt = compiler->AddDeoptStub(deopt_id(),
+                                          kDeoptCheckClass);
+    const Immediate& raw_null =
+        Immediate(reinterpret_cast<intptr_t>(Object::null()));
+    __ cmpl(locs()->in(0).reg(), raw_null);
+    __ j(EQUAL, deopt);
+    return;
+  }
+
   ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) ||
          (unary_checks().NumberOfChecks() > 1));
   Register value = locs()->in(0).reg();
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 5b392ce..de9556f 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -172,6 +172,17 @@
 }
 
 
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
 CompileType LoadIndexedInstr::ComputeType() const {
   UNIMPLEMENTED();
   return CompileType::Dynamic();
@@ -213,6 +224,17 @@
 }
 
 
+LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
   UNIMPLEMENTED();
   return NULL;
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 9f5793f..afac01f 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -13,6 +13,7 @@
 #include "vm/locations.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
+#include "vm/stack_frame.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 
@@ -420,6 +421,25 @@
 }
 
 
+static void LoadValueCid(FlowGraphCompiler* compiler,
+                         Register value_cid_reg,
+                         Register value_reg,
+                         Label* value_is_smi = NULL) {
+  Label done;
+  if (value_is_smi == NULL) {
+    __ movq(value_cid_reg, Immediate(kSmiCid));
+  }
+  __ testq(value_reg, Immediate(kSmiTagMask));
+  if (value_is_smi == NULL) {
+    __ j(ZERO, &done, Assembler::kNearJump);
+  } else {
+    __ j(ZERO, value_is_smi);
+  }
+  __ LoadClassId(value_cid_reg, value_reg);
+  __ Bind(&done);
+}
+
+
 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
                                           const ICData& orig_ic_data,
                                           LocationSummary* locs,
@@ -434,20 +454,9 @@
   Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
   Register left = locs->in(0).reg();
   Register right = locs->in(1).reg();
-  __ testq(left, Immediate(kSmiTagMask));
   Register temp = locs->temp(0).reg();
-  if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) {
-    Label done, load_class_id;
-    __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump);
-    __ movq(temp, Immediate(kSmiCid));
-    __ jmp(&done, Assembler::kNearJump);
-    __ Bind(&load_class_id);
-    __ LoadClassId(temp, left);
-    __ Bind(&done);
-  } else {
-    __ j(ZERO, deopt);  // Smi deopts.
-    __ LoadClassId(temp, left);
-  }
+  LoadValueCid(compiler, temp, left,
+               (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
   // 'temp' contains class-id of the left argument.
   ObjectStore* object_store = Isolate::Current()->object_store();
   Condition cond = TokenKindToSmiCondition(kind);
@@ -819,12 +828,7 @@
     // Load class into RDI. Since this is a call, any register except
     // the fixed input registers would be ok.
     ASSERT((left != RDI) && (right != RDI));
-    Label done;
-    __ movq(RDI, Immediate(kSmiCid));
-    __ testq(left, Immediate(kSmiTagMask));
-    __ j(ZERO, &done);
-    __ LoadClassId(RDI, left);
-    __ Bind(&done);
+    LoadValueCid(compiler, RDI, left);
     const intptr_t kNumArguments = 2;
     compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
                               RDI,  // Class id register.
@@ -961,25 +965,34 @@
 }
 
 
+LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_in(0, Location::RequiresRegister());
+  locs->set_out(Location::RequiresRegister());
+  return locs;
+}
+
+
+void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register object = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  __ movq(result, FieldAddress(object, offset()));
+}
+
+
 CompileType LoadIndexedInstr::ComputeType() const {
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
       return CompileType::Dynamic();
 
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid:
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
       return CompileType::FromCid(kDoubleCid);
 
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -989,8 +1002,6 @@
     case kTypedDataUint16ArrayCid:
     case kOneByteStringCid:
     case kTwoByteStringCid:
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       return CompileType::FromCid(kSmiCid);
@@ -1006,13 +1017,6 @@
   switch (class_id_) {
     case kArrayCid:
     case kImmutableArrayCid:
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -1022,13 +1026,9 @@
     case kTypedDataUint16ArrayCid:
     case kOneByteStringCid:
     case kTwoByteStringCid:
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       return kTagged;
-    case kFloat32ArrayCid :
-    case kFloat64ArrayCid :
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
       return kUnboxedDouble;
@@ -1071,33 +1071,25 @@
   Register array = locs()->in(0).reg();
   Location index = locs()->in(1);
 
-  if ((class_id() == kExternalUint8ArrayCid) ||
-      (class_id() == kExternalUint8ClampedArrayCid) ||
-      (class_id() == kExternalTypedDataUint8ArrayCid) ||
-      (class_id() == kExternalTypedDataUint8ClampedArrayCid)) {
-    Register result = locs()->out().reg();
-    Address element_address = index.IsRegister()
-        ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
-            index_scale(), result, index.reg())
-        : FlowGraphCompiler::ExternalElementAddressForIntIndex(
-            index_scale(), result, Smi::Cast(index.constant()).Value());
-    ASSERT(index_scale() == 1);
-    if (index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
-    __ movq(result,
-            FieldAddress(array, ExternalUint8Array::data_offset()));
-    __ movzxb(result, element_address);
-    __ SmiTag(result);
-    return;
-  }
+  const bool is_external =
+      (this->array()->definition()->representation() == kUntagged);
+  Address element_address(kNoRegister, 0);
 
-  FieldAddress element_address = index.IsRegister()
-      ? FlowGraphCompiler::ElementAddressForRegIndex(
-          class_id(), index_scale(), array, index.reg())
-      : FlowGraphCompiler::ElementAddressForIntIndex(
-          class_id(), index_scale(), array,
-          Smi::Cast(index.constant()).Value());
+  if (is_external) {
+    element_address = index.IsRegister()
+        ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
+            index_scale(), array, index.reg())
+        : FlowGraphCompiler::ExternalElementAddressForIntIndex(
+            index_scale(), array, Smi::Cast(index.constant()).Value());
+  } else {
+    ASSERT(this->array()->definition()->representation() == kTagged);
+    element_address = index.IsRegister()
+        ? FlowGraphCompiler::ElementAddressForRegIndex(
+            class_id(), index_scale(), array, index.reg())
+        : FlowGraphCompiler::ElementAddressForIntIndex(
+            class_id(), index_scale(), array,
+            Smi::Cast(index.constant()).Value());
+  }
 
   if (representation() == kUnboxedDouble) {
     if ((index_scale() == 1) && index.IsRegister()) {
@@ -1105,15 +1097,13 @@
     }
 
     XmmRegister result = locs()->out().fpu_reg();
-    if (class_id() == kFloat32ArrayCid ||
-        class_id() == kTypedDataFloat32ArrayCid) {
+    if (class_id() == kTypedDataFloat32ArrayCid) {
       // Load single precision float.
       __ movss(result, element_address);
       // Promote to double.
       __ cvtss2sd(result, locs()->out().fpu_reg());
     } else {
-      ASSERT(class_id() == kFloat64ArrayCid ||
-             class_id() == kTypedDataFloat64ArrayCid);
+      ASSERT(class_id() == kTypedDataFloat64ArrayCid);
       __ movsd(result, element_address);
     }
     return;
@@ -1124,36 +1114,31 @@
   }
   Register result = locs()->out().reg();
   switch (class_id()) {
-    case kInt8ArrayCid:
     case kTypedDataInt8ArrayCid:
       __ movsxb(result, element_address);
       __ SmiTag(result);
       break;
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
     case kOneByteStringCid:
       __ movzxb(result, element_address);
       __ SmiTag(result);
       break;
-    case kInt16ArrayCid:
     case kTypedDataInt16ArrayCid:
       __ movsxw(result, element_address);
       __ SmiTag(result);
       break;
-    case kUint16ArrayCid:
     case kTypedDataUint16ArrayCid:
     case kTwoByteStringCid:
       __ movzxw(result, element_address);
       __ SmiTag(result);
       break;
-    case kInt32ArrayCid:
     case kTypedDataInt32ArrayCid:
       __ movsxl(result, element_address);
       __ SmiTag(result);
       break;
-    case kUint32ArrayCid:
     case kTypedDataUint32ArrayCid:
       __ movl(result, element_address);
       __ SmiTag(result);
@@ -1168,19 +1153,11 @@
 
 Representation StoreIndexedInstr::RequiredInputRepresentation(
     intptr_t idx) const {
-  if ((idx == 0) || (idx == 1)) return kTagged;
+  if (idx == 0) return kNoRepresentation;
+  if (idx == 1) return kTagged;
   ASSERT(idx == 2);
   switch (class_id_) {
     case kArrayCid:
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kExternalUint8ArrayCid:
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ClampedArrayCid:
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
@@ -1191,8 +1168,6 @@
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
       return kTagged;
-    case kFloat32ArrayCid:
-    case kFloat64ArrayCid:
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
       return kUnboxedDouble;
@@ -1228,16 +1203,8 @@
                         ? Location::WritableRegister()
                         : Location::RegisterOrConstant(value()));
       break;
-    case kExternalUint8ArrayCid:
-    case kExternalUint8ClampedArrayCid:
     case kExternalTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid:
-      // Need temp register to load the external array's data array.
-      locs->AddTemp(Location::RequiresRegister());
-      // Fall through.
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kUint8ClampedArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kTypedDataUint8ClampedArrayCid:
@@ -1245,10 +1212,6 @@
       // RBX, RCX, RDX) instead of using a fixed register.
       locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX));
       break;
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid:
     case kTypedDataInt32ArrayCid:
@@ -1256,12 +1219,10 @@
       // Writable register because the value must be untagged before storing.
       locs->set_in(2, Location::WritableRegister());
       break;
-    case kFloat32ArrayCid:
     case kTypedDataFloat32ArrayCid:
       // Need temp register for float-to-double conversion.
       locs->AddTemp(Location::RequiresFpuRegister());
       // Fall through.
-    case kFloat64ArrayCid:
     case kTypedDataFloat64ArrayCid:
       // TODO(srdjan): Support Float64 constants.
       locs->set_in(2, Location::RequiresFpuRegister());
@@ -1278,20 +1239,17 @@
   Register array = locs()->in(0).reg();
   Location index = locs()->in(1);
 
+  const bool is_external =
+      (this->array()->definition()->representation() == kUntagged);
   Address element_address(kNoRegister, 0);
-  if ((class_id() == kExternalUint8ArrayCid) ||
-      (class_id() == kExternalUint8ClampedArrayCid) ||
-      (class_id() == kExternalTypedDataUint8ArrayCid) ||
-      (class_id() == kExternalTypedDataUint8ClampedArrayCid)) {
-    Register temp = locs()->temp(0).reg();
+  if (is_external) {
     element_address = index.IsRegister()
         ? FlowGraphCompiler::ExternalElementAddressForRegIndex(
-            index_scale(), temp, index.reg())
+            index_scale(), array, index.reg())
         : FlowGraphCompiler::ExternalElementAddressForIntIndex(
-            index_scale(), temp, Smi::Cast(index.constant()).Value());
-    __ movq(temp,
-            FieldAddress(array, ExternalUint8Array::data_offset()));
+            index_scale(), array, Smi::Cast(index.constant()).Value());
   } else {
+    ASSERT(this->array()->definition()->representation() == kTagged);
     element_address = index.IsRegister()
         ? FlowGraphCompiler::ElementAddressForRegIndex(
             class_id(), index_scale(), array, index.reg())
@@ -1316,9 +1274,6 @@
         __ StoreIntoObjectNoBarrier(array, element_address, value);
       }
       break;
-    case kInt8ArrayCid:
-    case kUint8ArrayCid:
-    case kExternalUint8ArrayCid:
     case kTypedDataInt8ArrayCid:
     case kTypedDataUint8ArrayCid:
     case kExternalTypedDataUint8ArrayCid:
@@ -1332,8 +1287,6 @@
         __ movb(element_address, RAX);
       }
       break;
-    case kUint8ClampedArrayCid:
-    case kExternalUint8ClampedArrayCid:
     case kTypedDataUint8ClampedArrayCid:
     case kExternalTypedDataUint8ClampedArrayCid: {
       if (locs()->in(2).IsConstant()) {
@@ -1364,8 +1317,6 @@
       }
       break;
     }
-    case kInt16ArrayCid:
-    case kUint16ArrayCid:
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid: {
       Register value = locs()->in(2).reg();
@@ -1373,8 +1324,6 @@
       __ movw(element_address, value);
       break;
     }
-    case kInt32ArrayCid:
-    case kUint32ArrayCid:
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid: {
       Register value = locs()->in(2).reg();
@@ -1382,14 +1331,12 @@
       __ movl(element_address, value);
         break;
     }
-    case kFloat32ArrayCid:
     case kTypedDataFloat32ArrayCid:
       // Convert to single precision.
       __ cvtsd2ss(locs()->temp(0).fpu_reg(), locs()->in(2).fpu_reg());
       // Store.
       __ movss(element_address, locs()->temp(0).fpu_reg());
       break;
-    case kFloat64ArrayCid:
     case kTypedDataFloat64ArrayCid:
       __ movsd(element_address, locs()->in(2).fpu_reg());
       break;
@@ -1399,6 +1346,154 @@
 }
 
 
+LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  if ((value()->Type()->ToCid() == kDynamicCid) &&
+      (field().guarded_cid() != kSmiCid)) {
+    summary->AddTemp(Location::RequiresRegister());
+  }
+  if (field().guarded_cid() == kIllegalCid) {
+    summary->AddTemp(Location::RequiresRegister());
+  }
+  return summary;
+}
+
+
+void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const intptr_t field_cid = field().guarded_cid();
+  const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
+
+  if (field_cid == kDynamicCid) {
+    ASSERT(!compiler->is_optimizing());
+    return;  // Nothing to emit.
+  }
+
+  const intptr_t value_cid = value()->Type()->ToCid();
+
+  Register value_reg = locs()->in(0).reg();
+
+  Register value_cid_reg = ((value_cid == kDynamicCid) &&
+      (field_cid != kSmiCid)) ? locs()->temp(0).reg() : kNoRegister;
+
+  Register field_reg = (field_cid == kIllegalCid) ?
+      locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
+
+  Label ok, fail_label;
+
+  Label* deopt = compiler->is_optimizing() ?
+      compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
+
+  Label* fail = (deopt != NULL) ? deopt : &fail_label;
+
+  const bool ok_is_fall_through = (deopt != NULL);
+
+  if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
+    if (!compiler->is_optimizing()) {
+      // Currently we can't have different location summaries for optimized
+      // and non-optimized code. So instead we manually pick up a register
+      // that is known to be free because we know how non-optimizing compiler
+      // allocates registers.
+      field_reg = RBX;
+      ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
+    }
+
+    __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
+
+    FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
+    FieldAddress field_nullability_operand(
+        field_reg, Field::is_nullable_offset());
+
+    if (value_cid == kDynamicCid) {
+      if (value_cid_reg == kNoRegister) {
+        ASSERT(!compiler->is_optimizing());
+        value_cid_reg = RDX;
+        ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
+      }
+
+      LoadValueCid(compiler, value_cid_reg, value_reg);
+
+      __ cmpq(value_cid_reg, field_cid_operand);
+      __ j(EQUAL, &ok);
+      __ cmpq(value_cid_reg, field_nullability_operand);
+    } else if (value_cid == kNullCid) {
+      __ cmpq(field_nullability_operand, Immediate(value_cid));
+    } else {
+      __ cmpq(field_cid_operand, Immediate(value_cid));
+    }
+    __ j(EQUAL, &ok);
+
+    __ cmpq(field_cid_operand, Immediate(kIllegalCid));
+    __ j(NOT_EQUAL, fail);
+
+    if (value_cid == kDynamicCid) {
+      __ movq(field_cid_operand, value_cid_reg);
+      __ movq(field_nullability_operand, value_cid_reg);
+    } else {
+      __ movq(field_cid_operand, Immediate(value_cid));
+      __ movq(field_nullability_operand, Immediate(value_cid));
+    }
+
+    if (!ok_is_fall_through) {
+      __ jmp(&ok);
+    }
+  } else {
+    if (value_cid == kDynamicCid) {
+      // Field's guarded class id is fixed but value's class id is not known.
+      __ testq(value_reg, Immediate(kSmiTagMask));
+
+      if (field_cid != kSmiCid) {
+        __ j(ZERO, fail);
+        __ LoadClassId(value_cid_reg, value_reg);
+        __ cmpq(value_cid_reg, Immediate(field_cid));
+      }
+
+      if (field().is_nullable() && (field_cid != kNullCid)) {
+        __ j(EQUAL, &ok);
+        const Immediate& raw_null =
+            Immediate(reinterpret_cast<intptr_t>(Object::null()));
+        __ cmpq(value_reg, raw_null);
+      }
+
+      if (ok_is_fall_through) {
+        __ j(NOT_EQUAL, fail);
+      } else {
+        __ j(EQUAL, &ok);
+      }
+    } else {
+      // Both value's and field's class id is known.
+      if ((value_cid != field_cid) && (value_cid != nullability)) {
+        if (ok_is_fall_through) {
+          __ jmp(fail);
+        }
+      } else {
+        // Nothing to emit.
+        ASSERT(!compiler->is_optimizing());
+        return;
+      }
+    }
+  }
+
+  if (deopt == NULL) {
+    ASSERT(!compiler->is_optimizing());
+    __ Bind(fail);
+
+    __ cmpq(FieldAddress(field_reg, Field::guarded_cid_offset()),
+            Immediate(kDynamicCid));
+    __ j(EQUAL, &ok);
+
+    __ pushq(field_reg);
+    __ pushq(value_reg);
+    __ CallRuntime(kUpdateFieldCidRuntimeEntry);
+    __ Drop(2);  // Drop the field and the value.
+  }
+
+  __ Bind(&ok);
+}
+
+
 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   const intptr_t num_temps = 0;
@@ -1417,7 +1512,9 @@
   if (ShouldEmitStoreBarrier()) {
     Register value_reg = locs()->in(1).reg();
     __ StoreIntoObject(instance_reg,
-        FieldAddress(instance_reg, field().Offset()), value_reg);
+                       FieldAddress(instance_reg, field().Offset()),
+                       value_reg,
+                       CanValueBeSmi());
   } else {
     if (locs()->in(1).IsConstant()) {
       __ StoreObject(FieldAddress(instance_reg, field().Offset()),
@@ -1891,7 +1988,7 @@
   if (locs.in(1).IsConstant()) {
     const Object& constant = locs.in(1).constant();
     ASSERT(constant.IsSmi());
-    // shll operation masks the count to 6 bits.
+    // shlq operation masks the count to 6 bits.
     const intptr_t kCountLimit = 0x3F;
     const intptr_t value = Smi::Cast(constant).Value();
     if (value == 0) {
@@ -2112,7 +2209,11 @@
       case Token::kMUL: {
         // Keep left value tagged and untag right value.
         const intptr_t value = Smi::Cast(constant).Value();
-        __ imulq(left, Immediate(value));
+        if (value == 2) {
+          __ shlq(left, Immediate(1));
+        } else {
+          __ imulq(left, Immediate(value));
+        }
         if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
@@ -2660,11 +2761,11 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* result =
       new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
-  result->set_in(0, Location::FpuRegisterLocation(XMM1, Location::kDouble));
+  result->set_in(0, Location::FpuRegisterLocation(XMM1, kUnboxedDouble));
   if (InputCount() == 2) {
-    result->set_in(1, Location::FpuRegisterLocation(XMM2, Location::kDouble));
+    result->set_in(1, Location::FpuRegisterLocation(XMM2, kUnboxedDouble));
   }
-  result->set_out(Location::FpuRegisterLocation(XMM1, Location::kDouble));
+  result->set_out(Location::FpuRegisterLocation(XMM1, kUnboxedDouble));
   return result;
 }
 
@@ -2712,17 +2813,8 @@
   // Load receiver into RAX.
   __ movq(RAX,
       Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize));
-  Label done;
-  if (ic_data().GetReceiverClassIdAt(0) == kSmiCid) {
-    __ movq(RDI, Immediate(kSmiCid));
-    __ testq(RAX, Immediate(kSmiTagMask));
-    __ j(ZERO, &done, Assembler::kNearJump);
-  } else {
-    __ testq(RAX, Immediate(kSmiTagMask));
-    __ j(ZERO, deopt);
-  }
-  __ LoadClassId(RDI, RAX);
-  __ Bind(&done);
+  LoadValueCid(compiler, RDI, RAX,
+               (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
   compiler->EmitTestAndCall(ic_data(),
                             RDI,  // Class id register.
                             instance_call()->ArgumentCount(),
@@ -2747,16 +2839,28 @@
 
 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 1;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_temp(0, Location::RequiresRegister());
+  if (!null_check()) {
+    summary->AddTemp(Location::RequiresRegister());
+  }
   return summary;
 }
 
 
 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (null_check()) {
+    Label* deopt = compiler->AddDeoptStub(deopt_id(),
+                                          kDeoptCheckClass);
+    const Immediate& raw_null =
+        Immediate(reinterpret_cast<intptr_t>(Object::null()));
+    __ cmpq(locs()->in(0).reg(), raw_null);
+    __ j(EQUAL, deopt);
+    return;
+  }
+
   ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) ||
          (unary_checks().NumberOfChecks() > 1));
   Register value = locs()->in(0).reg();
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 6afc6fb..74cf19c 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -31,7 +31,7 @@
             "Track function usage and report.");
 DEFINE_FLAG(bool, trace_isolates, false,
             "Trace isolate creation and shut down.");
-
+DECLARE_FLAG(bool, trace_deoptimization_verbose);
 
 class IsolateMessageHandler : public MessageHandler {
  public:
@@ -255,6 +255,61 @@
 #endif
 
 
+void DeferredDouble::Materialize() {
+  RawDouble** double_slot = reinterpret_cast<RawDouble**>(slot());
+  *double_slot = Double::New(value());
+
+  if (FLAG_trace_deoptimization_verbose) {
+    OS::PrintErr("materializing double at %"Px": %g\n",
+                 reinterpret_cast<uword>(slot()), value());
+  }
+}
+
+
+void DeferredMint::Materialize() {
+  RawMint** mint_slot = reinterpret_cast<RawMint**>(slot());
+  ASSERT(!Smi::IsValid64(value()));
+  *mint_slot = Mint::New(value());
+
+  if (FLAG_trace_deoptimization_verbose) {
+    OS::PrintErr("materializing mint at %"Px": %"Pd64"\n",
+                 reinterpret_cast<uword>(slot()), value());
+  }
+}
+
+
+void DeferredFloat32x4::Materialize() {
+  RawFloat32x4** float32x4_slot = reinterpret_cast<RawFloat32x4**>(slot());
+  RawFloat32x4* raw_float32x4 = Float32x4::New(value());
+  *float32x4_slot = raw_float32x4;
+
+  if (FLAG_trace_deoptimization_verbose) {
+    float x = raw_float32x4->x();
+    float y = raw_float32x4->y();
+    float z = raw_float32x4->z();
+    float w = raw_float32x4->w();
+    OS::PrintErr("materializing Float32x4 at %"Px": %g,%g,%g,%g\n",
+                 reinterpret_cast<uword>(slot()), x, y, z, w);
+  }
+}
+
+
+void DeferredUint32x4::Materialize() {
+  RawUint32x4** uint32x4_slot = reinterpret_cast<RawUint32x4**>(slot());
+  RawUint32x4* raw_uint32x4 = Uint32x4::New(value());
+  *uint32x4_slot = raw_uint32x4;
+
+  if (FLAG_trace_deoptimization_verbose) {
+    uint32_t x = raw_uint32x4->x();
+    uint32_t y = raw_uint32x4->y();
+    uint32_t z = raw_uint32x4->z();
+    uint32_t w = raw_uint32x4->w();
+    OS::PrintErr("materializing Uint32x4 at %"Px": %x,%x,%x,%x\n",
+                 reinterpret_cast<uword>(slot()), x, y, z, w);
+  }
+}
+
+
 Isolate::Isolate()
     : store_buffer_block_(),
       store_buffer_(),
@@ -287,8 +342,7 @@
       deopt_fpu_registers_copy_(NULL),
       deopt_frame_copy_(NULL),
       deopt_frame_copy_size_(0),
-      deferred_doubles_(NULL),
-      deferred_mints_(NULL) {
+      deferred_objects_(NULL) {
 }
 
 
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 2e6735f..9dcea6b 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -30,6 +30,7 @@
 class Mutex;
 class ObjectPointerVisitor;
 class ObjectStore;
+class RawInstance;
 class RawArray;
 class RawContext;
 class RawDouble;
@@ -40,47 +41,98 @@
 class StackResource;
 class StackZone;
 class StubCode;
+class RawFloat32x4;
+class RawUint32x4;
 
 
-// Used by the deoptimization infrastructure to defer allocation of Double
+// Used by the deoptimization infrastructure to defer allocation of unboxed
 // objects until frame is fully rewritten and GC is safe.
-// See callers of Isolate::DeferDoubleMaterialization.
-class DeferredDouble {
+// See callers of Isolate::DeferObjectMaterialization.
+class DeferredObject {
  public:
-  DeferredDouble(double value, RawDouble** slot, DeferredDouble* next)
-      : value_(value), slot_(slot), next_(next) { }
+  DeferredObject(RawInstance** slot, DeferredObject* next)
+      : slot_(slot), next_(next) { }
+  virtual ~DeferredObject() { }
+
+  RawInstance** slot() const { return slot_; }
+  DeferredObject* next() const { return next_; }
+
+  virtual void Materialize() = 0;
+
+ private:
+  RawInstance** const slot_;
+  DeferredObject* const next_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeferredObject);
+};
+
+
+class DeferredDouble : public DeferredObject {
+ public:
+  DeferredDouble(double value, RawInstance** slot, DeferredObject* next)
+      : DeferredObject(slot, next), value_(value) { }
+
+  virtual void Materialize();
 
   double value() const { return value_; }
-  RawDouble** slot() const { return slot_; }
-  DeferredDouble* next() const { return next_; }
 
  private:
   const double value_;
-  RawDouble** const slot_;
-  DeferredDouble* const next_;
 
   DISALLOW_COPY_AND_ASSIGN(DeferredDouble);
 };
 
 
-class DeferredMint {
+class DeferredMint : public DeferredObject {
  public:
-  DeferredMint(int64_t value, RawMint** slot, DeferredMint* next)
-      : value_(value), slot_(slot), next_(next) { }
+  DeferredMint(int64_t value, RawInstance** slot, DeferredObject* next)
+      : DeferredObject(slot, next), value_(value) { }
+
+  virtual void Materialize();
 
   int64_t value() const { return value_; }
-  RawMint** slot() const { return slot_; }
-  DeferredMint* next() const { return next_; }
 
  private:
   const int64_t value_;
-  RawMint** const slot_;
-  DeferredMint* const next_;
 
   DISALLOW_COPY_AND_ASSIGN(DeferredMint);
 };
 
 
+class DeferredFloat32x4 : public DeferredObject {
+ public:
+  DeferredFloat32x4(simd128_value_t value, RawInstance** slot,
+                    DeferredObject* next)
+      : DeferredObject(slot, next), value_(value) { }
+
+  virtual void Materialize();
+
+  simd128_value_t value() const { return value_; }
+
+ private:
+  const simd128_value_t value_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeferredFloat32x4);
+};
+
+
+class DeferredUint32x4 : public DeferredObject {
+ public:
+  DeferredUint32x4(simd128_value_t value, RawInstance** slot,
+                   DeferredObject* next)
+      : DeferredObject(slot, next), value_(value) { }
+
+  virtual void Materialize();
+
+  simd128_value_t value() const { return value_; }
+
+ private:
+  const simd128_value_t value_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeferredUint32x4);
+};
+
+
 class Isolate : public BaseIsolate {
  public:
   ~Isolate();
@@ -308,10 +360,10 @@
     ASSERT((value == NULL) || (deopt_cpu_registers_copy_ == NULL));
     deopt_cpu_registers_copy_ = value;
   }
-  double* deopt_fpu_registers_copy() const {
+  fpu_register_t* deopt_fpu_registers_copy() const {
     return deopt_fpu_registers_copy_;
   }
-  void set_deopt_fpu_registers_copy(double* value) {
+  void set_deopt_fpu_registers_copy(fpu_register_t* value) {
     ASSERT((value == NULL) || (deopt_fpu_registers_copy_ == NULL));
     deopt_fpu_registers_copy_ = value;
   }
@@ -325,22 +377,37 @@
   intptr_t deopt_frame_copy_size() const { return deopt_frame_copy_size_; }
 
   void DeferDoubleMaterialization(double value, RawDouble** slot) {
-    deferred_doubles_ = new DeferredDouble(value, slot, deferred_doubles_);
+    deferred_objects_ = new DeferredDouble(
+        value,
+        reinterpret_cast<RawInstance**>(slot),
+        deferred_objects_);
   }
 
   void DeferMintMaterialization(int64_t value, RawMint** slot) {
-    deferred_mints_ = new DeferredMint(value, slot, deferred_mints_);
+    deferred_objects_ = new DeferredMint(value,
+                                         reinterpret_cast<RawInstance**>(slot),
+                                         deferred_objects_);
   }
 
-  DeferredDouble* DetachDeferredDoubles() {
-    DeferredDouble* list = deferred_doubles_;
-    deferred_doubles_ = NULL;
-    return list;
+  void DeferFloat32x4Materialization(simd128_value_t value,
+                                     RawFloat32x4** slot) {
+    deferred_objects_ = new DeferredFloat32x4(
+        value,
+        reinterpret_cast<RawInstance**>(slot),
+        deferred_objects_);
   }
 
-  DeferredMint* DetachDeferredMints() {
-    DeferredMint* list = deferred_mints_;
-    deferred_mints_ = NULL;
+  void DeferUint32x4Materialization(simd128_value_t value,
+                                    RawUint32x4** slot) {
+    deferred_objects_ = new DeferredUint32x4(
+        value,
+        reinterpret_cast<RawInstance**>(slot),
+        deferred_objects_);
+  }
+
+  DeferredObject* DetachDeferredObjects() {
+    DeferredObject* list = deferred_objects_;
+    deferred_objects_ = NULL;
     return list;
   }
 
@@ -385,11 +452,10 @@
 
   // Deoptimization support.
   intptr_t* deopt_cpu_registers_copy_;
-  double* deopt_fpu_registers_copy_;
+  fpu_register_t* deopt_fpu_registers_copy_;
   intptr_t* deopt_frame_copy_;
   intptr_t deopt_frame_copy_size_;
-  DeferredDouble* deferred_doubles_;
-  DeferredMint* deferred_mints_;
+  DeferredObject* deferred_objects_;
 
   static Dart_IsolateCreateCallback create_callback_;
   static Dart_IsolateInterruptCallback interrupt_callback_;
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index 50ef036..58ecdd9 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -105,6 +105,8 @@
     case kFpuRegister: return Assembler::FpuRegisterName(fpu_reg());
     case kStackSlot: return "S";
     case kDoubleStackSlot: return "DS";
+    case kFloat32x4StackSlot: return "F32x4S";
+    case kUint32x4StackSlot: return "UI32x4S";
     case kUnallocated:
       switch (policy()) {
         case kAny:
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index 6a8dda8..24d9fd9 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -14,6 +14,19 @@
 class BufferFormatter;
 class Value;
 
+
+enum Representation {
+  kNoRepresentation,
+  kTagged,
+  kUntagged,
+  kUnboxedDouble,
+  kUnboxedMint,
+  kUnboxedFloat32x4,
+  kUnboxedUint32x4,
+  kNumRepresentations
+};
+
+
 // Location objects are used to connect register allocator and code generator.
 // Instruction templates used by code generator have a corresponding
 // LocationSummary object which specifies expected location for every input
@@ -27,7 +40,7 @@
  private:
   enum {
     // Number of bits required to encode Kind value.
-    kBitsForKind = 3,
+    kBitsForKind = 4,
     kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind,
   };
 
@@ -58,6 +71,8 @@
     // a spill index.
     kStackSlot = 3,
     kDoubleStackSlot = 4,
+    kFloat32x4StackSlot = 8,
+    kUint32x4StackSlot = 10,
 
     // Register location represents a fixed register.  Payload contains
     // register code.
@@ -160,10 +175,10 @@
   }
 
   // Register locations.
-  static Location RegisterLocation(Register reg) {
+  static Location RegisterLocation(Register reg, Representation rep = kTagged) {
     uword payload =
         RegisterField::encode(reg) |
-        RepresentationField::encode(kDouble);  // Unused for Register.
+        RepresentationField::encode(rep);
     return Location(kRegister, payload);
   }
 
@@ -176,15 +191,8 @@
     return RegisterField::decode(payload());
   }
 
-  // FPU registers and double spill slots can contain either doubles
-  // or 64-bit integers.
-  enum Representation {
-    kDouble,
-    kMint
-  };
 
   Representation representation() const {
-    ASSERT(IsFpuRegister() || IsDoubleStackSlot());
     return RepresentationField::decode(payload());
   }
 
@@ -228,14 +236,19 @@
     return static_cast<intptr_t>(RegisterField::decode(payload()));
   }
 
+  static uword make_stack_index_payload(intptr_t stack_index,
+                                        Representation rep) {
+    ASSERT((-kStackIndexBias <= stack_index) &&
+       (stack_index < kStackIndexBias));
+    uword payload =
+      IndexField::encode(static_cast<uword>(kStackIndexBias + stack_index));
+    return payload | RepresentationField::encode(rep);
+  }
+
   // Spill slots.
   static Location StackSlot(intptr_t stack_index,
-                            Representation rep = kDouble) {
-    ASSERT((-kStackIndexBias <= stack_index) &&
-           (stack_index < kStackIndexBias));
-    uword payload =
-        IndexField::encode(static_cast<uword>(kStackIndexBias + stack_index))
-      | RepresentationField::encode(rep);
+                            Representation rep = kTagged) {
+    uword payload = make_stack_index_payload(stack_index, rep);
     Location loc(kStackSlot, payload);
     // Ensure that sign is preserved.
     ASSERT(loc.stack_index() == stack_index);
@@ -247,11 +260,7 @@
   }
 
   static Location DoubleStackSlot(intptr_t stack_index, Representation rep) {
-    ASSERT((-kStackIndexBias <= stack_index) &&
-           (stack_index < kStackIndexBias));
-    uword payload =
-        IndexField::encode(static_cast<uword>(kStackIndexBias + stack_index))
-      | RepresentationField::encode(rep);
+    uword payload = make_stack_index_payload(stack_index, rep);
     Location loc(kDoubleStackSlot, payload);
     // Ensure that sign is preserved.
     ASSERT(loc.stack_index() == stack_index);
@@ -262,9 +271,34 @@
     return kind() == kDoubleStackSlot;
   }
 
+  static Location Float32x4StackSlot(intptr_t stack_index, Representation rep) {
+    uword payload = make_stack_index_payload(stack_index, rep);
+    Location loc(kFloat32x4StackSlot, payload);
+    // Ensure that sign is preserved.
+    ASSERT(loc.stack_index() == stack_index);
+    return loc;
+  }
+
+  bool IsFloat32x4StackSlot() const {
+    return kind() == kFloat32x4StackSlot;
+  }
+
+  static Location Uint32x4StackSlot(intptr_t stack_index, Representation rep) {
+    uword payload = make_stack_index_payload(stack_index, rep);
+    Location loc(kUint32x4StackSlot, payload);
+    // Ensure that sign is preserved.
+    ASSERT(loc.stack_index() == stack_index);
+    return loc;
+  }
+
+  bool IsUint32x4StackSlot() const {
+    return kind() == kUint32x4StackSlot;
+  }
+
 
   intptr_t stack_index() const {
-    ASSERT(IsStackSlot() || IsDoubleStackSlot());
+    ASSERT(IsStackSlot() || IsDoubleStackSlot() || IsFloat32x4StackSlot() ||
+           IsUint32x4StackSlot());
     // Decode stack index manually to preserve sign.
     return IndexField::decode(payload()) - kStackIndexBias;
   }
@@ -310,9 +344,10 @@
   // Layout for kUnallocated locations payload.
   typedef BitField<Policy, 0, 3> PolicyField;
 
-  // Layout for register locations payload. The representation bit is only used
-  // for FpuRegister and unused for Register.
-  static const intptr_t kBitsForRepresentation = 1;
+  // Layout for register locations payload.
+  static const intptr_t kBitsForRepresentation = 3;
+  COMPILE_ASSERT(kNumRepresentations <= (1 << kBitsForRepresentation),
+                 invalid_enum);
   static const intptr_t kBitsForRegister =
       kBitsForPayload - kBitsForRepresentation;
   typedef BitField<Representation,
@@ -325,8 +360,7 @@
                    kBitsForRepresentation,
                    kBitsForRegister> FpuRegisterField;
 
-  // Layout for stack slots. The representation bit is only used for
-  // DoubleStackSlot and unused for StackSlot.
+  // Layout for stack slots.
   static const intptr_t kBitsForIndex =
       kBitsForPayload - kBitsForRepresentation;
   typedef BitField<uword,
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b3c4336..121788b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -251,7 +251,9 @@
           (value == '\b') ||
           (value == '\t') ||
           (value == '\v') ||
-          (value == '\r'));
+          (value == '\r') ||
+          (value == '\\') ||
+          (value == '$'));
 }
 
 
@@ -271,6 +273,10 @@
     return 'v';
   } else if (value == '\r') {
     return 'r';
+  } else if (value == '\\') {
+    return '\\';
+  } else if (value == '$') {
+    return '$';
   }
   UNREACHABLE();
   return '\0';
@@ -3236,7 +3242,18 @@
 
 void Function::SwitchToUnoptimizedCode() const {
   ASSERT(HasOptimizedCode());
+
   const Code& current_code = Code::Handle(CurrentCode());
+
+  // Optimized code object might have been actually fully produced by the
+  // intrinsifier in this case nothing has to be done. In fact an attempt to
+  // patch such code will cause crash.
+  // TODO(vegorov): if intrisifier can fully intrisify the function then we
+  // should not later try to optimize it.
+  if (PcDescriptors::Handle(current_code.pc_descriptors()).Length() == 0) {
+    return;
+  }
+
   if (FLAG_trace_disabling_optimized_code) {
     OS::Print("Disabling optimized code: '%s' entry: %#"Px"\n",
       ToFullyQualifiedCString(),
@@ -4696,6 +4713,9 @@
   result.set_owner(owner);
   result.set_token_pos(token_pos);
   result.set_has_initializer(false);
+  result.set_guarded_cid(kIllegalCid);
+  result.set_is_nullable(false);
+  result.set_dependent_code(Array::Handle());
   return result.raw();
 }
 
@@ -4708,6 +4728,7 @@
   const PatchClass& clone_owner =
       PatchClass::Handle(PatchClass::New(new_owner, owner));
   clone.set_owner(clone_owner);
+  clone.set_dependent_code(Array::Handle());
   if (!clone.is_static()) {
     clone.SetOffset(0);
   }
@@ -4737,6 +4758,137 @@
 }
 
 
+RawArray* Field::dependent_code() const {
+  return raw_ptr()->dependent_code_;
+}
+
+
+void Field::set_dependent_code(const Array& array) const {
+  raw_ptr()->dependent_code_ = array.raw();
+}
+
+
+void Field::RegisterDependentCode(const Code& code) const {
+  const Array& dependent = Array::Handle(dependent_code());
+
+  if (!dependent.IsNull()) {
+    // Try to find and reuse cleared WeakProperty to avoid allocating new one.
+    WeakProperty& weak_property = WeakProperty::Handle();
+    for (intptr_t i = 0; i < dependent.Length(); i++) {
+      weak_property ^= dependent.At(i);
+      if (weak_property.key() == Code::null()) {
+        // Empty property found. Reuse it.
+        weak_property.set_key(code);
+        return;
+      }
+    }
+  }
+
+  const WeakProperty& weak_property = WeakProperty::Handle(
+      WeakProperty::New(Heap::kOld));
+  weak_property.set_key(code);
+
+  intptr_t length = dependent.IsNull() ? 0 : dependent.Length();
+  const Array& new_dependent = Array::Handle(
+      Array::Grow(dependent, length + 1, Heap::kOld));
+  new_dependent.SetAt(length, weak_property);
+  set_dependent_code(new_dependent);
+}
+
+
+static bool IsDependentCode(const Array& dependent_code, const Code& code) {
+  if (!code.is_optimized()) {
+    return false;
+  }
+
+  WeakProperty& weak_property = WeakProperty::Handle();
+  for (intptr_t i = 0; i < dependent_code.Length(); i++) {
+    weak_property ^= dependent_code.At(i);
+    if (code.raw() == weak_property.key()) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+void Field::DeoptimizeDependentCode() const {
+  const Array& code_objects = Array::Handle(dependent_code());
+
+  if (code_objects.IsNull()) {
+    return;
+  }
+  set_dependent_code(Array::Handle());
+
+  // Deoptimize all dependent code on the stack.
+  Code& code = Code::Handle();
+  {
+    DartFrameIterator iterator;
+    StackFrame* frame = iterator.NextFrame();
+    while (frame != NULL) {
+      code = frame->LookupDartCode();
+      if (IsDependentCode(code_objects, code)) {
+        DeoptimizeAt(code, frame->pc());
+      }
+      frame = iterator.NextFrame();
+    }
+  }
+
+  // Switch functions that use dependent code to unoptimized code.
+  WeakProperty& weak_property = WeakProperty::Handle();
+  Function& function = Function::Handle();
+  for (intptr_t i = 0; i < code_objects.Length(); i++) {
+    weak_property ^= code_objects.At(i);
+    code ^= weak_property.key();
+    if (code.IsNull()) {
+      // Code was garbage collected already.
+      continue;
+    }
+
+    function ^= code.function();
+    // If function uses dependent code switch it to unoptimized.
+    if (function.CurrentCode() == code.raw()) {
+      ASSERT(function.HasOptimizedCode());
+      function.SwitchToUnoptimizedCode();
+    }
+  }
+}
+
+
+void Field::UpdateCid(intptr_t cid) const {
+  if (guarded_cid() == kIllegalCid) {
+    // Field is assigned first time.
+    set_guarded_cid(cid);
+    set_is_nullable(cid == kNullCid);
+    return;
+  }
+
+  if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
+    // Class id of the assigned value matches expected class id and nullability.
+    return;
+  }
+
+  if ((cid == kNullCid) && !is_nullable()) {
+    // Assigning null value to a non-nullable field makes it nullable.
+    set_is_nullable(true);
+  } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) {
+    // Assigning non-null value to a field that previously contained only null
+    // turns it into a nullable field with the given class id.
+    ASSERT(is_nullable());
+    set_guarded_cid(cid);
+  } else {
+    // Give up on tracking class id of values contained in this field.
+    ASSERT(guarded_cid() != cid);
+    set_guarded_cid(kDynamicCid);
+    set_is_nullable(true);
+  }
+
+  // Expected class id or nullability of the field changed.
+  DeoptimizeDependentCode();
+}
+
+
 void LiteralToken::set_literal(const String& literal) const {
   StorePointer(&raw_ptr()->literal_, literal.raw());
 }
@@ -4844,37 +4996,17 @@
 
     // Handle the current token.
     if (curr == Token::kSTRING) {
-      bool is_raw_string = false;
       bool escape_characters = false;
       for (intptr_t i = 0; i < literal.Length(); i++) {
         if (IsSpecialCharacter(literal.CharAt(i))) {
           escape_characters = true;
         }
-        // TODO(4995): Temp solution for raw strings, this will break
-        // if we saw a string that is not a raw string but has back slashes
-        // in it.
-        if ((literal.CharAt(i) == '\\')) {
-          if ((next != Token::kINTERPOL_VAR) &&
-              (next != Token::kINTERPOL_START) &&
-              (prev != Token::kINTERPOL_VAR) &&
-              (prev != Token::kINTERPOL_END)) {
-            is_raw_string = true;
-          } else {
-            escape_characters = true;
-          }
-        }
-        if ((literal.CharAt(i) == '$')) {
-          escape_characters = true;
-        }
       }
       if ((prev != Token::kINTERPOL_VAR) && (prev != Token::kINTERPOL_END)) {
-        if (is_raw_string) {
-          literals.Add(Symbols::LowercaseR());
-        }
         literals.Add(Symbols::DoubleQuotes());
       }
       if (escape_characters) {
-        literal = String::EscapeSpecialCharacters(literal, is_raw_string);
+        literal = String::EscapeSpecialCharacters(literal);
         literals.Add(literal);
       } else {
         literals.Add(literal);
@@ -5217,7 +5349,7 @@
 
 
 TokenStream::Iterator::Iterator(const TokenStream& tokens, intptr_t token_pos)
-    : tokens_(tokens),
+    : tokens_(TokenStream::Handle(tokens.raw())),
       data_(ExternalUint8Array::Handle(tokens.GetStream())),
       stream_(data_.ByteAddr(0), data_.Length()),
       token_objects_(Array::Handle(tokens.TokenObjects())),
@@ -5229,6 +5361,20 @@
 }
 
 
+void TokenStream::Iterator::SetStream(const TokenStream& tokens,
+                                      intptr_t token_pos) {
+  tokens_ = tokens.raw();
+  data_ = tokens.GetStream();
+  stream_.SetStream(data_.ByteAddr(0), data_.Length());
+  token_objects_ = tokens.TokenObjects();
+  obj_ = Object::null();
+  cur_token_pos_ = token_pos;
+  cur_token_kind_ = Token::kILLEGAL;
+  cur_token_obj_index_ = -1;
+  SetCurrentPosition(token_pos);
+}
+
+
 bool TokenStream::Iterator::IsValid() const {
   return !tokens_.IsNull();
 }
@@ -7528,6 +7674,13 @@
 
   // Allocate the code object.
   Code& code = Code::ZoneHandle(Code::New(pointer_offsets.length()));
+
+  // Clone the object pool in the old space, if necessary.
+  Array& object_pool = Array::Handle(
+      Array::MakeArray(assembler->object_pool()));
+  if (!object_pool.IsOld()) {
+    object_pool ^= Object::Clone(object_pool, Heap::kOld);
+  }
   {
     NoGCScope no_gc;
 
@@ -7546,7 +7699,7 @@
     code.set_instructions(instrs.raw());
 
     // Set object pool in Instructions object.
-    instrs.set_object_pool(Array::MakeArray(assembler->object_pool()));
+    instrs.set_object_pool(object_pool.raw());
   }
   return code.raw();
 }
@@ -11136,12 +11289,12 @@
 }
 
 
-RawString* String::EscapeSpecialCharacters(const String& str, bool raw_str) {
+RawString* String::EscapeSpecialCharacters(const String& str) {
   if (str.IsOneByteString()) {
-    return OneByteString::EscapeSpecialCharacters(str, raw_str);
+    return OneByteString::EscapeSpecialCharacters(str);
   }
   ASSERT(str.IsTwoByteString());
-  return TwoByteString::EscapeSpecialCharacters(str, raw_str);
+  return TwoByteString::EscapeSpecialCharacters(str);
 }
 
 
@@ -11529,16 +11682,13 @@
 }
 
 
-RawOneByteString* OneByteString::EscapeSpecialCharacters(const String& str,
-                                                         bool raw_str) {
+RawOneByteString* OneByteString::EscapeSpecialCharacters(const String& str) {
   intptr_t len = str.Length();
   if (len > 0) {
     intptr_t num_escapes = 0;
     intptr_t index = 0;
     for (intptr_t i = 0; i < len; i++) {
-      if (IsSpecialCharacter(*CharAddr(str, i)) ||
-          (!raw_str && (*CharAddr(str, i) == '$')) ||
-          (!raw_str && (*CharAddr(str, i) == '\\'))) {
+      if (IsSpecialCharacter(*CharAddr(str, i))) {
         num_escapes += 1;
       }
     }
@@ -11549,14 +11699,6 @@
         *(CharAddr(dststr, index)) = '\\';
         *(CharAddr(dststr, index + 1)) = SpecialCharacter(*CharAddr(str, i));
         index += 2;
-      } else if (!raw_str && (*CharAddr(str, i) == '$')) {
-        *(CharAddr(dststr, index)) = '\\';
-        *(CharAddr(dststr, index + 1)) = '$';
-        index += 2;
-      } else if (!raw_str && (*CharAddr(str, i) == '\\')) {
-        *(CharAddr(dststr, index)) = '\\';
-        *(CharAddr(dststr, index + 1)) = '\\';
-        index += 2;
       } else {
         *(CharAddr(dststr, index)) = *CharAddr(str, i);
         index += 1;
@@ -11718,15 +11860,13 @@
 }
 
 
-RawTwoByteString* TwoByteString::EscapeSpecialCharacters(const String& str,
-                                                         bool raw_str) {
+RawTwoByteString* TwoByteString::EscapeSpecialCharacters(const String& str) {
   intptr_t len = str.Length();
   if (len > 0) {
     intptr_t num_escapes = 0;
     intptr_t index = 0;
     for (intptr_t i = 0; i < len; i++) {
-      if (IsSpecialCharacter(*CharAddr(str, i)) ||
-          (!raw_str && (*CharAddr(str, i) == '\\'))) {
+      if (IsSpecialCharacter(*CharAddr(str, i))) {
         num_escapes += 1;
       }
     }
@@ -11737,10 +11877,6 @@
         *(CharAddr(dststr, index)) = '\\';
         *(CharAddr(dststr, index + 1)) = SpecialCharacter(*CharAddr(str, i));
         index += 2;
-      } else if (!raw_str && (*CharAddr(str, i) == '\\')) {
-        *(CharAddr(dststr, index)) = '\\';
-        *(CharAddr(dststr, index + 1)) = '\\';
-        index += 2;
       } else {
         *(CharAddr(dststr, index)) = *CharAddr(str, i);
         index += 1;
@@ -12218,7 +12354,7 @@
 
 
 RawFloat32x4* Float32x4::New(float v0, float v1, float v2, float v3,
-                                       Heap::Space space) {
+                             Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
          Class::null());
   Float32x4& result = Float32x4::Handle();
@@ -12237,7 +12373,7 @@
 }
 
 
-RawFloat32x4* Float32x4::New(simd_value_t value, Heap::Space space) {
+RawFloat32x4* Float32x4::New(simd128_value_t value, Heap::Space space) {
 ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
          Class::null());
   Float32x4& result = Float32x4::Handle();
@@ -12253,13 +12389,13 @@
 }
 
 
-simd_value_t Float32x4::value() const {
-  return simd_value_safe_load(&raw_ptr()->value_[0]);
+simd128_value_t Float32x4::value() const {
+  return simd128_value_t().readFrom(&raw_ptr()->value_[0]);
 }
 
 
-void Float32x4::set_value(simd_value_t value) const {
-  simd_value_safe_store(&raw_ptr()->value_[0], value);
+void Float32x4::set_value(simd128_value_t value) const {
+  value.writeTo(&raw_ptr()->value_[0]);
 }
 
 
@@ -12337,7 +12473,7 @@
 }
 
 
-RawUint32x4* Uint32x4::New(simd_value_t value, Heap::Space space) {
+RawUint32x4* Uint32x4::New(simd128_value_t value, Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
          Class::null());
   Uint32x4& result = Uint32x4::Handle();
@@ -12393,13 +12529,13 @@
 }
 
 
-simd_value_t Uint32x4::value() const {
-  return simd_value_safe_load(&raw_ptr()->value_[0]);
+simd128_value_t Uint32x4::value() const {
+  return simd128_value_t().readFrom(&raw_ptr()->value_[0]);
 }
 
 
-void Uint32x4::set_value(simd_value_t value) const {
-  simd_value_safe_store(&raw_ptr()->value_[0], value);
+void Uint32x4::set_value(simd128_value_t value) const {
+  value.writeTo(&raw_ptr()->value_[0]);
 }
 
 
@@ -12869,7 +13005,7 @@
 
 
 RawFloat32x4Array* Float32x4Array::New(intptr_t len,
-                                                 Heap::Space space) {
+                                       Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->float32x4_array_class() !=
          Class::null());
   return NewImpl<Float32x4Array, RawFloat32x4Array>(kClassId, len,
@@ -12877,9 +13013,9 @@
 }
 
 
-RawFloat32x4Array* Float32x4Array::New(const simd_value_t* data,
-                                                 intptr_t len,
-                                                 Heap::Space space) {
+RawFloat32x4Array* Float32x4Array::New(const simd128_value_t* data,
+                                       intptr_t len,
+                                       Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->float32_array_class() !=
          Class::null());
   return NewImpl<Float32x4Array, RawFloat32x4Array>(kClassId, data,
@@ -13072,16 +13208,15 @@
 }
 
 
-RawExternalFloat32x4Array* ExternalFloat32x4Array::New(
-    simd_value_t* data,
-    intptr_t len,
-    Heap::Space space) {
+RawExternalFloat32x4Array* ExternalFloat32x4Array::New(simd128_value_t* data,
+                                                       intptr_t len,
+                                                       Heap::Space space) {
   RawClass* cls =
      Isolate::Current()->object_store()->external_float32x4_array_class();
   ASSERT(cls != Class::null());
   return NewExternalImpl<ExternalFloat32x4Array,
                          RawExternalFloat32x4Array>(kClassId, data, len,
-                                                         space);
+                                                    space);
 }
 
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 11a369e..21b5fec 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1775,6 +1775,49 @@
                                             raw_ptr()->kind_bits_));
   }
 
+  // Return class id that any non-null value read from this field is guaranteed
+  // to have or kDynamicCid if such class id is not known.
+  // Stores to this field must update this information hence the name.
+  intptr_t guarded_cid() const { return raw_ptr()->guarded_cid_; }
+  void set_guarded_cid(intptr_t cid) const {
+    raw_ptr()->guarded_cid_ = cid;
+  }
+  static intptr_t guarded_cid_offset() {
+    return OFFSET_OF(RawField, guarded_cid_);
+  }
+
+  // Returns false if any value read from this field is guaranteed to be
+  // not null.
+  // Internally we is_nullable_ field contains either kNullCid (nullable) or
+  // any other value (non-nullable) instead of boolean. This is done to simplify
+  // guarding sequence in the generated code.
+  bool is_nullable() const {
+    return raw_ptr()->is_nullable_ == kNullCid;
+  }
+  void set_is_nullable(bool val) const {
+    raw_ptr()->is_nullable_ = val ? kNullCid : kIllegalCid;
+  }
+  static intptr_t is_nullable_offset() {
+    return OFFSET_OF(RawField, is_nullable_);
+  }
+
+  // Update guarded class id and nullability of the field to reflect assignment
+  // of the value with the given class id to this field.
+  void UpdateCid(intptr_t cid) const;
+
+  // Return the list of optimized code objects that were optimized under
+  // assumptions about guarded class id and nullability of this field.
+  // These code objects must be deoptimized when field's properties change.
+  // Code objects are held weakly via an indirection through WeakProperty.
+  RawArray* dependent_code() const;
+  void set_dependent_code(const Array& array) const;
+
+  // Add the given code object to the list of dependent ones.
+  void RegisterDependentCode(const Code& code) const;
+
+  // Deoptimize all dependent code objects.
+  void DeoptimizeDependentCode() const;
+
   // Constructs getter and setter names for fields and vice versa.
   static RawString* GetterName(const String& field_name);
   static RawString* GetterSymbol(const String& field_name);
@@ -1878,6 +1921,7 @@
    public:
     Iterator(const TokenStream& tokens, intptr_t token_pos);
 
+    void SetStream(const TokenStream& tokens, intptr_t token_pos);
     bool IsValid() const;
 
     inline Token::Kind CurrentTokenKind() const {
@@ -1904,8 +1948,8 @@
       return static_cast<intptr_t>(value);
     }
 
-    const TokenStream& tokens_;
-    const ExternalUint8Array& data_;
+    TokenStream& tokens_;
+    ExternalUint8Array& data_;
     ReadStream stream_;
     Array& token_objects_;
     Object& obj_;
@@ -2281,6 +2325,7 @@
     raw_ptr()->code_ = code;
   }
   void set_object_pool(RawArray* object_pool) const {
+    ASSERT(object_pool->IsOldObject());
     raw_ptr()->object_pool_ = object_pool;
   }
 
@@ -4263,7 +4308,7 @@
                    intptr_t src_offset,
                    intptr_t len);
 
-  static RawString* EscapeSpecialCharacters(const String& str, bool raw_str);
+  static RawString* EscapeSpecialCharacters(const String& str);
 
   static RawString* Concat(const String& str1,
                            const String& str2,
@@ -4338,8 +4383,7 @@
     return *CharAddr(str, index);
   }
 
-  static RawOneByteString* EscapeSpecialCharacters(const String& str,
-                                                   bool raw_str);
+  static RawOneByteString* EscapeSpecialCharacters(const String& str);
 
   // We use the same maximum elements for all strings.
   static const intptr_t kBytesPerElement = 1;
@@ -4441,8 +4485,7 @@
     return *CharAddr(str, index);
   }
 
-  static RawTwoByteString* EscapeSpecialCharacters(const String& str,
-                                                   bool raw_str);
+  static RawTwoByteString* EscapeSpecialCharacters(const String& str);
 
   // We use the same maximum elements for all strings.
   static const intptr_t kBytesPerElement = 2;
@@ -4694,6 +4737,9 @@
   }
   static intptr_t length_offset() { return OFFSET_OF(RawArray, length_); }
   static intptr_t data_offset() { return length_offset() + kWordSize; }
+  static intptr_t element_offset(intptr_t index) {
+    return data_offset() + kWordSize * index;
+  }
 
   RawObject* At(intptr_t index) const {
     return *ObjectAddr(index);
@@ -4900,7 +4946,8 @@
  public:
   static RawFloat32x4* New(float value0, float value1, float value2,
                            float value3, Heap::Space space = Heap::kNew);
-  static RawFloat32x4* New(simd_value_t value, Heap::Space space = Heap::kNew);
+  static RawFloat32x4* New(simd128_value_t value,
+                           Heap::Space space = Heap::kNew);
 
   float x() const;
   float y() const;
@@ -4912,8 +4959,8 @@
   void set_z(float z) const;
   void set_w(float w) const;
 
-  simd_value_t value() const;
-  void set_value(simd_value_t value) const;
+  simd128_value_t value() const;
+  void set_value(simd128_value_t value) const;
 
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawFloat32x4));
@@ -4933,7 +4980,8 @@
  public:
   static RawUint32x4* New(uint32_t value0, uint32_t value1, uint32_t value2,
                           uint32_t value3, Heap::Space space = Heap::kNew);
-  static RawUint32x4* New(simd_value_t value, Heap::Space space = Heap::kNew);
+  static RawUint32x4* New(simd128_value_t value,
+                          Heap::Space space = Heap::kNew);
 
   uint32_t x() const;
   uint32_t y() const;
@@ -4945,8 +4993,8 @@
   void set_z(uint32_t z) const;
   void set_w(uint32_t w) const;
 
-  simd_value_t value() const;
-  void set_value(simd_value_t value) const;
+  simd128_value_t value() const;
+  void set_value(simd128_value_t value) const;
 
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawUint32x4));
@@ -5699,16 +5747,14 @@
     return Length() * kBytesPerElement;
   }
 
-  simd_value_t At(intptr_t index) const {
+  simd128_value_t At(intptr_t index) const {
     ASSERT((index >= 0) && (index < Length()));
-    simd_value_t* load_ptr = &raw_ptr()->data_[index];
-    return simd_value_safe_load(load_ptr);
+    return raw_ptr()->data_[index];
   }
 
-  void SetAt(intptr_t index, simd_value_t value) const {
+  void SetAt(intptr_t index, simd128_value_t value) const {
     ASSERT((index >= 0) && (index < Length()));
-    simd_value_t* store_ptr = &raw_ptr()->data_[index];
-    simd_value_safe_store(store_ptr, value);
+    raw_ptr()->data_[index] = value;
   }
 
   static const intptr_t kBytesPerElement = 16;
@@ -5732,7 +5778,7 @@
 
   static RawFloat32x4Array* New(intptr_t len,
                                      Heap::Space space = Heap::kNew);
-  static RawFloat32x4Array* New(const simd_value_t* data,
+  static RawFloat32x4Array* New(const simd128_value_t* data,
                                      intptr_t len,
                                      Heap::Space space = Heap::kNew);
 
@@ -6353,20 +6399,18 @@
     return Length() * kBytesPerElement;
   }
 
-  simd_value_t At(intptr_t index) const {
+  simd128_value_t At(intptr_t index) const {
     ASSERT((index >= 0) && (index < Length()));
-    simd_value_t* load_ptr = &raw_ptr()->data_[index];
-    return simd_value_safe_load(load_ptr);
+    return raw_ptr()->data_[index];
   }
 
-  void SetAt(intptr_t index, simd_value_t value) const {
+  void SetAt(intptr_t index, simd128_value_t value) const {
     ASSERT((index >= 0) && (index < Length()));
-    simd_value_t* store_ptr = &raw_ptr()->data_[index];
-    simd_value_safe_store(store_ptr, value);
+    raw_ptr()->data_[index] = value;
   }
 
 
-  simd_value_t* GetData() const {
+  simd128_value_t* GetData() const {
     return raw_ptr()->data_;
   }
 
@@ -6384,9 +6428,8 @@
     return RoundedAllocationSize(sizeof(RawExternalFloat32x4Array));
   }
 
-  static RawExternalFloat32x4Array* New(simd_value_t* data,
-                                             intptr_t len,
-                                             Heap::Space space = Heap::kNew);
+  static RawExternalFloat32x4Array* New(simd128_value_t* data, intptr_t len,
+                                        Heap::Space space = Heap::kNew);
 
  private:
   uint8_t* ByteAddr(intptr_t byte_offset) const {
@@ -6395,7 +6438,7 @@
     return data + byte_offset;
   }
 
-  void SetData(simd_value_t* data) const {
+  void SetData(simd128_value_t* data) const {
     raw_ptr()->data_ = data;
   }
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 06772b9..9908873 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -261,7 +261,7 @@
 
 // For parsing a compilation unit.
 Parser::Parser(const Script& script, const Library& library)
-    : script_(script),
+    : script_(Script::Handle(script.raw())),
       tokens_iterator_(TokenStream::Handle(script.tokens()), 0),
       token_kind_(Token::kILLEGAL),
       current_block_(NULL),
@@ -271,7 +271,7 @@
       parsed_function_(NULL),
       innermost_function_(Function::Handle()),
       current_class_(Class::Handle()),
-      library_(library),
+      library_(Library::Handle(library.raw())),
       try_blocks_list_(NULL) {
   ASSERT(tokens_iterator_.IsValid());
   ASSERT(!library.IsNull());
@@ -282,7 +282,7 @@
 Parser::Parser(const Script& script,
                ParsedFunction* parsed_function,
                intptr_t token_position)
-    : script_(script),
+    : script_(Script::Handle(script.raw())),
       tokens_iterator_(TokenStream::Handle(script.tokens()), token_position),
       token_kind_(Token::kILLEGAL),
       current_block_(NULL),
@@ -303,6 +303,13 @@
 }
 
 
+void Parser::SetScript(const Script & script, intptr_t token_pos) {
+  script_ = script.raw();
+  tokens_iterator_.SetStream(TokenStream::Handle(script.tokens()), token_pos);
+  token_kind_ = Token::kILLEGAL;
+}
+
+
 bool Parser::SetAllowFunctionLiterals(bool value) {
   bool current_value = allow_function_literals_;
   allow_function_literals_ = value;
@@ -987,9 +994,9 @@
   LoadLocalNode* value =
       new LoadLocalNode(ident_pos, current_block_->scope->VariableAt(1));
 
+  EnsureExpressionTemp();
   StoreInstanceFieldNode* store_field =
       new StoreInstanceFieldNode(ident_pos, receiver, field, value);
-
   current_block_->statements->Add(store_field);
   current_block_->statements->Add(new ReturnNode(ident_pos));
   return CloseBlock();
@@ -1791,6 +1798,7 @@
   }
   CheckDuplicateFieldInit(field_pos, initialized_fields, &field);
   AstNode* instance = new LoadLocalNode(field_pos, receiver);
+  EnsureExpressionTemp();
   return new StoreInstanceFieldNode(field_pos, instance, field, init_expr);
 }
 
@@ -1801,9 +1809,10 @@
   SequenceNode* initializers = current_block_->statements;
   for (int field_num = 0; field_num < fields.Length(); field_num++) {
     field ^= fields.At(field_num);
-    if (field.is_static() || !field.is_final()) {
+    if (field.is_static()) {
       continue;
     }
+
     bool found = false;
     for (int i = 0; i < initializers->length(); i++) {
       found = false;
@@ -1816,14 +1825,53 @@
         }
       }
     }
-    if (!found) {
+
+    if (found) continue;
+
+    if (field.is_final()) {
       ErrorMsg("final field '%s' not initialized",
                String::Handle(field.name()).ToCString());
+    } else {
+      field.UpdateCid(kNullCid);
     }
   }
 }
 
 
+AstNode* Parser::ParseExternalInitializedField(const Field& field) {
+  // Only use this function if the initialized field originates
+  // from a different class. We need to save and restore current
+  // class, library, and token stream (script).
+  ASSERT(current_class().raw() != field.origin());
+  const Class& saved_class = Class::Handle(current_class().raw());
+  const Library& saved_library = Library::Handle(library().raw());
+  const Script& saved_script = Script::Handle(script().raw());
+  const intptr_t saved_token_pos = TokenPos();
+
+  set_current_class(Class::Handle(field.origin()));
+  set_library(Library::Handle(current_class().library()));
+  SetScript(Script::Handle(current_class().script()), field.token_pos());
+
+  ASSERT(IsIdentifier());
+  ConsumeToken();
+  ExpectToken(Token::kASSIGN);
+  AstNode* init_expr = NULL;
+  if (field.is_const()) {
+    init_expr = ParseConstExpr();
+  } else {
+    init_expr = ParseExpr(kAllowConst, kConsumeCascades);
+    if (init_expr->EvalConstExpr() != NULL) {
+      init_expr =
+          new LiteralNode(field.token_pos(), EvaluateConstExpr(init_expr));
+    }
+  }
+  set_current_class(saved_class);
+  set_library(saved_library);
+  SetScript(saved_script, saved_token_pos);
+  return init_expr;
+}
+
+
 void Parser::ParseInitializedInstanceFields(const Class& cls,
                  LocalVariable* receiver,
                  GrowableArray<Field*>* initialized_fields) {
@@ -1842,30 +1890,27 @@
         // initialized.
         initialized_fields->Add(&field);
       }
-      intptr_t field_pos = field.token_pos();
-      if (current_class().raw() != field.origin()) {
-        const Class& origin_class = Class::Handle(field.origin());
-        if (origin_class.library() != library_.raw()) {
-          ErrorMsg("Cannot handle initialized mixin field '%s'"
-                   "from imported library\n", field.ToCString());
-        }
-      }
-      SetPosition(field_pos);
-      ASSERT(IsIdentifier());
-      ConsumeToken();
-      ExpectToken(Token::kASSIGN);
-
       AstNode* init_expr = NULL;
-      if (field.is_const()) {
-        init_expr = ParseConstExpr();
+      if (current_class().raw() != field.origin()) {
+        init_expr = ParseExternalInitializedField(field);
       } else {
-        init_expr = ParseExpr(kAllowConst, kConsumeCascades);
-        if (init_expr->EvalConstExpr() != NULL) {
-          init_expr = new LiteralNode(field_pos, EvaluateConstExpr(init_expr));
+        SetPosition(field.token_pos());
+        ASSERT(IsIdentifier());
+        ConsumeToken();
+        ExpectToken(Token::kASSIGN);
+        if (field.is_const()) {
+          init_expr = ParseConstExpr();
+        } else {
+          init_expr = ParseExpr(kAllowConst, kConsumeCascades);
+          if (init_expr->EvalConstExpr() != NULL) {
+            init_expr = new LiteralNode(field.token_pos(),
+                                        EvaluateConstExpr(init_expr));
+          }
         }
       }
       ASSERT(init_expr != NULL);
       AstNode* instance = new LoadLocalNode(field.token_pos(), receiver);
+      EnsureExpressionTemp();
       AstNode* field_init =
           new StoreInstanceFieldNode(field.token_pos(),
                                      instance,
@@ -2118,6 +2163,7 @@
         // Thus, make the parameter invisible.
         p->set_invisible(true);
         AstNode* value = new LoadLocalNode(param.name_pos, p);
+        EnsureExpressionTemp();
         AstNode* initializer = new StoreInstanceFieldNode(
             param.name_pos, instance, field, value);
         current_block_->statements->Add(initializer);
@@ -3266,10 +3312,7 @@
   cls.set_super_type(super_type);
 
   if (CurrentToken() == Token::kIMPLEMENTS) {
-    Array& interfaces = Array::Handle();
-    const intptr_t interfaces_pos = TokenPos();
-    interfaces = ParseInterfaceList(super_type);
-    AddInterfaces(interfaces_pos, cls, interfaces);
+    ParseInterfaceList(cls);
   }
 
   ExpectToken(Token::kLBRACE);
@@ -3442,10 +3485,7 @@
 
   AddImplicitConstructor(mixin_application);
   if (CurrentToken() == Token::kIMPLEMENTS) {
-    Array& interfaces = Array::Handle();
-    const intptr_t interfaces_pos = TokenPos();
-    interfaces = ParseInterfaceList(type);
-    AddInterfaces(interfaces_pos, mixin_application, interfaces);
+    ParseInterfaceList(mixin_application);
   }
   ExpectSemicolon();
   pending_classes.Add(mixin_application, Heap::kOld);
@@ -3779,40 +3819,33 @@
 }
 
 
-// Parse and return an array of interface types.
-RawArray* Parser::ParseInterfaceList(const AbstractType& super_type) {
+// Parse interface list and add to class cls.
+void Parser::ParseInterfaceList(const Class& cls) {
   TRACE_PARSER("ParseInterfaceList");
   ASSERT(CurrentToken() == Token::kIMPLEMENTS);
-  const GrowableObjectArray& interfaces =
+  const GrowableObjectArray& all_interfaces =
       GrowableObjectArray::Handle(GrowableObjectArray::New());
-  String& interface_name = String::Handle();
   AbstractType& interface = AbstractType::Handle();
-  String& other_name = String::Handle();
-  AbstractType& other_interface = AbstractType::Handle();
-  const String& super_type_name = String::Handle(super_type.Name());
+  // First get all the interfaces already implemented by class.
+  Array& cls_interfaces = Array::Handle(cls.interfaces());
+  for (intptr_t i = 0; i < cls_interfaces.Length(); i++) {
+    interface ^= cls_interfaces.At(i);
+    all_interfaces.Add(interface);
+  }
+  // Now parse and add the new interfaces.
   do {
     ConsumeToken();
     intptr_t interface_pos = TokenPos();
     interface = ParseType(ClassFinalizer::kTryResolve);
-    interface_name = interface.UserVisibleName();
-    if (interface_name.Equals(super_type_name)) {
-      // TODO(hausner): I think this check is not necessary. There is
-      // no such restriction. If the check is removed, the 'super_type'
-      // parameter to this function can be eliminated.
-      ErrorMsg(interface_pos, "class may not extend and implement '%s'",
-               interface_name.ToCString());
+    if (interface.IsTypeParameter()) {
+      ErrorMsg(interface_pos,
+               "type parameter '%s' may not be used in interface list",
+               String::Handle(interface.UserVisibleName()).ToCString());
     }
-    for (int i = 0; i < interfaces.Length(); i++) {
-      other_interface ^= interfaces.At(i);
-      other_name = other_interface.Name();
-      if (interface_name.Equals(other_name)) {
-        ErrorMsg(interface_pos, "duplicate interface '%s'",
-                 interface_name.ToCString());
-      }
-    }
-    interfaces.Add(interface);
+    all_interfaces.Add(interface);
   } while (CurrentToken() == Token::kCOMMA);
-  return Array::MakeArray(interfaces);
+  cls_interfaces = Array::MakeArray(all_interfaces);
+  cls.set_interfaces(cls_interfaces);
 }
 
 
@@ -3880,55 +3913,6 @@
 }
 
 
-// Add 'interface' to 'interface_list' if it is not already in the list.
-// An error is reported if the interface conflicts with an interface already in
-// the list with the same class and same type arguments.
-void Parser::AddInterfaceIfUnique(intptr_t interfaces_pos,
-                                  const GrowableObjectArray& interface_list,
-                                  const AbstractType& interface) {
-  String& interface_name = String::Handle(interface.Name());
-  String& existing_interface_name = String::Handle();
-  AbstractType& other_interface = AbstractType::Handle();
-  for (intptr_t i = 0; i < interface_list.Length(); i++) {
-    other_interface ^= interface_list.At(i);
-    existing_interface_name = other_interface.Name();
-    if (interface_name.Equals(existing_interface_name)) {
-      return;
-    }
-  }
-  interface_list.Add(interface);
-}
-
-
-void Parser::AddInterfaces(intptr_t interfaces_pos,
-                           const Class& cls,
-                           const Array& interfaces) {
-  const GrowableObjectArray& all_interfaces =
-      GrowableObjectArray::Handle(GrowableObjectArray::New());
-  AbstractType& interface = AbstractType::Handle();
-  // First get all the interfaces already implemented by class.
-  Array& cls_interfaces = Array::Handle(cls.interfaces());
-  for (intptr_t i = 0; i < cls_interfaces.Length(); i++) {
-    interface ^= cls_interfaces.At(i);
-    all_interfaces.Add(interface);
-  }
-  // Now add the new interfaces.
-  for (intptr_t i = 0; i < interfaces.Length(); i++) {
-    AbstractType& interface = AbstractType::ZoneHandle();
-    interface ^= interfaces.At(i);
-    if (interface.IsTypeParameter()) {
-      ErrorMsg(interfaces_pos,
-               "class '%s' may not implement type parameter '%s'",
-               String::Handle(cls.Name()).ToCString(),
-               String::Handle(interface.UserVisibleName()).ToCString());
-    }
-    AddInterfaceIfUnique(interfaces_pos, all_interfaces, interface);
-  }
-  cls_interfaces = Array::MakeArray(all_interfaces);
-  cls.set_interfaces(cls_interfaces);
-}
-
-
 void Parser::ParseTopLevelVariable(TopLevel* top_level) {
   TRACE_PARSER("ParseTopLevelVariable");
   const bool is_const = (CurrentToken() == Token::kCONST);
@@ -9944,8 +9928,14 @@
 
 void Parser::SkipSelectors() {
   while (true) {
-    if ((CurrentToken() == Token::kPERIOD) ||
-        (CurrentToken() == Token::kCASCADE)) {
+    if (CurrentToken() == Token::kCASCADE) {
+      ConsumeToken();
+      if (CurrentToken() == Token::kLBRACK) {
+        continue;  // Consume [ in next loop iteration.
+      } else {
+        ExpectIdentifier("identifier or [ expected after ..");
+      }
+    } else if (CurrentToken() == Token::kPERIOD) {
       ConsumeToken();
       ExpectIdentifier("identifier expected");
     } else if (CurrentToken() == Token::kLBRACK) {
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index d1a175e..732cb8c 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -221,6 +221,12 @@
     return parsed_function_;
   }
 
+  const Script& script() const { return script_; }
+  void SetScript(const Script& script, intptr_t token_pos);
+
+  const Library& library() const { return library_; }
+  void set_library(const Library& value) const { library_ = value.raw(); }
+
   // Parsing a library or a regular source script.
   bool is_library_source() const {
     return (script_.kind() == RawScript::kScriptTag) ||
@@ -368,6 +374,7 @@
   void CheckConstFieldsInitialized(const Class& cls);
   void AddImplicitConstructor(const Class& cls);
   void CheckConstructors(ClassDesc* members);
+  AstNode* ParseExternalInitializedField(const Field& field);
   void ParseInitializedInstanceFields(
       const Class& cls,
       LocalVariable* receiver,
@@ -386,14 +393,8 @@
                          LocalVariable* receiver,
                          GrowableArray<Field*>* initialized_fields);
   String& ParseNativeDeclaration();
-  RawArray* ParseInterfaceList(const AbstractType& super_type);
+  void ParseInterfaceList(const Class& cls);
   RawAbstractType* ParseMixins(const AbstractType& super_type);
-  void AddInterfaceIfUnique(intptr_t interfaces_pos,
-                            const GrowableObjectArray& interface_list,
-                            const AbstractType& interface);
-  void AddInterfaces(intptr_t interfaces_pos,
-                     const Class& cls,
-                     const Array& interfaces);
   StaticCallNode* BuildInvocationMirrorAllocation(
       intptr_t call_pos,
       const String& function_name,
@@ -633,7 +634,7 @@
 
   LocalVariable* BuildArrayTempLocal(intptr_t token_pos);
 
-  const Script& script_;
+  Script& script_;
   TokenStream::Iterator tokens_iterator_;
   Token::Kind token_kind_;  // Cached token kind for current token.
   Block* current_block_;
@@ -665,7 +666,7 @@
   // When parsing a function, this is the library in which the function
   // is defined. This can be the library in which the current_class_ is
   // defined, or the library of a mixin class where the function originates.
-  const Library& library_;
+  Library& library_;
 
   // List of try blocks seen so far, this is used to generate inlined finally
   // code at all points in the try block where an exit from the block is
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 82ba994..c8cb774 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -669,9 +669,15 @@
                       // where this field is defined.
   RawAbstractType* type_;
   RawInstance* value_;  // Offset in words for instance and value for static.
-  RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->value_); }
+  RawArray* dependent_code_;
+  RawObject** to() {
+    return reinterpret_cast<RawObject**>(&ptr()->dependent_code_);
+  }
 
   intptr_t token_pos_;
+  intptr_t guarded_cid_;
+  intptr_t is_nullable_;  // kNullCid if field can contain null value and
+                          // any other value otherwise.
   uint8_t kind_bits_;  // static, final, const, has initializer.
 };
 
@@ -1383,6 +1389,11 @@
   float value_[4];
 
   friend class SnapshotReader;
+ public:
+  float x() const { return value_[0]; }
+  float y() const { return value_[1]; }
+  float z() const { return value_[2]; }
+  float w() const { return value_[3]; }
 };
 
 
@@ -1392,6 +1403,11 @@
   uint32_t value_[4];
 
   friend class SnapshotReader;
+ public:
+  uint32_t x() const { return value_[0]; }
+  uint32_t y() const { return value_[1]; }
+  uint32_t z() const { return value_[2]; }
+  uint32_t w() const { return value_[3]; }
 };
 
 
@@ -1525,7 +1541,7 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(Float32x4Array);
 
   // Variable length data follows here.
-  simd_value_t data_[0];
+  simd128_value_t data_[0];
 };
 
 class RawFloat32Array : public RawByteArray {
@@ -1620,7 +1636,7 @@
 class RawExternalFloat32x4Array : public RawByteArray {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32x4Array);
 
-  simd_value_t* data_;
+  simd128_value_t* data_;
   void* peer_;
 };
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index dcecda6..6d39757 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -785,6 +785,8 @@
 
   // Set all non object fields.
   field.set_token_pos(reader->ReadIntptrValue());
+  field.set_guarded_cid(reader->ReadIntptrValue());
+  field.set_is_nullable(reader->ReadIntptrValue());
   field.set_kind_bits(reader->Read<uint8_t>());
 
   // Set all the object fields.
@@ -815,6 +817,8 @@
 
   // Write out all the non object fields.
   writer->WriteIntptrValue(ptr()->token_pos_);
+  writer->WriteIntptrValue(ptr()->guarded_cid_);
+  writer->WriteIntptrValue(ptr()->is_nullable_);
   writer->Write<uint8_t>(ptr()->kind_bits_);
 
   // Write out all the object pointer fields.
@@ -2261,13 +2265,13 @@
   result.set_tags(tags);
 
   // Setup the array elements.
-  float v[4];
+  simd128_value_t v;
   for (intptr_t i = 0; i < len; ++i) {
-    v[0] = reader->Read<float>();
-    v[1] = reader->Read<float>();
-    v[2] = reader->Read<float>();
-    v[3] = reader->Read<float>();
-    result.SetAt(i, simd_value_safe_load(&v[0]));
+    v.storage[0] = reader->Read<float>();
+    v.storage[1] = reader->Read<float>();
+    v.storage[2] = reader->Read<float>();
+    v.storage[3] = reader->Read<float>();
+    result.SetAt(i, v);
   }
   return result.raw();
 }
@@ -2293,7 +2297,7 @@
 }                                                                              \
 
 BYTEARRAY_TYPE_LIST(EXTERNALARRAY_READ_FROM)
-EXTERNALARRAY_READ_FROM(Float32x4, Float32x4, simd_value_t)
+EXTERNALARRAY_READ_FROM(Float32x4, Float32x4, simd128_value_t)
 #undef EXTERNALARRAY_READ_FROM
 
 
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index 3b90a0d..79470e2 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -319,7 +319,9 @@
 
   // Allocate the virtual memory for this scavenge heap.
   space_ = VirtualMemory::Reserve(max_capacity);
-  ASSERT(space_ != NULL);
+  if (space_ == NULL) {
+    FATAL("Out of memory.\n");
+  }
 
   // Allocate the entire space at the beginning.
   space_->Commit(false);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 232a69d..be561d0 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -95,6 +95,7 @@
 
   void Stop(Instr* instr, const char* message);
   void Debug();
+
   char* ReadLine(const char* prompt);
 
  private:
@@ -293,7 +294,6 @@
 void SimulatorDebugger::Debug() {
   intptr_t last_pc = -1;
   bool done = false;
-  bool decoded = true;
 
 #define COMMAND_SIZE 63
 #define ARG_SIZE 255
@@ -317,11 +317,11 @@
   while (!done) {
     if (last_pc != sim_->get_pc()) {
       last_pc = sim_->get_pc();
-      decoded = Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+      Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
     }
     char* line = ReadLine("sim> ");
     if (line == NULL) {
-      break;
+      FATAL("ReadLine failed");
     } else {
       // Use sscanf to parse the individual parts of the command line. At the
       // moment no command expects more than two parameters.
@@ -353,20 +353,12 @@
         OS::Print("Quitting\n");
         OS::Exit(0);
       } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
-        if (decoded) {
-          sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
-        } else {
-          OS::Print("Instruction could not be decoded. Stepping disabled.\n");
-        }
+        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
-        if (decoded) {
-          // Execute the one instruction we broke at with breakpoints disabled.
-          sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
-          // Leave the debugger shell.
-          done = true;
-        } else {
-          OS::Print("Instruction could not be decoded. Cannot continue.\n");
-        }
+        // Execute the one instruction we broke at with breakpoints disabled.
+        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
+        // Leave the debugger shell.
+        done = true;
       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
         if (args == 2) {
           uint32_t value;
@@ -845,6 +837,15 @@
 }
 
 
+void Simulator::UnimplementedInstruction(Instr* instr) {
+  char buffer[64];
+  snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr);
+  SimulatorDebugger dbg(this);
+  dbg.Stop(instr, buffer);
+  FATAL("Cannot continue execution after unimplemented instruction.");
+}
+
+
 int Simulator::ReadW(uword addr, Instr* instr) {
   static StatsCounter counter_read_w("Simulated word reads");
   counter_read_w.Increment();
@@ -1086,8 +1087,7 @@
   if (instr->Bit(4) == 0) {
     // by immediate
     if ((shift == ROR) && (shift_amount == 0)) {
-      UNIMPLEMENTED();
-      return result;
+      UnimplementedInstruction(instr);
     } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
       shift_amount = 32;
     }
@@ -1135,7 +1135,7 @@
       }
 
       case ROR: {
-        UNIMPLEMENTED();
+        UnimplementedInstruction(instr);
         break;
       }
 
@@ -1207,7 +1207,7 @@
       }
 
       case ROR: {
-        UNIMPLEMENTED();
+        UnimplementedInstruction(instr);
         break;
       }
 
@@ -1474,12 +1474,12 @@
             dbg.Stop(instr, buffer);
           } else {
              // Format(instr, "smc'cond");
-            UNIMPLEMENTED();
+            UnimplementedInstruction(instr);
           }
           break;
         }
         default: {
-          UNIMPLEMENTED();
+          UnimplementedInstruction(instr);
           break;
         }
       }
@@ -1539,7 +1539,7 @@
             break;
           }
           default: {
-            UNIMPLEMENTED();
+            UnimplementedInstruction(instr);
             break;
           }
         }
@@ -1569,7 +1569,7 @@
             break;
           }
           default: {
-            UNIMPLEMENTED();
+            UnimplementedInstruction(instr);
             break;
           }
         }
@@ -1594,12 +1594,12 @@
           if ((instr->Bits(16, 4) == 0) && (instr->Bits(0, 8) == 0)) {
             // Format(instr, "nop'cond");
           } else {
-            UNIMPLEMENTED();
+            UnimplementedInstruction(instr);
           }
           break;
         }
         default: {
-          UNIMPLEMENTED();
+          UnimplementedInstruction(instr);
           break;
         }
       }
@@ -1727,7 +1727,7 @@
             set_register(rd1, val_high);
           }
         } else {
-          UNIMPLEMENTED();
+          UnimplementedInstruction(instr);
         }
       }
     }
@@ -1856,7 +1856,7 @@
           SetNZFlags(alu_out);
           SetCFlag(shifter_carry_out);
         } else {
-          UNIMPLEMENTED();
+          UnimplementedInstruction(instr);
         }
         break;
       }
@@ -1869,7 +1869,7 @@
           SetNZFlags(alu_out);
           SetCFlag(shifter_carry_out);
         } else {
-          UNIMPLEMENTED();
+          UnimplementedInstruction(instr);
         }
         break;
       }
@@ -1883,7 +1883,7 @@
           SetCFlag(!BorrowFrom(rn_val, shifter_operand));
           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
         } else {
-          UNIMPLEMENTED();
+          UnimplementedInstruction(instr);
         }
         break;
       }
@@ -1897,7 +1897,7 @@
           SetCFlag(CarryFrom(rn_val, shifter_operand));
           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
         } else {
-          UNIMPLEMENTED();
+          UnimplementedInstruction(instr);
         }
         break;
       }
@@ -2281,7 +2281,7 @@
       }
     }
   } else {
-    UNIMPLEMENTED();
+    UnimplementedInstruction(instr);
   }
 }
 
@@ -2317,7 +2317,7 @@
       switch (instr->Bits(20, 4) & 0xb) {
         case 1:  // vnmla, vnmls, vnmul
         default: {
-          UNIMPLEMENTED();
+          UnimplementedInstruction(instr);
           break;
         }
         case 0: {  // vmla, vmls floating-point
@@ -2419,7 +2419,7 @@
                   break;
                 }
                 default: {
-                  UNIMPLEMENTED();
+                  UnimplementedInstruction(instr);
                   break;
                 }
               }
@@ -2448,7 +2448,7 @@
                   break;
                 }
                 default: {
-                  UNIMPLEMENTED();
+                  UnimplementedInstruction(instr);
                   break;
                 }
               }
@@ -2457,7 +2457,7 @@
             case 4:  // vcmp, vcmpe
             case 5: {  // vcmp #0.0, vcmpe #0.0
               if (instr->Bit(7) == 1) {  // vcmpe
-                UNIMPLEMENTED();
+                UnimplementedInstruction(instr);
               } else {
                 fp_n_flag_ = false;
                 fp_z_flag_ = false;
@@ -2560,7 +2560,7 @@
               // flags, because we do not use them.
               if (instr->Bit(7) == 0) {
                 // We only support round-to-zero mode
-                UNIMPLEMENTED();
+                UnimplementedInstruction(instr);
                 break;
               }
               int32_t id_val = 0;
@@ -2624,7 +2624,7 @@
             case 14:  // vcvt between floating-point and fixed-point
             case 15:  // vcvt between floating-point and fixed-point
             default: {
-              UNIMPLEMENTED();
+              UnimplementedInstruction(instr);
               break;
             }
           }
@@ -2651,7 +2651,7 @@
         c_flag_ = fp_c_flag_;
         v_flag_ = fp_v_flag_;
       } else {
-        UNIMPLEMENTED();
+        UnimplementedInstruction(instr);
       }
     }
   } else if (instr->IsMrcIdIsar0()) {
@@ -2663,7 +2663,7 @@
       set_register(rd, 0x00100010);  // simulator has only bkpt and clz.
     }
   } else {
-    UNIMPLEMENTED();
+    UnimplementedInstruction(instr);
   }
 }
 
@@ -2681,7 +2681,7 @@
       // Format(instr, "clrex");
       ClearExclusive();
     } else {
-      UNIMPLEMENTED();
+      UnimplementedInstruction(instr);
     }
   } else if (ConditionallyExecute(instr)) {
     switch (instr->TypeField()) {
@@ -2715,7 +2715,8 @@
         break;
       }
       default: {
-        UNIMPLEMENTED();
+        // Type field is three bits.
+        UNREACHABLE();
         break;
       }
     }
@@ -2756,7 +2757,7 @@
       counter_instructions.Increment();
       if (icount_ == FLAG_stop_sim_at) {
         SimulatorDebugger dbg(this);
-        dbg.Debug();
+        dbg.Stop(instr, "Instruction count reached");
       } else if (IsIllegalAddress(program_counter)) {
         HandleIllegalAccess(program_counter, instr);
       } else {
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index 9bedd7f..651f825 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -130,6 +130,9 @@
   }
   void HandleIllegalAccess(uword addr, Instr* instr);
 
+  // Handles a legal instruction that the simulator does not implement.
+  void UnimplementedInstruction(Instr* instr);
+
   // Unsupported instructions use Format to print an error and stop execution.
   void Format(Instr* instr, const char* format);
 
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 3ec2c27..1e70e4e 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -219,7 +219,6 @@
 void SimulatorDebugger::Debug() {
   intptr_t last_pc = -1;
   bool done = false;
-  bool decoded = true;
 
 #define COMMAND_SIZE 63
 #define ARG_SIZE 255
@@ -243,11 +242,11 @@
   while (!done) {
     if (last_pc != sim_->get_pc()) {
       last_pc = sim_->get_pc();
-      decoded = Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+      Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
     }
     char* line = ReadLine("sim> ");
     if (line == NULL) {
-      break;
+      FATAL("ReadLine failed");
     } else {
       // Use sscanf to parse the individual parts of the command line. At the
       // moment no command expects more than two parameters.
@@ -277,20 +276,12 @@
         OS::Print("Quitting\n");
         OS::Exit(0);
       } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
-        if (decoded) {
-          sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
-        } else {
-          OS::Print("Instruction could not be decoded. Stepping disabled.\n");
-        }
+        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
-        if (decoded) {
-          // Execute the one instruction we broke at with breakpoints disabled.
-          sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
-          // Leave the debugger shell.
-          done = true;
-        } else {
-          OS::Print("Instruction could not be decoded. Cannot continue.\n");
-        }
+        // Execute the one instruction we broke at with breakpoints disabled.
+        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
+        // Leave the debugger shell.
+        done = true;
       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
         if (args == 2) {
           uint32_t value;
@@ -561,6 +552,15 @@
 }
 
 
+void Simulator::UnimplementedInstruction(Instr* instr) {
+  char buffer[64];
+  snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr);
+  SimulatorDebugger dbg(this);
+  dbg.Stop(instr, buffer);
+  FATAL("Cannot continue execution after unimplemented instruction.");
+}
+
+
 void Simulator::HandleIllegalAccess(uword addr, Instr* instr) {
   uword fault_pc = get_pc();
   // The debugger will not be able to single step past this instruction, but
@@ -757,6 +757,28 @@
       set_hi_register(rs_val % rt_val);
       break;
     }
+    case JALR: {
+      ASSERT(instr->RtField() == R0);
+      ASSERT(instr->RsField() != instr->RdField());
+      ASSERT(!delay_slot_);
+      // Format(instr, "jalr'hint 'rd, rs");
+      uword next_pc = get_register(instr->RsField());
+      ExecuteDelaySlot();
+      // Set return address to be the instruction after the delay slot.
+      set_register(instr->RdField(), pc_ + Instr::kInstrSize);
+      pc_ = next_pc - Instr::kInstrSize;  // Account for regular PC increment.
+      break;
+    }
+    case JR: {
+      ASSERT(instr->RtField() == R0);
+      ASSERT(instr->RdField() == R0);
+      ASSERT(!delay_slot_);
+      // Format(instr, "jr'hint 'rs");
+      uword next_pc = get_register(instr->RsField());
+      ExecuteDelaySlot();
+      pc_ = next_pc - Instr::kInstrSize;  // Account for regular PC increment.
+      break;
+    }
     case MFHI: {
       ASSERT(instr->RsField() == 0);
       ASSERT(instr->RtField() == 0);
@@ -773,6 +795,64 @@
       set_register(instr->RdField(), get_lo_register());
       break;
     }
+    case MOVN: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "movn 'rd, 'rs, 'rt");
+      int32_t rt_val = get_register(instr->RtField());
+      int32_t rs_val = get_register(instr->RsField());
+      if (rt_val != 0) {
+        set_register(instr->RdField(), rs_val);
+      }
+      break;
+    }
+    case MOVZ: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "movz 'rd, 'rs, 'rt");
+      int32_t rt_val = get_register(instr->RtField());
+      int32_t rs_val = get_register(instr->RsField());
+      if (rt_val == 0) {
+        set_register(instr->RdField(), rs_val);
+      }
+      break;
+    }
+    case MULT: {
+      ASSERT(instr->RdField() == 0);
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "mult 'rs, 'rt");
+      int64_t rs = static_cast<int64_t>(get_register(instr->RsField()));
+      int64_t rt = static_cast<int64_t>(get_register(instr->RtField()));
+      int64_t res = rs * rt;
+      set_hi_register(Utils::High32Bits(res));
+      set_lo_register(Utils::Low32Bits(res));
+      break;
+    }
+    case MULTU: {
+      ASSERT(instr->RdField() == 0);
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "multu 'rs, 'rt");
+      uint64_t rs = static_cast<uint64_t>(get_register(instr->RsField()));
+      uint64_t rt = static_cast<uint64_t>(get_register(instr->RtField()));
+      uint64_t res = rs * rt;
+      set_hi_register(Utils::High32Bits(res));
+      set_lo_register(Utils::Low32Bits(res));
+      break;
+    }
+    case NOR: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "nor 'rd, 'rs, 'rt");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      set_register(instr->RdField(), ~(rs_val | rt_val));
+      break;
+    }
+    case OR: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "or 'rd, 'rs, 'rt");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      set_register(instr->RdField(), rs_val | rt_val);
+      break;
+    }
     case SLL: {
       ASSERT(instr->RsField() == 0);
       if ((instr->RdField() == R0) &&
@@ -787,19 +867,81 @@
       }
       break;
     }
-    case JR: {
-      ASSERT(instr->RtField() == R0);
-      ASSERT(instr->RdField() == R0);
-      ASSERT(!delay_slot_);
-      // Format(instr, "jr'hint 'rs");
-      uword next_pc = get_register(instr->RsField());
-      ExecuteDelaySlot();
-      pc_ = next_pc - Instr::kInstrSize;  // Account for regular PC increment.
+    case SLLV: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "sllv 'rd, 'rt, 'rs");
+      int32_t rt_val = get_register(instr->RtField());
+      int32_t rs_val = get_register(instr->RsField());
+      set_register(instr->RdField(), rt_val << (rs_val & 0x1f));
+      break;
+    }
+    case SLT: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "slt 'rd, 'rs, 'rt");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      set_register(instr->RdField(), rs_val < rt_val ? 1 : 0);
+      break;
+    }
+    case SLTU: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "sltu 'rd, 'rs, 'rt");
+      uint32_t rs_val = static_cast<uint32_t>(get_register(instr->RsField()));
+      uint32_t rt_val = static_cast<uint32_t>(get_register(instr->RtField()));
+      set_register(instr->RdField(), rs_val < rt_val ? 1 : 0);
+      break;
+    }
+    case SRA: {
+      ASSERT(instr->RsField() == 0);
+      // Format(instr, "sra 'rd, 'rt, 'sa");
+      int32_t rt_val = get_register(instr->RtField());
+      int32_t sa = instr->SaField();
+      set_register(instr->RdField(), rt_val >> sa);
+      break;
+    }
+    case SRAV: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "srav 'rd, 'rt, 'rs");
+      int32_t rt_val = get_register(instr->RtField());
+      int32_t rs_val = get_register(instr->RsField());
+      set_register(instr->RdField(), rt_val >> (rs_val & 0x1f));
+      break;
+    }
+    case SRL: {
+      ASSERT(instr->RsField() == 0);
+      // Format(instr, "srl 'rd, 'rt, 'sa");
+      uint32_t rt_val = get_register(instr->RtField());
+      uint32_t sa = instr->SaField();
+      set_register(instr->RdField(), rt_val >> sa);
+      break;
+    }
+    case SRLV: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "srlv 'rd, 'rt, 'rs");
+      uint32_t rt_val = get_register(instr->RtField());
+      uint32_t rs_val = get_register(instr->RsField());
+      set_register(instr->RdField(), rt_val >> (rs_val & 0x1f));
+      break;
+    }
+    case SUBU: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "subu 'rd, 'rs, 'rt");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      set_register(instr->RdField(), rs_val - rt_val);
+      break;
+    }
+    case XOR: {
+      ASSERT(instr->SaField() == 0);
+      // Format(instr, "xor 'rd, 'rs, 'rt");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      set_register(instr->RdField(), rs_val ^ rt_val);
       break;
     }
     default: {
       OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits());
-      UNIMPLEMENTED();
+      UnimplementedInstruction(instr);
       break;
     }
   }
@@ -841,7 +983,66 @@
     }
     default: {
       OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits());
-      UNIMPLEMENTED();
+      UnimplementedInstruction(instr);
+      break;
+    }
+  }
+}
+
+
+void Simulator::DoBranch(Instr* instr, bool taken, bool likely) {
+  ASSERT(!delay_slot_);
+  int32_t imm_val = instr->SImmField() << 2;
+
+  uword next_pc;
+  if (taken) {
+    // imm_val is added to the address of the instruction following the branch.
+    next_pc = pc_ + imm_val + Instr::kInstrSize;
+    if (likely) {
+      ExecuteDelaySlot();
+    }
+  } else {
+    next_pc = pc_ + (2 * Instr::kInstrSize);  // Next after delay slot.
+  }
+  if (!likely) {
+    ExecuteDelaySlot();
+  }
+  pc_ = next_pc - Instr::kInstrSize;
+
+  return;
+}
+
+
+void Simulator::DecodeRegImm(Instr* instr) {
+  ASSERT(instr->OpcodeField() == REGIMM);
+  switch (instr->RegImmFnField()) {
+    case BGEZ: {
+      // Format(instr, "bgez 'rs, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      DoBranch(instr, rs_val >= 0, false);
+      break;
+    }
+    case BGEZL: {
+      // Format(instr, "bgezl 'rs, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      DoBranch(instr, rs_val >= 0, true);
+      break;
+    }
+    case BLTZ: {
+      // Format(instr, "bltz 'rs, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      DoBranch(instr, rs_val < 0, false);
+      break;
+    }
+    case BLTZL: {
+      // Format(instr, "bltzl 'rs, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      DoBranch(instr, rs_val < 0, true);
+      break;
+    }
+    default: {
+      OS::PrintErr("DecodeRegImm: 0x%x\n", instr->InstructionBits());
+      UnimplementedInstruction(instr);
       break;
     }
   }
@@ -858,6 +1059,10 @@
       DecodeSpecial2(instr);
       break;
     }
+    case REGIMM: {
+      DecodeRegImm(instr);
+      break;
+    }
     case ADDIU: {
       // Format(instr, "addiu 'rt, 'rs, 'imms");
       int32_t rs_val = get_register(instr->RsField());
@@ -873,6 +1078,62 @@
       set_register(instr->RtField(), rs_val & instr->UImmField());
       break;
     }
+    case BEQ: {
+      // Format(instr, "beq 'rs, 'rt, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      DoBranch(instr, rs_val == rt_val, false);
+      break;
+    }
+    case BEQL: {
+      // Format(instr, "beql 'rs, 'rt, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      DoBranch(instr, rs_val == rt_val, true);
+      break;
+    }
+    case BGTZ: {
+      ASSERT(instr->RtField() == R0);
+      // Format(instr, "bgtz 'rs, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      DoBranch(instr, rs_val > 0, false);
+      break;
+    }
+    case BGTZL: {
+      ASSERT(instr->RtField() == R0);
+      // Format(instr, "bgtzl 'rs, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      DoBranch(instr, rs_val > 0, true);
+      break;
+    }
+    case BLEZ: {
+      ASSERT(instr->RtField() == R0);
+      // Format(instr, "blez 'rs, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      DoBranch(instr, rs_val <= 0, false);
+      break;
+    }
+    case BLEZL: {
+      ASSERT(instr->RtField() == R0);
+      // Format(instr, "blezl 'rs, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      DoBranch(instr, rs_val <= 0, true);
+      break;
+    }
+    case BNE: {
+      // Format(instr, "bne 'rs, 'rt, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      DoBranch(instr, rs_val != rt_val, false);
+      break;
+    }
+    case BNEL: {
+      // Format(instr, "bnel 'rs, 'rt, 'dest");
+      int32_t rs_val = get_register(instr->RsField());
+      int32_t rt_val = get_register(instr->RtField());
+      DoBranch(instr, rs_val != rt_val, true);
+      break;
+    }
     case LB: {
       // Format(instr, "lb 'rt, 'imms('rs)");
       int32_t base_val = get_register(instr->RsField());
@@ -991,7 +1252,7 @@
     default: {
       OS::PrintErr("Undecoded instruction: 0x%x at %p\n",
                     instr->InstructionBits(), instr);
-      UNIMPLEMENTED();
+      UnimplementedInstruction(instr);
       break;
     }
   }
@@ -1003,10 +1264,11 @@
   ASSERT(pc_ != kEndSimulatingPC);
   delay_slot_ = true;
   icount_++;
-  if (icount_ == FLAG_stop_sim_at) {
-    UNIMPLEMENTED();
-  }
   Instr* instr = Instr::At(pc_ + Instr::kInstrSize);
+  if (icount_ == FLAG_stop_sim_at) {
+    SimulatorDebugger dbg(this);
+    dbg.Stop(instr, "Instruction count reached");
+  }
   InstructionDecode(instr);
   delay_slot_ = false;
 }
@@ -1019,18 +1281,27 @@
     while (pc_ != kEndSimulatingPC) {
       icount_++;
       Instr* instr = Instr::At(pc_);
-      InstructionDecode(instr);
+      if (IsIllegalAddress(pc_)) {
+        HandleIllegalAccess(pc_, instr);
+      } else {
+        InstructionDecode(instr);
+      }
     }
   } else {
     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
     // we reach the particular instruction count.
     while (pc_ != kEndSimulatingPC) {
       icount_++;
+      Instr* instr = Instr::At(pc_);
       if (icount_ == FLAG_stop_sim_at) {
-        UNIMPLEMENTED();
+        SimulatorDebugger dbg(this);
+        dbg.Stop(instr, "Instruction count reached");
       } else {
-        Instr* instr = Instr::At(pc_);
-        InstructionDecode(instr);
+        if (IsIllegalAddress(pc_)) {
+          HandleIllegalAccess(pc_, instr);
+        } else {
+          InstructionDecode(instr);
+        }
       }
     }
   }
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index 919ed99..2407de1 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -96,6 +96,9 @@
   // Read and write memory.
   void UnalignedAccess(const char* msg, uword addr, Instr* instr);
 
+  // Handles a legal instruction that the simulator does not implement.
+  void UnimplementedInstruction(Instr* instr);
+
   bool OverflowFrom(int32_t alu_out,
                     int32_t left,
                     int32_t right,
@@ -115,8 +118,10 @@
   inline void WriteH(uword addr, uint16_t value, Instr* isntr);
   inline void WriteW(uword addr, int value, Instr* instr);
 
+  void DoBranch(Instr* instr, bool taken, bool likely);
   void DecodeSpecial(Instr* instr);
   void DecodeSpecial2(Instr* instr);
+  void DecodeRegImm(Instr* instr);
   void InstructionDecode(Instr* instr);
 
   void Execute();
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index fce9b23..021569c 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1130,7 +1130,7 @@
 
     // Load the test library from the snapshot.
     EXPECT(script_snapshot != NULL);
-    result = Dart_LoadScriptFromSnapshot(script_snapshot);
+    result = Dart_LoadScriptFromSnapshot(script_snapshot, size);
     EXPECT_VALID(result);
 
     // Get list of library URLs loaded and compare with expected count.
@@ -1204,7 +1204,7 @@
 
     // Load the test library from the snapshot.
     EXPECT(script_snapshot != NULL);
-    result = Dart_LoadScriptFromSnapshot(script_snapshot);
+    result = Dart_LoadScriptFromSnapshot(script_snapshot, size);
     EXPECT_VALID(result);
   }
   Dart_ShutdownIsolate();
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index ddd7963..3e5a567 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -345,12 +345,12 @@
   for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
     __ pushl(static_cast<Register>(i));
   }
-  __ subl(ESP, Immediate(kNumberOfXmmRegisters * kDoubleSize));
+  __ subl(ESP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize));
   intptr_t offset = 0;
   for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
     XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
-    __ movsd(Address(ESP, offset), xmm_reg);
-    offset += kDoubleSize;
+    __ movups(Address(ESP, offset), xmm_reg);
+    offset += kFpuRegisterSize;
   }
 
   __ movl(ECX, ESP);  // Saved saved registers block.
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 5164808..80f0f96 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -339,12 +339,12 @@
   for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
     __ pushq(static_cast<Register>(i));
   }
-  __ subq(RSP, Immediate(kNumberOfXmmRegisters * kDoubleSize));
+  __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize));
   intptr_t offset = 0;
   for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
     XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
-    __ movsd(Address(RSP, offset), xmm_reg);
-    offset += kDoubleSize;
+    __ movups(Address(RSP, offset), xmm_reg);
+    offset += kFpuRegisterSize;
   }
 
   __ movq(RCX, RSP);  // Saved saved registers block.
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 3a05318..7a7d9ae 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -175,6 +175,10 @@
   V(_ExternalFloat32x4Array, "_ExternalFloat32x4Array")                        \
   V(_ExternalFloat32Array, "_ExternalFloat32Array")                            \
   V(_ExternalFloat64Array, "_ExternalFloat64Array")                            \
+  V(ByteData, "ByteData")                                                      \
+  V(ByteDataDot, "ByteData.")                                                  \
+  V(ByteDataDotview, "ByteData.view")                                          \
+  V(_ByteDataView, "_ByteDataView")                                            \
   V(_WeakProperty, "_WeakProperty")                                            \
   V(InvocationMirror, "_InvocationMirror")                                     \
   V(AllocateInvocationMirror, "_allocateInvocationMirror")                     \
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 06f42ce..831a72b 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -99,7 +99,7 @@
   Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler);
   EXPECT_VALID(result);
   EXPECT_VALID(result);
-  Dart_Handle lib = Dart_LoadScript(url, source);
+  Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
   DART_CHECK_VALID(lib);
   result = Dart_SetNativeResolver(lib, resolver);
   DART_CHECK_VALID(result);
diff --git a/runtime/vm/virtual_memory.cc b/runtime/vm/virtual_memory.cc
index 7c683d9..8accabd 100644
--- a/runtime/vm/virtual_memory.cc
+++ b/runtime/vm/virtual_memory.cc
@@ -15,6 +15,9 @@
   ASSERT(Utils::IsPowerOfTwo(alignment));
   ASSERT(alignment >= PageSize());
   VirtualMemory* result = VirtualMemory::Reserve(size + alignment);
+  if (result == NULL) {
+    FATAL("Out of memory.\n");
+  }
   uword start = result->start();
   uword real_start = (start + alignment - 1) & ~(alignment - 1);
   result->Truncate(real_start, size);
diff --git a/sdk/bin/dart2js b/sdk/bin/dart2js
index 825712d..9e70d6f 100755
--- a/sdk/bin/dart2js
+++ b/sdk/bin/dart2js
@@ -42,7 +42,6 @@
 if test -f "$SNAPSHOT"; then
   # TODO(ahe): Remove the following line when we are relatively sure it works.
   echo Using snapshot "$SNAPSHOT" 1>&2
-  EXTRA_VM_OPTIONS[${#EXTRA_VM_OPTIONS[@]}]="--use-script-snapshot=$SNAPSHOT"
 fi
 
 # Tell the VM to grow the heap more aggressively. This should only
@@ -57,4 +56,8 @@
     ;;
 esac
 
-exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$DART2JS" "${EXTRA_OPTIONS[@]}" "$@"
+if test -f "$SNAPSHOT"; then
+  exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$SNAPSHOT" "${EXTRA_OPTIONS[@]}" "$@"
+else
+  exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$DART2JS" "${EXTRA_OPTIONS[@]}" "$@"
+fi
diff --git a/sdk/bin/dart2js.bat b/sdk/bin/dart2js.bat
index a5c67f6..4aa849d 100644
--- a/sdk/bin/dart2js.bat
+++ b/sdk/bin/dart2js.bat
@@ -9,7 +9,8 @@
 if %SCRIPTPATH:~-1%== set SCRIPTPATH=%SCRIPTPATH:~0,-1%
 
 set arguments=%*
+set SCRIPTNAME="%SCRIPTPATH%..\lib\_internal\compiler\implementation\dart2js.dart"
 set SNAPSHOTNAME="%SCRIPTPATH%dart2js.snapshot"
-if exist %SNAPSHOTNAME% set SNAPSHOT=--use-script-snapshot=%SNAPSHOTNAME%
+if exist %SNAPSHOTNAME% set SCRIPTNAME=%SNAPSHOTNAME%
 
-"%SCRIPTPATH%dart" --heap_growth_rate=512 %SNAPSHOT% "%SCRIPTPATH%..\lib\_internal\compiler\implementation\dart2js.dart" %arguments%
+"%SCRIPTPATH%dart" --heap_growth_rate=512 %SCRIPTNAME% %arguments%
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index bbac476..7a23913 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -895,7 +895,6 @@
     if (elements != null) {
       // Only analyze nodes with a corresponding [TreeElements].
       checker.check(tree, elements);
-      typesTask.analyze(tree, elements);
     }
     return elements;
   }
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index bc5be23..284607b 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -345,7 +345,7 @@
   if (uri.scheme != 'file') {
     fail('Error: Unhandled scheme ${uri.scheme}.');
   }
-  var file = new File(uriPathToNative(uri.path)).openSync(FileMode.WRITE);
+  var file = new File(uriPathToNative(uri.path)).openSync(mode: FileMode.WRITE);
   file.writeStringSync(text);
   file.closeSync();
 }
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index 1611434..830fddf 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -276,6 +276,15 @@
         fixedMemberNames.add(element.name.slowToString());
       });
     }
+    // As of now names of named optionals are not renamed. Therefore add all
+    // field names used as named optionals into [fixedMemberNames].
+    for (final element in resolvedElements.keys) {
+      if (!element.isConstructor()) continue;
+      for (final optional in element.functionSignature.optionalParameters) {
+        if (optional.kind != ElementKind.FIELD_PARAMETER) continue;
+        fixedMemberNames.add(optional.name.slowToString());
+      }
+    }
     // The VM will automatically invoke the call method of objects
     // that are invoked as functions. Make sure to not rename that.
     fixedMemberNames.add('call');
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index 3768453..b35824d 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -656,6 +656,7 @@
   int get requiredParameterCount;
   int get optionalParameterCount;
   bool get optionalParametersAreNamed;
+  Element get firstOptionalParameter;
 
   int get parameterCount;
   List<Element> get orderedOptionalParameters;
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index cbcb559..0a3b141 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1068,6 +1068,8 @@
     return list;
   }
 
+  Element get firstOptionalParameter => optionalParameters.head;
+
   void forEachParameter(void function(Element parameter)) {
     forEachRequiredParameter(function);
     forEachOptionalParameter(function);
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index b4e2ffa..b9b44ef 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -101,7 +101,7 @@
     int argumentsCount = node.inputs.length - 1;
     int startInvokeIndex = HInvoke.ARGUMENTS_OFFSET;
 
-    if (node.isInterceptorCall) {
+    if (node.isInterceptedCall) {
       argumentsCount--;
       startInvokeIndex++;
     }
@@ -655,6 +655,7 @@
   Element jsStringSplit;
   Element jsStringConcat;
   Element jsStringToString;
+  Element objectEquals;
 
   ClassElement typeLiteralClass;
   ClassElement mapLiteralClass;
@@ -730,14 +731,6 @@
    */
   final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>();
 
-  /**
-   * Set of selectors that are used from within loops. Used by the
-   * builder to allow speculative optimizations for functions without
-   * loops themselves.
-   */
-  final Map<SourceString, Set<Selector>> selectorsCalledInLoop =
-      new Map<SourceString, Set<Selector>>();
-
   List<CompilerTask> get tasks {
     return <CompilerTask>[builder, optimizer, generator, emitter];
   }
@@ -905,6 +898,9 @@
     constMapLiteralClass =
         compiler.findHelper(const SourceString('ConstantMap'));
 
+    objectEquals = compiler.lookupElementIn(
+        compiler.objectClass, const SourceString('=='));
+
     specialOperatorEqClasses
         ..add(jsNullClass)
         ..add(jsNumberClass);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
index 915b2f7..736bf5d 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
@@ -27,7 +27,7 @@
   patch static _rename(String path, String newPath) {
     throw new UnsupportedError("Directory._rename");
   }
-  patch static List _list(String path, bool recursive) {
+  patch static List _list(String path, bool recursive, bool followLinks) {
     throw new UnsupportedError("Directory._list");
   }
   patch static SendPort _newServicePort() {
@@ -57,6 +57,9 @@
   patch static int _getType(String path, bool followLinks) {
     throw new UnsupportedError("FileSystemEntity._getType");
   }
+  patch static bool _identical(String path1, String path2) {
+    throw new UnsupportedError("FileSystemEntity._identical");
+  }
 }
 
 patch class _File {
@@ -69,6 +72,9 @@
   patch static _createLink(String path, String target) {
     throw new UnsupportedError("File._createLink");
   }
+  patch static _linkTarget(String path) {
+    throw new UnsupportedError("File._linkTarget");
+  }
   patch static _delete(String path) {
     throw new UnsupportedError("File._delete");
   }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
index 5b09ac9..aa01bd2 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
@@ -18,6 +18,38 @@
 
 ReceivePort lazyPort;
 
+class CloseToken {
+  /// This token is sent from [IsolateSink]s to [IsolateStream]s to ask them to
+  /// close themselves.
+  const CloseToken();
+}
+
+class JsIsolateSink extends StreamSink<dynamic> implements IsolateSink {
+  bool _isClosed = false;
+  final SendPort _port;
+  JsIsolateSink.fromPort(this._port);
+
+  void add(dynamic message) {
+    _port.send(message);
+  }
+
+  void addError(AsyncError errorEvent) {
+    throw new UnimplementedError("signalError on isolate streams");
+  }
+
+  void close() {
+    if (_isClosed) return;
+    add(const CloseToken());
+    _isClosed = true;
+  }
+
+  bool operator==(var other) {
+    return other is IsolateSink && _port == other._port;
+  }
+
+  int get hashCode => _port.hashCode + 499;
+}
+
 /**
  * Called by the compiler to support switching
  * between isolates when we get a callback from the DOM.
@@ -906,6 +938,14 @@
       ports.add(port._futurePort);
     }
   }
+
+  visitIsolateSink(IsolateSink sink) {
+    visitSendPort(sink._port);
+  }
+
+  visitCloseToken(CloseToken token) {
+    // Do nothing.
+  }
 }
 
 /********************************************************
@@ -964,6 +1004,15 @@
     }
   }
 
+  visitIsolateSink(IsolateSink sink) {
+    SendPort port = sink._port;
+    bool isClosed = sink._isClosed;
+    return ['isolateSink', visitSendPort(port), isClosed];
+  }
+
+  visitCloseToken(CloseToken token) {
+    return ['closeToken'];
+  }
 }
 
 
@@ -998,14 +1047,25 @@
     }
   }
 
+  IsolateSink visitIsolateSink(IsolateSink sink) {
+    SendPort port = sink._port;
+    bool isClosed = sink._isClosed;
+    IsolateSink result = new JsIsolateSink.fromPort(visitSendPort(port));
+    result._isClosed = isClosed;
+    return result;
+  }
+
+  CloseToken visitCloseToken(CloseToken token) {
+    return token;  // Can be shared.
+  }
 }
 
 class _JsDeserializer extends _Deserializer {
 
-  SendPort deserializeSendPort(List x) {
-    int managerId = x[1];
-    int isolateId = x[2];
-    int receivePortId = x[3];
+  SendPort deserializeSendPort(List list) {
+    int managerId = list[1];
+    int isolateId = list[2];
+    int receivePortId = list[3];
     // If two isolates are in the same manager, we use NativeJsSendPorts to
     // deliver messages directly without using postMessage.
     if (managerId == _globalState.currentManagerId) {
@@ -1019,6 +1079,17 @@
     }
   }
 
+  IsolateSink deserializeIsolateSink(List list) {
+    SendPort port = deserializeSendPort(list[1]);
+    bool isClosed = list[2];
+    IsolateSink result = new JsIsolateSink.fromPort(port);
+    result._isClosed = isClosed;
+    return result;
+  }
+
+  CloseToken deserializeCloseToken(List list) {
+    return const CloseToken();
+  }
 }
 
 class _JsVisitedMap implements _MessageTraverserVisitedMap {
@@ -1116,6 +1187,8 @@
     if (x is Map) return visitMap(x);
     if (x is SendPort) return visitSendPort(x);
     if (x is SendPortSync) return visitSendPortSync(x);
+    if (x is JsIsolateSink) return visitIsolateSink(x);
+    if (x is CloseToken) return visitCloseToken(x);
 
     // Overridable fallback.
     return visitObject(x);
@@ -1126,6 +1199,8 @@
   visitMap(Map x);
   visitSendPort(SendPort x);
   visitSendPortSync(SendPortSync x);
+  visitIsolateSink(IsolateSink x);
+  visitCloseToken(CloseToken x);
 
   visitObject(Object x) {
     // TODO(floitsch): make this a real exception. (which one)?
@@ -1237,6 +1312,8 @@
       case 'list': return _deserializeList(x);
       case 'map': return _deserializeMap(x);
       case 'sendport': return deserializeSendPort(x);
+      case 'isolateSink': return deserializeIsolateSink(x);
+      case 'closeToken': return deserializeCloseToken(x);
       default: return deserializeObject(x);
     }
   }
@@ -1278,6 +1355,10 @@
 
   deserializeSendPort(List x);
 
+  deserializeIsolateSink(List x);
+
+  deserializeCloseToken(List x);
+
   deserializeObject(List x) {
     // TODO(floitsch): Use real exception (which one?).
     throw "Unexpected serialized object";
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
index 2514d60..4e6982a 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
@@ -6,7 +6,9 @@
 
 import 'dart:_isolate_helper' show IsolateNatives,
                                    lazyPort,
-                                   ReceivePortImpl;
+                                   ReceivePortImpl,
+                                   CloseToken,
+                                   JsIsolateSink;
 
 patch class _Isolate {
   patch static ReceivePort get port {
@@ -17,8 +19,12 @@
   }
 
   patch static SendPort spawnFunction(void topLevelFunction(),
-      [bool UnhandledExceptionCallback(IsolateUnhandledException e)]) {
-    // TODO(9012): Don't ignore the UnhandledExceptionCallback.
+      [bool unhandledExceptionCallback(IsolateUnhandledException e)]) {
+    if (unhandledExceptionCallback != null) {
+      // TODO(9012): Implement the UnhandledExceptionCallback.
+      throw new UnimplementedError(
+          "spawnFunction with unhandledExceptionCallback");
+    }
     return IsolateNatives.spawnFunction(topLevelFunction);
   }
 
@@ -27,9 +33,33 @@
   }
 }
 
+patch bool _isCloseToken(var object) {
+  return identical(object, const CloseToken());
+}
+
 /** Default factory for receive ports. */
 patch class ReceivePort {
   patch factory ReceivePort() {
     return new ReceivePortImpl();
   }
 }
+
+patch class MessageBox {
+  patch MessageBox.oneShot() : this._oneShot(new ReceivePort());
+  MessageBox._oneShot(ReceivePort receivePort)
+      : stream = new IsolateStream._fromOriginalReceivePortOneShot(receivePort),
+        sink = new JsIsolateSink.fromPort(receivePort.toSendPort());
+
+  patch MessageBox() : this._(new ReceivePort());
+  MessageBox._(ReceivePort receivePort)
+      : stream = new IsolateStream._fromOriginalReceivePort(receivePort),
+        sink = new JsIsolateSink.fromPort(receivePort.toSendPort());
+}
+
+patch IsolateSink streamSpawnFunction(
+    void topLevelFunction(),
+    [bool unhandledExceptionCallback(IsolateUnhandledException e)]) {
+  SendPort sendPort = spawnFunction(topLevelFunction,
+                                    unhandledExceptionCallback);
+  return new JsIsolateSink.fromPort(sendPort);
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index 64c08a1..155a74a 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -16,12 +16,14 @@
                                    RAW_DART_FUNCTION_REF,
                                    UNINTERCEPTED;
 import 'dart:_interceptors' show getInterceptor,
-                                 interceptedNames;
+                                 interceptedNames,
+                                 JSIndexable;
 
 part 'constant_map.dart';
 part 'native_helper.dart';
 part 'regexp_helper.dart';
 part 'string_helper.dart';
+part 'js_rti.dart';
 
 bool isJsArray(var value) {
   return value != null && JS('bool', r'(#.constructor === Array)', value);
@@ -598,46 +600,6 @@
   return value;
 }
 
-class MathNatives {
-  static double sqrt(num value)
-    => JS('double', r'Math.sqrt(#)', checkNum(value));
-
-  static double sin(num value)
-    => JS('double', r'Math.sin(#)', checkNum(value));
-
-  static double cos(num value)
-    => JS('double', r'Math.cos(#)', checkNum(value));
-
-  static double tan(num value)
-    => JS('double', r'Math.tan(#)', checkNum(value));
-
-  static double acos(num value)
-    => JS('double', r'Math.acos(#)', checkNum(value));
-
-  static double asin(num value)
-    => JS('double', r'Math.asin(#)', checkNum(value));
-
-  static double atan(num value)
-    => JS('double', r'Math.atan(#)', checkNum(value));
-
-  static double atan2(num a, num b)
-    => JS('double', r'Math.atan2(#, #)', checkNum(a), checkNum(b));
-
-  static double exp(num value)
-    => JS('double', r'Math.exp(#)', checkNum(value));
-
-  static double log(num value)
-    => JS('double', r'Math.log(#)', checkNum(value));
-
-  static num pow(num value, num exponent) {
-    checkNum(value);
-    checkNum(exponent);
-    return JS('num', r'Math.pow(#, #)', value, exponent);
-  }
-
-  static double random() => JS('double', r'Math.random()');
-}
-
 /**
  * Wrap the given Dart object and record a stack trace.
  *
@@ -1038,22 +1000,6 @@
   }
 }
 
-setRuntimeTypeInfo(target, typeInfo) {
-  assert(typeInfo == null || isJsArray(typeInfo));
-  // We have to check for null because factories may return null.
-  if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
-}
-
-getRuntimeTypeInfo(target) {
-  if (target == null) return null;
-  return JS('var', r'#.$builtinTypeInfo', target);
-}
-
-getRuntimeTypeArgument(target, substitution, index) {
-  var arguments = substitute(substitution, getRuntimeTypeInfo(target));
-  return (arguments == null) ? null : getField(arguments, index);
-}
-
 /**
  * The following methods are called by the runtime to implement
  * checked mode and casts. We specialize each primitive type (eg int, bool), and
@@ -1324,7 +1270,7 @@
  * objects that support integer indexing. This interface is not
  * visible to anyone, and is only injected into special libraries.
  */
-abstract class JavaScriptIndexingBehavior {
+abstract class JavaScriptIndexingBehavior extends JSIndexable {
 }
 
 // TODO(lrn): These exceptions should be implemented in core.
@@ -1412,217 +1358,3 @@
 void throwCyclicInit(String staticName) {
   throw new RuntimeError("Cyclic initialization for static $staticName");
 }
-
-class TypeImpl implements Type {
-  final String typeName;
-  TypeImpl(this.typeName);
-  toString() => typeName;
-  int get hashCode => typeName.hashCode;
-  bool operator ==(other) {
-    if (other is !TypeImpl) return false;
-    return typeName == other.typeName;
-  }
-}
-
-String getClassName(var object) {
-  return JS('String', r'#.constructor.builtin$cls', object);
-}
-
-String getRuntimeTypeAsString(List runtimeType) {
-  String className = getConstructorName(runtimeType[0]);
-  if (runtimeType.length == 1) return className;
-  return '$className<${joinArguments(runtimeType, 1)}>';
-}
-
-String getConstructorName(type) => JS('String', r'#.builtin$cls', type);
-
-String runtimeTypeToString(type) {
-  if (type == null) {
-    return 'dynamic';
-  } else if (isJsArray(type)) {
-    // A list representing a type with arguments.
-    return getRuntimeTypeAsString(type);
-  } else {
-    // A reference to the constructor.
-    return getConstructorName(type);
-  }
-}
-
-String joinArguments(var types, int startIndex) {
-  bool firstArgument = true;
-  StringBuffer buffer = new StringBuffer();
-  for (int index = startIndex; index < types.length; index++) {
-    if (firstArgument) {
-      firstArgument = false;
-    } else {
-      buffer.write(', ');
-    }
-    var argument = types[index];
-    buffer.write(runtimeTypeToString(argument));
-  }
-  return buffer.toString();
-}
-
-String getRuntimeTypeString(var object) {
-  String className = isJsArray(object) ? 'List' : getClassName(object);
-  var typeInfo = JS('var', r'#.$builtinTypeInfo', object);
-  if (typeInfo == null) return className;
-  return "$className<${joinArguments(typeInfo, 0)}>";
-}
-
-bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
-
-Object invoke(function, arguments) {
-  return JS('var', r'#.apply(null, #)', function, arguments);
-}
-
-Object call(target, name) => JS('var', r'#[#]()', target, name);
-
-substitute(var substitution, var arguments) {
-  if (isJsArray(substitution)) {
-    arguments = substitution;
-  } else if (isJsFunction(substitution)) {
-    arguments = invoke(substitution, arguments);
-  }
-  return arguments;
-}
-
-/**
- * Perform a type check with arguments on the Dart object [object].
- *
- * Parameters:
- * - [isField]: the name of the flag/function to check if the object
- *   is of the correct class.
- * - [checks]: the (JavaScript) list of type representations for the
- *   arguments to check against.
- * - [asField]: the name of the function that transforms the type
- *   arguments of [objects] to an instance of the class that we check
- *   against.
- * - [native]: [:true:] if we need to use calls (for handling native
- *   objects).
- */
-bool checkSubtype(Object object, String isField, List checks, String asField,
-                  bool native) {
-  if (object == null) return false;
-  var arguments = getRuntimeTypeInfo(object);
-  if (isJsArray(object)) {
-    object = getInterceptor(object);
-  }
-  bool isSubclass = native ? call(object, isField) : getField(object, isField);
-  // When we read the field and it is not there, [isSubclass] will be [:null:].
-  if (isSubclass == null || !isSubclass) return false;
-  var substitution = native ? call(object, asField) : getField(object, asField);
-  return checkArguments(substitution, arguments, checks);
-}
-
-/**
- * Check that the types in the list [arguments] are subtypes of the types in
- * list [checks] (at the respective positions), possibly applying [substitution]
- * to the arguments before the check.
- *
- * See [:RuntimeTypes.getSubtypeSubstitution:] for a description of the possible
- * values for [substitution].
- */
-bool checkArguments(var substitution, var arguments, var checks) {
-  return areSubtypes(substitute(substitution, arguments), checks);
-}
-
-bool areSubtypes(List s, List t) {
-  // [:null:] means a raw type.
-  if (s == null || t == null) return true;
-
-  assert(isJsArray(s));
-  assert(isJsArray(t));
-  assert(s.length == t.length);
-
-  int len = s.length;
-  for (int i = 0; i < len; i++) {
-    if (!isSubtype(s[i], t[i])) {
-      return false;
-    }
-  }
-  return true;
-}
-
-getArguments(var type) {
-  return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
-}
-
-getField(var object, var name) => JS('var', r'#[#]', object, name);
-
-/**
- * Tests whether the Dart object [o] is a subtype of the runtime type
- * representation [t], which is a type representation as described in the
- * comment on [isSubtype].
- */
-bool objectIsSubtype(Object o, var t) {
-  if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
-  // Get the runtime type information from the object here, because we may
-  // overwrite o with the interceptor below.
-  var rti = getRuntimeTypeInfo(o);
-  // Check for native objects and use the interceptor instead of the object.
-  o = getInterceptor(o);
-  // We can use the object as its own type representation because we install
-  // the subtype flags and the substitution on the prototype, so they are
-  // properties of the object in JS.
-  var type;
-  if (JS('bool', '# != null', rti)) {
-    // If the type has type variables (that is, [:rti != null:]), make a copy of
-    // the type arguments and insert [o] in the first position to create a
-    // compound type representation.
-    type = JS('List', '#.slice()', rti);
-    JS('', '#.splice(0, 0, #)', type, o);
-  } else {
-    // Use the object as representation of the raw type.
-    type = o;
-  }
-  return isSubtype(type, t);
-}
-
-/**
- * Check whether the type represented by [s] is a subtype of the type
- * represented by [t].
- *
- * Type representations can be:
- *  1) a JavaScript constructor for a class C: the represented type is the raw
- *     type C.
- *  2) a Dart object: this is the interceptor instance for a native type.
- *  3) a JavaScript object: this represents a class for which there is no
- *     JavaScript constructor, because it is only used in type arguments or it
- *     is native. The represented type is the raw type of this class.
- *  4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
- *     subtyping flags and the substitution of the type and the rest of the
- *     array are the type arguments.
- *  5) [:null:]: the dynamic type.
- */
-bool isSubtype(var s, var t) {
-  // If either type is dynamic, [s] is a subtype of [t].
-  if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true;
-  // Subtyping is reflexive.
-  if (JS('bool', '# === #', s, t)) return true;
-  // Get the object describing the class and check for the subtyping flag
-  // constructed from the type of [t].
-  var typeOfS = isJsArray(s) ? s[0] : s;
-  var typeOfT = isJsArray(t) ? t[0] : t;
-  // Check for a subtyping flag.
-  var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
-  if (getField(typeOfS, test) == null) return false;
-  // Get the necessary substitution of the type arguments, if there is one.
-  var substitution;
-  if (JS('bool', '# !== #', typeOfT, typeOfS)) {
-    var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
-    substitution = getField(typeOfS, field);
-  }
-  // The class of [s] is a subclass of the class of [t].  If [s] has no type
-  // arguments and no substitution, it is used as raw type.  If [t] has no
-  // type arguments, it used as a raw type.  In both cases, [s] is a subtype
-  // of [t].
-  if ((!isJsArray(s) && JS('bool', '# == null', substitution)) ||
-      !isJsArray(t)) {
-    return true;
-  }
-  // Recursively check the type arguments.
-  return checkArguments(substitution, getArguments(s), getArguments(t));
-}
-
-createRuntimeType(String name) => new TypeImpl(name);
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_number.dart b/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
index 527c4f5..c6b78bc8 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_number.dart
@@ -203,7 +203,7 @@
     // JavaScript only looks at the last 5 bits of the shift-amount. Shifting
     // by 33 is hence equivalent to a shift by 1.
     if (JS('bool', r'# > 31', other)) return 0;
-    return JS('num', r'(# << #) >>> 0', this, other);
+    return JS('int', r'(# << #) >>> 0', this, other);
   }
 
   num operator >>(num other) {
@@ -217,28 +217,28 @@
       // Given that 'a' is positive we must not use '>>'. Otherwise a number
       // that has the 31st bit set would be treated as negative and shift in
       // ones.
-      return JS('num', r'# >>> #', this, other);
+      return JS('int', r'# >>> #', this, other);
     }
     // For negative numbers we just clamp the shift-by amount. 'a' could be
     // negative but not have its 31st bit set. The ">>" would then shift in
     // 0s instead of 1s. Therefore we cannot simply return 0xFFFFFFFF.
     if (JS('num', '#', other) > 31) other = 31;
-    return JS('num', r'(# >> #) >>> 0', this, other);
+    return JS('int', r'(# >> #) >>> 0', this, other);
   }
 
   num operator &(num other) {
     if (other is !num) throw new ArgumentError(other);
-    return JS('num', r'(# & #) >>> 0', this, other);
+    return JS('int', r'(# & #) >>> 0', this, other);
   }
 
   num operator |(num other) {
     if (other is !num) throw new ArgumentError(other);
-    return JS('num', r'(# | #) >>> 0', this, other);
+    return JS('int', r'(# | #) >>> 0', this, other);
   }
 
   num operator ^(num other) {
     if (other is !num) throw new ArgumentError(other);
-    return JS('num', r'(# ^ #) >>> 0', this, other);
+    return JS('int', r'(# ^ #) >>> 0', this, other);
   }
 
   bool operator <(num other) {
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
new file mode 100644
index 0000000..559ccfb
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_rti.dart
@@ -0,0 +1,235 @@
+// 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 _js_helper;
+
+setRuntimeTypeInfo(target, typeInfo) {
+  assert(typeInfo == null || isJsArray(typeInfo));
+  // We have to check for null because factories may return null.
+  if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
+}
+
+getRuntimeTypeInfo(target) {
+  if (target == null) return null;
+  return JS('var', r'#.$builtinTypeInfo', target);
+}
+
+getRuntimeTypeArgument(target, substitution, index) {
+  var arguments = substitute(substitution, getRuntimeTypeInfo(target));
+  return (arguments == null) ? null : getField(arguments, index);
+}
+
+class TypeImpl implements Type {
+  final String typeName;
+  TypeImpl(this.typeName);
+  toString() => typeName;
+  int get hashCode => typeName.hashCode;
+  bool operator ==(other) {
+    if (other is !TypeImpl) return false;
+    return typeName == other.typeName;
+  }
+}
+
+String getClassName(var object) {
+  return JS('String', r'#.constructor.builtin$cls', object);
+}
+
+String getRuntimeTypeAsString(List runtimeType) {
+  String className = getConstructorName(runtimeType[0]);
+  if (runtimeType.length == 1) return className;
+  return '$className<${joinArguments(runtimeType, 1)}>';
+}
+
+String getConstructorName(type) => JS('String', r'#.builtin$cls', type);
+
+String runtimeTypeToString(type) {
+  if (type == null) {
+    return 'dynamic';
+  } else if (isJsArray(type)) {
+    // A list representing a type with arguments.
+    return getRuntimeTypeAsString(type);
+  } else {
+    // A reference to the constructor.
+    return getConstructorName(type);
+  }
+}
+
+String joinArguments(var types, int startIndex) {
+  bool firstArgument = true;
+  StringBuffer buffer = new StringBuffer();
+  for (int index = startIndex; index < types.length; index++) {
+    if (firstArgument) {
+      firstArgument = false;
+    } else {
+      buffer.write(', ');
+    }
+    var argument = types[index];
+    buffer.write(runtimeTypeToString(argument));
+  }
+  return buffer.toString();
+}
+
+String getRuntimeTypeString(var object) {
+  String className = isJsArray(object) ? 'List' : getClassName(object);
+  var typeInfo = JS('var', r'#.$builtinTypeInfo', object);
+  if (typeInfo == null) return className;
+  return "$className<${joinArguments(typeInfo, 0)}>";
+}
+
+bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
+
+Object invoke(function, arguments) {
+  return JS('var', r'#.apply(null, #)', function, arguments);
+}
+
+Object call(target, name) => JS('var', r'#[#]()', target, name);
+
+substitute(var substitution, var arguments) {
+  if (isJsArray(substitution)) {
+    arguments = substitution;
+  } else if (isJsFunction(substitution)) {
+    arguments = invoke(substitution, arguments);
+  }
+  return arguments;
+}
+
+/**
+ * Perform a type check with arguments on the Dart object [object].
+ *
+ * Parameters:
+ * - [isField]: the name of the flag/function to check if the object
+ *   is of the correct class.
+ * - [checks]: the (JavaScript) list of type representations for the
+ *   arguments to check against.
+ * - [asField]: the name of the function that transforms the type
+ *   arguments of [objects] to an instance of the class that we check
+ *   against.
+ * - [native]: [:true:] if we need to use calls (for handling native
+ *   objects).
+ */
+bool checkSubtype(Object object, String isField, List checks, String asField,
+                  bool native) {
+  if (object == null) return false;
+  var arguments = getRuntimeTypeInfo(object);
+  if (isJsArray(object)) {
+    object = getInterceptor(object);
+  }
+  bool isSubclass = native ? call(object, isField) : getField(object, isField);
+  // When we read the field and it is not there, [isSubclass] will be [:null:].
+  if (isSubclass == null || !isSubclass) return false;
+  var substitution = native ? call(object, asField) : getField(object, asField);
+  return checkArguments(substitution, arguments, checks);
+}
+
+/**
+ * Check that the types in the list [arguments] are subtypes of the types in
+ * list [checks] (at the respective positions), possibly applying [substitution]
+ * to the arguments before the check.
+ *
+ * See [:RuntimeTypes.getSubtypeSubstitution:] for a description of the possible
+ * values for [substitution].
+ */
+bool checkArguments(var substitution, var arguments, var checks) {
+  return areSubtypes(substitute(substitution, arguments), checks);
+}
+
+bool areSubtypes(List s, List t) {
+  // [:null:] means a raw type.
+  if (s == null || t == null) return true;
+
+  assert(isJsArray(s));
+  assert(isJsArray(t));
+  assert(s.length == t.length);
+
+  int len = s.length;
+  for (int i = 0; i < len; i++) {
+    if (!isSubtype(s[i], t[i])) {
+      return false;
+    }
+  }
+  return true;
+}
+
+getArguments(var type) {
+  return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
+}
+
+getField(var object, var name) => JS('var', r'#[#]', object, name);
+
+/**
+ * Tests whether the Dart object [o] is a subtype of the runtime type
+ * representation [t], which is a type representation as described in the
+ * comment on [isSubtype].
+ */
+bool objectIsSubtype(Object o, var t) {
+  if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
+  // Get the runtime type information from the object here, because we may
+  // overwrite o with the interceptor below.
+  var rti = getRuntimeTypeInfo(o);
+  // Check for native objects and use the interceptor instead of the object.
+  o = getInterceptor(o);
+  // We can use the object as its own type representation because we install
+  // the subtype flags and the substitution on the prototype, so they are
+  // properties of the object in JS.
+  var type;
+  if (JS('bool', '# != null', rti)) {
+    // If the type has type variables (that is, [:rti != null:]), make a copy of
+    // the type arguments and insert [o] in the first position to create a
+    // compound type representation.
+    type = JS('List', '#.slice()', rti);
+    JS('', '#.splice(0, 0, #)', type, o);
+  } else {
+    // Use the object as representation of the raw type.
+    type = o;
+  }
+  return isSubtype(type, t);
+}
+
+/**
+ * Check whether the type represented by [s] is a subtype of the type
+ * represented by [t].
+ *
+ * Type representations can be:
+ *  1) a JavaScript constructor for a class C: the represented type is the raw
+ *     type C.
+ *  2) a Dart object: this is the interceptor instance for a native type.
+ *  3) a JavaScript object: this represents a class for which there is no
+ *     JavaScript constructor, because it is only used in type arguments or it
+ *     is native. The represented type is the raw type of this class.
+ *  4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
+ *     subtyping flags and the substitution of the type and the rest of the
+ *     array are the type arguments.
+ *  5) [:null:]: the dynamic type.
+ */
+bool isSubtype(var s, var t) {
+  // If either type is dynamic, [s] is a subtype of [t].
+  if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true;
+  // Subtyping is reflexive.
+  if (JS('bool', '# === #', s, t)) return true;
+  // Get the object describing the class and check for the subtyping flag
+  // constructed from the type of [t].
+  var typeOfS = isJsArray(s) ? s[0] : s;
+  var typeOfT = isJsArray(t) ? t[0] : t;
+  // Check for a subtyping flag.
+  var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
+  if (getField(typeOfS, test) == null) return false;
+  // Get the necessary substitution of the type arguments, if there is one.
+  var substitution;
+  if (JS('bool', '# !== #', typeOfT, typeOfS)) {
+    var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
+    substitution = getField(typeOfS, field);
+  }
+  // The class of [s] is a subclass of the class of [t].  If [s] has no type
+  // arguments and no substitution, it is used as raw type.  If [t] has no
+  // type arguments, it used as a raw type.  In both cases, [s] is a subtype
+  // of [t].
+  if ((!isJsArray(s) && JS('bool', '# == null', substitution)) ||
+      !isJsArray(t)) {
+    return true;
+  }
+  // Recursively check the type arguments.
+  return checkArguments(substitution, getArguments(s), getArguments(t));
+}
+
+createRuntimeType(String name) => new TypeImpl(name);
diff --git a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
index f58d5ca..4157fc9 100644
--- a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -17,7 +17,7 @@
 import 'util/uri_extras.dart';
 
 String readAll(String filename) {
-  var file = (new File(filename)).openSync(FileMode.READ);
+  var file = (new File(filename)).openSync();
   var length = file.lengthSync();
   var buffer = new List<int>(length);
   var bytes = file.readListSync(buffer, 0, length);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 86535df..37e3b14 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -10,11 +10,11 @@
  * optimizers may look at its declared type.
  */
 class InterceptedElement extends ElementX {
-  final HType ssaType;
-  InterceptedElement(this.ssaType, SourceString name, Element enclosing)
+  final DartType type;
+  InterceptedElement(this.type, SourceString name, Element enclosing)
       : super(name, ElementKind.PARAMETER, enclosing);
 
-  DartType computeType(Compiler compiler) => ssaType.computeType(compiler);
+  DartType computeType(Compiler compiler) => type;
 }
 
 class SsaBuilderTask extends CompilerTask {
@@ -51,15 +51,8 @@
       }
       assert(graph.isValid());
       if (!identical(kind, ElementKind.FIELD)) {
-        Set<Selector> selectors = backend.selectorsCalledInLoop[element.name];
-        graph.calledInLoop = selectors != null &&
-            selectors.any((selector) => selector.applies(element, compiler));
-
-        // If there is an estimate of the parameter types assume these types
-        // when compiling.
-        // TODO(karlklose,ngeoffray): add a check to make sure that element is
-        // of type FunctionElement.
         FunctionElement function = element;
+        graph.calledInLoop = compiler.world.isCalledInLoop(function);
         OptionalParameterTypes defaultValueTypes = null;
         FunctionSignature signature = function.computeSignature(compiler);
         if (signature.optionalParameterCount > 0) {
@@ -300,41 +293,23 @@
     // parameter to it, that is the actual receiver for intercepted
     // classes, or the same as [:this:] for non-intercepted classes.
     ClassElement cls = element.getEnclosingClass();
-    if (builder.backend.isInterceptedMethod(element)) {
-      HType type = builder.getTypeOfThis();
-      SourceString name = const SourceString('receiver');
-      if (cls == builder.backend.jsArrayClass) {
-        type = HType.READABLE_ARRAY;
-      } else if (cls == builder.backend.jsStringClass) {
-        type = HType.STRING;
-      } else if (cls == builder.backend.jsNumberClass) {
-        type = HType.NUMBER;
-      } else if (cls == builder.backend.jsIntClass) {
-        type = HType.INTEGER;
-      } else if (cls == builder.backend.jsDoubleClass) {
-        type = HType.DOUBLE;
-      } else if (cls == builder.backend.jsNullClass) {
-        type = HType.NULL;
-      } else if (cls == builder.backend.jsBoolClass) {
-        type = HType.BOOLEAN;
-      } else if (cls == builder.backend.jsFunctionClass) {
-        type = HType.UNKNOWN;
-      } else if (cls != compiler.objectClass) {
-        JavaScriptBackend backend = compiler.backend;
-        if (!backend.isInterceptorClass(cls)) {
-          name = const SourceString('_');
-        }
-      }
-      Element parameter = new InterceptedElement(type, name, element);
+    JavaScriptBackend backend = compiler.backend;
+    if (backend.isInterceptedMethod(element)) {
+      bool isInterceptorClass = backend.isInterceptorClass(cls.declaration);
+      SourceString name = (cls == compiler.objectClass || isInterceptorClass)
+          ? const SourceString('receiver')
+          : const SourceString('_');
+      Element parameter = new InterceptedElement(
+          cls.computeType(compiler), name, element);
       HParameterValue value = new HParameterValue(parameter);
       builder.graph.explicitReceiverParameter = value;
       builder.graph.entry.addAfter(
           directLocals[closureData.thisElement], value);
-      if (builder.backend.isInterceptorClass(cls.declaration)) {
+      if (isInterceptorClass) {
         // Only use the extra parameter in intercepted classes.
         directLocals[closureData.thisElement] = value;
       }
-      value.instructionType = type;
+      value.instructionType = builder.getTypeOfThis();
     }
   }
 
@@ -2667,76 +2642,76 @@
   }
 
   void visitIsSend(Send node) {
-      Node argument = node.arguments.head;
-      visit(node.receiver);
-      HInstruction expression = pop();
-      TypeAnnotation typeAnnotation = argument.asTypeAnnotation();
-      bool isNot = false;
-      // TODO(ngeoffray): Duplicating pattern in resolver. We should
-      // add a new kind of node.
-      if (typeAnnotation == null) {
-        typeAnnotation = argument.asSend().receiver;
-        isNot = true;
-      }
-      DartType type = elements.getType(typeAnnotation);
-      if (type.isMalformed) {
-        String reasons = Types.fetchReasonsFromMalformedType(type);
-        if (compiler.enableTypeAssertions) {
-          generateMalformedSubtypeError(node, expression, type, reasons);
-        } else {
-          generateRuntimeError(node, '$type is malformed: $reasons');
-        }
-        return;
-      }
-
-      HInstruction instruction;
-      if (type.kind == TypeKind.TYPE_VARIABLE) {
-        HInstruction runtimeType = addTypeVariableReference(type);
-        Element helper = backend.getGetObjectIsSubtype();
-        HInstruction helperCall = new HStatic(helper);
-        add(helperCall);
-        List<HInstruction> inputs = <HInstruction>[helperCall, expression,
-                                                   runtimeType];
-        HInstruction call = new HInvokeStatic(inputs, HType.BOOLEAN);
-        add(call);
-        instruction = new HIs(type, <HInstruction>[expression, call],
-                              HIs.VARIABLE_CHECK);
-      } else if (RuntimeTypes.hasTypeArguments(type)) {
-        Element element = type.element;
-        bool needsNativeCheck =
-            backend.emitter.nativeEmitter.requiresNativeIsCheck(element);
-        Element helper = backend.getCheckSubtype();
-        HInstruction helperCall = new HStatic(helper);
-        add(helperCall);
-        HInstruction representations =
-          buildTypeArgumentRepresentations(type);
-        add(representations);
-        HInstruction isFieldName =
-            addConstantString(node, backend.namer.operatorIs(element));
-        // TODO(karlklose): use [:null:] for [asField] if [element] does not
-        // have a subclass.
-        HInstruction asFieldName =
-            addConstantString(node, backend.namer.substitutionName(element));
-        HInstruction native =
-            graph.addConstantBool(needsNativeCheck, constantSystem);
-        List<HInstruction> inputs = <HInstruction>[helperCall,
-                                                   expression,
-                                                   isFieldName,
-                                                   representations,
-                                                   asFieldName,
-                                                   native];
-        HInstruction call = new HInvokeStatic(inputs, HType.BOOLEAN);
-        add(call);
-        instruction = new HIs(type, <HInstruction>[expression, call],
-                              HIs.COMPOUND_CHECK);
+    Node argument = node.arguments.head;
+    visit(node.receiver);
+    HInstruction expression = pop();
+    TypeAnnotation typeAnnotation = argument.asTypeAnnotation();
+    bool isNot = false;
+    // TODO(ngeoffray): Duplicating pattern in resolver. We should
+    // add a new kind of node.
+    if (typeAnnotation == null) {
+      typeAnnotation = argument.asSend().receiver;
+      isNot = true;
+    }
+    DartType type = elements.getType(typeAnnotation);
+    if (type.isMalformed) {
+      String reasons = Types.fetchReasonsFromMalformedType(type);
+      if (compiler.enableTypeAssertions) {
+        generateMalformedSubtypeError(node, expression, type, reasons);
       } else {
-        instruction = new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK);
+        generateRuntimeError(node, '$type is malformed: $reasons');
       }
-      if (isNot) {
-        add(instruction);
-        instruction = new HNot(instruction);
-      }
-      push(instruction);
+      return;
+    }
+
+    HInstruction instruction;
+    if (type.kind == TypeKind.TYPE_VARIABLE) {
+      HInstruction runtimeType = addTypeVariableReference(type);
+      Element helper = backend.getGetObjectIsSubtype();
+      HInstruction helperCall = new HStatic(helper);
+      add(helperCall);
+      List<HInstruction> inputs = <HInstruction>[helperCall, expression,
+                                                 runtimeType];
+      HInstruction call = new HInvokeStatic(inputs, HType.BOOLEAN);
+      add(call);
+      instruction = new HIs(type, <HInstruction>[expression, call],
+                            HIs.VARIABLE_CHECK);
+    } else if (RuntimeTypes.hasTypeArguments(type)) {
+      Element element = type.element;
+      bool needsNativeCheck =
+          backend.emitter.nativeEmitter.requiresNativeIsCheck(element);
+      Element helper = backend.getCheckSubtype();
+      HInstruction helperCall = new HStatic(helper);
+      add(helperCall);
+      HInstruction representations =
+        buildTypeArgumentRepresentations(type);
+      add(representations);
+      HInstruction isFieldName =
+          addConstantString(node, backend.namer.operatorIs(element));
+      // TODO(karlklose): use [:null:] for [asField] if [element] does not
+      // have a subclass.
+      HInstruction asFieldName =
+          addConstantString(node, backend.namer.substitutionName(element));
+      HInstruction native =
+          graph.addConstantBool(needsNativeCheck, constantSystem);
+      List<HInstruction> inputs = <HInstruction>[helperCall,
+                                                 expression,
+                                                 isFieldName,
+                                                 representations,
+                                                 asFieldName,
+                                                 native];
+      HInstruction call = new HInvokeStatic(inputs, HType.BOOLEAN);
+      add(call);
+      instruction = new HIs(type, <HInstruction>[expression, call],
+                            HIs.COMPOUND_CHECK);
+    } else {
+      instruction = new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK);
+    }
+    if (isNot) {
+      add(instruction);
+      instruction = new HNot(instruction);
+    }
+    push(instruction);
   }
 
   void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) {
@@ -3150,7 +3125,10 @@
     }
     List<HInstruction> inputs = buildSuperAccessorInputs(element);
     if (node.isPropertyAccess) {
-      push(new HInvokeSuper(inputs));
+      HInstruction invokeSuper = new HInvokeSuper(inputs);
+      invokeSuper.instructionType =
+          new HType.inferredTypeForElement(element, compiler);
+      push(invokeSuper);
     } else if (element.isFunction() || element.isGenerativeConstructor()) {
       // TODO(5347): Try to avoid the need for calling [implementation] before
       // calling [addStaticSendArgumentsToList].
@@ -3160,10 +3138,15 @@
       if (!succeeded) {
         generateWrongArgumentCountError(node, element, node.arguments);
       } else {
-        push(new HInvokeSuper(inputs));
+        HInstruction invokeSuper = new HInvokeSuper(inputs);
+        invokeSuper.instructionType =
+            new HType.inferredReturnTypeForElement(element, compiler);
+        push(invokeSuper);
       }
     } else {
       HInstruction target = new HInvokeSuper(inputs);
+      target.instructionType =
+          new HType.inferredTypeForElement(element, compiler);
       add(target);
       inputs = <HInstruction>[target];
       addDynamicSendArgumentsToList(node, inputs);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 473756c..b8843da 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1515,7 +1515,7 @@
       // seen selectors.
       if (target.isGenerativeConstructorBody()) {
         methodName = name.slowToString();
-      } else if (!node.isInterceptorCall) {
+      } else if (!node.isInterceptedCall) {
         if (target == backend.jsArrayAdd) {
           methodName = 'push';
         } else if (target == backend.jsArrayRemoveLast) {
@@ -1586,20 +1586,12 @@
         backend.compiler.enabledInvokeOn) {
       return selector;
     }
-    int receiverIndex = node.isInterceptorCall ? 1 : 0;
-    HType receiverType = node.inputs[receiverIndex].instructionType;
+    HType receiverType = node.dartReceiver.instructionType;
     return receiverType.refine(selector, compiler);
   }
 
   void registerInvoke(HInvokeDynamic node, Selector selector) {
-    bool inLoop = node.block.enclosingLoopHeader != null;
-    if (inLoop) {
-      Set<Selector> selectors = backend.selectorsCalledInLoop.putIfAbsent(
-          selector.name, () => new Set<Selector>());
-      selectors.add(selector);
-    }
-
-    if (node.isInterceptorCall) {
+    if (node.isInterceptedCall) {
       backend.addInterceptedSelector(selector);
     }
   }
@@ -1635,7 +1627,7 @@
   void registerSetter(HInvokeDynamic node) {
     Selector selector = getOptimizedSelectorFor(node, node.selector);
     world.registerDynamicSetter(selector.name, selector);
-    HType valueType = node.isInterceptorCall
+    HType valueType = node.isInterceptedCall
         ? node.inputs[2].instructionType
         : node.inputs[1].instructionType;
     backend.addedDynamicSetter(selector, valueType);
@@ -1728,10 +1720,7 @@
     } else {
       String name = _fieldPropertyName(element);
       push(new js.PropertyAccess.field(pop(), name), node);
-      DartType type = node.receiver.instructionType.computeType(compiler);
-      if (type != null && !identical(type.kind, TypeKind.MALFORMED_TYPE)) {
-        world.registerFieldGetter(element);
-      }
+      world.registerFieldGetter(element);
     }
   }
 
@@ -1773,8 +1762,8 @@
     // instantiated. We should find a way of using something along the
     // lines of the NativeEnqueuerBase.processNativeBehavior method.
     if (type.isUnknown()) return;
-    DartType dartType = type.computeType(compiler);
-    world.registerInstantiatedClass(dartType.element, work.resolutionTree);
+    TypeMask mask = type.computeMask(compiler);
+    world.registerInstantiatedClass(mask.base.element, work.resolutionTree);
   }
 
   visitForeign(HForeign node) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
index 9e61f1b..1cfc99d 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -24,7 +24,8 @@
     return instruction.instructionType;
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     return null;
   }
 
@@ -96,7 +97,8 @@
     return HType.UNKNOWN;
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     if (instruction.inputs[1].isMutableArray()) {
       return new HIndexAssign(instruction.inputs[1],
                               instruction.inputs[2],
@@ -124,7 +126,8 @@
     return HType.UNKNOWN;
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     if (instruction.inputs[1].isIndexablePrimitive()) {
       return new HIndex(instruction.inputs[1], instruction.inputs[2]);
     }
@@ -144,7 +147,7 @@
                                    Compiler compiler) {
     if (input == instruction.inputs[1]) {
       HType propagatedType = instruction.instructionType;
-      if (propagatedType.isUnknown() || propagatedType.isNumber()) {
+      if (propagatedType.canBePrimitiveNumber(compiler)) {
         return HType.INTEGER;
       }
     }
@@ -159,7 +162,8 @@
     return instruction.instructionType;
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber()) return new HBitNot(input);
     return null;
@@ -182,7 +186,7 @@
       // want the outgoing type to be the input too.
       // If we don't know the outgoing type we try to make it a number.
       if (propagatedType.isNumber()) return propagatedType;
-      if (propagatedType.isUnknown()) return HType.NUMBER;
+      if (propagatedType.canBePrimitiveNumber(compiler)) return HType.NUMBER;
     }
     return HType.UNKNOWN;
   }
@@ -194,7 +198,8 @@
     return instruction.instructionType;
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber()) return new HNegate(input);
     return null;
@@ -228,7 +233,7 @@
     // If the outgoing type should be a number we can get that if both inputs
     // are numbers. If we don't know the outgoing type we try to make it a
     // number.
-    if (propagatedType.isUnknown() || propagatedType.isNumber()) {
+    if (propagatedType.canBePrimitiveNumber(compiler)) {
       return HType.NUMBER;
     }
     // Even if the desired outgoing type is not a number we still want the
@@ -249,7 +254,8 @@
         && instruction.inputs[2].isNumber();
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     if (isBuiltin(instruction)) {
       HInstruction builtin =
           newBuiltinVariant(instruction.inputs[1], instruction.inputs[2]);
@@ -374,12 +380,12 @@
                                    HInstruction input,
                                    Compiler compiler) {
     if (input == instruction.inputs[0]) return HType.UNKNOWN;
-    HType propagatedType = instruction.instructionType;
-    // If the outgoing type should be a number we can get that only if both
-    // inputs are integers. If we don't know the outgoing type we try to make
-    // it an integer.
-    if (propagatedType.isUnknown() || propagatedType.isNumber()) {
-      return HType.INTEGER;
+    // We match the implementation of bit operations on the
+    // [:JSNumber:] class by requesting a number if the receiver can
+    // be a number.
+    HInstruction left = instruction.inputs[1];
+    if (left.instructionType.canBePrimitiveNumber(compiler)) {
+      return HType.NUMBER;
     }
     return HType.UNKNOWN;
   }
@@ -392,7 +398,8 @@
     return constantSystem.shiftLeft;
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (!left.isNumber() || !right.isConstantInteger()) return null;
@@ -478,7 +485,7 @@
     // For all relational operations except HIdentity, we expect to get numbers
     // only. With numbers the outgoing type is a boolean. If something else
     // is desired, then numbers are incorrect, though.
-    if (propagatedType.isUnknown() || propagatedType.isBoolean()) {
+    if (propagatedType.canBePrimitiveBoolean(compiler)) {
       HInstruction left = instruction.inputs[1];
       if (left.instructionType.canBePrimitiveNumber(compiler)) {
         return HType.NUMBER;
@@ -487,7 +494,8 @@
     return HType.UNKNOWN;
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isNumber() && right.isNumber()) {
@@ -528,10 +536,21 @@
     return HType.UNKNOWN;
   }
 
-  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction) {
+  HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+                                   Compiler compiler) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
-    if (left.instructionType.isPrimitiveOrNull() || right.isConstantNull()) {
+    HType instructionType = left.instructionType;
+    if (right.isConstantNull() || instructionType.isPrimitiveOrNull()) {
+      return newBuiltinVariant(left, right);
+    }
+    // Make the mask non-nullable to avoid finding a potential
+    // JSNull::operator==.
+    TypeMask mask = instructionType.computeMask(compiler).nonNullable();
+    Selector selector = new TypedSelector(mask, instruction.selector);
+    World world = compiler.world;
+    JavaScriptBackend backend = compiler.backend;
+    if (world.locateSingleElement(selector) == backend.objectEquals) {
       return newBuiltinVariant(left, right);
     }
     return null;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index cf77fd6..84de9d5 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -1083,6 +1083,8 @@
   bool isConstantTrue() => false;
   bool isConstantSentinel() => false;
 
+  bool isInterceptor() => false;
+
   bool isValid() {
     HValidator validator = new HValidator();
     validator.currentBlock = block;
@@ -1314,11 +1316,12 @@
           : const InvokeDynamicSpecializer();
   toString() => 'invoke dynamic: $selector';
   HInstruction get receiver => inputs[0];
+  HInstruction get dartReceiver => isCallOnInterceptor ? inputs[1] : inputs[0];
 
   /**
    * Returns whether this call is on an intercepted method.
    */
-  bool get isInterceptorCall {
+  bool get isInterceptedCall {
     // We know it's a selector call if it follows the interceptor
     // calling convention, which adds the actual receiver as a
     // parameter to the call.
@@ -1329,12 +1332,7 @@
    * Returns whether this call is on an interceptor object.
    */
   bool get isCallOnInterceptor {
-    // When the optimizers know this call does not need an
-    // interceptor, they udpate the receiver of the call to be the
-    // actual receiver.
-    // TODO(ngeoffray): This is very fragile and we should inspect the
-    // receiver instead.
-    return isInterceptorCall && inputs[0] != inputs[1];
+    return isInterceptedCall && receiver.isInterceptor();
   }
 
   int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
@@ -1362,7 +1360,7 @@
   accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
 
   bool isIndexOperatorOnIndexablePrimitive() {
-    return isInterceptorCall
+    return isInterceptedCall
         && selector.kind == SelectorKind.INDEX
         && selector.name == const SourceString('[]')
         && inputs[1].isIndexablePrimitive();
@@ -1844,6 +1842,8 @@
   bool isConstantTrue() => constant.isTrue();
   bool isConstantSentinel() => constant.isSentinel();
 
+  bool isInterceptor() => constant.isInterceptor();
+
   // Maybe avoid this if the literal is big?
   bool isCodeMotionInvariant() => true;
 }
@@ -2034,6 +2034,7 @@
   String toString() => 'interceptor on $interceptedClasses';
   accept(HVisitor visitor) => visitor.visitInterceptor(this);
   HInstruction get receiver => inputs[0];
+  bool isInterceptor() => true;
 
   int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
   bool typeEquals(other) => other is HInterceptor;
@@ -2062,6 +2063,7 @@
     assert(inputs[0] is HConstant);
     assert(inputs[0].instructionType == HType.NULL);
   }
+  bool get isCallOnInterceptor => true;
 
   String toString() => 'one shot interceptor on $selector';
   accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index 08f565a..2a189f2 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -256,7 +256,7 @@
     return null;
   }
 
-  HInstruction handleInterceptorCall(HInvokeDynamic node) {
+  HInstruction handleInterceptedCall(HInvokeDynamic node) {
     // Try constant folding the instruction.
     Operation operation = node.specializer.operation(constantSystem);
     if (operation != null) {
@@ -268,11 +268,10 @@
 
     // Try converting the instruction to a builtin instruction.
     HInstruction instruction =
-        node.specializer.tryConvertToBuiltin(node);
+        node.specializer.tryConvertToBuiltin(node, compiler);
     if (instruction != null) return instruction;
 
     Selector selector = node.selector;
-    var interceptor = node.inputs[0];
     HInstruction input = node.inputs[1];
 
     if (selector.isCall()) {
@@ -321,24 +320,16 @@
       }
     }
 
-    // If the intercepted call is through a constant interceptor, we
-    // know which element to call.
-    if (node is !HOneShotInterceptor
-        && interceptor.isConstant()
-        && selector.isCall()) {
-      assert(interceptor.constant.isInterceptor());
-      ClassElement cls = interceptor.constant.dispatchedType.element;
-      Element target = cls.lookupSelector(selector);
-      if (target != null && selector.applies(target, compiler)) {
-        node.element = target;
-      }
-    }
     return node;
   }
 
   HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
-    if (node.isCallOnInterceptor) return handleInterceptorCall(node);
-    HType receiverType = node.receiver.instructionType;
+    if (node.isInterceptedCall) {
+      HInstruction folded = handleInterceptedCall(node);
+      if (folded != node) return folded;
+    }
+
+    HType receiverType = node.dartReceiver.instructionType;
     Selector selector = receiverType.refine(node.selector, compiler);
     Element element = compiler.world.locateSingleElement(selector);
     // TODO(ngeoffray): Also fold if it's a getter or variable.
@@ -466,13 +457,16 @@
       return node;
     } else if (element.isTypedef()) {
       return node;
+    } else if (element == compiler.functionClass) {
+      return node;
+    }
+
+    if (element == compiler.objectClass || element == compiler.dynamicClass) {
+      return graph.addConstantBool(true, constantSystem);
     }
 
     HType expressionType = node.expression.instructionType;
-    if (identical(element, compiler.objectClass)
-        || identical(element, compiler.dynamicClass)) {
-      return graph.addConstantBool(true, constantSystem);
-    } else if (expressionType.isInteger()) {
+    if (expressionType.isInteger()) {
       if (identical(element, compiler.intClass)
           || identical(element, compiler.numClass)
           || Elements.isNumberOrStringSupertype(element, compiler)) {
@@ -518,22 +512,17 @@
       } else {
         return graph.addConstantBool(false, constantSystem);
       }
-    // Wee need the [:hasTypeArguments:] check because we don't have
+    // We need the [:hasTypeArguments:] check because we don't have
     // the notion of generics in the backend. For example, [:this:] in
     // a class [:A<T>:], is currently always considered to have the
     // raw type.
-    } else if (expressionType.isUseful()
-               && !expressionType.canBeNull()
-               && !RuntimeTypes.hasTypeArguments(type)) {
-      var receiverType = expressionType.computeType(compiler);
-      if (receiverType != null) {
-        if (!receiverType.isMalformed &&
-            !type.isMalformed &&
-            compiler.types.isSubtype(receiverType.element.rawType, type)) {
-          return graph.addConstantBool(true, constantSystem);
-        } else if (expressionType.isExact()) {
-          return graph.addConstantBool(false, constantSystem);
-        }
+    } else if (!RuntimeTypes.hasTypeArguments(type) && !type.isMalformed) {
+      TypeMask expressionMask = expressionType.computeMask(compiler);
+      TypeMask typeMask = new TypeMask.nonNullSubtype(type);
+      if (expressionMask.union(typeMask, compiler) == typeMask) {
+        return graph.addConstantBool(true, constantSystem);
+      } else if (expressionMask.intersection(typeMask, compiler).isEmpty) {
+        return graph.addConstantBool(false, constantSystem);
       }
     }
     return node;
@@ -573,18 +562,45 @@
             && call.inputs[1].isInteger()) {
           return call.inputs[1];
         }
+      } else if (node.receiver.isConstantList()) {
+        var instruction = node.receiver;
+        return graph.addConstantInt(
+            instruction.constant.length, backend.constantSystem);
+      }
+    } else if (node.element == backend.jsStringLength
+               && node.receiver.isConstantString()) {
+        var instruction = node.receiver;
+        return graph.addConstantInt(
+            instruction.constant.length, backend.constantSystem);
+    }
+    return node;
+  }
+
+  HInstruction visitIndex(HIndex node) {
+    if (node.receiver.isConstantList() && node.index.isConstantInteger()) {
+      var instruction = node.receiver;
+      List<Constant> entries = instruction.constant.entries;
+      instruction = node.index;
+      int index = instruction.constant.value;
+      if (index >= 0 && index < entries.length) {
+        return graph.addConstant(entries[index]);
       }
     }
     return node;
   }
 
   HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
-    if (node.isCallOnInterceptor) return handleInterceptorCall(node);
-
-    Element field =
-        findConcreteFieldForDynamicAccess(node.receiver, node.selector);
+    if (node.isInterceptedCall) {
+      HInstruction folded = handleInterceptedCall(node);
+      if (folded != node) return folded;
+    }
+    Element field = findConcreteFieldForDynamicAccess(
+        node.dartReceiver, node.selector);
     if (field == null) return node;
+    return directFieldGet(node.dartReceiver, field);
+  }
 
+  HInstruction directFieldGet(HInstruction receiver, Element field) {
     Modifiers modifiers = field.modifiers;
     bool isAssignable = !(modifiers.isFinal() || modifiers.isConst());
     if (!compiler.resolverWorld.hasInvokedSetter(field, compiler)) {
@@ -600,7 +616,7 @@
       isAssignable = true;
     }
     HFieldGet result = new HFieldGet(
-        field, node.inputs[0], isAssignable: isAssignable);
+        field, receiver, isAssignable: isAssignable);
 
     if (field.getEnclosingClass().isNative()) {
       result.instructionType =
@@ -622,10 +638,13 @@
   }
 
   HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
-    if (node.isCallOnInterceptor) return handleInterceptorCall(node);
+    if (node.isInterceptedCall) {
+      HInstruction folded = handleInterceptedCall(node);
+      if (folded != node) return folded;
+    }
 
-    Element field =
-        findConcreteFieldForDynamicAccess(node.receiver, node.selector);
+    Element field = findConcreteFieldForDynamicAccess(
+        node.dartReceiver, node.selector);
     if (field == null || !field.isAssignable()) return node;
     // Use [:node.inputs.last:] in case the call follows the
     // interceptor calling convention, but is not a call on an
@@ -698,6 +717,13 @@
 
   HInstruction tryComputeConstantInterceptor(HInstruction input,
                                              Set<ClassElement> intercepted) {
+    if (input == graph.explicitReceiverParameter) {
+      // If `explicitReceiverParameter` is set it means the current method is an
+      // interceptor method, and `this` is the interceptor.  The caller just did
+      // `getInterceptor(foo).currentMethod(foo)` to enter the current method.
+      return graph.thisInstruction;
+    }
+
     HType type = input.instructionType;
     ClassElement constantInterceptor;
     if (type.isInteger()) {
@@ -733,7 +759,7 @@
   }
 
   HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
-    HInstruction newInstruction = handleInterceptorCall(node);
+    HInstruction newInstruction = handleInterceptedCall(node);
     if (newInstruction != node) return newInstruction;
 
     HInstruction constant = tryComputeConstantInterceptor(
@@ -790,9 +816,12 @@
   HBoundsCheck insertBoundsCheck(HInstruction node,
                                  HInstruction receiver,
                                  HInstruction index) {
-    bool isAssignable = !receiver.isFixedArray();
+    bool isAssignable = !receiver.isFixedArray() && !receiver.isString();
+    Element element = receiver.isString()
+        ? backend.jsStringLength
+        : backend.jsArrayLength;
     HFieldGet length = new HFieldGet(
-        backend.jsArrayLength, receiver, isAssignable: isAssignable);
+        element, receiver, isAssignable: isAssignable);
     length.instructionType = HType.INTEGER;
     length.instructionType = HType.INTEGER;
     node.block.addBefore(node, length);
@@ -836,7 +865,7 @@
 
   void visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
     Element element = node.element;
-    if (node.isInterceptorCall) return;
+    if (node.isInterceptedCall) return;
     if (element != backend.jsArrayRemoveLast) return;
     if (boundsChecked.contains(node)) return;
     insertBoundsCheck(
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index b2d7a07..bb1044b 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -20,8 +20,9 @@
   bool traceActive = false;
 
   HTracer([String path = "dart.cfg"])
-      : output = GENERATE_SSA_TRACE ? new File(path).openSync(FileMode.WRITE)
-                                    : null;
+      : output = GENERATE_SSA_TRACE
+          ? new File(path).openSync(mode: FileMode.WRITE)
+          : null;
 
   void close() {
     if (enabled) output.closeSync();
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index 62e632d..16bc916 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -34,6 +34,9 @@
     } else if (element == compiler.boolClass
                || element == backend.jsBoolClass) {
       return isNullable ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN;
+    } else if (element == compiler.nullClass
+               || element == backend.jsNullClass) {
+      return HType.NULL;
     }
 
     // TODO(kasperl): A lot of the code in the system currently
@@ -195,6 +198,7 @@
   bool canBePrimitiveNumber(Compiler compiler) => false;
   bool canBePrimitiveString(Compiler compiler) => false;
   bool canBePrimitiveArray(Compiler compiler) => false;
+  bool canBePrimitiveBoolean(Compiler compiler) => false;
 
   /** A type is useful it is not unknown, not conflicting, and not null. */
   bool isUseful() => !isUnknown() && !isConflicting() && !isNull();
@@ -210,9 +214,6 @@
     return new TypedSelector(mask, selector);
   }
 
-  // TODO(kasperl): Try to get rid of these.
-  DartType computeType(Compiler compiler);
-
   /**
    * The intersection of two types is the intersection of its values. For
    * example:
@@ -267,13 +268,11 @@
   bool canBePrimitiveNumber(Compiler compiler) => true;
   bool canBePrimitiveString(Compiler compiler) => true;
   bool canBePrimitiveArray(Compiler compiler) => true;
-
-  DartType computeType(Compiler compiler) {
-    return compiler.objectClass.computeType(compiler);
-  }
+  bool canBePrimitiveBoolean(Compiler compiler) => true;
 
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.subclass(computeType(compiler));
+    DartType base = compiler.objectClass.computeType(compiler);
+    return new TypeMask.subclass(base);
   }
 }
 
@@ -284,13 +283,11 @@
   bool canBePrimitiveNumber(Compiler compiler) => true;
   bool canBePrimitiveString(Compiler compiler) => true;
   bool canBePrimitiveArray(Compiler compiler) => true;
-
-  DartType computeType(Compiler compiler) {
-    return compiler.objectClass.computeType(compiler);
-  }
+  bool canBePrimitiveBoolean(Compiler compiler) => true;
 
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullSubclass(computeType(compiler));
+    DartType base = compiler.objectClass.computeType(compiler);
+    return new TypeMask.nonNullSubclass(base);
   }
 }
 
@@ -299,8 +296,6 @@
   bool canBePrimitive(Compiler compiler) => true;
   bool canBeNull() => false;
 
-  DartType computeType(Compiler compiler) => null;
-
   TypeMask computeMask(Compiler compiler) {
     return new TypeMask.nonNullEmpty();
   }
@@ -320,11 +315,6 @@
   String toString() => 'null type';
   bool isExact() => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsNullClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
     return new TypeMask.empty();
   }
@@ -341,14 +331,12 @@
   const HBooleanOrNullType();
   String toString() => "boolean or null";
   bool isBooleanOrNull() => true;
-
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsBoolClass.computeType(compiler);
-  }
+  bool canBePrimitiveBoolean(Compiler compiler) => true;
 
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.exact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsBoolClass.computeType(compiler);
+    return new TypeMask.exact(base);
   }
 }
 
@@ -358,14 +346,12 @@
   bool isBooleanOrNull() => true;
   String toString() => "boolean";
   bool isExact() => true;
-
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsBoolClass.computeType(compiler);
-  }
+  bool canBePrimitiveBoolean(Compiler compiler) => true;
 
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullExact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsBoolClass.computeType(compiler);
+    return new TypeMask.nonNullExact(base);
   }
 }
 
@@ -375,13 +361,10 @@
   String toString() => "number or null";
   bool canBePrimitiveNumber(Compiler compiler) => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsNumberClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.subclass(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsNumberClass.computeType(compiler);
+    return new TypeMask.subclass(base);
   }
 }
 
@@ -392,13 +375,10 @@
   String toString() => "number";
   bool canBePrimitiveNumber(Compiler compiler) => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsNumberClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullSubclass(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsNumberClass.computeType(compiler);
+    return new TypeMask.nonNullSubclass(base);
   }
 }
 
@@ -407,13 +387,10 @@
   bool isIntegerOrNull() => true;
   String toString() => "integer or null";
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsIntClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.exact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsIntClass.computeType(compiler);
+    return new TypeMask.exact(base);
   }
 }
 
@@ -424,13 +401,10 @@
   String toString() => "integer";
   bool isExact() => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsIntClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullExact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsIntClass.computeType(compiler);
+    return new TypeMask.nonNullExact(base);
   }
 }
 
@@ -439,13 +413,10 @@
   bool isDoubleOrNull() => true;
   String toString() => "double or null";
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsDoubleClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.exact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsDoubleClass.computeType(compiler);
+    return new TypeMask.exact(base);
   }
 }
 
@@ -456,13 +427,10 @@
   String toString() => "double";
   bool isExact() => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsDoubleClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullExact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsDoubleClass.computeType(compiler);
+    return new TypeMask.nonNullExact(base);
   }
 }
 
@@ -471,13 +439,10 @@
   bool isIndexablePrimitive() => true;
   String toString() => "indexable";
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsIndexableClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullSubtype(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsIndexableClass.computeType(compiler);
+    return new TypeMask.nonNullSubtype(base);
   }
 }
 
@@ -487,13 +452,10 @@
   String toString() => "String or null";
   bool canBePrimitiveString(Compiler compiler) => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsStringClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.exact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsStringClass.computeType(compiler);
+    return new TypeMask.exact(base);
   }
 }
 
@@ -505,13 +467,10 @@
   bool isExact() => true;
   bool canBePrimitiveString(Compiler compiler) => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsStringClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullExact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsStringClass.computeType(compiler);
+    return new TypeMask.nonNullExact(base);
   }
 }
 
@@ -521,13 +480,10 @@
   String toString() => "readable array";
   bool canBePrimitiveArray(Compiler compiler) => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsArrayClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullSubclass(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsArrayClass.computeType(compiler);
+    return new TypeMask.nonNullSubclass(base);
   }
 }
 
@@ -536,13 +492,10 @@
   bool isMutableArray() => true;
   String toString() => "mutable array";
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsMutableArrayClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullSubclass(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsMutableArrayClass.computeType(compiler);
+    return new TypeMask.nonNullSubclass(base);
   }
 }
 
@@ -552,13 +505,10 @@
   String toString() => "fixed array";
   bool isExact() => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsFixedArrayClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullExact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsFixedArrayClass.computeType(compiler);
+    return new TypeMask.nonNullExact(base);
   }
 }
 
@@ -568,13 +518,10 @@
   String toString() => "extendable array";
   bool isExact() => true;
 
-  DartType computeType(Compiler compiler) {
-    JavaScriptBackend backend = compiler.backend;
-    return backend.jsExtendableArrayClass.computeType(compiler);
-  }
-
   TypeMask computeMask(Compiler compiler) {
-    return new TypeMask.nonNullExact(computeType(compiler));
+    JavaScriptBackend backend = compiler.backend;
+    DartType base = backend.jsExtendableArrayClass.computeType(compiler);
+    return new TypeMask.nonNullExact(base);
   }
 }
 
@@ -589,6 +536,7 @@
   bool canBePrimitive(Compiler compiler) {
     return canBePrimitiveNumber(compiler)
         || canBePrimitiveArray(compiler)
+        || canBePrimitiveBoolean(compiler)
         || canBePrimitiveString(compiler);
   }
 
@@ -598,6 +546,12 @@
     return mask.contains(jsNumberType, compiler);
   }
 
+  bool canBePrimitiveBoolean(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    DartType jsBoolType = backend.jsBoolClass.computeType(compiler);
+    return mask.contains(jsBoolType, compiler);
+  }
+
   bool canBePrimitiveArray(Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
     DartType jsArrayType = backend.jsArrayClass.rawType;
@@ -614,7 +568,6 @@
     return mask.contains(jsStringType, compiler);
   }
 
-  DartType computeType(Compiler compiler) => mask.base;
   TypeMask computeMask(Compiler compiler) => mask;
 
   bool operator ==(HType other) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index e5c38cd..2d6b6f2 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -126,8 +126,7 @@
   }
 
   HType visitInvokeDynamic(HInvokeDynamic instruction) {
-    int receiverIndex = instruction.isInterceptorCall ? 1 : 0;
-    HType receiverType = instruction.inputs[receiverIndex].instructionType;
+    HType receiverType = instruction.dartReceiver.instructionType;
     Selector refined = receiverType.refine(instruction.selector, compiler);
     HType type = new HType.inferredTypeForSelector(refined, compiler);
     if (type.isUseful()) return type;
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index b6bf919..c61db0c 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -4,8 +4,10 @@
 
 library simple_types_inferrer;
 
+import 'dart:collection' show Queue;
+
 import '../closure.dart' show ClosureClassMap, ClosureScope;
-import '../dart_types.dart' show DartType, FunctionType;
+import '../dart_types.dart' show DartType, FunctionType, TypeKind;
 import '../elements/elements.dart';
 import '../native_handler.dart' as native;
 import '../tree/tree.dart';
@@ -20,21 +22,21 @@
 
 /**
  * A work queue that ensures there are no duplicates, and adds and
- * removes in LIFO.
+ * removes in FIFO.
  */
 class WorkSet<E extends Element> {
-  final List<E> queue = new List<E>();
+  final Queue<E> queue = new Queue<E>();
   final Set<E> elementsInQueue = new Set<E>();
 
   void add(E element) {
     element = element.implementation;
     if (elementsInQueue.contains(element)) return;
-    queue.add(element);
+    queue.addLast(element);
     elementsInQueue.add(element);
   }
 
   E remove() {
-    E element = queue.removeLast();
+    E element = queue.removeFirst();
     elementsInQueue.remove(element);
     return element;
   }
@@ -52,8 +54,8 @@
    * Maps a final field to a map from generative constructor to the
    * inferred type of the field in that generative constructor.
    */
-  final Map<Element, Map<Element, TypeMask>> typesOfFinalFields =
-      new Map<Element, Map<Element, TypeMask>>();
+  final Map<Element, Map<Node, TypeMask>> typesOfFinalFields =
+      new Map<Element, Map<Node, TypeMask>>();
 
   /**
    * The number of generative constructors that need to be visited
@@ -70,10 +72,13 @@
    * Records that the generative [constructor] has inferred [type]
    * for the final [field].
    */
-  void recordFinalFieldType(Element constructor, Element field, TypeMask type) {
-    Map<Element, TypeMask> typesFor = typesOfFinalFields.putIfAbsent(
-        field, () => new Map<Element, TypeMask>());
-    typesFor[constructor] = type;
+  void recordFinalFieldType(Node node,
+                            Element constructor,
+                            Element field,
+                            TypeMask type) {
+    Map<Node, TypeMask> typesFor = typesOfFinalFields.putIfAbsent(
+        field, () => new Map<Node, TypeMask>());
+    typesFor[node] = type;
   }
 
   /**
@@ -104,6 +109,12 @@
     return identical(this, other);
   }
 
+  TypeMask nullable() {
+    throw 'Unsupported operation';
+  }
+
+  bool get isNullable => true;
+
   String toString() => '$name sentinel type mask';
 }
 
@@ -133,6 +144,24 @@
       new Map<Element, Map<Node, TypeMask>>();
 
   /**
+   * Maps an element to the type of its parameters at call sites.
+   */
+  final Map<Element, Map<Node, ArgumentsTypes>> typeOfArguments =
+      new Map<Element, Map<Node, ArgumentsTypes>>();
+
+  /**
+   * Maps an optional parameter to its default type.
+   */
+  final Map<Element, TypeMask> defaultTypeOfParameter =
+      new Map<Element, TypeMask>();
+
+  /**
+   * Set of methods that the inferrer found could be closurized. We
+   * don't compute parameter types for such methods.
+   */
+  final Set<Element> methodsThatCanBeClosurized = new Set<Element>();
+
+  /**
    * Maps an element to the number of times this type inferrer
    * analyzed it.
    */
@@ -146,6 +175,23 @@
       new Map<ClassElement, ClassInfoForFinalFields>();
 
   /**
+   * A map of constraints on a setter. When computing the type
+   * of a field, these [Node] are initially discarded, and once the
+   * type is computed, we make sure these constraints are satisfied
+   * for that type. For example:
+   * 
+   * [: field++ ], or [: field += 42 :], the constraint is on the
+   * operator+, and we make sure that a typed selector with the found
+   * type returns that type.
+   * 
+   * [: field = other.field :], the constraint in on the [:field]
+   * getter selector, and we make sure that the getter selector
+   * returns that type.
+   *
+   */
+  final Map<Node, Selector> setterConstraints = new Map<Node, Selector>();
+
+  /**
    * The work list of the inferrer.
    */
   final WorkSet<Element> workSet = new WorkSet<Element>();
@@ -156,13 +202,6 @@
   final int MAX_ANALYSIS_COUNT_PER_ELEMENT = 5;
 
   /**
-   * Sentinel used by the inferrer to notify that it gave up finding a type
-   * on a specific element.
-   */
-  final TypeMask giveUpType = new SentinelTypeMask('give up');
-  bool isGiveUpType(TypeMask type) => identical(type, giveUpType);
-
-  /**
    * Sentinel used by the inferrer to notify that it does not know
    * the type of a specific element.
    */
@@ -257,13 +296,12 @@
     return getTypeIfValuable(typeOfSelector(selector));
   }
 
+  bool isTypeValuable(TypeMask returnType) {
+    return !isDynamicType(returnType);
+  }
+
   TypeMask getTypeIfValuable(TypeMask returnType) {
-    if (isDynamicType(returnType)
-        || isGiveUpType(returnType)
-        || returnType == nullType) {
-      return null;
-    }
-    return returnType;
+    return isTypeValuable(returnType) ? returnType : null;
   }
 
   /**
@@ -291,14 +329,16 @@
     // If we have analyzed all the world, we know all assigments to
     // fields and can therefore infer a type for them.
     typeOfFields.keys.forEach(updateNonFinalFieldType);
+    // We also know all calls to methods.
+    typeOfArguments.keys.forEach(updateArgumentsType);
   }
 
   /**
    * Enqueues [e] in the work queue if it is valuable.
    */
   void enqueueAgain(Element e) {
-    TypeMask type = e.isField() ? typeOf[e] : returnTypeOf[e];
-    if (analyzeCount[e] > MAX_ANALYSIS_COUNT_PER_ELEMENT) return;
+    int count = analyzeCount[e];
+    if (count != null && count > MAX_ANALYSIS_COUNT_PER_ELEMENT) return;
     workSet.add(e);
   }
 
@@ -331,8 +371,8 @@
         set.add(element);
     });
 
-    // This iteration assumes the [WorkSet] is LIFO.
-    for (int i = max; i >= 0; i--) {
+    // This iteration assumes the [WorkSet] is FIFO.
+    for (int i = 0; i <= max; i++) {
       Set<Element> set = methodSizes[i];
       if (set != null) {
         set.forEach((e) { workSet.add(e); });
@@ -395,7 +435,6 @@
         rawTypeOf(backend.mapImplementation));
     constMapType = new TypeMask.nonNullSubtype(
         rawTypeOf(backend.constMapImplementation));
-
     functionType = new TypeMask.nonNullSubtype(
         rawTypeOf(backend.functionImplementation));
     typeType = new TypeMask.nonNullExact(
@@ -404,18 +443,13 @@
 
   dump() {
     int interestingTypes = 0;
-    int giveUpTypes = 0;
     returnTypeOf.forEach((Element element, TypeMask type) {
-      if (isGiveUpType(type)) {
-        giveUpTypes++;
-      } else if (type != nullType && !isDynamicType(type)) {
+      if (type != nullType && !isDynamicType(type)) {
         interestingTypes++;
       }
     });
     typeOf.forEach((Element element, TypeMask type) {
-      if (isGiveUpType(type)) {
-        giveUpTypes++;
-      } else if (type != nullType && !isDynamicType(type)) {
+      if (type != nullType && !isDynamicType(type)) {
         interestingTypes++;
       }
     });
@@ -423,7 +457,7 @@
     compiler.log('Type inferrer re-analyzed methods $recompiles times '
                  'in ${recomputeWatch.elapsedMilliseconds} ms.');
     compiler.log('Type inferrer found $interestingTypes interesting '
-                 'types and gave up on $giveUpTypes elements.');
+                 'types.');
   }
 
   /**
@@ -434,6 +468,7 @@
     analyzeCount.clear();
     classInfoForFinalFields.clear();
     typeOfFields.clear();
+    setterConstraints.clear();
   }
 
   bool analyze(Element element) {
@@ -476,6 +511,7 @@
   }
 
   bool recordType(Element analyzedElement, TypeMask type) {
+    assert(type != null);
     return internalRecordType(analyzedElement, type, typeOf);
   }
 
@@ -523,16 +559,18 @@
       });
     } else if (element.isNative()) {
       return returnTypeOf.putIfAbsent(element, () {
-        // Only functions are native.
-        FunctionType functionType = element.computeType(compiler);
-        DartType returnType = functionType.returnType;
+        var elementType = element.computeType(compiler);
+        if (elementType.kind != TypeKind.FUNCTION) {
+          return dynamicType;
+        }
+        DartType returnType = elementType.returnType;
         return returnType.isVoid
             ? nullType
             : new TypeMask.subtype(returnType.asRaw());
       });
     }
     TypeMask returnType = returnTypeOf[element];
-    if (returnType == null || isGiveUpType(returnType)) {
+    if (returnType == null) {
       return dynamicType;
     }
     assert(returnType != null);
@@ -546,12 +584,14 @@
   TypeMask typeOfElement(Element element) {
     element = element.implementation;
     if (isNativeElement(element) && element.isField()) {
-      return typeOf.putIfAbsent(element, () {
+      var type = typeOf.putIfAbsent(element, () {
         return new TypeMask.subtype(element.computeType(compiler).asRaw());
       });
+      assert(type != null);
+      return type;
     }
     TypeMask type = typeOf[element];
-    if (type == null || isGiveUpType(type)) {
+    if (type == null) {
       return dynamicType;
     }
     assert(type != null);
@@ -570,28 +610,9 @@
     TypeMask result;
     iterateOverElements(selector, (Element element) {
       assert(element.isImplementation);
-      TypeMask type;
-      if (selector.isGetter()) {
-        if (element.isFunction()) {
-          type = functionType;
-        } else if (element.isField()) {
-          type = typeOf[element];
-        } else if (element.isGetter()) {
-          type = returnTypeOf[element];
-        }
-      } else {
-        type = returnTypeOf[element];
-      }
-      if (type == null
-          || isDynamicType(type)
-          || isGiveUpType(type)
-          || (type != result && result != null)) {
-        result = dynamicType;
-        return false;
-      } else {
-        result = type;
-        return true;
-      }
+      TypeMask type = typeOfElementWithSelector(element, selector);
+      result = computeLUB(result, type);
+      return isTypeValuable(result);
     });
     if (result == null) {
       result = dynamicType;
@@ -599,6 +620,22 @@
     return result;
   }
 
+  TypeMask typeOfElementWithSelector(Element element, Selector selector) {
+    if (selector.isGetter()) {
+      if (element.isFunction()) {
+        // [functionType] is null if the inferrer did not run.
+        return functionType == null ? dynamicType : functionType;
+      } else if (element.isField()) {
+        return typeOfElement(element);
+      } else {
+        assert(element.isGetter());
+        return returnTypeOfElement(element);
+      }
+    } else {
+      return returnTypeOfElement(element);
+    }
+  }
+
   bool isNotClosure(Element element) {
     // If the outermost enclosing element of [element] is [element]
     // itself, we know it cannot be a closure.
@@ -606,51 +643,187 @@
     return outermost.declaration == element.declaration;
   }
 
+  void addCaller(Element caller, Element callee) {
+    assert(caller.isImplementation);
+    assert(callee.isImplementation);
+    assert(isNotClosure(caller));
+    Set<Element> callers = callersOf.putIfAbsent(
+        callee, () => new Set<Element>());
+    callers.add(caller);
+  }
+
+  bool addArguments(Node node, Element element, ArgumentsTypes arguments) {
+    Map<Node, ArgumentsTypes> types = typeOfArguments.putIfAbsent(
+        element, () => new Map<Node, ArgumentsTypes>());
+    ArgumentsTypes existing = types[node];
+    types[node] = arguments;
+    return existing != arguments;
+  }
+
   /**
    * Registers that [caller] calls [callee] with the given
    * [arguments].
    */
-  void registerCalledElement(Element caller,
+  void registerCalledElement(Send send,
+                             Selector selector,
+                             Element caller,
                              Element callee,
-                             ArgumentsTypes arguments) {
+                             ArgumentsTypes arguments,
+                             bool inLoop) {
+    if (inLoop) {
+      // For instance methods, we only register a selector called in a
+      // loop if it is a typed selector, to avoid marking too many
+      // methods as being called from within a loop. This cuts down
+      // on the code bloat.
+      // TODO(ngeoffray): We should move the filtering on the selector
+      // in the backend. It is not the inferrer role to do this kind
+      // of optimization.
+      if (Elements.isStaticOrTopLevel(callee) || selector.mask != null) {
+        compiler.world.addFunctionCalledInLoop(callee);
+      }
+    }
+
     assert(isNotClosure(caller));
-    if (analyzeCount.containsKey(caller)) return;
     callee = callee.implementation;
-    addCaller(caller, callee);
+    if (!analyzeCount.containsKey(caller)) {
+      addCaller(caller, callee);
+    }
+
+    if (selector.isSetter() && callee.isField()) {
+      recordNonFinalFieldElementType(send, callee, arguments.positional[0]);
+      return;
+    } else if (selector.isGetter()) {
+      assert(arguments == null);
+      if (callee.isFunction()) {
+        methodsThatCanBeClosurized.add(callee);
+      }
+      return;
+    } else if (callee.isField()) {
+      // We're not tracking closure calls.
+      return;
+    } else if (callee.isGetter()) {
+      // Getters don't have arguments.
+      return;
+    }
+    FunctionElement function = callee;
+    if (function.computeSignature(compiler).parameterCount == 0) return;
+
+    assert(arguments != null);
+    bool isUseful = addArguments(send, callee, arguments);
+    if (hasAnalyzedAll && isUseful) {
+      updateArgumentsType(callee);
+    }
   }
 
-  void addCaller(Element caller, Element callee) {
-    Set<Element> callers = callersOf.putIfAbsent(
-        callee, () => new Set<Element>());
-    callers.add(caller);
+  void unregisterCalledElement(Send send,
+                               Selector selector,
+                               Element caller,
+                               Element callee) {
+    if (callee.isField()) {
+      if (selector.isSetter()) {
+        Map<Node, TypeMask> types = typeOfFields[callee];
+        if (types == null || !types.containsKey(send)) return;
+        types.remove(send);
+        if (hasAnalyzedAll) updateNonFinalFieldType(callee);
+      }
+    } if (callee.isGetter()) {
+      return;
+    } else {
+      Map<Node, ArgumentsTypes> types = typeOfArguments[callee];
+      if (types == null || !types.containsKey(send)) return;
+      types.remove(send);
+      if (hasAnalyzedAll) updateArgumentsType(callee);
+    }
+  }
+
+  /**
+   * Computes the parameter types of [element], based on all call sites we
+   * have collected on that [element]. This method can only be called after
+   * we have analyzed all elements in the world.
+   */
+  void updateArgumentsType(FunctionElement element) {
+    assert(hasAnalyzedAll);
+    if (methodsThatCanBeClosurized.contains(element)) return;
+    FunctionSignature signature = element.computeSignature(compiler);
+
+    if (typeOfArguments[element].isEmpty) {
+      signature.forEachParameter((Element parameter) {
+        typeOf.remove(parameter);
+      });
+      return;
+    }
+
+    int parameterIndex = 0;
+    bool changed = false;
+    bool visitingOptionalParameter = false;
+    signature.forEachParameter((Element parameter) {
+      if (parameter == signature.firstOptionalParameter) {
+        visitingOptionalParameter = true;
+      }
+      TypeMask type;
+      typeOfArguments[element].forEach((_, ArgumentsTypes arguments) {
+        if (!visitingOptionalParameter) {
+          type = computeLUB(type, arguments.positional[parameterIndex]);
+        } else {
+          TypeMask argumentType = signature.optionalParametersAreNamed
+              ? arguments.named[parameter.name]
+              : parameterIndex < arguments.positional.length
+                  ? arguments.positional[parameterIndex]
+                  : null;
+          if (argumentType == null) {
+            argumentType = defaultTypeOfParameter[parameter];
+          }
+          assert(argumentType != null);
+          type = computeLUB(type, argumentType);
+        }
+      });
+      if (recordType(parameter, type)) {
+        changed = true;
+      }
+      parameterIndex++;
+    });
+
+    if (changed) enqueueAgain(element);
   }
 
   /**
    * Registers that [caller] calls an element matching [selector]
    * with the given [arguments].
    */
-  void registerCalledSelector(Element caller,
-                              Selector selector,
-                              ArgumentsTypes arguments) {
+  TypeMask registerCalledSelector(Send send,
+                                  Selector selector,
+                                  TypeMask receiverType,
+                                  Element caller,
+                                  ArgumentsTypes arguments,
+                                  bool inLoop) {
     assert(isNotClosure(caller));
-    if (analyzeCount.containsKey(caller)) return;
-    iterateOverElements(selector, (Element element) {
+    Selector typedSelector = isDynamicType(receiverType)
+        ? selector
+        : new TypedSelector(receiverType, selector);
+
+    TypeMask result;
+    iterateOverElements(typedSelector, (Element element) {
       assert(element.isImplementation);
-      registerCalledElement(caller, element, arguments);
+      // TODO(ngeoffray): Enable unregistering by having a
+      // [: TypeMask.appliesTo(element) :] method, that will return
+      // whether [: element :] is a potential target for the type.
+      if (true) {
+        registerCalledElement(
+            send, typedSelector, caller, element, arguments, inLoop);
+      } else {
+        unregisterCalledElement(send, selector, caller, element);
+      }
+      if (!selector.isSetter()) {
+        TypeMask type = typeOfElementWithSelector(element, selector);
+        result = computeLUB(result, type);
+      }
       return true;
     });
-  }
 
-  /**
-   * Registers that [caller] closurizes [function].
-   */
-  void registerGetFunction(Element caller, Element function) {
-    assert(isNotClosure(caller));
-    assert(caller.isImplementation);
-    if (analyzeCount.containsKey(caller)) return;
-    // We don't register that [caller] calls [function] because we
-    // don't know if the code is going to call it, and if it is, then
-    // the inferrer has lost track of its identity anyway.
+    if (result == null) {
+      result = dynamicType;
+    }
+    return result;
   }
 
   /**
@@ -665,22 +838,6 @@
   }
 
   /**
-   * Records an assignment to [selector] with the given
-   * [argumentType]. This method iterates over fields that match
-   * [selector] and update their type.
-   */
-  void recordNonFinalFieldSelectorType(Node node,
-                                       Selector selector,
-                                       TypeMask argumentType) {
-    iterateOverElements(selector, (Element element) {
-      if (element.isField()) {
-        recordNonFinalFieldElementType(node, element, argumentType);
-      }
-      return true;
-    });
-  }
-
-  /**
    * Records an assignment to [element] with the given
    * [argumentType].
    */
@@ -692,7 +849,54 @@
     map[node] = argumentType;
     // If we have analyzed all elements, we can update the type of the
     // field right away.
-    if (hasAnalyzedAll) updateNonFinalFieldType(element);
+    if (hasAnalyzedAll) {
+      // Only update if the new type provides value.
+      if (typeOf[element] != argumentType) {
+        updateNonFinalFieldType(element);
+      }
+    }
+  }
+
+  TypeMask computeFieldTypeWithConstraints(Element element, Map types) {
+    Set<Selector> constraints = new Set<Selector>();
+    TypeMask fieldType;
+    types.forEach((Node node, TypeMask mask) {
+      Selector constraint = setterConstraints[node];
+      if (constraint != null) {
+        // If this update has a constraint, we collect it and don't
+        // use its type.
+        constraints.add(constraint);
+      } else {
+        fieldType = computeLUB(fieldType, mask);
+      }
+    });
+
+    if (!constraints.isEmpty && !isDynamicType(fieldType)) {
+      // Now that we have found a type, we go over the collected
+      // constraints, and make sure they apply to the found type. We
+      // update [typeOf] to make sure [typeOfSelector] knows the field
+      // type.
+      TypeMask existing = typeOf[element];
+      typeOf[element] = fieldType;
+
+      for (Selector constraint in constraints) {
+        if (constraint.isOperator()) {
+          // If the constraint is on an operator, we type the receiver
+          // to be the field.
+          constraint = new TypedSelector(fieldType, constraint);
+        } else {
+          // Otherwise the constraint is on the form [: field = other.field :].
+          assert(constraint.isGetter());
+        }
+        fieldType = computeLUB(fieldType, typeOfSelector(constraint));
+      }
+      if (existing == null) {
+        typeOf.remove(element);
+      } else {
+        typeOf[element] = existing;
+      }
+    }
+    return fieldType;
   }
 
   /**
@@ -701,12 +905,11 @@
    * we have analyzed all elements in the world.
    */
   void updateNonFinalFieldType(Element element) {
+    if (isNativeElement(element)) return;
     assert(hasAnalyzedAll);
 
-    TypeMask fieldType;
-    typeOfFields[element].forEach((_, TypeMask mask) {
-      fieldType = computeLUB(fieldType, mask);
-    });
+    TypeMask fieldType = computeFieldTypeWithConstraints(
+        element, typeOfFields[element]);
 
     // If the type of [element] has changed, re-analyze its users.
     if (recordType(element, fieldType)) {
@@ -718,14 +921,15 @@
    * Records in [classInfoForFinalFields] that [constructor] has
    * inferred [type] for the final [field].
    */
-  void recordFinalFieldType(Element constructor, Element field, TypeMask type) {
+  void recordFinalFieldType(
+      Node node, Element constructor, Element field, TypeMask type) {
     // If the field is being set at its declaration site, it is not
     // being tracked in the [classInfoForFinalFields] map.
     if (constructor == field) return;
     assert(field.modifiers.isFinal() || field.modifiers.isConst());
     ClassElement cls = constructor.getEnclosingClass();
     ClassInfoForFinalFields info = classInfoForFinalFields[cls.implementation];
-    info.recordFinalFieldType(constructor, field, type);
+    info.recordFinalFieldType(node, constructor, field, type);
   }
 
   /**
@@ -748,13 +952,13 @@
   void updateFinalFieldsType(ClassInfoForFinalFields info) {
     assert(info.isDone);
     info.typesOfFinalFields.forEach((Element field,
-                                     Map<Element, TypeMask> types) {
+                                     Map<Node, TypeMask> types) {
+      if (isNativeElement(field)) return;
       assert(field.modifiers.isFinal());
-      TypeMask fieldType;
-      types.forEach((_, TypeMask type) {
-        fieldType = computeLUB(fieldType, type);
-      });
-      recordType(field, fieldType);
+      TypeMask fieldType = computeFieldTypeWithConstraints(field, types);
+      if (recordType(field, fieldType)) {
+        enqueueCallersOf(field);
+      }
     });
   }
 
@@ -766,10 +970,6 @@
     assert(secondType != null);
     if (firstType == null) {
       return secondType;
-    } else if (isGiveUpType(firstType)) {
-      return firstType;
-    } else if (isGiveUpType(secondType)) {
-      return secondType;
     } else if (isDynamicType(secondType)) {
       return secondType;
     } else if (isDynamicType(firstType)) {
@@ -777,10 +977,14 @@
     } else {
       TypeMask union = firstType.union(secondType, compiler);
       // TODO(kasperl): If the union isn't nullable it seems wasteful
-      // to give up. Fix that.
-      return union.containsAll(compiler) ? giveUpType : union;
+      // to use dynamic. Fix that.
+      return union.containsAll(compiler) ? dynamicType : union;
     }
   }
+
+  void recordSetterConstraint(Node node, Selector selector) {
+    setterConstraints[node] = selector;
+  }
 }
 
 /**
@@ -788,10 +992,22 @@
  */
 class ArgumentsTypes {
   final List<TypeMask> positional;
-  final Map<Identifier, TypeMask> named;
-  ArgumentsTypes(this.positional, this.named);
+  final Map<SourceString, TypeMask> named;
+  ArgumentsTypes(this.positional, named)
+    : this.named = (named == null) ? new Map<SourceString, TypeMask>() : named;
   int get length => positional.length + named.length;
-  toString() => "{ positional = $positional, named = $named }";
+  String toString() => "{ positional = $positional, named = $named }";
+  bool operator==(other) {
+    if (positional.length != other.positional.length) return false;
+    if (named.length != other.named.length) return false;
+    for (int i = 0; i < positional.length; i++) {
+      if (positional[i] != other.positional[i]) return false;
+    }
+    named.forEach((name, type) {
+      if (other.named[name] != type) return false;
+    });
+    return true;
+  }
 }
 
 /**
@@ -838,7 +1054,6 @@
       // will be executed, so all assigments in that block are
       // potential types after we have left it.
       type = inferrer.computeLUB(locals[local], type);
-      if (inferrer.isGiveUpType(type)) type = inferrer.dynamicType;
     }
     locals[local] = type;
   }
@@ -869,7 +1084,6 @@
         return;
       }
       TypeMask type = inferrer.computeLUB(oldType, otherType);
-      if (inferrer.isGiveUpType(type)) type = inferrer.dynamicType;
       if (type != oldType) changed = true;
       locals[local] = type;
     });
@@ -933,7 +1147,9 @@
 
   bool visitingInitializers = false;
   bool isConstructorRedirect = false;
+  int loopLevel = 0;
 
+  bool get inLoop => loopLevel > 0;
   bool get isThisExposed => locals.isThisExposed;
   void set isThisExposed(value) { locals.isThisExposed = value; }
 
@@ -981,29 +1197,49 @@
       });
     }
     if (analyzedElement.isField()) {
-      returnType = visit(node.asSendSet().arguments.head);
-    } else if (analyzedElement.isGenerativeConstructor()) {
-      FunctionElement function = analyzedElement;
-      FunctionSignature signature = function.computeSignature(compiler);
+      return visit(node.asSendSet().arguments.head);
+    }
+    
+    FunctionElement function = analyzedElement;
+    FunctionSignature signature = function.computeSignature(compiler);
+    signature.forEachOptionalParameter((element) {
+      Node node = element.parseNode(compiler);
+      Send send = node.asSendSet();
+      inferrer.defaultTypeOfParameter[element] = (send == null)
+          ? inferrer.nullType
+          : visit(send.arguments.head);
+      assert(inferrer.defaultTypeOfParameter[element] != null);
+    });
+
+    if (analyzedElement.isNative()) {
+      // Native methods do not have a body, and we currently just say
+      // they return dynamic.
+      return inferrer.dynamicType;
+    }
+
+    if (analyzedElement.isGenerativeConstructor()) {
+      isThisExposed = false;
       signature.forEachParameter((element) {
-        // We don't track argument types yet, so just set the fields
-        // and parameters as dynamic.
+        TypeMask parameterType = inferrer.typeOfElement(element);
         if (element.kind == ElementKind.FIELD_PARAMETER) {
           if (element.fieldElement.modifiers.isFinal()) {
             inferrer.recordFinalFieldType(
-                analyzedElement, element.fieldElement, inferrer.dynamicType);
+                node,
+                analyzedElement,
+                element.fieldElement,
+                parameterType);
           } else {
+            locals.updateField(element.fieldElement, parameterType);
             inferrer.recordNonFinalFieldElementType(
                 element.parseNode(compiler),
                 element.fieldElement,
-                inferrer.dynamicType);
+                parameterType);
           }
         } else {
-          locals.update(element, inferrer.dynamicType);
+          locals.update(element, parameterType);
         }
       });
       visitingInitializers = true;
-      isThisExposed = false;
       visit(node.initializers);
       visitingInitializers = false;
       visit(node.body);
@@ -1022,27 +1258,30 @@
       }
       inferrer.doneAnalyzingGenerativeConstructor(analyzedElement);
       returnType = new TypeMask.nonNullExact(inferrer.rawTypeOf(cls));
-    } else if (analyzedElement.isNative()) {
-      // Native methods do not have a body, and we currently just say
-      // they return dynamic.
-      returnType = inferrer.dynamicType;
     } else {
-      FunctionElement function = analyzedElement;
-      FunctionSignature signature = function.computeSignature(compiler);
       signature.forEachParameter((element) {
-        // We don't track argument types yet, so just set the
-        // parameters as dynamic.
-        locals.update(element, inferrer.dynamicType);
+        locals.update(element, inferrer.typeOfElement(element));
       });
       visit(node.body);
       if (returnType == null) {
         // No return in the body.
         returnType = inferrer.nullType;
-      } else if (!locals.seenReturn) {
+      } else if (!locals.seenReturn && !inferrer.isDynamicType(returnType)) {
         // We haven't seen returns on all branches. So the method may
         // also return null.
         returnType = returnType.nullable();
       }
+
+      if (analyzedElement.name == const SourceString('==')) {
+        // TODO(ngeoffray): Should this be done at the call site?
+        // When the argument passed in is null, we know we return a
+        // bool.
+        signature.forEachParameter((Element parameter) {
+          if (inferrer.typeOfElement(parameter).isNullable){
+            returnType = inferrer.computeLUB(returnType, inferrer.boolType);
+          }
+        });
+      }
     }
 
     if (analyzedElement == outermostElement) {
@@ -1054,7 +1293,6 @@
       });
       // TODO(ngeoffray): Re-analyze method if [changed]?
     }
-
     return returnType;
   }
 
@@ -1120,7 +1358,6 @@
       // parameters), as well as captured argument checks.
       if (locals.locals[variable] == null) return;
       inferrer.recordType(variable, locals.locals[variable]);
-      assert(!inferrer.isGiveUpType(inferrer.typeOf[variable]));
     });
 
     return inferrer.functionType;
@@ -1297,17 +1534,13 @@
       // [: foo = 42 :] or [: foo.bar = 42 :].
       ArgumentsTypes arguments =  new ArgumentsTypes([rhsType], null);
       if (Elements.isStaticOrTopLevelField(element)) {
-        if (element.isSetter()) {
-          inferrer.registerCalledElement(outermostElement, element, arguments);
-        } else {
-          assert(element.isField());
-          inferrer.recordNonFinalFieldElementType(node, element, rhsType);
-        }
+        handleStaticSend(node, setterSelector, element, arguments);
       } else if (Elements.isUnresolved(element) || element.isSetter()) {
         handleDynamicSend(node, setterSelector, receiverType, arguments);
       } else if (element.isField()) {
         if (element.modifiers.isFinal()) {
-          inferrer.recordFinalFieldType(outermostElement, element, rhsType);
+          inferrer.recordFinalFieldType(
+              node, outermostElement, element, rhsType);
         } else {
           locals.updateField(element, rhsType);
           if (visitingInitializers) {
@@ -1319,6 +1552,25 @@
       } else if (Elements.isLocal(element)) {
         locals.update(element, rhsType);
       }
+
+      if (!Elements.isLocal(element)) {
+        // Recognize a constraint of the form [: field = other.field :].
+        // Note that we check if the right hand side is a local to
+        // recognize the situation [: var a = 42; this.a = a; :]. Our
+        // constraint mechanism only works with members or top level
+        // elements.
+        var rhs = node.arguments.head;
+        if (rhs.asSend() != null
+            && rhs.isPropertyAccess
+            && !Elements.isLocal(elements[rhs])
+            && rhs.selector.source == node.selector.asIdentifier().source) {
+          // TODO(ngeoffray): We should update selectors in the
+          // element tree and find out if the typed selector still
+          // applies to the receiver type.
+          Selector constraint = elements.getSelector(rhs);
+          inferrer.recordSetterConstraint(node, constraint);
+        }
+      }
       return rhsType;
     } else {
       // [: foo++ :] or [: foo += 1 :].
@@ -1330,32 +1582,21 @@
         getterType = getterElement.isField()
             ? inferrer.typeOfElement(element)
             : inferrer.returnTypeOfElement(element);
-        if (getterElement.isGetter()) {
-          inferrer.registerCalledElement(outermostElement, getterElement, null);
-        }
+        handleStaticSend(node, getterSelector, getterElement, null);
         newType = handleDynamicSend(
             node, operatorSelector, getterType, operatorArguments);
-        if (element.isField()) {
-          inferrer.recordNonFinalFieldElementType(node, element, newType);
-        } else {
-          assert(element.isSetter());
-          inferrer.registerCalledElement(
-              outermostElement, element, new ArgumentsTypes([newType], null));
-        }
-      } else if (Elements.isUnresolved(element) || element.isSetter()) {
+        handleStaticSend(
+            node, setterSelector, element,
+            new ArgumentsTypes([newType], null));
+      } else if (Elements.isUnresolved(element)
+                 || element.isSetter()
+                 || element.isField()) {
         getterType = handleDynamicSend(
             node, getterSelector, receiverType, null);
         newType = handleDynamicSend(
             node, operatorSelector, getterType, operatorArguments);
         handleDynamicSend(node, setterSelector, receiverType,
                           new ArgumentsTypes([newType], null));
-      } else if (element.isField()) {
-        assert(!element.modifiers.isFinal());
-        getterType = inferrer.dynamicType; // The type of the field.
-        newType = handleDynamicSend(
-            node, operatorSelector, getterType, operatorArguments);
-        handleDynamicSend(node, setterSelector, receiverType,
-                          new ArgumentsTypes([newType], null));
       } else if (Elements.isLocal(element)) {
         getterType = locals.use(element);
         newType = handleDynamicSend(
@@ -1368,6 +1609,11 @@
             node, operatorSelector, getterType, operatorArguments);
       }
 
+      if (!Elements.isLocal(element)) {
+        // Record a constraint of the form [: field++ :], or [: field += 42 :].
+        inferrer.recordSetterConstraint(node, operatorSelector);
+      }
+
       if (node.isPostfix) {
         return getterType;
       } else {
@@ -1395,11 +1641,12 @@
     // are calling does not expose this.
     isThisExposed = true;
     if (node.isPropertyAccess) {
-      inferrer.registerCalledElement(outermostElement, element, null);
+      handleStaticSend(node, selector, element, null);
       return inferrer.typeOfElement(element);
     } else if (element.isFunction()) {
+      if (!selector.applies(element, compiler)) return inferrer.dynamicType;
       ArgumentsTypes arguments = analyzeArguments(node.arguments);
-      inferrer.registerCalledElement(outermostElement, element, arguments);
+      handleStaticSend(node, selector, element, arguments);
       return inferrer.returnTypeOfElement(element);
     } else {
       analyzeArguments(node.arguments);
@@ -1417,18 +1664,21 @@
     if (element.isForeign(compiler)) {
       return handleForeignSend(node);
     }
+    Selector selector = elements.getSelector(node);
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     if (Elements.isUnresolved(element)
         || element.isGetter()
         || element.isField()) {
       if (element.isGetter()) {
-        inferrer.registerCalledElement(outermostElement, element, null);
+        handleStaticSend(node, new Selector.getterFrom(selector),
+                         element, null);
       }
       return inferrer.dynamicType;
     }
 
-    Selector selector = elements.getSelector(node);
-    inferrer.registerCalledElement(outermostElement, element, arguments);
+    if (!selector.applies(element, compiler)) return inferrer.dynamicType;
+
+    handleStaticSend(node, selector, element, arguments);
     if (Elements.isGrowableListConstructorCall(element, node, compiler)) {
       return inferrer.growableListType;
     } else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
@@ -1479,6 +1729,10 @@
               inferrer.rawTypeOf(type.element));
         }
         returnType = inferrer.computeLUB(returnType, mappedType);
+        if (!inferrer.isTypeValuable(returnType)) {
+          returnType = inferrer.dynamicType;
+          break;
+        }
       }
       return returnType;
     } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')
@@ -1491,12 +1745,12 @@
 
   ArgumentsTypes analyzeArguments(Link<Node> arguments) {
     List<TypeMask> positional = [];
-    Map<Identifier, TypeMask> named = new Map<Identifier, TypeMask>();
+    Map<SourceString, TypeMask> named = new Map<SourceString, TypeMask>();
     for (var argument in arguments) {
       NamedArgument namedArgument = argument.asNamedArgument();
       if (namedArgument != null) {
         argument = namedArgument.expression;
-        named[namedArgument.name] = argument.accept(this);
+        named[namedArgument.name.source] = argument.accept(this);
       } else {
         positional.add(argument.accept(this));
       }
@@ -1552,13 +1806,14 @@
 
   TypeMask visitGetterSend(Send node) {
     Element element = elements[node];
+    Selector selector = elements.getSelector(node);
     if (Elements.isStaticOrTopLevelField(element)) {
-      inferrer.registerCalledElement(outermostElement, element, null);
+      handleStaticSend(node, selector, element, null);
       return inferrer.typeOfElement(element);
     } else if (Elements.isInstanceSend(node, elements)) {
       return visitDynamicSend(node);
     } else if (Elements.isStaticOrTopLevelFunction(element)) {
-      inferrer.registerGetFunction(outermostElement, element);
+      handleStaticSend(node, selector, element, null);
       return inferrer.functionType;
     } else if (Elements.isErroneousElement(element)) {
       return inferrer.dynamicType;
@@ -1584,22 +1839,21 @@
     return inferrer.dynamicType;
   }
 
+  void handleStaticSend(Node node,
+                        Selector selector,
+                        Element element,
+                        ArgumentsTypes arguments) {
+    if (Elements.isUnresolved(element)) return;
+    inferrer.registerCalledElement(
+        node, selector, outermostElement, element, arguments, inLoop);
+  }
+
   TypeMask handleDynamicSend(Node node,
                              Selector selector,
                              TypeMask receiver,
                              ArgumentsTypes arguments) {
-    if (!inferrer.isDynamicType(receiver)) {
-      selector = new TypedSelector(receiver, selector);
-    }
-    inferrer.registerCalledSelector(outermostElement, selector, arguments);
-    if (selector.isSetter()) {
-      inferrer.recordNonFinalFieldSelectorType(
-          node, selector, arguments.positional[0]);
-      // We return null to prevent using a type for a called setter.
-      // The return type is the right hand side of the setter.
-      return null;
-    }
-    return inferrer.typeOfSelector(selector);
+    return inferrer.registerCalledSelector(
+        node, selector, receiver, outermostElement, arguments, inLoop);
   }
 
   TypeMask visitDynamicSend(Send node) {
@@ -1633,10 +1887,27 @@
         recordReturnType(inferrer.dynamicType);
       } else {
         element = element.implementation;
-        // Call [:addCaller:] directly and not
-        // [:registerCalledElement:] because we should actually pass
-        // the parameters.
+        // We don't create a selector for redirecting factories, and
+        // the send is just a property access. Therefore we must
+        // manually create the [ArgumentsTypes] of the call, and
+        // manually register [analyzedElement] as a caller of [element].
+        FunctionElement function = analyzedElement;
+        FunctionSignature signature = function.computeSignature(compiler);
+        List<TypeMask> unnamed = <TypeMask>[];
+        Map<SourceString, TypeMask> named = new Map<SourceString, TypeMask>();
+        signature.forEachRequiredParameter((Element element) {
+          unnamed.add(locals.use(element));
+        });
+        signature.forEachOptionalParameter((Element element) {
+          if (signature.optionalParametersAreNamed) {
+            named[element.name] = locals.use(element);
+          } else {
+            unnamed.add(locals.use(element));
+          }
+        });
+        ArgumentsTypes arguments = new ArgumentsTypes(unnamed, named);
         inferrer.addCaller(analyzedElement, element);
+        inferrer.addArguments(node.expression, element, arguments);
         recordReturnType(inferrer.returnTypeOfElement(element));
       }
     } else {
@@ -1658,7 +1929,6 @@
     TypeMask secondType = node.elseExpression.accept(this);
     locals.merge(thenLocals);
     TypeMask type = inferrer.computeLUB(firstType, secondType);
-    if (inferrer.isGiveUpType(type)) type = inferrer.dynamicType;
     return type;
   }
 
@@ -1689,6 +1959,7 @@
   }
 
   TypeMask visitWhile(While node) {
+    loopLevel++;
     bool changed = false;
     do {
       LocalsHandler saved = new LocalsHandler.from(locals);
@@ -1697,10 +1968,12 @@
       changed = saved.merge(locals);
       locals = saved;
     } while (changed);
+    loopLevel--;
     return inferrer.dynamicType;
   }
 
- TypeMask visitDoWhile(DoWhile node) {
+  TypeMask visitDoWhile(DoWhile node) {
+    loopLevel++;
     bool changed = false;
     do {
       LocalsHandler saved = new LocalsHandler.from(locals);
@@ -1709,12 +1982,14 @@
       changed = saved.merge(locals);
       locals = saved;
     } while (changed);
+    loopLevel--;
     return inferrer.dynamicType;
   }
 
   TypeMask visitFor(For node) {
     bool changed = false;
     visit(node.initializer);
+    loopLevel++;
     do {
       LocalsHandler saved = new LocalsHandler.from(locals);
       visit(node.condition);
@@ -1723,6 +1998,7 @@
       changed = saved.merge(locals);
       locals = saved;
     } while (changed);
+    loopLevel--;
     return inferrer.dynamicType;
   }
 
@@ -1748,12 +2024,14 @@
       variable = elements[variableDefinitions.definitions.nodes.head];
     }
     locals.update(variable, inferrer.dynamicType);
+    loopLevel++;
     do {
       LocalsHandler saved = new LocalsHandler.from(locals);
       visit(node.body);
       changed = saved.merge(locals);
       locals = saved;
     } while (changed);
+    loopLevel--;
     return inferrer.dynamicType;
   }
 
@@ -1776,6 +2054,28 @@
   TypeMask visitThrow(Throw node) {
     node.visitChildren(this);
     locals.seenReturn = true;
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitCatchBlock(CatchBlock node) {
+    Node exception = node.exception;
+    if (exception != null) {
+      DartType type = elements.getType(node.type);
+      TypeMask mask = type == null
+          ? inferrer.dynamicType
+          : new TypeMask.nonNullSubtype(type.asRaw());
+      locals.update(elements[exception], mask);
+    }
+    Node trace = node.trace;
+    if (trace != null) {
+      locals.update(elements[trace], inferrer.dynamicType);
+    }
+    visit(node.block);
+    return inferrer.dynamicType;
+  }
+
+  TypeMask visitParenthesizedExpression(ParenthesizedExpression node) {
+    return visit(node.expression);
   }
 
   void internalError(String reason, {Node node}) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart
index c23390a..48c6c1c 100644
--- a/sdk/lib/_internal/compiler/implementation/types/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -20,9 +20,7 @@
 part 'type_mask.dart';
 
 /**
- * Common super class for our type inferrers. Currently, its query methods
- * return instances of [ConcreteType], but that may change in the
- * future.
+ * Common super class for our type inferrers.
  */
 abstract class TypesInferrer {
   analyzeMain(Element element);
@@ -37,29 +35,15 @@
  */
 class TypesTask extends CompilerTask {
   final String name = 'Type inference';
-  final Set<Element> untypedElements;
-  final Map<Element, Link<Element>> typedSends;
   TypesInferrer typesInferrer;
 
   TypesTask(Compiler compiler)
-    : untypedElements = new Set<Element>(),
-      typedSends = new Map<Element, Link<Element>>(),
-      typesInferrer = compiler.enableConcreteTypeInference
+    : typesInferrer = compiler.enableConcreteTypeInference
           ? new ConcreteTypesInferrer(compiler)
           : new SimpleTypesInferrer(compiler),
       super(compiler);
 
   /**
-   * Called once for each method during the resolution phase of the
-   * compiler.
-   */
-  void analyze(Node node, TreeElements elements) {
-    measure(() {
-      node.accept(new ConcreteTypeInferencer(this, elements));
-    });
-  }
-
-  /**
    * Called when resolution is complete.
    */
   void onResolutionComplete(Element mainElement) {
@@ -86,21 +70,6 @@
             typesInferrer .getTypeOfElement(element);
         if (guaranteedType != null) return guaranteedType;
       }
-      if (!element.isParameter()) return null;
-      Element holder = element.enclosingElement;
-      Link<Element> types = typedSends[holder];
-      if (types == null) return null;
-      if (!holder.isFunction()) return null;
-      if (untypedElements.contains(holder)) return null;
-      FunctionElement function = holder;
-      FunctionSignature signature = function.computeSignature(compiler);
-      for (Element parameter in signature.requiredParameters) {
-        if (types.isEmpty) return null;
-        if (element == parameter) {
-          return new TypeMask.nonNullExact(types.head.computeType(compiler));
-        }
-        types = types.tail;
-      }
       return null;
     });
   }
@@ -142,160 +111,3 @@
     });
   }
 }
-
-/**
- * Infers concrete types for a single method or expression.
- */
-class ConcreteTypeInferencer extends Visitor {
-  final TypesTask task;
-  final TreeElements elements;
-  final ClassElement boolClass;
-  final ClassElement doubleClass;
-  final ClassElement intClass;
-  final ClassElement listClass;
-  final ClassElement nullClass;
-  final ClassElement stringClass;
-
-  final Map<Node, ClassElement> concreteTypes;
-
-  ConcreteTypeInferencer(TypesTask task, this.elements)
-    : this.task = task,
-      this.boolClass = task.compiler.backend.boolImplementation,
-      this.doubleClass = task.compiler.backend.doubleImplementation,
-      this.intClass = task.compiler.backend.intImplementation,
-      this.listClass = task.compiler.backend.listImplementation,
-      this.nullClass = task.compiler.backend.nullImplementation,
-      this.stringClass = task.compiler.backend.stringImplementation,
-      this.concreteTypes = new Map<Node, ClassElement>();
-
-  visitNode(Node node) => node.visitChildren(this);
-
-  visitLiteralString(LiteralString node) {
-    recordConcreteType(node, stringClass);
-  }
-
-  visitStringInterpolation(StringInterpolation node) {
-    node.visitChildren(this);
-    recordConcreteType(node, stringClass);
-  }
-
-  visitStringJuxtaposition(StringJuxtaposition node) {
-    node.visitChildren(this);
-    recordConcreteType(node, stringClass);
-  }
-
-  recordConcreteType(Node node, ClassElement cls) {
-    concreteTypes[node] = cls;
-  }
-
-  visitLiteralBool(LiteralBool node) {
-    recordConcreteType(node, boolClass);
-  }
-
-  visitLiteralDouble(LiteralDouble node) {
-    recordConcreteType(node, doubleClass);
-  }
-
-  visitLiteralInt(LiteralInt node) {
-    recordConcreteType(node, intClass);
-  }
-
-  visitLiteralList(LiteralList node) {
-    node.visitChildren(this);
-    recordConcreteType(node, listClass);
-  }
-
-  visitLiteralMap(LiteralMap node) {
-    node.visitChildren(this);
-    // TODO(ahe): map class?
-  }
-
-  visitLiteralNull(LiteralNull node) {
-    recordConcreteType(node, nullClass);
-  }
-
-  Link<Element> computeConcreteSendArguments(Send node) {
-    if (node.argumentsNode == null) return null;
-    if (node.arguments.isEmpty) return const Link<Element>();
-    if (node.receiver != null && concreteTypes[node.receiver] == null) {
-      return null;
-    }
-    LinkBuilder<Element> types = new LinkBuilder<Element>();
-    for (Node argument in node.arguments) {
-      Element type = concreteTypes[argument];
-      if (type == null) return null;
-      types.addLast(type);
-    }
-    return types.toLink();
-  }
-
-  visitSend(Send node) {
-    node.visitChildren(this);
-    Element element = elements[node.selector];
-    if (element == null) return;
-    if (!Elements.isStaticOrTopLevelFunction(element)) return;
-    if (node.argumentsNode == null) {
-      // interest(node, 'closurized method');
-      task.untypedElements.add(element);
-      return;
-    }
-    Link<Element> types = computeConcreteSendArguments(node);
-    if (types != null) {
-      Link<Element> existing = task.typedSends[element];
-      if (existing == null) {
-        task.typedSends[element] = types;
-      } else {
-        // interest(node, 'multiple invocations');
-        Link<Element> lub = computeLubs(existing, types);
-        if (lub == null) {
-          task.untypedElements.add(element);
-        } else {
-          task.typedSends[element] = lub;
-        }
-      }
-    } else {
-      // interest(node, 'dynamically typed invocation');
-      task.untypedElements.add(element);
-    }
-  }
-
-  visitSendSet(SendSet node) {
-    // TODO(ahe): Implement this. For now, overridden to avoid calling
-    // visitSend through super.
-    node.visitChildren(this);
-  }
-
-  void interest(Node node, String note) {
-    var message = MessageKind.GENERIC.message({'text': note});
-    task.compiler.reportWarning(node, message);
-  }
-
-  /**
-   * Computes the pairwise Least Upper Bound (LUB) of the elements of
-   * [a] and [b]. Returns [:null:] if it gives up, or if the lists
-   * aren't the same length.
-   */
-  Link<Element> computeLubs(Link<Element> a, Link<Element> b) {
-    LinkBuilder<Element> lubs = new LinkBuilder<Element>();
-    while (!a.isEmpty && !b.isEmpty) {
-      Element lub = computeLub(a.head, b.head);
-      if (lub == null) return null;
-      lubs.addLast(lub);
-      a = a.tail;
-      b = b.tail;
-    }
-    return (a.isEmpty && b.isEmpty) ? lubs.toLink() : null;
-  }
-
-  /**
-   * Computes the Least Upper Bound (LUB) of [a] and [b]. Returns
-   * [:null:] if it gives up.
-   */
-  Element computeLub(Element a, Element b) {
-    // Fast common case, but also simple initial implementation.
-    if (identical(a, b)) return a;
-
-    // TODO(ahe): Improve the following "computation"...
-    return null;
-  }
-}
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index 4dbd9a8..c167c6f 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -519,8 +519,8 @@
       return false;
     }
 
-    if (mask.isNullable && compiler.backend.isNullImplementation(other)) {
-      return appliesUntyped(element, compiler);
+    if (compiler.backend.isNullImplementation(other)) {
+      return mask.isNullable && appliesUntyped(element, compiler);
     } else if (mask.isExact) {
       return hasElementIn(self, element) && appliesUntyped(element, compiler);
     } else if (mask.isSubclass) {
diff --git a/sdk/lib/_internal/compiler/implementation/world.dart b/sdk/lib/_internal/compiler/implementation/world.dart
index ff5d6a9..66b583f 100644
--- a/sdk/lib/_internal/compiler/implementation/world.dart
+++ b/sdk/lib/_internal/compiler/implementation/world.dart
@@ -9,6 +9,7 @@
   final Map<ClassElement, Set<MixinApplicationElement>> mixinUses;
   final Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses;
   final FullFunctionSet allFunctions;
+  final Set<Element> functionsCalledInLoop = new Set<Element>();
 
   // We keep track of subtype and subclass relationships in four
   // distinct sets to make class hierarchy analysis faster.
@@ -153,7 +154,7 @@
     ClassElement enclosing = result.getEnclosingClass();
     // TODO(kasperl): Move this code to the type mask.
     ti.TypeMask mask = selector.mask;
-    ClassElement receiverTypeElement = (mask == null)
+    ClassElement receiverTypeElement = (mask == null || mask.base == null)
         ? compiler.objectClass
         : mask.base.element;
     // We only return the found element if it is guaranteed to be
@@ -175,4 +176,12 @@
         .map((Element member) => member.getEnclosingClass())
         .where((ClassElement holder) => !identical(holder, objectClass));
   }
+
+  void addFunctionCalledInLoop(Element element) {
+    functionsCalledInLoop.add(element);
+  }
+
+  bool isCalledInLoop(Element element) {
+    return functionsCalledInLoop.contains(element);
+  }
 }
diff --git a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
index e8cae41..470c9f2 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -73,7 +73,7 @@
 }
 
 void writeString(File file, String text) {
-  var randomAccessFile = file.openSync(FileMode.WRITE);
+  var randomAccessFile = file.openSync(mode: FileMode.WRITE);
   randomAccessFile.writeStringSync(text);
   randomAccessFile.closeSync();
 }
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index 33bbb47..b321e41 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.dart
@@ -27,6 +27,9 @@
    *       var duration = milliseconds == null ? TIMEOUT : ms * milliseconds;
    *       return new Timer(duration, handleTimeout);
    *     }
+   *
+   * Note: If Dart code using Timer is compiled to JavaScript, the finest
+   * granularity available in the browser is 4 milliseconds.
    */
   external factory Timer(Duration duration, void callback());
 
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index c18ae9a..53b3e08 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -1191,14 +1191,6 @@
   @Experimental
   bool imageSmoothingEnabled;
 
-  @JSName('webkitLineDash')
-  @DomName('CanvasRenderingContext2D.webkitLineDash')
-  @DocsEditable
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental
-  List lineDash;
-
   @JSName('arc')
   @DomName('CanvasRenderingContext2D.arc')
   @DocsEditable
@@ -1231,26 +1223,27 @@
   @DomName('CanvasRenderingContext2D.createImageData')
   @DocsEditable
   @Creates('ImageData|=Object')
-  ImageData createImageData(imagedata_OR_sw, [num sh]) {
-    if ((imagedata_OR_sw is ImageData || imagedata_OR_sw == null) && !?sh) {
-      var imagedata_1 = _convertDartToNative_ImageData(imagedata_OR_sw);
-      return _convertNativeToDart_ImageData(_createImageData_1(imagedata_1));
-    }
-    if ((imagedata_OR_sw is num || imagedata_OR_sw == null)) {
-      return _convertNativeToDart_ImageData(_createImageData_2(imagedata_OR_sw, sh));
-    }
-    throw new ArgumentError("Incorrect number or type of arguments");
+  ImageData createImageData(num sw, num sh) {
+    return _convertNativeToDart_ImageData(_createImageData_1(sw, sh));
   }
   @JSName('createImageData')
   @DomName('CanvasRenderingContext2D.createImageData')
   @DocsEditable
   @Creates('ImageData|=Object')
-  _createImageData_1(imagedata) native;
+  _createImageData_1(sw, sh) native;
+
+  @DomName('CanvasRenderingContext2D.createImageData')
+  @DocsEditable
+  @Creates('ImageData|=Object')
+  ImageData createImageDataFromImageData(ImageData imagedata) {
+    var imagedata_1 = _convertDartToNative_ImageData(imagedata);
+    return _convertNativeToDart_ImageData(_createImageDataFromImageData_1(imagedata_1));
+  }
   @JSName('createImageData')
   @DomName('CanvasRenderingContext2D.createImageData')
   @DocsEditable
   @Creates('ImageData|=Object')
-  _createImageData_2(num sw, sh) native;
+  _createImageDataFromImageData_1(imagedata) native;
 
   @DomName('CanvasRenderingContext2D.createLinearGradient')
   @DocsEditable
@@ -1264,11 +1257,6 @@
   @DocsEditable
   CanvasGradient createRadialGradient(num x0, num y0, num r0, num x1, num y1, num r1) native;
 
-  @JSName('drawImage')
-  @DomName('CanvasRenderingContext2D.drawImage')
-  @DocsEditable
-  void $dom_drawImage(canvas_OR_image_OR_video, num sx_OR_x, num sy_OR_y, [num sw_OR_width, num height_OR_sh, num dx, num dy, num dw, num dh]) native;
-
   @DomName('CanvasRenderingContext2D.fill')
   @DocsEditable
   void fill([String winding]) native;
@@ -1484,11 +1472,73 @@
   }
 
   /**
+   * Draws an image from a CanvasImageSource to an area of this canvas.
+   *
+   * The image will be drawn to an area of this canvas defined by
+   * [destRect]. [sourceRect] defines the region of the source image that is
+   * drawn.
+   * If [sourceRect] is not provided, then
+   * the entire rectangular image from [source] will be drawn to this context.
+   *
+   * If the image is larger than canvas
+   * will allow, the image will be clipped to fit the available space.
+   *
+   *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
+   *     CanvasRenderingContext2D ctx = canvas.context2d;
+   *     ImageElement img = document.query('img');
+   *     img.width = 100;
+   *     img.height = 100;
+   *
+   *     // Scale the image to 20x20.
+   *     ctx.drawImageToRect(img, new Rect(50, 50, 20, 20));
+   *
+   *     VideoElement video = document.query('video');
+   *     video.width = 100;
+   *     video.height = 100;
+   *     // Take the middle 20x20 pixels from the video and stretch them.
+   *     ctx.drawImageToRect(video, new Rect(50, 50, 100, 100),
+   *         sourceRect: new Rect(40, 40, 20, 20));
+   *
+   *     // Draw the top 100x20 pixels from the otherCanvas.
+   *     CanvasElement otherCanvas = document.query('canvas');
+   *     ctx.drawImageToRect(otherCanvas, new Rect(0, 0, 100, 20),
+   *         sourceRect: new Rect(0, 0, 100, 20));
+   *
+   * See also:
+   *
+   *   * [CanvasImageSource] for more information on what data is retrieved
+   * from [source].
+   *   * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+   * from the WHATWG.
+   */
+  @DomName('CanvasRenderingContext2D.drawImage')
+  void drawImageToRect(CanvasImageSource source, Rect destRect,
+      {Rect sourceRect}) {
+    if (sourceRect == null) {
+      drawImageScaled(source,
+          destRect.left,
+          destRect.top,
+          destRect.width,
+          destRect.height);
+    } else {
+      drawImageScaledFromSource(source,
+          sourceRect.left,
+          sourceRect.top,
+          sourceRect.width,
+          sourceRect.height,
+          destRect.left,
+          destRect.top,
+          destRect.width,
+          destRect.height);
+    }
+  }
+
+  /**
    * Draws an image from a CanvasImageSource to this canvas.
    *
    * The entire image from [source] will be drawn to this context with its top
-   * left corner at the point ([destinationX], [destinationY]). If the image is
-   * larger than canvas will allow, the image will be cropped to fit the
+   * left corner at the point ([destX], [destY]). If the image is
+   * larger than canvas will allow, the image will be clipped to fit the
    * available space.
    *
    *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
@@ -1503,7 +1553,7 @@
    *     CanvasElement otherCanvas = document.query('canvas');
    *     otherCanvas.width = 100;
    *     otherCanvas.height = 100;
-   *     ctx.drawImage(otherCanvas, 590, 590); // will get cropped
+   *     ctx.drawImage(otherCanvas, 590, 590); // will get clipped
    *
    * See also:
    *
@@ -1513,20 +1563,18 @@
    * from the WHATWG.
    */
   @DomName('CanvasRenderingContext2D.drawImage')
-  void drawImage(CanvasImageSource source, num destinationX, num destinationY) {
-    $dom_drawImage(source, destinationX, destinationY);
-  }
+  @JSName('drawImage')
+  void drawImage(CanvasImageSource source, num destX, num destY) native;
 
   /**
    * Draws an image from a CanvasImageSource to an area of this canvas.
    *
-   * The image will be drawn to an area of this canvas defined by
-   * [destinationRect]. If [sourceRect] is not provided, then
-   * the entire rectangular image from [source] will be drawn to this context.
-   * If the dimensions of [source] or [sourceRect]
-   * differ from [destinationRect], then the image will be scaled to fit.
+   * The image will be drawn to this context with its top left corner at the
+   * point ([destX], [destY]) and will be scaled to be [destWidth] wide and
+   * [destHeight] tall.
+   *
    * If the image is larger than canvas
-   * will allow, the image will be cropped to fit the available space.
+   * will allow, the image will be clipped to fit the available space.
    *
    *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
    *     CanvasRenderingContext2D ctx = canvas.context2d;
@@ -1534,20 +1582,8 @@
    *     img.width = 100;
    *     img.height = 100;
    *
-   *     // Scale the image to 20x20.
-   *     ctx.drawImageAtScale(img, new Rect(50, 50, 20, 20));
-   *
-   *     VideoElement video = document.query('video');
-   *     video.width = 100;
-   *     video.height = 100;
-   *     // Take the middle 20x20 pixels from the video and stretch them.
-   *     ctx.drawImageAtScale(video, new Rect(50, 50, 100, 100),
-   *         sourceRect: new Rect(40, 40, 20, 20));
-   *
-   *     // Draw the top 100x20 pixels from the otherCanvas.
-   *     CanvasElement otherCanvas = document.query('canvas');
-   *     ctx.drawImageAtScale(otherCanvas, new Rect(0, 0, 100, 20),
-   *         sourceRect: new Rect(0, 0, 100, 20));
+   *     // Scale the image to 300x50 at the point (20, 20)
+   *     ctx.drawImageScaled(img, 20, 20, 300, 50);
    *
    * See also:
    *
@@ -1557,26 +1593,44 @@
    * from the WHATWG.
    */
   @DomName('CanvasRenderingContext2D.drawImage')
-  void drawImageAtScale(CanvasImageSource source, Rect destinationRect,
-      {Rect sourceRect}) {
-    if (sourceRect == null) {
-      $dom_drawImage(source,
-          destinationRect.left,
-          destinationRect.top,
-          destinationRect.width,
-          destinationRect.height);
-    } else {
-      $dom_drawImage(source,
-          sourceRect.left,
-          sourceRect.top,
-          sourceRect.width,
-          sourceRect.height,
-          destinationRect.left,
-          destinationRect.top,
-          destinationRect.width,
-          destinationRect.height);
-    }
-  }
+  @JSName('drawImage')
+  void drawImageScaled(CanvasImageSource source,
+      num destX, num destY, num destWidth, num destHeight) native;
+
+  /**
+   * Draws an image from a CanvasImageSource to an area of this canvas.
+   *
+   * The image is a region of [source] that is [sourceWidth] wide and
+   * [destHeight] tall with top left corner at ([sourceX], [sourceY]).
+   * The image will be drawn to this context with its top left corner at the
+   * point ([destX], [destY]) and will be scaled to be [destWidth] wide and
+   * [destHeight] tall.
+   *
+   * If the image is larger than canvas
+   * will allow, the image will be clipped to fit the available space.
+   *
+   *     VideoElement video = document.query('video');
+   *     video.width = 100;
+   *     video.height = 100;
+   *     // Take the middle 20x20 pixels from the video and stretch them.
+   *     ctx.drawImageScaledFromSource(video, 40, 40, 20, 20, 50, 50, 100, 100);
+   *
+   *     // Draw the top 100x20 pixels from the otherCanvas to this one.
+   *     CanvasElement otherCanvas = document.query('canvas');
+   *     ctx.drawImageScaledFromSource(otherCanvas, 0, 0, 100, 20, 0, 0, 100, 20);
+   *
+   * See also:
+   *
+   *   * [CanvasImageSource] for more information on what data is retrieved
+   * from [source].
+   *   * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+   * from the WHATWG.
+   */
+  @DomName('CanvasRenderingContext2D.drawImage')
+  @JSName('drawImage')
+  void drawImageScaledFromSource(CanvasImageSource source,
+      num sourceX, num sourceY, num sourceWidth, num sourceHeight,
+      num destX, num destY, num destWidth, num destHeight) native;
 
   @DomName('CanvasRenderingContext2D.lineDashOffset')
   num get lineDashOffset => JS('num',
@@ -1587,6 +1641,7 @@
       'typeof #.lineDashOffset != "undefined" ? #.lineDashOffset = # : '
       '#.webkitLineDashOffset = #', this, this, value, this, value);
 }
+
 // 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.
@@ -2437,6 +2492,11 @@
   @DocsEditable
   final CssRule parentRule;
 
+  @JSName('getPropertyValue')
+  @DomName('CSSStyleDeclaration.getPropertyValue')
+  @DocsEditable
+  String _getPropertyValue(String propertyName) native;
+
   @JSName('getPropertyCSSValue')
   @DomName('CSSStyleDeclaration.getPropertyCSSValue')
   @DocsEditable
@@ -2450,11 +2510,6 @@
   @DocsEditable
   String getPropertyShorthand(String propertyName) native;
 
-  @JSName('getPropertyValue')
-  @DomName('CSSStyleDeclaration.getPropertyValue')
-  @DocsEditable
-  String _getPropertyValue(String propertyName) native;
-
   @DomName('CSSStyleDeclaration.isPropertyImplicit')
   @DocsEditable
   bool isPropertyImplicit(String propertyName) native;
@@ -6184,14 +6239,50 @@
   void $dom_initDeviceOrientationEvent(String type, bool bubbles, bool cancelable, num alpha, num beta, num gamma, bool absolute) native;
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
 
-@DocsEditable
 @DomName('DirectoryEntry')
 class DirectoryEntry extends Entry native "*DirectoryEntry" {
+  
+  /**
+   * Create a new directory with the specified `path`. If `exclusive` is true,
+   * the returned Future will complete with an error if a directory already
+   * exists with the specified `path`.
+   */
+  Future<Entry> createDirectory(String path, {bool exclusive: false}) {
+    return _getDirectory(path, options: 
+        {'create': true, 'exclusive': exclusive});
+  }
+
+  /**
+   * Retrieve an already existing directory entry. The returned future will
+   * result in an error if a directory at `path` does not exist or if the item
+   * at `path` is not a directory.
+   */
+  Future<Entry> getDirectory(String path) {
+    return _getDirectory(path);
+  }
+
+  /**
+   * Create a new file with the specified `path`. If `exclusive` is true,
+   * the returned Future will complete with an error if a file already
+   * exists at the specified `path`.
+   */
+  Future<Entry> createFile(String path, {bool exclusive: false}) {
+    return _getFile(path, options: {'create': true, 'exclusive': exclusive});
+  }
+  
+  /**
+   * Retrieve an already existing file entry. The returned future will
+   * result in an error if a file at `path` does not exist or if the item at
+   * `path` is not a file.
+   */
+  Future<Entry> getFile(String path) {
+    return _getFile(path);
+  }
 
   @DomName('DirectoryEntry.createReader')
   @DocsEditable
@@ -6199,48 +6290,48 @@
 
   @DomName('DirectoryEntry.getDirectory')
   @DocsEditable
-  void _getDirectory(String path, {Map options, _EntryCallback successCallback, _ErrorCallback errorCallback}) {
+  void __getDirectory(String path, {Map options, _EntryCallback successCallback, _ErrorCallback errorCallback}) {
     if (?errorCallback) {
       var options_1 = convertDartToNative_Dictionary(options);
-      __getDirectory_1(path, options_1, successCallback, errorCallback);
+      ___getDirectory_1(path, options_1, successCallback, errorCallback);
       return;
     }
     if (?successCallback) {
       var options_2 = convertDartToNative_Dictionary(options);
-      __getDirectory_2(path, options_2, successCallback);
+      ___getDirectory_2(path, options_2, successCallback);
       return;
     }
     if (?options) {
       var options_3 = convertDartToNative_Dictionary(options);
-      __getDirectory_3(path, options_3);
+      ___getDirectory_3(path, options_3);
       return;
     }
-    __getDirectory_4(path);
+    ___getDirectory_4(path);
     return;
   }
   @JSName('getDirectory')
   @DomName('DirectoryEntry.getDirectory')
   @DocsEditable
-  void __getDirectory_1(path, options, _EntryCallback successCallback, _ErrorCallback errorCallback) native;
+  void ___getDirectory_1(path, options, _EntryCallback successCallback, _ErrorCallback errorCallback) native;
   @JSName('getDirectory')
   @DomName('DirectoryEntry.getDirectory')
   @DocsEditable
-  void __getDirectory_2(path, options, _EntryCallback successCallback) native;
+  void ___getDirectory_2(path, options, _EntryCallback successCallback) native;
   @JSName('getDirectory')
   @DomName('DirectoryEntry.getDirectory')
   @DocsEditable
-  void __getDirectory_3(path, options) native;
+  void ___getDirectory_3(path, options) native;
   @JSName('getDirectory')
   @DomName('DirectoryEntry.getDirectory')
   @DocsEditable
-  void __getDirectory_4(path) native;
+  void ___getDirectory_4(path) native;
 
   @JSName('getDirectory')
   @DomName('DirectoryEntry.getDirectory')
   @DocsEditable
-  Future<Entry> getDirectory(String path, {Map options}) {
+  Future<Entry> _getDirectory(String path, {Map options}) {
     var completer = new Completer<Entry>();
-    _getDirectory(path, options : options,
+    __getDirectory(path, options : options,
         successCallback : (value) { completer.complete(value); },
         errorCallback : (error) { completer.completeError(error); });
     return completer.future;
@@ -6248,48 +6339,48 @@
 
   @DomName('DirectoryEntry.getFile')
   @DocsEditable
-  void _getFile(String path, {Map options, _EntryCallback successCallback, _ErrorCallback errorCallback}) {
+  void __getFile(String path, {Map options, _EntryCallback successCallback, _ErrorCallback errorCallback}) {
     if (?errorCallback) {
       var options_1 = convertDartToNative_Dictionary(options);
-      __getFile_1(path, options_1, successCallback, errorCallback);
+      ___getFile_1(path, options_1, successCallback, errorCallback);
       return;
     }
     if (?successCallback) {
       var options_2 = convertDartToNative_Dictionary(options);
-      __getFile_2(path, options_2, successCallback);
+      ___getFile_2(path, options_2, successCallback);
       return;
     }
     if (?options) {
       var options_3 = convertDartToNative_Dictionary(options);
-      __getFile_3(path, options_3);
+      ___getFile_3(path, options_3);
       return;
     }
-    __getFile_4(path);
+    ___getFile_4(path);
     return;
   }
   @JSName('getFile')
   @DomName('DirectoryEntry.getFile')
   @DocsEditable
-  void __getFile_1(path, options, _EntryCallback successCallback, _ErrorCallback errorCallback) native;
+  void ___getFile_1(path, options, _EntryCallback successCallback, _ErrorCallback errorCallback) native;
   @JSName('getFile')
   @DomName('DirectoryEntry.getFile')
   @DocsEditable
-  void __getFile_2(path, options, _EntryCallback successCallback) native;
+  void ___getFile_2(path, options, _EntryCallback successCallback) native;
   @JSName('getFile')
   @DomName('DirectoryEntry.getFile')
   @DocsEditable
-  void __getFile_3(path, options) native;
+  void ___getFile_3(path, options) native;
   @JSName('getFile')
   @DomName('DirectoryEntry.getFile')
   @DocsEditable
-  void __getFile_4(path) native;
+  void ___getFile_4(path) native;
 
   @JSName('getFile')
   @DomName('DirectoryEntry.getFile')
   @DocsEditable
-  Future<Entry> getFile(String path, {Map options}) {
+  Future<Entry> _getFile(String path, {Map options}) {
     var completer = new Completer<Entry>();
-    _getFile(path, options : options,
+    __getFile(path, options : options,
         successCallback : (value) { completer.complete(value); },
         errorCallback : (error) { completer.completeError(error); });
     return completer.future;
@@ -6310,7 +6401,9 @@
         (error) { completer.completeError(error); });
     return completer.future;
   }
+
 }
+
 // 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.
@@ -8322,7 +8415,7 @@
     if (index == length) {
       _element.append(element);
     } else {
-      throw new UnimplementedError("insert on ElementLists");
+      _element.insertBefore(element, this[index]);
     }
   }
 
@@ -8829,37 +8922,15 @@
     return window.$dom_getComputedStyle(this, pseudoElement);
   }
 
-  @deprecated
-  int get clientHeight => client.height;
-  @deprecated
-  int get clientLeft => client.left;
-  @deprecated
-  int get clientTop => client.top;
-  @deprecated
-  int get clientWidth => client.width;
+  /**
+   * Gets the position of this element relative to the client area of the page.
+   */
+  Rect get client => new Rect(clientLeft, clientTop, clientWidth, clientHeight);
 
-  @DomName('Element.clientHeight')
-  @DomName('Element.clientLeft')
-  @DomName('Element.clientTop')
-  @DomName('Element.clientWidth')
-  Rect get client => new Rect($dom_clientLeft, $dom_clientTop, $dom_clientWidth,
-      $dom_clientHeight);
-
-  @deprecated
-  int get offsetHeight => offset.height;
-  @deprecated
-  int get offsetLeft => offset.left;
-  @deprecated
-  int get offsetTop => offset.top;
-  @deprecated
-  int get offsetWidth => offset.width;
-
-  @DomName('Element.offsetHeight')
-  @DomName('Element.offsetLeft')
-  @DomName('Element.offsetTop')
-  @DomName('Element.offsetWidth')
-  Rect get offset => new Rect($dom_offsetLeft, $dom_offsetTop, $dom_offsetWidth,
-      $dom_offsetHeight);
+  /**
+   * Gets the offset of this element relative to its offsetParent.
+   */
+  Rect get offset => new Rect(offsetLeft, offsetTop, offsetWidth, offsetHeight);
 
   /**
    * Adds the specified text as a text node after the last child of this
@@ -9367,25 +9438,21 @@
   @DocsEditable
   String $dom_className;
 
-  @JSName('clientHeight')
   @DomName('Element.clientHeight')
   @DocsEditable
-  final int $dom_clientHeight;
+  final int clientHeight;
 
-  @JSName('clientLeft')
   @DomName('Element.clientLeft')
   @DocsEditable
-  final int $dom_clientLeft;
+  final int clientLeft;
 
-  @JSName('clientTop')
   @DomName('Element.clientTop')
   @DocsEditable
-  final int $dom_clientTop;
+  final int clientTop;
 
-  @JSName('clientWidth')
   @DomName('Element.clientWidth')
   @DocsEditable
-  final int $dom_clientWidth;
+  final int clientWidth;
 
   @JSName('firstElementChild')
   @DomName('Element.firstElementChild')
@@ -9401,29 +9468,25 @@
   @DocsEditable
   final Element nextElementSibling;
 
-  @JSName('offsetHeight')
   @DomName('Element.offsetHeight')
   @DocsEditable
-  final int $dom_offsetHeight;
+  final int offsetHeight;
 
-  @JSName('offsetLeft')
   @DomName('Element.offsetLeft')
   @DocsEditable
-  final int $dom_offsetLeft;
+  final int offsetLeft;
 
   @DomName('Element.offsetParent')
   @DocsEditable
   final Element offsetParent;
 
-  @JSName('offsetTop')
   @DomName('Element.offsetTop')
   @DocsEditable
-  final int $dom_offsetTop;
+  final int offsetTop;
 
-  @JSName('offsetWidth')
   @DomName('Element.offsetWidth')
   @DocsEditable
-  final int $dom_offsetWidth;
+  final int offsetWidth;
 
   @DomName('Element.previousElementSibling')
   @DocsEditable
@@ -10340,6 +10403,9 @@
 
   @DomName('Event.clipboardData')
   @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
   final DataTransfer clipboardData;
 
   EventTarget get currentTarget => _convertNativeToDart_EventTarget(this._get_currentTarget);
@@ -10425,14 +10491,19 @@
   @DocsEditable
   String toString() native;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
 
-@DocsEditable
 @DomName('EventSource')
 class EventSource extends EventTarget native "*EventSource" {
+  factory EventSource(String title, {withCredentials: false}) {
+    var parsedOptions = {
+      'withCredentials': withCredentials,
+    };
+    return EventSource._factoryEventSource(title, parsedOptions);
+  }
 
   @DomName('EventSource.errorEvent')
   @DocsEditable
@@ -10448,7 +10519,7 @@
 
   @DomName('EventSource.EventSource')
   @DocsEditable
-  factory EventSource(String url, [Map eventSourceInit]) {
+  static EventSource _factoryEventSource(String url, [Map eventSourceInit]) {
     if (?eventSourceInit) {
       return EventSource._create_1(url, eventSourceInit);
     }
@@ -10504,6 +10575,7 @@
   @DomName('EventSource.onopen')
   @DocsEditable
   Stream<Event> get onOpen => openEvent.forTarget(this);
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -12905,38 +12977,65 @@
   }
 
   @DomName('Document.webkitCancelFullScreen')
-  void webkitCancelFullScreen() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void cancelFullScreen() {
     document.$dom_webkitCancelFullScreen();
   }
 
   @DomName('Document.webkitExitFullscreen')
-  void webkitExitFullscreen() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void exitFullscreen() {
     document.$dom_webkitExitFullscreen();
   }
 
   @DomName('Document.webkitExitPointerLock')
-  void webkitExitPointerLock() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void exitPointerLock() {
     document.$dom_webkitExitPointerLock();
   }
 
   @DomName('Document.webkitFullscreenElement')
-  Element get webkitFullscreenElement => document.$dom_webkitFullscreenElement;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  Element get fullscreenElement => document.$dom_webkitFullscreenElement;
 
   @DomName('Document.webkitFullscreenEnabled')
-  bool get webkitFullscreenEnabled => document.$dom_webkitFullscreenEnabled;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get fullscreenEnabled => document.$dom_webkitFullscreenEnabled;
 
   @DomName('Document.webkitHidden')
-  bool get webkitHidden => document.$dom_webkitHidden;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get hidden => document.$dom_webkitHidden;
 
   @DomName('Document.webkitIsFullScreen')
-  bool get webkitIsFullScreen => document.$dom_webkitIsFullScreen;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get isFullScreen => document.$dom_webkitIsFullScreen;
 
   @DomName('Document.webkitPointerLockElement')
-  Element get webkitPointerLockElement =>
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  Element get pointerLockElement =>
       document.$dom_webkitPointerLockElement;
 
   @DomName('Document.webkitVisibilityState')
-  String get webkitVisibilityState => document.$dom_webkitVisibilityState;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  String get visibilityState => document.$dom_webkitVisibilityState;
 }
 // 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
@@ -12988,8 +13087,9 @@
  * wish to retrieve the HTML of the top-level page and print it out.
  * The easiest way to do that would be:
  *
- *     var httpRequest = HttpRequest.get('http://api.dartlang.org',
- *         (request) => print(request.responseText));
+ *     HttpRequest.getString('http://api.dartlang.org').then((response) {
+ *       print(response);
+ *     });
  *
  * **Important**: With the default behavior of this class, your
  * code making the request should be served from the same origin (domain name,
@@ -13102,7 +13202,19 @@
    */
   static bool get supportsProgressEvent {
     var xhr = new HttpRequest();
-    return JS('bool', '"onprogress" in #', xhr);
+    return JS('bool', '("onprogress" in #)', xhr);
+  }
+
+  /**
+   * Checks to see if the current platform supports making cross origin
+   * requests.
+   *
+   * Note that even if cross origin requests are supported, they still may fail
+   * if the destination server does not support CORS requests.
+   */
+  static bool get supportsCrossOrigin {
+    var xhr = new HttpRequest();
+    return JS('bool', '("withCredentials" in #)', xhr);
   }
 
   /**
@@ -13110,7 +13222,7 @@
    */
   static bool get supportsLoadEndEvent {
     var xhr = new HttpRequest();
-    return JS('bool', '"onloadend" in #', xhr);
+    return JS('bool', '("onloadend" in #)', xhr);
   }
 
 
@@ -17190,10 +17302,6 @@
 @Experimental
 class MutationObserver native "*MutationObserver" {
 
-  @DomName('MutationObserver.disconnect')
-  @DocsEditable
-  void disconnect() native;
-
   @DomName('MutationObserver.observe')
   @DocsEditable
   void _observe(Node target, Map options) {
@@ -17206,6 +17314,10 @@
   @DocsEditable
   void __observe_1(Node target, options) native;
 
+  @DomName('MutationObserver.disconnect')
+  @DocsEditable
+  void disconnect() native;
+
   @DomName('MutationObserver.takeRecords')
   @DocsEditable
   List<MutationRecord> takeRecords() native;
@@ -17220,8 +17332,7 @@
   }
 
   void observe(Node target,
-               {Map options,
-                bool childList,
+               {bool childList,
                 bool attributes,
                 bool characterData,
                 bool subtree,
@@ -17232,19 +17343,6 @@
     // Parse options into map of known type.
     var parsedOptions = _createDict();
 
-    if (options != null) {
-      options.forEach((k, v) {
-          if (_boolKeys.containsKey(k)) {
-            _add(parsedOptions, k, true == v);
-          } else if (k == 'attributeFilter') {
-            _add(parsedOptions, k, _fixupList(v));
-          } else {
-            throw new ArgumentError(
-                "Illegal MutationObserver.observe option '$k'");
-          }
-        });
-    }
-
     // Override options passed in the map with named optional arguments.
     override(key, value) {
       if (value != null) _add(parsedOptions, key, value);
@@ -17356,32 +17454,48 @@
    * Gets a stream (video and or audio) from the local computer.
    *
    * Use [MediaStream.supported] to check if this is supported by the current
-   * platform.
+   * platform. The arguments `audio` and `video` default to `false` (stream does
+   * not use audio or video, respectively).
    *
-   * Example use:
+   * Simple example usage:
    *
-   *     window.navigator.getUserMedia(audio:true, video: true).then((stream) {
+   *     window.navigator.getUserMedia(audio: true, video: true).then((stream) {
    *       var video = new VideoElement()
    *         ..autoplay = true
    *         ..src = Url.createObjectUrl(stream);
    *       document.body.append(video);
    *     });
    *
+   * The user can also pass in Maps to the audio or video parameters to specify 
+   * mandatory and optional constraints for the media stream. Not passing in a 
+   * map, but passing in `true` will provide a LocalMediaStream with audio or 
+   * video capabilities, but without any additional constraints. The particular
+   * constraint names for audio and video are still in flux, but as of this 
+   * writing, here is an example providing more constraints.
+   *
+   *     window.navigator.getUserMedia(
+   *         audio: true, 
+   *         video: {'mandatory': 
+   *                    { 'minAspectRatio': 1.333, 'maxAspectRatio': 1.334 },
+   *                 'optional': 
+   *                    [{ 'minFrameRate': 60 },
+   *                     { 'maxWidth': 640 }]
+   *     });
+   *
    * See also:
    * * [MediaStream.supported]
    */
   @DomName('Navigator.webkitGetUserMedia')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  Future<LocalMediaStream> getUserMedia({bool audio: false,
-      bool video: false}) {
+  Future<LocalMediaStream> getUserMedia({audio: false, video: false}) {
     var completer = new Completer<LocalMediaStream>();
     var options = {
       'audio': audio,
       'video': video
     };
     _ensureGetUserMedia();
-    this._getUserMedia(convertDartToNative_Dictionary(options),
+    this._getUserMedia(convertDartToNative_SerializedScriptValue(options),
       (stream) {
         completer.complete(stream);
       },
@@ -17468,6 +17582,22 @@
   @Experimental
   final BatteryManager battery;
 
+  @JSName('webkitPersistentStorage')
+  @DomName('Navigator.webkitPersistentStorage')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  final StorageQuota persistentStorage;
+
+  @JSName('webkitTemporaryStorage')
+  @DomName('Navigator.webkitTemporaryStorage')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  final StorageQuota temporaryStorage;
+
   @DomName('Navigator.getStorageUpdates')
   @DocsEditable
   void getStorageUpdates() native;
@@ -17591,7 +17721,7 @@
     if (index == length) {
       _this.append(node);
     } else {
-      this_.insertBefore(node, this[index]);
+      _this.insertBefore(node, this[index]);
     }
   }
 
@@ -18355,13 +18485,18 @@
 
 @DomName('Notification')
 class Notification extends EventTarget native "*Notification" {
-  factory Notification(String title, [Map options]) {
-    if (?options) {
-      return JS('Notification', 'new Notification(#,#)', title,
-          convertDartToNative_SerializedScriptValue(options));
-    } else {
-      return JS('Notification', 'new Notification(#)', title);
-    }
+
+  factory Notification(String title, {String titleDir: null, String body: null, 
+      String bodyDir: null, String tag: null, String iconUrl: null}) {
+
+    var parsedOptions = {};
+    if (titleDir != null) parsedOptions['titleDir'] = titleDir;
+    if (body != null) parsedOptions['body'] = body;
+    if (bodyDir != null) parsedOptions['bodyDir'] = bodyDir;
+    if (tag != null) parsedOptions['tag'] = tag;
+    if (iconUrl != null) parsedOptions['iconUrl'] = iconUrl;
+
+    return Notification._factoryNotification(title, parsedOptions);
   }
 
   @DomName('Notification.clickEvent')
@@ -18384,6 +18519,17 @@
   @DocsEditable
   static const EventStreamProvider<Event> showEvent = const EventStreamProvider<Event>('show');
 
+  @DomName('Notification.Notification')
+  @DocsEditable
+  static Notification _factoryNotification(String title, [Map options]) {
+    if (?options) {
+      return Notification._create_1(title, options);
+    }
+    return Notification._create_2(title);
+  }
+  static Notification _create_1(title, options) => JS('Notification', 'new Notification(#,#)', title, options);
+  static Notification _create_2(title) => JS('Notification', 'new Notification(#)', title);
+
   @DomName('Notification.dir')
   @DocsEditable
   String dir;
@@ -19583,6 +19729,68 @@
   @DocsEditable
   final RtcDataChannel channel;
 }
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+@DocsEditable
+@DomName('RTCDTMFSender')
+class RtcDtmfSender extends EventTarget native "*RTCDTMFSender" {
+
+  @JSName('canInsertDTMF')
+  @DomName('RTCDTMFSender.canInsertDTMF')
+  @DocsEditable
+  final bool canInsertDtmf;
+
+  @DomName('RTCDTMFSender.duration')
+  @DocsEditable
+  final int duration;
+
+  @DomName('RTCDTMFSender.interToneGap')
+  @DocsEditable
+  final int interToneGap;
+
+  @DomName('RTCDTMFSender.toneBuffer')
+  @DocsEditable
+  final String toneBuffer;
+
+  @DomName('RTCDTMFSender.track')
+  @DocsEditable
+  final MediaStreamTrack track;
+
+  @JSName('addEventListener')
+  @DomName('RTCDTMFSender.addEventListener')
+  @DocsEditable
+  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native;
+
+  @DomName('RTCDTMFSender.dispatchEvent')
+  @DocsEditable
+  bool dispatchEvent(Event event) native;
+
+  @JSName('insertDTMF')
+  @DomName('RTCDTMFSender.insertDTMF')
+  @DocsEditable
+  void insertDtmf(String tones, [int duration, int interToneGap]) native;
+
+  @JSName('removeEventListener')
+  @DomName('RTCDTMFSender.removeEventListener')
+  @DocsEditable
+  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+@DocsEditable
+@DomName('RTCDTMFToneChangeEvent')
+class RtcDtmfToneChangeEvent extends Event native "*RTCDTMFToneChangeEvent" {
+
+  @DomName('RTCDTMFToneChangeEvent.tone')
+  @DocsEditable
+  final String tone;
+}
 // 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.
@@ -19660,6 +19868,21 @@
     } catch (_) {}
     return false;
   }
+  Future<RtcSessionDescription> createOffer([Map mediaConstraints]) {
+    var completer = new Completer<RtcSessionDescription>();
+    _createOffer(
+        (value) { completer.complete(value); },
+        (error) { completer.completeError(error); }, mediaConstraints);
+    return completer.future;
+  }
+
+  Future<RtcSessionDescription> createAnswer([Map mediaConstraints]) {
+    var completer = new Completer<RtcSessionDescription>();
+    _createAnswer(
+        (value) { completer.complete(value); },
+        (error) { completer.completeError(error); }, mediaConstraints);
+    return completer.future;
+  }
 
   @DomName('RTCPeerConnection.addstreamEvent')
   @DocsEditable
@@ -19770,21 +19993,10 @@
   @DocsEditable
   void __createAnswer_2(_RtcSessionDescriptionCallback successCallback, _RtcErrorCallback failureCallback) native;
 
-  @JSName('createAnswer')
-  @DomName('RTCPeerConnection.createAnswer')
-  @DocsEditable
-  Future<RtcSessionDescription> createAnswer([Map mediaConstraints]) {
-    var completer = new Completer<RtcSessionDescription>();
-    _createAnswer(mediaConstraints,
-        (value) { completer.complete(value); },
-        (error) { completer.completeError(error); });
-    return completer.future;
-  }
-
   @JSName('createDTMFSender')
   @DomName('RTCPeerConnection.createDTMFSender')
   @DocsEditable
-  RtcdtmfSender createDtmfSender(MediaStreamTrack track) native;
+  RtcDtmfSender createDtmfSender(MediaStreamTrack track) native;
 
   @DomName('RTCPeerConnection.createDataChannel')
   @DocsEditable
@@ -19824,17 +20036,6 @@
   @DocsEditable
   void __createOffer_2(_RtcSessionDescriptionCallback successCallback, _RtcErrorCallback failureCallback) native;
 
-  @JSName('createOffer')
-  @DomName('RTCPeerConnection.createOffer')
-  @DocsEditable
-  Future<RtcSessionDescription> createOffer([Map mediaConstraints]) {
-    var completer = new Completer<RtcSessionDescription>();
-    _createOffer(mediaConstraints,
-        (value) { completer.complete(value); },
-        (error) { completer.completeError(error); });
-    return completer.future;
-  }
-
   @DomName('RTCPeerConnection.dispatchEvent')
   @DocsEditable
   bool dispatchEvent(Event event) native;
@@ -19851,6 +20052,10 @@
   @DocsEditable
   void getStats(RtcStatsCallback successCallback, MediaStreamTrack selector) native;
 
+  @DomName('RTCPeerConnection.getStreamById')
+  @DocsEditable
+  MediaStream getStreamById(String streamId) native;
+
   @JSName('removeEventListener')
   @DomName('RTCPeerConnection.removeEventListener')
   @DocsEditable
@@ -19986,39 +20191,34 @@
 
 
 @DocsEditable
-@DomName('RTCStatsElement')
-class RtcStatsElement native "*RTCStatsElement" {
-
-  DateTime get timestamp => _convertNativeToDart_DateTime(this._get_timestamp);
-  @JSName('timestamp')
-  @DomName('RTCStatsElement.timestamp')
-  @DocsEditable
-  final dynamic _get_timestamp;
-
-  @DomName('RTCStatsElement.names')
-  @DocsEditable
-  List<String> names() native;
-
-  @DomName('RTCStatsElement.stat')
-  @DocsEditable
-  String stat(String name) native;
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-
-@DocsEditable
 @DomName('RTCStatsReport')
 class RtcStatsReport native "*RTCStatsReport" {
 
+  @DomName('RTCStatsReport.id')
+  @DocsEditable
+  final String id;
+
   @DomName('RTCStatsReport.local')
   @DocsEditable
-  final RtcStatsElement local;
+  final RtcStatsReport local;
 
   @DomName('RTCStatsReport.remote')
   @DocsEditable
-  final RtcStatsElement remote;
+  final RtcStatsReport remote;
+
+  DateTime get timestamp => _convertNativeToDart_DateTime(this._get_timestamp);
+  @JSName('timestamp')
+  @DomName('RTCStatsReport.timestamp')
+  @DocsEditable
+  final dynamic _get_timestamp;
+
+  @DomName('RTCStatsReport.names')
+  @DocsEditable
+  List<String> names() native;
+
+  @DomName('RTCStatsReport.stat')
+  @DocsEditable
+  String stat(String name) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -20029,72 +20229,14 @@
 @DomName('RTCStatsResponse')
 class RtcStatsResponse native "*RTCStatsResponse" {
 
+  @DomName('RTCStatsResponse.namedItem')
+  @DocsEditable
+  RtcStatsReport namedItem(String name) native;
+
   @DomName('RTCStatsResponse.result')
   @DocsEditable
   List<RtcStatsReport> result() native;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-
-@DocsEditable
-@DomName('RTCDTMFSender')
-class RtcdtmfSender extends EventTarget native "*RTCDTMFSender" {
-
-  @JSName('canInsertDTMF')
-  @DomName('RTCDTMFSender.canInsertDTMF')
-  @DocsEditable
-  final bool canInsertDtmf;
-
-  @DomName('RTCDTMFSender.duration')
-  @DocsEditable
-  final int duration;
-
-  @DomName('RTCDTMFSender.interToneGap')
-  @DocsEditable
-  final int interToneGap;
-
-  @DomName('RTCDTMFSender.toneBuffer')
-  @DocsEditable
-  final String toneBuffer;
-
-  @DomName('RTCDTMFSender.track')
-  @DocsEditable
-  final MediaStreamTrack track;
-
-  @JSName('addEventListener')
-  @DomName('RTCDTMFSender.addEventListener')
-  @DocsEditable
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native;
-
-  @DomName('RTCDTMFSender.dispatchEvent')
-  @DocsEditable
-  bool dispatchEvent(Event event) native;
-
-  @JSName('insertDTMF')
-  @DomName('RTCDTMFSender.insertDTMF')
-  @DocsEditable
-  void insertDtmf(String tones, [int duration, int interToneGap]) native;
-
-  @JSName('removeEventListener')
-  @DomName('RTCDTMFSender.removeEventListener')
-  @DocsEditable
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native;
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-
-@DocsEditable
-@DomName('RTCDTMFToneChangeEvent')
-class RtcdtmfToneChangeEvent extends Event native "*RTCDTMFToneChangeEvent" {
-
-  @DomName('RTCDTMFToneChangeEvent.tone')
-  @DocsEditable
-  final String tone;
-}
 // 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.
@@ -21425,6 +21567,14 @@
   void $dom_setItem(String key, String data) native;
 
 }
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// WARNING: Do not edit - generated code.
+
+
+typedef void StorageErrorCallback(DomException error);
 // 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.
@@ -21470,12 +21620,11 @@
   void $dom_initStorageEvent(String typeArg, bool canBubbleArg, bool cancelableArg, String keyArg, String oldValueArg, String newValueArg, String urlArg, Storage storageAreaArg) native;
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
 
-@DocsEditable
 @DomName('StorageInfo')
 class StorageInfo native "*StorageInfo" {
 
@@ -21486,23 +21635,12 @@
   @JSName('queryUsageAndQuota')
   @DomName('StorageInfo.queryUsageAndQuota')
   @DocsEditable
-  void _queryUsageAndQuota(int storageType, [_StorageInfoUsageCallback usageCallback, _StorageInfoErrorCallback errorCallback]) native;
-
-  @JSName('queryUsageAndQuota')
-  @DomName('StorageInfo.queryUsageAndQuota')
-  @DocsEditable
-  Future<int> queryUsageAndQuota(int storageType) {
-    var completer = new Completer<int>();
-    _queryUsageAndQuota(storageType,
-        (value) { completer.complete(value); },
-        (error) { completer.completeError(error); });
-    return completer.future;
-  }
+  void _queryUsageAndQuota(int storageType, [StorageUsageCallback usageCallback, StorageErrorCallback errorCallback]) native;
 
   @JSName('requestQuota')
   @DomName('StorageInfo.requestQuota')
   @DocsEditable
-  void _requestQuota(int storageType, int newQuotaInBytes, [StorageInfoQuotaCallback quotaCallback, _StorageInfoErrorCallback errorCallback]) native;
+  void _requestQuota(int storageType, int newQuotaInBytes, [StorageQuotaCallback quotaCallback, StorageErrorCallback errorCallback]) native;
 
   @JSName('requestQuota')
   @DomName('StorageInfo.requestQuota')
@@ -21514,6 +21652,44 @@
         (error) { completer.completeError(error); });
     return completer.future;
   }
+
+  Future<StorageInfoUsage> queryUsageAndQuota(int storageType) {
+    var completer = new Completer<StorageInfoUsage>();
+    _queryUsageAndQuota(storageType,
+        (currentUsageInBytes, currentQuotaInBytes) { 
+          completer.complete(new StorageInfoUsage(currentUsageInBytes, 
+              currentQuotaInBytes));
+        },
+        (error) { completer.completeError(error); });
+    return completer.future;
+  }
+}
+
+/** 
+ * A simple container class for the two values that are returned from the
+ * futures in requestQuota and queryUsageAndQuota.
+ */
+class StorageInfoUsage {
+  final int currentUsageInBytes;
+  final int currentQuotaInBytes;
+  const StorageInfoUsage(this.currentUsageInBytes, this.currentQuotaInBytes);
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+@DocsEditable
+@DomName('StorageQuota')
+class StorageQuota native "*StorageQuota" {
+
+  @DomName('StorageQuota.queryUsageAndQuota')
+  @DocsEditable
+  void queryUsageAndQuota(StorageUsageCallback usageCallback, [StorageErrorCallback errorCallback]) native;
+
+  @DomName('StorageQuota.requestQuota')
+  @DocsEditable
+  void requestQuota(int newQuotaInBytes, [StorageQuotaCallback quotaCallback, StorageErrorCallback errorCallback]) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -21522,7 +21698,7 @@
 // WARNING: Do not edit - generated code.
 
 
-typedef void _StorageInfoErrorCallback(DomException error);
+typedef void StorageQuotaCallback(int grantedQuotaInBytes);
 // 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.
@@ -21530,15 +21706,7 @@
 // WARNING: Do not edit - generated code.
 
 
-typedef void StorageInfoQuotaCallback(int grantedQuotaInBytes);
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// WARNING: Do not edit - generated code.
-
-
-typedef void _StorageInfoUsageCallback(int currentUsageInBytes, int currentQuotaInBytes);
+typedef void StorageUsageCallback(int currentUsageInBytes, int currentQuotaInBytes);
 // 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.
@@ -24508,6 +24676,21 @@
 
 
 @DocsEditable
+@DomName('WebGLCompressedTextureATC')
+class WebGLCompressedTextureAtc native "*WebGLCompressedTextureATC" {
+
+  static const int COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93;
+
+  static const int COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
+
+  static const int COMPRESSED_RGB_ATC_WEBGL = 0x8C92;
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+@DocsEditable
 @DomName('WebGLCompressedTextureS3TC')
 class WebGLCompressedTextureS3TC native "*WebGLCompressedTextureS3TC" {
 
@@ -26647,6 +26830,17 @@
     JS('void', '#.setImmediate(#)', this, convertDartClosureToJS(callback, 0));
   }
 
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. Returns a [Future] whose value stores a reference to the
+   * sandboxed file system for use. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  Future<FileSystem> requestFileSystem(int size, {bool persistent: false}) {
+    return _requestFileSystem(persistent? 1 : 0, size);
+  }
 
   @DomName('DOMWindow.DOMContentLoadedEvent')
   @DocsEditable
@@ -27109,16 +27303,16 @@
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  void _requestFileSystem(int type, int size, _FileSystemCallback successCallback, [_ErrorCallback errorCallback]) native;
+  void __requestFileSystem(int type, int size, _FileSystemCallback successCallback, [_ErrorCallback errorCallback]) native;
 
   @JSName('webkitRequestFileSystem')
   @DomName('DOMWindow.webkitRequestFileSystem')
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  Future<FileSystem> requestFileSystem(int type, int size) {
+  Future<FileSystem> _requestFileSystem(int type, int size) {
     var completer = new Completer<FileSystem>();
-    _requestFileSystem(type, size,
+    __requestFileSystem(type, size,
         (value) { completer.complete(value); },
         (error) { completer.completeError(error); });
     return completer.future;
@@ -27410,13 +27604,59 @@
   @DocsEditable
   Stream<MessageEvent> get onMessage => messageEvent.forTarget(this);
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
 
 @DomName('WorkerContext')
 class WorkerContext extends EventTarget native "*WorkerContext" {
+  /**
+   * Gets an instance of the Indexed DB factory to being using Indexed DB.
+   *
+   * Use [IdbFactory.supported] to check if Indexed DB is supported on the
+   * current platform.
+   */
+  @SupportedBrowser(SupportedBrowser.CHROME, '23.0')
+  @SupportedBrowser(SupportedBrowser.FIREFOX, '15.0')
+  @SupportedBrowser(SupportedBrowser.IE, '10.0')
+  @Experimental
+  IdbFactory get indexedDB =>
+      JS('IdbFactory',
+         '#.indexedDB || #.webkitIndexedDB || #.mozIndexedDB',
+         this, this, this);
+
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. Returns a [Future] whose value stores a reference to the
+   * sandboxed file system for use. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  @DomName('WorkerContext.webkitRequestFileSystem')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  Future<FileSystem> requestFileSystem(int size, {bool persistent: false}) {
+    return _requestFileSystem(persistent? 1 : 0, size);
+  }
+
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. This call will block until a reference to the synchronous file 
+   * system API has been obtained. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  @DomName('WorkerContext.webkitRequestFileSystemSync')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  FileSystemSync requestFileSystemSync(int size, {bool persistent: false}) {
+    return _requestFileSystemSync(persistent? 1 : 0, size);
+  }
 
   @DomName('WorkerContext.errorEvent')
   @DocsEditable
@@ -27503,16 +27743,16 @@
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  void _requestFileSystem(int type, int size, [_FileSystemCallback successCallback, _ErrorCallback errorCallback]) native;
+  void __requestFileSystem(int type, int size, [_FileSystemCallback successCallback, _ErrorCallback errorCallback]) native;
 
   @JSName('webkitRequestFileSystem')
   @DomName('WorkerContext.webkitRequestFileSystem')
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  Future<FileSystem> requestFileSystem(int type, int size) {
+  Future<FileSystem> _requestFileSystem(int type, int size) {
     var completer = new Completer<FileSystem>();
-    _requestFileSystem(type, size,
+    __requestFileSystem(type, size,
         (value) { completer.complete(value); },
         (error) { completer.completeError(error); });
     return completer.future;
@@ -27523,7 +27763,7 @@
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  FileSystemSync requestFileSystemSync(int type, int size) native;
+  FileSystemSync _requestFileSystemSync(int type, int size) native;
 
   @JSName('webkitResolveLocalFileSystemSyncURL')
   @DomName('WorkerContext.webkitResolveLocalFileSystemSyncURL')
@@ -27556,21 +27796,6 @@
   @DocsEditable
   Stream<Event> get onError => errorEvent.forTarget(this);
 
-
-  /**
-   * Gets an instance of the Indexed DB factory to being using Indexed DB.
-   *
-   * Use [IdbFactory.supported] to check if Indexed DB is supported on the
-   * current platform.
-   */
-  @SupportedBrowser(SupportedBrowser.CHROME, '23.0')
-  @SupportedBrowser(SupportedBrowser.FIREFOX, '15.0')
-  @SupportedBrowser(SupportedBrowser.IE, '10.0')
-  @Experimental
-  IdbFactory get indexedDB =>
-      JS('IdbFactory',
-         '#.indexedDB || #.webkitIndexedDB || #.mozIndexedDB',
-         this, this, this);
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -30304,8 +30529,8 @@
     return _element.$dom_getAttribute(key);
   }
 
-  void operator []=(String key, value) {
-    _element.$dom_setAttribute(key, '$value');
+  void operator []=(String key, String value) {
+    _element.$dom_setAttribute(key, value);
   }
 
   String remove(String key) {
@@ -30341,8 +30566,8 @@
     return _element.$dom_getAttributeNS(_namespace, key);
   }
 
-  void operator []=(String key, value) {
-    _element.$dom_setAttributeNS(_namespace, key, '$value');
+  void operator []=(String key, String value) {
+    _element.$dom_setAttributeNS(_namespace, key, value);
   }
 
   String remove(String key) {
@@ -30381,8 +30606,8 @@
 
   String operator [](String key) => $dom_attributes[_attr(key)];
 
-  void operator []=(String key, value) {
-    $dom_attributes[_attr(key)] = '$value';
+  void operator []=(String key, String value) {
+    $dom_attributes[_attr(key)] = value;
   }
 
   String putIfAbsent(String key, String ifAbsent()) =>
@@ -30442,8 +30667,10 @@
 
 /**
  * An object that can be drawn to a [CanvasRenderingContext2D] object with
- * [CanvasRenderingContext2D.drawImage] or
- * [CanvasRenderingContext2D.drawImageAtScale].
+ * [CanvasRenderingContext2D.drawImage],
+ * [CanvasRenderingContext2D.drawImageRect],
+ * [CanvasRenderingContext2D.drawImageScaled], or
+ * [CanvasRenderingContext2D.drawImageScaledFromSource].
  *
  * If the CanvasImageSource is an [ImageElement] then the element's image is
  * used. If the [ImageElement] is an animated image, then the poster frame is
@@ -30455,10 +30682,16 @@
  * If the CanvasImageSource is a [CanvasElement] then the element's bitmap is
  * used.
  *
+ * ** Note: ** Currently, all versions of Internet Explorer do not support
+ * drawing a VideoElement to a canvas. Also, you may experience problems drawing
+ * a video to a canvas in Firefox if the source of the video is a data URL.
+ *
  * See also:
  *
  *  * [CanvasImageSource](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#image-sources-for-2d-rendering-contexts)
  * from the WHATWG.
+ *  * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+ * from the WHATWG.
  */
 abstract class CanvasImageSource {}
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -30601,7 +30834,7 @@
   }
 
   /**
-   * Adds the class [token] to the element if it is not on it, removes it if it
+   * Adds the class [value] to the element if it is not on it, removes it if it
    * is.
    */
   bool toggle(String value) {
@@ -30655,14 +30888,33 @@
   // interface Collection - END
 
   // interface Set - BEGIN
+  /**
+   * Determine if this element contains the class [value].
+   *
+   * This is the Dart equivalent of jQuery's
+   * [hasClass](http://api.jquery.com/hasClass/).
+   */
   bool contains(String value) => readClasses().contains(value);
 
+  /**
+   * Add the class [value] to element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [addClass](http://api.jquery.com/addClass/).
+   */
   void add(String value) {
     // TODO - figure out if we need to do any validation here
     // or if the browser natively does enough.
     _modify((s) => s.add(value));
   }
 
+  /**
+   * Remove the class [value] from element, and return true on successful
+   * removal.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
   bool remove(Object value) {
     if (value is! String) return false;
     Set<String> s = readClasses();
@@ -30671,15 +30923,38 @@
     return result;
   }
 
+  /**
+   * Add all classes specified in [iterable] to element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [addClass](http://api.jquery.com/addClass/).
+   */
   void addAll(Iterable<String> iterable) {
     // TODO - see comment above about validation.
     _modify((s) => s.addAll(iterable));
   }
 
+  /**
+   * Remove all classes specified in [iterable] from element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
   void removeAll(Iterable<String> iterable) {
     _modify((s) => s.removeAll(iterable));
   }
 
+  /**
+   * Toggles all classes specified in [iterable] on element.
+   *
+   * Iterate through [iterable]'s items, and add it if it is not on it, or
+   * remove it if it is. This is the Dart equivalent of jQuery's
+   * [toggleClass](http://api.jquery.com/toggleClass/).
+   */
+  void toggleAll(Iterable<String> iterable) {
+    iterable.forEach(toggle);
+  }
+
   void retainAll(Iterable<String> iterable) {
     _modify((s) => s.retainAll(iterable));
   }
@@ -32476,7 +32751,7 @@
                             onComplete(HttpRequest request),
                             bool withCredentials) {
     final request = new HttpRequest();
-    request.open('GET', url, true);
+    request.open('GET', url, async: true);
 
     request.withCredentials = withCredentials;
 
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 5904236..e1424ad 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -1461,20 +1461,6 @@
   @Experimental
   void set imageSmoothingEnabled(bool value) native "CanvasRenderingContext2D_webkitImageSmoothingEnabled_Setter";
 
-  @DomName('CanvasRenderingContext2D.webkitLineDash')
-  @DocsEditable
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental
-  List get lineDash native "CanvasRenderingContext2D_webkitLineDash_Getter";
-
-  @DomName('CanvasRenderingContext2D.webkitLineDash')
-  @DocsEditable
-  @SupportedBrowser(SupportedBrowser.CHROME)
-  @SupportedBrowser(SupportedBrowser.SAFARI)
-  @Experimental
-  void set lineDash(List value) native "CanvasRenderingContext2D_webkitLineDash_Setter";
-
   @DomName('CanvasRenderingContext2D.arc')
   @DocsEditable
   void $dom_arc(num x, num y, num radius, num startAngle, num endAngle, bool anticlockwise) native "CanvasRenderingContext2D_arc_Callback";
@@ -1516,23 +1502,13 @@
   @DocsEditable
   void closePath() native "CanvasRenderingContext2D_closePath_Callback";
 
-  ImageData createImageData(imagedata_OR_sw, [num sh]) {
-    if ((imagedata_OR_sw is ImageData || imagedata_OR_sw == null) && !?sh) {
-      return _createImageData_1(imagedata_OR_sw);
-    }
-    if ((imagedata_OR_sw is num || imagedata_OR_sw == null) && (sh is num || sh == null)) {
-      return _createImageData_2(imagedata_OR_sw, sh);
-    }
-    throw new ArgumentError("Incorrect number or type of arguments");
-  }
-
-  @DomName('CanvasRenderingContext2D._createImageData_1')
+  @DomName('CanvasRenderingContext2D.createImageData')
   @DocsEditable
-  ImageData _createImageData_1(imagedata_OR_sw) native "CanvasRenderingContext2D__createImageData_1_Callback";
+  ImageData createImageData(num sw, num sh) native "CanvasRenderingContext2D_createImageData_Callback";
 
-  @DomName('CanvasRenderingContext2D._createImageData_2')
+  @DomName('CanvasRenderingContext2D.createImageDataFromImageData')
   @DocsEditable
-  ImageData _createImageData_2(imagedata_OR_sw, sh) native "CanvasRenderingContext2D__createImageData_2_Callback";
+  ImageData createImageDataFromImageData(ImageData imagedata) native "CanvasRenderingContext2D_createImageDataFromImageData_Callback";
 
   @DomName('CanvasRenderingContext2D.createLinearGradient')
   @DocsEditable
@@ -1882,11 +1858,73 @@
   }
 
   /**
+   * Draws an image from a CanvasImageSource to an area of this canvas.
+   *
+   * The image will be drawn to an area of this canvas defined by
+   * [destRect]. [sourceRect] defines the region of the source image that is
+   * drawn.
+   * If [sourceRect] is not provided, then
+   * the entire rectangular image from [source] will be drawn to this context.
+   *
+   * If the image is larger than canvas
+   * will allow, the image will be clipped to fit the available space.
+   *
+   *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
+   *     CanvasRenderingContext2D ctx = canvas.context2d;
+   *     ImageElement img = document.query('img');
+   *     img.width = 100;
+   *     img.height = 100;
+   *
+   *     // Scale the image to 20x20.
+   *     ctx.drawImageToRect(img, new Rect(50, 50, 20, 20));
+   *
+   *     VideoElement video = document.query('video');
+   *     video.width = 100;
+   *     video.height = 100;
+   *     // Take the middle 20x20 pixels from the video and stretch them.
+   *     ctx.drawImageToRect(video, new Rect(50, 50, 100, 100),
+   *         sourceRect: new Rect(40, 40, 20, 20));
+   *
+   *     // Draw the top 100x20 pixels from the otherCanvas.
+   *     CanvasElement otherCanvas = document.query('canvas');
+   *     ctx.drawImageToRect(otherCanvas, new Rect(0, 0, 100, 20),
+   *         sourceRect: new Rect(0, 0, 100, 20));
+   *
+   * See also:
+   *
+   *   * [CanvasImageSource] for more information on what data is retrieved
+   * from [source].
+   *   * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+   * from the WHATWG.
+   */
+  @DomName('CanvasRenderingContext2D.drawImage')
+  void drawImageToRect(CanvasImageSource source, Rect destRect,
+      {Rect sourceRect}) {
+    if (sourceRect == null) {
+      $dom_drawImage(source,
+          destRect.left,
+          destRect.top,
+          destRect.width,
+          destRect.height);
+    } else {
+      $dom_drawImage(source,
+          sourceRect.left,
+          sourceRect.top,
+          sourceRect.width,
+          sourceRect.height,
+          destRect.left,
+          destRect.top,
+          destRect.width,
+          destRect.height);
+    }
+  }
+
+  /**
    * Draws an image from a CanvasImageSource to this canvas.
    *
    * The entire image from [source] will be drawn to this context with its top
-   * left corner at the point ([destinationX], [destinationY]). If the image is
-   * larger than canvas will allow, the image will be cropped to fit the
+   * left corner at the point ([destX], [destY]). If the image is
+   * larger than canvas will allow, the image will be clipped to fit the
    * available space.
    *
    *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
@@ -1901,7 +1939,7 @@
    *     CanvasElement otherCanvas = document.query('canvas');
    *     otherCanvas.width = 100;
    *     otherCanvas.height = 100;
-   *     ctx.drawImage(otherCanvas, 590, 590); // will get cropped
+   *     ctx.drawImage(otherCanvas, 590, 590); // will get clipped
    *
    * See also:
    *
@@ -1911,20 +1949,19 @@
    * from the WHATWG.
    */
   @DomName('CanvasRenderingContext2D.drawImage')
-  void drawImage(CanvasImageSource source, num destinationX, num destinationY) {
-    $dom_drawImage(source, destinationX, destinationY);
+  void drawImage(CanvasImageSource source, num destX, num destY) {
+    $dom_drawImage(source, destX, destY);
   }
 
   /**
    * Draws an image from a CanvasImageSource to an area of this canvas.
    *
-   * The image will be drawn to an area of this canvas defined by
-   * [destinationRect]. If [sourceRect] is not provided, then
-   * the entire rectangular image from [source] will be drawn to this context.
-   * If the dimensions of [source] or [sourceRect]
-   * differ from [destinationRect], then the image will be scaled to fit.
+   * The image will be drawn to this context with its top left corner at the
+   * point ([destX], [destY]) and will be scaled to be [destWidth] wide and
+   * [destHeight] tall.
+   *
    * If the image is larger than canvas
-   * will allow, the image will be cropped to fit the available space.
+   * will allow, the image will be clipped to fit the available space.
    *
    *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
    *     CanvasRenderingContext2D ctx = canvas.context2d;
@@ -1932,20 +1969,8 @@
    *     img.width = 100;
    *     img.height = 100;
    *
-   *     // Scale the image to 20x20.
-   *     ctx.drawImageAtScale(img, new Rect(50, 50, 20, 20));
-   *
-   *     VideoElement video = document.query('video');
-   *     video.width = 100;
-   *     video.height = 100;
-   *     // Take the middle 20x20 pixels from the video and stretch them.
-   *     ctx.drawImageAtScale(video, new Rect(50, 50, 100, 100),
-   *         sourceRect: new Rect(40, 40, 20, 20));
-   *
-   *     // Draw the top 100x20 pixels from the otherCanvas.
-   *     CanvasElement otherCanvas = document.query('canvas');
-   *     ctx.drawImageAtScale(otherCanvas, new Rect(0, 0, 100, 20),
-   *         sourceRect: new Rect(0, 0, 100, 20));
+   *     // Scale the image to 300x50 at the point (20, 20)
+   *     ctx.drawImageScaled(img, 20, 20, 300, 50);
    *
    * See also:
    *
@@ -1955,28 +1980,52 @@
    * from the WHATWG.
    */
   @DomName('CanvasRenderingContext2D.drawImage')
-  void drawImageAtScale(CanvasImageSource source, Rect destinationRect,
-      {Rect sourceRect}) {
-    if (sourceRect == null) {
-      $dom_drawImage(source,
-          destinationRect.left,
-          destinationRect.top,
-          destinationRect.width,
-          destinationRect.height);
-    } else {
-      $dom_drawImage(source,
-          sourceRect.left,
-          sourceRect.top,
-          sourceRect.width,
-          sourceRect.height,
-          destinationRect.left,
-          destinationRect.top,
-          destinationRect.width,
-          destinationRect.height);
-    }
+  void drawImageScaled(CanvasImageSource source,
+      num destX, num destY, num destWidth, num destHeight) {
+    $dom_drawImage(source, destX, destY, destWidth, destHeight);
   }
 
+  /**
+   * Draws an image from a CanvasImageSource to an area of this canvas.
+   *
+   * The image is a region of [source] that is [sourceWidth] wide and
+   * [destHeight] tall with top left corner at ([sourceX], [sourceY]).
+   * The image will be drawn to this context with its top left corner at the
+   * point ([destX], [destY]) and will be scaled to be [destWidth] wide and
+   * [destHeight] tall.
+   *
+   * If the image is larger than canvas
+   * will allow, the image will be clipped to fit the available space.
+   *
+   *     VideoElement video = document.query('video');
+   *     video.width = 100;
+   *     video.height = 100;
+   *     // Take the middle 20x20 pixels from the video and stretch them.
+   *     ctx.drawImageScaledFromSource(video, 40, 40, 20, 20, 50, 50, 100, 100);
+   *
+   *     // Draw the top 100x20 pixels from the otherCanvas to this one.
+   *     CanvasElement otherCanvas = document.query('canvas');
+   *     ctx.drawImageScaledFromSource(otherCanvas, 0, 0, 100, 20, 0, 0, 100, 20);
+   *
+   * See also:
+   *
+   *   * [CanvasImageSource] for more information on what data is retrieved
+   * from [source].
+   *   * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+   * from the WHATWG.
+   */
+  @DomName('CanvasRenderingContext2D.drawImage')
+  void drawImageScaledFromSource(CanvasImageSource source,
+      num sourceX, num sourceY, num sourceWidth, num sourceHeight,
+      num destX, num destY, num destWidth, num destHeight) {
+    $dom_drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight,
+        destX, destY, destWidth, destHeight);
+  }
+
+  // TODO(amouravski): Add Dartium native methods for drawImage once we figure
+  // out how to not break native bindings.
 }
+
 // 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.
@@ -3019,6 +3068,10 @@
   @DocsEditable
   CssRule get parentRule native "CSSStyleDeclaration_parentRule_Getter";
 
+  @DomName('CSSStyleDeclaration._getPropertyValue')
+  @DocsEditable
+  String _getPropertyValue(String propertyName) native "CSSStyleDeclaration__getPropertyValue_Callback";
+
   @DomName('CSSStyleDeclaration.getPropertyCSSValue')
   @DocsEditable
   CssValue getPropertyCssValue(String propertyName) native "CSSStyleDeclaration_getPropertyCSSValue_Callback";
@@ -3031,10 +3084,6 @@
   @DocsEditable
   String getPropertyShorthand(String propertyName) native "CSSStyleDeclaration_getPropertyShorthand_Callback";
 
-  @DomName('CSSStyleDeclaration._getPropertyValue')
-  @DocsEditable
-  String _getPropertyValue(String propertyName) native "CSSStyleDeclaration__getPropertyValue_Callback";
-
   @DomName('CSSStyleDeclaration.isPropertyImplicit')
   @DocsEditable
   bool isPropertyImplicit(String propertyName) native "CSSStyleDeclaration_isPropertyImplicit_Callback";
@@ -6959,16 +7008,50 @@
   void $dom_initDeviceOrientationEvent(String type, bool bubbles, bool cancelable, num alpha, num beta, num gamma, bool absolute) native "DeviceOrientationEvent_initDeviceOrientationEvent_Callback";
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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: Do not edit - generated code.
 
-
-@DocsEditable
 @DomName('DirectoryEntry')
 class DirectoryEntry extends Entry {
+  
+  /**
+   * Create a new directory with the specified `path`. If `exclusive` is true,
+   * the returned Future will complete with an error if a directory already
+   * exists with the specified `path`.
+   */
+  Future<Entry> createDirectory(String path, {bool exclusive: false}) {
+    return _getDirectory(path, options: 
+        {'create': true, 'exclusive': exclusive});
+  }
+
+  /**
+   * Retrieve an already existing directory entry. The returned future will
+   * result in an error if a directory at `path` does not exist or if the item
+   * at `path` is not a directory.
+   */
+  Future<Entry> getDirectory(String path) {
+    return _getDirectory(path);
+  }
+
+  /**
+   * Create a new file with the specified `path`. If `exclusive` is true,
+   * the returned Future will complete with an error if a file already
+   * exists at the specified `path`.
+   */
+  Future<Entry> createFile(String path, {bool exclusive: false}) {
+    return _getFile(path, options: {'create': true, 'exclusive': exclusive});
+  }
+  
+  /**
+   * Retrieve an already existing file entry. The returned future will
+   * result in an error if a file at `path` does not exist or if the item at
+   * `path` is not a file.
+   */
+  Future<Entry> getFile(String path) {
+    return _getFile(path);
+  }
   DirectoryEntry.internal() : super.internal();
 
   @DomName('DirectoryEntry.createReader')
@@ -6977,11 +7060,11 @@
 
   @DomName('DirectoryEntry.getDirectory')
   @DocsEditable
-  void _getDirectory(String path, {Map options, _EntryCallback successCallback, _ErrorCallback errorCallback}) native "DirectoryEntry_getDirectory_Callback";
+  void __getDirectory(String path, {Map options, _EntryCallback successCallback, _ErrorCallback errorCallback}) native "DirectoryEntry_getDirectory_Callback";
 
-  Future<Entry> getDirectory(String path, {Map options}) {
+  Future<Entry> _getDirectory(String path, {Map options}) {
     var completer = new Completer<Entry>();
-    _getDirectory(path, options : options,
+    __getDirectory(path, options : options,
         successCallback : (value) { completer.complete(value); },
         errorCallback : (error) { completer.completeError(error); });
     return completer.future;
@@ -6989,11 +7072,11 @@
 
   @DomName('DirectoryEntry.getFile')
   @DocsEditable
-  void _getFile(String path, {Map options, _EntryCallback successCallback, _ErrorCallback errorCallback}) native "DirectoryEntry_getFile_Callback";
+  void __getFile(String path, {Map options, _EntryCallback successCallback, _ErrorCallback errorCallback}) native "DirectoryEntry_getFile_Callback";
 
-  Future<Entry> getFile(String path, {Map options}) {
+  Future<Entry> _getFile(String path, {Map options}) {
     var completer = new Completer<Entry>();
-    _getFile(path, options : options,
+    __getFile(path, options : options,
         successCallback : (value) { completer.complete(value); },
         errorCallback : (error) { completer.completeError(error); });
     return completer.future;
@@ -7012,6 +7095,7 @@
   }
 
 }
+
 // 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.
@@ -9058,7 +9142,7 @@
     if (index == length) {
       _element.append(element);
     } else {
-      throw new UnimplementedError("insert on ElementLists");
+      _element.insertBefore(element, this[index]);
     }
   }
 
@@ -9565,37 +9649,15 @@
     return window.$dom_getComputedStyle(this, pseudoElement);
   }
 
-  @deprecated
-  int get clientHeight => client.height;
-  @deprecated
-  int get clientLeft => client.left;
-  @deprecated
-  int get clientTop => client.top;
-  @deprecated
-  int get clientWidth => client.width;
+  /**
+   * Gets the position of this element relative to the client area of the page.
+   */
+  Rect get client => new Rect(clientLeft, clientTop, clientWidth, clientHeight);
 
-  @DomName('Element.clientHeight')
-  @DomName('Element.clientLeft')
-  @DomName('Element.clientTop')
-  @DomName('Element.clientWidth')
-  Rect get client => new Rect($dom_clientLeft, $dom_clientTop, $dom_clientWidth,
-      $dom_clientHeight);
-
-  @deprecated
-  int get offsetHeight => offset.height;
-  @deprecated
-  int get offsetLeft => offset.left;
-  @deprecated
-  int get offsetTop => offset.top;
-  @deprecated
-  int get offsetWidth => offset.width;
-
-  @DomName('Element.offsetHeight')
-  @DomName('Element.offsetLeft')
-  @DomName('Element.offsetTop')
-  @DomName('Element.offsetWidth')
-  Rect get offset => new Rect($dom_offsetLeft, $dom_offsetTop, $dom_offsetWidth,
-      $dom_offsetHeight);
+  /**
+   * Gets the offset of this element relative to its offsetParent.
+   */
+  Rect get offset => new Rect(offsetLeft, offsetTop, offsetWidth, offsetHeight);
 
   /**
    * Adds the specified text as a text node after the last child of this
@@ -9938,19 +10000,19 @@
 
   @DomName('Element.clientHeight')
   @DocsEditable
-  int get $dom_clientHeight native "Element_clientHeight_Getter";
+  int get clientHeight native "Element_clientHeight_Getter";
 
   @DomName('Element.clientLeft')
   @DocsEditable
-  int get $dom_clientLeft native "Element_clientLeft_Getter";
+  int get clientLeft native "Element_clientLeft_Getter";
 
   @DomName('Element.clientTop')
   @DocsEditable
-  int get $dom_clientTop native "Element_clientTop_Getter";
+  int get clientTop native "Element_clientTop_Getter";
 
   @DomName('Element.clientWidth')
   @DocsEditable
-  int get $dom_clientWidth native "Element_clientWidth_Getter";
+  int get clientWidth native "Element_clientWidth_Getter";
 
   @DomName('Element.firstElementChild')
   @DocsEditable
@@ -9966,11 +10028,11 @@
 
   @DomName('Element.offsetHeight')
   @DocsEditable
-  int get $dom_offsetHeight native "Element_offsetHeight_Getter";
+  int get offsetHeight native "Element_offsetHeight_Getter";
 
   @DomName('Element.offsetLeft')
   @DocsEditable
-  int get $dom_offsetLeft native "Element_offsetLeft_Getter";
+  int get offsetLeft native "Element_offsetLeft_Getter";
 
   @DomName('Element.offsetParent')
   @DocsEditable
@@ -9978,11 +10040,11 @@
 
   @DomName('Element.offsetTop')
   @DocsEditable
-  int get $dom_offsetTop native "Element_offsetTop_Getter";
+  int get offsetTop native "Element_offsetTop_Getter";
 
   @DomName('Element.offsetWidth')
   @DocsEditable
-  int get $dom_offsetWidth native "Element_offsetWidth_Getter";
+  int get offsetWidth native "Element_offsetWidth_Getter";
 
   @DomName('Element.previousElementSibling')
   @DocsEditable
@@ -10987,6 +11049,9 @@
 
   @DomName('Event.clipboardData')
   @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
   DataTransfer get clipboardData native "Event_clipboardData_Getter";
 
   @DomName('Event.currentTarget')
@@ -11071,16 +11136,19 @@
   String toString() native "EventException_toString_Callback";
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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: Do not edit - generated code.
 
-
-@DocsEditable
 @DomName('EventSource')
 class EventSource extends EventTarget {
+  factory EventSource(String title, {withCredentials: false}) {
+    var parsedOptions = {
+      'withCredentials': withCredentials,
+    };
+    return EventSource._factoryEventSource(title, parsedOptions);
+  }
   EventSource.internal() : super.internal();
 
   @DomName('EventSource.errorEvent')
@@ -11097,7 +11165,7 @@
 
   @DomName('EventSource.EventSource')
   @DocsEditable
-  factory EventSource(String url, [Map eventSourceInit]) {
+  static EventSource _factoryEventSource(String url, [Map eventSourceInit]) {
     return EventSource._create_1(url, eventSourceInit);
   }
 
@@ -13700,38 +13768,65 @@
   }
 
   @DomName('Document.webkitCancelFullScreen')
-  void webkitCancelFullScreen() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void cancelFullScreen() {
     document.$dom_webkitCancelFullScreen();
   }
 
   @DomName('Document.webkitExitFullscreen')
-  void webkitExitFullscreen() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void exitFullscreen() {
     document.$dom_webkitExitFullscreen();
   }
 
   @DomName('Document.webkitExitPointerLock')
-  void webkitExitPointerLock() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void exitPointerLock() {
     document.$dom_webkitExitPointerLock();
   }
 
   @DomName('Document.webkitFullscreenElement')
-  Element get webkitFullscreenElement => document.$dom_webkitFullscreenElement;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  Element get fullscreenElement => document.$dom_webkitFullscreenElement;
 
   @DomName('Document.webkitFullscreenEnabled')
-  bool get webkitFullscreenEnabled => document.$dom_webkitFullscreenEnabled;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get fullscreenEnabled => document.$dom_webkitFullscreenEnabled;
 
   @DomName('Document.webkitHidden')
-  bool get webkitHidden => document.$dom_webkitHidden;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get hidden => document.$dom_webkitHidden;
 
   @DomName('Document.webkitIsFullScreen')
-  bool get webkitIsFullScreen => document.$dom_webkitIsFullScreen;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get isFullScreen => document.$dom_webkitIsFullScreen;
 
   @DomName('Document.webkitPointerLockElement')
-  Element get webkitPointerLockElement =>
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  Element get pointerLockElement =>
       document.$dom_webkitPointerLockElement;
 
   @DomName('Document.webkitVisibilityState')
-  String get webkitVisibilityState => document.$dom_webkitVisibilityState;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  String get visibilityState => document.$dom_webkitVisibilityState;
 }
 // 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
@@ -13799,8 +13894,9 @@
  * wish to retrieve the HTML of the top-level page and print it out.
  * The easiest way to do that would be:
  *
- *     var httpRequest = HttpRequest.get('http://api.dartlang.org',
- *         (request) => print(request.responseText));
+ *     HttpRequest.getString('http://api.dartlang.org').then((response) {
+ *       print(response);
+ *     });
  *
  * **Important**: With the default behavior of this class, your
  * code making the request should be served from the same origin (domain name,
@@ -13916,6 +14012,17 @@
   }
 
   /**
+   * Checks to see if the current platform supports making cross origin
+   * requests.
+   *
+   * Note that even if cross origin requests are supported, they still may fail
+   * if the destination server does not support CORS requests.
+   */
+  static bool get supportsCrossOrigin {
+    return true;
+  }
+
+  /**
    * Checks to see if the LoadEnd event is supported on the current platform.
    */
   static bool get supportsLoadEndEvent {
@@ -18666,14 +18773,14 @@
   @DocsEditable
   static MutationObserver _create(callback) native "MutationObserver_constructorCallback";
 
-  @DomName('MutationObserver.disconnect')
-  @DocsEditable
-  void disconnect() native "MutationObserver_disconnect_Callback";
-
   @DomName('MutationObserver._observe')
   @DocsEditable
   void _observe(Node target, Map options) native "MutationObserver__observe_Callback";
 
+  @DomName('MutationObserver.disconnect')
+  @DocsEditable
+  void disconnect() native "MutationObserver_disconnect_Callback";
+
   @DomName('MutationObserver.takeRecords')
   @DocsEditable
   List<MutationRecord> takeRecords() native "MutationObserver_takeRecords_Callback";
@@ -18687,8 +18794,7 @@
   }
 
   void observe(Node target,
-               {Map options,
-                bool childList,
+               {bool childList,
                 bool attributes,
                 bool characterData,
                 bool subtree,
@@ -18699,19 +18805,6 @@
     // Parse options into map of known type.
     var parsedOptions = _createDict();
 
-    if (options != null) {
-      options.forEach((k, v) {
-          if (_boolKeys.containsKey(k)) {
-            _add(parsedOptions, k, true == v);
-          } else if (k == 'attributeFilter') {
-            _add(parsedOptions, k, _fixupList(v));
-          } else {
-            throw new ArgumentError(
-                "Illegal MutationObserver.observe option '$k'");
-          }
-        });
-    }
-
     // Override options passed in the map with named optional arguments.
     override(key, value) {
       if (value != null) _add(parsedOptions, key, value);
@@ -18810,25 +18903,41 @@
    * Gets a stream (video and or audio) from the local computer.
    *
    * Use [MediaStream.supported] to check if this is supported by the current
-   * platform.
+   * platform. The arguments `audio` and `video` default to `false` (stream does
+   * not use audio or video, respectively).
    *
-   * Example use:
+   * Simple example usage:
    *
-   *     window.navigator.getUserMedia(audio:true, video: true).then((stream) {
+   *     window.navigator.getUserMedia(audio: true, video: true).then((stream) {
    *       var video = new VideoElement()
    *         ..autoplay = true
    *         ..src = Url.createObjectUrl(stream);
    *       document.body.append(video);
    *     });
    *
+   * The user can also pass in Maps to the audio or video parameters to specify 
+   * mandatory and optional constraints for the media stream. Not passing in a 
+   * map, but passing in `true` will provide a LocalMediaStream with audio or 
+   * video capabilities, but without any additional constraints. The particular
+   * constraint names for audio and video are still in flux, but as of this 
+   * writing, here is an example providing more constraints.
+   *
+   *     window.navigator.getUserMedia(
+   *         audio: true, 
+   *         video: {'mandatory': 
+   *                    { 'minAspectRatio': 1.333, 'maxAspectRatio': 1.334 },
+   *                 'optional': 
+   *                    [{ 'minFrameRate': 60 },
+   *                     { 'maxWidth': 640 }]
+   *     });
+   *
    * See also:
    * * [MediaStream.supported]
    */
   @DomName('Navigator.webkitGetUserMedia')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  Future<LocalMediaStream> getUserMedia({bool audio: false,
-      bool video: false}) {
+  Future<LocalMediaStream> getUserMedia({audio: false, video: false}) {
     var completer = new Completer<LocalMediaStream>();
     var options = {
       'audio': audio,
@@ -18914,6 +19023,20 @@
   @Experimental
   BatteryManager get battery native "Navigator_webkitBattery_Getter";
 
+  @DomName('Navigator.webkitPersistentStorage')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  StorageQuota get persistentStorage native "Navigator_webkitPersistentStorage_Getter";
+
+  @DomName('Navigator.webkitTemporaryStorage')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  StorageQuota get temporaryStorage native "Navigator_webkitTemporaryStorage_Getter";
+
   @DomName('Navigator.getStorageUpdates')
   @DocsEditable
   void getStorageUpdates() native "Navigator_getStorageUpdates_Callback";
@@ -19042,7 +19165,7 @@
     if (index == length) {
       _this.append(node);
     } else {
-      this_.insertBefore(node, this[index]);
+      _this.insertBefore(node, this[index]);
     }
   }
 
@@ -19800,16 +19923,26 @@
   String get systemId native "Notation_systemId_Getter";
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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: Do not edit - generated code.
 
-
-@DocsEditable
 @DomName('Notification')
 class Notification extends EventTarget {
+
+  factory Notification(String title, {String titleDir: null, String body: null, 
+      String bodyDir: null, String tag: null, String iconUrl: null}) {
+
+    var parsedOptions = {};
+    if (titleDir != null) parsedOptions['titleDir'] = titleDir;
+    if (body != null) parsedOptions['body'] = body;
+    if (bodyDir != null) parsedOptions['bodyDir'] = bodyDir;
+    if (tag != null) parsedOptions['tag'] = tag;
+    if (iconUrl != null) parsedOptions['iconUrl'] = iconUrl;
+
+    return Notification._factoryNotification(title, parsedOptions);
+  }
   Notification.internal() : super.internal();
 
   @DomName('Notification.clickEvent')
@@ -19834,7 +19967,7 @@
 
   @DomName('Notification.Notification')
   @DocsEditable
-  factory Notification(String title, [Map options]) {
+  static Notification _factoryNotification(String title, [Map options]) {
     return Notification._create_1(title, options);
   }
 
@@ -21288,6 +21421,93 @@
 
 
 @DocsEditable
+@DomName('RTCDTMFSender')
+class RtcDtmfSender extends EventTarget {
+  RtcDtmfSender.internal() : super.internal();
+
+  @DomName('RTCDTMFSender.canInsertDTMF')
+  @DocsEditable
+  bool get canInsertDtmf native "RTCDTMFSender_canInsertDTMF_Getter";
+
+  @DomName('RTCDTMFSender.duration')
+  @DocsEditable
+  int get duration native "RTCDTMFSender_duration_Getter";
+
+  @DomName('RTCDTMFSender.interToneGap')
+  @DocsEditable
+  int get interToneGap native "RTCDTMFSender_interToneGap_Getter";
+
+  @DomName('RTCDTMFSender.toneBuffer')
+  @DocsEditable
+  String get toneBuffer native "RTCDTMFSender_toneBuffer_Getter";
+
+  @DomName('RTCDTMFSender.track')
+  @DocsEditable
+  MediaStreamTrack get track native "RTCDTMFSender_track_Getter";
+
+  @DomName('RTCDTMFSender.addEventListener')
+  @DocsEditable
+  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDTMFSender_addEventListener_Callback";
+
+  @DomName('RTCDTMFSender.dispatchEvent')
+  @DocsEditable
+  bool dispatchEvent(Event event) native "RTCDTMFSender_dispatchEvent_Callback";
+
+  void insertDtmf(String tones, [int duration, int interToneGap]) {
+    if (?interToneGap) {
+      _insertDTMF_1(tones, duration, interToneGap);
+      return;
+    }
+    if (?duration) {
+      _insertDTMF_2(tones, duration);
+      return;
+    }
+    _insertDTMF_3(tones);
+    return;
+  }
+
+  @DomName('RTCDTMFSender._insertDTMF_1')
+  @DocsEditable
+  void _insertDTMF_1(tones, duration, interToneGap) native "RTCDTMFSender__insertDTMF_1_Callback";
+
+  @DomName('RTCDTMFSender._insertDTMF_2')
+  @DocsEditable
+  void _insertDTMF_2(tones, duration) native "RTCDTMFSender__insertDTMF_2_Callback";
+
+  @DomName('RTCDTMFSender._insertDTMF_3')
+  @DocsEditable
+  void _insertDTMF_3(tones) native "RTCDTMFSender__insertDTMF_3_Callback";
+
+  @DomName('RTCDTMFSender.removeEventListener')
+  @DocsEditable
+  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDTMFSender_removeEventListener_Callback";
+
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
+@DomName('RTCDTMFToneChangeEvent')
+class RtcDtmfToneChangeEvent extends Event {
+  RtcDtmfToneChangeEvent.internal() : super.internal();
+
+  @DomName('RTCDTMFToneChangeEvent.tone')
+  @DocsEditable
+  String get tone native "RTCDTMFToneChangeEvent_tone_Getter";
+
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
 @DomName('RTCIceCandidate')
 @SupportedBrowser(SupportedBrowser.CHROME)
 @Experimental
@@ -21348,6 +21568,21 @@
    * the current platform.
    */
   static bool get supported => true;
+  Future<RtcSessionDescription> createOffer([Map mediaConstraints]) {
+    var completer = new Completer<RtcSessionDescription>();
+    _createOffer(
+        (value) { completer.complete(value); },
+        (error) { completer.completeError(error); }, mediaConstraints);
+    return completer.future;
+  }
+
+  Future<RtcSessionDescription> createAnswer([Map mediaConstraints]) {
+    var completer = new Completer<RtcSessionDescription>();
+    _createAnswer(
+        (value) { completer.complete(value); },
+        (error) { completer.completeError(error); }, mediaConstraints);
+    return completer.future;
+  }
   RtcPeerConnection.internal() : super.internal();
 
   @DomName('RTCPeerConnection.addstreamEvent')
@@ -21435,17 +21670,9 @@
   @DocsEditable
   void _createAnswer(_RtcSessionDescriptionCallback successCallback, [_RtcErrorCallback failureCallback, Map mediaConstraints]) native "RTCPeerConnection_createAnswer_Callback";
 
-  Future<RtcSessionDescription> createAnswer([Map mediaConstraints]) {
-    var completer = new Completer<RtcSessionDescription>();
-    _createAnswer(mediaConstraints,
-        (value) { completer.complete(value); },
-        (error) { completer.completeError(error); });
-    return completer.future;
-  }
-
   @DomName('RTCPeerConnection.createDTMFSender')
   @DocsEditable
-  RtcdtmfSender createDtmfSender(MediaStreamTrack track) native "RTCPeerConnection_createDTMFSender_Callback";
+  RtcDtmfSender createDtmfSender(MediaStreamTrack track) native "RTCPeerConnection_createDTMFSender_Callback";
 
   @DomName('RTCPeerConnection.createDataChannel')
   @DocsEditable
@@ -21455,14 +21682,6 @@
   @DocsEditable
   void _createOffer(_RtcSessionDescriptionCallback successCallback, [_RtcErrorCallback failureCallback, Map mediaConstraints]) native "RTCPeerConnection_createOffer_Callback";
 
-  Future<RtcSessionDescription> createOffer([Map mediaConstraints]) {
-    var completer = new Completer<RtcSessionDescription>();
-    _createOffer(mediaConstraints,
-        (value) { completer.complete(value); },
-        (error) { completer.completeError(error); });
-    return completer.future;
-  }
-
   @DomName('RTCPeerConnection.dispatchEvent')
   @DocsEditable
   bool dispatchEvent(Event event) native "RTCPeerConnection_dispatchEvent_Callback";
@@ -21479,6 +21698,10 @@
   @DocsEditable
   void getStats(RtcStatsCallback successCallback, MediaStreamTrack selector) native "RTCPeerConnection_getStats_Callback";
 
+  @DomName('RTCPeerConnection.getStreamById')
+  @DocsEditable
+  MediaStream getStreamById(String streamId) native "RTCPeerConnection_getStreamById_Callback";
+
   @DomName('RTCPeerConnection.removeEventListener')
   @DocsEditable
   void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCPeerConnection_removeEventListener_Callback";
@@ -21598,42 +21821,33 @@
 
 
 @DocsEditable
-@DomName('RTCStatsElement')
-class RtcStatsElement extends NativeFieldWrapperClass1 {
-  RtcStatsElement.internal();
-
-  @DomName('RTCStatsElement.timestamp')
-  @DocsEditable
-  DateTime get timestamp native "RTCStatsElement_timestamp_Getter";
-
-  @DomName('RTCStatsElement.names')
-  @DocsEditable
-  List<String> names() native "RTCStatsElement_names_Callback";
-
-  @DomName('RTCStatsElement.stat')
-  @DocsEditable
-  String stat(String name) native "RTCStatsElement_stat_Callback";
-
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable
 @DomName('RTCStatsReport')
 class RtcStatsReport extends NativeFieldWrapperClass1 {
   RtcStatsReport.internal();
 
+  @DomName('RTCStatsReport.id')
+  @DocsEditable
+  String get id native "RTCStatsReport_id_Getter";
+
   @DomName('RTCStatsReport.local')
   @DocsEditable
-  RtcStatsElement get local native "RTCStatsReport_local_Getter";
+  RtcStatsReport get local native "RTCStatsReport_local_Getter";
 
   @DomName('RTCStatsReport.remote')
   @DocsEditable
-  RtcStatsElement get remote native "RTCStatsReport_remote_Getter";
+  RtcStatsReport get remote native "RTCStatsReport_remote_Getter";
+
+  @DomName('RTCStatsReport.timestamp')
+  @DocsEditable
+  DateTime get timestamp native "RTCStatsReport_timestamp_Getter";
+
+  @DomName('RTCStatsReport.names')
+  @DocsEditable
+  List<String> names() native "RTCStatsReport_names_Callback";
+
+  @DomName('RTCStatsReport.stat')
+  @DocsEditable
+  String stat(String name) native "RTCStatsReport_stat_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -21648,98 +21862,15 @@
 class RtcStatsResponse extends NativeFieldWrapperClass1 {
   RtcStatsResponse.internal();
 
+  @DomName('RTCStatsResponse.namedItem')
+  @DocsEditable
+  RtcStatsReport namedItem(String name) native "RTCStatsResponse_namedItem_Callback";
+
   @DomName('RTCStatsResponse.result')
   @DocsEditable
   List<RtcStatsReport> result() native "RTCStatsResponse_result_Callback";
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable
-@DomName('RTCDTMFSender')
-class RtcdtmfSender extends EventTarget {
-  RtcdtmfSender.internal() : super.internal();
-
-  @DomName('RTCDTMFSender.canInsertDTMF')
-  @DocsEditable
-  bool get canInsertDtmf native "RTCDTMFSender_canInsertDTMF_Getter";
-
-  @DomName('RTCDTMFSender.duration')
-  @DocsEditable
-  int get duration native "RTCDTMFSender_duration_Getter";
-
-  @DomName('RTCDTMFSender.interToneGap')
-  @DocsEditable
-  int get interToneGap native "RTCDTMFSender_interToneGap_Getter";
-
-  @DomName('RTCDTMFSender.toneBuffer')
-  @DocsEditable
-  String get toneBuffer native "RTCDTMFSender_toneBuffer_Getter";
-
-  @DomName('RTCDTMFSender.track')
-  @DocsEditable
-  MediaStreamTrack get track native "RTCDTMFSender_track_Getter";
-
-  @DomName('RTCDTMFSender.addEventListener')
-  @DocsEditable
-  void $dom_addEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDTMFSender_addEventListener_Callback";
-
-  @DomName('RTCDTMFSender.dispatchEvent')
-  @DocsEditable
-  bool dispatchEvent(Event event) native "RTCDTMFSender_dispatchEvent_Callback";
-
-  void insertDtmf(String tones, [int duration, int interToneGap]) {
-    if (?interToneGap) {
-      _insertDTMF_1(tones, duration, interToneGap);
-      return;
-    }
-    if (?duration) {
-      _insertDTMF_2(tones, duration);
-      return;
-    }
-    _insertDTMF_3(tones);
-    return;
-  }
-
-  @DomName('RTCDTMFSender._insertDTMF_1')
-  @DocsEditable
-  void _insertDTMF_1(tones, duration, interToneGap) native "RTCDTMFSender__insertDTMF_1_Callback";
-
-  @DomName('RTCDTMFSender._insertDTMF_2')
-  @DocsEditable
-  void _insertDTMF_2(tones, duration) native "RTCDTMFSender__insertDTMF_2_Callback";
-
-  @DomName('RTCDTMFSender._insertDTMF_3')
-  @DocsEditable
-  void _insertDTMF_3(tones) native "RTCDTMFSender__insertDTMF_3_Callback";
-
-  @DomName('RTCDTMFSender.removeEventListener')
-  @DocsEditable
-  void $dom_removeEventListener(String type, EventListener listener, [bool useCapture]) native "RTCDTMFSender_removeEventListener_Callback";
-
-}
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable
-@DomName('RTCDTMFToneChangeEvent')
-class RtcdtmfToneChangeEvent extends Event {
-  RtcdtmfToneChangeEvent.internal() : super.internal();
-
-  @DomName('RTCDTMFToneChangeEvent.tone')
-  @DocsEditable
-  String get tone native "RTCDTMFToneChangeEvent_tone_Getter";
-
-}
 // 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.
@@ -23281,6 +23412,14 @@
   void $dom_setItem(String key, String data) native "Storage_setItem_Callback";
 
 }
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// WARNING: Do not edit - generated code.
+
+
+typedef void StorageErrorCallback(DomException error);
 // 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.
@@ -23326,14 +23465,11 @@
   void $dom_initStorageEvent(String typeArg, bool canBubbleArg, bool cancelableArg, String keyArg, String oldValueArg, String newValueArg, String urlArg, Storage storageAreaArg) native "StorageEvent_initStorageEvent_Callback";
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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: Do not edit - generated code.
 
-
-@DocsEditable
 @DomName('StorageInfo')
 class StorageInfo extends NativeFieldWrapperClass1 {
   StorageInfo.internal();
@@ -23344,19 +23480,11 @@
 
   @DomName('StorageInfo.queryUsageAndQuota')
   @DocsEditable
-  void _queryUsageAndQuota(int storageType, [_StorageInfoUsageCallback usageCallback, _StorageInfoErrorCallback errorCallback]) native "StorageInfo_queryUsageAndQuota_Callback";
-
-  Future<int> queryUsageAndQuota(int storageType) {
-    var completer = new Completer<int>();
-    _queryUsageAndQuota(storageType,
-        (value) { completer.complete(value); },
-        (error) { completer.completeError(error); });
-    return completer.future;
-  }
+  void _queryUsageAndQuota(int storageType, [StorageUsageCallback usageCallback, StorageErrorCallback errorCallback]) native "StorageInfo_queryUsageAndQuota_Callback";
 
   @DomName('StorageInfo.requestQuota')
   @DocsEditable
-  void _requestQuota(int storageType, int newQuotaInBytes, [StorageInfoQuotaCallback quotaCallback, _StorageInfoErrorCallback errorCallback]) native "StorageInfo_requestQuota_Callback";
+  void _requestQuota(int storageType, int newQuotaInBytes, [StorageQuotaCallback quotaCallback, StorageErrorCallback errorCallback]) native "StorageInfo_requestQuota_Callback";
 
   Future<int> requestQuota(int storageType, int newQuotaInBytes) {
     var completer = new Completer<int>();
@@ -23366,6 +23494,26 @@
     return completer.future;
   }
 
+  Future<StorageInfoUsage> queryUsageAndQuota(int storageType) {
+    var completer = new Completer<StorageInfoUsage>();
+    _queryUsageAndQuota(storageType,
+        (currentUsageInBytes, currentQuotaInBytes) { 
+          completer.complete(new StorageInfoUsage(currentUsageInBytes, 
+              currentQuotaInBytes));
+        },
+        (error) { completer.completeError(error); });
+    return completer.future;
+  }
+}
+
+/** 
+ * A simple container class for the two values that are returned from the
+ * futures in requestQuota and queryUsageAndQuota.
+ */
+class StorageInfoUsage {
+  final int currentUsageInBytes;
+  final int currentQuotaInBytes;
+  const StorageInfoUsage(this.currentUsageInBytes, this.currentQuotaInBytes);
 }
 // 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
@@ -23374,7 +23522,20 @@
 // WARNING: Do not edit - generated code.
 
 
-typedef void _StorageInfoErrorCallback(DomException error);
+@DocsEditable
+@DomName('StorageQuota')
+class StorageQuota extends NativeFieldWrapperClass1 {
+  StorageQuota.internal();
+
+  @DomName('StorageQuota.queryUsageAndQuota')
+  @DocsEditable
+  void queryUsageAndQuota(StorageUsageCallback usageCallback, [StorageErrorCallback errorCallback]) native "StorageQuota_queryUsageAndQuota_Callback";
+
+  @DomName('StorageQuota.requestQuota')
+  @DocsEditable
+  void requestQuota(int newQuotaInBytes, [StorageQuotaCallback quotaCallback, StorageErrorCallback errorCallback]) native "StorageQuota_requestQuota_Callback";
+
+}
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
@@ -23382,7 +23543,7 @@
 // WARNING: Do not edit - generated code.
 
 
-typedef void StorageInfoQuotaCallback(int grantedQuotaInBytes);
+typedef void StorageQuotaCallback(int grantedQuotaInBytes);
 // 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.
@@ -23390,7 +23551,7 @@
 // WARNING: Do not edit - generated code.
 
 
-typedef void _StorageInfoUsageCallback(int currentUsageInBytes, int currentQuotaInBytes);
+typedef void StorageUsageCallback(int currentUsageInBytes, int currentQuotaInBytes);
 // 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.
@@ -26726,6 +26887,25 @@
 
 
 @DocsEditable
+@DomName('WebGLCompressedTextureATC')
+class WebGLCompressedTextureAtc extends NativeFieldWrapperClass1 {
+  WebGLCompressedTextureAtc.internal();
+
+  static const int COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93;
+
+  static const int COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
+
+  static const int COMPRESSED_RGB_ATC_WEBGL = 0x8C92;
+
+}
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable
 @DomName('WebGLCompressedTextureS3TC')
 class WebGLCompressedTextureS3TC extends NativeFieldWrapperClass1 {
   WebGLCompressedTextureS3TC.internal();
@@ -28744,6 +28924,17 @@
     throw new UnsupportedError('setImmediate is not supported');
   }
 
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. Returns a [Future] whose value stores a reference to the
+   * sandboxed file system for use. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  Future<FileSystem> requestFileSystem(int size, {bool persistent: false}) {
+    return _requestFileSystem(persistent? 1 : 0, size);
+  }
   Window.internal() : super.internal();
 
   @DomName('DOMWindow.DOMContentLoadedEvent')
@@ -29205,11 +29396,11 @@
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  void _requestFileSystem(int type, int size, _FileSystemCallback successCallback, [_ErrorCallback errorCallback]) native "DOMWindow_webkitRequestFileSystem_Callback";
+  void __requestFileSystem(int type, int size, _FileSystemCallback successCallback, [_ErrorCallback errorCallback]) native "DOMWindow_webkitRequestFileSystem_Callback";
 
-  Future<FileSystem> requestFileSystem(int type, int size) {
+  Future<FileSystem> _requestFileSystem(int type, int size) {
     var completer = new Completer<FileSystem>();
-    _requestFileSystem(type, size,
+    __requestFileSystem(type, size,
         (value) { completer.complete(value); },
         (error) { completer.completeError(error); });
     return completer.future;
@@ -29484,16 +29675,45 @@
   Stream<MessageEvent> get onMessage => messageEvent.forTarget(this);
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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: Do not edit - generated code.
 
-
-@DocsEditable
 @DomName('WorkerContext')
 class WorkerContext extends EventTarget {
+
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. Returns a [Future] whose value stores a reference to the
+   * sandboxed file system for use. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  @DomName('WorkerContext.webkitRequestFileSystem')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  Future<FileSystem> requestFileSystem(int size, {bool persistent: false}) {
+    return _requestFileSystem(persistent? 1 : 0, size);
+  }
+
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. This call will block until a reference to the synchronous file 
+   * system API has been obtained. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  @DomName('WorkerContext.webkitRequestFileSystemSync')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  FileSystemSync requestFileSystemSync(int size, {bool persistent: false}) {
+    return _requestFileSystemSync(persistent? 1 : 0, size);
+  }
   WorkerContext.internal() : super.internal();
 
   @DomName('WorkerContext.errorEvent')
@@ -29585,11 +29805,11 @@
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  void _requestFileSystem(int type, int size, [_FileSystemCallback successCallback, _ErrorCallback errorCallback]) native "WorkerContext_webkitRequestFileSystem_Callback";
+  void __requestFileSystem(int type, int size, [_FileSystemCallback successCallback, _ErrorCallback errorCallback]) native "WorkerContext_webkitRequestFileSystem_Callback";
 
-  Future<FileSystem> requestFileSystem(int type, int size) {
+  Future<FileSystem> _requestFileSystem(int type, int size) {
     var completer = new Completer<FileSystem>();
-    _requestFileSystem(type, size,
+    __requestFileSystem(type, size,
         (value) { completer.complete(value); },
         (error) { completer.completeError(error); });
     return completer.future;
@@ -29599,7 +29819,7 @@
   @DocsEditable
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  FileSystemSync requestFileSystemSync(int type, int size) native "WorkerContext_webkitRequestFileSystemSync_Callback";
+  FileSystemSync _requestFileSystemSync(int type, int size) native "WorkerContext_webkitRequestFileSystemSync_Callback";
 
   @DomName('WorkerContext.webkitResolveLocalFileSystemSyncURL')
   @DocsEditable
@@ -32612,8 +32832,8 @@
     return _element.$dom_getAttribute(key);
   }
 
-  void operator []=(String key, value) {
-    _element.$dom_setAttribute(key, '$value');
+  void operator []=(String key, String value) {
+    _element.$dom_setAttribute(key, value);
   }
 
   String remove(String key) {
@@ -32649,8 +32869,8 @@
     return _element.$dom_getAttributeNS(_namespace, key);
   }
 
-  void operator []=(String key, value) {
-    _element.$dom_setAttributeNS(_namespace, key, '$value');
+  void operator []=(String key, String value) {
+    _element.$dom_setAttributeNS(_namespace, key, value);
   }
 
   String remove(String key) {
@@ -32689,8 +32909,8 @@
 
   String operator [](String key) => $dom_attributes[_attr(key)];
 
-  void operator []=(String key, value) {
-    $dom_attributes[_attr(key)] = '$value';
+  void operator []=(String key, String value) {
+    $dom_attributes[_attr(key)] = value;
   }
 
   String putIfAbsent(String key, String ifAbsent()) =>
@@ -32750,8 +32970,10 @@
 
 /**
  * An object that can be drawn to a [CanvasRenderingContext2D] object with
- * [CanvasRenderingContext2D.drawImage] or
- * [CanvasRenderingContext2D.drawImageAtScale].
+ * [CanvasRenderingContext2D.drawImage],
+ * [CanvasRenderingContext2D.drawImageRect],
+ * [CanvasRenderingContext2D.drawImageScaled], or
+ * [CanvasRenderingContext2D.drawImageScaledFromSource].
  *
  * If the CanvasImageSource is an [ImageElement] then the element's image is
  * used. If the [ImageElement] is an animated image, then the poster frame is
@@ -32763,10 +32985,16 @@
  * If the CanvasImageSource is a [CanvasElement] then the element's bitmap is
  * used.
  *
+ * ** Note: ** Currently, all versions of Internet Explorer do not support
+ * drawing a VideoElement to a canvas. Also, you may experience problems drawing
+ * a video to a canvas in Firefox if the source of the video is a data URL.
+ *
  * See also:
  *
  *  * [CanvasImageSource](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#image-sources-for-2d-rendering-contexts)
  * from the WHATWG.
+ *  * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+ * from the WHATWG.
  */
 abstract class CanvasImageSource {}
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -32909,7 +33137,7 @@
   }
 
   /**
-   * Adds the class [token] to the element if it is not on it, removes it if it
+   * Adds the class [value] to the element if it is not on it, removes it if it
    * is.
    */
   bool toggle(String value) {
@@ -32963,14 +33191,33 @@
   // interface Collection - END
 
   // interface Set - BEGIN
+  /**
+   * Determine if this element contains the class [value].
+   *
+   * This is the Dart equivalent of jQuery's
+   * [hasClass](http://api.jquery.com/hasClass/).
+   */
   bool contains(String value) => readClasses().contains(value);
 
+  /**
+   * Add the class [value] to element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [addClass](http://api.jquery.com/addClass/).
+   */
   void add(String value) {
     // TODO - figure out if we need to do any validation here
     // or if the browser natively does enough.
     _modify((s) => s.add(value));
   }
 
+  /**
+   * Remove the class [value] from element, and return true on successful
+   * removal.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
   bool remove(Object value) {
     if (value is! String) return false;
     Set<String> s = readClasses();
@@ -32979,15 +33226,38 @@
     return result;
   }
 
+  /**
+   * Add all classes specified in [iterable] to element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [addClass](http://api.jquery.com/addClass/).
+   */
   void addAll(Iterable<String> iterable) {
     // TODO - see comment above about validation.
     _modify((s) => s.addAll(iterable));
   }
 
+  /**
+   * Remove all classes specified in [iterable] from element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
   void removeAll(Iterable<String> iterable) {
     _modify((s) => s.removeAll(iterable));
   }
 
+  /**
+   * Toggles all classes specified in [iterable] on element.
+   *
+   * Iterate through [iterable]'s items, and add it if it is not on it, or
+   * remove it if it is. This is the Dart equivalent of jQuery's
+   * [toggleClass](http://api.jquery.com/toggleClass/).
+   */
+  void toggleAll(Iterable<String> iterable) {
+    iterable.forEach(toggle);
+  }
+
   void retainAll(Iterable<String> iterable) {
     _modify((s) => s.retainAll(iterable));
   }
@@ -34931,7 +35201,7 @@
                             onComplete(HttpRequest request),
                             bool withCredentials) {
     final request = new HttpRequest();
-    request.open('GET', url, true);
+    request.open('GET', url, async: true);
 
     request.withCredentials = withCredentials;
 
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 9ecf7cb..79a467c 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -179,16 +179,16 @@
   @DocsEditable
   void advance(int count) native;
 
-  @JSName('continue')
-  @DomName('IDBCursor.continue')
-  @DocsEditable
-  void next([Object key]) native;
-
   @JSName('delete')
   @DomName('IDBCursor.delete')
   @DocsEditable
   Request $dom_delete() native;
 
+  @JSName('continue')
+  @DomName('IDBCursor.continue')
+  @DocsEditable
+  void next([Object key]) native;
+
   @DomName('IDBCursor.update')
   @DocsEditable
   Request $dom_update(/*any*/ value) {
@@ -766,10 +766,10 @@
     }
   }
 
-  @DomName('IDBObjectStore.getObject')
+  @DomName('IDBObjectStore.get')
   Future getObject(key) {
     try {
-      var request = $dom_getObject(key);
+      var request = $dom_get(key);
 
       return _completeRequest(request);
     } catch (e, stacktrace) {
@@ -949,7 +949,7 @@
   @Returns('Request')
   @Creates('Request')
   @annotation_Creates_SerializedScriptValue
-  Request $dom_getObject(key) native;
+  Request $dom_get(key) native;
 
   @DomName('IDBObjectStore.index')
   @DocsEditable
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 3e843ac..0c150df 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -80,6 +80,10 @@
   @DocsEditable
   void advance(int count) native "IDBCursor_advance_Callback";
 
+  @DomName('IDBCursor.delete')
+  @DocsEditable
+  Request $dom_delete() native "IDBCursor_delete_Callback";
+
   void next([Object key]) {
     if (?key) {
       _continue_1(key);
@@ -97,10 +101,6 @@
   @DocsEditable
   void _continue_2() native "IDBCursor__continue_2_Callback";
 
-  @DomName('IDBCursor.delete')
-  @DocsEditable
-  Request $dom_delete() native "IDBCursor_delete_Callback";
-
   @DomName('IDBCursor.update')
   @DocsEditable
   Request $dom_update(Object value) native "IDBCursor_update_Callback";
@@ -801,10 +801,10 @@
     }
   }
 
-  @DomName('IDBObjectStore.getObject')
+  @DomName('IDBObjectStore.get')
   Future getObject(key) {
     try {
-      var request = $dom_getObject(key);
+      var request = $dom_get(key);
 
       return _completeRequest(request);
     } catch (e, stacktrace) {
@@ -975,7 +975,7 @@
   @DocsEditable
   void deleteIndex(String name) native "IDBObjectStore_deleteIndex_Callback";
 
-  Request $dom_getObject(key) {
+  Request $dom_get(key) {
     if ((key is KeyRange || key == null)) {
       return _get_1(key);
     }
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index cf9ae48..f9bcff5 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -134,19 +134,29 @@
    * Lists the sub-directories and files of this [Directory].
    * Optionally recurses into sub-directories.
    *
+   * If [followLinks] is false, then any symbolic links found
+   * are reported as links, rather than as directories or files,
+   * and are not recursed into.
+   *
    * The result is a stream of [FileSystemEntity] objects
-   * for the directories and files.
+   * for the directories, files, and links.
    */
-  Stream<FileSystemEntity> list({bool recursive: false});
+  Stream<FileSystemEntity> list({bool recursive: false,
+                                 bool followLinks: true});
 
   /**
    * Lists the sub-directories and files of this [Directory].
    * Optionally recurses into sub-directories.
    *
+   * If [followLinks] is false, then any symbolic links found
+   * are reported as links, rather than as directories or files,
+   * and are not recursed into.
+   *
    * Returns a [List] containing [FileSystemEntity] objects for the
-   * directories and files.
+   * directories, files, and links.
    */
-  List<FileSystemEntity> listSync({bool recursive: false});
+  List<FileSystemEntity> listSync({bool recursive: false,
+                                   bool followLinks: true});
 
   /**
    * Returns a human readable string for this Directory instance.
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index a129cc7..6b6cc38 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -26,7 +26,7 @@
   external static _create(String path);
   external static _delete(String path, bool recursive);
   external static _rename(String path, String newPath);
-  external static List _list(String path, bool recursive);
+  external static List _list(String path, bool recursive, bool followLinks);
   external static SendPort _newServicePort();
 
   Future<bool> exists() {
@@ -226,11 +226,13 @@
     return new Directory(newPath);
   }
 
-  Stream<FileSystemEntity> list({bool recursive: false}) {
+  Stream<FileSystemEntity> list({bool recursive: false,
+                                 bool followLinks: true}) {
     const int LIST_FILE = 0;
     const int LIST_DIRECTORY = 1;
-    const int LIST_ERROR = 2;
-    const int LIST_DONE = 3;
+    const int LIST_LINK = 2;
+    const int LIST_ERROR = 3;
+    const int LIST_DONE = 4;
 
     const int RESPONSE_TYPE = 0;
     const int RESPONSE_PATH = 1;
@@ -239,7 +241,7 @@
 
     var controller = new StreamController<FileSystemEntity>();
 
-    List request = [ _Directory.LIST_REQUEST, path, recursive ];
+    List request = [ _Directory.LIST_REQUEST, path, recursive, followLinks ];
     ReceivePort responsePort = new ReceivePort();
     // Use a separate directory service port for each listing as
     // listing operations on the same directory can run in parallel.
@@ -257,6 +259,9 @@
         case LIST_DIRECTORY:
           controller.add(new Directory(message[RESPONSE_PATH]));
           break;
+        case LIST_LINK:
+          controller.add(new Link(message[RESPONSE_PATH]));
+          break;
         case LIST_ERROR:
           var errorType =
               message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE];
@@ -287,11 +292,11 @@
     return controller.stream;
   }
 
-  List listSync({bool recursive: false}) {
+  List listSync({bool recursive: false, bool followLinks: true}) {
     if (_path is! String || recursive is! bool) {
       throw new ArgumentError();
     }
-    return _list(_path, recursive);
+    return _list(_path, recursive, followLinks);
   }
 
   String get path => _path;
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index d484cf3..7de3d7d 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -135,7 +135,7 @@
    * [FileMode.APPEND]: same as [FileMode.WRITE] except that the file is
    * not truncated.
    */
-  Future<RandomAccessFile> open([FileMode mode = FileMode.READ]);
+  Future<RandomAccessFile> open({FileMode mode: FileMode.READ});
 
   /**
    * Synchronously open the file for random access operations. The
@@ -145,7 +145,7 @@
    *
    * See [open] for information on the [mode] argument.
    */
-  RandomAccessFile openSync([FileMode mode = FileMode.READ]);
+  RandomAccessFile openSync({FileMode mode: FileMode.READ});
 
   /**
    * Get the canonical full path corresponding to the file path.
@@ -207,13 +207,13 @@
    * Returns a [:Future<String>:] that completes with the string once
    * the file contents has been read.
    */
-  Future<String> readAsString([Encoding encoding = Encoding.UTF_8]);
+  Future<String> readAsString({Encoding encoding: Encoding.UTF_8});
 
   /**
    * Synchronously read the entire file contents as a string using the
    * given [Encoding].
    */
-  String readAsStringSync([Encoding encoding = Encoding.UTF_8]);
+  String readAsStringSync({Encoding encoding: Encoding.UTF_8});
 
   /**
    * Read the entire file contents as lines of text using the given
@@ -222,13 +222,13 @@
    * Returns a [:Future<List<String>>:] that completes with the lines
    * once the file contents has been read.
    */
-  Future<List<String>> readAsLines([Encoding encoding = Encoding.UTF_8]);
+  Future<List<String>> readAsLines({Encoding encoding: Encoding.UTF_8});
 
   /**
    * Synchronously read the entire file contents as lines of text
    * using the given [Encoding].
    */
-  List<String> readAsLinesSync([Encoding encoding = Encoding.UTF_8]);
+  List<String> readAsLinesSync({Encoding encoding: Encoding.UTF_8});
 
   /**
    * Write a list of bytes to a file.
@@ -241,7 +241,7 @@
    * file if it already exists. In order to append the bytes to an existing
    * file, pass [FileMode.APPEND] as the optional mode parameter.
    */
-  Future<File> writeAsBytes(List<int> bytes, [FileMode mode = FileMode.WRITE]);
+  Future<File> writeAsBytes(List<int> bytes, {FileMode mode: FileMode.WRITE});
 
   /**
    * Synchronously write a list of bytes to a file.
@@ -252,7 +252,7 @@
    * the file if it already exists. In order to append the bytes to an existing
    * file, pass [FileMode.APPEND] as the optional mode parameter.
    */
-  void writeAsBytesSync(List<int> bytes, [FileMode mode = FileMode.WRITE]);
+  void writeAsBytesSync(List<int> bytes, {FileMode mode: FileMode.WRITE});
 
   /**
    * Write a string to a file.
@@ -381,7 +381,7 @@
    * RandomAccessFile when the write completes.
    */
   Future<RandomAccessFile> writeString(String string,
-                                       [Encoding encoding = Encoding.UTF_8]);
+                                       {Encoding encoding: Encoding.UTF_8});
 
   /**
    * Synchronously writes a single string to the file using the given
@@ -389,7 +389,7 @@
    * written.
    */
   int writeStringSync(String string,
-                      [Encoding encoding = Encoding.UTF_8]);
+                      {Encoding encoding: Encoding.UTF_8});
 
   /**
    * Gets the current byte position in the file. Returns a
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 1d9aa40..f6fdb84 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -104,7 +104,7 @@
   void _start() {
     Future<RandomAccessFile> openFuture;
     if (_path != null) {
-      openFuture = new File(_path).open(FileMode.READ);
+      openFuture = new File(_path).open(mode: FileMode.READ);
     } else {
       openFuture = new Future.immediate(_File._openStdioSync(0));
     }
@@ -153,7 +153,7 @@
   StreamSubscription _subscription;
 
   _FileStreamConsumer(File this._file, FileMode mode) {
-    _openFuture = _file.open(mode);
+    _openFuture = _file.open(mode: mode);
   }
 
   _FileStreamConsumer.fromStdio(int fd) {
@@ -301,6 +301,8 @@
 
   external static _createLink(String path, String target);
 
+  external static _linkTarget(String path);
+
   void createSync() {
     var result = _create(_path);
     throwIfError(result, "Cannot create file '$_path'");
@@ -349,7 +351,7 @@
     return new Directory(result);
   }
 
-  Future<RandomAccessFile> open([FileMode mode = FileMode.READ]) {
+  Future<RandomAccessFile> open({FileMode mode: FileMode.READ}) {
     _ensureFileService();
     Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
     if (mode != FileMode.READ &&
@@ -421,7 +423,7 @@
 
   external static _open(String path, int mode);
 
-  RandomAccessFile openSync([FileMode mode = FileMode.READ]) {
+  RandomAccessFile openSync({FileMode mode: FileMode.READ}) {
     if (mode != FileMode.READ &&
         mode != FileMode.WRITE &&
         mode != FileMode.APPEND) {
@@ -511,14 +513,14 @@
     return result;
   }
 
-  Future<String> readAsString([Encoding encoding = Encoding.UTF_8]) {
+  Future<String> readAsString({Encoding encoding: Encoding.UTF_8}) {
     _ensureFileService();
     return readAsBytes().then((bytes) {
       return _decodeString(bytes, encoding);
     });
   }
 
-  String readAsStringSync([Encoding encoding = Encoding.UTF_8]) {
+  String readAsStringSync({Encoding encoding: Encoding.UTF_8}) {
     List<int> bytes = readAsBytesSync();
     return _decodeString(bytes, encoding);
   }
@@ -536,7 +538,7 @@
     return list;
   }
 
-  Future<List<String>> readAsLines([Encoding encoding = Encoding.UTF_8]) {
+  Future<List<String>> readAsLines({Encoding encoding: Encoding.UTF_8}) {
     _ensureFileService();
     Completer<List<String>> completer = new Completer<List<String>>();
     return readAsBytes().then((bytes) {
@@ -544,12 +546,12 @@
     });
   }
 
-  List<String> readAsLinesSync([Encoding encoding = Encoding.UTF_8]) {
+  List<String> readAsLinesSync({Encoding encoding: Encoding.UTF_8}) {
     return _decodeLines(readAsBytesSync(), encoding);
   }
 
   Future<File> writeAsBytes(List<int> bytes,
-                            [FileMode mode = FileMode.WRITE]) {
+                            {FileMode mode: FileMode.WRITE}) {
     try {
       IOSink<File> sink = openWrite(mode: mode);
       sink.writeBytes(bytes);
@@ -560,8 +562,8 @@
     }
   }
 
-  void writeAsBytesSync(List<int> bytes, [FileMode mode = FileMode.WRITE]) {
-    RandomAccessFile opened = openSync(mode);
+  void writeAsBytesSync(List<int> bytes, {FileMode mode: FileMode.WRITE}) {
+    RandomAccessFile opened = openSync(mode: mode);
     opened.writeListSync(bytes, 0, bytes.length);
     opened.closeSync();
   }
@@ -570,7 +572,7 @@
                              {FileMode mode: FileMode.WRITE,
                               Encoding encoding: Encoding.UTF_8}) {
     try {
-      return writeAsBytes(_encodeString(contents, encoding), mode);
+      return writeAsBytes(_encodeString(contents, encoding), mode: mode);
     } catch (e) {
       var completer = new Completer();
       Timer.run(() => completer.completeError(e));
@@ -581,7 +583,7 @@
   void writeAsStringSync(String contents,
                          {FileMode mode: FileMode.WRITE,
                           Encoding encoding: Encoding.UTF_8}) {
-    writeAsBytesSync(_encodeString(contents, encoding), mode);
+    writeAsBytesSync(_encodeString(contents, encoding), mode: mode);
   }
 
   String get path => _path;
@@ -865,7 +867,7 @@
   }
 
   Future<RandomAccessFile> writeString(String string,
-                                       [Encoding encoding = Encoding.UTF_8]) {
+                                       {Encoding encoding: Encoding.UTF_8}) {
     if (encoding is! Encoding) {
       var completer = new Completer();
       Timer.run(() {
@@ -878,7 +880,7 @@
     return writeList(data, 0, data.length);
   }
 
-  int writeStringSync(String string, [Encoding encoding = Encoding.UTF_8]) {
+  int writeStringSync(String string, {Encoding encoding: Encoding.UTF_8}) {
     if (encoding is! Encoding) {
       throw new FileIOException(
           "Invalid encoding in writeStringSync: $encoding");
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index e13477b..ac00741 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -35,6 +35,7 @@
   String get path;
 
   external static int _getType(String path, bool followLinks);
+  external static bool _identical(String path1, String path2);
 
   static int _getTypeSync(String path, bool followLinks) {
     var result = _getType(path, followLinks);
@@ -42,6 +43,22 @@
     return result;
   }
 
+  /**
+   * Do two paths refer to the same object in the file system?
+   * Links are not identical to their targets, and two links
+   * are not identical just because they point to identical targets.
+   * Links in intermediate directories in the paths are followed, though.
+   *
+   * Throws an error if one of the paths points to an object that does not
+   * exist.
+   * The target of a link can be compared by first getting it with Link.target.
+   */
+  static bool identicalSync(String path1, String path2) {
+    var result = _identical(path1, path2);
+    _throwIfError(result, 'Error in FileSystemEntity.identical');
+    return result;
+  }
+
   static FileSystemEntityType typeSync(String path, {bool followLinks: true})
       => FileSystemEntityType._lookup(_getTypeSync(path, followLinks));
 
@@ -57,6 +74,8 @@
   static _throwIfError(Object result, String msg) {
     if (result is OSError) {
       throw new FileIOException(msg, result);
+    } else if (result is ArgumentError) {
+      throw result;
     }
   }
 }
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 912a366..9a54af2 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -866,10 +866,64 @@
    * separated by semicolons, e.g.
    *
    *   "PROXY host:port; PROXY host2:port2; DIRECT"
+   *
+   * The static function [findProxyFromEnvironment] on this class can
+   * be used to implement proxy server resolving based on environment
+   * variables.
    */
   set findProxy(String f(Uri url));
 
   /**
+   * Function for resolving the proxy server to be used for a HTTP
+   * connection from the proxy configuration specified through
+   * environment variables.
+   *
+   * The following environment variables are taken into account:
+   *
+   *  * http_proxy
+   *  * https_proxy
+   *  * no_proxy
+   *  * HTTP_PROXY
+   *  * HTTPS_PROXY
+   *  * NO_PROXY
+   *
+   * [:http_proxy:] and [:HTTP_PROXY:] specify the proxy server to use for
+   * http:// urls. Use the format [:hostname:port:]. If no port is used a
+   * default of 1080 will be used. If both are set the lower case one takes
+   * precedence.
+   *
+   * [:https_proxy:] and [:HTTPS_PROXY:] specify the proxy server to use for
+   * https:// urls. Use the format [:hostname:port:]. If no port is used a
+   * default of 1080 will be used. If both are set the lower case one takes
+   * precedence.
+   *
+   * [:no_proxy:] and [:NO_PROXY:] specify a comma separated list of
+   * postfixes of hostnames for which not to use the proxy
+   * server. E.g. the value "localhost,127.0.0.1" will make requests
+   * to both "localhost" and "127.0.0.1" not use a proxy. If both are set
+   * the lower case one takes precedence.
+   *
+   * To activate this way of resolving proxies assign this function to
+   * the [findProxy] property on the [HttpClient].
+   *
+   *   HttpClient client = new HttpClient();
+   *   client.findProxy = HttpClient.findProxyFromEnvironment;
+   *
+   * If you don't want to use the system environment you can use a
+   * different one by wrapping the function.
+   *
+   *   HttpClient client = new HttpClient();
+   *   client.findProxy = (url) {
+   *     return HttpClient.findProxyFromEnvironment(
+   *         url, {"http_proxy": ..., "no_proxy": ...});
+   *   }
+   */
+  static String findProxyFromEnvironment(Uri url,
+                                         {Map<String, String> environment}) {
+    return _HttpClient._findProxyFromEnvironment(url, environment);
+  }
+
+  /**
    * Shutdown the HTTP client. If [force] is [:false:] (the default)
    * the [:HttpClient:] will be kept alive until all active
    * connections are done. If [force] is [:true:] any active
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 1f79457..c1272d3 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -1258,6 +1258,56 @@
       _credentials.removeAt(index);
     }
   }
+
+  static String _findProxyFromEnvironment(Uri url,
+                                          Map<String, String> environment) {
+    checkNoProxy(String option) {
+      if (option == null) return null;
+      Iterator<String> names = option.split(",").map((s) => s.trim()).iterator;
+      while (names.moveNext()) {
+        if (url.domain.endsWith(names.current)) {
+          return "DIRECT";
+        }
+      }
+      return null;
+    }
+
+    checkProxy(String option) {
+      if (option == null) return null;
+      int pos = option.indexOf("://");
+      if (pos >= 0) {
+        option = option.substring(pos + 3);
+      }
+      if (option.indexOf(":") == -1) option = "$option:1080";
+      return "PROXY $option";
+    }
+
+    // Default to using the process current environment.
+    if (environment == null) environment = Platform.environment;
+
+    String proxyCfg;
+
+    String noProxy = environment["no_proxy"];
+    if (noProxy == null) noProxy = environment["NO_PROXY"];
+    if ((proxyCfg = checkNoProxy(noProxy)) != null) {
+      return proxyCfg;
+    }
+
+    if (url.scheme == "http") {
+      String proxy = environment["http_proxy"];
+      if (proxy == null) proxy = environment["HTTP_PROXY"];
+      if ((proxyCfg = checkProxy(proxy)) != null) {
+        return proxyCfg;
+      }
+    } else if (url.scheme == "https") {
+      String proxy = environment["https_proxy"];
+      if (proxy == null) proxy = environment["HTTPS_PROXY"];
+      if ((proxyCfg = checkProxy(proxy)) != null) {
+        return proxyCfg;
+      }
+    }
+    return "DIRECT";
+  }
 }
 
 
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index c008f34..047f37a 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -420,9 +420,6 @@
 
           case _State.RESPONSE_LINE_REASON_PHRASE:
             if (byte == _CharCode.CR) {
-              if (_uri_or_reason_phrase.length == 0) {
-                throw new HttpParserException("Invalid response reason phrase");
-              }
               _state = _State.RESPONSE_LINE_ENDING;
             } else {
               if (byte == _CharCode.CR || byte == _CharCode.LF) {
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 00aeb2d..fee4f97 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -10,30 +10,30 @@
  */
 abstract class Link extends FileSystemEntity {
   /**
-   * Create a Link object.
+   * Creates a Link object.
    */
   factory Link(String path) => new _Link(path);
 
   /**
-   * Create a Link object from a Path object.
+   * Creates a Link object from a Path object.
    */
   factory Link.fromPath(Path path) => new _Link.fromPath(path);
 
   /**
-   * Check if the link exists. The link may exist, even if its target
+   * Checks if the link exists. The link may exist, even if its target
    * is missing or deleted.
    * Returns a [:Future<bool>:] that completes when the answer is known.
    */
   Future<bool> exists();
 
   /**
-   * Synchronously check if the link exists. The link may exist, even if
+   * Synchronously checks if the link exists. The link may exist, even if
    * its target is missing or deleted.
    */
   bool existsSync();
 
   /**
-   * Create a symbolic link. Returns a [:Future<Link>:] that completes with
+   * Creates a symbolic link. Returns a [:Future<Link>:] that completes with
    * the link when it has been created. If the link exists, the function
    * the future will complete with an error.
    *
@@ -56,7 +56,7 @@
   void createSync(String target);
 
   /**
-   * Synchronously update the link. Calling [updateSync] on a non-existing link
+   * Synchronously updates the link. Calling [updateSync] on a non-existing link
    * will throw an exception.
    *
    * If [linkRelative] is true, the target argument should be a relative path,
@@ -69,17 +69,39 @@
   void updateSync(String target, {bool linkRelative: false });
 
   /**
-   * Delete the link. Returns a [:Future<Link>:] that completes with
+   * Deletes the link. Returns a [:Future<Link>:] that completes with
    * the link when it has been deleted.  This does not delete, or otherwise
    * affect, the target of the link.
    */
   Future<Link> delete();
 
   /**
-   * Synchronously delete the link. This does not delete, or otherwise
+   * Synchronously deletes the link. This does not delete, or otherwise
    * affect, the target of the link.
    */
   void deleteSync();
+
+  /**
+   * Gets the target of the link. Returns a future that completes with
+   * the path to the target.
+   *
+   * If the returned target is a relative path, it is relative to the
+   * directory containing the link.
+   *
+   * If the link does not exist, or is not a link, the future completes with
+   * a LinkIOException.
+   */
+  Future<String> target();
+
+  /**
+   * Synchronously gets the target of the link. Returns the path to the target.
+   *
+   * If the returned target is a relative path, it is relative to the
+   * directory containing the link.
+   *
+   * If the link does not exist, or is not a link, throws a LinkIOException.
+   */
+  String targetSync();
 }
 
 
@@ -90,6 +112,8 @@
 
   _Link.fromPath(Path inputPath) : path = inputPath.toNativePath();
 
+  String toString() => "Link: '$path'";
+
   Future<bool> exists() {
     // TODO(whesse): Replace with asynchronous version.
     return new Future.immediate(existsSync());
@@ -110,7 +134,7 @@
       target = _makeWindowsLinkTarget(target);
     }
     var result = _File._createLink(path, target);
-    if (result is Error) {
+    if (result is OSError) {
       throw new LinkIOException("Error in Link.createSync", result);
     }
   }
@@ -146,6 +170,19 @@
   void deleteSync() {
     new File(path).deleteSync();
   }
+
+  Future<String> target() {
+    // TODO(whesse): Replace with asynchronous version.
+    return new Future.of(targetSync);
+  }
+
+  String targetSync() {
+    var result = _File._linkTarget(path);
+    if (result is OSError) {
+      throw new LinkIOException("Error in Link.targetSync", result);
+    }
+    return result;
+  }
 }
 
 
diff --git a/sdk/lib/isolate/base.dart b/sdk/lib/isolate/base.dart
index 73b550c..519cf49 100644
--- a/sdk/lib/isolate/base.dart
+++ b/sdk/lib/isolate/base.dart
@@ -31,11 +31,16 @@
  * [spawnFunction] returns a [SendPort] derived from the child isolate's default
  * port.
  *
+ * The optional [unhandledExceptionCallback] argument is invoked whenever an
+ * exception inside the isolate is unhandled. It can be seen as a big
+ * `try/catch` around everything that is executed inside the isolate. The
+ * callback should return `true` when it was able to handled the exception.
+ *
  * See comments at the top of this library for more details.
  */
 SendPort spawnFunction(void topLevelFunction(),
-    [bool UnhandledExceptionCallback(IsolateUnhandledException e)])
-    => _Isolate.spawnFunction(topLevelFunction, UnhandledExceptionCallback);
+    [bool unhandledExceptionCallback(IsolateUnhandledException e)])
+    => _Isolate.spawnFunction(topLevelFunction, unhandledExceptionCallback);
 
 /**
  * Creates and spawns an isolate whose code is available at [uri].  Like with
@@ -171,7 +176,7 @@
 abstract class _Isolate {
   external static ReceivePort get port;
   external static SendPort spawnFunction(void topLevelFunction(),
-    [bool UnhandledExceptionCallback(IsolateUnhandledException e)]);
+    [bool unhandledExceptionCallback(IsolateUnhandledException e)]);
   external static SendPort spawnUri(String uri);
 }
 
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 947cc14..0b57f15 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -8,4 +8,3 @@
 
 part "base.dart";
 part "isolate_stream.dart";
-part "mangler.dart";
diff --git a/sdk/lib/isolate/isolate_sources.gypi b/sdk/lib/isolate/isolate_sources.gypi
index 8077ccf..2fa168c 100644
--- a/sdk/lib/isolate/isolate_sources.gypi
+++ b/sdk/lib/isolate/isolate_sources.gypi
@@ -8,6 +8,5 @@
     # The above file needs to be first as it lists the parts below.
     'base.dart',
     'isolate_stream.dart',
-    'mangler.dart',
   ],
 }
diff --git a/sdk/lib/isolate/isolate_stream.dart b/sdk/lib/isolate/isolate_stream.dart
index 4cb39f1..9a735c9 100644
--- a/sdk/lib/isolate/isolate_stream.dart
+++ b/sdk/lib/isolate/isolate_stream.dart
@@ -23,25 +23,11 @@
   final IsolateStream stream;
   final IsolateSink sink;
 
-  MessageBox.oneShot() : this._oneShot(new ReceivePort());
-  MessageBox._oneShot(ReceivePort receivePort)
-      : stream = new IsolateStream._fromOriginalReceivePortOneShot(receivePort),
-        sink = new IsolateSink._fromPort(receivePort.toSendPort());
-
-  MessageBox() : this._(new ReceivePort());
-  MessageBox._(ReceivePort receivePort)
-      : stream = new IsolateStream._fromOriginalReceivePort(receivePort),
-        sink = new IsolateSink._fromPort(receivePort.toSendPort());
+  external MessageBox.oneShot();
+  external MessageBox();
 }
 
-// Used for mangling.
-const int _ISOLATE_STREAM_TOKEN = 132421119;
-
-class _CloseToken {
-  /// This token is sent from [IsolateSink]s to [IsolateStream]s to ask them to
-  /// close themselves.
-  const _CloseToken();
-}
+external bool _isCloseToken(var object);
 
 /**
  * [IsolateStream]s, together with [IsolateSink]s, are the only means of
@@ -70,8 +56,7 @@
   }
 
   void _add(var message) {
-    message = _unmangleMessage(message);
-    if (identical(message, const _CloseToken())) {
+    if (_isCloseToken(message)) {
       close();
     } else {
       _controller.sink.add(message);
@@ -100,22 +85,6 @@
                                        onDone: onDone,
                                        unsubscribeOnError: unsubscribeOnError);
   }
-
-  dynamic _unmangleMessage(var message) {
-    _IsolateDecoder decoder = new _IsolateDecoder(
-        _ISOLATE_STREAM_TOKEN,
-        (data) {
-          if (data is! List) return data;
-          if (data.length == 2 && data[0] == "Sink" && data[1] is SendPort) {
-            return new IsolateSink._fromPort(data[1]);
-          }
-          if (data.length == 1 && data[0] == "Close") {
-            return const _CloseToken();
-          }
-          return data;
-        });
-    return decoder.decode(message);
-  }
 }
 
 /**
@@ -125,11 +94,10 @@
  *
  * [IsolateSink]s can be transmitted to other isolates.
  */
-class IsolateSink extends StreamSink<dynamic> {
+abstract class IsolateSink extends StreamSink<dynamic> {
   // TODO(8997): Implement EventSink instead.
-  bool _isClosed = false;
-  final SendPort _port;
-  IsolateSink._fromPort(this._port);
+  // TODO(floitsch): Actually it should be a StreamSink (being able to flow-
+  // control).
 
   /**
    * Sends an asynchronous [message] to the linked [IsolateStream]. The message
@@ -145,41 +113,18 @@
    * process). This is currently only supported by the dartvm.  For now, the
    * dart2js compiler only supports the restricted messages described above.
    */
-  void add(dynamic message) {
-    var mangled = _mangleMessage(message);
-    _port.send(mangled);
-  }
+  void add(dynamic message);
 
-  void addError(AsyncError errorEvent) {
-    throw new UnimplementedError("signalError on isolate streams");
-  }
+  void addError(AsyncError errorEvent);
 
-  dynamic _mangleMessage(var message) {
-    _IsolateEncoder encoder = new _IsolateEncoder(
-        _ISOLATE_STREAM_TOKEN,
-        (data) {
-          if (data is IsolateSink) return ["Sink", data._port];
-          if (identical(data, const _CloseToken())) return ["Close"];
-          return data;
-        });
-    return encoder.encode(message);
-  }
-
-  void close() {
-    if (_isClosed) throw new StateError("Sending on closed stream");
-    add(const _CloseToken());
-    _isClosed = true;
-  }
+  /** Closing multiple times is allowed. */
+  void close();
 
   /**
    * Tests whether [other] is an [IsolateSink] feeding into the same
    * [IsolateStream] as this one.
    */
-  bool operator==(var other) {
-    return other is IsolateSink && _port == other._port;
-  }
-
-  int get hashCode => _port.hashCode + 499;
+  bool operator==(var other);
 }
 
 
@@ -196,21 +141,13 @@
  * [spawnFunction] returns an [IsolateSink] feeding into the child isolate's
  * default stream.
  *
- * See comments at the top of this library for more details.
- */
-IsolateSink streamSpawnFunction(void topLevelFunction()) {
-  SendPort sendPort = spawnFunction(topLevelFunction);
-  return new IsolateSink._fromPort(sendPort);
-}
-
-/**
- * Creates and spawns an isolate whose code is available at [uri].  Like with
- * [streamSpawnFunction], the child isolate will have a default [IsolateStream],
- * and a this function returns an [IsolateSink] feeding into it.
+ * The optional [unhandledExceptionCallback] argument is invoked whenever an
+ * exception inside the isolate is unhandled. It can be seen as a big
+ * `try/catch` around everything that is executed inside the isolate. The
+ * callback should return `true` when it was able to handled the exception.
  *
  * See comments at the top of this library for more details.
  */
-IsolateSink streamSpawnUri(String uri) {
-  SendPort sendPort = spawnUri(uri);
-  return new IsolateSink._fromPort(sendPort);
-}
+external IsolateSink streamSpawnFunction(
+    void topLevelFunction(),
+    [bool unhandledExceptionCallback(IsolateUnhandledException e)]);
diff --git a/sdk/lib/isolate/mangler.dart b/sdk/lib/isolate/mangler.dart
deleted file mode 100644
index 8b31d5a6..0000000
--- a/sdk/lib/isolate/mangler.dart
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.isolate;
-
-class _IsolateEncoder {
-  final manglingToken;
-  // TODO(floitsch): switch to identity set.
-  final Map _encoded = new Map();
-  final Map _visiting = new Map();
-  final Function _mangle;
-  static const int _REFERENCE = 0;
-  static const int _DECLARATION = 1;
-  static const int _ESCAPED = 2;
-  static const int _MANGLED = 3;
-
-  _IsolateEncoder(this.manglingToken, mangle(data))
-      : this._mangle = mangle;
-
-  encode(var data) {
-    if (data is num || data is String || data is bool || data == null) {
-      return data;
-    }
-
-    if (_encoded.containsKey(data)) return _encoded[data];
-    if (_visiting.containsKey(data)) {
-      // Self reference.
-      var selfReference = _visiting[data];
-      if (selfReference == data) {
-        // Nobody used the self-reference yet.
-        selfReference = _createReference();
-        _visiting[data] = selfReference;
-      }
-      return selfReference;
-    }
-    _visiting[data] = data;
-
-    var result;
-
-    if (data is List) {
-      bool hasBeenDuplicated = false;
-      result = data;
-      for (int i = 0; i < data.length; i++) {
-        var mangled = encode(data[i]);
-        if (mangled != data[i] && !hasBeenDuplicated) {
-          result = new List(data.length);
-          for (int j = 0; j < i; j++) {
-            result[j] = data[j];
-          }
-          hasBeenDuplicated = true;
-        }
-        if (hasBeenDuplicated) {
-          result[i] = mangled;
-        }
-      }
-      result = _escapeIfNecessary(result);
-    } else if (data is Set) {
-      // TODO(floitsch): should we accept sets?
-      bool needsCopy = false;
-      for (var entry in data) {
-        var encoded = encode(entry);
-        if (encoded != entry) {
-          needsCopy = true;
-          break;
-        }
-      }
-      result = data;
-      if (needsCopy) {
-        result = new Set();
-        data.forEach((entry) {
-          result.add(encode(entry));
-        });
-      }
-    } else if (data is Map) {
-      bool needsCopy = false;
-      data.forEach((key, value) {
-        var encodedKey = encode(key);
-        var encodedValue = encode(value);
-        if (encodedKey != key) needsCopy = true;
-        if (encodedValue != value) needsCopy = true;
-      });
-      result = data;
-      if (needsCopy) {
-        result = new Map();
-        data.forEach((key, value) {
-          result[encode(key)] = encode(value);
-        });
-      }
-    } else {
-      // We don't handle self-references for user data.
-      // TODO(floitsch): we could keep the reference and throw when we see it
-      // again. However now the user has at least the possibility to do
-      // cyclic data-structures.
-      _visiting.remove(data);
-      result = _mangle(data);
-      if (result != data) {
-        result = _wrapMangled(encode(result));
-      }
-    }
-
-    var selfReference = _visiting[data];
-    if (selfReference != null && selfReference != data) {
-      // A self-reference has been used.
-      result = _declareReference(selfReference, result);
-    }
-    _encoded[data] = result;
-
-    _visiting.remove(data);
-    return result;
-  }
-
-  _createReference() => [manglingToken, _REFERENCE];
-  _declareReference(reference, data) {
-    return [manglingToken, _DECLARATION, reference, data];
-  }
-
-  _wrapMangled(data) => [manglingToken, _MANGLED, data];
-  _escapeIfNecessary(List list) {
-    if (!list.isEmpty && list[0] == manglingToken) {
-      return [manglingToken, _ESCAPED, list];
-    } else {
-      return list;
-    }
-  }
-}
-
-class _IsolateDecoder {
-  final manglingToken;
-  final Map _decoded = new Map();
-  final Function _unmangle;
-  static const int _REFERENCE = _IsolateEncoder._REFERENCE;
-  static const int _DECLARATION = _IsolateEncoder._DECLARATION;
-  static const int _ESCAPED = _IsolateEncoder._ESCAPED;
-  static const int _MANGLED = _IsolateEncoder._MANGLED;
-
-  _IsolateDecoder(this.manglingToken, unmangle(data))
-      : this._unmangle = unmangle;
-
-  decode(var data) {
-    if (data is num || data is String || data is bool || data == null) {
-      return data;
-    }
-
-    if (_decoded.containsKey(data)) return _decoded[data];
-
-    if (_isDeclaration(data)) {
-      var reference = _extractReference(data);
-      var declared = _extractDeclared(data);
-      return _decodeObject(declared, reference);
-    } else {
-      return _decodeObject(data, null);
-    }
-  }
-
-  _decodeObject(data, reference) {
-    if (_decoded.containsKey(data)) {
-      assert(reference == null);
-      return _decoded[data];
-    }
-
-    // If the data was a reference then we would have found it in the _decoded
-    // map.
-    assert(!_isReference(data));
-
-    var result;
-    if (_isMangled(data)) {
-      assert(reference == null);
-      List mangled = _extractMangled(data);
-      var decoded = decode(mangled);
-      result = _unmangle(decoded);
-    } else if (data is List) {
-      if (_isEscaped(data)) data = _extractEscaped(data);
-      assert(!_isMarked(data));
-      result = data;
-      bool hasBeenDuplicated = false;
-      List duplicate() {
-        assert(!hasBeenDuplicated);
-        result = new List();
-        result.length = data.length;
-        if (reference != null) _decoded[reference] = result;
-        hasBeenDuplicated = true;
-      }
-
-      if (reference != null) duplicate();
-      for (int i = 0; i < data.length; i++) {
-        var decoded = decode(data[i]);
-        if (decoded != data[i] && !hasBeenDuplicated) {
-          duplicate();
-          for (int j = 0; j < i; j++) {
-            result[j] = data[j];
-          }
-        }
-        if (hasBeenDuplicated) {
-          result[i] = decoded;
-        }
-      }
-    } else if (data is Set) {
-      bool needsCopy = reference != null;
-      if (!needsCopy) {
-        for (var entry in data) {
-          var decoded = decode(entry);
-          if (decoded != entry) {
-            needsCopy = true;
-            break;
-          }
-        }
-      }
-      result = data;
-      if (needsCopy) {
-        result = new Set();
-        if (reference != null) _decoded[reference] = result;
-        for (var entry in data) {
-          result.add(decode(entry));
-        }
-      }
-    } else if (data is Map) {
-      bool needsCopy = reference != null;
-      if (!needsCopy) {
-        data.forEach((key, value) {
-          var decodedKey = decode(key);
-          var decodedValue = decode(value);
-          if (decodedKey != key) needsCopy = true;
-          if (decodedValue != value) needsCopy = true;
-        });
-      }
-      result = data;
-      if (needsCopy) {
-        result = new Map();
-        if (reference != null) _decoded[reference] = result;
-        data.forEach((key, value) {
-          result[decode(key)] = decode(value);
-        });
-      }
-    } else {
-      result = data;
-    }
-    _decoded[data] = result;
-    return result;
-  }
-
-  _isMarked(data) {
-    if (data is List && !data.isEmpty && data[0] == manglingToken) {
-      assert(data.length > 1);
-      return true;
-    }
-    return false;
-  }
-  _isReference(data) => _isMarked(data) && data[1] == _REFERENCE;
-  _isDeclaration(data) => _isMarked(data) && data[1] == _DECLARATION;
-  _isMangled(data) => _isMarked(data) && data[1] == _MANGLED;
-  _isEscaped(data) => _isMarked(data) && data[1] == _ESCAPED;
-
-  _extractReference(declaration) {
-    assert(_isDeclaration(declaration));
-    return declaration[2];
-  }
-  _extractDeclared(declaration) {
-    assert(_isDeclaration(declaration));
-    return declaration[3];
-  }
-  _extractMangled(wrappedMangled) {
-    assert(_isMangled(wrappedMangled));
-    return wrappedMangled[2];
-  }
-  _extractEscaped(data) {
-    assert(_isEscaped(data));
-    return data[2];
-  }
-}
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index 13d8b36..6fd8b6e 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -4,7 +4,7 @@
 import 'dart:collection';
 import 'dart:html';
 import 'dart:html_common';
-import 'dart:_js_helper' show Creates, Returns;
+import 'dart:_js_helper' show Creates, Returns, convertDartClosureToJS;
 import 'dart:_foreign_helper' show JS;
 // DO NOT EDIT - unless you are editing documentation as per:
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
@@ -184,6 +184,9 @@
   @DocsEditable
   static const EventStreamProvider<Event> completeEvent = const EventStreamProvider<Event>('complete');
 
+  /// Checks if this type is supported on the current platform.
+  static bool get supported => JS('bool', '!!(window.AudioContext || window.webkitAudioContext)');
+
   @DomName('AudioContext.activeSourceCount')
   @DocsEditable
   final int activeSourceCount;
@@ -316,9 +319,9 @@
 @DomName('AudioDestinationNode')
 class AudioDestinationNode extends AudioNode native "*AudioDestinationNode" {
 
-  @DomName('AudioDestinationNode.numberOfChannels')
+  @DomName('AudioDestinationNode.maxChannelCount')
   @DocsEditable
-  final int numberOfChannels;
+  final int maxChannelCount;
 }
 // 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
@@ -813,18 +816,50 @@
   @DocsEditable
   void setVelocity(num x, num y, num z) native;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
 
-@DocsEditable
 @DomName('ScriptProcessorNode')
-class ScriptProcessorNode extends AudioNode implements EventTarget native "*ScriptProcessorNode" {
+class ScriptProcessorNode extends AudioNode native "*ScriptProcessorNode" {
+  Stream<AudioProcessingEvent> _eventStream;
+
+  /**
+   * Get a Stream that fires events when AudioProcessingEvents occur.
+   * This particular stream is special in that it only allows one listener to a
+   * given stream. Converting the returned Stream [asBroadcast] will likely ruin
+   * the soft-real-time properties which which these events are fired and can
+   * be processed.
+   */
+  Stream<AudioProcessingEvent> get onAudioProcess {
+    if (_eventStream == null) {
+      var controller = new StreamController();
+      var callback = (audioData) { 
+          if (controller.hasSubscribers) {
+            // This stream is a strange combination of broadcast and single
+            // subscriber streams. We only allow one listener, but if there is
+            // no listener, we don't queue up events, we just drop them on the
+            // floor.
+            controller.add(audioData);
+          }
+        };
+      _setEventListener(callback);
+      _eventStream = controller.stream;
+    }
+    return _eventStream;
+  }
+
+    _setEventListener(callback) {
+      JS('void', '#.onaudioprocess = #', this,
+          convertDartClosureToJS(callback, 1));
+    }
+
 
   @DomName('ScriptProcessorNode.bufferSize')
   @DocsEditable
   final int bufferSize;
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index 59a43ad..713c60e 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -236,6 +236,9 @@
   @DocsEditable
   static AudioContext _create() native "AudioContext_constructorCallback";
 
+  /// Checks if this type is supported on the current platform.
+  static bool get supported => true;
+
   @DomName('AudioContext.activeSourceCount')
   @DocsEditable
   int get activeSourceCount native "AudioContext_activeSourceCount_Getter";
@@ -418,9 +421,9 @@
 class AudioDestinationNode extends AudioNode {
   AudioDestinationNode.internal() : super.internal();
 
-  @DomName('AudioDestinationNode.numberOfChannels')
+  @DomName('AudioDestinationNode.maxChannelCount')
   @DocsEditable
-  int get numberOfChannels native "AudioDestinationNode_numberOfChannels_Getter";
+  int get maxChannelCount native "AudioDestinationNode_maxChannelCount_Getter";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -1086,22 +1089,51 @@
   void setVelocity(num x, num y, num z) native "PannerNode_setVelocity_Callback";
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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: Do not edit - generated code.
 
-
-@DocsEditable
 @DomName('ScriptProcessorNode')
-class ScriptProcessorNode extends AudioNode implements EventTarget {
+class ScriptProcessorNode extends AudioNode {
+  Stream<AudioProcessingEvent> _eventStream;
+
+  /**
+   * Get a Stream that fires events when AudioProcessingEvents occur.
+   * This particular stream is special in that it only allows one listener to a
+   * given stream. Converting the returned Stream [asBroadcast] will likely ruin
+   * the soft-real-time properties which which these events are fired and can
+   * be processed.
+   */
+  Stream<AudioProcessingEvent> get onAudioProcess {
+    if (_eventStream == null) {
+      var controller = new StreamController();
+      var callback = (audioData) { 
+          if (controller.hasSubscribers) {
+            // This stream is a strange combination of broadcast and single
+            // subscriber streams. We only allow one listener, but if there is
+            // no listener, we don't queue up events, we just drop them on the
+            // floor.
+            controller.add(audioData);
+          }
+        };
+      _setEventListener(callback);
+      _eventStream = controller.stream;
+    }
+    return _eventStream;
+  }
+
+
   ScriptProcessorNode.internal() : super.internal();
 
   @DomName('ScriptProcessorNode.bufferSize')
   @DocsEditable
   int get bufferSize native "ScriptProcessorNode_bufferSize_Getter";
 
+  @DomName('ScriptProcessorNode._setEventListener')
+  @DocsEditable
+  void _setEventListener(EventListener eventListener) native "ScriptProcessorNode__setEventListener_Callback";
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 5210805..5e60059 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -257,6 +257,9 @@
 Language/13_Libraries_and_Scripts/3_Parts_A03_t01: Fail # http://dartbug.com/5022
 Language/14_Types/3_Type_Declarations/1_Typedef_A01_t01: Fail # http://dartbug.com/5022
 
+LibTest/core/List/operator_subscript_A03_t01: Fail # http://dartbug.com/9228
+LibTest/core/List/operator_subscripted_assignment_A03_t01: Fail # http://dartbug.com/9228
+
 [ $compiler == dart2js ]
 LibTest/core/int/operator_GT_A01_t01: Fail, OK # co19 issue 200
 LibTest/core/int/operator_LT_A01_t01: Fail, OK # co19 issue 200
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
new file mode 100644
index 0000000..1d1bad9
--- /dev/null
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -0,0 +1,263 @@
+// 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 '../../../sdk/lib/_internal/compiler/implementation/types/types.dart'
+    show TypeMask;
+
+import 'compiler_helper.dart';
+import 'parser_helper.dart';
+
+void compileAndFind(String code,
+                    String className,
+                    String memberName,
+                    bool disableInlining,
+                    check(compiler, element)) {
+  Uri uri = new Uri.fromComponents(scheme: 'source');
+  var compiler = compilerFor(code, uri);
+  compiler.disableInlining = disableInlining;
+  compiler.runCompiler(uri);
+  var cls = findElement(compiler, className);
+  var member = cls.lookupLocalMember(buildSourceString(memberName));
+  return check(compiler.typesTask.typesInferrer, member);
+}
+
+const String TEST_1 = r"""
+  class A {
+    x(p) => p;
+  }
+  main() { new A().x("s"); }
+""";
+
+const String TEST_2 = r"""
+  class A {
+    x(p) => p;
+  }
+  main() { new A().x(1); }
+""";
+
+const String TEST_3 = r"""
+  class A {
+    x(p) => x(p - 1);
+  }
+  main() { new A().x(1); }
+""";
+
+const String TEST_4 = r"""
+  class A {
+    x(p) => x(p - 1);
+  }
+  main() { new A().x(1.5); }
+""";
+
+const String TEST_5 = r"""
+  class A {
+    x(p) => p;
+  }
+  main() {
+    new A().x(1);
+    new A().x(1.5);
+  }
+""";
+
+const String TEST_6 = r"""
+  class A {
+    x(p) => p;
+  }
+  main() {
+    new A().x(1.5);
+    new A().x(1);
+  }
+""";
+
+const String TEST_7 = r"""
+  class A {
+    x(p) => x("x");
+  }
+  main() {
+    new A().x(1);
+  }
+""";
+
+const String TEST_8 = r"""
+  class A {
+    x(p1, p2) => x(p1, "x");
+  }
+  main() {
+    new A().x(1, 2);
+  }
+""";
+
+const String TEST_9 = r"""
+  class A {
+    x(p1, p2) => x(p1, p2);
+  }
+  main() {
+    new A().x(1, 2);
+  }
+""";
+
+const String TEST_10 = r"""
+  class A {
+    x(p1, p2) => x(p1, p2);
+  }
+  void f(p) {
+    p.x("x", "y");
+  }
+  main() {
+    f(null);
+    new A().x(1, 2);
+  }
+""";
+
+const String TEST_11 = r"""
+  class A {
+    x(p1, p2) => x(1, 2);
+  }
+  main() {
+    new A().x("x", "y");
+  }
+""";
+
+const String TEST_12 = r"""
+  class A {
+    x(p1, [p2 = 1]) => 1;
+  }
+  main() {
+    new A().x("x", 1);
+    new A().x("x");
+  }
+""";
+
+const String TEST_13 = r"""
+  class A {
+    x(p) => 1;
+  }
+  f(p) => p.x(2.2);
+  main() {
+    new A().x(1);
+    f(new A());
+  }
+""";
+
+const String TEST_14 = r"""
+  class A {
+    x(p1, [p2 = "s"]) => 1;
+  }
+  main() {
+    new A().x(1);
+  }
+""";
+
+const String TEST_15 = r"""
+  class A {
+    x(p1, [p2 = true]) => 1;
+  }
+  f(p) => p.a("x");
+  main() {
+    new A().x("x");
+    new A().x("x", false);
+    f(null);
+  }
+""";
+
+const String TEST_16 = r"""
+  class A {
+    x(p1, [p2 = 1, p3 = "s"]) => 1;
+  }
+  main() {
+    new A().x(1);
+    new A().x(1, 2);
+    new A().x(1, 2, "x");
+    new A().x(1, p2: 2);
+    new A().x(1, p3: "x");
+    new A().x(1, p3: "x", p2: 2);
+    new A().x(1, p2: 2, p3: "x");
+  }
+""";
+
+const String TEST_17 = r"""
+  class A {
+    x(p1, [p2 = 1, p3 = "s"]) => 1;
+  }
+  main() {
+    new A().x(1, true, 1.1);
+    new A().x(1, false, 2.2);
+    new A().x(1, p3: 3.3, p2: true);
+    new A().x(1, p2: false, p3: 4.4);
+  }
+""";
+
+const String TEST_18 = r"""
+  class A {
+    x(p1, p2) => x(p1, p2);
+  }
+  class B extends A {
+  }
+  main() {
+    new B().x("a", "b");
+    new A().x(1, 2);
+  }
+""";
+
+void doTest(String test, bool enableInlining, Function f) {
+  compileAndFind(
+    test,
+    'A',
+    'x',
+    enableInlining,
+    (inferrer, element) {
+      var expectedTypes = f(inferrer);
+      var signature = element.computeSignature(inferrer.compiler);
+      int index = 0;
+      signature.forEachParameter((Element element) {
+        Expect.equals(expectedTypes[index++], inferrer.typeOf[element]);
+      });
+      Expect.equals(index, expectedTypes.length);
+  });
+}
+
+void runTest(String test, Function f) {
+  doTest(test, false, f);
+  doTest(test, true, f);
+}
+
+void test() {
+  runTest(TEST_1, (inferrer) => [inferrer.stringType]);
+  runTest(TEST_2, (inferrer) => [inferrer.intType]);
+  runTest(TEST_3, (inferrer) => [inferrer.numType]);
+  runTest(TEST_4, (inferrer) => [inferrer.numType]);
+  runTest(TEST_5, (inferrer) => [inferrer.numType]);
+  runTest(TEST_6, (inferrer) => [inferrer.numType]);
+  runTest(TEST_7, (inferrer) => [inferrer.dynamicType]);
+
+  // In the following tests, we can't infer the right types because we
+  // have recursive calls with the same parameters. We should build a
+  // constraint system for those, to find the types.
+  runTest(TEST_8, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
+  runTest(TEST_9, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
+  runTest(TEST_10, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
+  runTest(TEST_11, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
+
+  runTest(TEST_12, (inferrer) => [inferrer.stringType, inferrer.intType]);
+
+  runTest(TEST_13, (inferrer) => [inferrer.numType]);
+
+  runTest(TEST_14, (inferrer) => [inferrer.intType, inferrer.stringType]);
+
+  runTest(TEST_15, (inferrer) => [inferrer.stringType, inferrer.boolType]);
+
+  runTest(TEST_16, (inferrer) => [inferrer.intType,
+                                  inferrer.intType,
+                                  inferrer.stringType]);
+
+  runTest(TEST_17, (inferrer) => [inferrer.intType,
+                                  inferrer.boolType,
+                                  inferrer.doubleType]);
+
+  runTest(TEST_18, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
+}
+
+void main() {
+  test();
+}
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index b86d2e6..b2a83d5 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -48,28 +48,28 @@
 
 void testBasicTypes() {
   checkPrintType('true', (compiler, type) {
-    var backend = compiler.backend;
-    Expect.identical(backend.boolImplementation, type.exactType.element);
+    var inferrer = compiler.typesTask.typesInferrer;
+    Expect.identical(inferrer.boolType, type);
   });
   checkPrintType('1.0', (compiler, type) {
-    var backend = compiler.backend;
-    Expect.identical(backend.doubleImplementation, type.exactType.element);
+    var inferrer = compiler.typesTask.typesInferrer;
+    Expect.identical(inferrer.doubleType, type);
   });
   checkPrintType('1', (compiler, type) {
-    var backend = compiler.backend;
-    Expect.identical(backend.intImplementation, type.exactType.element);
+    var inferrer = compiler.typesTask.typesInferrer;
+    Expect.identical(inferrer.intType, type);
   });
   checkPrintType('[]', (compiler, type) {
-    var backend = compiler.backend;
-    Expect.identical(backend.listImplementation, type.exactType.element);
+    var inferrer = compiler.typesTask.typesInferrer;
+    Expect.identical(inferrer.growableListType, type);
   });
   checkPrintType('null', (compiler, type) {
-    var backend = compiler.backend;
-    Expect.identical(backend.nullImplementation, type.exactType.element);
+    var inferrer = compiler.typesTask.typesInferrer;
+    Expect.identical(inferrer.nullType, type);
   });
   checkPrintType('"foo"', (compiler, type) {
-    var backend = compiler.backend;
-    Expect.identical(backend.stringImplementation, type.exactType.element);
+    var inferrer = compiler.typesTask.typesInferrer;
+    Expect.identical(inferrer.stringType, type);
   });
 }
 
@@ -84,14 +84,17 @@
           fiskElement.computeSignature(compiler).optionalParameters.head;
         var thirdParameter =
           fiskElement.computeSignature(compiler).optionalParameters.tail.head;
+        var typesTask = compiler.typesTask;
+        var inferrer = typesTask.typesInferrer;
         Expect.identical(
-            compiler.backend.intImplementation,
-            compiler.typesTask.getGuaranteedTypeOfElement(firstParameter)
-                .exactType.element);
-        Expect.isNull(
-            compiler.typesTask.getGuaranteedTypeOfElement(secondParameter));
-        Expect.isNull(
-            compiler.typesTask.getGuaranteedTypeOfElement(thirdParameter));
+            inferrer.intType,
+            typesTask.getGuaranteedTypeOfElement(firstParameter));
+        Expect.identical(
+            inferrer.nullType,
+            typesTask.getGuaranteedTypeOfElement(secondParameter));
+        Expect.identical(
+            inferrer.nullType,
+            typesTask.getGuaranteedTypeOfElement(thirdParameter));
       });
 }
 
diff --git a/tests/compiler/dart2js/constant_folding_test.dart b/tests/compiler/dart2js/constant_folding_test.dart
index 482b8da..0721bbd 100644
--- a/tests/compiler/dart2js/constant_folding_test.dart
+++ b/tests/compiler/dart2js/constant_folding_test.dart
@@ -30,6 +30,30 @@
 }
 """;
 
+const String LIST_LENGTH_FOLDING = """
+foo() {
+  return const [1, 2, 3].length;
+}
+""";
+
+const String STRING_LENGTH_FOLDING = """
+foo() {
+  return '123'.length;
+}
+""";
+
+const String LIST_INDEX_FOLDING = """
+foo() {
+  return const [1, 2, 3][0];
+}
+""";
+
+const String RANGE_ERROR_INDEX_FOLDING = """
+foo() {
+  return [1][1];
+}
+""";
+
 main() {
   compileAndMatch(
       NUMBER_FOLDING, 'main', new RegExp(r"print\(7\)"));
@@ -48,4 +72,19 @@
 
   regexp = new RegExp('"foo" === d');
   Expect.isTrue(regexp.hasMatch(generated));
+
+  compileAndMatch(
+      LIST_LENGTH_FOLDING, 'foo', new RegExp(r"return 3"));
+
+  compileAndMatch(
+      LIST_INDEX_FOLDING, 'foo', new RegExp(r"return 1"));
+
+  compileAndDoNotMatch(
+      LIST_INDEX_FOLDING, 'foo', new RegExp(r"throw"));
+
+  compileAndMatch(
+      STRING_LENGTH_FOLDING, 'foo', new RegExp(r"return 3"));
+
+  compileAndMatch(
+      RANGE_ERROR_INDEX_FOLDING, 'foo', new RegExp(r"throw"));
 }
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 1c393d7..03e83cb 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -398,6 +398,35 @@
   }
 """;
 
+const String TEST_24 = r"""
+  class A {
+    var f1 = 42;
+    var f2 = 42;
+    var f3 = 42;
+    final f4;
+    var f5;
+    var f6 = null;
+    A() : f4 = 42 {
+      f1++;
+      f2 += 42;
+      var f6 = 'foo';
+      this.f6 = f6;
+    }
+    A.foo(other) : f3 = other.f3, f4 = other.f4, f5 = other.bar();
+    operator+(other) => 'foo';
+    bar() => 42.5;
+  }
+  class B extends A {
+    bar() => 42;
+  }
+  main() {
+    new A();
+    new A.foo(new A());
+    new A.foo(new B());
+
+  }
+""";
+
 void doTest(String test, bool disableInlining, Map<String, Function> fields) {
   fields.forEach((String name, Function f) {
     compileAndFind(
@@ -424,26 +453,26 @@
                    'f2': (inferrer) => inferrer.intType});
   runTest(TEST_3, {'f1': (inferrer) => inferrer.intType,
                    'f2': (inferrer) => inferrer.intType.nullable()});
-  runTest(TEST_4, {'f1': (inferrer) => inferrer.giveUpType,
+  runTest(TEST_4, {'f1': (inferrer) => inferrer.dynamicType,
                    'f2': (inferrer) => inferrer.stringType.nullable()});
 
   // TODO(ngeoffray): We should try to infer that the initialization
   // code at the declaration site of the fields does not matter.
-  runTest(TEST_5, {'f1': (inferrer) => inferrer.giveUpType,
-                   'f2': (inferrer) => inferrer.giveUpType});
-  runTest(TEST_6, {'f1': (inferrer) => inferrer.giveUpType,
-                   'f2': (inferrer) => inferrer.giveUpType});
-  runTest(TEST_7, {'f1': (inferrer) => inferrer.giveUpType,
-                   'f2': (inferrer) => inferrer.giveUpType});
+  runTest(TEST_5, {'f1': (inferrer) => inferrer.dynamicType,
+                   'f2': (inferrer) => inferrer.dynamicType});
+  runTest(TEST_6, {'f1': (inferrer) => inferrer.dynamicType,
+                   'f2': (inferrer) => inferrer.dynamicType});
+  runTest(TEST_7, {'f1': (inferrer) => inferrer.dynamicType,
+                   'f2': (inferrer) => inferrer.dynamicType});
 
   runTest(TEST_8, {'f': (inferrer) => inferrer.stringType.nullable()});
   runTest(TEST_9, {'f': (inferrer) => inferrer.stringType.nullable()});
-  runTest(TEST_10, {'f': (inferrer) => inferrer.giveUpType});
+  runTest(TEST_10, {'f': (inferrer) => inferrer.dynamicType});
   runTest(TEST_11, {'fs': (inferrer) => inferrer.intType});
 
   // TODO(ngeoffray): We should try to infer that the initialization
   // code at the declaration site of the fields does not matter.
-  runTest(TEST_12, {'fs': (inferrer) => inferrer.giveUpType});
+  runTest(TEST_12, {'fs': (inferrer) => inferrer.dynamicType});
 
   runTest(TEST_13, {'fs': (inferrer) => inferrer.intType});
   runTest(TEST_14, {'f': (inferrer) => inferrer.intType});
@@ -452,7 +481,7 @@
                                 inferrer.compiler.backend.jsIndexableClass;
                             return new TypeMask.nonNullSubtype(cls.rawType);
                          }});
-  runTest(TEST_16, {'f': (inferrer) => inferrer.giveUpType});
+  runTest(TEST_16, {'f': (inferrer) => inferrer.dynamicType});
   runTest(TEST_17, {'f': (inferrer) => inferrer.intType.nullable()});
   runTest(TEST_18, {'f1': (inferrer) => inferrer.intType,
                     'f2': (inferrer) => inferrer.stringType,
@@ -471,6 +500,13 @@
                     'f2': (inferrer) => inferrer.intType.nullable(),
                     'f3': (inferrer) => inferrer.intType.nullable(),
                     'f4': (inferrer) => inferrer.intType.nullable()});
+
+  runTest(TEST_24, {'f1': (inferrer) => inferrer.numType,
+                    'f2': (inferrer) => inferrer.numType,
+                    'f3': (inferrer) => inferrer.intType,
+                    'f4': (inferrer) => inferrer.intType,
+                    'f5': (inferrer) => inferrer.numType.nullable(),
+                    'f6': (inferrer) => inferrer.stringType.nullable()});
 }
 
 void main() {
diff --git a/tests/compiler/dart2js/gvn_test.dart b/tests/compiler/dart2js/gvn_test.dart
index 59e5904..b580aca 100644
--- a/tests/compiler/dart2js/gvn_test.dart
+++ b/tests/compiler/dart2js/gvn_test.dart
@@ -26,6 +26,7 @@
 // Check that is checks get GVN'ed.
 const String TEST_THREE = r"""
 void foo(a) {
+  print(42);  // Make sure numbers are used.
   print(a is num);
   print(a is num);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 5f82f9e..6da3bd1 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -10,13 +10,16 @@
 class A {
   final intField;
   final giveUpField;
+  final fieldParameter;
   A() : intField = 42, giveUpField = 'foo';
   A.bar() : intField = 54, giveUpField = 42;
+  A.foo(this.fieldParameter);
 }
 
 main() {
   new A();
   new A.bar();
+  new A.foo(42);
 }
 """;
 
@@ -33,5 +36,6 @@
   }
 
   checkFieldTypeInClass('A', 'intField', typesInferrer.intType);
-  checkFieldTypeInClass('A', 'giveUpField', typesInferrer.giveUpType);
+  checkFieldTypeInClass('A', 'giveUpField', typesInferrer.dynamicType);
+  checkFieldTypeInClass('A', 'fieldParameter', typesInferrer.intType);
 }
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index ff250e0..ba3721c 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -60,12 +60,17 @@
   throw 42;
 }
 
+returnInt4() {
+  return (42);
+}
+
 get topLevelGetter => 42;
 returnDynamic() => topLevelGetter(42);
 
 class A {
   factory A() = A.generative;
   A.generative();
+  operator==(other) => 42;
 
   get myField => 42;
   set myField(a) {}
@@ -97,12 +102,14 @@
   returnInt1(true);
   returnInt2(true);
   returnInt3(true);
+  returnInt4();
   returnDouble(true);
   returnGiveUp(true);
   returnNum3();
   returnNum4();
   returnIntOrNull(true);
   returnDynamic();
+  new A() == null;
   new A()..returnNum1()
          ..returnNum2()
          ..returnNum3()
@@ -136,12 +143,13 @@
   checkReturn('returnInt1', typesInferrer.intType);
   checkReturn('returnInt2', typesInferrer.intType);
   checkReturn('returnDouble', typesInferrer.doubleType);
-  checkReturn('returnGiveUp', typesInferrer.giveUpType);
+  checkReturn('returnGiveUp', typesInferrer.dynamicType);
   checkReturn('returnNum3', typesInferrer.numType);
   checkReturn('returnNum4', typesInferrer.numType);
   checkReturn('returnIntOrNull', typesInferrer.intType.nullable());
   checkReturn('returnInt3', typesInferrer.intType);
   checkReturn('returnDynamic', typesInferrer.dynamicType);
+  checkReturn('returnInt4', typesInferrer.intType);
 
   checkReturnInClass(String className, String methodName, type) {
     var cls = findElement(compiler, className);
@@ -155,6 +163,7 @@
   checkReturnInClass('A', 'returnNum4', typesInferrer.numType);
   checkReturnInClass('A', 'returnNum5', typesInferrer.numType);
   checkReturnInClass('A', 'returnNum6', typesInferrer.numType);
+  checkReturnInClass('A', '==', typesInferrer.dynamicType);
 
   checkReturnInClass('B', 'returnNum1', typesInferrer.numType);
   checkReturnInClass('B', 'returnNum2', typesInferrer.numType);
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
index 150d2c7..be8f90e 100644
--- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -2,6 +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.
 
+import '../../../sdk/lib/_internal/compiler/implementation/types/types.dart'
+    show TypeMask;
+
 import 'compiler_helper.dart';
 
 const String TEST = """
@@ -114,6 +117,23 @@
   return a;
 }
 
+returnInt6() {
+  try {
+    throw 42;
+  } on int catch (e) {
+    return e;
+  }
+  return 42;
+}
+
+returnDyn6() {
+  try {
+    throw 42;
+  } catch (e) {
+    return e;
+  }
+}
+
 
 main() {
   returnInt1();
@@ -125,6 +145,9 @@
   returnInt4();
   returnDyn4();
   returnInt5();
+  returnDyn5();
+  returnInt6();
+  returnDyn6();
 }
 """;
 
@@ -145,9 +168,13 @@
   checkReturn('returnInt3', typesInferrer.intType);
   checkReturn('returnInt4', typesInferrer.intType);
   checkReturn('returnInt5', typesInferrer.intType);
+  checkReturn('returnInt6',
+      new TypeMask.nonNullSubtype(compiler.intClass.rawType));
 
   checkReturn('returnDyn1', typesInferrer.dynamicType);
   checkReturn('returnDyn2', typesInferrer.dynamicType);
   checkReturn('returnDyn3', typesInferrer.dynamicType);
   checkReturn('returnDyn4', typesInferrer.dynamicType);
+  checkReturn('returnDyn5', typesInferrer.dynamicType);
+  checkReturn('returnDyn6', typesInferrer.dynamicType);
 }
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index f0490f9..0116aec 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -10,8 +10,8 @@
 
 deferred_semantics_test/none: Fail # TODO(ahe): Multitest cannot use import.
 
-[ $runtime == ff ]
-deferred/deferred_constant_test: Pass, Crash # Issue 9158
+[ $runtime == ff || $jscl ]
+deferred/deferred_constant_test: Pass, Crash, Fail # Issue 9158
 deferred/deferred_class_test: Pass, Crash # Issue 9158
 
 [ $compiler == dart2js && $checked ]
diff --git a/tests/compiler/dart2js_native/field_type2_test.dart b/tests/compiler/dart2js_native/field_type2_test.dart
new file mode 100644
index 0000000..b4c138c
--- /dev/null
+++ b/tests/compiler/dart2js_native/field_type2_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that a closure call on a native field is recognized by the
+// type inferrer.
+
+class Node native "*Node" {
+  final parentNode;
+}
+
+makeNode(parent) native;
+
+void setup() native """
+// This code is all inside 'setup' and so not accesible from the global scope.
+function Node(parent){ this.parentNode = parent; }
+makeNode = function(p){return new Node(p);};
+""";
+
+
+main() {
+  setup();
+  var node = makeNode(null);
+  if (node.parentNode != null) {
+    node = node.parentNode();
+  }
+}
diff --git a/tests/html/audiobuffersourcenode_test.dart b/tests/html/audiobuffersourcenode_test.dart
index 3e19ba6..10fecc9 100644
--- a/tests/html/audiobuffersourcenode_test.dart
+++ b/tests/html/audiobuffersourcenode_test.dart
@@ -1,17 +1,27 @@
 library AudioBufferSourceNodeTest;
 import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:web_audio';
 
 main() {
 
-  useHtmlConfiguration();
+  useHtmlIndividualConfiguration();
 
-  test('createBuffer', () {
-      var ctx = new AudioContext();
-      AudioBufferSourceNode node = ctx.createBufferSource();
-      node.start(ctx.currentTime, 0, 2);
-      node.stop(ctx.currentTime + 2);
-      expect(node is AudioBufferSourceNode, isTrue);
+  group('supported', () {
+    test('supported', () {
+      expect(AudioContext.supported, true);
+    });
+  });
+
+  group('functional', () {
+    test('createBuffer', () {
+      if(AudioContext.supported) {
+        var ctx = new AudioContext();
+        AudioBufferSourceNode node = ctx.createBufferSource();
+        node.start(ctx.currentTime, 0, 2);
+        node.stop(ctx.currentTime + 2);
+        expect(node is AudioBufferSourceNode, isTrue);
+      }
+    });
   });
 }
diff --git a/tests/html/audiocontext_test.dart b/tests/html/audiocontext_test.dart
index 33a7907..bcf60a3 100644
--- a/tests/html/audiocontext_test.dart
+++ b/tests/html/audiocontext_test.dart
@@ -1,44 +1,79 @@
 library AudioContextTest;
 import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
 import 'dart:web_audio';
+import 'dart:async';
 
 main() {
 
-  useHtmlConfiguration();
+  useHtmlIndividualConfiguration();
 
   var isAudioContext =
       predicate((x) => x is AudioContext, 'is an AudioContext');
 
-  test('constructorTest', () {
-      var ctx = new AudioContext();
-      expect(ctx, isNotNull);
-      expect(ctx, isAudioContext);
+  group('supported', () {
+    test('supported', () {
+      expect(AudioContext.supported, true);
+    });
   });
-  test('createBuffer', () {
-      var ctx = new AudioContext();
-      ArrayBufferView arrayBufferView = new Float32Array.fromList([]);
-      try {
-        // Test that native overload is chosen correctly. Native implementation
-        // should throw 'SyntaxError' DomException because the buffer is empty.
-        AudioBuffer buffer = ctx.createBuffer(arrayBufferView.buffer, false);
-      } catch (e) {
-        expect(e.name, DomException.SYNTAX);
+
+  group('functional', () {
+    test('constructorTest', () {
+      if(AudioContext.supported) {
+        var ctx = new AudioContext();
+        expect(ctx, isNotNull);
+        expect(ctx, isAudioContext);
       }
-  });
+    });
 
-  test('audioRenames', () {
-    AudioContext context = new AudioContext();
-    GainNode gainNode = context.createGain();
-    gainNode.connect(context.destination, 0, 0);
-    expect(gainNode is GainNode, isTrue);
+    test('createBuffer', () {
+      if(AudioContext.supported) {
+        var ctx = new AudioContext();
+        ArrayBufferView arrayBufferView = new Float32Array.fromList([]);
+        try {
+          // Test that native overload is chosen correctly. Native
+          // implementation should throw 'SyntaxError' DomException because the
+          // buffer is empty.
+          AudioBuffer buffer = ctx.createBuffer(arrayBufferView.buffer, false);
+        } catch (e) {
+          expect(e.name, DomException.SYNTAX);
+        }
+      }
+    });
 
-    expect(context.createAnalyser() is AnalyserNode, isTrue);
-    expect(context.createChannelMerger() is ChannelMergerNode, isTrue);
-    expect(context.createChannelSplitter() is ChannelSplitterNode, isTrue);
-    expect(context.createOscillator() is OscillatorNode, isTrue);
-    expect(context.createPanner() is PannerNode, isTrue);
-    expect(context.createScriptProcessor(4096) is ScriptProcessorNode, isTrue);
+    test('audioRenames', () {
+      if(AudioContext.supported) {
+        AudioContext context = new AudioContext();
+        GainNode gainNode = context.createGain();
+        gainNode.connect(context.destination, 0, 0);
+        expect(gainNode is GainNode, isTrue);
+
+        expect(context.createAnalyser() is AnalyserNode, isTrue);
+        expect(context.createChannelMerger() is AudioNode, isTrue);
+        expect(context.createChannelSplitter() is AudioNode, isTrue);
+        expect(context.createOscillator() is OscillatorNode, isTrue);
+        expect(context.createPanner() is PannerNode, isTrue);
+        expect(context.createScriptProcessor(4096) is ScriptProcessorNode,
+            isTrue);
+      }
+    });
+
+    test('onAudioProcess', () {
+      if(AudioContext.supported) {
+        var completer = new Completer<bool>();
+        var context = new AudioContext();
+        var scriptProcessor = context.createScriptProcessor(1024, 1, 2);
+        scriptProcessor.connect(context.destination, 0, 0);
+        bool alreadyCalled = false;
+        scriptProcessor.onAudioProcess.listen((event) {
+          if (!alreadyCalled) {
+            completer.complete(true);
+          }
+          alreadyCalled = true;
+        });
+        return completer.future;
+      }
+    });
   });
 }
diff --git a/tests/html/canvasrenderingcontext2d_test.dart b/tests/html/canvasrenderingcontext2d_test.dart
index 5069680..7e82241 100644
--- a/tests/html/canvasrenderingcontext2d_test.dart
+++ b/tests/html/canvasrenderingcontext2d_test.dart
@@ -2,9 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library canvas_rendering_context_2d_test;
-import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
+library canvas_rendering_context_2d_test; import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
 import 'dart:math';
 
@@ -16,68 +15,74 @@
   expect(pixel[3], closeTo(expected[3], 2));
 }
 
+var canvas;
+var context;
+var otherCanvas;
+var otherContext;
+var video;
+
+void createCanvas() {
+  canvas = new CanvasElement();
+  canvas.width = 100;
+  canvas.height = 100;
+
+  context = canvas.context2d;
+}
+
+void createOtherCanvas() {
+  otherCanvas = new CanvasElement();
+  otherCanvas.width = 10;
+  otherCanvas.height = 10;
+  otherContext = otherCanvas.context2d;
+  otherContext.fillStyle = "red";
+  otherContext.fillRect(0, 0, otherCanvas.width, otherCanvas.height);
+}
+
+void setupFunc() {
+  createCanvas();
+  createOtherCanvas();
+  video = new VideoElement();
+}
+
+void tearDownFunc() {
+  canvas = null;
+  context = null;
+  otherCanvas = null;
+  otherContext = null;
+  video = null;
+}
+
+List<int> readPixel(int x, int y) {
+  var imageData = context.getImageData(x, y, 1, 1);
+  return imageData.data;
+}
+
+/// Returns true if the pixel has some data in it, false otherwise.
+bool isPixelFilled(int x, int y) => readPixel(x,y).any((p) => p != 0);
+
+String pixelDataToString(List<int> data, int x, int y) {
+  return '[${data.join(", ")}]';
+}
+
+String _filled(bool v) => v ? "filled" : "unfilled";
+
+void expectPixelFilled(int x, int y, [bool filled = true]) {
+  expect(isPixelFilled(x, y), filled, reason:
+      'Pixel at ($x, $y) was expected to'
+      ' be: <${_filled(filled)}> but was: <${_filled(!filled)}> with data: '
+      '${pixelDataToString(readPixel(x, y), x, y)}');
+}
+
+void expectPixelUnfilled(int x, int y) {
+  expectPixelFilled(x, y, false);
+}
+
 main() {
-  useHtmlConfiguration();
+  useHtmlIndividualConfiguration();
 
-  group('canvasRenderingContext2d', () {
-    var canvas;
-    var context;
-    var otherCanvas;
-    var otherContext;
-
-    void createOtherCanvas() {
-      otherCanvas = new CanvasElement();
-      otherCanvas.width = 10;
-      otherCanvas.height = 10;
-      otherContext = otherCanvas.context2d;
-      otherContext.fillStyle = "red";
-      otherContext.fillRect(0, 0, otherCanvas.width, otherCanvas.height);
-    }
-
-    setUp(() {
-      canvas = new CanvasElement();
-      canvas.width = 100;
-      canvas.height = 100;
-
-      context = canvas.context2d;
-
-      createOtherCanvas();
-    });
-
-    tearDown(() {
-      canvas = null;
-      context = null;
-      otherCanvas = null;
-      otherContext = null;
-    });
-
-    List<int> readPixel(int x, int y) {
-      var imageData = context.getImageData(x, y, 1, 1);
-      return imageData.data;
-    }
-
-    /// Returns true if the pixel has some data in it, false otherwise.
-    bool isPixelFilled(int x, int y) => readPixel(x,y).any((p) => p != 0);
-
-    String pixelDataToString(int x, int y) {
-      var data = readPixel(x, y);
-
-      return '[${data.join(", ")}]';
-    }
-
-    String _filled(bool v) => v ? "filled" : "unfilled";
-
-    void expectPixelFilled(int x, int y, [bool filled = true]) {
-      expect(isPixelFilled(x, y), filled, reason:
-          'Pixel at ($x, $y) was expected to'
-          ' be: <${_filled(filled)}> but was: <${_filled(!filled)}> with data: '
-          '${pixelDataToString(x,y)}');
-    }
-
-    void expectPixelUnfilled(int x, int y) {
-      expectPixelFilled(x, y, false);
-    }
-
+  group('pixel_manipulation', () {
+    setUp(setupFunc);
+    tearDown(tearDownFunc);
 
     test('setFillColorRgb', () {
       context.setFillColorRgb(255, 0, 255, 1);
@@ -169,6 +174,11 @@
       // Make sure that we read back what we wrote.
       expect(resultingData.data, expectedData.data);
     });
+  });
+
+  group('arc', () {
+    setUp(setupFunc);
+    tearDown(tearDownFunc);
 
     test('default arc should be clockwise', () {
       context.beginPath();
@@ -252,9 +262,13 @@
       // (cx - r/SQRT2, cy - r/SQRT2) should be filled.
       expectPixelFilled((cx + r/SQRT2).toInt(), (cy - r/SQRT2).toInt(), true);
     });
+  });
 
+  group('drawImage_image_element', () {
+    setUp(setupFunc);
+    tearDown(tearDownFunc);
     // Draw an image to the canvas from an image element.
-    test('drawImage from img element with 3 params', () {
+    test('with 3 params', () {
       var dataUrl = otherCanvas.toDataUrl('image/gif');
       var img = new ImageElement();
 
@@ -277,12 +291,12 @@
     });
 
     // Draw an image to the canvas from an image element and scale it.
-    test('drawImage from img element with 5 params', () {
+    test('with 5 params', () {
       var dataUrl = otherCanvas.toDataUrl('image/gif');
       var img = new ImageElement();
 
       img.onLoad.listen(expectAsync1((_) {
-        context.drawImageAtScale(img, new Rect(50, 50, 20, 20));
+        context.drawImageToRect(img, new Rect(50, 50, 20, 20));
 
         expectPixelFilled(50, 50);
         expectPixelFilled(55, 55);
@@ -302,7 +316,7 @@
     });
 
     // Draw an image to the canvas from an image element and scale it.
-    test('drawImage from img element with 9 params', () {
+    test('with 9 params', () {
       otherContext.fillStyle = "blue";
       otherContext.fillRect(5, 5, 5, 5);
       var dataUrl = otherCanvas.toDataUrl('image/gif');
@@ -310,9 +324,9 @@
 
       img.onLoad.listen(expectAsync1((_) {
         // This will take a 6x6 square from the first canvas from position 2,2
-        // and then scale it to a 20x20 square and place it to the second canvas
-        // at 50,50.
-        context.drawImageAtScale(img, new Rect(50, 50, 20, 20),
+        // and then scale it to a 20x20 square and place it to the second
+        // canvas at 50,50.
+        context.drawImageToRect(img, new Rect(50, 50, 20, 20),
           sourceRect: new Rect(2, 2, 6, 6));
 
         checkPixel(readPixel(50, 50), [255, 0, 0, 255]);
@@ -337,155 +351,202 @@
       });
       img.src = dataUrl;
     });
+  });
 
-    // These base64 strings are the same video, representing 2 frames of 8x8 red
-    // pixels.
-    // The videos were created with:
-    //   convert -size 8x8 xc:red blank1.jpg
-    //   convert -size 8x8 xc:red blank2.jpg
-    //   avconv -f image2  -i "blank%d.jpg" -c:v libx264 small.mp4
-    //   python -m base64 -e small.mp4
-    //   avconv -i small.mp4 small.webm
-    //   python -m base64 -e small.webm
-    var mp4VideoUrl =
-      'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZn'
-      'JlZQAAAsdtZGF0AAACmwYF//+X3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDEyMCByMj'
-      'E1MSBhM2Y0NDA3IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMj'
-      'AxMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYm'
-      'FjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibW'
-      'U9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm'
-      '9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3'
-      'Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTE4IHNsaWNlZF90aHJlYWRzPT'
-      'AgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYW'
-      'luZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTAgYl9hZGFwdD0xIGJfYmlhcz0wIG'
-      'RpcmVjdD0xIHdlaWdodGI9MCBvcGVuX2dvcD0xIHdlaWdodHA9MiBrZXlpbnQ9MjUwIGtleW'
-      'ludF9taW49MjUgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MC'
-      'ByYz1jcmYgbWJ0cmVlPTEgY3JmPTUxLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IH'
-      'Fwc3RlcD00IGlwX3JhdGlvPTEuMjUgYXE9MToxLjAwAIAAAAARZYiEB//3aoK5/tP9+8yeuI'
-      'EAAAAHQZoi2P/wgAAAAzxtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAUAABAAABAA'
-      'AAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT/////7/AAACUHRyYWsAAA'
-      'BcdGtoZAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAA'
-      'AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAACAAAAAgAAAAAACRlZHRzAAAAHGVsc3QAAA'
-      'AAAAAAAQAAAFAAAAABAAEAAAAAAchtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAAAZAAAAAl'
-      'XEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAFzbW'
-      'luZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybC'
-      'AAAAABAAABM3N0YmwAAACXc3RzZAAAAAAAAAABAAAAh2F2YzEAAAAAAAAAAQAAAAAAAAAAAA'
-      'AAAAAAAAAACAAIAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
-      'AAAAAY//8AAAAxYXZjQwFNQAr/4QAYZ01ACuiPyy4C2QAAAwABAAADADIPEiUSAQAGaOvAZS'
-      'yAAAAAGHN0dHMAAAAAAAAAAQAAAAIAAAABAAAAFHN0c3MAAAAAAAAAAQAAAAEAAAAYY3R0cw'
-      'AAAAAAAAABAAAAAgAAAAEAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAA'
-      'AAAAAAAAAAAAIAAAK0AAAACwAAABhzdGNvAAAAAAAAAAIAAAAwAAAC5AAAAGB1ZHRhAAAAWG'
-      '1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAK2lsc3QAAAAjqX'
-      'RvbwAAABtkYXRhAAAAAQAAAABMYXZmNTMuMjEuMQ==';
-    var webmVideoUrl =
-      'data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlYm1Ch'
-      '4ECQoWBAhhTgGcBAAAAAAAB/hFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua1OsggEsT'
-      'buMU6uEHFO7a1OsggHk7AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAAEEq17GDD0JATYCLTGF2ZjUzL'
-      'jIxLjFXQYtMYXZmNTMuMjEuMXOkkJatuHwTJ7cvFLSzBSmxbp5EiYhAVAAAAAAAABZUrmsBA'
-      'AAAAAAAR64BAAAAAAAAPteBAXPFgQGcgQAitZyDdW5khoVWX1ZQOIOBASPjg4QCYloA4AEAA'
-      'AAAAAASsIEIuoEIVLCBCFS6gQhUsoEDH0O2dQEAAAAAAABZ54EAo72BAACA8AIAnQEqCAAIA'
-      'ABHCIWFiIWEiAICAnWqA/gD+gINTRgA/v0hRf/kb+PnRv/I4//8WE8DijI//FRAo5WBACgAs'
-      'QEAARAQABgAGFgv9AAIAAAcU7trAQAAAAAAAA67jLOBALeH94EB8YIBfw==';
+  // These videos and base64 strings are the same video, representing 2
+  // frames of 8x8 red pixels.
+  // The videos were created with:
+  //   convert -size 8x8 xc:red blank1.jpg
+  //   convert -size 8x8 xc:red blank2.jpg
+  //   avconv -f image2  -i "blank%d.jpg" -c:v libx264 small.mp4
+  //   avconv -i small.mp4 small.webm
+  //   python -m base64 -e small.mp4
+  //   python -m base64 -e small.webm
+  var mp4VideoUrl = '/root_dart/tests/html/small.mp4';
+  var webmVideoUrl = '/root_dart/tests/html/small.webm';
+  var mp4VideoDataUrl =
+      'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAA'
+      'AIZnJlZQAAAsdtZGF0AAACmwYF//+X3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlID'
+      'EyMCByMjE1MSBhM2Y0NDA3IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZW'
+      'Z0IDIwMDMtMjAxMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG'
+      '9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweD'
+      'ExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj'
+      '0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MC'
+      'BkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aH'
+      'JlYWRzPTE4IHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZW'
+      'Q9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl'
+      '9weXJhbWlkPTAgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MCBvcG'
+      'VuX2dvcD0xIHdlaWdodHA9MiBrZXlpbnQ9MjUwIGtleWludF9taW49MjUgc2NlbmVjdX'
+      'Q9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPT'
+      'EgY3JmPTUxLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IGlwX3'
+      'JhdGlvPTEuMjUgYXE9MToxLjAwAIAAAAARZYiEB//3aoK5/tP9+8yeuIEAAAAHQZoi2P'
+      '/wgAAAAzxtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAUAABAAABAAAAAAAAAA'
+      'AAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAA'
+      'AAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT/////7/AAACUHRyYWsAAA'
+      'BcdGtoZAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAQAAAA'
+      'AAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAACAAAAAgAAAAAACRlZHRzAAAAHG'
+      'Vsc3QAAAAAAAAAAQAAAFAAAAABAAEAAAAAAchtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAA'
+      'AAAAAZAAAAAlXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSG'
+      'FuZGxlcgAAAAFzbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZg'
+      'AAAAAAAAABAAAADHVybCAAAAABAAABM3N0YmwAAACXc3RzZAAAAAAAAAABAAAAh2F2Yz'
+      'EAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAAIAEgAAABIAAAAAAAAAAEAAAAAAAAAAA'
+      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwFNQAr/4QAYZ01ACuiPyy'
+      '4C2QAAAwABAAADADIPEiUSAQAGaOvAZSyAAAAAGHN0dHMAAAAAAAAAAQAAAAIAAAABAA'
+      'AAFHN0c3MAAAAAAAAAAQAAAAEAAAAYY3R0cwAAAAAAAAABAAAAAgAAAAEAAAAcc3RzYw'
+      'AAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAK0AAAACwAAAB'
+      'hzdGNvAAAAAAAAAAIAAAAwAAAC5AAAAGB1ZHRhAAAAWG1ldGEAAAAAAAAAIWhkbHIAAA'
+      'AAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAK2lsc3QAAAAjqXRvbwAAABtkYXRhAAAAAQ'
+      'AAAABMYXZmNTMuMjEuMQ==';
+  var webmVideoDataUrl =
+      'data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlY'
+      'm1Ch4ECQoWBAhhTgGcBAAAAAAAB/hFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua'
+      '1OsggEsTbuMU6uEHFO7a1OsggHk7AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAA'
+      'EEq17GDD0JATYCLTGF2ZjUzLjIxLjFXQYtMYXZmNTMuMjEuMXOkkJatuHwTJ7cvFLSzB'
+      'Smxbp5EiYhAVAAAAAAAABZUrmsBAAAAAAAAR64BAAAAAAAAPteBAXPFgQGcgQAitZyDd'
+      'W5khoVWX1ZQOIOBASPjg4QCYloA4AEAAAAAAAASsIEIuoEIVLCBCFS6gQhUsoEDH0O2d'
+      'QEAAAAAAABZ54EAo72BAACA8AIAnQEqCAAIAABHCIWFiIWEiAICAnWqA/gD+gINTRgA/'
+      'v0hRf/kb+PnRv/I4//8WE8DijI//FRAo5WBACgAsQEAARAQABgAGFgv9AAIAAAcU7trA'
+      'QAAAAAAAA67jLOBALeH94EB8YIBfw==';
+  group('drawImage_video_element', () {
+    setUp(setupFunc);
+    tearDown(tearDownFunc);
 
-//    test('drawImage from video element with 3 params', () {
-//      var video = new VideoElement();
-//
-//      video.onLoadedData.listen(expectAsync1((_) {
-//        context.drawImage(video, 50, 50);
-//
-//        expectPixelFilled(50, 50);
-//        expectPixelFilled(54, 54);
-//        expectPixelFilled(57, 57);
-//        expectPixelUnfilled(58, 58);
-//        expectPixelUnfilled(0, 0);
-//        expectPixelUnfilled(70, 70);
-//      }));
-//      video.onError.listen((_) {
-//        guardAsync(() {
-//          fail('URL failed to load.');
-//        });
-//      });
-//
-//      if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
-//        video.src = webmVideoUrl;
-//      } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"',
-//            null) != '') {
-//        video.src = mp4VideoUrl;
-//      } else {
-//        logMessage('Video is not supported on this system.');
-//      }
-//    });
-//
-//    test('drawImage from video element with 5 params', () {
-//      var video = new VideoElement();
-//
-//      video.onLoadedData.listen(expectAsync1((_) {
-//        context.drawImageAtScale(video, new Rect(50, 50, 20, 20));
-//
-//        expectPixelFilled(50, 50);
-//        expectPixelFilled(55, 55);
-//        expectPixelFilled(59, 59);
-//        expectPixelFilled(60, 60);
-//        expectPixelFilled(69, 69);
-//        expectPixelUnfilled(70, 70);
-//        expectPixelUnfilled(0, 0);
-//        expectPixelUnfilled(80, 80);
-//      }));
-//      video.onError.listen((_) {
-//        guardAsync(() {
-//          fail('URL failed to load.');
-//        });
-//      });
-//
-//      if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
-//        video.src = webmVideoUrl;
-//      } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"',
-//            null) != '') {
-//        video.src = mp4VideoUrl;
-//      } else {
-//        // TODO(amouravski): Better fallback?
-//        logMessage('Video is not supported on this system.');
-//      }
-//    });
-//
-//    test('drawImage from video element with 9 params', () {
-//      var video = new VideoElement();
-//
-//      video.onLoadedData.listen(expectAsync1((_) {
-//        context.drawImageAtScale(video, new Rect(50, 50, 20, 20),
-//          sourceRect: new Rect(2, 2, 6, 6));
-//
-//        expectPixelFilled(50, 50);
-//        expectPixelFilled(55, 55);
-//        expectPixelFilled(59, 59);
-//        expectPixelFilled(60, 60);
-//        expectPixelFilled(69, 69);
-//        expectPixelUnfilled(70, 70);
-//        expectPixelUnfilled(0, 0);
-//        expectPixelUnfilled(80, 80);
-//      }));
-//      video.onError.listen((_) {
-//        guardAsync(() {
-//          fail('URL failed to load.');
-//        });
-//      });
-//
-//      if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
-//        video.src = webmVideoUrl;
-//      } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"',
-//            null) != '') {
-//        video.src = mp4VideoUrl;
-//      } else {
-//        // TODO(amouravski): Better fallback?
-//        logMessage('Video is not supported on this system.');
-//      }
-//    });
+    test('with 3 params', () {
+      video.onCanPlay.listen(expectAsync1((_) {
+        context.drawImage(video, 50, 50);
 
-    test('drawImage from canvas element with 3 params', () {
+        expectPixelFilled(50, 50);
+        expectPixelFilled(54, 54);
+        expectPixelFilled(57, 57);
+        expectPixelUnfilled(58, 58);
+        expectPixelUnfilled(0, 0);
+        expectPixelUnfilled(70, 70);
+      }));
+
+      video.onError.listen((_) {
+        guardAsync(() {
+          fail('URL failed to load.');
+        });
+      });
+
+      if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+        video.src = webmVideoUrl;
+      } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"',
+            null) != '') {
+        video.src = mp4VideoUrl;
+      } else {
+        window.console.log('Video is not supported on this system.');
+      }
+    });
+
+    test('with 5 params', () {
+      video.onCanPlay.listen(expectAsync1((_) {
+        context.drawImageToRect(video, new Rect(50, 50, 20, 20));
+
+        expectPixelFilled(50, 50);
+        expectPixelFilled(55, 55);
+        expectPixelFilled(59, 59);
+        expectPixelFilled(60, 60);
+        expectPixelFilled(69, 69);
+        expectPixelUnfilled(70, 70);
+        expectPixelUnfilled(0, 0);
+        expectPixelUnfilled(80, 80);
+      }));
+      video.onError.listen((_) {
+        guardAsync(() {
+          fail('URL failed to load.');
+        });
+      });
+
+      if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+        video.src = webmVideoUrl;
+      } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"',
+            null) != '') {
+        video.src = mp4VideoUrl;
+      } else {
+        // TODO(amouravski): Better fallback?
+        window.console.log('Video is not supported on this system.');
+      }
+    });
+
+    test('with 9 params', () {
+      video.onCanPlay.listen(expectAsync1((_) {
+        context.drawImageToRect(video, new Rect(50, 50, 20, 20),
+          sourceRect: new Rect(2, 2, 6, 6));
+
+        expectPixelFilled(50, 50);
+        expectPixelFilled(55, 55);
+        expectPixelFilled(59, 59);
+        expectPixelFilled(60, 60);
+        expectPixelFilled(69, 69);
+        expectPixelUnfilled(70, 70);
+        expectPixelUnfilled(0, 0);
+        expectPixelUnfilled(80, 80);
+      }));
+      video.onError.listen((_) {
+        guardAsync(() {
+          fail('URL failed to load.');
+        });
+      });
+
+      if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+        video.src = webmVideoUrl;
+      } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"',
+            null) != '') {
+        video.src = mp4VideoUrl;
+      } else {
+        // TODO(amouravski): Better fallback?
+        window.console.log('Video is not supported on this system.');
+      }
+    });
+  });
+
+  group('drawImage_video_element_dataUrl', () {
+    setUp(setupFunc);
+    tearDown(tearDownFunc);
+
+    test('with 9 params', () {
+      video = new VideoElement();
+      canvas = new CanvasElement();
+      video.onCanPlay.listen(expectAsync1((_) {
+        context.drawImageToRect(video, new Rect(50, 50, 20, 20),
+          sourceRect: new Rect(2, 2, 6, 6));
+
+        expectPixelFilled(50, 50);
+        expectPixelFilled(55, 55);
+        expectPixelFilled(59, 59);
+        expectPixelFilled(60, 60);
+        expectPixelFilled(69, 69);
+        expectPixelUnfilled(70, 70);
+        expectPixelUnfilled(0, 0);
+        expectPixelUnfilled(80, 80);
+      }));
+      video.onError.listen((_) {
+        guardAsync(() {
+          fail('URL failed to load.');
+        });
+      });
+
+      if(video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+        video.src = webmVideoDataUrl;
+      } else if(video.canPlayType('video/mp4; codecs="avc1.4D401E, mp4a.40.2"',
+            null) != '') {
+        video.src = mp4VideoDataUrl;
+      } else {
+        // TODO(amouravski): Better fallback?
+        window.console.log('Video is not supported on this system.');
+      }
+    });
+  });
+
+  group('drawImage_canvas_element', () {
+    setUp(setupFunc);
+    tearDown(tearDownFunc);
+
+    test('with 3 params', () {
       // Draw an image to the canvas from a canvas element.
       context.drawImage(otherCanvas, 50, 50);
 
@@ -496,9 +557,9 @@
       expectPixelUnfilled(0, 0);
       expectPixelUnfilled(70, 70);
     });
-    test('drawImage from canvas element with 5 params', () {
+    test('with 5 params', () {
       // Draw an image to the canvas from a canvas element.
-      context.drawImageAtScale(otherCanvas, new Rect(50, 50, 20, 20));
+      context.drawImageToRect(otherCanvas, new Rect(50, 50, 20, 20));
 
       expectPixelFilled(50, 50);
       expectPixelFilled(55, 55);
@@ -509,11 +570,11 @@
       expectPixelUnfilled(0, 0);
       expectPixelUnfilled(80, 80);
     });
-    test('drawImage from canvas element with 9 params', () {
+    test('with 9 params', () {
       // Draw an image to the canvas from a canvas element.
       otherContext.fillStyle = "blue";
       otherContext.fillRect(5, 5, 5, 5);
-      context.drawImageAtScale(otherCanvas, new Rect(50, 50, 20, 20),
+      context.drawImageToRect(otherCanvas, new Rect(50, 50, 20, 20),
           sourceRect: new Rect(2, 2, 6, 6));
 
       checkPixel(readPixel(50, 50), [255, 0, 0, 255]);
@@ -530,5 +591,15 @@
       expectPixelUnfilled(0, 0);
       expectPixelUnfilled(80, 80);
     });
+
+    test('createImageData', () {
+      var imageData = context.createImageData(15, 15);
+      expect(imageData.width, 15);
+      expect(imageData.height, 15);
+
+      var other = context.createImageDataFromImageData(imageData);
+      expect(other.width, 15);
+      expect(other.height, 15);
+    });
   });
 }
diff --git a/tests/html/element_classes_test.dart b/tests/html/element_classes_test.dart
index 0af9f3e..10b4111 100644
--- a/tests/html/element_classes_test.dart
+++ b/tests/html/element_classes_test.dart
@@ -142,6 +142,14 @@
     expect(classes, orderedEquals(['foo']));
   });
 
+  test('toggleAll', () {
+    final classes = makeClassSet();
+    classes.toggleAll(['bar', 'foo']);
+    expect(classes, orderedEquals(['baz']));
+    classes.toggleAll(['qux', 'quux']);
+    expect(classes, orderedEquals(['baz', 'qux', 'quux']));
+  });
+
   test('isSubsetOf', () {
     final classes = makeClassSet();
     expect(classes.isSubsetOf(['foo', 'bar', 'baz'].toSet()), isTrue);
diff --git a/tests/html/element_test.dart b/tests/html/element_test.dart
index 7fc6bfe..53a743c 100644
--- a/tests/html/element_test.dart
+++ b/tests/html/element_test.dart
@@ -280,13 +280,6 @@
   });
 
   group('attributes', () {
-      test('coercion', () {
-        final element = new Element.tag('div');
-        element.attributes['foo'] = 42;
-        element.attributes['bar'] = 3.1;
-        expect(element.attributes['foo'], '42');
-        expect(element.attributes['bar'], '3.1');
-      });
       test('manipulation', () {
         final element = new Element.html(
             '''<div class="foo" style="overflow: hidden" data-foo="bar"
@@ -465,6 +458,18 @@
       expect(el.children[5], isHeadingElement);
     });
 
+    test('insert', () {
+      var element = new DivElement();
+      element.children.insert(0, new BRElement());
+      expect(element.children[0], isBRElement);
+      element.children.insert(0, new HRElement());
+      expect(element.children[0], isHRElement);
+      element.children.insert(1, new ImageElement());
+      expect(element.children[1], isImageElement);
+      element.children.insert(element.children.length, new InputElement());
+      expect(element.children.last, isInputElement);
+    });
+
     test('clear', () {
       var el = makeElementWithChildren();
       el.children.clear();
diff --git a/tests/html/fileapi_test.dart b/tests/html/fileapi_test.dart
index 681750c..697f176 100644
--- a/tests/html/fileapi_test.dart
+++ b/tests/html/fileapi_test.dart
@@ -22,7 +22,7 @@
   });
 
   getFileSystem() {
-    return window.requestFileSystem(Window.TEMPORARY, 100)
+    return window.requestFileSystem(100)
       .then((FileSystem fileSystem) {
         fs = fileSystem;
       });
@@ -32,7 +32,7 @@
     test('requestFileSystem', () {
       var expectation = FileSystem.supported ? returnsNormally : throws;
       expect(() {
-        window.requestFileSystem(Window.TEMPORARY, 100);
+        window.requestFileSystem(100);
       }, expectation);
     });
   });
@@ -43,17 +43,15 @@
 
       test('directoryDoesntExist', () {
         return fs.root.getDirectory(
-            'directory2',
-            options: {})
+            'directory2')
               .catchError((e) {
                 expect(e.error.code, equals(FileError.NOT_FOUND_ERR));
               }, test: (e) => e is FileError);
         });
 
       test('directoryCreate', () {
-        return fs.root.getDirectory(
-            'directory3',
-            options: {'create': true})
+        return fs.root.createDirectory(
+            'directory3')
               .then((DirectoryEntry e) {
                 expect(e.name, equals('directory3'));
               });
@@ -67,17 +65,15 @@
 
       test('fileDoesntExist', () {
         return fs.root.getFile(
-            'file2',
-            options: {})
+            'file2')
           .catchError((e) {
             expect(e.error.code, equals(FileError.NOT_FOUND_ERR));
           }, test: (e) => e is FileError);
       });
 
       test('fileCreate', () {
-        return fs.root.getFile(
-            'file4',
-            options: {'create': true})
+        return fs.root.createFile(
+            'file4')
           .then((FileEntry e) {
             expect(e.name, equals('file4'));
             expect(e.isFile, isTrue);
@@ -97,13 +93,11 @@
   // Do the boilerplate to get several files and directories created to then
   // test the functions that use those items.
   Future doDirSetup() {
-    return fs.root.getFile(
-      'file4',
-      options: {'create': true})
+    return fs.root.createFile(
+      'file4')
         .then((FileEntry file) {
-          return fs.root.getDirectory(
-              'directory3',
-              options: {'create': true})
+          return fs.root.createDirectory(
+              'directory3')
             .then((DirectoryEntry dir) {
               return new Future.immediate(new FileAndDir(file, dir));
             });
@@ -157,7 +151,7 @@
           }).then((entry) {
             expect(entry.name, 'movedFile');
             expect(entry.fullPath, '/directory3/movedFile');
-            return fs.root.getFile('file4', options: {'create': false});
+            return fs.root.getFile('file4');
           }).catchError((e) {
             expect(e.error.code, equals(FileError.NOT_FOUND_ERR));
           }, test: (e) => e is FileError);
diff --git a/tests/html/html.status b/tests/html/html.status
index 1195281..b7ecd42 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -19,7 +19,7 @@
 [$runtime == drt || $runtime == dartium || $runtime == chrome]
 webgl_1_test: Pass, Fail # Issue 8219
 
-[ $runtime == drt || $runtime == chrome]
+[ $runtime == drt || ($runtime == chrome && $system == windows) ]
 audiobuffersourcenode_test: Pass, Fail, Timeout, Crash # AudiobufferSourceNode is flaky on Chrome and Dartium - filed issue 8021 for the timeout.
 audiocontext_test: Pass, Timeout, Crash  # Issue 8021.
 
@@ -32,18 +32,14 @@
 [ $compiler == none && ($runtime == drt || $runtime == dartium) && $mode == debug]
 websql_test: Fail, Pass # Issue 4941: stderr contains a backtrace.
 
-[ $compiler == none && $runtime == drt && $system == macos]
-audiocontext_test: Pass, Fail
-
 [ $compiler == dart2js && $runtime == drt && $system == macos]
 audiobuffersourcenode_test: Pass, Fail
 
 [$runtime == ie10 ]
-audiobuffersourcenode_test: Fail
-audiocontext_test: Fail
 dromaeo_smoke_test: Skip #TODO(efortuna): investigating.
 element_test/click: Fail                # IE does not support firing this event.
 history_test/history: Pass, Fail # issue 8183
+indexeddb_1_test/functional: Pass, Timeout # http://dartbug.com/9269
 isolates_test: Skip
 microtask_test: Fail, Pass # Appears to be flaky
 native_gc_test: Fail, Pass # BUG(7774): Untriaged.
@@ -51,10 +47,13 @@
 storage_test: Fail, Pass
 websocket_test/websocket: Fail # TODO(efortuna): Issue 7875.
 window_open_test: Skip
-xhr_cross_origin_test: Fail # TODO(efortuna): Issue 7875.
+canvasrenderingcontext2d_test/drawImage_video_element: Fail # IE does not support drawImage w/ video element
+canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # IE does not support drawImage w/ video element
 
 # IE10 Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
+audiobuffersourcenode_test/supported: Fail
+audiocontext_test/supported: Fail
 crypto_test/supported: Fail
 css_test/supported_CssMatrix: Fail
 css_test/supported_DomPoint: Fail
@@ -94,8 +93,6 @@
 xsltprocessor_test/supported: Fail
 
 [ $runtime == ie9 ]
-audiobuffersourcenode_test: Fail
-audiocontext_test: Fail
 blob_constructor_test: Fail
 dom_constructors_test: Fail
 dromaeo_smoke_test: Skip #TODO(efortuna): investigating.
@@ -109,11 +106,13 @@
 serialized_script_value_test: Fail
 url_test: Fail              # IE9 does not support createObjectURL (it is supported in IE10)
 window_open_test: Skip      # BUG(4016)
-xhr_cross_origin_test: Fail # Issue 6016.
-canvasrenderingcontext2d_test: Pass, Fail # flaky drawImage. BUG(9189)
+canvasrenderingcontext2d_test/drawImage_video_element: Fail # IE does not support drawImage w/ video element
+canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # IE does not support drawImage w/ video element
 
 # IE9 Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
+audiobuffersourcenode_test/supported: Fail
+audiocontext_test/supported: Fail
 cache_test/supported: Fail
 crypto_test/supported: Fail
 css_test/supported_CssMatrix: Fail
@@ -189,13 +188,13 @@
 webgl_1_test/supported: Fail
 websocket_test/supported: Fail
 websql_test/supported: Fail
+xhr_cross_origin_test/supported: Fail
 xhr_test/supported_HttpRequestProgressEvent: Fail
 xhr_test/supported_onLoadEnd: Fail
 xhr_test/supported_onProgress: Fail
 xsltprocessor_test/supported: Fail
 
 [ $runtime == safari ]
-audiocontext_test: Crash, Fail # Issue: 7414
 datalistelement_test: Fail # Issue: 7414
 element_test/elements: Crash, Fail # Issue: 7414
 element_types_test/supported_track: Pass, Fail
@@ -205,6 +204,8 @@
 webgl_1_test: Pass, Fail # Issue 8219
 wheelevent_test: Fail # Issue: 7414
 xhr_test/xhr_requestBlob: Fail # Issue: 9178 Safari doesn't support Blob responses.
+canvasrenderingcontext2d_test/drawImage_video_element: Fail # Safari does not support drawImage w/ video element
+canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Safari does not support drawImage w/ video element
 
 # Safari Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
@@ -227,8 +228,6 @@
 touchevent_test/supported: Fail
 
 [ $runtime == opera ]
-audiobuffersourcenode_test: Fail
-audiocontext_test: Fail
 blob_constructor_test: Fail
 canvas_test: Fail
 canvas_test: Pass,Fail
@@ -257,6 +256,8 @@
 
 # Opera Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
+audiobuffersourcenode_test/supported: Fail
+audiocontext_test/supported: Fail
 crypto_test/supported: Fail
 css_test/supported_CssMatrix: Fail
 css_test/supported_DomPoint: Fail
@@ -272,15 +273,16 @@
 websql_test/supported: Fail
 
 [ $runtime == ff ]
-audiobuffersourcenode_test: Fail # FF only has Audio element.
-audiocontext_test: Fail      # FF only has Audio element
 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
-postmessage_structured_test: Fail
+postmessage_structured_test/typed_arrays: Fail # FF incorrectly clones arrays.
+canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Firefox does not like dataUrl videos for drawImage
 
 # FireFox Feature support statuses-
 # All changes should be accompanied by platform support annotation changes.
+audiobuffersourcenode_test/supported: Fail
+audiocontext_test/supported: Fail
 crypto_test/supported: Fail
 css_test/supported_CssMatrix: Fail
 css_test/supported_DomPoint: Fail
diff --git a/tests/html/indexeddb_1_test.dart b/tests/html/indexeddb_1_test.dart
index 3505c2e..7fb41fb 100644
--- a/tests/html/indexeddb_1_test.dart
+++ b/tests/html/indexeddb_1_test.dart
@@ -5,12 +5,16 @@
 import 'dart:html' as html;
 import 'dart:indexed_db' as idb;
 
-const String DB_NAME = 'Test';
 const String STORE_NAME = 'TEST';
 const int VERSION = 1;
 
+var databaseNameIndex = 0;
+String nextDatabaseName() {
+  return 'Test1_${databaseNameIndex++}';
+}
+
 Future testUpgrade() {
-  var dbName = 'version_db';
+  var dbName = nextDatabaseName();
   var upgraded = false;
 
   // Delete any existing DBs.
@@ -34,7 +38,10 @@
 }
 
 testReadWrite(key, value, matcher,
-    [dbName = DB_NAME, storeName = STORE_NAME, version = VERSION]) => () {
+    [dbName, storeName = STORE_NAME, version = VERSION]) => () {
+  if (dbName == null) {
+    dbName = nextDatabaseName();
+  }
   createObjectStore(e) {
     var store = e.target.result.createObjectStore(storeName);
     expect(store, isNotNull);
@@ -59,11 +66,15 @@
       if (db != null) {
         db.close();
       }
+      return html.window.indexedDB.deleteDatabase(dbName);
     });
 };
 
 testReadWriteTyped(key, value, matcher,
-    [dbName = DB_NAME, storeName = STORE_NAME, version = VERSION]) => () {
+    [dbName, storeName = STORE_NAME, version = VERSION]) => () {
+  if (dbName == null) {
+    dbName = nextDatabaseName();
+  }
   void createObjectStore(e) {
     var store = e.target.result.createObjectStore(storeName);
     expect(store, isNotNull);
@@ -90,6 +101,7 @@
       if (db != null) {
         db.close();
       }
+      return html.window.indexedDB.deleteDatabase(dbName);
     });
 };
 
diff --git a/tests/html/indexeddb_2_test.dart b/tests/html/indexeddb_2_test.dart
index 8faf23d..9a9feac3e 100644
--- a/tests/html/indexeddb_2_test.dart
+++ b/tests/html/indexeddb_2_test.dart
@@ -9,7 +9,7 @@
 
 // Write and re-read Maps: simple Maps; Maps with DAGs; Maps with cycles.
 
-const String DB_NAME = 'Test';
+const String DB_NAME = 'Test2';
 const String STORE_NAME = 'TEST';
 const int VERSION = 1;
 
diff --git a/tests/html/indexeddb_3_test.dart b/tests/html/indexeddb_3_test.dart
index 7b0b36c..5ed83ea 100644
--- a/tests/html/indexeddb_3_test.dart
+++ b/tests/html/indexeddb_3_test.dart
@@ -7,7 +7,7 @@
 
 // Read with cursor.
 
-const String DB_NAME = 'Test';
+const String DB_NAME = 'Test3';
 const String STORE_NAME = 'TEST';
 const int VERSION = 1;
 
diff --git a/tests/html/indexeddb_4_test.dart b/tests/html/indexeddb_4_test.dart
index 8cfd420..7ae6014 100644
--- a/tests/html/indexeddb_4_test.dart
+++ b/tests/html/indexeddb_4_test.dart
@@ -7,7 +7,7 @@
 
 // Test for KeyRange and Cursor.
 
-const String DB_NAME = 'Test';
+const String DB_NAME = 'Test4';
 const String STORE_NAME = 'TEST';
 const int VERSION = 1;
 
diff --git a/tests/html/instance_of_test.dart b/tests/html/instance_of_test.dart
index 30572c8..2d6069d 100644
--- a/tests/html/instance_of_test.dart
+++ b/tests/html/instance_of_test.dart
@@ -7,17 +7,17 @@
   CanvasElement canvas;
 
   canvas = new Element.tag('canvas');
-  canvas.attributes['width'] = 100;
-  canvas.attributes['height'] = 100;
+  canvas.attributes['width'] = '100';
+  canvas.attributes['height'] = '100';
   document.body.nodes.add(canvas);
 
   var isCanvasRenderingContext = predicate((x) => x is CanvasRenderingContext,
       'is a CanvasRenderingContext');
-  var isCanvasRenderingContext2D = 
+  var isCanvasRenderingContext2D =
       predicate((x) => x is CanvasRenderingContext2D,
       'is a CanvasRenderingContext2D');
   var isElement = predicate((x) => x is Element, 'is an Element');
-  var isCanvasElement = 
+  var isCanvasElement =
       predicate((x) => x is CanvasElement, 'is a CanvasElement');
   var isImageData = predicate((x) => x is ImageData, 'is an ImageData');
   //var isUint8ClampedArray =
diff --git a/tests/html/interactive_test.dart b/tests/html/interactive_test.dart
index f688ee5b..47bbe08 100644
--- a/tests/html/interactive_test.dart
+++ b/tests/html/interactive_test.dart
@@ -15,7 +15,7 @@
   useHtmlIndividualConfiguration();
 
   group('Geolocation', () {
-    futureTest('getCurrentPosition', () {
+    test('getCurrentPosition', () {
       return window.navigator.geolocation.getCurrentPosition().then(
         (position) {
           expect(position.coords.latitude, isNotNull);
@@ -24,7 +24,7 @@
         });
     });
 
-    futureTest('watchPosition', () {
+    test('watchPosition', () {
       return window.navigator.geolocation.watchPosition().first.then(
         (position) {
           expect(position.coords.latitude, isNotNull);
@@ -36,7 +36,7 @@
 
   group('MediaStream', () {
     if (MediaStream.supported) {
-      futureTest('getUserMedia', () {
+      test('getUserMedia', () {
         return window.navigator.getUserMedia(video: true).then((stream) {
           expect(stream,  isNotNull);
 
@@ -60,6 +60,37 @@
           return completer.future;
         });
       });
+
+      test('getUserMediaComplexConstructor', () {
+        return window.navigator.getUserMedia(
+            video: {'mandatory':
+                      { 'minAspectRatio': 1.333, 'maxAspectRatio': 1.334 },
+                    'optional':
+                      [{ 'minFrameRate': 60 },
+                       { 'maxWidth': 640 }]
+            }).then((stream) {
+          expect(stream,  isNotNull);
+
+          var url = Url.createObjectUrl(stream);
+          expect(url,  isNotNull);
+
+          var video = new VideoElement()
+            ..autoplay = true;
+
+          var completer = new Completer();
+          video.onError.listen((e) {
+            completer.completeError(e);
+          });
+          video.onPlaying.first.then((e) {
+            completer.complete(video);
+          });
+
+          document.body.append(video);
+          video.src = url;
+
+          return completer.future;
+        });
+      });
     }
   });
 }
diff --git a/tests/html/mutationobserver_test.dart b/tests/html/mutationobserver_test.dart
index 1886a57..9710310 100644
--- a/tests/html/mutationobserver_test.dart
+++ b/tests/html/mutationobserver_test.dart
@@ -58,20 +58,6 @@
       }, expectation);
     });
 
-    test('direct-parallel options-map', () {
-      expect(() {
-        var container = new DivElement();
-        var div1 = new DivElement();
-        var div2 = new DivElement();
-        var mutationObserver = new MutationObserver(
-            mutationCallback(2, orderedEquals([div1, div2])));
-        mutationObserver.observe(container, options: {'childList': true});
-
-        container.nodes.add(div1);
-        container.nodes.add(div2);
-      }, expectation);
-    });
-
     test('direct-parallel options-named', () {
       expect(() {
         var container = new DivElement();
@@ -100,22 +86,6 @@
       }, expectation);
     });
 
-
-    test('subtree options-map', () {
-      expect(() {
-        var container = new DivElement();
-        var div1 = new DivElement();
-        var div2 = new DivElement();
-        var mutationObserver = new MutationObserver(
-            mutationCallback(2, orderedEquals([div1, div2])));
-        mutationObserver.observe(container,
-                                 options: {'childList': true, 'subtree': true});
-
-        container.nodes.add(div1);
-        div1.nodes.add(div2);
-      }, expectation);
-    });
-
     test('subtree options-named', () {
       expect(() {
         var container = new DivElement();
diff --git a/tests/html/node_model_test.dart b/tests/html/node_model_test.dart
index 64cab4b..0e1b23a 100644
--- a/tests/html/node_model_test.dart
+++ b/tests/html/node_model_test.dart
@@ -8,8 +8,9 @@
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
 
+var stepDuration;
 Future get nextStep {
-  return new Future.delayed(new Duration());
+  return new Future.delayed(stepDuration);
 }
 
 class ModelTracker {
@@ -34,11 +35,24 @@
   void clearModel() {
     element.clearModel();
   }
+
+  void remove() {
+    element.remove();
+  }
 }
 
 main() {
   useHtmlConfiguration();
 
+  if (MutationObserver.supported) {
+    stepDuration = new Duration();
+  } else {
+    // Need to step after the tree update notifications, but on IE9 these may
+    // get polyfilled to use setTimeout(0). So use a longer timer to try to
+    // get a later callback.
+    stepDuration = new Duration(milliseconds: 15);
+  }
+
   test('basic top down', () {
     var a = new DivElement();
     var b = new SpanElement();
@@ -99,6 +113,9 @@
 
       c.clearModel();
       expect(d.model, model2);
+
+      a.remove();
+      return nextStep;
     });
   });
 
@@ -140,6 +157,9 @@
       c.clearModel();
       expect(c.models, [model, cModel, model]);
       expect(d.models, [model, cModel, model]);
+
+      a.remove();
+      return nextStep;
     });
   });
 
@@ -164,6 +184,9 @@
       expect(b.models, [aModel]);
       expect(c.models, [cModel]);
       expect(d.models, [cModel]);
+
+      a.remove();
+      return nextStep;
     });
   });
 }
diff --git a/tests/html/node_test.dart b/tests/html/node_test.dart
index 3eab98e..7a2161a 100644
--- a/tests/html/node_test.dart
+++ b/tests/html/node_test.dart
@@ -227,6 +227,18 @@
       expect(a.nodes.length, nodesLength);
     });
 
+    test('insert', () {
+      var node = new DivElement();
+      node.nodes.insert(0, new BRElement());
+      expect(node.nodes[0], isBRElement);
+      node.nodes.insert(0, new HRElement());
+      expect(node.nodes[0], isHRElement);
+      node.nodes.insert(1, new ImageElement());
+      expect(node.nodes[1], isImageElement);
+      node.nodes.insert(node.nodes.length, new InputElement());
+      expect(node.nodes.last, isInputElement);
+    });
+
     test('clear', () {
       var node = makeNodeWithChildren();
       node.nodes.clear();
diff --git a/tests/html/notifications_test.dart b/tests/html/notifications_test.dart
index dbb34eb..8e3ae43 100644
--- a/tests/html/notifications_test.dart
+++ b/tests/html/notifications_test.dart
@@ -33,8 +33,7 @@
       // Sporadically flaky on Mac Chrome. Uncomment when Issue 8482 is fixed.
       test('construct notification', () {
         var note = new Notification('this is a notification');
-        var note2 = new Notification('another notificiation',
-          {'option1': 'foo'});
+        var note2 = new Notification('another notificiation', titleDir: 'foo');
       });
       */
     }
diff --git a/tests/html/postmessage_structured_test.dart b/tests/html/postmessage_structured_test.dart
index 76860ea..ba35420 100644
--- a/tests/html/postmessage_structured_test.dart
+++ b/tests/html/postmessage_structured_test.dart
@@ -4,7 +4,7 @@
 
 library postmessage_js_test;
 import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
 import 'dart:collection';  // SplayTreeMap
 import 'utils.dart';
@@ -17,61 +17,7 @@
 }
 
 main() {
-  useHtmlConfiguration();
-
-  test('js-to-dart-postmessage', () {
-      // Pass an object literal from JavaScript. It should be seen as a Dart
-      // Map.
-
-      final JS_CODE = """
-        window.postMessage({eggs: 3}, '*');
-        """;
-      var completed = false;
-      var subscription = null;
-      subscription = window.onMessage.listen(expectAsyncUntil1(
-        (e) {
-          var data = e.data;
-          if (data is String) return;    // Messages from unit test protocol.
-          completed = true;
-          subscription.cancel();
-          expect(data, isMap);
-          expect(data['eggs'], equals(3));
-        },
-        () => completed));
-      injectSource(JS_CODE);
-    });
-
-  test('dart-to-js-to-dart-postmessage', () {
-      // Pass dictionaries between Dart and JavaScript.
-
-      final JS_CODE = """
-        window.addEventListener('message', handler);
-        function handler(e) {
-          var data = e.data;
-          if (typeof data == 'string') return;
-          if (data.recipient != 'JS') return;
-          var response = {recipient: 'DART'};
-          response[data['curry']] = 50;
-          window.removeEventListener('message', handler);
-          window.postMessage(response, '*');
-        }
-        """;
-      var completed = false;
-      var subscription = null;
-      subscription = window.onMessage.listen(expectAsyncUntil1(
-        (e) {
-          var data = e.data;
-          if (data is String) return;    // Messages from unit test protocol.
-          if (data['recipient'] != 'DART') return;  // Hearing the sent message.
-          completed = true;
-          subscription.cancel();
-          expect(data, isMap);
-          expect(data['peas'], equals(50));
-        },
-        () => completed));
-      injectSource(JS_CODE);
-      window.postMessage({'recipient': 'JS', 'curry': 'peas'}, '*');
-    });
+  useHtmlIndividualConfiguration();
 
   go(testName, value) =>
       test(testName, () {
@@ -108,34 +54,98 @@
           window.postMessage({'recipient': 'JS', 'data': value}, '*');
         });
 
-  var obj1 = {'a': 100, 'b': 's'};
-  var obj2 = {'x': obj1, 'y': obj1};  // DAG.
+  group('primitives', () {
+    test('js-to-dart-postmessage', () {
+      // Pass an object literal from JavaScript. It should be seen as a Dart
+      // Map.
 
-  var obj3 = {};
-  obj3['a'] = 100;
-  obj3['b'] = obj3;  // Cycle.
+      final JS_CODE = """
+        window.postMessage({eggs: 3}, '*');
+        """;
+      var completed = false;
+      var subscription = null;
+      subscription = window.onMessage.listen(expectAsyncUntil1(
+        (e) {
+          var data = e.data;
+          if (data is String) return;    // Messages from unit test protocol.
+          completed = true;
+          subscription.cancel();
+          expect(data, isMap);
+          expect(data['eggs'], equals(3));
+        },
+        () => completed));
+      injectSource(JS_CODE);
+    });
 
-  var obj4 = new SplayTreeMap<String, dynamic>();  // Different implementation.
-  obj4['a'] = 100;
-  obj4['b'] = 's';
+    test('dart-to-js-to-dart-postmessage', () {
+      // Pass dictionaries between Dart and JavaScript.
 
-  var cyclic_list = [1, 2, 3];
-  cyclic_list[1] = cyclic_list;
+      final JS_CODE = """
+        window.addEventListener('message', handler);
+        function handler(e) {
+          var data = e.data;
+          if (typeof data == 'string') return;
+          if (data.recipient != 'JS') return;
+          var response = {recipient: 'DART'};
+          response[data['curry']] = 50;
+          window.removeEventListener('message', handler);
+          window.postMessage(response, '*');
+        }
+        """;
+      var completed = false;
+      var subscription = null;
+      subscription = window.onMessage.listen(expectAsyncUntil1(
+        (e) {
+          var data = e.data;
+          if (data is String) return;    // Messages from unit test protocol.
+          if (data['recipient'] != 'DART') return;  // Hearing the sent message.
+          completed = true;
+          subscription.cancel();
+          expect(data, isMap);
+          expect(data['peas'], equals(50));
+        },
+        () => completed));
+      injectSource(JS_CODE);
+      window.postMessage({'recipient': 'JS', 'curry': 'peas'}, '*');
+    });
 
-  var array_buffer = new ArrayBuffer(16);
-  var view_a = new Float32Array.fromBuffer(array_buffer, 0, 4);
-  var view_b = new Uint8Array.fromBuffer(array_buffer, 1, 13);
-  var typed_arrays_list = [view_a, array_buffer, view_b];
+    var obj1 = {'a': 100, 'b': 's'};
+    var obj2 = {'x': obj1, 'y': obj1};  // DAG.
 
-  go('test_simple_list', [1, 2, 3]);
-  go('test_map', obj1);
-  go('test_DAG', obj2);
-  go('test_cycle', obj3);
-  go('test_simple_splay', obj4);
-  go('const_array_1', const [const [1], const [2]]);
-  go('const_array_dag', const [const [1], const [1]]);
-  go('array_deferred_copy', [1,2,3, obj3, obj3, 6]);
-  go('array_deferred_copy_2', [1,2,3, [4, 5, obj3], [obj3, 6]]);
-  go('cyclic_list', cyclic_list);
-  go('typed_arrays_list', typed_arrays_list);
+    var obj3 = {};
+    obj3['a'] = 100;
+    obj3['b'] = obj3;  // Cycle.
+
+    var obj4 = new SplayTreeMap<String, dynamic>();  // Different implementation.
+    obj4['a'] = 100;
+    obj4['b'] = 's';
+
+    var cyclic_list = [1, 2, 3];
+    cyclic_list[1] = cyclic_list;
+
+    go('test_simple_list', [1, 2, 3]);
+    go('test_map', obj1);
+    go('test_DAG', obj2);
+    go('test_cycle', obj3);
+    go('test_simple_splay', obj4);
+    go('const_array_1', const [const [1], const [2]]);
+    go('const_array_dag', const [const [1], const [1]]);
+    go('array_deferred_copy', [1,2,3, obj3, obj3, 6]);
+    go('array_deferred_copy_2', [1,2,3, [4, 5, obj3], [obj3, 6]]);
+    go('cyclic_list', cyclic_list);
+  });
+
+  group('typed_arrays', () {
+    var array_buffer = new ArrayBuffer(16);
+    var view_a = new Float32Array.fromBuffer(array_buffer, 0, 4);
+    var view_b = new Uint8Array.fromBuffer(array_buffer, 1, 13);
+    var typed_arrays_list = [view_a, array_buffer, view_b];
+
+    // Note that FF is failing this test because in the sent message:
+    // view_a.buffer == array_buffer
+    // But in the response:
+    // view_a.buffer != array_buffer
+    go('typed_arrays_list', typed_arrays_list);
+  });
+
 }
diff --git a/tests/html/small.mp4 b/tests/html/small.mp4
new file mode 100644
index 0000000..5bb2780
--- /dev/null
+++ b/tests/html/small.mp4
Binary files differ
diff --git a/tests/html/small.webm b/tests/html/small.webm
new file mode 100644
index 0000000..ff01e61
--- /dev/null
+++ b/tests/html/small.webm
Binary files differ
diff --git a/tests/html/xhr_cross_origin_test.dart b/tests/html/xhr_cross_origin_test.dart
index d4dbecd..cb56240 100644
--- a/tests/html/xhr_cross_origin_test.dart
+++ b/tests/html/xhr_cross_origin_test.dart
@@ -4,7 +4,7 @@
 
 library XHRCrossOriginTest;
 import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
 import 'dart:json' as json;
 
@@ -25,49 +25,69 @@
 }
 
 main() {
-  useHtmlConfiguration();
+  useHtmlIndividualConfiguration();
 
-  var port = crossOriginPort;
-
-  test('XHR Cross-domain', () {
-    var url = "http://localhost:$port/"
-              "root_dart/tests/html/xhr_cross_origin_data.txt";
-    var xhr = new HttpRequest();
-    xhr.open('GET', url, async: true);
-    var validate = expectAsync1((data) {
-      expect(data, contains('feed'));
-      expect(data['feed'], contains('entry'));
-      expect(data, isMap);
+  group('supported', () {
+    test('supported', () {
+      expect(HttpRequest.supportsCrossOrigin, isTrue);
     });
-    xhr.onReadyStateChange.listen((e) {
-      guardAsync(() {
-        if (xhr.readyState == HttpRequest.DONE) {
-          validate(json.parse(xhr.response));
-        }
+  });
+
+  group('functional', () {
+
+    var port = crossOriginPort;
+    var host = '${window.location.protocol}//${window.location.hostname}:$port';
+
+    test('XHR.get Cross-domain', () {
+      var gotError = false;
+      var url = '$host/root_dart/tests/html/xhr_cross_origin_data.txt';
+      return HttpRequest.request(url).then((xhr) {
+        var data = json.parse(xhr.response);
+        expect(data, contains('feed'));
+        expect(data['feed'], contains('entry'));
+        expect(data, isMap);
+      }).catchError((error) {}, test: (error) {
+        gotError = true;
+        // Consume errors when not supporting cross origin.
+        return !HttpRequest.supportsCrossOrigin;
+      }).whenComplete(() {
+        // Expect that we got an error when cross origin is not supported.
+        expect(gotError, !HttpRequest.supportsCrossOrigin);
       });
     });
-    xhr.send();
-  });
 
-  test('XHR.get Cross-domain', () {
-    var url = "http://localhost:$port/"
-              "root_dart/tests/html/xhr_cross_origin_data.txt";
-    HttpRequest.request(url).then(expectAsync1((xhr) {
-      var data = json.parse(xhr.response);
-      expect(data, contains('feed'));
-      expect(data['feed'], contains('entry'));
-      expect(data, isMap);
-    }));
-  });
+    // Skip the rest if not supported.
+    if (!HttpRequest.supportsCrossOrigin) {
+      return;
+    }
 
-  test('XHR.getWithCredentials Cross-domain', () {
-    var url = "http://localhost:$port/"
-              "root_dart/tests/html/xhr_cross_origin_data.txt";
-    HttpRequest.request(url, withCredentials: true).then(expectAsync1((xhr) {
-      var data = json.parse(xhr.response);
-      expect(data, contains('feed'));
-      expect(data['feed'], contains('entry'));
-      expect(data, isMap);
-    }));
+    test('XHR Cross-domain', () {
+      var url =  '$host/root_dart/tests/html/xhr_cross_origin_data.txt';
+      var xhr = new HttpRequest();
+      xhr.open('GET', url, async: true);
+      var validate = expectAsync1((data) {
+        expect(data, contains('feed'));
+        expect(data['feed'], contains('entry'));
+        expect(data, isMap);
+      });
+      xhr.onReadyStateChange.listen((e) {
+        guardAsync(() {
+          if (xhr.readyState == HttpRequest.DONE) {
+            validate(json.parse(xhr.response));
+          }
+        });
+      });
+      xhr.send();
+    });
+
+    test('XHR.getWithCredentials Cross-domain', () {
+      var url = '$host/root_dart/tests/html/xhr_cross_origin_data.txt';
+      return HttpRequest.request(url, withCredentials: true).then((xhr) {
+        var data = json.parse(xhr.response);
+        expect(data, contains('feed'));
+        expect(data['feed'], contains('entry'));
+        expect(data, isMap);
+      });
+    });
   });
 }
diff --git a/tests/isolate/compute_this_script_browser_stream_test.dart b/tests/isolate/compute_this_script_browser_stream_test.dart
new file mode 100644
index 0000000..a6f5173
--- /dev/null
+++ b/tests/isolate/compute_this_script_browser_stream_test.dart
@@ -0,0 +1,39 @@
+// 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.
+
+// Test that spawn works even when there are many script files in the page.
+// This requires computing correctly the URL to the orignal script, so we can
+// pass it to the web worker APIs.
+library compute_this_script;
+
+import 'dart:html';
+import 'dart:isolate';
+import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_config.dart';
+
+child() {
+  var sink;
+  stream.listen((msg) {
+    sink = msg;
+  }, onDone: () {
+    sink.add("done");
+    sink.close();
+  });
+}
+
+main() {
+  useHtmlConfiguration();
+  var script = new ScriptElement();
+  document.body.append(script);
+  test('spawn with other script tags in page', () {
+    var box = new MessageBox();
+    box.stream.listen(expectAsync1((msg) {
+      expect(msg, equals("done"));
+    }));
+
+    IsolateSink s = streamSpawnFunction(child);
+    s.add(box.sink);
+    s.close();
+  });
+}
diff --git a/tests/isolate/count_stream_test.dart b/tests/isolate/count_stream_test.dart
new file mode 100644
index 0000000..50119ae
--- /dev/null
+++ b/tests/isolate/count_stream_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library CountTest;
+import '../../pkg/unittest/lib/unittest.dart';
+import 'dart:isolate';
+
+void countMessages() {
+  int count = 0;
+  IsolateSink replySink;
+  bool isFirst = true;
+  stream.listen((msg) {
+    if (isFirst) {
+      replySink = msg;
+      isFirst = false;
+      return;
+    }
+    replySink.add(count);
+    count++;
+  }, onDone: () {
+    expect(count, 10);
+    replySink.close();
+  });
+}
+
+void main() {
+  test("count 10 consecutive stream messages", () {
+    int count = 0;
+    MessageBox box = new MessageBox();
+    IsolateSink remote = streamSpawnFunction(countMessages);
+    remote.add(box.sink);
+    box.stream.listen(expectAsync1((remoteCount) {
+      expect(remoteCount, count);
+      count++;
+      if (count < 10) {
+        remote.add(null);
+      } else {
+        remote.close();
+      }
+    }, count: 10), onDone: expectAsync0(() {
+      expect(count, 10);
+    }));
+    remote.add(null);
+  });
+}
diff --git a/tests/isolate/cross_isolate_message_stream_test.dart b/tests/isolate/cross_isolate_message_stream_test.dart
new file mode 100644
index 0000000..70d1345
--- /dev/null
+++ b/tests/isolate/cross_isolate_message_stream_test.dart
@@ -0,0 +1,112 @@
+// 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 that isolates can communicate to isolates
+// other than the main isolate.
+
+library CrossIsolateMessageTest;
+import 'dart:isolate';
+import '../../pkg/unittest/lib/unittest.dart';
+
+/*
+ * Everything starts in the main-isolate (in the main-method).
+ * The main isolate spawns two isolates: isolate1 (with entry point
+ * 'crossIsolate1') and isolate2 (with entry point 'crossIsolate2').
+ *
+ * The main-isolate creates a new message-box and sends its sink to both
+ * isolates. Whenever isolate1 or isolate2 send something to the main-isolate
+ * they will use this sink.
+ * Isolate2 stores the sink and replies with a new sink (sink2b) it created.
+ * Isolate1 stores the sink and waits for another message.
+ * Main receives isolate2's sink2b and sends it to isolate1.
+ * Isolate1 stores this sink as "otherIsolate" and send a new sink (sink1b) to
+ * the main isolate.
+ * Main receives sink1b and sents a message "fromMain, 42" to sink1b.
+ * isolate1 receives this message, modifies it (adding 58 to 42) and forwards
+ * it to isolate2 (otherIsolate).
+ * isolate2 receives the message, modifies it (adding 399), and sends it to
+ * the main isolate.
+ * The main-isolate receives it, verifies that the result is 499 and ends the
+ * test.
+ */
+
+void crossIsolate1() {
+  bool first = true;
+  IsolateSink mainIsolate;
+  var subscription = stream.listen((msg) {
+    if (first) {
+      first = false;
+      mainIsolate = msg;
+      return;
+    }
+    IsolateSink otherIsolate = msg;
+    MessageBox box = new MessageBox();
+    box.stream.single.then((msg) {
+      expect(msg[0], "fromMain");
+      otherIsolate.add(["fromIsolate1", msg[1] + 58]);  // 100;
+      otherIsolate.close();
+      box.stream.close();
+    });
+    mainIsolate.add(['ready1', box.sink]);
+    stream.close();
+  });
+}
+
+void crossIsolate2() {
+  var subscription;
+  subscription = stream.listen((msg) {
+    IsolateSink mainIsolate = msg;
+    MessageBox box = new MessageBox();
+    box.stream.listen((msg) {
+      expect(msg[0], "fromIsolate1");
+      mainIsolate.add(["fromIsolate2", msg[1] + 399]);  // 499;
+      mainIsolate.close();
+      box.stream.close();
+    });
+    mainIsolate.add(['ready2', box.sink]);
+    subscription.cancel();
+  });
+}
+
+main() {
+  test("share sink, and send message cross isolates ", () {
+    IsolateSink sink1 = streamSpawnFunction(crossIsolate1);
+    IsolateSink sink2 = streamSpawnFunction(crossIsolate2);
+    // Create a new sink and send it to isolate2.
+    MessageBox box = new MessageBox();
+    sink1.add(box.sink);
+    sink2.add(box.sink);
+    int msgNumber = 0;
+
+    bool isReady1 = false;
+    bool isReady2 = false;
+    bool hasSentMessage = false;
+
+    Function ready1 = expectAsync0(() => isReady1 = true);
+    Function ready2 = expectAsync0(() => isReady2 = true);
+    Function fromIsolate2 = expectAsync1((data) {
+      expect(data, 499);
+    });
+    IsolateSink sink1b;
+    IsolateSink sink2b;
+
+    box.stream.listen((msg) {
+      switch (msg[0]) {
+        case 'ready1': ready1(); sink1b = msg[1]; break;
+        case 'ready2':
+          ready2();
+          sink2b = msg[1];
+          sink1.add(sink2b);
+          break;
+        case 'fromIsolate2': fromIsolate2(msg[1]); break;
+        default: throw "bad message";
+      }
+      if (isReady1 && isReady2 && !hasSentMessage) {
+        hasSentMessage = true;
+        sink1b.add(["fromMain", 42]);
+        sink1b.close();
+      }
+    });
+  });
+}
diff --git a/tests/isolate/global_error_handler2_test.dart b/tests/isolate/global_error_handler2_test.dart
new file mode 100644
index 0000000..7b6e876
--- /dev/null
+++ b/tests/isolate/global_error_handler2_test.dart
@@ -0,0 +1,41 @@
+// 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;
+
+import 'dart:async';
+import 'dart:isolate';
+
+runTest() {
+  SendPort mainIsolate;
+  bool isFirst = true;
+  port.receive((msg, replyTo) {
+    if (isFirst) {
+      mainIsolate = msg;
+      isFirst = false;
+      throw new RuntimeError("ignore exception");
+    }
+    Expect.equals("message 2", msg);
+    mainIsolate.send("received");
+  });
+}
+
+bool globalErrorHandler(IsolateUnhandledException e) {
+  return e.source is RuntimeError && e.source.message == "ignore exception";
+}
+
+main() {
+  // Make sure this test doesn't last longer than 2 seconds.
+  var timer = new Timer(const Duration(seconds: 2), () { throw "failed"; });
+
+  var port = new ReceivePort();
+  SendPort otherIsolate = spawnFunction(runTest, globalErrorHandler);
+  otherIsolate.send(port.toSendPort());
+  otherIsolate.send("message 2");
+  port.receive((msg, replyPort) {
+    Expect.equals("received", msg);
+    port.close();
+    timer.cancel();
+  });
+}
diff --git a/tests/isolate/global_error_handler_stream2_test.dart b/tests/isolate/global_error_handler_stream2_test.dart
new file mode 100644
index 0000000..db07be7
--- /dev/null
+++ b/tests/isolate/global_error_handler_stream2_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test;
+
+import 'dart:async';
+import 'dart:isolate';
+
+runTest() {
+  IsolateSink mainIsolate;
+  stream.listen((msg) {
+    mainIsolate = msg;
+    throw new RuntimeError("ignore exception");
+  }, onDone: () {
+    mainIsolate.add("received done");
+    mainIsolate.close();
+  });
+}
+
+bool globalErrorHandler(IsolateUnhandledException e) {
+  var source = e.source;
+  if (source is AsyncError) {
+    source = source.error;
+  }
+  return source is RuntimeError && source.message == "ignore exception";
+}
+
+main() {
+  var keepRunningBox = new MessageBox();
+  // Make sure this test doesn't last longer than 2 seconds.
+  var timer = new Timer(const Duration(seconds: 2), () { throw "failed"; });
+
+  var box = new MessageBox();
+  IsolateSink otherIsolate = streamSpawnFunction(runTest, globalErrorHandler);
+  otherIsolate.add(box.sink);
+  // The previous event should have been handled entirely, but the current
+  // implementations don't guarantee that and might mix the done event with
+  // the handling of the previous event. We therefore delay the closing.
+  // Note: if the done is sent too early it won't lead to failing tests, but
+  // just won't make sure that the globalErrorHandler works.
+  new Timer(const Duration(milliseconds: 10), otherIsolate.close);
+  box.stream.single.then((msg) {
+    Expect.equals("received done", msg);
+    timer.cancel();
+    keepRunningBox.stream.close();
+  });
+}
diff --git a/tests/isolate/global_error_handler_stream_test.dart b/tests/isolate/global_error_handler_stream_test.dart
new file mode 100644
index 0000000..5c09487
--- /dev/null
+++ b/tests/isolate/global_error_handler_stream_test.dart
@@ -0,0 +1,47 @@
+// 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;
+
+import 'dart:async';
+import 'dart:isolate';
+
+var firstFunction;
+var finishFunction;
+
+void runFunctions() {
+  try {
+    firstFunction();
+  } catch (e) {
+    new Timer(Duration.ZERO, finishFunction);
+    throw;
+  }
+}
+
+void startTest(StreamSink finishSink) {
+  firstFunction = () { throw new RuntimeError("ignore exception"); };
+  finishFunction = () { finishSink.add("done"); finishSink.close(); };
+  new Timer(Duration.ZERO, runFunctions);
+}
+
+runTest() {
+  stream.single.then(startTest);
+}
+
+bool globalErrorHandler(IsolateUnhandledException e) {
+  return e.source is RuntimeError && e.source.message == "ignore exception";
+}
+
+main() {
+  var box = new MessageBox();
+  var timer;
+  StreamSink otherIsolate = streamSpawnFunction(runTest, globalErrorHandler);
+  otherIsolate.add(box.sink);
+  otherIsolate.close();
+  box.stream.single.then((msg) {
+    box.stream.close();
+    timer.cancel();
+  });
+  timer = new Timer(const Duration(seconds: 2), () { throw "failed"; });
+}
diff --git a/tests/isolate/global_error_handler_test.dart b/tests/isolate/global_error_handler_test.dart
index cbb659a..a4acbac 100644
--- a/tests/isolate/global_error_handler_test.dart
+++ b/tests/isolate/global_error_handler_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+library test;
+
 import 'dart:async';
 import 'dart:isolate';
 
diff --git a/tests/isolate/illegal_msg_stream_test.dart b/tests/isolate/illegal_msg_stream_test.dart
new file mode 100644
index 0000000..663572b
--- /dev/null
+++ b/tests/isolate/illegal_msg_stream_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test;
+
+import 'dart:isolate';
+
+funcFoo(x) => x + 2;
+
+foo() {
+  stream.single.then((msg) {
+    IsolateSink sink = msg;
+    sink.add(499);
+    sink.close();
+  });
+}
+
+main() {
+  var box = new MessageBox();
+  var snd = streamSpawnFunction(foo);
+  var caught_exception = false;
+  try {
+    snd.add(funcFoo);
+  } catch (e) {
+    caught_exception = true;
+  }
+  snd.add(box.sink);
+  snd.close();
+
+  box.stream.single.then((msg) {
+    Expect.equals(499, msg);
+  });
+}
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index d6d1368..de88329 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -8,12 +8,14 @@
 serialization_test: Skip  # tests dart2js-specific serialization code
 spawn_uri_test: Fail, OK # test uses a ".js" suffix that is bogus on vm.
 compute_this_script_browser_test: Skip # browser specific test
+compute_this_script_browser_stream_test: Skip # browser specific test
 ports_compilation_browser_test: Skip # browser specific test
-timer_not_available_test: Fail, OK # only meant to test when there is no way to
-                                   # implement timer (currently only in d8)
-timer_isolate_test: Skip # See Issue 4997
 unresolved_ports_negative_test: Skip # See Issue 6839
 global_error_handler_test: Fail # See Issue 9013.
+global_error_handler_stream_test: Fail # See Issue 9013.
+
+[ $runtime == vm && $system == windows ]
+timer_test: Pass, Fail # See Issue 5133
 
 [ $compiler == none && $runtime == drt ]
 isolate2_negative_test: Skip  # Inherited from VM.
@@ -23,10 +25,6 @@
 spawn_uri_negative_test: Skip # ditto
 spawn_uri_vm_test: Skip # not implemented in dartium yet.
 spawn_uri_vm_negative_test: Skip
-timer_isolate_test: Skip # See Issue 4997
-timer_not_available_test: Skip # only meant to test when there is no way to
-                               # implement timer (currently only in d8)
-global_error_handler_test: Fail # See Issue 9013.
 
 [ $compiler == dartc ]
 isolate_negative_test: Fail    # status change with --check-only
@@ -41,12 +39,21 @@
 compute_this_script_browser_test: Pass
 
 
+[ $compiler == dart2js && ($runtime == d8 || $jscl) ]
+illegal_msg_stream_test: Fail # Issue 6750
+
+[ $compiler == dart2js && $browser ]
+illegal_msg_stream_test: Fail, Pass # Issue 6750
+
 [ $compiler == dart2js ]
 serialization_test: Fail # Tries to access class TestingOnly declared in isolate_patch.dart
 illegal_msg_test: Fail # Issue 6750
+stream_mangling_test: Fail # Issue 9245
 
-[ $compiler == dart2js ]
 global_error_handler_test: Pass, Fail # http://dartbug.com/9012 and http://dartbug.com/9024
+global_error_handler_stream_test: Pass, Fail # http://dartbug.com/9012 and http://dartbug.com/9024
+global_error_handler2_test: Pass, Fail # http://dartbug.com/9012 and http://dartbug.com/9024
+global_error_handler_stream2_test: Pass, Fail # http://dartbug.com/9012 and http://dartbug.com/9024
 
 [ $runtime == safari ]
 cross_isolate_message_test: Skip      # Depends on 32/64 bit Safari. See Issue 1120
@@ -54,12 +61,6 @@
 mixed2_test: Pass,Fail              # Depends on 32/64 bit Safari. See Issue 1120
 message_test: Skip
 
-[ $runtime == ff ]
-# FF setTimeout can fire early: https://bugzilla.mozilla.org/show_bug.cgi?id=291386
-multiple_timer_test: Pass, Fail
-timer_isolate_test: Pass, Fail
-timer_test: Pass, Fail
-
 # TODO(ager): Update these.
 [ $runtime == ie9 && $system == windows ]
 v2*: Skip
@@ -74,35 +75,21 @@
 *: Skip
 
 [ $runtime == opera ]
-multiple_timer_test: Pass, Fail
 isolate2_negative_test: Skip # Timeout.
 unresolved_ports_negative_test: Skip # See Issue 6839
 
-[ $runtime == opera && $system == windows]
-# TODO(efortuna): Investigate.
-timer_test: Fail, Pass
-
 [ $compiler == dart2js && $browser ]
 spawn_uri_test: Skip # dart2js does not support spawnUri yet
 spawn_uri_negative_test: Skip # ditto
 spawn_uri_vm_test: Skip # test uses a ".dart" suffix that only works in vm.
 spawn_uri_vm_negative_test: Skip # ditto above.
-timer_not_available_test: Fail, OK # only meant to test when there is no way to
-                                   # implement timer (currently only in d8)
 isolate2_negative_test: Fail, Pass # Issue 7769
 
 [ $compiler == dart2js && $jscl ]
-multiple_timer_test: Fail,OK # Needs Timer to run.
 spawn_uri_negative_test: Pass # for the wrong reasons (not supported in d8)
 spawn_uri_test: Fail, OK # loading another file is not supported in d8
 spawn_uri_vm_negative_test: Skip # ditto above.
 spawn_uri_vm_test: Skip # test uses a ".dart" suffix that only works in vm.
-timer_cancel_test: Fail,OK # Needs Timer to run.
-timer_cancel1_test: Fail,OK # Needs Timer to run.
-timer_cancel2_test: Fail,OK # Needs Timer to run.
-timer_isolate_test: Fail, OK # Needs Timer to run.
-timer_repeat_test: Fail,OK # Needs Timer to run.
-timer_test: Fail,OK # Needs Timer to run.
 
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
diff --git a/tests/isolate/isolate_complex_messages_stream_test.dart b/tests/isolate/isolate_complex_messages_stream_test.dart
new file mode 100644
index 0000000..219b289
--- /dev/null
+++ b/tests/isolate/isolate_complex_messages_stream_test.dart
@@ -0,0 +1,78 @@
+// 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 isolate communication with
+// complex messages.
+
+library IsolateComplexMessagesTest;
+import 'dart:isolate';
+import '../../pkg/unittest/lib/unittest.dart';
+
+main() {
+  test("complex messages are serialized correctly", () {
+    var box = new MessageBox();
+    IsolateSink remote = streamSpawnFunction(logMessages);
+    remote.add(1);
+    remote.add("Hello");
+    remote.add("World");
+    remote.add(const [null, 1, 2, 3, 4]);
+    remote.add(const [1, 2.0, true, false, 0xffffffffff]);
+    remote.add(const ["Hello", "World", 0xffffffffff]);
+    remote.add(box.sink);
+    remote.close();
+    box.stream.single.then((message) {
+      expect(message, 7);
+    });
+  });
+}
+
+
+void logMessages() {
+  int count = 0;
+  IsolateSink replySink;
+
+  stream.listen((message) {
+    switch (count) {
+      case 0:
+        expect(message, 1);
+        break;
+      case 1:
+        expect(message, "Hello");
+        break;
+      case 2:
+        expect(message, "World");
+        break;
+      case 3:
+        expect(message.length, 5);
+        expect(message[0], null);
+        expect(message[1], 1);
+        expect(message[2], 2);
+        expect(message[3], 3);
+        expect(message[4], 4);
+        break;
+      case 4:
+        expect(message.length, 5);
+        expect(message[0], 1);
+        expect(message[1], 2.0);
+        expect(message[2], true);
+        expect(message[3], false);
+        expect(message[4], 0xffffffffff);
+        break;
+      case 5:
+        expect(message.length, 3);
+        expect(message[0], "Hello");
+        expect(message[1], "World");
+        expect(message[2], 0xffffffffff);
+        break;
+      case 6:
+        replySink = message;
+        break;
+    }
+    count++;
+  },
+  onDone: () {
+    replySink.add(count);
+    replySink.close();
+  });
+}
diff --git a/tests/isolate/mandel_isolate_stream_test.dart b/tests/isolate/mandel_isolate_stream_test.dart
new file mode 100644
index 0000000..302696e
--- /dev/null
+++ b/tests/isolate/mandel_isolate_stream_test.dart
@@ -0,0 +1,153 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library MandelIsolateTest;
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:math';
+import '../../pkg/unittest/lib/unittest.dart';
+
+const TERMINATION_MESSAGE = -1;
+const N = 100;
+const ISOLATES = 20;
+
+main() {
+  test("Render Mandelbrot in parallel", () {
+    final state = new MandelbrotState();
+    state._validated.future.then(expectAsync1((result) {
+      expect(result, isTrue);
+    }));
+    for (int i = 0; i < min(ISOLATES, N); i++) state.startClient(i);
+  });
+}
+
+
+class MandelbrotState {
+
+  MandelbrotState() {
+    _result = new List<List<int>>(N);
+    _lineProcessedBy = new List<LineProcessorClient>(N);
+    _sent = 0;
+    _missing = N;
+    _validated = new Completer<bool>();
+  }
+
+  void startClient(int id) {
+    assert(_sent < N);
+    final client = new LineProcessorClient(this, id);
+    client.processLine(_sent++);
+  }
+
+  void notifyProcessedLine(LineProcessorClient client, int y, List<int> line) {
+    assert(_result[y] == null);
+    _result[y] = line;
+    _lineProcessedBy[y] = client;
+
+    if (_sent != N) {
+      client.processLine(_sent++);
+    } else {
+      client.shutdown();
+    }
+
+    // If all lines have been computed, validate the result.
+    if (--_missing == 0) {
+      _printResult();
+      _validateResult();
+    }
+  }
+
+  void _validateResult() {
+    // TODO(ngeoffray): Implement this.
+    _validated.complete(true);
+  }
+
+  void _printResult() {
+    var output = new StringBuffer();
+    for (int i = 0; i < _result.length; i++) {
+      List<int> line = _result[i];
+      for (int j = 0; j < line.length; j++) {
+        if (line[j] < 10) output.write("0");
+        output.write(line[j]);
+      }
+      output.write("\n");
+    }
+    // print(output);
+  }
+
+  List<List<int>> _result;
+  List<LineProcessorClient> _lineProcessedBy;
+  int _sent;
+  int _missing;
+  Completer<bool> _validated;
+}
+
+
+class LineProcessorClient {
+
+  LineProcessorClient(MandelbrotState this._state, int this._id) {
+    _sink = streamSpawnFunction(processLines);
+    _box = new MessageBox();
+    _sink.add(_box.sink);
+    _box.stream.listen((List<int> message) {
+      _state.notifyProcessedLine(this, _currentLine, message);
+    });
+  }
+
+  void processLine(int y) {
+    _currentLine = y;
+    _sink.add(y);
+  }
+
+  void shutdown() {
+    _sink.close();
+    _box.stream.close();
+  }
+
+  MandelbrotState _state;
+  int _id;
+  IsolateSink _sink;
+  int _currentLine;
+  MessageBox _box;
+}
+
+List<int> processLine(int y) {
+  double inverseN = 2.0 / N;
+  double Civ = y * inverseN - 1.0;
+  List<int> result = new List<int>(N);
+  for (int x = 0; x < N; x++) {
+    double Crv = x * inverseN - 1.5;
+
+    double Zrv = Crv;
+    double Ziv = Civ;
+
+    double Trv = Crv * Crv;
+    double Tiv = Civ * Civ;
+
+    int i = 49;
+    do {
+      Ziv = (Zrv * Ziv) + (Zrv * Ziv) + Civ;
+      Zrv = Trv - Tiv + Crv;
+
+      Trv = Zrv * Zrv;
+      Tiv = Ziv * Ziv;
+    } while (((Trv + Tiv) <= 4.0) && (--i > 0));
+
+    result[x] = i;
+  }
+  return result;
+}
+
+void processLines() {
+  bool isFirst = true;
+  IsolateSink replyTo;
+
+  stream.listen((message) {
+    if (isFirst) {
+      isFirst = false;
+      replyTo = message;
+      return;
+    }
+    replyTo.add(processLine(message));
+  });
+}
diff --git a/tests/isolate/message_stream2_test.dart b/tests/isolate/message_stream2_test.dart
new file mode 100644
index 0000000..c9a6a67
--- /dev/null
+++ b/tests/isolate/message_stream2_test.dart
@@ -0,0 +1,76 @@
+// 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 serialization of messages.
+// VMOptions=--enable_type_checks --enable_asserts
+
+library Message2Test;
+import 'dart:isolate';
+import '../../pkg/unittest/lib/unittest.dart';
+
+// ---------------------------------------------------------------------------
+// Message passing test 2.
+// ---------------------------------------------------------------------------
+
+class MessageTest {
+  static void mapEqualsDeep(Map expected, Map actual) {
+    expect(expected, isMap);
+    expect(actual, isMap);
+    expect(actual.length, expected.length);
+    testForEachMap(key, value) {
+      if (value is List) {
+        listEqualsDeep(value, actual[key]);
+      } else {
+        expect(actual[key], value);
+      }
+    }
+    expected.forEach(testForEachMap);
+  }
+
+  static void listEqualsDeep(List expected, List actual) {
+    for (int i = 0; i < expected.length; i++) {
+      if (expected[i] is List) {
+        listEqualsDeep(expected[i], actual[i]);
+      } else if (expected[i] is Map) {
+        mapEqualsDeep(expected[i], actual[i]);
+      } else {
+        expect(actual[i], expected[i]);
+      }
+    }
+  }
+}
+
+void pingPong() {
+  bool isFirst = true;
+  IsolateSink replyTo;
+  stream.listen((var message) {
+    if (isFirst) {
+      isFirst = false;
+      replyTo = message;
+      return;
+    }
+    // Bounce the received object back so that the sender
+    // can make sure that the object matches.
+    replyTo.add(message);
+  });
+}
+
+main() {
+  test("map is equal after it is sent back and forth", () {
+    IsolateSink remote = streamSpawnFunction(pingPong);
+    Map m = new Map();
+    m[1] = "eins";
+    m[2] = "deux";
+    m[3] = "tre";
+    m[4] = "four";
+    MessageBox box = new MessageBox();
+    remote.add(box.sink);
+    remote.add(m);
+    box.stream.listen(expectAsync1((var received) {
+      MessageTest.mapEqualsDeep(m, received);
+      remote.close();
+      box.stream.close();
+    }));
+  });
+}
diff --git a/tests/isolate/message_stream_test.dart b/tests/isolate/message_stream_test.dart
new file mode 100644
index 0000000..bfd7d4c
--- /dev/null
+++ b/tests/isolate/message_stream_test.dart
@@ -0,0 +1,144 @@
+// 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 serialization of messages.
+// VMOptions=--enable_type_checks --enable_asserts
+
+library MessageTest;
+import 'dart:isolate';
+import '../../pkg/unittest/lib/unittest.dart';
+
+// ---------------------------------------------------------------------------
+// Message passing test.
+// ---------------------------------------------------------------------------
+
+class MessageTest {
+  static const List list1 = const ["Hello", "World", "Hello", 0xfffffffffff];
+  static const List list2 = const [null, list1, list1, list1, list1];
+  static const List list3 = const [list2, 2.0, true, false, 0xfffffffffff];
+  static const Map map1 = const {
+    "a=1" : 1, "b=2" : 2, "c=3" : 3,
+  };
+  static const Map map2 = const {
+    "list1" : list1, "list2" : list2, "list3" : list3,
+  };
+  static const List list4 = const [map1, map2];
+  static const List elms = const [
+      list1, list2, list3, list4,
+  ];
+
+  static void VerifyMap(Map expected, Map actual) {
+    expect(expected, isMap);
+    expect(actual,  isMap);
+    expect(actual.length, expected.length);
+    testForEachMap(key, value) {
+      if (value is List) {
+        VerifyList(value, actual[key]);
+      } else {
+        expect(actual[key], value);
+      }
+    }
+    expected.forEach(testForEachMap);
+  }
+
+  static void VerifyList(List expected, List actual) {
+    for (int i = 0; i < expected.length; i++) {
+      if (expected[i] is List) {
+        VerifyList(expected[i], actual[i]);
+      } else if (expected[i] is Map) {
+        VerifyMap(expected[i], actual[i]);
+      } else {
+        expect(actual[i], expected[i]);
+      }
+    }
+  }
+
+  static void VerifyObject(int index, var actual) {
+    var expected = elms[index];
+    expect(expected, isList);
+    expect(actual, isList);
+    expect(actual.length, expected.length);
+    VerifyList(expected, actual);
+  }
+}
+
+pingPong() {
+  int count = 0;
+  bool isFirst = true;
+  IsolateSink replyTo;
+  stream.listen((var message) {
+    if (isFirst) {
+      isFirst = false;
+      replyTo = message;
+      return;
+    }
+    // Check if the received object is correct.
+    if (count < MessageTest.elms.length) {
+      MessageTest.VerifyObject(count, message);
+    }
+    // Bounce the received object back so that the sender
+    // can make sure that the object matches.
+    replyTo.add(message);
+    count++;
+  }, onDone: () {
+    replyTo.add(count);
+    replyTo.close();
+  });
+}
+
+main() {
+  test("send objects and receive them back", () {
+    IsolateSink remote = streamSpawnFunction(pingPong);
+    MessageBox box = new MessageBox();
+    remote.add(box.sink);
+
+    // Send objects and receive them back.
+    for (int i = 0; i < MessageTest.elms.length; i++) {
+      var sentObject = MessageTest.elms[i];
+      // TODO(asiva): remove this local var idx once thew new for-loop
+      // semantics for closures is implemented.
+      var idx = i;
+      remote.add(sentObject);
+    }
+
+    // Send recursive objects and receive them back.
+    List local_list1 = ["Hello", "World", "Hello", 0xffffffffff];
+    List local_list2 = [null, local_list1, local_list1 ];
+    List local_list3 = [local_list2, 2.0, true, false, 0xffffffffff];
+    List sendObject = new List(5);
+    sendObject[0] = local_list1;
+    sendObject[1] = sendObject;
+    sendObject[2] = local_list2;
+    sendObject[3] = sendObject;
+    sendObject[4] = local_list3;
+    remote.add(sendObject);
+
+    // Shutdown the MessageServer.
+    remote.close();
+
+    int receivedCounter = 0;
+    box.stream.listen((message) {
+      if (receivedCounter < MessageTest.elms.length) {
+        MessageTest.VerifyObject(receivedCounter, message);
+      } else if (receivedCounter == MessageTest.elms.length) {
+        var replyObject = message;
+        expect(sendObject, isList);
+        expect(replyObject, isList);
+        expect(sendObject.length, equals(replyObject.length));
+        expect(replyObject[1], same(replyObject));
+        expect(replyObject[3], same(replyObject));
+        expect(replyObject[0], same(replyObject[2][1]));
+        expect(replyObject[0], same(replyObject[2][2]));
+        expect(replyObject[2], same(replyObject[4][0]));
+        expect(replyObject[0][0], same(replyObject[0][2]));
+        // Bigint literals are not canonicalized so do a == check.
+        expect(replyObject[0][3], equals(replyObject[4][4]));
+      } else {
+        // Reply from done.
+        expect(message, MessageTest.elms.length + 1);
+      }
+      receivedCounter++;
+    });
+  });
+}
diff --git a/tests/isolate/nested_spawn_stream2_test.dart b/tests/isolate/nested_spawn_stream2_test.dart
new file mode 100644
index 0000000..d21933e
--- /dev/null
+++ b/tests/isolate/nested_spawn_stream2_test.dart
@@ -0,0 +1,80 @@
+// 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 that isolates can spawn other isolates and
+// that the nested isolates can communicate with the main once the spawner has
+// disappeared.
+
+library NestedSpawn2Test;
+import 'dart:isolate';
+import '../../pkg/unittest/lib/unittest.dart';
+
+void _call(IsolateSink sink, msg, void onreceive(m, replyTo)) {
+  final box = new MessageBox();
+  sink.add([msg, box.sink]);
+  sink.close();
+  box.stream.single.then((msg) {
+    onreceive(msg[0], msg[1]);
+  });
+}
+
+void _receive(IsolateStream stream, void onreceive(m, replyTo)) {
+  stream.single.then((msg) {
+    onreceive(msg[0], msg[1]);
+  });
+}
+
+void isolateA() {
+  _receive(stream, (msg, replyTo) {
+    expect(msg, "launch nested!");
+    IsolateSink sink = streamSpawnFunction(isolateB);
+    sink.add(replyTo);
+    sink.close();
+    stream.close();
+  });
+}
+
+String msg0 = "0 there?";
+String msg1 = "1 Yes.";
+String msg2 = "2 great. Think the other one is already dead?";
+String msg3 = "3 Give him some time.";
+String msg4 = "4 now?";
+String msg5 = "5 Now.";
+String msg6 = "6 Great. Bye";
+
+void isolateB() {
+  stream.single.then((mainPort) {
+    // Do a little ping-pong dance to give the intermediate isolate
+    // time to die.
+    _call(mainPort, msg0, ((msg, replyTo) {
+      expect(msg[0], "1");
+      _call(replyTo, msg2, ((msg, replyTo) {
+        expect(msg[0], "3");
+        _call(replyTo, msg4, ((msg, replyTo) {
+          expect(msg[0], "5");
+          replyTo.add(msg6);
+          replyTo.close();
+        }));
+      }));
+    }));
+  });
+}
+
+main() {
+  test("spawned isolate can spawn other isolates", () {
+    IsolateSink sink = streamSpawnFunction(isolateA);
+    _call(sink, "launch nested!", expectAsync2((msg, replyTo) {
+      expect(msg[0], "0");
+      _call(replyTo, msg1, expectAsync2((msg, replyTo) {
+        expect(msg[0], "2");
+        _call(replyTo, msg3, expectAsync2((msg, replyTo) {
+          expect(msg[0], "4");
+          _call(replyTo, msg5, expectAsync2((msg, replyTo) {
+            expect(msg[0], "6");
+          }));
+        }));
+      }));
+    }));
+  });
+}
diff --git a/tests/isolate/nested_spawn_stream_test.dart b/tests/isolate/nested_spawn_stream_test.dart
new file mode 100644
index 0000000..bc589ac
--- /dev/null
+++ b/tests/isolate/nested_spawn_stream_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Dart test program for testing that isolates can spawn other isolates.
+
+library NestedSpawnTest;
+import 'dart:isolate';
+import '../../pkg/unittest/lib/unittest.dart';
+
+void isolateA() {
+  IsolateSink replyTo;
+  bool isFirst = true;
+  stream.listen((msg) {
+    if (isFirst) {
+      isFirst = false;
+      replyTo = msg;
+      return;
+    }
+    expect(msg, "launch nested!");
+    IsolateSink sink = streamSpawnFunction(isolateB);
+    MessageBox box = new MessageBox();
+    sink.add(box.sink);
+    sink.add("alive?");
+    box.stream.single.then((msg) {
+      expect(msg, "and kicking");
+      replyTo.add(499);
+      replyTo.close();
+      stream.close();
+    });
+  });
+}
+
+void isolateB() {
+  IsolateSink replyTo;
+  bool isFirst = true;
+  stream.listen((msg) {
+    if (isFirst) {
+      isFirst = false;
+      replyTo = msg;
+      return;
+    }
+    expect(msg, "alive?");
+    replyTo.add("and kicking");
+    replyTo.close();
+    stream.close();
+  });
+}
+
+
+main() {
+  test("spawned isolates can spawn nested isolates", () {
+    MessageBox box = new MessageBox();
+    IsolateSink sink = streamSpawnFunction(isolateA);
+    sink.add(box.sink);
+    sink.add("launch nested!");
+    box.stream.single.then(expectAsync1((msg) {
+      expect(msg, 499);
+    }));
+  });
+}
diff --git a/tests/language/cascade_in_expression_function_test.dart b/tests/language/cascade_in_expression_function_test.dart
index 51e02ef..2c5852f 100644
--- a/tests/language/cascade_in_expression_function_test.dart
+++ b/tests/language/cascade_in_expression_function_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 // Dart test program for testing throw statement
 
+makeMap() => new Map()..[3] = 4 ..[0] = 11;
+
 class MyClass {
   foo() => this..bar(3)..baz(4);
   bar(x) => x;
@@ -12,4 +14,7 @@
 main() {
   var o = new MyClass();
   Expect.equals(o.foo(), o);
+  var g = makeMap();
+  Expect.equals(g[3], 4);
+  Expect.equals(g[0], 11);
 }
diff --git a/tests/language/class_cycle_test.dart b/tests/language/class_cycle_test.dart
index e75c545..e41181e 100644
--- a/tests/language/class_cycle_test.dart
+++ b/tests/language/class_cycle_test.dart
@@ -19,6 +19,8 @@
 , C  /// 02: compile-time error
 {}
 
+// Spec says: It is a compile-time error if the superclass
+// of a class C appears in the implements clause of C.
 class ExtendsC extends C
 implements C  /// 03: compile-time error
 {}
diff --git a/tests/language/duplicate_interface_lib.dart b/tests/language/duplicate_interface_lib.dart
new file mode 100644
index 0000000..4602bcda
--- /dev/null
+++ b/tests/language/duplicate_interface_lib.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Check fail because of cycles in super class relationship.
+
+library Interface_Lib;
+
+class InterfA { }
+
+class InterfB { }
+
diff --git a/tests/language/duplicate_interface_negative_test.dart b/tests/language/duplicate_interface_negative_test.dart
new file mode 100644
index 0000000..444c02b
--- /dev/null
+++ b/tests/language/duplicate_interface_negative_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Check fail because of cycles in super class relationship.
+
+library duplicateInterfaceNegativeTest;
+
+import "duplicate_interface_lib.dart" as alib;
+import "duplicate_interface_lib.dart" show InterfA;
+
+
+// Expect error since InterfA and alib.InterfA refer to the same interface.
+class Foo implements InterfA, alib.InterfA { } /// compile-time error
+
+
+main() {
+  Expect.isTrue(new Foo() is InterfA);
+  Expect.isTrue(new Foo() is alib.InterfA);
+}
+
diff --git a/tests/language/duplicate_interface_test.dart b/tests/language/duplicate_interface_test.dart
new file mode 100644
index 0000000..5553a5e
--- /dev/null
+++ b/tests/language/duplicate_interface_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Check fail because of cycles in super class relationship.
+
+library duplicateInterfaceTest;
+
+import "duplicate_interface_lib.dart" as alib;
+
+class InterfB { }
+
+// Ok since InterfB and alib.InterfB are not the same interface
+class Foo implements InterfB , alib.InterfB { }
+
+
+main() {
+  Expect.isTrue(new Foo() is InterfB);
+  Expect.isTrue(new Foo() is alib.InterfB);
+}
+
diff --git a/tests/language/getter_no_setter2_test.dart b/tests/language/getter_no_setter2_test.dart
index f42cda6..c7b8859 100644
--- a/tests/language/getter_no_setter2_test.dart
+++ b/tests/language/getter_no_setter2_test.dart
@@ -10,11 +10,11 @@
     {
       bool flag_exception = false;
       try {
-        nextVar++;
+        nextVar++;  /// 03: static type warning
       } catch (excpt) {
         flag_exception = true;
       }
-      Expect.isTrue(flag_exception);
+      Expect.isTrue(flag_exception);  /// 03: continued
     }
     {
       bool flag_exception = false;
@@ -27,7 +27,7 @@
     }
   }
   static test() {
-    nextVar++;  /// 01: compile-time error
+    nextVar++;  /// 01: runtime error
     this.nextVar++;  /// 02: compile-time error
   }
 }
diff --git a/tests/language/language.status b/tests/language/language.status
index c767089..b323119 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -59,7 +59,6 @@
 on_catch_malformed_type_test: Fail # Issue 8601
 
 mixin_mixin_test: Fail
-mixin_lib_extends_field_test: Fail
 
 type_variable_field_initializer_closure_test: Crash # issue 8847
 
@@ -98,6 +97,8 @@
 list_literal1_negative_test: Fail
 map_literal1_negative_test: Fail
 
+mixin_type_parameters_errors_test/03: Fail
+mixin_type_parameters_errors_test/04: Fail
 
 # test issue 8129
 redirecting_factory_infinite_steps_test/01: Fail
@@ -154,7 +155,7 @@
 field_method4_negative_test: Fail  # Runtime only test, rewrite as multitest
 
 getter_no_setter_test/01: Fail # Fails to detect compile-time error.
-getter_no_setter2_test/01: Fail # Fails to detect compile-time error.
+getter_no_setter2_test/03: Fail  # Issue 9378
 instance_call_wrong_argument_count_negative_test: Fail # Runtime only test, rewrite as multitest
 type_annotation_test/02: Fail # Issue 6974
 type_annotation_test/07: Fail # Issue 6974
@@ -354,6 +355,9 @@
 
 on_catch_malformed_type_test: Fail # Issue 8601
 
+# False positive compile-time error is masking expected compile-time error
+mixin_type_parameters_errors_test/*: Skip
+
 # Mixins fail on the VM.
 mixin_mixin_test: Fail                      # VM issue
 mixin_illegal_constructor_test/none: Fail   # VM issue
@@ -405,7 +409,6 @@
 final_syntax_test/03: Fail # http://dartbug.com/5519
 final_syntax_test/04: Fail # http://dartbug.com/5519
 getter_no_setter_test/01: Fail # http://dartbug.com/5519
-getter_no_setter2_test/01: Fail # http://dartbug.com/5519
 isnot_malformed_type_test/01: Fail # http://dartbug.com/5519
 method_override2_test/01: Fail # http://dartbug.com/5519
 named_parameters_aggregated_test/01: Fail # http://dartbug.com/5519
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 356649c..f288df9 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -41,6 +41,7 @@
 mixin_type_parameters_mixin_extends_test: Fail # http://dartbug.com/8116
 mixin_type_parameters_mixin_test: Fail # http://dartbug.com/8116
 
+
 prefix16_test: Fail # dartbug.com/7354
 default_factory2_test/01: Pass # For the wrong reasons.
 type_variable_scope_test/none: Fail
@@ -63,6 +64,7 @@
 type_annotation_test/09: Fail # Named constructors interpreted as a type.
 prefix15_test: Fail # Issue 5022
 local_function2_test: Fail # Issue 5022
+number_identity_test: Fail # Issue 9249
 
 [ $compiler == dart2js && $unchecked ]
 default_factory2_test/01: Fail # type arguments on redirecting factory not implemented
@@ -124,7 +126,6 @@
 bad_constructor_test/06: Fail # http://dartbug.com/5519
 call_nonexistent_constructor_test: Fail
 constructor_named_arguments_test/01: Fail # http://dartbug.com/5519
-getter_no_setter2_test/01: Fail # http://dartbug.com/5519
 getter_no_setter_test/01: Fail # http://dartbug.com/5519
 isnot_malformed_type_test/01: Fail # http://dartbug.com/5519
 not_enough_positional_arguments_test/01: Fail # http://dartbug.com/5519
@@ -199,6 +200,14 @@
 switch_label_test: Fail # error: target of continue is not a loop or switch case
 on_catch_malformed_type_test: Fail # Malformed types cause compile-time errors.
 
+# Missing compilation error for wrong number of type arguments.
+mixin_type_parameters_errors_test/01: Fail
+mixin_type_parameters_errors_test/02: Fail
+mixin_type_parameters_errors_test/05: Fail
+
+# new with wrong number of type arguments should be a runtime error.
+mixin_type_parameters_errors_test/03: Fail
+mixin_type_parameters_errors_test/04: Fail
 
 # External tests.
 external_test/01: Fail
diff --git a/tests/language/mixin_field_initializer_test.dart b/tests/language/mixin_field_initializer_test.dart
new file mode 100644
index 0000000..c179684
--- /dev/null
+++ b/tests/language/mixin_field_initializer_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for testing throw statement
+
+class S {
+  var s1 = good_stuff();
+  static good_stuff() => "Speyburn";
+}
+
+good_stuff() => "Glenfiddich";
+
+class M {
+  var m1 = good_stuff();
+  static good_stuff() => "Macallen";
+}
+
+class A extends S with M {
+  static good_stuff() => "Ardberg";
+}
+
+main() {
+  var a = new A();
+  Expect.equals("Macallen", a.m1);
+  Expect.equals("Speyburn", a.s1);
+
+  var m = new M();
+  Expect.equals("Macallen", m.m1);
+}
\ No newline at end of file
diff --git a/tests/language/mixin_lib_extends_field_test.dart b/tests/language/mixin_lib_extends_field_test.dart
index 07a8ebb..b58c44a 100644
--- a/tests/language/mixin_lib_extends_field_test.dart
+++ b/tests/language/mixin_lib_extends_field_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+library mixin_lib_extends_field_test;
+
 import "mixin_lib_extends_field_lib.dart" as L;
 
 class S {
diff --git a/tests/language/mixin_type_parameters_errors_test.dart b/tests/language/mixin_type_parameters_errors_test.dart
new file mode 100644
index 0000000..7938160
--- /dev/null
+++ b/tests/language/mixin_type_parameters_errors_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class S<T> { }
+class M<U> { }
+
+class A<X> extends S<int> with M<double> { }
+class B<U, V> extends S with M<U, V> { }  /// 01: compile-time error
+class C<A, B> extends S<A, int> with M { }  /// 02: compile-time error
+
+typedef F<X> = S<X> with M<X>;
+typedef G = S<int> with M<double, double>;  /// 05: compile-time error
+
+main() {
+  var a;
+  a = new A();
+  a = new A<int>();
+  a = new A<String, String>();  /// 03: static type warning, runtime error
+  a = new F<int>();
+  a = new F<int, String>();   /// 04: static type warning, runtime error
+} 
\ No newline at end of file
diff --git a/tests/language/operator_equals_test.dart b/tests/language/operator_equals_test.dart
new file mode 100644
index 0000000..1f0d720
--- /dev/null
+++ b/tests/language/operator_equals_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js that used to infer [:super == null:]
+// always returns an int.
+
+class A {
+  operator==(other) => 42;
+}
+
+class B extends A {
+  foo() => (super == null) + 4;
+}
+
+main() {
+  Expect.throws(() => new B().foo(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/isolate/multiple_timer_test.dart b/tests/lib/async/multiple_timer_test.dart
similarity index 70%
rename from tests/isolate/multiple_timer_test.dart
rename to tests/lib/async/multiple_timer_test.dart
index 27e429e..0a57ef0 100644
--- a/tests/isolate/multiple_timer_test.dart
+++ b/tests/lib/async/multiple_timer_test.dart
@@ -5,13 +5,21 @@
 library multiple_timer_test;
 
 import 'dart:async';
-import '../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/unittest/lib/unittest.dart';
 
 const Duration TIMEOUT1 = const Duration(seconds: 1);
 const Duration TIMEOUT2 = const Duration(seconds: 2);
 const Duration TIMEOUT3 = const Duration(milliseconds: 500);
 const Duration TIMEOUT4 = const Duration(milliseconds: 1500);
 
+// The stopwatch is more precise than the Timer. It can happen that
+// the TIMEOUT triggers *slightly* too early on the VM. So we add a millisecond
+// as safetymargin.
+// Some browsers (Firefox and IE so far) can trigger too early. So we add more
+// margin. We use identical(1, 1.0) as an easy way to know if the test is
+// compiled by dart2js.
+int get safetyMargin => identical(1, 1.0) ? 100 : 1;
+
 main() {
   test("multiple timer test", () {
     Stopwatch _stopwatch1 = new Stopwatch();
@@ -22,36 +30,28 @@
     int _message;
 
     void timeoutHandler1() {
-      // The stopwatch is more precise than the Timer. It can happen that
-      // the TIMEOUT triggers *slightly* too early.
-      expect(_stopwatch1.elapsedMilliseconds + 1,
+      expect(_stopwatch1.elapsedMilliseconds + safetyMargin,
              greaterThanOrEqualTo(TIMEOUT1.inMilliseconds));
       expect(_order[_message], 0);
       _message++;
     }
 
     void timeoutHandler2() {
-      // The stopwatch is more precise than the Timer. It can happen that
-      // the TIMEOUT triggers *slightly* too early.
-      expect(_stopwatch2.elapsedMilliseconds + 1,
+      expect(_stopwatch2.elapsedMilliseconds + safetyMargin,
              greaterThanOrEqualTo(TIMEOUT2.inMilliseconds));
       expect(_order[_message], 1);
       _message++;
     }
 
     void timeoutHandler3() {
-      // The stopwatch is more precise than the Timer. It can happen that
-      // the TIMEOUT triggers *slightly* too early.
-      expect(_stopwatch3.elapsedMilliseconds + 1,
+      expect(_stopwatch3.elapsedMilliseconds + safetyMargin,
              greaterThanOrEqualTo(TIMEOUT3.inMilliseconds));
       expect(_order[_message], 2);
       _message++;
     }
 
     void timeoutHandler4() {
-      // The stopwatch is more precise than the Timer. It can happen that
-      // the TIMEOUT triggers *slightly* too early.
-      expect(_stopwatch4.elapsedMilliseconds + 1,
+      expect(_stopwatch4.elapsedMilliseconds + safetyMargin,
              greaterThanOrEqualTo(TIMEOUT4.inMilliseconds));
       expect(_order[_message], 3);
       _message++;
diff --git a/tests/lib/async/slow_consumer3_test.dart b/tests/lib/async/slow_consumer3_test.dart
index 7f3794b..6def12f 100644
--- a/tests/lib/async/slow_consumer3_test.dart
+++ b/tests/lib/async/slow_consumer3_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.
 
-// VMOptions=--old_gen_heap_size=32
+// VMOptions=--old_gen_heap_size=64
 
 library slow_consumer3_test;
 
diff --git a/tests/lib/async/stream_periodic3_test.dart b/tests/lib/async/stream_periodic3_test.dart
index e46e29d..7f31d75 100644
--- a/tests/lib/async/stream_periodic3_test.dart
+++ b/tests/lib/async/stream_periodic3_test.dart
@@ -8,15 +8,21 @@
 import "dart:async";
 import '../../../pkg/unittest/lib/unittest.dart';
 
+// The stopwatch is more precise than the Timer. It can happen that
+// the TIMEOUT triggers *slightly* too early on the VM. So we add a millisecond
+// as safetymargin.
+// Some browsers (Firefox and IE so far) can trigger too early. So we add more
+// margin. We use identical(1, 1.0) as an easy way to know if the test is
+// compiled by dart2js.
+int get safetyMargin => identical(1, 1.0) ? 5 : 1;
+
 main() {
   test("stream-periodic3", () {
     Stopwatch watch = new Stopwatch()..start();
     Stream stream = new Stream.periodic(const Duration(milliseconds: 1),
                                         (x) => x);
     stream.take(10).listen((_) { }, onDone: expectAsync0(() {
-      int microsecs = watch.elapsedMicroseconds;
-      // Give it some slack. The Stopwatch is more precise than the timers.
-      int millis = (microsecs + 200) ~/ 1000;
+      int millis = watch.elapsedMilliseconds + safetyMargin;
       expect(millis, greaterThan(10));
     }));
   });
diff --git a/tests/lib/async/stream_periodic5_test.dart b/tests/lib/async/stream_periodic5_test.dart
index a2403b2..12a5198 100644
--- a/tests/lib/async/stream_periodic5_test.dart
+++ b/tests/lib/async/stream_periodic5_test.dart
@@ -38,9 +38,7 @@
           watch.start();
           subscription.resume();
         });
-      } else {
-        expect(ms, lessThan(100));
-      }
+      } 
     }, onDone: expectAsync0(() { }));
   });
 }
diff --git a/tests/isolate/timer_cancel1_test.dart b/tests/lib/async/timer_cancel1_test.dart
similarity index 93%
rename from tests/isolate/timer_cancel1_test.dart
rename to tests/lib/async/timer_cancel1_test.dart
index 61bb5dd..c964b15 100644
--- a/tests/isolate/timer_cancel1_test.dart
+++ b/tests/lib/async/timer_cancel1_test.dart
@@ -4,7 +4,7 @@
 
 library timer_cancel1_test;
 import 'dart:async';
-import '../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/unittest/lib/unittest.dart';
 
 main() {
   // Test that a timeout handler can cancel another.
diff --git a/tests/isolate/timer_cancel2_test.dart b/tests/lib/async/timer_cancel2_test.dart
similarity index 92%
rename from tests/isolate/timer_cancel2_test.dart
rename to tests/lib/async/timer_cancel2_test.dart
index b684af5..5908109 100644
--- a/tests/isolate/timer_cancel2_test.dart
+++ b/tests/lib/async/timer_cancel2_test.dart
@@ -5,7 +5,7 @@
 library timer_cancel2_test;
 
 import 'dart:async';
-import '../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/unittest/lib/unittest.dart';
 
 main() {
   // Test that a timeout handler can cancel itself.
diff --git a/tests/isolate/timer_cancel_test.dart b/tests/lib/async/timer_cancel_test.dart
similarity index 95%
rename from tests/isolate/timer_cancel_test.dart
rename to tests/lib/async/timer_cancel_test.dart
index 88acbb1..25c459b 100644
--- a/tests/isolate/timer_cancel_test.dart
+++ b/tests/lib/async/timer_cancel_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/unittest/lib/unittest.dart';
 
 main() {
   final ms = const Duration(milliseconds: 1);
diff --git a/tests/isolate/timer_isolate_test.dart b/tests/lib/async/timer_isolate_test.dart
similarity index 94%
rename from tests/isolate/timer_isolate_test.dart
rename to tests/lib/async/timer_isolate_test.dart
index 98f8af4..80d2220 100644
--- a/tests/isolate/timer_isolate_test.dart
+++ b/tests/lib/async/timer_isolate_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:isolate';
 import 'dart:async';
-import '../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/unittest/lib/unittest.dart';
 
 const Duration TIMEOUT = const Duration(milliseconds: 100);
 
diff --git a/tests/isolate/timer_not_available_test.dart b/tests/lib/async/timer_not_available_test.dart
similarity index 100%
rename from tests/isolate/timer_not_available_test.dart
rename to tests/lib/async/timer_not_available_test.dart
diff --git a/tests/isolate/timer_repeat_test.dart b/tests/lib/async/timer_repeat_test.dart
similarity index 94%
rename from tests/isolate/timer_repeat_test.dart
rename to tests/lib/async/timer_repeat_test.dart
index 0c299d4..e523ed4 100644
--- a/tests/isolate/timer_repeat_test.dart
+++ b/tests/lib/async/timer_repeat_test.dart
@@ -5,7 +5,7 @@
 library timer_repeat_test;
 
 import 'dart:async';
-import '../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/unittest/lib/unittest.dart';
 
 const Duration TIMEOUT = const Duration(milliseconds: 500);
 const int ITERATIONS = 5;
diff --git a/tests/isolate/timer_test.dart b/tests/lib/async/timer_test.dart
similarity index 73%
rename from tests/isolate/timer_test.dart
rename to tests/lib/async/timer_test.dart
index c2fe071..cbb317c 100644
--- a/tests/isolate/timer_test.dart
+++ b/tests/lib/async/timer_test.dart
@@ -5,7 +5,7 @@
 library timer_test;
 
 import 'dart:async';
-import '../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/unittest/lib/unittest.dart';
 
 const int STARTTIMEOUT = 1050;
 const int DECREASE = 200;
@@ -15,9 +15,14 @@
 int timeout;
 int iteration;
 
+// Some browsers (Firefox and IE so far) can trigger too early. Add a safety
+// margin. We use identical(1, 1.0) as an easy way to know if the test is
+// compiled by dart2js.
+int get safetyMargin => identical(1, 1.0) ? 100 : 1;
+
 void timeoutHandler() {
   int endTime = (new DateTime.now()).millisecondsSinceEpoch;
-  expect(endTime - startTime, greaterThanOrEqualTo(timeout));
+  expect(endTime - startTime + safetyMargin, greaterThanOrEqualTo(timeout));
   if (iteration < ITERATIONS) {
     iteration++;
     timeout = timeout - DECREASE;
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 8e729b4..4e76f32 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -2,6 +2,7 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+async/stream_periodic4_test: Pass, Fail # Issue http://dartbug.com/9367
 
 # The scalarlist library is not supported by dart2js or dart2dart yet.
 [ $compiler == dart2js  || $compiler == dart2dart ]
@@ -23,6 +24,13 @@
 async/slow_consumer_test: Fail # Timer interface not supported; dartbug.com/7728.
 async/stream_from_iterable_test: Fail # Timer interface not supported; dartbug.com/7728.
 async/stream_state_nonzero_timer_test: Fail # Timer interface not supported; dartbug.com/7728.
+async/multiple_timer_test: Fail,OK # Needs Timer to run.
+async/timer_cancel_test: Fail,OK # Needs Timer to run.
+async/timer_cancel1_test: Fail,OK # Needs Timer to run.
+async/timer_cancel2_test: Fail,OK # Needs Timer to run.
+async/timer_isolate_test: Fail, OK # Needs Timer to run.
+async/timer_repeat_test: Fail,OK # Needs Timer to run.
+async/timer_test: Fail,OK # Needs Timer to run.
 
 [ $compiler == dart2js && ($jscl || $runtime == d8) ]
 async/stream_periodic_test: Fail # Timer interface not supported; dartbug.com/7728.
@@ -34,6 +42,8 @@
 [ $compiler == dart2js && $browser ]
 crypto/sha256_test: Slow, Pass
 crypto/sha1_test: Slow, Pass
+async/timer_not_available_test: Fail, OK # only meant to test when there is no way to
+                                         # implement timer (currently only in d8)
 
 [ $compiler == dart2dart ]
 # Skip until we stabilize language tests.
@@ -48,6 +58,23 @@
  # Bug in JSC: the test only passes when being debugged.
 crypto/hmac_md5_test: Fail, Pass
 
+[ $runtime == ff ]
+# FF setTimeout can fire early: https://bugzilla.mozilla.org/show_bug.cgi?id=291386
+multiple_timer_test: Pass, Fail
+timer_isolate_test: Pass, Fail
+timer_test: Pass, Fail
+
+[ $runtime == opera ]
+async/multiple_timer_test: Pass, Fail
+
+[ $runtime == opera && $system == windows]
+# TODO(efortuna): Investigate.
+async/timer_test: Fail, Pass
+
+[ $runtime == vm ]
+async/timer_not_available_test: Fail, OK # only meant to test when there is no way to
+                                         # implement timer (currently only in d8)
+async/timer_isolate_test: Skip # See Issue 4997
 
 [ $runtime == vm || ($compiler == none && $runtime == drt) ]
 async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9001.
@@ -55,6 +82,9 @@
 
 [ $compiler == none && $runtime == drt ]
 async/deferred/deferred_api_test: Fail # http://dartbug.com/2264
+async/timer_isolate_test: Skip # See Issue 4997
+async/timer_not_available_test: Skip # only meant to test when there is no way to
+                                     # implement timer (currently only in d8)
 
 [ $arch == arm ]
 *: Skip
diff --git a/tests/standalone/io/file_error_test.dart b/tests/standalone/io/file_error_test.dart
index 59ad391..c7b07e9 100644
--- a/tests/standalone/io/file_error_test.dart
+++ b/tests/standalone/io/file_error_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 //
@@ -50,7 +50,7 @@
   Expect.throws(() => file.openSync(),
                 (e) => checkOpenNonExistentFileException(e));
 
-  var openFuture = file.open(FileMode.READ);
+  var openFuture = file.open(mode: FileMode.READ);
   openFuture.then((raf) => Expect.fail("Unreachable code"))
             .catchError((e) {
               checkOpenNonExistentFileException(e.error);
@@ -236,7 +236,7 @@
   Expect.throws(() => file.readAsStringSync(),
                 (e) => checkOpenNonExistentFileException(e));
 
-  var readAsStringFuture = file.readAsString(Encoding.ASCII);
+  var readAsStringFuture = file.readAsString(encoding: Encoding.ASCII);
   readAsStringFuture.then((data) => Expect.fail("Unreachable code"))
   .catchError((e) {
     checkOpenNonExistentFileException(e.error);
@@ -257,7 +257,7 @@
   Expect.throws(() => file.readAsLinesSync(),
                 (e) => checkOpenNonExistentFileException(e));
 
-  var readAsLinesFuture = file.readAsLines(Encoding.ASCII);
+  var readAsLinesFuture = file.readAsLines(encoding: Encoding.ASCII);
   readAsLinesFuture.then((data) => Expect.fail("Unreachable code"))
   .catchError((e) {
     checkOpenNonExistentFileException(e.error);
@@ -292,7 +292,7 @@
 
 testWriteByteToReadOnlyFile() {
   createTestFile((file, port) {
-    var openedFile = file.openSync(FileMode.READ);
+    var openedFile = file.openSync(mode: FileMode.READ);
 
     // Writing to read only file should throw an exception.
     Expect.throws(() => openedFile.writeByteSync(0),
@@ -308,7 +308,7 @@
 
 testWriteListToReadOnlyFile() {
   createTestFile((file, port) {
-    var openedFile = file.openSync(FileMode.READ);
+    var openedFile = file.openSync(mode: FileMode.READ);
 
     List data = [0, 1, 2, 3];
     // Writing to read only file should throw an exception.
@@ -325,10 +325,10 @@
 
 testTruncateReadOnlyFile() {
   createTestFile((file, port) {
-    var openedFile = file.openSync(FileMode.WRITE);
+    var openedFile = file.openSync(mode: FileMode.WRITE);
     openedFile.writeByteSync(0);
     openedFile.closeSync();
-    openedFile = file.openSync(FileMode.READ);
+    openedFile = file.openSync(mode: FileMode.READ);
 
     // Truncating read only file should throw an exception.
     Expect.throws(() => openedFile.truncateSync(0),
@@ -352,7 +352,7 @@
 
 testOperateOnClosedFile() {
   createTestFile((file, port) {
-    var openedFile = file.openSync(FileMode.READ);
+    var openedFile = file.openSync(mode: FileMode.READ);
     openedFile.closeSync();
 
     List data = [0, 1, 2, 3];
diff --git a/tests/standalone/io/file_fuzz_test.dart b/tests/standalone/io/file_fuzz_test.dart
index 9e4ff73..b210bff 100644
--- a/tests/standalone/io/file_fuzz_test.dart
+++ b/tests/standalone/io/file_fuzz_test.dart
@@ -27,7 +27,7 @@
       doItSync(f.readAsStringSync);
       doItSync(f.readAsLinesSync);
       typeMapping.forEach((k2, v2) {
-        doItSync(() => f.openSync(v2));
+        doItSync(() => f.openSync(mode: v2));
         doItSync(() => f.openWrite(mode: v2));
         doItSync(() => f.readAsStringSync(v2));
         doItSync(() => f.readAsLinesSync(v2));
@@ -70,7 +70,7 @@
   file.createSync();
   var modes = [ FileMode.READ, FileMode.WRITE, FileMode.APPEND ];
   for (var m in modes) {
-    var opened = file.openSync(m);
+    var opened = file.openSync(mode: m);
     typeMapping.forEach((k, v) {
       doItSync(() => opened.setPositionSync(v));
       doItSync(() => opened.truncateSync(v));
@@ -97,7 +97,7 @@
   var futures = [];
   var openedFiles = [];
   for (var m in modes) {
-    var opened = file.openSync(m);
+    var opened = file.openSync(mode: m);
     openedFiles.add(opened);
     typeMapping.forEach((k, v) {
         futures.add(doItAsync(() => opened.setPosition(v)));
diff --git a/tests/standalone/io/file_input_stream_test.dart b/tests/standalone/io/file_input_stream_test.dart
index babd948..b25bfc1 100644
--- a/tests/standalone/io/file_input_stream_test.dart
+++ b/tests/standalone/io/file_input_stream_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 // Testing file input stream, VM-only, standalone test.
@@ -77,7 +77,7 @@
         if (streamedBytes == 0) {
           subscription.pause();
           // Truncate the file by opening it for writing.
-          file.open(FileMode.WRITE).then((opened) {
+          file.open(mode: FileMode.WRITE).then((opened) {
             opened.close().then((_) {
                 Expect.equals(0, file.lengthSync());
                 subscription.resume();
@@ -150,7 +150,7 @@
           subscription.pause();
           // Double the length of the underlying file.
           file.readAsBytes().then((bytes) {
-            file.writeAsBytes(bytes, FileMode.APPEND).then((_) {
+            file.writeAsBytes(bytes, mode: FileMode.APPEND).then((_) {
               Expect.equals(2 * originalLength, file.lengthSync());
               subscription.resume();
             });
diff --git a/tests/standalone/io/file_invalid_arguments_test.dart b/tests/standalone/io/file_invalid_arguments_test.dart
index b4c1720..515271c 100644
--- a/tests/standalone/io/file_invalid_arguments_test.dart
+++ b/tests/standalone/io/file_invalid_arguments_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -62,7 +62,7 @@
 void testWriteByteInvalidArgs(value) {
   var port = new ReceivePort();
   String filename = getFilename("tests/vm/data/fixed_length_file");
-  var file = (new File("${filename}_out")).openSync(FileMode.WRITE);
+  var file = (new File("${filename}_out")).openSync(mode: FileMode.WRITE);
   try {
     file.writeByteSync(value);
     Expect.fail('exception expected');
@@ -86,7 +86,7 @@
 void testWriteListInvalidArgs(buffer, offset, bytes) {
   var port = new ReceivePort();
   String filename = getFilename("tests/vm/data/fixed_length_file");
-  var file = (new File("${filename}_out")).openSync(FileMode.WRITE);
+  var file = (new File("${filename}_out")).openSync(mode: FileMode.WRITE);
   try {
     file.writeListSync(buffer, offset, bytes);
     Expect.fail('exception expected');
@@ -107,34 +107,26 @@
   });
 }
 
-void testWriteStringInvalidArgs(string) {
+void testWriteStringInvalidArgs(string, encoding) {
   var port = new ReceivePort();
   String filename = getFilename("tests/vm/data/fixed_length_file");
-  var file = new File("${filename}_out");
-  file.openSync(FileMode.WRITE);
+  var file = new File("${filename}_out").openSync(mode: FileMode.WRITE);
   try {
-    file.writeString(string);
+    file.writeStringSync(string, encoding: encoding);
     Expect.fail('exception expected');
   } catch (e) {
     Expect.isTrue(e is FileIOException);
-    Expect.isTrue(e.toString().contains('writeString failed'));
   }
 
-  var errors = 0;
-  file.onError = (s) {
-    errors++;
-    Expect.isTrue(s.contains('writeString failed'));
-  };
-  var calls = 0;
-  file.onNoPendingWrites = () {
-    if (++calls > 1) Expect.fail('write list invalid argument');
-  };
-  file.writeString(string);
-  file.onClosed = () {
-    Expect.equals(1, errors);
-    port.close();
-  };
-  file.close();
+  var writeStringFuture = file.writeString(string, encoding: encoding);
+  writeStringFuture.then((ignore) {
+    Expect.fail('exception expected');
+  }).catchError((s) {
+    Expect.isTrue(s.error is FileIOException);
+    file.close().then((ignore) {
+      port.close();
+    });
+  });
 }
 
 String getFilename(String path) {
@@ -150,4 +142,5 @@
   testWriteListInvalidArgs(12, 0, 1);
   testWriteListInvalidArgs(new List(10), '0', 1);
   testWriteListInvalidArgs(new List(10), 0, '1');
+  testWriteStringInvalidArgs("Hello, world", 42);
 }
diff --git a/tests/standalone/io/file_system_links_test.dart b/tests/standalone/io/file_system_links_test.dart
index d2e6796..a1bd0af 100644
--- a/tests/standalone/io/file_system_links_test.dart
+++ b/tests/standalone/io/file_system_links_test.dart
@@ -26,6 +26,7 @@
                   FileSystemEntity.typeSync(y, followLinks: false));
     Expect.equals(FileSystemEntityType.NOT_FOUND,
                   FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
 
     new File(y).createSync();
     Expect.isTrue(new File(y).existsSync());
@@ -40,6 +41,8 @@
                   FileSystemEntity.typeSync(y, followLinks: false));
     Expect.equals(FileSystemEntityType.FILE,
                   FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
+
     new File(x).deleteSync();
     new Directory(x).createSync();
     Expect.isTrue(FileSystemEntity.isLinkSync(y));
@@ -52,11 +55,14 @@
                   FileSystemEntity.typeSync(y, followLinks: false));
     Expect.equals(FileSystemEntityType.DIRECTORY,
                   FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
+
     new File(y).deleteSync();
     Expect.isFalse(FileSystemEntity.isLinkSync(y));
     Expect.isFalse(FileSystemEntity.isLinkSync(x));
     Expect.equals(FileSystemEntityType.NOT_FOUND, FileSystemEntity.typeSync(y));
     Expect.equals(FileSystemEntityType.DIRECTORY, FileSystemEntity.typeSync(x));
+    Expect.throws(() => new Link(y).targetSync());
 
     temp.deleteSync(recursive: true);
   });
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
index 122a4cd..1583d7f 100644
--- a/tests/standalone/io/file_test.dart
+++ b/tests/standalone/io/file_test.dart
@@ -200,7 +200,7 @@
     // Read a file and check part of it's contents.
     String filename = getFilename("bin/file_test.cc");
     File file = new File(filename);
-    file.open(FileMode.READ).then((RandomAccessFile file) {
+    file.open(mode: FileMode.READ).then((RandomAccessFile file) {
       List<int> buffer = new List<int>(10);
       file.readList(buffer, 0, 5).then((bytes_read) {
         Expect.equals(5, bytes_read);
@@ -262,7 +262,7 @@
     // Read a file.
     String inFilename = getFilename("tests/vm/data/fixed_length_file");
     final File file = new File(inFilename);
-    file.open(FileMode.READ).then((openedFile) {
+    file.open(mode: FileMode.READ).then((openedFile) {
       List<int> buffer1 = new List<int>(42);
       openedFile.readList(buffer1, 0, 42).then((bytes_read) {
         Expect.equals(42, bytes_read);
@@ -276,12 +276,12 @@
               if (s[0] != '/' && s[0] != '\\' && s[1] != ':') {
                 Expect.fail("Not a full path");
               }
-              file2.open(FileMode.WRITE).then((openedFile2) {
+              file2.open(mode: FileMode.WRITE).then((openedFile2) {
                 openedFile2.writeList(buffer1, 0, bytes_read).then((ignore) {
                   openedFile2.close().then((ignore) {
                     List<int> buffer2 = new List<int>(bytes_read);
                     final File file3 = new File(outFilename);
-                    file3.open(FileMode.READ).then((openedFile3) {
+                    file3.open(mode: FileMode.READ).then((openedFile3) {
                       openedFile3.readList(buffer2, 0, 42).then((bytes_read) {
                         Expect.equals(42, bytes_read);
                         openedFile3.close().then((ignore) {
@@ -320,17 +320,17 @@
     file.createSync();
     Expect.isTrue(new File(filename).existsSync());
     List<int> buffer = content.codeUnits;
-    RandomAccessFile openedFile = file.openSync(FileMode.WRITE);
+    RandomAccessFile openedFile = file.openSync(mode: FileMode.WRITE);
     openedFile.writeListSync(buffer, 0, buffer.length);
     openedFile.closeSync();
     // Reopen the file in write mode to ensure that we overwrite the content.
-    openedFile = (new File(filename)).openSync(FileMode.WRITE);
+    openedFile = (new File(filename)).openSync(mode: FileMode.WRITE);
     openedFile.writeListSync(buffer, 0, buffer.length);
     Expect.equals(content.length, openedFile.lengthSync());
     openedFile.closeSync();
     // Open the file in append mode and ensure that we do not overwrite
     // the existing content.
-    openedFile = (new File(filename)).openSync(FileMode.APPEND);
+    openedFile = (new File(filename)).openSync(mode: FileMode.APPEND);
     openedFile.writeListSync(buffer, 0, buffer.length);
     Expect.equals(content.length * 2, openedFile.lengthSync());
     openedFile.closeSync();
@@ -353,7 +353,7 @@
       appendingOutput.close();
       appendingOutput.done.then((_) {
         File file3 = new File(filename);
-        file3.open(FileMode.READ).then((RandomAccessFile openedFile) {
+        file3.open(mode: FileMode.READ).then((RandomAccessFile openedFile) {
           openedFile.length().then((int length) {
             Expect.equals(content.length * 2, length);
             openedFile.close().then((ignore) {
@@ -416,7 +416,7 @@
       Expect.fail("Not a full path");
     }
     Expect.isTrue(new File(path).existsSync());
-    RandomAccessFile openedFile = outFile.openSync(FileMode.WRITE);
+    RandomAccessFile openedFile = outFile.openSync(mode: FileMode.WRITE);
     openedFile.writeListSync(buffer1, 0, bytes_read);
     openedFile.closeSync();
     // Now read the contents of the file just written.
@@ -450,7 +450,7 @@
     File file = new File(fileName);
     asyncTestStarted();
     file.create().then((ignore) {
-      file.open(FileMode.READ).then((RandomAccessFile openedFile) {
+      file.open(mode: FileMode.READ).then((RandomAccessFile openedFile) {
         var readByteFuture = openedFile.readByte();
         readByteFuture.then((int byte) {
           Expect.equals(-1, byte);
@@ -468,7 +468,7 @@
     final String fileName = "${tempDirectory.path}/testWriteVariousLists";
     final File file = new File(fileName);
     file.create().then((ignore) {
-      file.open(FileMode.WRITE).then((RandomAccessFile openedFile) {
+      file.open(mode: FileMode.WRITE).then((RandomAccessFile openedFile) {
         // Write bytes from 0 to 7.
         openedFile.writeList([0], 0, 1);
         openedFile.writeList(const [1], 0, 1);
@@ -629,7 +629,7 @@
   static void testTruncate() {
     File file = new File(tempDirectory.path + "/out_truncate");
     List buffer = const [65, 65, 65, 65, 65, 65, 65, 65, 65, 65];
-    file.open(FileMode.WRITE).then((RandomAccessFile openedFile) {
+    file.open(mode: FileMode.WRITE).then((RandomAccessFile openedFile) {
       openedFile.writeList(buffer, 0, 10).then((ignore) {
         openedFile.length().then((length) {
           Expect.equals(10, length);
@@ -655,7 +655,7 @@
   static void testTruncateSync() {
     File file = new File(tempDirectory.path + "/out_truncate_sync");
     List buffer = const [65, 65, 65, 65, 65, 65, 65, 65, 65, 65];
-    RandomAccessFile openedFile = file.openSync(FileMode.WRITE);
+    RandomAccessFile openedFile = file.openSync(mode: FileMode.WRITE);
     openedFile.writeListSync(buffer, 0, 10);
     Expect.equals(10, openedFile.lengthSync());
     openedFile.truncateSync(5);
@@ -670,7 +670,7 @@
     bool exceptionCaught = false;
     bool wrongExceptionCaught = false;
     File input = new File(tempDirectory.path + "/out_close_exception");
-    RandomAccessFile openedFile = input.openSync(FileMode.WRITE);
+    RandomAccessFile openedFile = input.openSync(mode: FileMode.WRITE);
     openedFile.closeSync();
     try {
       openedFile.readByteSync();
@@ -778,7 +778,7 @@
     bool wrongExceptionCaught = false;
     File file =
         new File(tempDirectory.path + "/out_buffer_out_of_bounds");
-    RandomAccessFile openedFile = file.openSync(FileMode.WRITE);
+    RandomAccessFile openedFile = file.openSync(mode: FileMode.WRITE);
     try {
       List<int> buffer = new List<int>(10);
       openedFile.readListSync(buffer, 0, 12);
@@ -872,7 +872,7 @@
 
   static void testOpenDirectoryAsFile() {
     var f = new File('.');
-    var future = f.open(FileMode.READ);
+    var future = f.open(mode: FileMode.READ);
     future.then((r) => Expect.fail('Directory opened as file'))
           .catchError((e) {});
   }
@@ -947,20 +947,20 @@
     });
     var name = getFilename("tests/vm/data/fixed_length_file");
     var f = new File(name);
-    f.readAsString(Encoding.UTF_8).then((text) {
+    f.readAsString(encoding: Encoding.UTF_8).then((text) {
       Expect.isTrue(text.endsWith("42 bytes."));
       Expect.equals(42, text.length);
       var name = getDataFilename("tests/standalone/io/read_as_text.dat");
       var f = new File(name);
-      f.readAsString(Encoding.UTF_8).then((text) {
+      f.readAsString(encoding: Encoding.UTF_8).then((text) {
         Expect.equals(6, text.length);
         var expected = [955, 120, 46, 32, 120, 10];
         Expect.listEquals(expected, text.codeUnits);
-        f.readAsString(Encoding.ISO_8859_1).then((text) {
+        f.readAsString(encoding: Encoding.ISO_8859_1).then((text) {
           Expect.equals(7, text.length);
           var expected = [206, 187, 120, 46, 32, 120, 10];
           Expect.listEquals(expected, text.codeUnits);
-          var readAsStringFuture = f.readAsString(Encoding.ASCII);
+          var readAsStringFuture = f.readAsString(encoding: Encoding.ASCII);
           readAsStringFuture.then((text) {
             Expect.fail("Non-ascii char should cause error");
           }).catchError((e) {
@@ -979,7 +979,7 @@
     });
     var name = getFilename("tests/vm/data/empty_file");
     var f = new File(name);
-    f.readAsString(Encoding.UTF_8).then((text) {
+    f.readAsString(encoding: Encoding.UTF_8).then((text) {
       port.toSendPort().send(text.length);
       return true;
     });
@@ -995,11 +995,11 @@
     Expect.equals(6, text.length);
     var expected = [955, 120, 46, 32, 120, 10];
     Expect.listEquals(expected, text.codeUnits);
-    text = new File(name).readAsStringSync(Encoding.ASCII);
+    text = new File(name).readAsStringSync(encoding: Encoding.ASCII);
     // Default replacement character is '?', char code 63.
     expected = [63, 63, 120, 46, 32, 120, 10];
     Expect.listEquals(expected, text.codeUnits);
-    text = new File(name).readAsStringSync(Encoding.ISO_8859_1);
+    text = new File(name).readAsStringSync(encoding: Encoding.ISO_8859_1);
     expected = [206, 187, 120, 46, 32, 120, 10];
     Expect.equals(7, text.length);
     Expect.listEquals(expected, text.codeUnits);
@@ -1019,7 +1019,7 @@
     });
     var name = getFilename("tests/vm/data/fixed_length_file");
     var f = new File(name);
-    f.readAsLines(Encoding.UTF_8).then((lines) {
+    f.readAsLines(encoding: Encoding.UTF_8).then((lines) {
       Expect.equals(1, lines.length);
       var line = lines[0];
       Expect.isTrue(line.endsWith("42 bytes."));
@@ -1053,10 +1053,10 @@
     var readAsBytesFuture = f.readAsBytes();
     readAsBytesFuture.then((bytes) => Expect.fail("no bytes expected"))
     .catchError((e) {
-      var readAsStringFuture = f.readAsString(Encoding.UTF_8);
+      var readAsStringFuture = f.readAsString(encoding: Encoding.UTF_8);
       readAsStringFuture.then((text) => Expect.fail("no text expected"))
       .catchError((e) {
-        var readAsLinesFuture = f.readAsLines(Encoding.UTF_8);
+        var readAsLinesFuture = f.readAsLines(encoding: Encoding.UTF_8);
         readAsLinesFuture.then((lines) => Expect.fail("no lines expected"))
         .catchError((e) {
           port.toSendPort().send(1);
@@ -1084,10 +1084,10 @@
   // that the file is not truncated when opened for appending.
   static void testAppend() {
     var file = new File('${tempDirectory.path}/out_append');
-    file.open(FileMode.WRITE).then((openedFile) {
+    file.open(mode: FileMode.WRITE).then((openedFile) {
       openedFile.writeString("asdf").then((ignore) {
         openedFile.close().then((ignore) {
-          file.open(FileMode.APPEND).then((openedFile) {
+          file.open(mode: FileMode.APPEND).then((openedFile) {
             openedFile.length().then((length) {
               Expect.equals(4, length);
               openedFile.writeString("asdf").then((ignore) {
@@ -1113,11 +1113,11 @@
 
   static void testAppendSync() {
     var file = new File('${tempDirectory.path}/out_append_sync');
-    var openedFile = file.openSync(FileMode.WRITE);
+    var openedFile = file.openSync(mode: FileMode.WRITE);
     openedFile.writeStringSync("asdf");
     Expect.equals(4, openedFile.lengthSync());
     openedFile.closeSync();
-    openedFile = file.openSync(FileMode.WRITE);
+    openedFile = file.openSync(mode: FileMode.WRITE);
     openedFile.setPositionSync(4);
     openedFile.writeStringSync("asdf");
     Expect.equals(8, openedFile.lengthSync());
@@ -1129,12 +1129,12 @@
   static void testWriteStringUtf8() {
     var file = new File('${tempDirectory.path}/out_write_string');
     var string = new String.fromCharCodes([0x192]);
-    file.open(FileMode.WRITE).then((openedFile) {
+    file.open(mode: FileMode.WRITE).then((openedFile) {
       openedFile.writeString(string).then((_) {
         openedFile.length().then((l) {
           Expect.equals(2, l);
           openedFile.close().then((_) {
-            file.open(FileMode.APPEND).then((openedFile) {
+            file.open(mode: FileMode.APPEND).then((openedFile) {
               openedFile.setPosition(2).then((_) {
                 openedFile.writeString(string).then((_) {
                   openedFile.length().then((l) {
@@ -1164,11 +1164,11 @@
   static void testWriteStringUtf8Sync() {
     var file = new File('${tempDirectory.path}/out_write_string_sync');
     var string = new String.fromCharCodes([0x192]);
-    var openedFile = file.openSync(FileMode.WRITE);
+    var openedFile = file.openSync(mode: FileMode.WRITE);
     openedFile.writeStringSync(string);
     Expect.equals(2, openedFile.lengthSync());
     openedFile.closeSync();
-    openedFile = file.openSync(FileMode.APPEND);
+    openedFile = file.openSync(mode: FileMode.APPEND);
     openedFile.setPositionSync(2);
     openedFile.writeStringSync(string);
     Expect.equals(4, openedFile.lengthSync());
diff --git a/tests/standalone/io/file_write_as_test.dart b/tests/standalone/io/file_write_as_test.dart
index fd53f07..1932b70 100644
--- a/tests/standalone/io/file_write_as_test.dart
+++ b/tests/standalone/io/file_write_as_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -11,7 +11,7 @@
   var data = [50,50,50];
   f.writeAsBytesSync(data);
   Expect.listEquals(data, f.readAsBytesSync());
-  f.writeAsBytesSync(data, FileMode.APPEND);
+  f.writeAsBytesSync(data, mode: FileMode.APPEND);
   var expected = [50, 50, 50, 50, 50, 50];
   Expect.listEquals(expected, f.readAsBytesSync());
 }
@@ -33,7 +33,7 @@
     Expect.equals(f, file);
     f.readAsBytes().then((bytes) {
       Expect.listEquals(data, bytes);
-      f.writeAsBytes(data, FileMode.APPEND).then((file) {
+      f.writeAsBytes(data, mode: FileMode.APPEND).then((file) {
         Expect.equals(f, file);
         f.readAsBytes().then((bytes) {
           var expected = [50, 50, 50, 50, 50, 50];
diff --git a/tests/standalone/io/http_proxy_configuration_test.dart b/tests/standalone/io/http_proxy_configuration_test.dart
new file mode 100644
index 0000000..b5016ee
--- /dev/null
+++ b/tests/standalone/io/http_proxy_configuration_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+import "dart:uri";
+
+expect(expected, String uri, environment) {
+  Expect.equals(expected,
+                HttpClient.findProxyFromEnvironment(Uri.parse(uri),
+                                                    environment: environment));
+}
+
+expectDirect(String uri, environment) {
+  Expect.equals("DIRECT",
+                HttpClient.findProxyFromEnvironment(Uri.parse(uri),
+                                                    environment: environment));
+}
+
+main() {
+  expectDirect("http://www.google.com", {});
+  expect("PROXY www.proxy.com:1080",
+         "http://www.google.com",
+         {"http_proxy": "www.proxy.com"});
+  expect("PROXY www.proxys.com:1080",
+         "https://www.google.com",
+         {"https_proxy": "www.proxys.com"});
+  expect("PROXY www.proxy.com:8080",
+         "http://www.google.com",
+         {"http_proxy": "www.proxy.com:8080"});
+  expect("PROXY www.proxys.com:8080",
+         "https://www.google.com",
+         {"https_proxy": "www.proxys.com:8080"});
+  expect("PROXY www.proxy.com:8080",
+         "http://www.google.com",
+         {"http_proxy": "www.proxy.com:8080",
+          "https_proxy": "www.proxy.com:8080"});
+  expect("PROXY www.proxys.com:8080",
+         "https://www.google.com",
+         {"http_proxy": "www.proxy.com:8080",
+          "https_proxy": "www.proxys.com:8080"});
+  expectDirect("http://www.google.com",
+               {"http_proxy": "www.proxy.com:8080",
+                "no_proxy": "www.google.com"});
+  expectDirect("http://www.google.com",
+               {"http_proxy": "www.proxy.com:8080",
+                "no_proxy": "google.com"});
+  expectDirect("http://www.google.com",
+               {"http_proxy": "www.proxy.com:8080",
+                "no_proxy": ".com"});
+  expectDirect("http://www.google.com",
+               {"http_proxy": "www.proxy.com:8080",
+                "no_proxy": ",,  , www.google.edu,,.com    "});
+  expectDirect("http://www.google.edu",
+               {"http_proxy": "www.proxy.com:8080",
+                "no_proxy": ",,  , www.google.edu,,.com    "});
+  expectDirect("http://www.google.com",
+               {"https_proxy": "www.proxy.com:8080"});
+}
diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart
index dd87619..945189d 100644
--- a/tests/standalone/io/http_proxy_test.dart
+++ b/tests/standalone/io/http_proxy_test.dart
@@ -232,6 +232,7 @@
               testProxyDoneCount++;
               if (testProxyDoneCount == proxy.length * 2) {
                 Expect.equals(proxy.length, server.requestCount);
+                Expect.equals(proxy.length, secureServer.requestCount);
                 proxyServer.shutdown();
                 server.shutdown();
                 secureServer.shutdown();
@@ -311,6 +312,56 @@
   });
 }
 
+int testProxyFromEnviromentDoneCount = 0;
+void testProxyFromEnviroment() {
+  setupProxyServer().then((proxyServer) {
+  setupServer(1).then((server) {
+  setupServer(1, secure: true).then((secureServer) {
+    HttpClient client = new HttpClient();
+
+    client.findProxy = (Uri uri) {
+      return HttpClient.findProxyFromEnvironment(
+          uri,
+          environment: {"http_proxy": "localhost:${proxyServer.port}",
+                        "https_proxy": "localhost:${proxyServer.port}"});
+    };
+
+    const int loopCount = 5;
+    for (int i = 0; i < loopCount; i++) {
+      test(bool secure) {
+        String url = secure
+            ? "https://localhost:${secureServer.port}/$i"
+            : "http://127.0.0.1:${server.port}/$i";
+
+        client.postUrl(Uri.parse(url))
+          .then((HttpClientRequest clientRequest) {
+            String content = "$i$i$i";
+            clientRequest.write(content);
+            return clientRequest.close();
+          })
+          .then((HttpClientResponse response) {
+            response.listen((_) {}, onDone: () {
+              testProxyFromEnviromentDoneCount++;
+              if (testProxyFromEnviromentDoneCount == loopCount * 2) {
+                Expect.equals(loopCount, server.requestCount);
+                Expect.equals(loopCount, secureServer.requestCount);
+                proxyServer.shutdown();
+                server.shutdown();
+                secureServer.shutdown();
+                client.close();
+              }
+            });
+          });
+      }
+
+      test(false);
+      test(true);
+    }
+  });
+  });
+  });
+}
+
 int testRealProxyDoneCount = 0;
 void testRealProxy() {
   setupServer(1).then((server) {
@@ -363,6 +414,7 @@
   testDirectProxy();
   testProxy();
   testProxyChain();
+  testProxyFromEnviroment();
   // This test is not normally run. It can be used for locally testing
   // with a real proxy server (e.g. Apache).
   //testRealProxy();
diff --git a/tests/standalone/io/http_server_early_client_close_test.dart b/tests/standalone/io/http_server_early_client_close_test.dart
index 72324e2..8573f93 100644
--- a/tests/standalone/io/http_server_early_client_close_test.dart
+++ b/tests/standalone/io/http_server_early_client_close_test.dart
@@ -152,7 +152,8 @@
           socket.write("\r\n");
           socket.write("data");
           socket.close();
-          socket.listen((_) {});
+          socket.listen((_) {}, onError: (_) {});
+          socket.done.catchError((_) {});
         });
   });
 }
diff --git a/tests/standalone/io/link_test.dart b/tests/standalone/io/link_test.dart
index afcffb8..8d467d4 100644
--- a/tests/standalone/io/link_test.dart
+++ b/tests/standalone/io/link_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import "dart:async";
 import "dart:io";
 import "dart:isolate";
 
@@ -28,6 +29,8 @@
   Expect.isTrue(new Directory(target).existsSync());
   Expect.isTrue(new Link(link).existsSync());
   Expect.isFalse(new Link(target).existsSync());
+  Expect.equals(target, new Link(link).targetSync());
+  Expect.throws(() => new Link(target).targetSync());
 
   String createdThroughLink =
       base.append('link/createdThroughLink').toNativePath();
@@ -46,7 +49,91 @@
   Expect.equals(FileSystemEntityType.DIRECTORY,
                 FileSystemEntity.typeSync(createdDirectly, followLinks: false));
 
-  new Directory.fromPath(base).deleteSync(recursive: true);
+  // Test FileSystemEntity.identical on files, directories, and links,
+  // reached by different paths.
+  Expect.isTrue(FileSystemEntity.identicalSync(createdDirectly,
+                                               createdDirectly));
+  Expect.isFalse(FileSystemEntity.identicalSync(createdDirectly,
+                                                createdThroughLink));
+  Expect.isTrue(FileSystemEntity.identicalSync(createdDirectly,
+      base.append('link/createdDirectly').toNativePath()));
+  Expect.isTrue(FileSystemEntity.identicalSync(createdThroughLink,
+      base.append('target/createdThroughLink').toNativePath()));
+
+  Expect.isFalse(FileSystemEntity.identicalSync(target, link));
+  Expect.isTrue(FileSystemEntity.identicalSync(link, link));
+  Expect.isTrue(FileSystemEntity.identicalSync(target, target));
+  Expect.isTrue(FileSystemEntity.identicalSync(target,
+                                               new Link(link).targetSync()));
+  String absolutePath = new File(".").fullPathSync();
+  Expect.isTrue(FileSystemEntity.identicalSync(".", absolutePath));
+
+  String createdFile = base.append('target/createdFile').toNativePath();
+  new File(createdFile).createSync();
+  Expect.isTrue(FileSystemEntity.identicalSync(createdFile, createdFile));
+  Expect.isFalse(FileSystemEntity.identicalSync(createdFile, createdDirectly));
+  Expect.isTrue(FileSystemEntity.identicalSync(createdFile,
+      base.append('link/createdFile').toNativePath()));
+  Expect.throws(() => FileSystemEntity.identicalSync(createdFile,
+      base.append('link/foo').toNativePath()));
+
+  var baseDir = new Directory.fromPath(base);
+
+  Map makeExpected(bool recursive, bool followLinks) {
+    Map expected = new Map();
+    expected['target'] = 'Directory';
+    expected['link'] = followLinks ? 'Directory' : 'Link';
+    if (recursive) {
+      expected['target/createdDirectly'] = 'Directory';
+      expected['target/createdThroughLink'] = 'Directory';
+      expected['target/createdFile'] = 'File';
+      if (followLinks) {
+        expected['link/createdDirectly'] = 'Directory';
+        expected['link/createdThroughLink'] = 'Directory';
+        expected['link/createdFile'] = 'File';
+      }
+    }
+    return expected;
+  }
+
+  void checkEntity(FileSystemEntity x, Map expected) {
+    String ending = new Path(x.path).relativeTo(base).toString();
+    Expect.isNotNull(expected[ending]);
+    Expect.isTrue(x.toString().startsWith(expected[ending]));
+    expected[ending] = 'Found';
+  }
+
+  List futures = [];
+  for (bool recursive in [true, false]) {
+    for (bool followLinks in [true, false]) {
+      Map expected = makeExpected(recursive, followLinks);
+      for (var x in baseDir.listSync(recursive: recursive,
+                                     followLinks: followLinks)) {
+        checkEntity(x, expected);
+      }
+      for (var v in expected.values) {
+        Expect.equals('Found', v);
+      }
+      expected = makeExpected(recursive, followLinks);
+      // We use Stream.reduce to run a function on each entry, and return
+      // a future that completes when done.
+      var f = new Completer();
+      futures.add(f.future);
+      baseDir.list(recursive: recursive, followLinks: followLinks).listen(
+          (entity) {
+            checkEntity(entity, expected);
+          },
+          onDone: () {
+            for (var v in expected.values) {
+              Expect.equals('Found', v);
+            }
+            f.complete(null);
+          });
+    }
+  }
+  Future.wait(futures).then((_) {
+    baseDir.deleteSync(recursive: true);
+  });
 }
 
 
diff --git a/tests/standalone/io/regress_9194_test.dart b/tests/standalone/io/regress_9194_test.dart
new file mode 100644
index 0000000..32e8851
--- /dev/null
+++ b/tests/standalone/io/regress_9194_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+void main() {
+  HttpServer.bind('127.0.0.1', 0).then((server) {
+      server.listen((request) {
+        request.response
+            ..reasonPhrase = ''
+            ..close();
+      });
+
+      HttpClient client = new HttpClient();
+      client.get("127.0.0.1", server.port, "/")
+          .then((HttpClientRequest request) {
+            return request.close();
+          })
+          .then((HttpClientResponse response) {
+            Expect.equals("", response.reasonPhrase);
+            server.close();
+            client.close();
+          });
+    });
+}
diff --git a/tests/standalone/io/skipping_dart2js_compilations_test.dart b/tests/standalone/io/skipping_dart2js_compilations_test.dart
index c6ce377..a142ab3 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_test.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -104,7 +104,7 @@
 
   void _writeToFile(File file, String content) {
     if (content != null) {
-      var fd = new File(file.fullPathSync()).openSync(FileMode.WRITE);
+      var fd = new File(file.fullPathSync()).openSync(mode: FileMode.WRITE);
       fd.writeStringSync(content);
       fd.closeSync();
     }
diff --git a/tests/standalone/io/windows_file_system_links_test.dart b/tests/standalone/io/windows_file_system_links_test.dart
index a458a5f..f161b0e 100644
--- a/tests/standalone/io/windows_file_system_links_test.dart
+++ b/tests/standalone/io/windows_file_system_links_test.dart
@@ -26,6 +26,8 @@
                   FileSystemEntity.typeSync(y, followLinks: false));
     Expect.equals(FileSystemEntityType.DIRECTORY,
                   FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
+
     // Test Junction pointing to a missing directory.
     new Directory(x).deleteSync();
     Expect.isTrue(new Directory(y).existsSync());
@@ -42,12 +44,14 @@
                   FileSystemEntity.typeSync(y, followLinks: false));
     Expect.equals(FileSystemEntityType.NOT_FOUND,
                   FileSystemEntity.typeSync(x, followLinks: false));
+    Expect.equals(x, new Link(y).targetSync());
 
     // Delete Junction pointing to a missing directory.
     new Directory(y).deleteSync();
     Expect.isFalse(FileSystemEntity.isLinkSync(y));
     Expect.equals(FileSystemEntityType.NOT_FOUND,
                   FileSystemEntity.typeSync(y));
+    Expect.throws(() => new Link(y).targetSync());
 
     new Directory(x).createSync();
     new Link(y).create(x).then((_) {
@@ -55,6 +59,7 @@
                     FileSystemEntity.typeSync(y, followLinks: false));
       Expect.equals(FileSystemEntityType.DIRECTORY,
                     FileSystemEntity.typeSync(x, followLinks: false));
+      Expect.equals(x, new Link(y).targetSync());
 
       // Delete Junction pointing to an existing directory.
       new Directory(y).deleteSync();
@@ -66,6 +71,8 @@
                     FileSystemEntity.typeSync(x));
       Expect.equals(FileSystemEntityType.DIRECTORY,
                     FileSystemEntity.typeSync(x, followLinks: false));
+      Expect.throws(() => new Link(y).targetSync());
+
       temp.deleteSync(recursive: true);
     });
   });
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 963802f..22c188d 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -16,7 +16,6 @@
 # Issue 8232.
 debugger/basic_debugger_test: Pass, Fail
 
-
 [ $runtime == vm && $checked ]
 # These tests have type errors on purpose.
 io/process_invalid_arguments_test: Fail, OK
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index 14ac5bb..c4d6603 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -18,7 +18,9 @@
   } else if (uri.scheme == "lib") {
     if (uri.path.endsWith("/core.dart")) {
       source = """library core;
-                  class Object {}
+                  class Object {
+                    operator==(other) {}
+                  }
                   class Type {}
                   class bool {}
                   class num {}
diff --git a/tests/utils/recursive_import_test.dart b/tests/utils/recursive_import_test.dart
index 62bf362..b3020c5 100644
--- a/tests/utils/recursive_import_test.dart
+++ b/tests/utils/recursive_import_test.dart
@@ -10,7 +10,9 @@
 
 const CORE_LIB = """
 library core;
-class Object{}
+class Object{
+  operator==(other) {}
+}
 class bool {}
 class num {}
 class int {}
diff --git a/tools/VERSION b/tools/VERSION
index c49f814..6c6a0d8 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 4
-BUILD 2
-PATCH 8
+BUILD 3
+PATCH 0
diff --git a/tools/bots/bot.py b/tools/bots/bot.py
index 0d9284b..a050b42 100644
--- a/tools/bots/bot.py
+++ b/tools/bots/bot.py
@@ -86,10 +86,12 @@
 
   def __enter__(self):
     print '@@@BUILD_STEP %s@@@' % self.name
+    sys.stdout.flush()
 
   def __exit__(self, type, value, traceback):
     if value:
       print '@@@STEP_FAILURE@@@'
+      sys.stdout.flush()
       if self.swallow_error and isinstance(value, OSError):
         return True
 
diff --git a/tools/bots/editor.py b/tools/bots/editor.py
new file mode 100755
index 0000000..4e4e02e
--- /dev/null
+++ b/tools/bots/editor.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+# 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 os
+import sys
+
+import bot
+
+def GetEditorExecutable(mode, arch):
+  configuration_dir = mode + arch.upper()
+  linux_path = os.path.join('out', configuration_dir, 'editor')
+  win_path = os.path.join('build', configuration_dir, 'editor')
+  mac_path = os.path.join('xcodebuild', configuration_dir, 'editor')
+
+  if sys.platform == 'darwin':
+    executable = os.path.join('DartEditor.app', 'Contents', 'MacOS',
+                              'DartEditor')
+    # TODO(kustermann,ricow): Maybe we're able to get rid of this in the future.
+    # We use ninja on bots which use out/ instead of xcodebuild/
+    if os.path.exists(linux_path) and os.path.isdir(linux_path):
+      return os.path.join(linux_path, executable)
+    else:
+      return os.path.join(mac_path, executable)
+  elif sys.platform == 'win32':
+    return os.path.join(win_path, 'DartEditor.exe')
+  elif sys.platform == 'linux2':
+    return os.path.join(linux_path, 'DartEditor')
+  else:
+    raise Exception('Unknown platform %s' % sys.platform)
+
+
+def main():
+  build_py = os.path.join('tools', 'build.py')
+  architectures = ['ia32', 'x64']
+  test_architectures = ['x64']
+  if sys.platform == 'win32':
+    # Our windows bots pull in only a 32 bit JVM.
+    test_architectures = ['ia32']
+
+  for arch in architectures:
+    with bot.BuildStep('Build Editor %s' % arch):
+      args = [sys.executable, build_py,
+              '-mrelease', '--arch=%s' % arch, 'editor']
+      print 'Running: %s' % (' '.join(args))
+      sys.stdout.flush()
+      bot.RunProcess(args)
+
+  for arch in test_architectures:
+    editor_executable = GetEditorExecutable('Release', arch)
+    with bot.BuildStep('Test Editor %s' % arch):
+      args = [editor_executable, '--test', '--auto-exit']
+      print 'Running: %s' % (' '.join(args))
+      sys.stdout.flush()
+      bot.RunProcess(args)
+  return 0
+
+if __name__ == '__main__':
+  try:
+    sys.exit(main())
+  except OSError as e:
+    sys.exit(e.errno)
diff --git a/tools/create_editor.py b/tools/create_editor.py
index 379bd6d..6c95963 100644
--- a/tools/create_editor.py
+++ b/tools/create_editor.py
@@ -5,11 +5,12 @@
 # BSD-style license that can be found in the LICENSE file.
 #
 # A script which will be invoked from gyp to create a build of the editor.
-# 
-# TODO(devoncarew): currently this script is not callable from tools/build.py
-# Usage: ./tools/build.py editor
-#  -or-
-# Usage: ./tools/build_editor.py [--mode <mode>] [--arch <arch>] output
+#
+# Usage: ./tools/create_editor.py
+#            [--mode <mode>] [--arch <arch>] [--out <output>] [--build <build>]
+#
+# DO NOT CALL THIS SCRIPT DIRECTLY, instead invoke:
+# ./tools/build.py -mrelease editor
 
 import glob
 import optparse
@@ -23,6 +24,7 @@
 from os.path import join
 
 OUTPUT = None
+BUILD = None
 
 OS_CONFIG = {
   'win32': 'win32, win32',
@@ -45,11 +47,16 @@
 
 def ProcessEditorArchive(archive, outDir):
   tempDir = join(GetEditorTemp(), 'editor.out')
-  os.makedirs(tempDir)
+  try:
+    os.makedirs(tempDir)
+  except OSError:
+    # Directory already exists.
+    pass
 
   if utils.IsWindows():
     f = zipfile.ZipFile(archive)
     f.extractall(tempDir)
+    f.close()
   else:
     subprocess.call(['unzip', '-q', archive, '-d', tempDir])
 
@@ -61,19 +68,15 @@
 
 
 def GetEditorTemp():
-  return join(GetBuildRoot(), 'editor.build.temp')
+  return join(BUILD, 'editor.build.temp')
 
 
 def GetDownloadCache():
   return GetEclipseBuildRoot()
 
 
-def GetBuildRoot():
-  return os.path.abspath(utils.GetBuildRoot(utils.GuessOS()))
-
-
 def GetEclipseBuildRoot():
-  return join(GetBuildRoot(), 'editor.build.cache')
+  return join(BUILD, 'editor.build.cache')
 
 
 def GetSdkPath():
@@ -86,35 +89,42 @@
 
 def BuildOptions():
   options = optparse.OptionParser(usage='usage: %prog [options] <output>')
-  options.add_option("-m", "--mode",
-      help='Build variant',
-      metavar='[debug,release]')
-  options.add_option("-a", "--arch",
-      help='Target architecture',
-      metavar='[ia32,x64]')
+  options.add_option("-m", "--mode", metavar='[debug,release]')
+  options.add_option("-a", "--arch", metavar='[ia32,x64]')
+  options.add_option("-o", "--out")
+  options.add_option("-b", "--build")
   return options
 
-  
+
 def Main():
   global OUTPUT
-  
+  global BUILD
+
   parser = BuildOptions()
   (options, args) = parser.parse_args()
-  
-  if len(args) > 1:
+
+  if args:
     parser.print_help()
     return 1
-  
+
   osName = utils.GuessOS()
   mode = 'debug'
   arch = utils.GuessArchitecture()
-  
-  if args:
+
+  if not options.build:
+    print >> sys.stderr, 'Error: no --build option specified'
+    exit(1)
+  else:
+    BUILD = options.build
+
+  if not options.out:
+    print >> sys.stderr, 'Error: no --out option specified'
+    exit(1)
+  else:
     # TODO(devoncarew): Currently we scrape the output path to determine the
     # mode and arch. This is fragile and should moved into one location
     # (utils.py?) or made more explicit.
-    OUTPUT = args[0]
-    
+    OUTPUT = options.out
     mode = ('release', 'debug')['Debug' in OUTPUT]
     arch = ('ia32', 'x64')['X64' in OUTPUT]
 
@@ -124,18 +134,15 @@
   if options.arch:
     arch = options.arch
 
-  # If an output dir was not given, create one from os, mode, and arch.
-  if not OUTPUT:
-    OUTPUT = join(utils.GetBuildRoot(osName, mode, arch), 'editor')
-  
   OUTPUT = os.path.abspath(OUTPUT)
-  
+  BUILD = os.path.abspath(BUILD)
+
   print "\nBuilding the editor"
   print "  config : %s, %s, %s" % (osName, arch, mode)
   print "  output : %s" % OUTPUT
 
   # Clean the editor output directory.
-  print '  cleaning %s' % OUTPUT
+  print '\ncleaning %s' % OUTPUT
   shutil.rmtree(OUTPUT, True)
 
   # These are the valid eclipse build configurations that we can produce.
@@ -151,12 +158,10 @@
   sys.stdout.flush()
   sys.stderr.flush()
 
-  buildScript = join('editor', 'tools', 'features', 
-                     'com.google.dart.tools.deploy.feature_releng', 
+  buildScript = join('editor', 'tools', 'features',
+                     'com.google.dart.tools.deploy.feature_releng',
                      'build_rcp.xml')
-
-  buildRcpStatus = subprocess.call(
-      [AntPath(), 
+  build_cmd = [AntPath(),
       '-lib',
       join('third_party', 'bzip2', 'bzip2.jar'),
       '-Dbuild.out=' + OUTPUT,
@@ -169,8 +174,9 @@
       '-Dbuild.dart.sdk=' + GetSdkPath(),
       '-Dbuild.no.properties=true',
       '-buildfile',
-      buildScript],
-    shell=utils.IsWindows())
+      buildScript]
+  print build_cmd
+  buildRcpStatus = subprocess.call(build_cmd, shell=utils.IsWindows())
 
   if buildRcpStatus != 0:
     sys.exit(buildRcpStatus)
@@ -180,7 +186,7 @@
   # dart/ subdirectory. We unzip the contents of the archive into OUTPUT. It
   # will use the ../dart-sdk directory as its SDK.
   archives = glob.glob(join(OUTPUT, '*.zip'))
-  
+
   if archives:
     ProcessEditorArchive(archives[0], OUTPUT)
 
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 0450497..0b17457 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -12,8 +12,8 @@
 
 [Supplemental]
 interface ScriptProcessorNode {
-  // FIXME(antonm): provide proper support.
   [Suppressed] attribute EventListener onaudioprocess;
+  [Custom] void _setEventListener(EventListener eventListener);
 };
 
 // Force ElementTraversal. WebKit defines these directly.
@@ -32,6 +32,11 @@
 };
 
 [Supplemental]
+interface CanvasRenderingContext2D {
+  [DartName=createImageDataFromImageData] ImageData createImageData(in ImageData imagedata) raises (DOMException);
+};
+
+[Supplemental]
 interface Console {
   [Suppressed] void assert(in boolean condition);
   [CallWith=ScriptArguments|ScriptState] void assertCondition(boolean condition);
@@ -241,15 +246,6 @@
   [Suppressed, CallWith=ScriptExecutionContext] IDBTransaction transaction(in DOMString storeName, in unsigned short mode)
       raises (IDBDatabaseException);
 };
-[Supplemental]
-interface IDBIndex {
-  [DartName=getObject] IDBRequest get(in any key);
-};
-[Supplemental]
-interface IDBObjectStore {
-  [DartName=getObject] IDBRequest get(in any key);
-  [DartName=getObject] IDBRequest get(in IDBKeyRange key);
-};
 
 [Supplemental]
 interface IDBKeyRange {
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index c84c6e6..a76fb64 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -805,6 +805,7 @@
     "@SupportedBrowser(SupportedBrowser.CHROME, '25')",
     "@Experimental",
   ],
+  'Event.clipboardData': _webkit_experimental_annotations,
   'FormData': _all_but_ie9_annotations,
   'HashChangeEvent': [
     "@SupportedBrowser(SupportedBrowser.CHROME)",
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index fef2cac..393d7b4 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -23,6 +23,10 @@
   'History': 'HistoryBase',
 }
 
+_custom_factories = [
+  'Notification',
+  'EventSource',
+]
 
 class HtmlDartGenerator(object):
   def __init__(self, interface, options):
@@ -78,16 +82,12 @@
           self.AmendIndexer(parent_type_info.list_item_type())
           break
 
-    # Group overloaded operations by id.
-    operationsById = {}
-    for operation in interface.operations:
-      if operation.id not in operationsById:
-        operationsById[operation.id] = []
-      operationsById[operation.id].append(operation)
+    # Group overloaded operations by name.
+    operationsByName = self._OperationsByName(interface)
 
     # Generate operations.
-    for id in sorted(operationsById.keys()):
-      operations = operationsById[id]
+    for id in sorted(operationsByName.keys()):
+      operations = operationsByName[id]
       info = AnalyzeOperation(interface, operations)
       self.AddOperation(info, declare_only)
       if ('%s.%s' % (interface.id, info.declared_name) in
@@ -108,21 +108,24 @@
           self.SecondaryContext(parent_interface)
           self.AddAttribute(attr)
 
-      # Group overloaded operations by id.
-      operationsById = {}
-      for operation in parent_interface.operations:
-        if operation.id not in operationsById:
-          operationsById[operation.id] = []
-        operationsById[operation.id].append(operation)
+      # Group overloaded operations by name.
+      operationsByName =self._OperationsByName(parent_interface)
 
       # Generate operations.
-      for id in sorted(operationsById.keys()):
+      for id in sorted(operationsByName.keys()):
         if not any(op.id == id for op in interface.operations):
-          operations = operationsById[id]
+          operations = operationsByName[id]
           info = AnalyzeOperation(interface, operations)
           self.SecondaryContext(parent_interface)
           self.AddOperation(info)
 
+  def _OperationsByName(self, interface):
+    operationsByName = {}
+    for operation in interface.operations:
+      name = operation.ext_attrs.get('DartName', operation.id)
+      operationsByName.setdefault(name, []).append(operation)
+    return operationsByName
+
   def AddConstant(self, constant):
     const_name = self._renamer.RenameMember(
         self._interface.id, constant, constant.id, 'get:', dartify_name=False)
@@ -485,12 +488,18 @@
       def IsOptional(signature_index, argument):
         return self.IsConstructorArgumentOptional(argument)
 
+      custom_factory_ctr = self._interface.id in _custom_factories
+      constructor_full_name = constructor_info._ConstructorFullName(
+          self._DartType)
       self._GenerateOverloadDispatcher(
           constructor_info.idl_args,
           False,
           [info.name for info in constructor_info.param_infos],
-          emitter.Format('$(ANNOTATIONS)factory $CTOR($PARAMS)',
-            CTOR=constructor_info._ConstructorFullName(self._DartType),
+          emitter.Format('$(ANNOTATIONS)$FACTORY_KEYWORD $CTOR($PARAMS)',
+            FACTORY_KEYWORD=('factory' if not custom_factory_ctr else
+                'static %s' % constructor_full_name),
+            CTOR=(('' if not custom_factory_ctr else '_factory')
+                + constructor_full_name),
             ANNOTATIONS=annotations,
             PARAMS=constructor_info.ParametersDeclaration(self._DartType)),
           GenerateCall,
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index c855787..f2480b4 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -34,6 +34,8 @@
     'PositionErrorCallback': '_PositionErrorCallback',
     'Rect': 'CssRect',
     'RGBColor': 'CssRgbColor',
+    'RTCDTMFSender': 'RtcDtmfSender',
+    'RTCDTMFToneChangeEvent': 'RtcDtmfToneChangeEvent',
     'RTCErrorCallback': '_RtcErrorCallback',
     'RTCSessionDescriptionCallback': '_RtcSessionDescriptionCallback',
     'StorageInfoErrorCallback': '_StorageInfoErrorCallback',
@@ -111,11 +113,8 @@
   'FileEntry.file',
   'Notification.requestPermission',
   'NotificationCenter.requestPermission',
-  'RTCPeerConnection.createAnswer',
-  'RTCPeerConnection.createOffer',
   'RTCPeerConnection.setLocalDescription',
   'RTCPeerConnection.setRemoteDescription',
-  'StorageInfo.queryUsageAndQuota',
   'StorageInfo.requestQuota',
   'WorkerContext.webkitResolveLocalFileSystemURL',
   'WorkerContext.webkitRequestFileSystem',
@@ -166,10 +165,6 @@
   'Element.childElementCount',
   'Element.children',
   'Element.className',
-  'Element.clientHeight',
-  'Element.clientLeft',
-  'Element.clientTop',
-  'Element.clientWidth',
   'Element.firstElementChild',
   'Element.getAttribute',
   'Element.getAttributeNS',
@@ -177,10 +172,6 @@
   'Element.hasAttribute',
   'Element.hasAttributeNS',
   'Element.lastElementChild',
-  'Element.offsetHeight',
-  'Element.offsetLeft',
-  'Element.offsetTop',
-  'Element.offsetWidth',
   'Element.querySelectorAll',
   'Element.removeAttribute',
   'Element.removeAttributeNS',
@@ -226,7 +217,7 @@
   'IDBObjectStore.count',
   'IDBObjectStore.createIndex',
   'IDBObjectStore.delete',
-  'IDBObjectStore.getObject',
+  'IDBObjectStore.get',
   'IDBObjectStore.openCursor',
   'IDBObjectStore.put',
   'KeyboardEvent.initKeyboardEvent',
@@ -285,6 +276,8 @@
 # Members from the standard dom that exist in the dart:html library with
 # identical functionality but with cleaner names.
 renamed_html_members = monitored.Dict('htmlrenamer.renamed_html_members', {
+    'DirectoryEntry.getDirectory': '_getDirectory',
+    'DirectoryEntry.getFile': '_getFile',
     'Document.createCDATASection': 'createCDataSection',
     'Document.defaultView': 'window',
     'Document.querySelector': 'query',
@@ -297,7 +290,7 @@
     'DOMWindow.webkitConvertPointFromNodeToPage': 'convertPointFromNodeToPage',
     'DOMWindow.webkitConvertPointFromPageToNode': 'convertPointFromPageToNode',
     'DOMWindow.webkitNotifications': 'notifications',
-    'DOMWindow.webkitRequestFileSystem': 'requestFileSystem',
+    'DOMWindow.webkitRequestFileSystem': '_requestFileSystem',
     'DOMWindow.webkitResolveLocalFileSystemURL': 'resolveLocalFileSystemUrl',
     'Element.querySelector': 'query',
     'Element.webkitCreateShadowRoot': 'createShadowRoot',
@@ -310,11 +303,14 @@
     'Node.parentElement': 'parent',
     'Node.previousSibling': 'previousNode',
     'Node.textContent': 'text',
+    'RTCPeerConnection.createAnswer': '_createAnswer',
+    'RTCPeerConnection.createOffer': '_createOffer',
+    'StorageInfo.queryUsageAndQuota': '_queryUsageAndQuota',
     'SVGComponentTransferFunctionElement.offset': 'gradientOffset',
     'SVGElement.className': '$dom_svgClassName',
     'SVGStopElement.offset': 'gradientOffset',
-    'WorkerContext.webkitRequestFileSystem': 'requestFileSystem',
-    'WorkerContext.webkitRequestFileSystemSync': 'requestFileSystemSync',
+    'WorkerContext.webkitRequestFileSystem': '_requestFileSystem',
+    'WorkerContext.webkitRequestFileSystemSync': '_requestFileSystemSync',
     'WorkerContext.webkitResolveLocalFileSystemSyncURL':
         'resolveLocalFileSystemSyncUrl',
     'WorkerContext.webkitResolveLocalFileSystemURL':
@@ -347,6 +343,7 @@
     'CanvasRenderingContext2D.setMiterLimit',
     'CanvasRenderingContext2D.setShadow',
     'CanvasRenderingContext2D.setStrokeColor',
+    'CanvasRenderingContext2D.webkitLineDash',
     'CanvasRenderingContext2D.webkitLineDashOffset',
     'CharacterData.remove',
     'DOMWindow.call:blur',
@@ -602,6 +599,13 @@
     'Document.hasFocus',
     ])
 
+# Manual dart: library name lookup.
+_library_names = monitored.Dict('htmlrenamer._library_names', {
+  'DOMWindow': 'html',
+  'Navigator': 'html',
+  'WorkerContext': 'html',
+})
+
 class HtmlRenamer(object):
   def __init__(self, database):
     self._database = database
@@ -666,6 +670,10 @@
         return member_name
 
   def GetLibraryName(self, interface):
+    # Some types have attributes merged in from many other interfaces.
+    if interface.id in _library_names:
+      return _library_names[interface.id]
+
     if 'Conditional' in interface.ext_attrs:
       if 'WEB_AUDIO' in interface.ext_attrs['Conditional']:
         return 'web_audio'
@@ -674,9 +682,7 @@
       if 'INDEXED_DATABASE' in interface.ext_attrs['Conditional']:
         return 'indexed_db'
       if 'SQL_DATABASE' in interface.ext_attrs['Conditional']:
-        # WorkerContext has attributes merged in from many other interfaces.
-        if interface.id != 'WorkerContext':
-          return 'web_sql'
+        return 'web_sql'
 
     return 'html'
 
diff --git a/tools/dom/scripts/idlsync.py b/tools/dom/scripts/idlsync.py
index 94f435e..b258908 100755
--- a/tools/dom/scripts/idlsync.py
+++ b/tools/dom/scripts/idlsync.py
@@ -10,6 +10,7 @@
 import shutil
 import subprocess
 import sys
+import tempfile
 
 SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__))
 DART_PATH = os.path.abspath(os.path.join(SCRIPT_PATH, '..', '..', '..'))
@@ -176,6 +177,26 @@
   out.write(readme)
   out.close()
 
+def SaveVersionControlDir(local_path):
+  version_control_dir = os.path.join(local_path, '.git')
+  if not os.path.isdir(version_control_dir):
+    version_control_dir = os.path.join(local_path, '.svn')
+    if not os.path.isdir(version_control_dir):
+      raise '%s is not a git or svn directory' % local_path
+  temp_dir = tempfile.mkdtemp()
+  shutil.move(version_control_dir, temp_dir)
+  return temp_dir
+
+
+def RestoreVersionControlDir(local_path, saved_version_control_dir):
+  version_control_dir = os.path.join(saved_version_control_dir, '.git')
+  if not os.path.isdir(version_control_dir):
+    version_control_dir = os.path.join(saved_version_control_dir, '.svn')
+    if not os.path.isdir(version_control_dir):
+      raise 'Failed restoring version control directory'
+  shutil.move(version_control_dir, local_path)
+  shutil.rmtree(saved_version_control_dir)
+
 
 def ParseOptions():
   parser = optparse.OptionParser()
@@ -204,10 +225,11 @@
       url, latest = GetSvnRevision(deps, component)
       if revision is None:
         revision = latest
+      saved_version_control_dir = SaveVersionControlDir(local_path);
       RefreshFiles(url, revision, remote_path, local_path, depth)
       PruneExtraFiles(local_path)
       GenerateReadme(local_path, readme, url, revision)
-
+      RestoreVersionControlDir(local_path, saved_version_control_dir);
 
 if __name__ == '__main__':
   main()
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 0f2de53..1559cc7 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -18,6 +18,7 @@
     'AudioBufferSourceNode.stop',
     'AudioContext.createGain',
     'AudioContext.createScriptProcessor',
+    'CanvasRenderingContext2D.drawImage',
     'CanvasRenderingContext2D.lineDashOffset',
     'Console.memory',
     'Console.profiles',
@@ -56,6 +57,7 @@
     'MouseEvent.offsetY',
     'Navigator.language',
     'Navigator.webkitGetUserMedia',
+    'ScriptProcessorNode._setEventListener',
     'URL.createObjectURL',
     'URL.revokeObjectURL',
     'WheelEvent.deltaMode',
@@ -75,7 +77,6 @@
     'AudioContext',
     'Blob',
     'MutationObserver',
-    'Notification',
     'RTCIceCandidate',
     'RTCPeerConnection',
     'RTCSessionDescription',
@@ -358,6 +359,8 @@
 ]
 
 js_support_checks = dict({
+    'AudioContext': "JS('bool', '!!(window.AudioContext ||"
+        " window.webkitAudioContext)')",
     'ArrayBuffer': "JS('bool', 'typeof window.ArrayBuffer != \"undefined\"')",
     'Crypto':
         "JS('bool', '!!(window.crypto && window.crypto.getRandomValues)')",
diff --git a/tools/dom/src/AttributeMap.dart b/tools/dom/src/AttributeMap.dart
index d309a71..1d196e3 100644
--- a/tools/dom/src/AttributeMap.dart
+++ b/tools/dom/src/AttributeMap.dart
@@ -90,8 +90,8 @@
     return _element.$dom_getAttribute(key);
   }
 
-  void operator []=(String key, value) {
-    _element.$dom_setAttribute(key, '$value');
+  void operator []=(String key, String value) {
+    _element.$dom_setAttribute(key, value);
   }
 
   String remove(String key) {
@@ -127,8 +127,8 @@
     return _element.$dom_getAttributeNS(_namespace, key);
   }
 
-  void operator []=(String key, value) {
-    _element.$dom_setAttributeNS(_namespace, key, '$value');
+  void operator []=(String key, String value) {
+    _element.$dom_setAttributeNS(_namespace, key, value);
   }
 
   String remove(String key) {
@@ -167,8 +167,8 @@
 
   String operator [](String key) => $dom_attributes[_attr(key)];
 
-  void operator []=(String key, value) {
-    $dom_attributes[_attr(key)] = '$value';
+  void operator []=(String key, String value) {
+    $dom_attributes[_attr(key)] = value;
   }
 
   String putIfAbsent(String key, String ifAbsent()) =>
diff --git a/tools/dom/src/CanvasImageSource.dart b/tools/dom/src/CanvasImageSource.dart
index 9b4feea..9d35871 100644
--- a/tools/dom/src/CanvasImageSource.dart
+++ b/tools/dom/src/CanvasImageSource.dart
@@ -6,8 +6,10 @@
 
 /**
  * An object that can be drawn to a [CanvasRenderingContext2D] object with
- * [CanvasRenderingContext2D.drawImage] or
- * [CanvasRenderingContext2D.drawImageAtScale].
+ * [CanvasRenderingContext2D.drawImage],
+ * [CanvasRenderingContext2D.drawImageRect],
+ * [CanvasRenderingContext2D.drawImageScaled], or
+ * [CanvasRenderingContext2D.drawImageScaledFromSource].
  *
  * If the CanvasImageSource is an [ImageElement] then the element's image is
  * used. If the [ImageElement] is an animated image, then the poster frame is
@@ -19,9 +21,15 @@
  * If the CanvasImageSource is a [CanvasElement] then the element's bitmap is
  * used.
  *
+ * ** Note: ** Currently, all versions of Internet Explorer do not support
+ * drawing a VideoElement to a canvas. Also, you may experience problems drawing
+ * a video to a canvas in Firefox if the source of the video is a data URL.
+ *
  * See also:
  *
  *  * [CanvasImageSource](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#image-sources-for-2d-rendering-contexts)
  * from the WHATWG.
+ *  * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+ * from the WHATWG.
  */
 abstract class CanvasImageSource {}
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index dbc8afc..473c037 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -11,7 +11,7 @@
   }
 
   /**
-   * Adds the class [token] to the element if it is not on it, removes it if it
+   * Adds the class [value] to the element if it is not on it, removes it if it
    * is.
    */
   bool toggle(String value) {
@@ -65,14 +65,33 @@
   // interface Collection - END
 
   // interface Set - BEGIN
+  /**
+   * Determine if this element contains the class [value].
+   *
+   * This is the Dart equivalent of jQuery's
+   * [hasClass](http://api.jquery.com/hasClass/).
+   */
   bool contains(String value) => readClasses().contains(value);
 
+  /**
+   * Add the class [value] to element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [addClass](http://api.jquery.com/addClass/).
+   */
   void add(String value) {
     // TODO - figure out if we need to do any validation here
     // or if the browser natively does enough.
     _modify((s) => s.add(value));
   }
 
+  /**
+   * Remove the class [value] from element, and return true on successful
+   * removal.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
   bool remove(Object value) {
     if (value is! String) return false;
     Set<String> s = readClasses();
@@ -81,15 +100,38 @@
     return result;
   }
 
+  /**
+   * Add all classes specified in [iterable] to element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [addClass](http://api.jquery.com/addClass/).
+   */
   void addAll(Iterable<String> iterable) {
     // TODO - see comment above about validation.
     _modify((s) => s.addAll(iterable));
   }
 
+  /**
+   * Remove all classes specified in [iterable] from element.
+   *
+   * This is the Dart equivalent of jQuery's
+   * [removeClass](http://api.jquery.com/removeClass/).
+   */
   void removeAll(Iterable<String> iterable) {
     _modify((s) => s.removeAll(iterable));
   }
 
+  /**
+   * Toggles all classes specified in [iterable] on element.
+   *
+   * Iterate through [iterable]'s items, and add it if it is not on it, or
+   * remove it if it is. This is the Dart equivalent of jQuery's
+   * [toggleClass](http://api.jquery.com/toggleClass/).
+   */
+  void toggleAll(Iterable<String> iterable) {
+    iterable.forEach(toggle);
+  }
+
   void retainAll(Iterable<String> iterable) {
     _modify((s) => s.retainAll(iterable));
   }
diff --git a/tools/dom/src/_HttpRequestUtils.dart b/tools/dom/src/_HttpRequestUtils.dart
index 352ddfc..5ba04bf 100644
--- a/tools/dom/src/_HttpRequestUtils.dart
+++ b/tools/dom/src/_HttpRequestUtils.dart
@@ -11,7 +11,7 @@
                             onComplete(HttpRequest request),
                             bool withCredentials) {
     final request = new HttpRequest();
-    request.open('GET', url, true);
+    request.open('GET', url, async: true);
 
     request.withCredentials = withCredentials;
 
diff --git a/tools/dom/templates/html/dart2js/impl_Notification.darttemplate b/tools/dom/templates/html/dart2js/impl_Notification.darttemplate
deleted file mode 100644
index ec9c3d3..0000000
--- a/tools/dom/templates/html/dart2js/impl_Notification.darttemplate
+++ /dev/null
@@ -1,17 +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 $LIBRARYNAME;
-
-$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
-  factory $CLASSNAME(String title, [Map options]) {
-    if (?options) {
-      return JS('Notification', 'new Notification(#,#)', title,
-          convertDartToNative_SerializedScriptValue(options));
-    } else {
-      return JS('Notification', 'new Notification(#)', title);
-    }
-  }
-$!MEMBERS
-}
diff --git a/tools/dom/templates/html/dart2js/impl_WorkerContext.darttemplate b/tools/dom/templates/html/dart2js/impl_WorkerContext.darttemplate
deleted file mode 100644
index 27275bf..0000000
--- a/tools/dom/templates/html/dart2js/impl_WorkerContext.darttemplate
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of $LIBRARYNAME;
-
-$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
-$!MEMBERS
-
-  /**
-   * Gets an instance of the Indexed DB factory to being using Indexed DB.
-   *
-   * Use [IdbFactory.supported] to check if Indexed DB is supported on the
-   * current platform.
-   */
-  @SupportedBrowser(SupportedBrowser.CHROME, '23.0')
-  @SupportedBrowser(SupportedBrowser.FIREFOX, '15.0')
-  @SupportedBrowser(SupportedBrowser.IE, '10.0')
-  @Experimental
-  IdbFactory get indexedDB =>
-      JS('IdbFactory',
-         '#.indexedDB || #.webkitIndexedDB || #.mozIndexedDB',
-         this, this, this);
-}
diff --git a/tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate b/tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate
index 2295902..a229e0a 100644
--- a/tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/web_audio_dart2js.darttemplate
@@ -8,7 +8,7 @@
 import 'dart:collection';
 import 'dart:html';
 import 'dart:html_common';
-import 'dart:_js_helper' show Creates, Returns;
+import 'dart:_js_helper' show Creates, Returns, convertDartClosureToJS;
 import 'dart:_foreign_helper' show JS;
 
 $!GENERATED_DART_FILES
diff --git a/tools/dom/templates/html/dartium/cpp_header.template b/tools/dom/templates/html/dartium/cpp_header.template
index bbe5835..ee4ef1f 100644
--- a/tools/dom/templates/html/dartium/cpp_header.template
+++ b/tools/dom/templates/html/dartium/cpp_header.template
@@ -8,6 +8,7 @@
 #define Dart$(INTERFACE)_h
 
 #include "DartDOMWrapper.h"
+#include "DartWrapperTypeInfo.h"
 $WEBCORE_INCLUDES
 #include <dart_api.h>
 
@@ -20,6 +21,7 @@
     static const bool isNode = $IS_NODE;
     static const bool isActive = $IS_ACTIVE;
     static const bool isEventTarget = $IS_EVENT_TARGET;
+    static DartWrapperTypeInfo info;
 
 $TO_NATIVE
 $TO_DART
@@ -31,6 +33,12 @@
     static Dart_NativeFunction resolver(Dart_Handle name, int argumentCount);
 };
 
+template<>
+class DartWrapperTypeTraits<$WEBCORE_CLASS_NAME > {
+public:
+    static DartWrapperTypeInfo* info() { return &Dart$INTERFACE::info; }
+};
+
 namespace Dart$(INTERFACE)Internal {
 $DECLARATIONS
 }
diff --git a/tools/dom/templates/html/dartium/cpp_implementation.template b/tools/dom/templates/html/dartium/cpp_implementation.template
index d06cb8d..7c9e45c 100644
--- a/tools/dom/templates/html/dartium/cpp_implementation.template
+++ b/tools/dom/templates/html/dartium/cpp_implementation.template
@@ -24,5 +24,6 @@
 
 const char* const Dart$(INTERFACE)::dartImplementationClassName = "$DART_IMPLEMENTATION_CLASS";
 const char* const Dart$(INTERFACE)::dartImplementationLibraryName = "$DART_IMPLEMENTATION_LIBRARY";
+DartWrapperTypeInfo Dart$(INTERFACE)::info;
 
 }
diff --git a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
index 93fc2fa..8aa13d1 100644
--- a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
@@ -50,11 +50,93 @@
   }
 
   /**
+   * Draws an image from a CanvasImageSource to an area of this canvas.
+   *
+   * The image will be drawn to an area of this canvas defined by
+   * [destRect]. [sourceRect] defines the region of the source image that is
+   * drawn.
+   * If [sourceRect] is not provided, then
+   * the entire rectangular image from [source] will be drawn to this context.
+   *
+   * If the image is larger than canvas
+   * will allow, the image will be clipped to fit the available space.
+   *
+   *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
+   *     CanvasRenderingContext2D ctx = canvas.context2d;
+   *     ImageElement img = document.query('img');
+   *     img.width = 100;
+   *     img.height = 100;
+   *
+   *     // Scale the image to 20x20.
+   *     ctx.drawImageToRect(img, new Rect(50, 50, 20, 20));
+   *
+   *     VideoElement video = document.query('video');
+   *     video.width = 100;
+   *     video.height = 100;
+   *     // Take the middle 20x20 pixels from the video and stretch them.
+   *     ctx.drawImageToRect(video, new Rect(50, 50, 100, 100),
+   *         sourceRect: new Rect(40, 40, 20, 20));
+   *
+   *     // Draw the top 100x20 pixels from the otherCanvas.
+   *     CanvasElement otherCanvas = document.query('canvas');
+   *     ctx.drawImageToRect(otherCanvas, new Rect(0, 0, 100, 20),
+   *         sourceRect: new Rect(0, 0, 100, 20));
+   *
+   * See also:
+   *
+   *   * [CanvasImageSource] for more information on what data is retrieved
+   * from [source].
+   *   * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+   * from the WHATWG.
+   */
+  @DomName('CanvasRenderingContext2D.drawImage')
+  void drawImageToRect(CanvasImageSource source, Rect destRect,
+      {Rect sourceRect}) {
+$if DART2JS
+    if (sourceRect == null) {
+      drawImageScaled(source,
+          destRect.left,
+          destRect.top,
+          destRect.width,
+          destRect.height);
+    } else {
+      drawImageScaledFromSource(source,
+          sourceRect.left,
+          sourceRect.top,
+          sourceRect.width,
+          sourceRect.height,
+          destRect.left,
+          destRect.top,
+          destRect.width,
+          destRect.height);
+    }
+$else
+    if (sourceRect == null) {
+      $dom_drawImage(source,
+          destRect.left,
+          destRect.top,
+          destRect.width,
+          destRect.height);
+    } else {
+      $dom_drawImage(source,
+          sourceRect.left,
+          sourceRect.top,
+          sourceRect.width,
+          sourceRect.height,
+          destRect.left,
+          destRect.top,
+          destRect.width,
+          destRect.height);
+    }
+$endif
+  }
+
+  /**
    * Draws an image from a CanvasImageSource to this canvas.
    *
    * The entire image from [source] will be drawn to this context with its top
-   * left corner at the point ([destinationX], [destinationY]). If the image is
-   * larger than canvas will allow, the image will be cropped to fit the
+   * left corner at the point ([destX], [destY]). If the image is
+   * larger than canvas will allow, the image will be clipped to fit the
    * available space.
    *
    *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
@@ -69,7 +151,7 @@
    *     CanvasElement otherCanvas = document.query('canvas');
    *     otherCanvas.width = 100;
    *     otherCanvas.height = 100;
-   *     ctx.drawImage(otherCanvas, 590, 590); // will get cropped
+   *     ctx.drawImage(otherCanvas, 590, 590); // will get clipped
    *
    * See also:
    *
@@ -79,20 +161,24 @@
    * from the WHATWG.
    */
   @DomName('CanvasRenderingContext2D.drawImage')
-  void drawImage(CanvasImageSource source, num destinationX, num destinationY) {
-    $dom_drawImage(source, destinationX, destinationY);
+$if DART2JS
+  @JSName('drawImage')
+  void drawImage(CanvasImageSource source, num destX, num destY) native;
+$else
+  void drawImage(CanvasImageSource source, num destX, num destY) {
+    $dom_drawImage(source, destX, destY);
   }
+$endif
 
   /**
    * Draws an image from a CanvasImageSource to an area of this canvas.
    *
-   * The image will be drawn to an area of this canvas defined by
-   * [destinationRect]. If [sourceRect] is not provided, then
-   * the entire rectangular image from [source] will be drawn to this context.
-   * If the dimensions of [source] or [sourceRect]
-   * differ from [destinationRect], then the image will be scaled to fit.
+   * The image will be drawn to this context with its top left corner at the
+   * point ([destX], [destY]) and will be scaled to be [destWidth] wide and
+   * [destHeight] tall.
+   *
    * If the image is larger than canvas
-   * will allow, the image will be cropped to fit the available space.
+   * will allow, the image will be clipped to fit the available space.
    *
    *     CanvasElement canvas = new CanvasElement(width: 600, height: 600);
    *     CanvasRenderingContext2D ctx = canvas.context2d;
@@ -100,20 +186,8 @@
    *     img.width = 100;
    *     img.height = 100;
    *
-   *     // Scale the image to 20x20.
-   *     ctx.drawImageAtScale(img, new Rect(50, 50, 20, 20));
-   *
-   *     VideoElement video = document.query('video');
-   *     video.width = 100;
-   *     video.height = 100;
-   *     // Take the middle 20x20 pixels from the video and stretch them.
-   *     ctx.drawImageAtScale(video, new Rect(50, 50, 100, 100),
-   *         sourceRect: new Rect(40, 40, 20, 20));
-   *
-   *     // Draw the top 100x20 pixels from the otherCanvas.
-   *     CanvasElement otherCanvas = document.query('canvas');
-   *     ctx.drawImageAtScale(otherCanvas, new Rect(0, 0, 100, 20),
-   *         sourceRect: new Rect(0, 0, 100, 20));
+   *     // Scale the image to 300x50 at the point (20, 20)
+   *     ctx.drawImageScaled(img, 20, 20, 300, 50);
    *
    * See also:
    *
@@ -123,26 +197,60 @@
    * from the WHATWG.
    */
   @DomName('CanvasRenderingContext2D.drawImage')
-  void drawImageAtScale(CanvasImageSource source, Rect destinationRect,
-      {Rect sourceRect}) {
-    if (sourceRect == null) {
-      $dom_drawImage(source,
-          destinationRect.left,
-          destinationRect.top,
-          destinationRect.width,
-          destinationRect.height);
-    } else {
-      $dom_drawImage(source,
-          sourceRect.left,
-          sourceRect.top,
-          sourceRect.width,
-          sourceRect.height,
-          destinationRect.left,
-          destinationRect.top,
-          destinationRect.width,
-          destinationRect.height);
-    }
+$if DART2JS
+  @JSName('drawImage')
+  void drawImageScaled(CanvasImageSource source,
+      num destX, num destY, num destWidth, num destHeight) native;
+$else
+  void drawImageScaled(CanvasImageSource source,
+      num destX, num destY, num destWidth, num destHeight) {
+    $dom_drawImage(source, destX, destY, destWidth, destHeight);
   }
+$endif
+
+  /**
+   * Draws an image from a CanvasImageSource to an area of this canvas.
+   *
+   * The image is a region of [source] that is [sourceWidth] wide and
+   * [destHeight] tall with top left corner at ([sourceX], [sourceY]).
+   * The image will be drawn to this context with its top left corner at the
+   * point ([destX], [destY]) and will be scaled to be [destWidth] wide and
+   * [destHeight] tall.
+   *
+   * If the image is larger than canvas
+   * will allow, the image will be clipped to fit the available space.
+   *
+   *     VideoElement video = document.query('video');
+   *     video.width = 100;
+   *     video.height = 100;
+   *     // Take the middle 20x20 pixels from the video and stretch them.
+   *     ctx.drawImageScaledFromSource(video, 40, 40, 20, 20, 50, 50, 100, 100);
+   *
+   *     // Draw the top 100x20 pixels from the otherCanvas to this one.
+   *     CanvasElement otherCanvas = document.query('canvas');
+   *     ctx.drawImageScaledFromSource(otherCanvas, 0, 0, 100, 20, 0, 0, 100, 20);
+   *
+   * See also:
+   *
+   *   * [CanvasImageSource] for more information on what data is retrieved
+   * from [source].
+   *   * [drawImage](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage)
+   * from the WHATWG.
+   */
+  @DomName('CanvasRenderingContext2D.drawImage')
+$if DART2JS
+  @JSName('drawImage')
+  void drawImageScaledFromSource(CanvasImageSource source,
+      num sourceX, num sourceY, num sourceWidth, num sourceHeight,
+      num destX, num destY, num destWidth, num destHeight) native;
+$else
+  void drawImageScaledFromSource(CanvasImageSource source,
+      num sourceX, num sourceY, num sourceWidth, num sourceHeight,
+      num destX, num destY, num destWidth, num destHeight) {
+    $dom_drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight,
+        destX, destY, destWidth, destHeight);
+  }
+$endif
 
 $if DART2JS
   @DomName('CanvasRenderingContext2D.lineDashOffset')
@@ -153,5 +261,9 @@
   void set lineDashOffset(num value) => JS('void', 
       'typeof #.lineDashOffset != "undefined" ? #.lineDashOffset = # : '
       '#.webkitLineDashOffset = #', this, this, value, this, value);
+$else
+  // TODO(amouravski): Add Dartium native methods for drawImage once we figure
+  // out how to not break native bindings.
 $endif
 }
+
diff --git a/tools/dom/templates/html/impl/impl_DirectoryEntry.darttemplate b/tools/dom/templates/html/impl/impl_DirectoryEntry.darttemplate
new file mode 100644
index 0000000..493b783
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_DirectoryEntry.darttemplate
@@ -0,0 +1,47 @@
+// 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 $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+  
+  /**
+   * Create a new directory with the specified `path`. If `exclusive` is true,
+   * the returned Future will complete with an error if a directory already
+   * exists with the specified `path`.
+   */
+  Future<Entry> createDirectory(String path, {bool exclusive: false}) {
+    return _getDirectory(path, options: 
+        {'create': true, 'exclusive': exclusive});
+  }
+
+  /**
+   * Retrieve an already existing directory entry. The returned future will
+   * result in an error if a directory at `path` does not exist or if the item
+   * at `path` is not a directory.
+   */
+  Future<Entry> getDirectory(String path) {
+    return _getDirectory(path);
+  }
+
+  /**
+   * Create a new file with the specified `path`. If `exclusive` is true,
+   * the returned Future will complete with an error if a file already
+   * exists at the specified `path`.
+   */
+  Future<Entry> createFile(String path, {bool exclusive: false}) {
+    return _getFile(path, options: {'create': true, 'exclusive': exclusive});
+  }
+  
+  /**
+   * Retrieve an already existing file entry. The returned future will
+   * result in an error if a file at `path` does not exist or if the item at
+   * `path` is not a file.
+   */
+  Future<Entry> getFile(String path) {
+    return _getFile(path);
+  }
+$!MEMBERS
+}
+
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index a5b8cb6..a868eb0 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -225,7 +225,7 @@
     if (index == length) {
       _element.append(element);
     } else {
-      throw new UnimplementedError("insert on ElementLists");
+      _element.insertBefore(element, this[index]);
     }
   }
 
@@ -731,37 +731,15 @@
     return window.$dom_getComputedStyle(this, pseudoElement);
   }
 
-  @deprecated
-  int get clientHeight => client.height;
-  @deprecated
-  int get clientLeft => client.left;
-  @deprecated
-  int get clientTop => client.top;
-  @deprecated
-  int get clientWidth => client.width;
+  /**
+   * Gets the position of this element relative to the client area of the page.
+   */
+  Rect get client => new Rect(clientLeft, clientTop, clientWidth, clientHeight);
 
-  @DomName('Element.clientHeight')
-  @DomName('Element.clientLeft')
-  @DomName('Element.clientTop')
-  @DomName('Element.clientWidth')
-  Rect get client => new Rect($dom_clientLeft, $dom_clientTop, $dom_clientWidth,
-      $dom_clientHeight);
-
-  @deprecated
-  int get offsetHeight => offset.height;
-  @deprecated
-  int get offsetLeft => offset.left;
-  @deprecated
-  int get offsetTop => offset.top;
-  @deprecated
-  int get offsetWidth => offset.width;
-
-  @DomName('Element.offsetHeight')
-  @DomName('Element.offsetLeft')
-  @DomName('Element.offsetTop')
-  @DomName('Element.offsetWidth')
-  Rect get offset => new Rect($dom_offsetLeft, $dom_offsetTop, $dom_offsetWidth,
-      $dom_offsetHeight);
+  /**
+   * Gets the offset of this element relative to its offsetParent.
+   */
+  Rect get offset => new Rect(offsetLeft, offsetTop, offsetWidth, offsetHeight);
 
   /**
    * Adds the specified text as a text node after the last child of this
diff --git a/tools/dom/templates/html/impl/impl_EventSource.darttemplate b/tools/dom/templates/html/impl/impl_EventSource.darttemplate
new file mode 100644
index 0000000..c75e2925
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_EventSource.darttemplate
@@ -0,0 +1,15 @@
+// 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 $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+  factory $CLASSNAME(String title, {withCredentials: false}) {
+    var parsedOptions = {
+      'withCredentials': withCredentials,
+    };
+    return $CLASSNAME._factory$CLASSNAME(title, parsedOptions);
+  }
+$!MEMBERS
+}
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index c64f11a..a8940cb 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -100,36 +100,63 @@
   }
 
   @DomName('Document.webkitCancelFullScreen')
-  void webkitCancelFullScreen() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void cancelFullScreen() {
     document.$dom_webkitCancelFullScreen();
   }
 
   @DomName('Document.webkitExitFullscreen')
-  void webkitExitFullscreen() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void exitFullscreen() {
     document.$dom_webkitExitFullscreen();
   }
 
   @DomName('Document.webkitExitPointerLock')
-  void webkitExitPointerLock() {
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  void exitPointerLock() {
     document.$dom_webkitExitPointerLock();
   }
 
   @DomName('Document.webkitFullscreenElement')
-  Element get webkitFullscreenElement => document.$dom_webkitFullscreenElement;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  Element get fullscreenElement => document.$dom_webkitFullscreenElement;
 
   @DomName('Document.webkitFullscreenEnabled')
-  bool get webkitFullscreenEnabled => document.$dom_webkitFullscreenEnabled;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get fullscreenEnabled => document.$dom_webkitFullscreenEnabled;
 
   @DomName('Document.webkitHidden')
-  bool get webkitHidden => document.$dom_webkitHidden;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get hidden => document.$dom_webkitHidden;
 
   @DomName('Document.webkitIsFullScreen')
-  bool get webkitIsFullScreen => document.$dom_webkitIsFullScreen;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  bool get isFullScreen => document.$dom_webkitIsFullScreen;
 
   @DomName('Document.webkitPointerLockElement')
-  Element get webkitPointerLockElement =>
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  Element get pointerLockElement =>
       document.$dom_webkitPointerLockElement;
 
   @DomName('Document.webkitVisibilityState')
-  String get webkitVisibilityState => document.$dom_webkitVisibilityState;
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @SupportedBrowser(SupportedBrowser.SAFARI)
+  @Experimental
+  String get visibilityState => document.$dom_webkitVisibilityState;
 }
diff --git a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
index db9f162..d963e04eb 100644
--- a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
@@ -69,10 +69,10 @@
     }
   }
 
-  @DomName('IDBObjectStore.getObject')
+  @DomName('IDBObjectStore.get')
   Future getObject(key) {
     try {
-      var request = $dom_getObject(key);
+      var request = $dom_get(key);
 
       return _completeRequest(request);
     } catch (e, stacktrace) {
diff --git a/tools/dom/templates/html/impl/impl_MutationObserver.darttemplate b/tools/dom/templates/html/impl/impl_MutationObserver.darttemplate
index abab691..7a107ef 100644
--- a/tools/dom/templates/html/impl/impl_MutationObserver.darttemplate
+++ b/tools/dom/templates/html/impl/impl_MutationObserver.darttemplate
@@ -20,8 +20,7 @@
   }
 
   void observe(Node target,
-               {Map options,
-                bool childList,
+               {bool childList,
                 bool attributes,
                 bool characterData,
                 bool subtree,
@@ -32,19 +31,6 @@
     // Parse options into map of known type.
     var parsedOptions = _createDict();
 
-    if (options != null) {
-      options.forEach((k, v) {
-          if (_boolKeys.containsKey(k)) {
-            _add(parsedOptions, k, true == v);
-          } else if (k == 'attributeFilter') {
-            _add(parsedOptions, k, _fixupList(v));
-          } else {
-            throw new ArgumentError(
-                "Illegal MutationObserver.observe option '$k'");
-          }
-        });
-    }
-
     // Override options passed in the map with named optional arguments.
     override(key, value) {
       if (value != null) _add(parsedOptions, key, value);
diff --git a/tools/dom/templates/html/impl/impl_Navigator.darttemplate b/tools/dom/templates/html/impl/impl_Navigator.darttemplate
index 9d8d8c4..e6ffe05 100644
--- a/tools/dom/templates/html/impl/impl_Navigator.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Navigator.darttemplate
@@ -16,25 +16,41 @@
    * Gets a stream (video and or audio) from the local computer.
    *
    * Use [MediaStream.supported] to check if this is supported by the current
-   * platform.
+   * platform. The arguments `audio` and `video` default to `false` (stream does
+   * not use audio or video, respectively).
    *
-   * Example use:
+   * Simple example usage:
    *
-   *     window.navigator.getUserMedia(audio:true, video: true).then((stream) {
+   *     window.navigator.getUserMedia(audio: true, video: true).then((stream) {
    *       var video = new VideoElement()
    *         ..autoplay = true
    *         ..src = Url.createObjectUrl(stream);
    *       document.body.append(video);
    *     });
    *
+   * The user can also pass in Maps to the audio or video parameters to specify 
+   * mandatory and optional constraints for the media stream. Not passing in a 
+   * map, but passing in `true` will provide a LocalMediaStream with audio or 
+   * video capabilities, but without any additional constraints. The particular
+   * constraint names for audio and video are still in flux, but as of this 
+   * writing, here is an example providing more constraints.
+   *
+   *     window.navigator.getUserMedia(
+   *         audio: true, 
+   *         video: {'mandatory': 
+   *                    { 'minAspectRatio': 1.333, 'maxAspectRatio': 1.334 },
+   *                 'optional': 
+   *                    [{ 'minFrameRate': 60 },
+   *                     { 'maxWidth': 640 }]
+   *     });
+   *
    * See also:
    * * [MediaStream.supported]
    */
   @DomName('Navigator.webkitGetUserMedia')
   @SupportedBrowser(SupportedBrowser.CHROME)
   @Experimental
-  Future<LocalMediaStream> getUserMedia({bool audio: false,
-      bool video: false}) {
+  Future<LocalMediaStream> getUserMedia({audio: false, video: false}) {
     var completer = new Completer<LocalMediaStream>();
     var options = {
       'audio': audio,
@@ -42,7 +58,7 @@
     };
 $if DART2JS
     _ensureGetUserMedia();
-    this._getUserMedia(convertDartToNative_Dictionary(options),
+    this._getUserMedia(convertDartToNative_SerializedScriptValue(options),
       (stream) {
         completer.complete(stream);
       },
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index 0d6e362..56d2d11 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -91,7 +91,7 @@
     if (index == length) {
       _this.append(node);
     } else {
-      this_.insertBefore(node, this[index]);
+      _this.insertBefore(node, this[index]);
     }
   }
 
diff --git a/tools/dom/templates/html/impl/impl_Notification.darttemplate b/tools/dom/templates/html/impl/impl_Notification.darttemplate
new file mode 100644
index 0000000..dd64491
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_Notification.darttemplate
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+  factory $CLASSNAME(String title, {String titleDir: null, String body: null, 
+      String bodyDir: null, String tag: null, String iconUrl: null}) {
+
+    var parsedOptions = {};
+    if (titleDir != null) parsedOptions['titleDir'] = titleDir;
+    if (body != null) parsedOptions['body'] = body;
+    if (bodyDir != null) parsedOptions['bodyDir'] = bodyDir;
+    if (tag != null) parsedOptions['tag'] = tag;
+    if (iconUrl != null) parsedOptions['iconUrl'] = iconUrl;
+
+    return $CLASSNAME._factory$CLASSNAME(title, parsedOptions);
+  }
+$!MEMBERS
+}
diff --git a/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate b/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
index edef225..8af6b9a 100644
--- a/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
+++ b/tools/dom/templates/html/impl/impl_RTCPeerConnection.darttemplate
@@ -39,6 +39,21 @@
 $else
   static bool get supported => true;
 $endif
+  Future<RtcSessionDescription> createOffer([Map mediaConstraints]) {
+    var completer = new Completer<RtcSessionDescription>();
+    _createOffer(
+        (value) { completer.complete(value); },
+        (error) { completer.completeError(error); }, mediaConstraints);
+    return completer.future;
+  }
+
+  Future<RtcSessionDescription> createAnswer([Map mediaConstraints]) {
+    var completer = new Completer<RtcSessionDescription>();
+    _createAnswer(
+        (value) { completer.complete(value); },
+        (error) { completer.completeError(error); }, mediaConstraints);
+    return completer.future;
+  }
 $!MEMBERS
 }
 
diff --git a/tools/dom/templates/html/impl/impl_ScriptProcessorNode.darttemplate b/tools/dom/templates/html/impl/impl_ScriptProcessorNode.darttemplate
new file mode 100644
index 0000000..15bf88e
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_ScriptProcessorNode.darttemplate
@@ -0,0 +1,43 @@
+// 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 $LIBRARY;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$NATIVESPEC {
+  Stream<AudioProcessingEvent> _eventStream;
+
+  /**
+   * Get a Stream that fires events when AudioProcessingEvents occur.
+   * This particular stream is special in that it only allows one listener to a
+   * given stream. Converting the returned Stream [asBroadcast] will likely ruin
+   * the soft-real-time properties which which these events are fired and can
+   * be processed.
+   */
+  Stream<AudioProcessingEvent> get onAudioProcess {
+    if (_eventStream == null) {
+      var controller = new StreamController();
+      var callback = (audioData) { 
+          if (controller.hasSubscribers) {
+            // This stream is a strange combination of broadcast and single
+            // subscriber streams. We only allow one listener, but if there is
+            // no listener, we don't queue up events, we just drop them on the
+            // floor.
+            controller.add(audioData);
+          }
+        };
+      _setEventListener(callback);
+      _eventStream = controller.stream;
+    }
+    return _eventStream;
+  }
+
+$if DART2JS
+    _setEventListener(callback) {
+      JS('void', '#.onaudioprocess = #', this,
+          convertDartClosureToJS(callback, 1));
+    }
+$endif
+
+$!MEMBERS
+}
diff --git a/tools/dom/templates/html/impl/impl_StorageInfo.darttemplate b/tools/dom/templates/html/impl/impl_StorageInfo.darttemplate
new file mode 100644
index 0000000..111ce8a
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_StorageInfo.darttemplate
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+$!MEMBERS
+  Future<StorageInfoUsage> queryUsageAndQuota(int storageType) {
+    var completer = new Completer<StorageInfoUsage>();
+    _queryUsageAndQuota(storageType,
+        (currentUsageInBytes, currentQuotaInBytes) { 
+          completer.complete(new StorageInfoUsage(currentUsageInBytes, 
+              currentQuotaInBytes));
+        },
+        (error) { completer.completeError(error); });
+    return completer.future;
+  }
+}
+
+/** 
+ * A simple container class for the two values that are returned from the
+ * futures in requestQuota and queryUsageAndQuota.
+ */
+class StorageInfoUsage {
+  final int currentUsageInBytes;
+  final int currentQuotaInBytes;
+  const StorageInfoUsage(this.currentUsageInBytes, this.currentQuotaInBytes);
+}
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index d8d90d6..2f1c194 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -225,5 +225,16 @@
   }
 $endif
 
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. Returns a [Future] whose value stores a reference to the
+   * sandboxed file system for use. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  Future<FileSystem> requestFileSystem(int size, {bool persistent: false}) {
+    return _requestFileSystem(persistent? 1 : 0, size);
+  }
 $!MEMBERS
 }
diff --git a/tools/dom/templates/html/impl/impl_WorkerContext.darttemplate b/tools/dom/templates/html/impl/impl_WorkerContext.darttemplate
new file mode 100644
index 0000000..9215272
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_WorkerContext.darttemplate
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+$if DART2JS
+  /**
+   * Gets an instance of the Indexed DB factory to being using Indexed DB.
+   *
+   * Use [IdbFactory.supported] to check if Indexed DB is supported on the
+   * current platform.
+   */
+  @SupportedBrowser(SupportedBrowser.CHROME, '23.0')
+  @SupportedBrowser(SupportedBrowser.FIREFOX, '15.0')
+  @SupportedBrowser(SupportedBrowser.IE, '10.0')
+  @Experimental
+  IdbFactory get indexedDB =>
+      JS('IdbFactory',
+         '#.indexedDB || #.webkitIndexedDB || #.mozIndexedDB',
+         this, this, this);
+$endif
+
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. Returns a [Future] whose value stores a reference to the
+   * sandboxed file system for use. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  @DomName('WorkerContext.webkitRequestFileSystem')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  Future<FileSystem> requestFileSystem(int size, {bool persistent: false}) {
+    return _requestFileSystem(persistent? 1 : 0, size);
+  }
+
+  /**
+   * Access a sandboxed file system of the specified `size`. If `persistent` is
+   * true, the application will request permission from the user to create
+   * lasting storage. This storage cannot be freed without the user's
+   * permission. This call will block until a reference to the synchronous file 
+   * system API has been obtained. Because the file system is sandboxed,
+   * applications cannot access file systems created in other web pages. 
+   */
+  @DomName('WorkerContext.webkitRequestFileSystemSync')
+  @DocsEditable
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  FileSystemSync requestFileSystemSync(int size, {bool persistent: false}) {
+    return _requestFileSystemSync(persistent? 1 : 0, size);
+  }
+$!MEMBERS
+}
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index eb6f2a9..7ae7698 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -14,8 +14,9 @@
  * wish to retrieve the HTML of the top-level page and print it out.
  * The easiest way to do that would be:
  *
- *     var httpRequest = HttpRequest.get('http://api.dartlang.org',
- *         (request) => print(request.responseText));
+ *     HttpRequest.getString('http://api.dartlang.org').then((response) {
+ *       print(response);
+ *     });
  *
  * **Important**: With the default behavior of this class, your
  * code making the request should be served from the same origin (domain name,
@@ -128,7 +129,23 @@
   static bool get supportsProgressEvent {
 $if DART2JS
     var xhr = new HttpRequest();
-    return JS('bool', '"onprogress" in #', xhr);
+    return JS('bool', '("onprogress" in #)', xhr);
+$else
+    return true;
+$endif
+  }
+
+  /**
+   * Checks to see if the current platform supports making cross origin
+   * requests.
+   *
+   * Note that even if cross origin requests are supported, they still may fail
+   * if the destination server does not support CORS requests.
+   */
+  static bool get supportsCrossOrigin {
+$if DART2JS
+    var xhr = new HttpRequest();
+    return JS('bool', '("withCredentials" in #)', xhr);
 $else
     return true;
 $endif
@@ -140,7 +157,7 @@
   static bool get supportsLoadEndEvent {
 $if DART2JS
     var xhr = new HttpRequest();
-    return JS('bool', '"onloadend" in #', xhr);
+    return JS('bool', '("onloadend" in #)', xhr);
 $else
     return true;
 $endif
diff --git a/tools/gyp/configurations_xcode.gypi b/tools/gyp/configurations_xcode.gypi
index 8ddb3dc..c308bdf 100644
--- a/tools/gyp/configurations_xcode.gypi
+++ b/tools/gyp/configurations_xcode.gypi
@@ -13,15 +13,7 @@
 
 {
   'variables': {
-    # To switch to the LLVM based backend create a ~/.gyp/include.gypi
-    # including:
-    #
-    # {
-    #   'variables': {
-    #     'xcode_gcc_version': 'com.apple.compilers.llvmgcc42',
-    #   }
-    # }
-    'xcode_gcc_version%': '4.2',
+    'xcode_gcc_version%': '<!(python <(DEPTH)/tools/gyp/find_mac_gcc_version.py)',
   },
   'target_defaults': {
     'configurations': {
diff --git a/tools/gyp/find_mac_gcc_version.py b/tools/gyp/find_mac_gcc_version.py
new file mode 100755
index 0000000..0af8412
--- /dev/null
+++ b/tools/gyp/find_mac_gcc_version.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# 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 re
+import subprocess
+import sys
+
+def main():
+  job = subprocess.Popen(['xcodebuild', '-version'],
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+  stdout, stderr = job.communicate()
+  if job.returncode != 0:
+    print >>sys.stderr, stdout
+    print >>sys.stderr, stderr
+    raise Exception('Error %d running xcodebuild!' % job.returncode)
+  matches = re.findall('^Xcode (\d+)\.(\d+)(\.(\d+))?$', stdout, re.MULTILINE)
+  if len(matches) > 0:
+    major = int(matches[0][0])
+    minor = int(matches[0][1])
+
+    if major >= 4:
+      return 'com.apple.compilers.llvmgcc42'
+    elif major == 3 and minor >= 1:
+      return '4.2'
+    else:
+      raise Exception('Unknown XCode Version "%s"' % version_match)
+  else:
+    raise Exception('Could not parse output of xcodebuild "%s"' % stdout)
+
+if __name__ == '__main__':
+  if sys.platform != 'darwin':
+    raise Exception("This script only runs on Mac")
+  print main()
diff --git a/tools/publish_pkg.py b/tools/publish_pkg.py
index 1c4cb59..55326ff 100755
--- a/tools/publish_pkg.py
+++ b/tools/publish_pkg.py
@@ -96,6 +96,9 @@
           pubspecFile.write(line)
       if not foundVersion:
         pubspecFile.write('\nversion: ' + version + '\n')
+      pubspecFile.write('environment:\n')
+      pubspecFile.write('  sdk: ">=' + version + '"\n')
+
   else:
     #
     # If there's a lib/ directory in the package, copy the package.
@@ -120,6 +123,8 @@
       pubspecFile.write('  ' + argv[1] + ' . This package will change in\n')
       pubspecFile.write('  unpredictable/incompatible ways without warning.\n')
       pubspecFile.write('dependencies:\n')
+      pubspecFile.write('environment:\n')
+      pubspecFile.write('  sdk: ">=' + version + '"\n')
 
     libpath = os.path.join(HOME, argv[1], '../libraries.dart')
     if os.path.exists(libpath):
@@ -133,11 +138,12 @@
 
   if not os.path.exists(os.path.join(tmpDir, pkgName, 'LICENSE')):
     with open(os.path.join(tmpDir, pkgName, 'LICENSE'), 'w') as licenseFile:
-      licenseFile.write('''
-Copyright 2012, the Dart project authors. All rights reserved.
+      licenseFile.write(
+'''Copyright 2012, the Dart project authors. All rights reserved.
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 met:
+
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above
@@ -147,6 +153,7 @@
     * Neither the name of Google Inc. nor the names of its
       contributors may be used to endorse or promote products derived
       from this software without specific prior written permission.
+
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/tools/test-runtime.dart b/tools/test-runtime.dart
deleted file mode 100755
index f7796a2..0000000
--- a/tools/test-runtime.dart
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/env dart
-// 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(ager): Get rid of this version of test.dart when we don't have
-// to worry about the special runtime checkout anymore.
-// This file is identical to test.dart with test suites in the
-// directories samples, client, compiler, and utils removed.
-
-library test;
-
-import "dart:io";
-import "testing/dart/test_runner.dart";
-import "testing/dart/test_options.dart";
-import "testing/dart/test_suite.dart";
-import "testing/dart/http_server.dart";
-import "testing/dart/utils.dart";
-import "testing/dart/test_progress.dart";
-
-import "../tests/co19/test_config.dart";
-import "../runtime/tests/vm/test_config.dart";
-
-/**
- * The directories that contain test suites which follow the conventions
- * required by [StandardTestSuite]'s forDirectory constructor.
- * New test suites should follow this convention because it makes it much
- * simpler to add them to test.dart.  Existing test suites should be
- * moved to here, if possible.
-*/
-final TEST_SUITE_DIRECTORIES = [
-  new Path('runtime/tests/vm'),
-  new Path('tests/corelib'),
-  new Path('tests/isolate'),
-  new Path('tests/language'),
-  new Path('tests/lib'),
-  new Path('tests/standalone'),
-  new Path('tests/utils'),
-];
-
-main() {
-  var startTime = new DateTime.now();
-  var optionsParser = new TestOptionsParser();
-  List<Map> configurations = optionsParser.parse(new Options().arguments);
-  if (configurations == null) return;
-
-  // Extract global options from first configuration.
-  var firstConf = configurations[0];
-  Map<String, RegExp> selectors = firstConf['selectors'];
-  var maxProcesses = firstConf['tasks'];
-  var progressIndicator = firstConf['progress'];
-  var verbose = firstConf['verbose'];
-  var printTiming = firstConf['time'];
-  var listTests = firstConf['list'];
-
-  if (!firstConf['append_logs'])  {
-    var file = new File(TestUtils.flakyFileName());
-    if (file.existsSync()) {
-      file.deleteSync();
-    }
-  }
-  // Print the configurations being run by this execution of
-  // test.dart. However, don't do it if the silent progress indicator
-  // is used. This is only needed because of the junit tests.
-  if (progressIndicator != 'silent') {
-    List output_words = configurations.length > 1 ?
-        ['Test configurations:'] : ['Test configuration:'];
-    for (Map conf in configurations) {
-      List settings = ['compiler', 'runtime', 'mode', 'arch']
-          .map((name) => conf[name]).toList();
-      if (conf['checked']) settings.add('checked');
-      output_words.add(settings.join('_'));
-    }
-    print(output_words.join(' '));
-  }
-
-  var testSuites = new List<TestSuite>();
-  for (var conf in configurations) {
-    if (selectors.containsKey('co19')) {
-      testSuites.add(new Co19TestSuite(conf));
-    }
-
-    if (conf['runtime'] == 'vm' && selectors.containsKey('vm')) {
-      // vm tests contain both cc tests (added here) and dart tests (added in
-      // [TEST_SUITE_DIRECTORIES]).
-      testSuites.add(new VMTestSuite(conf));
-    }
-
-    for (final testSuiteDir in TEST_SUITE_DIRECTORIES) {
-      final name = testSuiteDir.filename;
-      if (selectors.containsKey(name)) {
-        testSuites.add(new StandardTestSuite.forDirectory(conf, testSuiteDir));
-      }
-    }
-  }
-
-  void allTestsFinished() {
-    DebugLogger.close();
-  }
-
-  var maxBrowserProcesses = maxProcesses;
-
-  var eventListener = [];
-  if (progressIndicator != 'silent') {
-    var printFailures = true;
-    var formatter = new Formatter();
-    if (progressIndicator == 'color') {
-      progressIndicator = 'compact';
-      formatter = new ColorFormatter();
-    }
-    if (progressIndicator == 'diff') {
-      progressIndicator = 'compact';
-      formatter = new ColorFormatter();
-      printFailures = false;
-      eventListener.add(new StatusFileUpdatePrinter());
-    }
-    eventListener.add(new SummaryPrinter());
-    eventListener.add(new FlakyLogWriter());
-    if (printFailures) {
-      eventListener.add(new TestFailurePrinter(formatter));
-    }
-    eventListener.add(new ProgressIndicator.fromName(progressIndicator,
-                                                     startTime,
-                                                     formatter));
-    if (printTiming) {
-      eventListener.add(new TimingPrinter(startTime));
-    }
-    eventListener.add(new SkippedCompilationsPrinter());
-    eventListener.add(new LeftOverTempDirPrinter());
-  }
-  eventListener.add(new ExitCodeSetter());
-
-  // Start process queue.
-  new ProcessQueue(
-      maxProcesses,
-      maxBrowserProcesses,
-      startTime,
-      testSuites,
-      eventListener,
-      allTestsFinished,
-      verbose,
-      listTests);
-}
diff --git a/tools/test.dart b/tools/test.dart
index 7300699..9a23cfa 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -71,17 +71,14 @@
     new Path('sdk/lib/_internal/dartdoc'),
 ];
 
-main() {
+void testConfigurations(List<Map> configurations) {
   var startTime = new DateTime.now();
-  var optionsParser = new TestOptionsParser();
-  List<Map> configurations = optionsParser.parse(new Options().arguments);
-  if (configurations == null || configurations.length == 0) return;
-
   // Extract global options from first configuration.
   var firstConf = configurations[0];
   Map<String, RegExp> selectors = firstConf['selectors'];
   var maxProcesses = firstConf['tasks'];
   var progressIndicator = firstConf['progress'];
+  var failureSummary = firstConf['failure-summary'];
   BuildbotProgressIndicator.stepName = firstConf['step_name'];
   var verbose = firstConf['verbose'];
   var printTiming = firstConf['time'];
@@ -195,7 +192,11 @@
     eventListener.add(new SummaryPrinter());
     eventListener.add(new FlakyLogWriter());
     if (printFailures) {
-      eventListener.add(new TestFailurePrinter(formatter));
+      // The buildbot has it's own failure summary since it needs to wrap it
+      // into'@@@'-annotated sections.
+      var printFaiureSummary =
+          failureSummary && progressIndicator != 'buildbot';
+      eventListener.add(new TestFailurePrinter(printFaiureSummary, formatter));
     }
     eventListener.add(new ProgressIndicator.fromName(progressIndicator,
                                                      startTime,
@@ -227,3 +228,12 @@
     Future.wait(serverFutures).then((_) => startProcessQueue());
   }
 }
+
+void main() {
+  var optionsParser = new TestOptionsParser();
+  var configurations = optionsParser.parse(new Options().arguments);
+  if (configurations != null && configurations.length > 0) {
+    testConfigurations(configurations);
+  }
+}
+
diff --git a/tools/test.py b/tools/test.py
index 3ab247b..d047998 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -17,10 +17,7 @@
   tools_dir = os.path.dirname(os.path.realpath(__file__))
   current_directory = os.path.abspath('');
   client = os.path.abspath(os.path.join(tools_dir, '..'));
-  if current_directory == os.path.join(client, 'runtime'):
-    dart_script_name = 'test-runtime.dart'
-  else:
-    dart_script_name = 'test.dart'
+  dart_script_name = 'test.dart'
   dart_test_script = string.join([tools_dir, dart_script_name], os.sep)
   command = [utils.DartBinary(), dart_test_script] + args
   exit_code = subprocess.call(command)
diff --git a/tools/testing/dart/co19_test.dart b/tools/testing/dart/co19_test.dart
index 8b02ed1..f2ec040 100644
--- a/tools/testing/dart/co19_test.dart
+++ b/tools/testing/dart/co19_test.dart
@@ -21,6 +21,7 @@
 import "test_options.dart";
 import "test_suite.dart";
 import "test_progress.dart";
+import "../../test.dart" as test_dart;
 
 import "../../../tests/co19/test_config.dart";
 
@@ -41,7 +42,6 @@
       new Path(scriptFile.fullPathSync())
       .directoryPath.directoryPath.directoryPath.append('test.dart');
   TestUtils.testScriptPath = scriptPath.toNativePath();
-  var startTime = new DateTime.now();
   var optionsParser = new TestOptionsParser();
   List<Map> configurations = <Map>[];
   for (var commandLine in COMMAND_LINES) {
@@ -50,36 +50,12 @@
     arguments.addAll(options.arguments);
     arguments.addAll(commandLine);
     arguments.add('co19');
+    arguments.add('--progress=diff');
     configurations.addAll(optionsParser.parse(arguments));
   }
-  if (configurations == null || configurations.isEmpty) return;
 
-  var firstConfiguration = configurations[0];
-  Map<String, RegExp> selectors = firstConfiguration['selectors'];
-  var maxProcesses = firstConfiguration['tasks'];
-  var verbose = firstConfiguration['verbose'];
-  var listTests = firstConfiguration['list'];
-
-  var configurationIterator = configurations.iterator;
-  void enqueueConfiguration(ProcessQueue queue) {
-    if (!configurationIterator.moveNext()) return;
-    var configuration = configurationIterator.current;
-    for (String selector in selectors.keys) {
-      if (selector == 'co19') {
-        queue.addTestSuite(new Co19TestSuite(configuration));
-      } else {
-        throw 'Error: unexpected selector: "$selector".';
-      }
-    }
+  if (configurations != null || configurations.length > 0) {
+    test_dart.testConfigurations(configurations);
   }
-
-  // Start process queue.
-  var queue = new ProcessQueue(maxProcesses,
-                               'diff',
-                               startTime,
-                               false,
-                               enqueueConfiguration,
-                               () {},
-                               verbose,
-                               listTests);
 }
+
diff --git a/tools/testing/dart/http_server.dart b/tools/testing/dart/http_server.dart
index 4e68894..08c26f6 100644
--- a/tools/testing/dart/http_server.dart
+++ b/tools/testing/dart/http_server.dart
@@ -277,10 +277,20 @@
                         Path path,
                         File file) {
     if (allowedPort != -1) {
-      var origin = new Uri(request.headers.value('Origin'));
-      // Allow loading from http://*:$allowedPort in browsers.
-      var allowedOrigin =
+      var headerOrigin = request.headers.value('Origin');
+      var allowedOrigin;
+      if (headerOrigin != null) {
+        var origin = new Uri(headerOrigin);
+        // Allow loading from http://*:$allowedPort in browsers.
+        allowedOrigin =
           '${origin.scheme}://${origin.domain}:${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.
+        allowedOrigin = '*';
+      }
+
+
       response.headers.set("Access-Control-Allow-Origin", allowedOrigin);
       response.headers.set('Access-Control-Allow-Credentials', 'true');
     } else {
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 4a58683..a7f7983 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -162,6 +162,13 @@
                'silent', 'status', 'buildbot', 'diff'],
               'compact'),
           new _TestOptionSpecification(
+              'failure-summary',
+              'Print failure summary at the end',
+              ['--failure-summary'],
+              [],
+              false,
+              'bool'),
+          new _TestOptionSpecification(
               'step_name',
               'Step name for use by -pbuildbot',
               ['--step_name'],
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index 20a6646..72da366 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -314,16 +314,36 @@
 }
 
 class TestFailurePrinter extends EventListener {
+  bool _printSummary;
   var _formatter;
+  var _failureSummary = <String>[];
 
-  TestFailurePrinter([this._formatter = const Formatter()]);
+  TestFailurePrinter(this._printSummary,
+                     [this._formatter = const Formatter()]);
 
   void done(TestCase test) {
     if (test.lastCommandOutput.unexpectedOutput) {
-      for (var line in _buildFailureOutput(test, _formatter)) {
+      var lines = _buildFailureOutput(test, _formatter);
+      for (var line in lines) {
         print(line);
       }
       print('');
+      if (_printSummary) {
+        _failureSummary.addAll(lines);
+        _failureSummary.add('');
+      }
+    }
+  }
+
+  void allDone() {
+    if (_printSummary) {
+      print('\n=== Failure summary:\n');
+      if (!_failureSummary.isEmpty) {
+        for (String line in _failureSummary) {
+          print(line);
+        }
+        print('');
+      }
     }
   }
 }
@@ -406,7 +426,6 @@
       : super(startTime);
 
   void allDone() {
-    stdout.writeln('');
     if (_failedTests > 0) {
       // We may have printed many failure logs, so reprint the summary data.
       _printProgress();
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 9be1651..f81135d 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -962,6 +962,8 @@
                                                 command.arguments,
                                                 processOptions);
         processFuture.then((io.Process process) {
+          // Close stdin so that tests that try to block on input will fail.
+          process.stdin.close();
           void timeoutHandler() {
             timedOut = true;
             if (process != null) {
diff --git a/utils/lib/file_system_vm.dart b/utils/lib/file_system_vm.dart
index 12fb712..7c09b70 100644
--- a/utils/lib/file_system_vm.dart
+++ b/utils/lib/file_system_vm.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -12,7 +12,7 @@
 /** File system implementation using the vm api's. */
 class VMFileSystem implements FileSystem {
   void writeString(String path, String text) {
-    var file = new File(path).openSync(FileMode.WRITE);
+    var file = new File(path).openSync(mode: FileMode.WRITE);
     file.writeStringSync(text);
     file.closeSync();
   }
diff --git a/utils/pub/entrypoint.dart b/utils/pub/entrypoint.dart
index e1bed5f..a190c1b 100644
--- a/utils/pub/entrypoint.dart
+++ b/utils/pub/entrypoint.dart
@@ -73,13 +73,14 @@
     var packageDir = path.join(packagesDir, id.name);
     var future = defer(() {
       ensureDir(path.dirname(packageDir));
-      if (!dirExists(packageDir)) return;
 
-      // TODO(nweiz): figure out when to actually delete the directory, and when
-      // we can just re-use the existing symlink.
-      log.fine("Deleting package directory for ${id.name} before install.");
-      return deleteDir(packageDir);
-    }).then((_) {
+      if (dirExists(packageDir)) {
+        // TODO(nweiz): figure out when to actually delete the directory, and
+        // when we can just re-use the existing symlink.
+        log.fine("Deleting package directory for ${id.name} before install.");
+        deleteDir(packageDir);
+      }
+
       if (id.source.shouldCache) {
         return cache.install(id).then(
             (pkg) => createPackageSymlink(id.name, pkg.dir, packageDir));
@@ -130,7 +131,8 @@
   /// Removes the old packages directory, installs all dependencies listed in
   /// [packageVersions], and writes a [LockFile].
   Future _installDependencies(List<PackageId> packageVersions) {
-    return cleanDir(packagesDir).then((_) {
+    return new Future.of(() {
+      cleanDir(packagesDir);
       return Future.wait(packageVersions.map((id) {
         if (id.isRoot) return new Future.immediate(id);
         return install(id);
@@ -291,11 +293,16 @@
     }).then(flatten);
   }
 
-  /// Creates a symlink to the `packages` directory in [dir] if none exists.
+  /// Creates a symlink to the `packages` directory in [dir]. Will replace one
+  /// if already there.
   Future _linkSecondaryPackageDir(String dir) {
     return defer(() {
       var symlink = path.join(dir, 'packages');
-      if (entryExists(symlink)) return;
+      if (fileExists(symlink)) {
+        deleteFile(symlink);
+      } else if (dirExists(symlink)) {
+        deleteDir(symlink);
+      }
       return createSymlink(packagesDir, symlink, relative: true);
     });
   }
diff --git a/utils/pub/hosted_source.dart b/utils/pub/hosted_source.dart
index 00e489b..bb4345c 100644
--- a/utils/pub/hosted_source.dart
+++ b/utils/pub/hosted_source.dart
@@ -82,8 +82,9 @@
         // Now that the install has succeeded, move it to the real location in
         // the cache. This ensures that we don't leave half-busted ghost
         // directories in the user's pub cache if an install fails.
-        return renameDir(tempDir, destPath);
-      }).then((_) => true);
+        renameDir(tempDir, destPath);
+        return true;
+      });
     });
   }
 
diff --git a/utils/pub/io.dart b/utils/pub/io.dart
index 1d9b824..f4bb6de 100644
--- a/utils/pub/io.dart
+++ b/utils/pub/io.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -20,8 +20,6 @@
 
 export '../../pkg/http/lib/http.dart' show ByteStream;
 
-final NEWLINE_PATTERN = new RegExp("\r\n?|\n\r?");
-
 /// Returns whether or not [entry] is nested somewhere within [dir]. This just
 /// performs a path comparison; it doesn't look at the actual filesystem.
 bool isBeneath(String entry, String dir) {
@@ -29,15 +27,17 @@
   return !path.isAbsolute(relative) && path.split(relative)[0] != '..';
 }
 
-/// Determines if a file or directory at [path] exists.
-bool entryExists(String path) => fileExists(path) || dirExists(path);
+/// Determines if a file or directory exists at [path].
+bool entryExists(String path) => dirExists(path) || fileExists(path);
 
-/// Determines if [file] exists on the file system.
-bool fileExists(String file) => new File(file).existsSync();
+/// Determines if [file] exists on the file system. Will also return `true` if
+/// [file] points to a symlink, even a directory symlink.
+bool fileExists(String file) =>
+    new File(file).existsSync() || new Link(file).existsSync();
 
 /// Reads the contents of the text file [file].
 String readTextFile(String file) =>
-    new File(file).readAsStringSync(Encoding.UTF_8);
+    new File(file).readAsStringSync(encoding: Encoding.UTF_8);
 
 /// Reads the contents of the binary file [file].
 List<int> readBinaryFile(String file) {
@@ -69,7 +69,7 @@
 /// Creates [file] and writes [contents] to it.
 String writeBinaryFile(String file, List<int> contents) {
   log.io("Writing ${contents.length} bytes to binary file $file.");
-  new File(file).openSync(FileMode.WRITE)
+  new File(file).openSync(mode: FileMode.WRITE)
       ..writeListSync(contents, 0, contents.length)
       ..closeSync();
   log.fine("Wrote text file $file.");
@@ -126,11 +126,10 @@
   return tempDir.path;
 }
 
-/// Asynchronously recursively deletes [dir]. Returns a [Future] that completes
-/// when the deletion is done.
-Future<String> deleteDir(String dir) {
-  return _attemptRetryable(() => log.ioAsync("delete directory $dir",
-      new Directory(dir).delete(recursive: true).then((_) => dir)));
+/// Recursively deletes [dir].
+void deleteDir(String dir) {
+  log.io("Deleting directory $dir.");
+  new Directory(dir).deleteSync(recursive: true);
 }
 
 /// Asynchronously lists the contents of [dir]. If [recursive] is `true`, lists
@@ -165,15 +164,14 @@
             if (!includeHiddenFiles && path.basename(file).startsWith('.')) {
               return;
             }
-            contents.add(path.join(dir, path.basename(file)));
+            contents.add(file);
           } else if (entity is Directory) {
             var file = entity.path;
             if (!includeHiddenFiles && path.basename(file).startsWith('.')) {
               return;
             }
-            file = path.join(dir, path.basename(file));
             contents.add(file);
-            // TODO(nweiz): don't manually recurse once issue 7358 is fixed.
+            // TODO(nweiz): don't manually recurse once issue 4794 is fixed.
             // Note that once we remove the manual recursion, we'll need to
             // explicitly filter out files in hidden directories.
             if (recursive) {
@@ -205,59 +203,24 @@
 bool dirExists(String dir) => new Directory(dir).existsSync();
 
 /// "Cleans" [dir]. If that directory already exists, it will be deleted. Then a
-/// new empty directory will be created. Returns a [Future] that completes when
-/// the new clean directory is created.
-Future<String> cleanDir(String dir) {
-  return defer(() {
-    if (dirExists(dir)) {
-      // Delete it first.
-      return deleteDir(dir).then((_) => createDir(dir));
-    } else {
-      // Just create it.
-      return createDir(dir);
-    }
-  });
-}
-
-/// Renames (i.e. moves) the directory [from] to [to]. Returns a [Future] with
-/// the destination directory.
-Future<String> renameDir(String from, String to) {
-  log.io("Renaming directory $from to $to.");
-
-  return _attemptRetryable(() => new Directory(from).rename(to)).then((dir) {
-    log.fine("Renamed directory $from to $to.");
-    return to;
-  });
-}
-
-/// On Windows, we sometimes get failures where the directory is still in use
-/// when we try to do something with it. This is usually because the OS hasn't
-/// noticed yet that a process using that directory has closed. To be a bit
-/// more resilient, we wait and retry a few times.
-///
-/// Takes a [callback] which returns a future for the operation being attempted.
-/// If that future completes with an error, it will slepp and then [callback]
-/// will be invoked again to retry the operation. It will try a few times before
-/// giving up.
-Future _attemptRetryable(Future callback()) {
-  // Only do lame retry logic on Windows.
-  if (Platform.operatingSystem != 'windows') return callback();
-
-  var attempts = 0;
-  makeAttempt(_) {
-    attempts++;
-    return callback().catchError((e) {
-      if (attempts >= 10) {
-        throw 'Could not complete operation. Gave up after $attempts attempts.';
-      }
-
-      // Wait a bit and try again.
-      log.fine("Operation failed, retrying (attempt $attempts).");
-      return sleep(500).then(makeAttempt);
-    });
+/// new empty directory will be created.
+void cleanDir(String dir) {
+  if (dirExists(dir)) {
+    // Delete it first.
+    deleteDir(dir);
+  } else if (fileExists(dir)) {
+    // If there is a non-directory there (file or symlink), delete it.
+    deleteFile(dir);
   }
 
-  return makeAttempt(null);
+  // Just create it.
+  createDir(dir);
+}
+
+/// Renames (i.e. moves) the directory [from] to [to].
+void renameDir(String from, String to) {
+  log.io("Renaming directory $from to $to.");
+  new Directory(from).renameSync(to);
 }
 
 /// Creates a new symlink at path [symlink] that points to [target]. Returns a
@@ -444,7 +407,7 @@
       .then((result) {
     // TODO(rnystrom): Remove this and change to returning one string.
     List<String> toLines(String output) {
-      var lines = output.split(NEWLINE_PATTERN);
+      var lines = splitLines(output);
       if (!lines.isEmpty && lines.last == "") lines.removeLast();
       return lines;
     }
@@ -610,16 +573,16 @@
 
 /// Creates a temporary directory and passes its path to [fn]. Once the [Future]
 /// returned by [fn] completes, the temporary directory and all its contents
-/// will be deleted.
+/// will be deleted. [fn] can also return `null`, in which case the temporary
+/// directory is deleted immediately afterwards.
 ///
 /// Returns a future that completes to the value that the future returned from
 /// [fn] completes to.
 Future withTempDir(Future fn(String path)) {
   return defer(() {
     var tempDir = createTempDir();
-    return fn(tempDir).whenComplete(() {
-      return deleteDir(tempDir);
-    });
+    return new Future.of(() => fn(tempDir))
+        .whenComplete(() => deleteDir(tempDir));
   });
 }
 
diff --git a/utils/pub/log.dart b/utils/pub/log.dart
index 870a305..ec3fee9 100644
--- a/utils/pub/log.dart
+++ b/utils/pub/log.dart
@@ -6,7 +6,9 @@
 library log;
 
 import 'dart:async';
+
 import 'io.dart';
+import 'utils.dart';
 
 typedef LogFn(Entry entry);
 final Map<Level, LogFn> _loggers = new Map<Level, LogFn>();
@@ -73,7 +75,7 @@
 void write(Level level, message) {
   if (_loggers.isEmpty) showNormal();
 
-  var lines = message.toString().split(NEWLINE_PATTERN);
+  var lines = splitLines(message.toString());
   var entry = new Entry(level, lines);
 
   var logFn = _loggers[level];
diff --git a/utils/pub/package.dart b/utils/pub/package.dart
index 8e96cbd..b7c2f99 100644
--- a/utils/pub/package.dart
+++ b/utils/pub/package.dart
@@ -45,16 +45,17 @@
   /// chosen.
   Future<String> get readmePath {
     return listDir(dir).then((entries) {
-      var readmes = entries.where((entry) => entry.contains(_README_REGEXP));
+      var readmes = entries.map(path.basename).
+          where((entry) => entry.contains(_README_REGEXP));
       if (readmes.isEmpty) return;
 
-      return readmes.min((readme1, readme2) {
+      return path.join(dir, readmes.min((readme1, readme2) {
         var extensions1 = ".".allMatches(readme1).length;
         var extensions2 = ".".allMatches(readme2).length;
         var comparison = extensions1.compareTo(extensions2);
         if (comparison != 0) return comparison;
         return readme1.compareTo(readme2);
-      });
+      }));
     });
   }
 
diff --git a/utils/pub/path_source.dart b/utils/pub/path_source.dart
index bfa09e7..6cdc070 100644
--- a/utils/pub/path_source.dart
+++ b/utils/pub/path_source.dart
@@ -106,14 +106,16 @@
   void _validatePath(String name, description) {
     var dir = description["path"];
 
+    if (dirExists(dir)) return;
+
+    // Check this after dirExists() so that symlinks to directories don't get
+    // confused as files.
     if (fileExists(dir)) {
       throw new FormatException(
           "Path dependency for package '$name' must refer to a "
           "directory, not a file. Was '$dir'.");
     }
 
-    if (!dirExists(dir)) {
-      throw new FormatException("Could not find package '$name' at '$dir'.");
-    }
+    throw new FormatException("Could not find package '$name' at '$dir'.");
   }
 }
diff --git a/utils/pub/source.dart b/utils/pub/source.dart
index 53c56b3..60d455b 100644
--- a/utils/pub/source.dart
+++ b/utils/pub/source.dart
@@ -119,7 +119,8 @@
         if (!isCorrupted) return true;
 
         // Busted, so wipe out the package and reinstall.
-        return deleteDir(packageDir).then((_) => false);
+        deleteDir(packageDir);
+        return false;
       });
     }).then((isInstalled) {
       if (isInstalled) return true;
diff --git a/utils/pub/system_cache.dart b/utils/pub/system_cache.dart
index e93f8f4..b6467b5 100644
--- a/utils/pub/system_cache.dart
+++ b/utils/pub/system_cache.dart
@@ -108,12 +108,10 @@
     return io.createTempDir(path.join(temp, 'dir'));
   }
 
-  /// Delete's the system cache's internal temp directory.
-  Future deleteTempDir() {
+  /// Deletes the system cache's internal temp directory.
+  void deleteTempDir() {
     log.fine('Clean up system cache temp directory $tempDir.');
-    return defer(() {
-      if (!dirExists(tempDir)) return;
-      return deleteDir(tempDir);
-    });
+    if (!dirExists(tempDir)) return;
+    deleteDir(tempDir);
   }
 }
diff --git a/utils/pub/utils.dart b/utils/pub/utils.dart
index 1d687f3..d354e68 100644
--- a/utils/pub/utils.dart
+++ b/utils/pub/utils.dart
@@ -218,9 +218,14 @@
   return new Pair<Stream, Stream>(controller1.stream, controller2.stream);
 }
 
-/// A regular expression matching a line termination character or character
-/// sequence.
-final RegExp _lineRegexp = new RegExp(r"\r\n|\r|\n");
+/// A regular expression matching a trailing CR character.
+final _trailingCR = new RegExp(r"\r$");
+
+// TODO(nweiz): Use `text.split(new RegExp("\r\n?|\n\r?"))` when issue 9360 is
+// fixed.
+/// Splits [text] on its line breaks in a Windows-line-break-friendly way.
+List<String> splitLines(String text) =>
+  text.split("\n").map((line) => line.replaceFirst(_trailingCR, "")).toList();
 
 /// Converts a stream of arbitrarily chunked strings into a line-by-line stream.
 /// The lines don't include line termination characters. A single trailing
@@ -229,7 +234,7 @@
   var buffer = new StringBuffer();
   return stream.transform(new StreamTransformer(
       handleData: (chunk, sink) {
-        var lines = chunk.split(_lineRegexp);
+        var lines = splitLines(chunk);
         var leftover = lines.removeLast();
         for (var line in lines) {
           if (!buffer.isEmpty) {
@@ -337,3 +342,28 @@
 /// replacing `+` with ` `.
 String urlDecode(String encoded) =>
   decodeUriComponent(encoded.replaceAll("+", " "));
+
+/// Takes a simple data structure (composed of [Map]s, [List]s, scalar objects,
+/// and [Future]s) and recursively resolves all the [Future]s contained within.
+/// Completes with the fully resolved structure.
+Future awaitObject(object) {
+  // Unroll nested futures.
+  if (object is Future) return object.then(awaitObject);
+  if (object is Collection) {
+    return Future.wait(object.map(awaitObject).toList());
+  }
+  if (object is! Map) return new Future.immediate(object);
+
+  var pairs = <Future<Pair>>[];
+  object.forEach((key, value) {
+    pairs.add(awaitObject(value)
+        .then((resolved) => new Pair(key, resolved)));
+  });
+  return Future.wait(pairs).then((resolvedPairs) {
+    var map = {};
+    for (var pair in resolvedPairs) {
+      map[pair.first] = pair.last;
+    }
+    return map;
+  });
+}
diff --git a/utils/pub/validator/compiled_dartdoc.dart b/utils/pub/validator/compiled_dartdoc.dart
index cd83e76..3ab5c34 100644
--- a/utils/pub/validator/compiled_dartdoc.dart
+++ b/utils/pub/validator/compiled_dartdoc.dart
@@ -22,7 +22,7 @@
   Future validate() {
     return listDir(entrypoint.root.dir, recursive: true).then((entries) {
       for (var entry in entries) {
-        if (path.basename(entry) != "nav.json") return false;
+        if (path.basename(entry) != "nav.json") continue;
         var dir = path.dirname(entry);
 
         // Look for tell-tale Dartdoc output files all in the same directory.
diff --git a/utils/pub/version_solver.dart b/utils/pub/version_solver.dart
index c00cda5..5b055d8 100644
--- a/utils/pub/version_solver.dart
+++ b/utils/pub/version_solver.dart
@@ -183,7 +183,8 @@
     for (var dependerName in dependency.dependers) {
       var depender = getDependency(dependerName);
       var locked = lockFile.packages[dependerName];
-      if (locked != null && depender.version == locked.version) {
+      if (locked != null && depender.version == locked.version &&
+          depender.source.name == locked.source.name) {
         enqueue(new UnlockPackage(depender));
         return true;
       }
@@ -360,7 +361,7 @@
     // If the dependency is on a package in the lockfile, use the lockfile's
     // version for that package if it's valid given the other constraints.
     var lockedPackage = solver.lockFile.packages[name];
-    if (lockedPackage != null) {
+    if (lockedPackage != null && newDependency.source == lockedPackage.source) {
       var lockedVersion = lockedPackage.version;
       if (newConstraint.allows(lockedVersion)) {
         solver.enqueue(
diff --git a/utils/tests/pub/descriptor.dart b/utils/tests/pub/descriptor.dart
new file mode 100644
index 0000000..957299c
--- /dev/null
+++ b/utils/tests/pub/descriptor.dart
@@ -0,0 +1,178 @@
+// 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.
+
+/// Pub-specific scheduled_test descriptors.
+library descriptor;
+
+import '../../../pkg/oauth2/lib/oauth2.dart' as oauth2;
+import '../../../pkg/scheduled_test/lib/scheduled_server.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
+import '../../../pkg/scheduled_test/lib/descriptor.dart';
+
+import '../../pub/utils.dart';
+import 'descriptor/git.dart';
+import 'descriptor/tar.dart';
+import 'test_pub.dart';
+
+export '../../../pkg/scheduled_test/lib/descriptor.dart';
+export 'descriptor/git.dart';
+export 'descriptor/tar.dart';
+
+/// Creates a new [GitRepoDescriptor] with [name] and [contents].
+GitRepoDescriptor git(String name, [Iterable<Descriptor> contents]) =>
+    new GitRepoDescriptor(name, contents == null ? <Descriptor>[] : contents);
+
+/// Creates a new [TarRepoDescriptor] with [name] and [contents].
+TarFileDescriptor tar(String name, [Iterable<Descriptor> contents]) =>
+    new TarFileDescriptor(name, contents == null ? <Descriptor>[] : contents);
+
+/// Describes a package that passes all validation.
+Descriptor get validPackage => dir(appPath, [
+  libPubspec("test_pkg", "1.0.0"),
+  file("LICENSE", "Eh, do what you want."),
+  dir("lib", [
+    file("test_pkg.dart", "int i = 1;")
+  ])
+]);
+
+/// Describes a file named `pubspec.yaml` with the given YAML-serialized
+/// [contents], which should be a serializable object.
+///
+/// [contents] may contain [Future]s that resolve to serializable objects,
+/// which may in turn contain [Future]s recursively.
+Descriptor pubspec(Map contents) {
+  return async(awaitObject(contents).then((resolvedContents) =>
+      file("pubspec.yaml", yaml(resolvedContents))));
+}
+
+/// Describes a file named `pubspec.yaml` for an application package with the
+/// given [dependencies].
+Descriptor appPubspec(List dependencies) {
+  return pubspec({
+    "name": "myapp",
+    "dependencies": dependencyListToMap(dependencies)
+  });
+}
+
+/// Describes a file named `pubspec.yaml` for a library package with the given
+/// [name], [version], and [deps]. If "sdk" is given, then it adds an SDK
+/// constraint on that version.
+Descriptor libPubspec(String name, String version, {List deps, String sdk}) {
+  var map = packageMap(name, version, deps);
+
+  if (sdk != null) {
+    map["environment"] = {
+      "sdk": sdk
+    };
+  }
+
+  return pubspec(map);
+}
+
+/// Describes a directory named `lib` containing a single dart file named
+/// `<name>.dart` that contains a line of Dart code.
+Descriptor libDir(String name, [String code]) {
+  // Default to printing the name if no other code was given.
+  if (code == null) {
+    code = name;
+  }
+
+  return dir("lib", [
+    file("$name.dart", 'main() => "$code";')
+  ]);
+}
+
+/// Describes a directory for a package installed from the mock package server.
+/// This directory is of the form found in the global package cache.
+Descriptor packageCacheDir(String name, String version) {
+  return dir("$name-$version", [
+    libDir(name, '$name $version')
+  ]);
+}
+
+/// Describes a directory for a Git package. This directory is of the form
+/// found in the revision cache of the global package cache.
+Descriptor gitPackageRevisionCacheDir(String name, [int modifier]) {
+  var value = name;
+  if (modifier != null) value = "$name $modifier";
+  return pattern(new RegExp("$name${r'-[a-f0-9]+'}"),
+      (dirName) => dir(dirName, [libDir(name, value)]));
+}
+
+/// Describes a directory for a Git package. This directory is of the form
+/// found in the repo cache of the global package cache.
+Descriptor gitPackageRepoCacheDir(String name) {
+  return pattern(new RegExp("$name${r'-[a-f0-9]+'}"),
+      (dirName) => dir(dirName, [
+    dir('hooks'),
+    dir('info'),
+    dir('objects'),
+    dir('refs')
+  ]));
+}
+
+/// Describes the `packages/` directory containing all the given [packages],
+/// which should be name/version pairs. The packages will be validated against
+/// the format produced by the mock package server.
+///
+/// A package with a null version should not be installed.
+Descriptor packagesDir(Map<String, String> packages) {
+  var contents = <Descriptor>[];
+  packages.forEach((name, version) {
+    if (version == null) {
+      contents.add(nothing(name));
+    } else {
+      contents.add(dir(name, [
+        file("$name.dart", 'main() => "$name $version";')
+      ]));
+    }
+  });
+  return dir(packagesPath, contents);
+}
+
+/// Describes the global package cache directory containing all the given
+/// [packages], which should be name/version pairs. The packages will be
+/// validated against the format produced by the mock package server.
+///
+/// A package's value may also be a list of versions, in which case all
+/// versions are expected to be installed.
+Descriptor cacheDir(Map packages) {
+  var contents = <Descriptor>[];
+  packages.forEach((name, versions) {
+    if (versions is! List) versions = [versions];
+    for (var version in versions) {
+      contents.add(packageCacheDir(name, version));
+    }
+  });
+  return dir(cachePath, [
+    dir('hosted', [
+      async(port.then((p) => dir('localhost%58$p', contents)))
+    ])
+  ]);
+}
+
+/// Describes the file in the system cache that contains the client's OAuth2
+/// credentials. The URL "/token" on [server] will be used as the token
+/// endpoint for refreshing the access token.
+Descriptor credentialsFile(
+    ScheduledServer server,
+    String accessToken,
+    {String refreshToken,
+     DateTime expiration}) {
+  return async(server.url.then((url) {
+    return dir(cachePath, [
+      file('credentials.json', new oauth2.Credentials(
+          accessToken,
+          refreshToken,
+          url.resolve('/token'),
+          ['https://www.googleapis.com/auth/userinfo.email'],
+          expiration).toJson())
+    ]);
+  }));
+}
+
+/// Describes the application directory, containing only a pubspec specifying
+/// the given [dependencies].
+DirectoryDescriptor appDir(List dependencies) =>
+  dir(appPath, [appPubspec(dependencies)]);
diff --git a/utils/tests/pub/descriptor/git.dart b/utils/tests/pub/descriptor/git.dart
new file mode 100644
index 0000000..5e4b3b2
--- /dev/null
+++ b/utils/tests/pub/descriptor/git.dart
@@ -0,0 +1,78 @@
+// 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 descriptor.git;
+
+import 'dart:async';
+
+import '../../../../pkg/pathos/lib/path.dart' as path;
+import '../../../../pkg/scheduled_test/lib/scheduled_test.dart';
+import '../../../../pkg/scheduled_test/lib/descriptor.dart';
+
+import '../../../pub/git.dart' as git;
+
+/// Describes a Git repository and its contents.
+class GitRepoDescriptor extends DirectoryDescriptor {
+  GitRepoDescriptor(String name, List<Descriptor> contents)
+      : super(name, contents);
+
+  /// Creates the Git repository and commits the contents.
+  Future create([String parent]) => schedule(() {
+    return super.create(parent).then((_) {
+      return _runGitCommands(parent, [
+        ['init'],
+        ['add', '.'],
+        ['commit', '-m', 'initial commit']
+      ]);
+    });
+  }, 'creating Git repo:\n${describe()}');
+
+  /// Writes this descriptor to the filesystem, than commits any changes from
+  /// the previous structure to the Git repo.
+  ///
+  /// [parent] defaults to [defaultRoot].
+  Future commit([String parent]) => schedule(() {
+    return super.create(parent).then((_) {
+      return _runGitCommands(parent, [
+        ['add', '.'],
+        ['commit', '-m', 'update']
+      ]);
+    });
+  }, 'committing Git repo:\n${describe()}');
+
+  /// Return a Future that completes to the commit in the git repository
+  /// referred to by [ref] at the current point in the scheduled test run.
+  ///
+  /// [parent] defaults to [defaultRoot].
+  Future<String> revParse(String ref, [String parent]) => schedule(() {
+    return _runGit(['rev-parse', ref], parent).then((output) => output[0]);
+  }, 'parsing revision $ref for Git repo:\n${describe()}');
+
+  /// Schedule a Git command to run in this repository.
+  ///
+  /// [parent] defaults to [defaultRoot].
+  Future runGit(List<String> args, [String parent]) => schedule(() {
+    return _runGit(args, parent);
+  }, "running 'git ${args.join(' ')}' in Git repo:\n${describe()}");
+
+  Future _runGitCommands(String parent, List<List<String>> commands) =>
+      Future.forEach(commands, (command) => _runGit(command, parent));
+
+  Future<List<String>> _runGit(List<String> args, String parent) {
+    // Explicitly specify the committer information. Git needs this to commit
+    // and we don't want to rely on the buildbots having this already set up.
+    var environment = {
+      'GIT_AUTHOR_NAME': 'Pub Test',
+      'GIT_AUTHOR_EMAIL': 'pub@dartlang.org',
+      'GIT_COMMITTER_NAME': 'Pub Test',
+      'GIT_COMMITTER_EMAIL': 'pub@dartlang.org'
+    };
+
+    if (parent == null) parent = defaultRoot;
+    return git.run(args,
+        workingDir: path.join(parent, name),
+        environment: environment);
+  }
+}
+
diff --git a/utils/tests/pub/descriptor/tar.dart b/utils/tests/pub/descriptor/tar.dart
new file mode 100644
index 0000000..ef9b1f3
--- /dev/null
+++ b/utils/tests/pub/descriptor/tar.dart
@@ -0,0 +1,53 @@
+// 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 descriptor.tar;
+
+import 'dart:io';
+import 'dart:async';
+
+import '../../../../pkg/pathos/lib/path.dart' as path;
+import '../../../../pkg/scheduled_test/lib/scheduled_test.dart';
+import '../../../../pkg/scheduled_test/lib/descriptor.dart';
+
+import '../../../pub/io.dart';
+import '../../../pub/utils.dart';
+
+/// Describes a tar file and its contents.
+class TarFileDescriptor extends DirectoryDescriptor {
+  TarFileDescriptor(String name, List<Descriptor> contents)
+      : super(name, contents);
+
+  /// Creates the files and directories within this tar file, then archives
+  /// them, compresses them, and saves the result to [parentDir].
+  Future<String> create([String parent]) => schedule(() {
+    if (parent == null) parent = defaultRoot;
+    return withTempDir((tempDir) {
+      return Future.wait(contents.map((entry) {
+        return entry.create(tempDir);
+      })).then((_) {
+        return listDir(tempDir, recursive: true, includeHiddenFiles: true);
+      }).then((createdContents) {
+        return createTarGz(createdContents, baseDir: tempDir).toBytes();
+      }).then((bytes) {
+        var file = path.join(parent, name);
+        writeBinaryFile(file, bytes);
+        return file;
+      });
+    });
+  }, 'creating tar file:\n${describe()}');
+
+  /// Validates that the `.tar.gz` file at [path] contains the expected
+  /// contents.
+  Future validate([String parent]) {
+    throw "TODO(nweiz): implement this";
+  }
+
+  Stream<List<int>> read() {
+    return new Stream<List<int>>.fromFuture(withTempDir((tempDir) {
+      return create(tempDir).then((_) =>
+          readBinaryFile(path.join(tempDir, name)));
+    }));
+  }
+}
diff --git a/utils/tests/pub/dev_dependency_test.dart b/utils/tests/pub/dev_dependency_test.dart
index 961d208..8934302 100644
--- a/utils/tests/pub/dev_dependency_test.dart
+++ b/utils/tests/pub/dev_dependency_test.dart
@@ -4,113 +4,114 @@
 
 import '../../../pkg/pathos/lib/path.dart' as path;
 
+import 'descriptor.dart' as d;
 import 'test_pub.dart';
 
 main() {
   initConfig();
   integration("includes root package's dev dependencies", () {
-    dir('foo', [
-      libDir('foo'),
-      libPubspec('foo', '0.0.1')
-    ]).scheduleCreate();
+    d.dir('foo', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '0.0.1')
+    ]).create();
 
-    dir('bar', [
-      libDir('bar'),
-      libPubspec('bar', '0.0.1')
-    ]).scheduleCreate();
+    d.dir('bar', [
+      d.libDir('bar'),
+      d.libPubspec('bar', '0.0.1')
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dev_dependencies": {
           "foo": {"path": "../foo"},
           "bar": {"path": "../bar"},
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [
-        file("foo.dart", 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
       ]),
-      dir("bar", [
-        file("bar.dart", 'main() => "bar";')
+      d.dir("bar", [
+        d.file("bar.dart", 'main() => "bar";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 
   integration("includes dev dependency's transitive dependencies", () {
-    dir('foo', [
-      libDir('foo'),
-      libPubspec('foo', '0.0.1', deps: [
+    d.dir('foo', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '0.0.1', deps: [
         {"path": "../bar"}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir('bar', [
-      libDir('bar'),
-      libPubspec('bar', '0.0.1')
-    ]).scheduleCreate();
+    d.dir('bar', [
+      d.libDir('bar'),
+      d.libPubspec('bar', '0.0.1')
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dev_dependencies": {
           "foo": {"path": "../foo"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [
-        file("foo.dart", 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
       ]),
-      dir("bar", [
-        file("bar.dart", 'main() => "bar";')
+      d.dir("bar", [
+        d.file("bar.dart", 'main() => "bar";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 
   integration("ignores transitive dependency's dev dependencies", () {
-    dir('foo', [
-      libDir('foo'),
-      pubspec({
+    d.dir('foo', [
+      d.libDir('foo'),
+      d.pubspec({
         "name": "foo",
         "version": "0.0.1",
         "dev_dependencies": {
           "bar": {"path": "../bar"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
-    dir('bar', [
-      libDir('bar'),
-      libPubspec('bar', '0.0.1')
-    ]).scheduleCreate();
+    d.dir('bar', [
+      d.libDir('bar'),
+      d.libPubspec('bar', '0.0.1')
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": "../foo"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [
-        file("foo.dart", 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
       ]),
-      nothing("bar")
-    ]).scheduleValidate();
+      d.nothing("bar")
+    ]).validate();
   });
 }
\ No newline at end of file
diff --git a/utils/tests/pub/install/broken_symlink_test.dart b/utils/tests/pub/install/broken_symlink_test.dart
index 07a5530..76540dc 100644
--- a/utils/tests/pub/install/broken_symlink_test.dart
+++ b/utils/tests/pub/install/broken_symlink_test.dart
@@ -7,18 +7,18 @@
 import 'dart:io';
 
 import '../../../../pkg/pathos/lib/path.dart' as path;
-import '../../../../pkg/unittest/lib/unittest.dart';
 
+import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
 main() {
   initConfig();
   integration('replaces a broken "packages" symlink', () {
-    dir(appPath, [
-      appPubspec([]),
-      libDir('foo'),
-      dir("bin")
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.appPubspec([]),
+      d.libDir('foo'),
+      d.dir("bin")
+    ]).create();
 
     // Create a broken "packages" symlink in "bin".
     scheduleSymlink("nonexistent", path.join(appPath, "packages"));
@@ -26,23 +26,23 @@
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(appPath, [
-      dir("bin", [
-        dir("packages", [
-          dir("myapp", [
-            file('foo.dart', 'main() => "foo";')
+    d.dir(appPath, [
+      d.dir("bin", [
+        d.dir("packages", [
+          d.dir("myapp", [
+            d.file('foo.dart', 'main() => "foo";')
           ])
         ])
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 
   integration('replaces a broken secondary "packages" symlink', () {
-    dir(appPath, [
-      appPubspec([]),
-      libDir('foo'),
-      dir("bin")
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.appPubspec([]),
+      d.libDir('foo'),
+      d.dir("bin")
+    ]).create();
 
     // Create a broken "packages" symlink in "bin".
     scheduleSymlink("nonexistent", path.join(appPath, "bin", "packages"));
@@ -50,14 +50,14 @@
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(appPath, [
-      dir("bin", [
-        dir("packages", [
-          dir("myapp", [
-            file('foo.dart', 'main() => "foo";')
+    d.dir(appPath, [
+      d.dir("bin", [
+        d.dir("packages", [
+          d.dir("myapp", [
+            d.file('foo.dart', 'main() => "foo";')
           ])
         ])
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/check_out_and_update_test.dart b/utils/tests/pub/install/git/check_out_and_update_test.dart
index 22fed50..14e65c7 100644
--- a/utils/tests/pub/install/git/check_out_and_update_test.dart
+++ b/utils/tests/pub/install/git/check_out_and_update_test.dart
@@ -6,61 +6,58 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('checks out and updates a package from Git', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(cachePath, [
-      dir('git', [
-        dir('cache', [gitPackageRepoCacheDir('foo')]),
-        gitPackageRevisionCacheDir('foo')
+    d.dir(cachePath, [
+      d.dir('git', [
+        d.dir('cache', [d.gitPackageRepoCacheDir('foo')]),
+        d.gitPackageRevisionCacheDir('foo')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    // TODO(nweiz): remove this once we support pub update
-    dir(packagesPath).scheduleDelete();
-    file('$appPath/pubspec.lock', '').scheduleDelete();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 2'),
+      d.libPubspec('foo', '1.0.0')
+    ]).commit();
 
-    git('foo.git', [
-      libDir('foo', 'foo 2'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCommit();
-
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    schedulePub(args: ['update'],
+        output: new RegExp(r"Dependencies updated!$"));
 
     // When we download a new version of the git package, we should re-use the
     // git/cache directory but create a new git/ directory.
-    dir(cachePath, [
-      dir('git', [
-        dir('cache', [gitPackageRepoCacheDir('foo')]),
-        gitPackageRevisionCacheDir('foo'),
-        gitPackageRevisionCacheDir('foo', 2)
+    d.dir(cachePath, [
+      d.dir('git', [
+        d.dir('cache', [d.gitPackageRepoCacheDir('foo')]),
+        d.gitPackageRevisionCacheDir('foo'),
+        d.gitPackageRevisionCacheDir('foo', 2)
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 2";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 2";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/check_out_branch_test.dart b/utils/tests/pub/install/git/check_out_branch_test.dart
index 42e65bd..8375fb2 100644
--- a/utils/tests/pub/install/git/check_out_branch_test.dart
+++ b/utils/tests/pub/install/git/check_out_branch_test.dart
@@ -6,33 +6,34 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('checks out a package at a specific branch from Git', () {
     ensureGit();
 
-    var repo = git('foo.git', [
-      libDir('foo', 'foo 1'),
-      libPubspec('foo', '1.0.0')
+    var repo = d.git('foo.git', [
+      d.libDir('foo', 'foo 1'),
+      d.libPubspec('foo', '1.0.0')
     ]);
-    repo.scheduleCreate();
-    repo.scheduleGit(["branch", "old"]);
+    repo.create();
+    repo.runGit(["branch", "old"]);
 
-    git('foo.git', [
-      libDir('foo', 'foo 2'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCommit();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 2'),
+      d.libPubspec('foo', '1.0.0')
+    ]).commit();
 
-    appDir([{"git": {"url": "../foo.git", "ref": "old"}}]).scheduleCreate();
+    d.appDir([{"git": {"url": "../foo.git", "ref": "old"}}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 1";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 1";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/check_out_revision_test.dart b/utils/tests/pub/install/git/check_out_revision_test.dart
index 3f11693..e9fec81 100644
--- a/utils/tests/pub/install/git/check_out_revision_test.dart
+++ b/utils/tests/pub/install/git/check_out_revision_test.dart
@@ -6,33 +6,34 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('checks out a package at a specific revision from Git', () {
     ensureGit();
 
-    var repo = git('foo.git', [
-      libDir('foo', 'foo 1'),
-      libPubspec('foo', '1.0.0')
+    var repo = d.git('foo.git', [
+      d.libDir('foo', 'foo 1'),
+      d.libPubspec('foo', '1.0.0')
     ]);
-    repo.scheduleCreate();
+    repo.create();
     var commit = repo.revParse('HEAD');
 
-    git('foo.git', [
-      libDir('foo', 'foo 2'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCommit();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 2'),
+      d.libPubspec('foo', '1.0.0')
+    ]).commit();
 
-    appDir([{"git": {"url": "../foo.git", "ref": commit}}]).scheduleCreate();
+    d.appDir([{"git": {"url": "../foo.git", "ref": commit}}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 1";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 1";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/check_out_test.dart b/utils/tests/pub/install/git/check_out_test.dart
index f91fd1f..dcd530b 100644
--- a/utils/tests/pub/install/git/check_out_test.dart
+++ b/utils/tests/pub/install/git/check_out_test.dart
@@ -6,33 +6,34 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('checks out a package from Git', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(cachePath, [
-      dir('git', [
-        dir('cache', [gitPackageRepoCacheDir('foo')]),
-        gitPackageRevisionCacheDir('foo')
+    d.dir(cachePath, [
+      d.dir('git', [
+        d.dir('cache', [d.gitPackageRepoCacheDir('foo')]),
+        d.gitPackageRevisionCacheDir('foo')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/check_out_transitive_test.dart b/utils/tests/pub/install/git/check_out_transitive_test.dart
index c0e7b8d..6031447 100644
--- a/utils/tests/pub/install/git/check_out_transitive_test.dart
+++ b/utils/tests/pub/install/git/check_out_transitive_test.dart
@@ -6,45 +6,46 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('checks out packages transitively from Git', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0', deps: [{"git": "../bar.git"}])
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0', deps: [{"git": "../bar.git"}])
+    ]).create();
 
-    git('bar.git', [
-      libDir('bar'),
-      libPubspec('bar', '1.0.0')
-    ]).scheduleCreate();
+    d.git('bar.git', [
+      d.libDir('bar'),
+      d.libPubspec('bar', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp("Dependencies installed!\$"));
 
-    dir(cachePath, [
-      dir('git', [
-        dir('cache', [
-          gitPackageRepoCacheDir('foo'),
-          gitPackageRepoCacheDir('bar')
+    d.dir(cachePath, [
+      d.dir('git', [
+        d.dir('cache', [
+          d.gitPackageRepoCacheDir('foo'),
+          d.gitPackageRepoCacheDir('bar')
         ]),
-        gitPackageRevisionCacheDir('foo'),
-        gitPackageRevisionCacheDir('bar')
+        d.gitPackageRevisionCacheDir('foo'),
+        d.gitPackageRevisionCacheDir('bar')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ]),
-      dir('bar', [
-        file('bar.dart', 'main() => "bar";')
+      d.dir('bar', [
+        d.file('bar.dart', 'main() => "bar";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/check_out_twice_test.dart b/utils/tests/pub/install/git/check_out_twice_test.dart
index 8195a25..8ddd2ac 100644
--- a/utils/tests/pub/install/git/check_out_twice_test.dart
+++ b/utils/tests/pub/install/git/check_out_twice_test.dart
@@ -6,41 +6,39 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('checks out a package from Git twice', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(cachePath, [
-      dir('git', [
-        dir('cache', [gitPackageRepoCacheDir('foo')]),
-        gitPackageRevisionCacheDir('foo')
+    d.dir(cachePath, [
+      d.dir('git', [
+        d.dir('cache', [d.gitPackageRepoCacheDir('foo')]),
+        d.gitPackageRevisionCacheDir('foo')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
-
-    // TODO(nweiz): remove this once we support pub update
-    dir(packagesPath).scheduleDelete();
+    ]).validate();
 
     // Verify that nothing breaks if we install a Git revision that's already
     // in the cache.
-    schedulePub(args: ['install'],
-        output: new RegExp(r"Dependencies installed!$"));
+    schedulePub(args: ['update'],
+        output: new RegExp(r"Dependencies updated!$"));
   });
 }
diff --git a/utils/tests/pub/install/git/check_out_with_trailing_slash_test.dart b/utils/tests/pub/install/git/check_out_with_trailing_slash_test.dart
index eee21d4..64c4534 100644
--- a/utils/tests/pub/install/git/check_out_with_trailing_slash_test.dart
+++ b/utils/tests/pub/install/git/check_out_with_trailing_slash_test.dart
@@ -6,7 +6,9 @@
 
 import 'dart:io';
 
-import '../../../../../pkg/unittest/lib/unittest.dart';
+import '../../../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -14,28 +16,28 @@
     integration('checks out a package from Git with a trailing slash', () {
       ensureGit();
 
-      git('foo.git', [
-        libDir('foo'),
-        libPubspec('foo', '1.0.0')
-      ]).scheduleCreate();
+      d.git('foo.git', [
+        d.libDir('foo'),
+        d.libPubspec('foo', '1.0.0')
+      ]).create();
 
-      appDir([{"git": "../foo.git/"}]).scheduleCreate();
+      d.appDir([{"git": "../foo.git/"}]).create();
 
       schedulePub(args: ['install'],
           output: new RegExp(r"Dependencies installed!$"));
 
-      dir(cachePath, [
-        dir('git', [
-          dir('cache', [gitPackageRepoCacheDir('foo')]),
-          gitPackageRevisionCacheDir('foo')
+      d.dir(cachePath, [
+        d.dir('git', [
+          d.dir('cache', [d.gitPackageRepoCacheDir('foo')]),
+          d.gitPackageRevisionCacheDir('foo')
         ])
-      ]).scheduleValidate();
+      ]).validate();
 
-      dir(packagesPath, [
-        dir('foo', [
-          file('foo.dart', 'main() => "foo";')
+      d.dir(packagesPath, [
+        d.dir('foo', [
+          d.file('foo.dart', 'main() => "foo";')
         ])
-      ]).scheduleValidate();
+      ]).validate();
     });
   });
 }
diff --git a/utils/tests/pub/install/git/dependency_name_match_pubspec_test.dart b/utils/tests/pub/install/git/dependency_name_match_pubspec_test.dart
index d54881f..cd12ff2 100644
--- a/utils/tests/pub/install/git/dependency_name_match_pubspec_test.dart
+++ b/utils/tests/pub/install/git/dependency_name_match_pubspec_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -13,19 +14,19 @@
       'name', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "weirdname": {"git": "../foo.git"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     // TODO(nweiz): clean up this RegExp when either issue 4706 or 4707 is
     // fixed.
diff --git a/utils/tests/pub/install/git/different_repo_name_test.dart b/utils/tests/pub/install/git/different_repo_name_test.dart
index 8f5657c..3c30faf 100644
--- a/utils/tests/pub/install/git/different_repo_name_test.dart
+++ b/utils/tests/pub/install/git/different_repo_name_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -13,27 +14,27 @@
       'pubspec', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('weirdname'),
-      libPubspec('weirdname', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('weirdname'),
+      d.libPubspec('weirdname', '1.0.0')
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "weirdname": {"git": "../foo.git"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('weirdname', [
-        file('weirdname.dart', 'main() => "weirdname";')
+    d.dir(packagesPath, [
+      d.dir('weirdname', [
+        d.file('weirdname.dart', 'main() => "weirdname";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/lock_version_test.dart b/utils/tests/pub/install/git/lock_version_test.dart
index 793294c..7c3824b 100644
--- a/utils/tests/pub/install/git/lock_version_test.dart
+++ b/utils/tests/pub/install/git/lock_version_test.dart
@@ -6,45 +6,50 @@
 
 import 'dart:io';
 
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+import '../../../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
+import '../../../../pub/io.dart';
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('keeps a Git package locked to the version in the lockfile', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     // This install should lock the foo.git dependency to the current revision.
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
     // Delete the packages path to simulate a new checkout of the application.
-    dir(packagesPath).scheduleDelete();
+    schedule(() => deleteDir(path.join(sandboxDir, packagesPath)));
 
-    git('foo.git', [
-      libDir('foo', 'foo 2'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCommit();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 2'),
+      d.libPubspec('foo', '1.0.0')
+    ]).commit();
 
     // This install shouldn't update the foo.git dependency due to the lockfile.
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/require_pubspec_name_test.dart b/utils/tests/pub/install/git/require_pubspec_name_test.dart
index 68cc91ea..1713e04 100644
--- a/utils/tests/pub/install/git/require_pubspec_name_test.dart
+++ b/utils/tests/pub/install/git/require_pubspec_name_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -13,12 +14,12 @@
       'field', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      pubspec({})
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.pubspec({})
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     // TODO(nweiz): clean up this RegExp when either issue 4706 or 4707 is
     // fixed.
diff --git a/utils/tests/pub/install/git/require_pubspec_test.dart b/utils/tests/pub/install/git/require_pubspec_test.dart
index ffc0b60..084bbe0 100644
--- a/utils/tests/pub/install/git/require_pubspec_test.dart
+++ b/utils/tests/pub/install/git/require_pubspec_test.dart
@@ -6,17 +6,18 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('requires the dependency to have a pubspec', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     // TODO(nweiz): clean up this RegExp when either issue 4706 or 4707 is
     // fixed.
diff --git a/utils/tests/pub/install/git/stay_locked_if_compatible_test.dart b/utils/tests/pub/install/git/stay_locked_if_compatible_test.dart
index 67bef62..0f57785 100644
--- a/utils/tests/pub/install/git/stay_locked_if_compatible_test.dart
+++ b/utils/tests/pub/install/git/stay_locked_if_compatible_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -13,36 +14,36 @@
       "constraint", () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo', 'foo 1.0.0'),
-      libPubspec("foo", "1.0.0")
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 1.0.0'),
+      d.libPubspec("foo", "1.0.0")
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 1.0.0";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 1.0.0";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    git('foo.git', [
-      libDir('foo', 'foo 1.0.1'),
-      libPubspec("foo", "1.0.1")
-    ]).scheduleCommit();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 1.0.1'),
+      d.libPubspec("foo", "1.0.1")
+    ]).commit();
 
-    appDir([{"git": "../foo.git", "version": ">=1.0.0"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git", "version": ">=1.0.0"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 1.0.0";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 1.0.0";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/git/unlock_if_incompatible_test.dart b/utils/tests/pub/install/git/unlock_if_incompatible_test.dart
index 47aa138..64d4406 100644
--- a/utils/tests/pub/install/git/unlock_if_incompatible_test.dart
+++ b/utils/tests/pub/install/git/unlock_if_incompatible_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -13,36 +14,36 @@
       'constraint', () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '0.5.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '0.5.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    git('foo.git', [
-      libDir('foo', 'foo 1.0.0'),
-      libPubspec("foo", "1.0.0")
-    ]).scheduleCommit();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 1.0.0'),
+      d.libPubspec("foo", "1.0.0")
+    ]).commit();
 
-    appDir([{"git": "../foo.git", "version": ">=1.0.0"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git", "version": ">=1.0.0"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 1.0.0";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 1.0.0";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/do_not_update_on_removed_constraints_test.dart b/utils/tests/pub/install/hosted/do_not_update_on_removed_constraints_test.dart
index 9bd2348..ba49e66 100644
--- a/utils/tests/pub/install/hosted/do_not_update_on_removed_constraints_test.dart
+++ b/utils/tests/pub/install/hosted/do_not_update_on_removed_constraints_test.dart
@@ -6,38 +6,39 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("doesn't update dependencies whose constraints have been "
       "removed", () {
     servePackages([
-      package("foo", "1.0.0", [dependency("shared-dep")]),
-      package("bar", "1.0.0", [dependency("shared-dep", "<2.0.0")]),
-      package("shared-dep", "1.0.0"),
-      package("shared-dep", "2.0.0")
+      packageMap("foo", "1.0.0", [dependencyMap("shared-dep")]),
+      packageMap("bar", "1.0.0", [dependencyMap("shared-dep", "<2.0.0")]),
+      packageMap("shared-dep", "1.0.0"),
+      packageMap("shared-dep", "2.0.0")
     ]);
 
-    appDir([dependency("foo"), dependency("bar")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0",
       "shared-dep": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": null,
       "shared-dep": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/fail_gracefully_on_missing_package_test.dart b/utils/tests/pub/install/hosted/fail_gracefully_on_missing_package_test.dart
index ed0ca96..e0b4615 100644
--- a/utils/tests/pub/install/hosted/fail_gracefully_on_missing_package_test.dart
+++ b/utils/tests/pub/install/hosted/fail_gracefully_on_missing_package_test.dart
@@ -6,13 +6,14 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('fails gracefully if the package does not exist', () {
     servePackages([]);
 
-    appDir([dependency("foo", "1.2.3")]).scheduleCreate();
+    d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
     schedulePub(args: ['install'],
         error: new RegExp('Could not find package "foo" at '
diff --git a/utils/tests/pub/install/hosted/fail_gracefully_on_url_resolve_test.dart b/utils/tests/pub/install/hosted/fail_gracefully_on_url_resolve_test.dart
index 6a40f08..6c7acde 100644
--- a/utils/tests/pub/install/hosted/fail_gracefully_on_url_resolve_test.dart
+++ b/utils/tests/pub/install/hosted/fail_gracefully_on_url_resolve_test.dart
@@ -6,12 +6,13 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('fails gracefully if the url does not resolve', () {
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {
@@ -22,7 +23,7 @@
           }
          }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ['install'],
         error: new RegExp('Could not resolve URL "http://pub.invalid".'),
diff --git a/utils/tests/pub/install/hosted/install_test.dart b/utils/tests/pub/install/hosted/install_test.dart
index 5bc120c..5db5553 100644
--- a/utils/tests/pub/install/hosted/install_test.dart
+++ b/utils/tests/pub/install/hosted/install_test.dart
@@ -6,26 +6,27 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   initConfig();
   integration('installs a package from a pub server', () {
-    servePackages([package("foo", "1.2.3")]);
+    servePackages([packageMap("foo", "1.2.3")]);
 
-    appDir([dependency("foo", "1.2.3")]).scheduleCreate();
+    d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp("Dependencies installed!\$"));
 
-    cacheDir({"foo": "1.2.3"}).scheduleValidate();
-    packagesDir({"foo": "1.2.3"}).scheduleValidate();
+    d.cacheDir({"foo": "1.2.3"}).validate();
+    d.packagesDir({"foo": "1.2.3"}).validate();
   });
 
   integration('URL encodes the package name', () {
     servePackages([]);
 
-    appDir([dependency("bad name!", "1.2.3")]).scheduleCreate();
+    d.appDir([dependencyMap("bad name!", "1.2.3")]).create();
 
     schedulePub(args: ['install'],
         error: new RegExp('Could not find package "bad name!" at '
diff --git a/utils/tests/pub/install/hosted/install_transitive_test.dart b/utils/tests/pub/install/hosted/install_transitive_test.dart
index b111d79..23e4bd6 100644
--- a/utils/tests/pub/install/hosted/install_transitive_test.dart
+++ b/utils/tests/pub/install/hosted/install_transitive_test.dart
@@ -6,23 +6,24 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('installs packages transitively from a pub server', () {
     servePackages([
-      package("foo", "1.2.3", [dependency("bar", "2.0.4")]),
-      package("bar", "2.0.3"),
-      package("bar", "2.0.4"),
-      package("bar", "2.0.5")
+      packageMap("foo", "1.2.3", [dependencyMap("bar", "2.0.4")]),
+      packageMap("bar", "2.0.3"),
+      packageMap("bar", "2.0.4"),
+      packageMap("bar", "2.0.5")
     ]);
 
-    appDir([dependency("foo", "1.2.3")]).scheduleCreate();
+    d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp("Dependencies installed!\$"));
 
-    cacheDir({"foo": "1.2.3", "bar": "2.0.4"}).scheduleValidate();
-    packagesDir({"foo": "1.2.3", "bar": "2.0.4"}).scheduleValidate();
+    d.cacheDir({"foo": "1.2.3", "bar": "2.0.4"}).validate();
+    d.packagesDir({"foo": "1.2.3", "bar": "2.0.4"}).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/remove_removed_dependency_test.dart b/utils/tests/pub/install/hosted/remove_removed_dependency_test.dart
index 01d95b7..d009ac3 100644
--- a/utils/tests/pub/install/hosted/remove_removed_dependency_test.dart
+++ b/utils/tests/pub/install/hosted/remove_removed_dependency_test.dart
@@ -6,33 +6,34 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("removes a dependency that's been removed from the pubspec", () {
     servePackages([
-      package("foo", "1.0.0"),
-      package("bar", "1.0.0")
+      packageMap("foo", "1.0.0"),
+      packageMap("bar", "1.0.0")
     ]);
 
-    appDir([dependency("foo"), dependency("bar")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": null
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/remove_removed_transitive_dependency_test.dart b/utils/tests/pub/install/hosted/remove_removed_transitive_dependency_test.dart
index 959d51a..6120c33 100644
--- a/utils/tests/pub/install/hosted/remove_removed_transitive_dependency_test.dart
+++ b/utils/tests/pub/install/hosted/remove_removed_transitive_dependency_test.dart
@@ -6,43 +6,44 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("removes a transitive dependency that's no longer depended"
       " on", () {
     servePackages([
-      package("foo", "1.0.0", [dependency("shared-dep")]),
-      package("bar", "1.0.0", [
-        dependency("shared-dep"),
-        dependency("bar-dep")
+      packageMap("foo", "1.0.0", [dependencyMap("shared-dep")]),
+      packageMap("bar", "1.0.0", [
+        dependencyMap("shared-dep"),
+        dependencyMap("bar-dep")
       ]),
-      package("shared-dep", "1.0.0"),
-      package("bar-dep", "1.0.0")
+      packageMap("shared-dep", "1.0.0"),
+      packageMap("bar-dep", "1.0.0")
     ]);
 
-    appDir([dependency("foo"), dependency("bar")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0",
       "shared-dep": "1.0.0",
       "bar-dep": "1.0.0",
-    }).scheduleValidate();
+    }).validate();
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": null,
       "shared-dep": "1.0.0",
       "bar-dep": null,
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/repair_cache_test.dart b/utils/tests/pub/install/hosted/repair_cache_test.dart
index 1636c0f..5af5ab6 100644
--- a/utils/tests/pub/install/hosted/repair_cache_test.dart
+++ b/utils/tests/pub/install/hosted/repair_cache_test.dart
@@ -7,58 +7,57 @@
 import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/io.dart';
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   initConfig();
   integration('re-installs a package if it has an empty "lib" directory', () {
-
-    servePackages([package("foo", "1.2.3")]);
+    servePackages([packageMap("foo", "1.2.3")]);
 
     // Set up a cache with a broken foo package.
-    dir(cachePath, [
-      dir('hosted', [
-        async(port.then((p) => dir('localhost%58$p', [
-          dir("foo-1.2.3", [
-            libPubspec("foo", "1.2.3"),
+    d.dir(cachePath, [
+      d.dir('hosted', [
+        d.async(port.then((p) => d.dir('localhost%58$p', [
+          d.dir("foo-1.2.3", [
+            d.libPubspec("foo", "1.2.3"),
             // Note: empty "lib" directory.
-            dir("lib", [])
+            d.dir("lib", [])
           ])
         ])))
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    appDir([dependency("foo", "1.2.3")]).scheduleCreate();
+    d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp("Dependencies installed!\$"));
 
-    cacheDir({"foo": "1.2.3"}).scheduleValidate();
-    packagesDir({"foo": "1.2.3"}).scheduleValidate();
+    d.cacheDir({"foo": "1.2.3"}).validate();
+    d.packagesDir({"foo": "1.2.3"}).validate();
   });
 
   integration('re-installs a package if it has no pubspec', () {
-
-    servePackages([package("foo", "1.2.3")]);
+    servePackages([packageMap("foo", "1.2.3")]);
 
     // Set up a cache with a broken foo package.
-    dir(cachePath, [
-      dir('hosted', [
-        async(port.then((p) => dir('localhost%58$p', [
-          dir("foo-1.2.3", [
-            libDir("foo")
+    d.dir(cachePath, [
+      d.dir('hosted', [
+        d.async(port.then((p) => d.dir('localhost%58$p', [
+          d.dir("foo-1.2.3", [
+            d.libDir("foo")
             // Note: no pubspec.
           ])
         ])))
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    appDir([dependency("foo", "1.2.3")]).scheduleCreate();
+    d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp("Dependencies installed!\$"));
 
-    cacheDir({"foo": "1.2.3"}).scheduleValidate();
-    packagesDir({"foo": "1.2.3"}).scheduleValidate();
+    d.cacheDir({"foo": "1.2.3"}).validate();
+    d.packagesDir({"foo": "1.2.3"}).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/resolve_constraints_test.dart b/utils/tests/pub/install/hosted/resolve_constraints_test.dart
index fa95d32..2b6f2b0 100644
--- a/utils/tests/pub/install/hosted/resolve_constraints_test.dart
+++ b/utils/tests/pub/install/hosted/resolve_constraints_test.dart
@@ -6,33 +6,34 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('resolves version constraints from a pub server', () {
     servePackages([
-      package("foo", "1.2.3", [dependency("baz", ">=2.0.0")]),
-      package("bar", "2.3.4", [dependency("baz", "<3.0.0")]),
-      package("baz", "2.0.3"),
-      package("baz", "2.0.4"),
-      package("baz", "3.0.1")
+      packageMap("foo", "1.2.3", [dependencyMap("baz", ">=2.0.0")]),
+      packageMap("bar", "2.3.4", [dependencyMap("baz", "<3.0.0")]),
+      packageMap("baz", "2.0.3"),
+      packageMap("baz", "2.0.4"),
+      packageMap("baz", "3.0.1")
     ]);
 
-    appDir([dependency("foo"), dependency("bar")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp("Dependencies installed!\$"));
 
-    cacheDir({
+    d.cacheDir({
       "foo": "1.2.3",
       "bar": "2.3.4",
       "baz": "2.0.4"
-    }).scheduleValidate();
+    }).validate();
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.2.3",
       "bar": "2.3.4",
       "baz": "2.0.4"
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/stay_locked_if_compatible_test.dart b/utils/tests/pub/install/hosted/stay_locked_if_compatible_test.dart
index e6ccc35..7681164 100644
--- a/utils/tests/pub/install/hosted/stay_locked_if_compatible_test.dart
+++ b/utils/tests/pub/install/hosted/stay_locked_if_compatible_test.dart
@@ -6,27 +6,28 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("doesn't update a locked pub server package with a new "
       "compatible constraint", () {
-    servePackages([package("foo", "1.0.0")]);
+    servePackages([packageMap("foo", "1.0.0")]);
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({"foo": "1.0.0"}).scheduleValidate();
+    d.packagesDir({"foo": "1.0.0"}).validate();
 
-    servePackages([package("foo", "1.0.1")]);
+    servePackages([packageMap("foo", "1.0.1")]);
 
-    appDir([dependency("foo", ">=1.0.0")]).scheduleCreate();
+    d.appDir([dependencyMap("foo", ">=1.0.0")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({"foo": "1.0.0"}).scheduleValidate();
+    d.packagesDir({"foo": "1.0.0"}).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/stay_locked_if_new_is_satisfied_test.dart b/utils/tests/pub/install/hosted/stay_locked_if_new_is_satisfied_test.dart
index 782a52a..81bf855 100644
--- a/utils/tests/pub/install/hosted/stay_locked_if_new_is_satisfied_test.dart
+++ b/utils/tests/pub/install/hosted/stay_locked_if_new_is_satisfied_test.dart
@@ -6,45 +6,46 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("doesn't unlock dependencies if a new dependency is already "
       "satisfied", () {
     servePackages([
-      package("foo", "1.0.0", [dependency("bar", "<2.0.0")]),
-      package("bar", "1.0.0", [dependency("baz", "<2.0.0")]),
-      package("baz", "1.0.0")
+      packageMap("foo", "1.0.0", [dependencyMap("bar", "<2.0.0")]),
+      packageMap("bar", "1.0.0", [dependencyMap("baz", "<2.0.0")]),
+      packageMap("baz", "1.0.0")
     ]);
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0",
       "baz": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
 
     servePackages([
-      package("foo", "2.0.0", [dependency("bar", "<3.0.0")]),
-      package("bar", "2.0.0", [dependency("baz", "<3.0.0")]),
-      package("baz", "2.0.0"),
-      package("newdep", "2.0.0", [dependency("baz", ">=1.0.0")])
+      packageMap("foo", "2.0.0", [dependencyMap("bar", "<3.0.0")]),
+      packageMap("bar", "2.0.0", [dependencyMap("baz", "<3.0.0")]),
+      packageMap("baz", "2.0.0"),
+      packageMap("newdep", "2.0.0", [dependencyMap("baz", ">=1.0.0")])
     ]);
 
-    appDir([dependency("foo"), dependency("newdep")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("newdep")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0",
       "baz": "1.0.0",
       "newdep": "2.0.0"
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/stay_locked_test.dart b/utils/tests/pub/install/hosted/stay_locked_test.dart
index 5bd5ec2..dc8f72a 100644
--- a/utils/tests/pub/install/hosted/stay_locked_test.dart
+++ b/utils/tests/pub/install/hosted/stay_locked_test.dart
@@ -6,31 +6,36 @@
 
 import 'dart:io';
 
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+import '../../../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
+import '../../../../pub/io.dart';
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('keeps a pub server package locked to the version in the '
       'lockfile', () {
-    servePackages([package("foo", "1.0.0")]);
+    servePackages([packageMap("foo", "1.0.0")]);
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     // This install should lock the foo dependency to version 1.0.0.
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({"foo": "1.0.0"}).scheduleValidate();
+    d.packagesDir({"foo": "1.0.0"}).validate();
 
     // Delete the packages path to simulate a new checkout of the application.
-    dir(packagesPath).scheduleDelete();
+    schedule(() => deleteDir(path.join(sandboxDir, packagesPath)));
 
     // Start serving a newer package as well.
-    servePackages([package("foo", "1.0.1")]);
+    servePackages([packageMap("foo", "1.0.1")]);
 
     // This install shouldn't update the foo dependency due to the lockfile.
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({"foo": "1.0.0"}).scheduleValidate();
+    d.packagesDir({"foo": "1.0.0"}).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/unlock_if_incompatible_test.dart b/utils/tests/pub/install/hosted/unlock_if_incompatible_test.dart
index 13a6920..f1dd592 100644
--- a/utils/tests/pub/install/hosted/unlock_if_incompatible_test.dart
+++ b/utils/tests/pub/install/hosted/unlock_if_incompatible_test.dart
@@ -6,27 +6,28 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('updates a locked pub server package with a new incompatible '
       'constraint', () {
-    servePackages([package("foo", "1.0.0")]);
+    servePackages([packageMap("foo", "1.0.0")]);
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({"foo": "1.0.0"}).scheduleValidate();
+    d.packagesDir({"foo": "1.0.0"}).validate();
 
-    servePackages([package("foo", "1.0.1")]);
+    servePackages([packageMap("foo", "1.0.1")]);
 
-    appDir([dependency("foo", ">1.0.0")]).scheduleCreate();
+    d.appDir([dependencyMap("foo", ">1.0.0")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({"foo": "1.0.1"}).scheduleValidate();
+    d.packagesDir({"foo": "1.0.1"}).validate();
   });
 }
diff --git a/utils/tests/pub/install/hosted/unlock_if_new_is_unsatisfied_test.dart b/utils/tests/pub/install/hosted/unlock_if_new_is_unsatisfied_test.dart
index 91edd34..8da00dd 100644
--- a/utils/tests/pub/install/hosted/unlock_if_new_is_unsatisfied_test.dart
+++ b/utils/tests/pub/install/hosted/unlock_if_new_is_unsatisfied_test.dart
@@ -6,49 +6,50 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("unlocks dependencies if necessary to ensure that a new "
       "dependency is satisfied", () {
     servePackages([
-      package("foo", "1.0.0", [dependency("bar", "<2.0.0")]),
-      package("bar", "1.0.0", [dependency("baz", "<2.0.0")]),
-      package("baz", "1.0.0", [dependency("qux", "<2.0.0")]),
-      package("qux", "1.0.0")
+      packageMap("foo", "1.0.0", [dependencyMap("bar", "<2.0.0")]),
+      packageMap("bar", "1.0.0", [dependencyMap("baz", "<2.0.0")]),
+      packageMap("baz", "1.0.0", [dependencyMap("qux", "<2.0.0")]),
+      packageMap("qux", "1.0.0")
     ]);
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0",
       "baz": "1.0.0",
       "qux": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
 
     servePackages([
-      package("foo", "2.0.0", [dependency("bar", "<3.0.0")]),
-      package("bar", "2.0.0", [dependency("baz", "<3.0.0")]),
-      package("baz", "2.0.0", [dependency("qux", "<3.0.0")]),
-      package("qux", "2.0.0"),
-      package("newdep", "2.0.0", [dependency("baz", ">=1.5.0")])
+      packageMap("foo", "2.0.0", [dependencyMap("bar", "<3.0.0")]),
+      packageMap("bar", "2.0.0", [dependencyMap("baz", "<3.0.0")]),
+      packageMap("baz", "2.0.0", [dependencyMap("qux", "<3.0.0")]),
+      packageMap("qux", "2.0.0"),
+      packageMap("newdep", "2.0.0", [dependencyMap("baz", ">=1.5.0")])
     ]);
 
-    appDir([dependency("foo"), dependency("newdep")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("newdep")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "2.0.0",
       "bar": "2.0.0",
       "baz": "2.0.0",
       "qux": "1.0.0",
       "newdep": "2.0.0"
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/install/path/absolute_path_test.dart b/utils/tests/pub/install/path/absolute_path_test.dart
index 2445b26..9e991c4 100644
--- a/utils/tests/pub/install/path/absolute_path_test.dart
+++ b/utils/tests/pub/install/path/absolute_path_test.dart
@@ -1,46 +1,49 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
+import '../../../../../pkg/scheduled_test/lib/scheduled_test.dart';
 
+import '../../../../pub/io.dart';
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   initConfig();
   integration('path dependency with absolute path', () {
-    dir('foo', [
-      libDir('foo'),
-      libPubspec('foo', '0.0.1')
-    ]).scheduleCreate();
+    d.dir('foo', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '0.0.1')
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": path.join(sandboxDir, "foo")}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [
-        file("foo.dart", 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
     // Move the packages directory and ensure the symlink still works. That
     // will validate that we actually created an absolute symlink.
-    dir("moved").scheduleCreate();
+    d.dir("moved").create();
     scheduleRename(packagesPath, "moved/packages");
 
-    dir("moved/packages", [
-      dir("foo", [
-        file("foo.dart", 'main() => "foo";')
+    d.dir("moved/packages", [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
\ No newline at end of file
diff --git a/utils/tests/pub/install/path/absolute_symlink_test.dart b/utils/tests/pub/install/path/absolute_symlink_test.dart
index 3e65f19..7ecb0e5 100644
--- a/utils/tests/pub/install/path/absolute_symlink_test.dart
+++ b/utils/tests/pub/install/path/absolute_symlink_test.dart
@@ -1,45 +1,46 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   initConfig();
   integration("generates a symlink with an absolute path if the dependency "
               "path was absolute", () {
-    dir("foo", [
-      libDir("foo"),
-      libPubspec("foo", "0.0.1")
-    ]).scheduleCreate();
+    d.dir("foo", [
+      d.libDir("foo"),
+      d.libPubspec("foo", "0.0.1")
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": path.join(sandboxDir, "foo")}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir("moved").scheduleCreate();
+    d.dir("moved").create();
 
     // Move the app but not the package. Since the symlink is absolute, it
     // should still be able to find it.
     scheduleRename(appPath, path.join("moved", appPath));
 
-    dir("moved", [
-      dir(packagesPath, [
-        dir("foo", [
-          file("foo.dart", 'main() => "foo";')
+    d.dir("moved", [
+      d.dir(packagesPath, [
+        d.dir("foo", [
+          d.file("foo.dart", 'main() => "foo";')
         ])
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
\ No newline at end of file
diff --git a/utils/tests/pub/install/path/no_pubspec_test.dart b/utils/tests/pub/install/path/no_pubspec_test.dart
index 8481617..37620fa 100644
--- a/utils/tests/pub/install/path/no_pubspec_test.dart
+++ b/utils/tests/pub/install/path/no_pubspec_test.dart
@@ -1,28 +1,30 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import 'dart:io';
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
+import '../../../../../pkg/scheduled_test/lib/scheduled_test.dart';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   initConfig();
   integration('path dependency to non-package directory', () {
     // Make an empty directory.
-    dir('foo').scheduleCreate();
+    d.dir('foo').create();
     var fooPath = path.join(sandboxDir, "foo");
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": fooPath}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ['install'],
         error: new RegExp('Package "foo" doesn\'t have a pubspec.yaml file.'),
diff --git a/utils/tests/pub/install/path/nonexistent_dir_test.dart b/utils/tests/pub/install/path/nonexistent_dir_test.dart
index 915a683..53009cf 100644
--- a/utils/tests/pub/install/path/nonexistent_dir_test.dart
+++ b/utils/tests/pub/install/path/nonexistent_dir_test.dart
@@ -1,12 +1,14 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import 'dart:io';
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
+import '../../../../../pkg/scheduled_test/lib/scheduled_test.dart';
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -14,14 +16,14 @@
   integration('path dependency to non-existent directory', () {
     var badPath = path.join(sandboxDir, "bad_path");
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": badPath}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     // TODO(rnystrom): The "\" in a Windows path gets treated like a regex
     // character, so hack escape. A better fix is to use a literal string
diff --git a/utils/tests/pub/install/path/path_is_file_test.dart b/utils/tests/pub/install/path/path_is_file_test.dart
index 093e9f5..75fc8ba 100644
--- a/utils/tests/pub/install/path/path_is_file_test.dart
+++ b/utils/tests/pub/install/path/path_is_file_test.dart
@@ -1,31 +1,33 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
+import '../../../../../pkg/scheduled_test/lib/scheduled_test.dart';
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   initConfig();
-  integration('path dependency when path is a file', () {
-    dir('foo', [
-      libDir('foo'),
-      libPubspec('foo', '0.0.1')
-    ]).scheduleCreate();
+  integration('path dependency when path is a d.file', () {
+    d.dir('foo', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '0.0.1')
+    ]).create();
 
-    file('dummy.txt', '').scheduleCreate();
+    d.file('dummy.txt', '').create();
     var dummyPath = path.join(sandboxDir, 'dummy.txt');
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": dummyPath}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     // TODO(rnystrom): The "\" in a Windows path gets treated like a regex
     // character, so hack escape. A better fix is to use a literal string
diff --git a/utils/tests/pub/install/path/relative_path_test.dart b/utils/tests/pub/install/path/relative_path_test.dart
index 691beed..4474562 100644
--- a/utils/tests/pub/install/path/relative_path_test.dart
+++ b/utils/tests/pub/install/path/relative_path_test.dart
@@ -1,72 +1,73 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   initConfig();
   integration("can use relative path", () {
-    dir("foo", [
-      libDir("foo"),
-      libPubspec("foo", "0.0.1")
-    ]).scheduleCreate();
+    d.dir("foo", [
+      d.libDir("foo"),
+      d.libPubspec("foo", "0.0.1")
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": "../foo"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [
-        file("foo.dart", 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 
-  integration("path is relative to containing pubspec", () {
-    dir("relative", [
-      dir("foo", [
-        libDir("foo"),
-        libPubspec("foo", "0.0.1", deps: [
+  integration("path is relative to containing d.pubspec", () {
+    d.dir("relative", [
+      d.dir("foo", [
+        d.libDir("foo"),
+        d.libPubspec("foo", "0.0.1", deps: [
           {"path": "../bar"}
         ])
       ]),
-      dir("bar", [
-        libDir("bar"),
-        libPubspec("bar", "0.0.1")
+      d.dir("bar", [
+        d.libDir("bar"),
+        d.libPubspec("bar", "0.0.1")
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": "../relative/foo"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [
-        file("foo.dart", 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir("foo", [
+        d.file("foo.dart", 'main() => "foo";')
       ]),
-      dir("bar", [
-        file("bar.dart", 'main() => "bar";')
+      d.dir("bar", [
+        d.file("bar.dart", 'main() => "bar";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/path/relative_symlink_test.dart b/utils/tests/pub/install/path/relative_symlink_test.dart
index 66c41c8..eef8570 100644
--- a/utils/tests/pub/install/path/relative_symlink_test.dart
+++ b/utils/tests/pub/install/path/relative_symlink_test.dart
@@ -1,12 +1,13 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import 'dart:io';
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -19,36 +20,36 @@
   initConfig();
   integration("generates a symlink with a relative path if the dependency "
               "path was relative", () {
-    dir("foo", [
-      libDir("foo"),
-      libPubspec("foo", "0.0.1")
-    ]).scheduleCreate();
+    d.dir("foo", [
+      d.libDir("foo"),
+      d.libPubspec("foo", "0.0.1")
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": "../foo"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir("moved").scheduleCreate();
+    d.dir("moved").create();
 
     // Move the app and package. Since they are still next to each other, it
     // should still be found.
     scheduleRename("foo", path.join("moved", "foo"));
     scheduleRename(appPath, path.join("moved", appPath));
 
-    dir("moved", [
-      dir(packagesPath, [
-        dir("foo", [
-          file("foo.dart", 'main() => "foo";')
+    d.dir("moved", [
+      d.dir(packagesPath, [
+        d.dir("foo", [
+          d.file("foo.dart", 'main() => "foo";')
         ])
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/path/shared_dependency_symlink_test.dart b/utils/tests/pub/install/path/shared_dependency_symlink_test.dart
index fddff6b..b192be3 100644
--- a/utils/tests/pub/install/path/shared_dependency_symlink_test.dart
+++ b/utils/tests/pub/install/path/shared_dependency_symlink_test.dart
@@ -1,11 +1,12 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import 'dart:io';
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -15,45 +16,45 @@
 
   initConfig();
   integration("shared dependency with symlink", () {
-    dir("shared", [
-      libDir("shared"),
-      libPubspec("shared", "0.0.1")
-    ]).scheduleCreate();
+    d.dir("shared", [
+      d.libDir("shared"),
+      d.libPubspec("shared", "0.0.1")
+    ]).create();
 
-    dir("foo", [
-      libDir("foo"),
-      libPubspec("foo", "0.0.1", deps: [
+    d.dir("foo", [
+      d.libDir("foo"),
+      d.libPubspec("foo", "0.0.1", deps: [
         {"path": "../shared"}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir("bar", [
-      libDir("bar"),
-      libPubspec("bar", "0.0.1", deps: [
+    d.dir("bar", [
+      d.libDir("bar"),
+      d.libPubspec("bar", "0.0.1", deps: [
         {"path": "../link/shared"}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": "../foo"},
           "bar": {"path": "../bar"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
-    dir("link").scheduleCreate();
+    d.dir("link").create();
     scheduleSymlink("shared", path.join("link", "shared"));
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [file("foo.dart", 'main() => "foo";')]),
-      dir("bar", [file("bar.dart", 'main() => "bar";')]),
-      dir("shared", [file("shared.dart", 'main() => "shared";')])
-    ]).scheduleValidate();
+    d.dir(packagesPath, [
+      d.dir("foo", [d.file("foo.dart", 'main() => "foo";')]),
+      d.dir("bar", [d.file("bar.dart", 'main() => "bar";')]),
+      d.dir("shared", [d.file("shared.dart", 'main() => "shared";')])
+    ]).validate();
   });
 }
\ No newline at end of file
diff --git a/utils/tests/pub/install/path/shared_dependency_test.dart b/utils/tests/pub/install/path/shared_dependency_test.dart
index b7e1596..d425112 100644
--- a/utils/tests/pub/install/path/shared_dependency_test.dart
+++ b/utils/tests/pub/install/path/shared_dependency_test.dart
@@ -1,130 +1,131 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 import '../../../../../pkg/pathos/lib/path.dart' as path;
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   initConfig();
   integration("shared dependency with same path", () {
-    dir("shared", [
-      libDir("shared"),
-      libPubspec("shared", "0.0.1")
-    ]).scheduleCreate();
+    d.dir("shared", [
+      d.libDir("shared"),
+      d.libPubspec("shared", "0.0.1")
+    ]).create();
 
-    dir("foo", [
-      libDir("foo"),
-      libPubspec("foo", "0.0.1", deps: [
+    d.dir("foo", [
+      d.libDir("foo"),
+      d.libPubspec("foo", "0.0.1", deps: [
         {"path": "../shared"}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir("bar", [
-      libDir("bar"),
-      libPubspec("bar", "0.0.1", deps: [
+    d.dir("bar", [
+      d.libDir("bar"),
+      d.libPubspec("bar", "0.0.1", deps: [
         {"path": "../shared"}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": "../foo"},
           "bar": {"path": "../bar"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [file("foo.dart", 'main() => "foo";')]),
-      dir("bar", [file("bar.dart", 'main() => "bar";')]),
-      dir("shared", [file("shared.dart", 'main() => "shared";')])
-    ]).scheduleValidate();
+    d.dir(packagesPath, [
+      d.dir("foo", [d.file("foo.dart", 'main() => "foo";')]),
+      d.dir("bar", [d.file("bar.dart", 'main() => "bar";')]),
+      d.dir("shared", [d.file("shared.dart", 'main() => "shared";')])
+    ]).validate();
   });
 
   integration("shared dependency with paths that normalize the same", () {
-    dir("shared", [
-      libDir("shared"),
-      libPubspec("shared", "0.0.1")
-    ]).scheduleCreate();
+    d.dir("shared", [
+      d.libDir("shared"),
+      d.libPubspec("shared", "0.0.1")
+    ]).create();
 
-    dir("foo", [
-      libDir("foo"),
-      libPubspec("foo", "0.0.1", deps: [
+    d.dir("foo", [
+      d.libDir("foo"),
+      d.libPubspec("foo", "0.0.1", deps: [
         {"path": "../shared"}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir("bar", [
-      libDir("bar"),
-      libPubspec("bar", "0.0.1", deps: [
+    d.dir("bar", [
+      d.libDir("bar"),
+      d.libPubspec("bar", "0.0.1", deps: [
         {"path": "../././shared"}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": "../foo"},
           "bar": {"path": "../bar"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [file("foo.dart", 'main() => "foo";')]),
-      dir("bar", [file("bar.dart", 'main() => "bar";')]),
-      dir("shared", [file("shared.dart", 'main() => "shared";')])
-    ]).scheduleValidate();
+    d.dir(packagesPath, [
+      d.dir("foo", [d.file("foo.dart", 'main() => "foo";')]),
+      d.dir("bar", [d.file("bar.dart", 'main() => "bar";')]),
+      d.dir("shared", [d.file("shared.dart", 'main() => "shared";')])
+    ]).validate();
   });
 
   integration("shared dependency with absolute and relative path", () {
-    dir("shared", [
-      libDir("shared"),
-      libPubspec("shared", "0.0.1")
-    ]).scheduleCreate();
+    d.dir("shared", [
+      d.libDir("shared"),
+      d.libPubspec("shared", "0.0.1")
+    ]).create();
 
-    dir("foo", [
-      libDir("foo"),
-      libPubspec("foo", "0.0.1", deps: [
+    d.dir("foo", [
+      d.libDir("foo"),
+      d.libPubspec("foo", "0.0.1", deps: [
         {"path": "../shared"}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir("bar", [
-      libDir("bar"),
-      libPubspec("bar", "0.0.1", deps: [
+    d.dir("bar", [
+      d.libDir("bar"),
+      d.libPubspec("bar", "0.0.1", deps: [
         {"path": path.join(sandboxDir, "shared")}
       ])
-    ]).scheduleCreate();
+    ]).create();
 
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {"path": "../foo"},
           "bar": {"path": "../bar"}
         }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ["install"],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("foo", [file("foo.dart", 'main() => "foo";')]),
-      dir("bar", [file("bar.dart", 'main() => "bar";')]),
-      dir("shared", [file("shared.dart", 'main() => "shared";')])
-    ]).scheduleValidate();
+    d.dir(packagesPath, [
+      d.dir("foo", [d.file("foo.dart", 'main() => "foo";')]),
+      d.dir("bar", [d.file("bar.dart", 'main() => "bar";')]),
+      d.dir("shared", [d.file("shared.dart", 'main() => "shared";')])
+    ]).validate();
   });
 }
\ No newline at end of file
diff --git a/utils/tests/pub/install/pub_install_test.dart b/utils/tests/pub/install/pub_install_test.dart
index f01bc8f..bdaa25f 100644
--- a/utils/tests/pub/install/pub_install_test.dart
+++ b/utils/tests/pub/install/pub_install_test.dart
@@ -1,12 +1,14 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS d.file
 // for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
+// BSD-style license that can be found in the LICENSE d.file.
 
 library pub_tests;
 
 import 'dart:io';
 
-import '../../../../pkg/unittest/lib/unittest.dart';
+import '../../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
 main() {
@@ -14,7 +16,7 @@
 
   group('requires', () {
     integration('a pubspec', () {
-      dir(appPath, []).scheduleCreate();
+      d.dir(appPath, []).create();
 
       schedulePub(args: ['install'],
           error: new RegExp(r'^Could not find a file named "pubspec\.yaml"'),
@@ -22,9 +24,9 @@
     });
 
     integration('a pubspec with a "name" key', () {
-      dir(appPath, [
-        pubspec({"dependencies": {"foo": null}})
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.pubspec({"dependencies": {"foo": null}})
+      ]).create();
 
       schedulePub(args: ['install'],
           error: new RegExp(r'^pubspec.yaml is missing the required "name" '
@@ -36,45 +38,45 @@
   integration('adds itself to the packages', () {
     // The symlink should use the name in the pubspec, not the name of the
     // directory.
-    dir(appPath, [
-      pubspec({"name": "myapp_name"}),
-      libDir('foo'),
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.pubspec({"name": "myapp_name"}),
+      d.libDir('foo'),
+    ]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir("myapp_name", [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir("myapp_name", [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 
   integration('does not adds itself to the packages if it has no "lib" directory', () {
     // The symlink should use the name in the pubspec, not the name of the
     // directory.
-    dir(appPath, [
-      pubspec({"name": "myapp_name"}),
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.pubspec({"name": "myapp_name"}),
+    ]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      nothing("myapp_name")
-    ]).scheduleValidate();
+    d.dir(packagesPath, [
+      d.nothing("myapp_name")
+    ]).validate();
   });
 
   integration('does not add a package if it does not have a "lib" directory', () {
     // Using a path source, but this should be true of all sources.
-    dir('foo', [
-      libPubspec('foo', '0.0.0-not.used')
-    ]).scheduleCreate();
+    d.dir('foo', [
+      d.libPubspec('foo', '0.0.0-not.used')
+    ]).create();
 
-    dir(appPath, [
-      pubspec({"name": "myapp", "dependencies": {"foo": {"path": "../foo"}}})
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.pubspec({"name": "myapp", "dependencies": {"foo": {"path": "../foo"}}})
+    ]).create();
 
     schedulePub(args: ['install'],
         error: new RegExp(r'Warning: Package "foo" does not have a "lib" '
@@ -84,166 +86,166 @@
   });
 
   integration('does not warn if the root package lacks a "lib" directory', () {
-    dir(appPath, [
-      appPubspec([])
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.appPubspec([])
+    ]).create();
 
     schedulePub(args: ['install'],
-        error: '',
+        error: new RegExp(r'^\s*$'),
         output: new RegExp(r"Dependencies installed!$"));
   });
 
   integration('overwrites the existing packages directory', () {
-    dir(appPath, [
-      appPubspec([]),
-      dir('packages', [
-        dir('foo'),
-        dir('myapp'),
+    d.dir(appPath, [
+      d.appPubspec([]),
+      d.dir('packages', [
+        d.dir('foo'),
+        d.dir('myapp'),
       ]),
-      libDir('myapp')
-    ]).scheduleCreate();
+      d.libDir('myapp')
+    ]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      nothing('foo'),
-      dir('myapp', [file('myapp.dart', 'main() => "myapp";')])
-    ]).scheduleValidate();
+    d.dir(packagesPath, [
+      d.nothing('foo'),
+      d.dir('myapp', [d.file('myapp.dart', 'main() => "myapp";')])
+    ]).validate();
   });
 
   group('creates a packages directory in', () {
     integration('"test/" and its subdirectories', () {
-      dir(appPath, [
-        appPubspec([]),
-        libDir('foo'),
-        dir("test", [dir("subtest")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.appPubspec([]),
+        d.libDir('foo'),
+        d.dir("test", [d.dir("subtest")])
+      ]).create();
 
       schedulePub(args: ['install'],
           output: new RegExp(r"Dependencies installed!$"));
 
-      dir(appPath, [
-        dir("test", [
-          dir("packages", [
-            dir("myapp", [
-              file('foo.dart', 'main() => "foo";')
+      d.dir(appPath, [
+        d.dir("test", [
+          d.dir("packages", [
+            d.dir("myapp", [
+              d.file('foo.dart', 'main() => "foo";')
             ])
           ]),
-          dir("subtest", [
-            dir("packages", [
-              dir("myapp", [
-                file('foo.dart', 'main() => "foo";')
+          d.dir("subtest", [
+            d.dir("packages", [
+              d.dir("myapp", [
+                d.file('foo.dart', 'main() => "foo";')
               ])
             ])
           ])
         ])
-      ]).scheduleValidate();
+      ]).validate();
     });
 
     integration('"example/" and its subdirectories', () {
-      dir(appPath, [
-        appPubspec([]),
-        libDir('foo'),
-        dir("example", [dir("subexample")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.appPubspec([]),
+        d.libDir('foo'),
+        d.dir("example", [d.dir("subexample")])
+      ]).create();
 
       schedulePub(args: ['install'],
           output: new RegExp(r"Dependencies installed!$"));
 
-      dir(appPath, [
-        dir("example", [
-          dir("packages", [
-            dir("myapp", [
-              file('foo.dart', 'main() => "foo";')
+      d.dir(appPath, [
+        d.dir("example", [
+          d.dir("packages", [
+            d.dir("myapp", [
+              d.file('foo.dart', 'main() => "foo";')
             ])
           ]),
-          dir("subexample", [
-            dir("packages", [
-              dir("myapp", [
-                file('foo.dart', 'main() => "foo";')
+          d.dir("subexample", [
+            d.dir("packages", [
+              d.dir("myapp", [
+                d.file('foo.dart', 'main() => "foo";')
               ])
             ])
           ])
         ])
-      ]).scheduleValidate();
+      ]).validate();
     });
 
     integration('"tool/" and its subdirectories', () {
-      dir(appPath, [
-        appPubspec([]),
-        libDir('foo'),
-        dir("tool", [dir("subtool")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.appPubspec([]),
+        d.libDir('foo'),
+        d.dir("tool", [d.dir("subtool")])
+      ]).create();
 
       schedulePub(args: ['install'],
           output: new RegExp(r"Dependencies installed!$"));
 
-      dir(appPath, [
-        dir("tool", [
-          dir("packages", [
-            dir("myapp", [
-              file('foo.dart', 'main() => "foo";')
+      d.dir(appPath, [
+        d.dir("tool", [
+          d.dir("packages", [
+            d.dir("myapp", [
+              d.file('foo.dart', 'main() => "foo";')
             ])
           ]),
-          dir("subtool", [
-            dir("packages", [
-              dir("myapp", [
-                file('foo.dart', 'main() => "foo";')
+          d.dir("subtool", [
+            d.dir("packages", [
+              d.dir("myapp", [
+                d.file('foo.dart', 'main() => "foo";')
               ])
             ])
           ])
         ])
-      ]).scheduleValidate();
+      ]).validate();
     });
 
     integration('"web/" and its subdirectories', () {
-      dir(appPath, [
-        appPubspec([]),
-        libDir('foo'),
-        dir("web", [dir("subweb")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.appPubspec([]),
+        d.libDir('foo'),
+        d.dir("web", [d.dir("subweb")])
+      ]).create();
 
       schedulePub(args: ['install'],
           output: new RegExp(r"Dependencies installed!$"));
 
-      dir(appPath, [
-        dir("web", [
-          dir("packages", [
-            dir("myapp", [
-              file('foo.dart', 'main() => "foo";')
+      d.dir(appPath, [
+        d.dir("web", [
+          d.dir("packages", [
+            d.dir("myapp", [
+              d.file('foo.dart', 'main() => "foo";')
             ])
           ]),
-          dir("subweb", [
-            dir("packages", [
-              dir("myapp", [
-                file('foo.dart', 'main() => "foo";')
+          d.dir("subweb", [
+            d.dir("packages", [
+              d.dir("myapp", [
+                d.file('foo.dart', 'main() => "foo";')
               ])
             ])
           ])
         ])
-      ]).scheduleValidate();
+      ]).validate();
     });
 
     integration('"bin/"', () {
-      dir(appPath, [
-        appPubspec([]),
-        libDir('foo'),
-        dir("bin")
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.appPubspec([]),
+        d.libDir('foo'),
+        d.dir("bin")
+      ]).create();
 
       schedulePub(args: ['install'],
           output: new RegExp(r"Dependencies installed!$"));
 
-      dir(appPath, [
-        dir("bin", [
-          dir("packages", [
-            dir("myapp", [
-              file('foo.dart', 'main() => "foo";')
+      d.dir(appPath, [
+        d.dir("bin", [
+          d.dir("packages", [
+            d.dir("myapp", [
+              d.file('foo.dart', 'main() => "foo";')
             ])
           ])
         ])
-      ]).scheduleValidate();
+      ]).validate();
     });
   });
 }
diff --git a/utils/tests/pub/install/relative_symlink_test.dart b/utils/tests/pub/install/relative_symlink_test.dart
index 166a7ca..5791999 100644
--- a/utils/tests/pub/install/relative_symlink_test.dart
+++ b/utils/tests/pub/install/relative_symlink_test.dart
@@ -6,7 +6,9 @@
 
 import 'dart:io';
 
-import '../../../../pkg/unittest/lib/unittest.dart';
+import '../../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
 main() {
@@ -18,45 +20,45 @@
 
   initConfig();
   integration('uses a relative symlink for the self link', () {
-    dir(appPath, [
-      appPubspec([]),
-      libDir('foo')
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.appPubspec([]),
+      d.libDir('foo')
+    ]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
     scheduleRename(appPath, "moved");
 
-    dir("moved", [
-      dir("packages", [
-        dir("myapp", [
-          file('foo.dart', 'main() => "foo";')
+    d.dir("moved", [
+      d.dir("packages", [
+        d.dir("myapp", [
+          d.file('foo.dart', 'main() => "foo";')
         ])
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 
   integration('uses a relative symlink for secondary packages directory', () {
-    dir(appPath, [
-      appPubspec([]),
-      libDir('foo'),
-      dir("bin")
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.appPubspec([]),
+      d.libDir('foo'),
+      d.dir("bin")
+    ]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
     scheduleRename(appPath, "moved");
 
-    dir("moved", [
-      dir("bin", [
-        dir("packages", [
-          dir("myapp", [
-            file('foo.dart', 'main() => "foo";')
+    d.dir("moved", [
+      d.dir("bin", [
+        d.dir("packages", [
+          d.dir("myapp", [
+            d.file('foo.dart', 'main() => "foo";')
           ])
         ])
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/install/switch_source_test.dart b/utils/tests/pub/install/switch_source_test.dart
new file mode 100644
index 0000000..db8864e
--- /dev/null
+++ b/utils/tests/pub/install/switch_source_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS d.file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE d.file.
+
+library pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+main() {
+  initConfig();
+  integration('re-installs a package if its source has changed', () {
+    d.dir('foo', [
+      d.libDir('foo', 'foo 0.0.1'),
+      d.libPubspec('foo', '0.0.1')
+    ]).create();
+
+    d.appDir([{"path": "../foo"}]).create();
+
+    schedulePub(args: ['install'],
+        output: new RegExp("Dependencies installed!\$"));
+
+    d.packagesDir({"foo": "0.0.1"}).validate();
+
+    servePackages([packageMap("foo", "1.2.3")]);
+
+    d.appDir([dependencyMap("foo", "any")]).create();
+
+    schedulePub(args: ['install'],
+        output: new RegExp("Dependencies installed!\$"));
+
+    d.packagesDir({"foo": "1.2.3"}).validate();
+  });
+}
diff --git a/utils/tests/pub/oauth2_test.dart b/utils/tests/pub/oauth2_test.dart
index afeedc6..0b2772b 100644
--- a/utils/tests/pub/oauth2_test.dart
+++ b/utils/tests/pub/oauth2_test.dart
@@ -8,47 +8,53 @@
 import 'dart:json' as json;
 import 'dart:uri';
 
-import 'test_pub.dart';
 import '../../../pkg/http/lib/http.dart' as http;
-import '../../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_process.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_server.dart';
+
 import '../../pub/io.dart';
 import '../../pub/utils.dart';
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
+
+import 'dart:async';
 
 main() {
-  setUp(() => normalPackage.scheduleCreate());
+  setUp(() => d.validPackage.create());
 
   integration('with no credentials.json, authenticates and saves '
       'credentials.json', () {
     var server = new ScheduledServer();
-    var pub = startPubLish(server);
+    var pub = startPublish(server);
     confirmPublish(pub);
     authorizePub(pub, server);
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
+    server.handle('GET', '/packages/versions/new.json', (request) {
       expect(request.headers.value('authorization'),
           equals('Bearer access token'));
 
-      response.close();
+      request.response.close();
     });
 
     // After we give pub an invalid response, it should crash. We wait for it to
     // do so rather than killing it so it'll write out the credentials file.
     pub.shouldExit(1);
 
-    credentialsFile(server, 'access token').scheduleValidate();
+    d.credentialsFile(server, 'access token').validate();
   });
 
   integration('with a pre-existing credentials.json does not authenticate', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
     confirmPublish(pub);
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
+    server.handle('GET', '/packages/versions/new.json', (request) {
       expect(request.headers.value('authorization'),
           equals('Bearer access token'));
 
-      response.close();
+      request.response.close();
     });
 
     pub.kill();
@@ -57,110 +63,111 @@
   integration('with an expired credentials.json, refreshes and saves the '
       'refreshed access token to credentials.json', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token',
+    d.credentialsFile(server, 'access token',
         refreshToken: 'refresh token',
         expiration: new DateTime.now().subtract(new Duration(hours: 1)))
-        .scheduleCreate();
+        .create();
 
-    var pub = startPubLish(server);
+    var pub = startPublish(server);
     confirmPublish(pub);
 
-    server.handle('POST', '/token', (request, response) {
+    server.handle('POST', '/token', (request) {
       return new ByteStream(request).toBytes().then((bytes) {
         var body = new String.fromCharCodes(bytes);
         expect(body, matches(
             new RegExp(r'(^|&)refresh_token=refresh\+token(&|$)')));
 
-        response.headers.contentType = new ContentType("application", "json");
-        response.write(json.stringify({
+        request.response.headers.contentType =
+            new ContentType("application", "json");
+        request.response.write(json.stringify({
           "access_token": "new access token",
           "token_type": "bearer"
         }));
-        response.close();
+        request.response.close();
       });
     });
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
+    server.handle('GET', '/packages/versions/new.json', (request) {
       expect(request.headers.value('authorization'),
           equals('Bearer new access token'));
 
-      response.close();
+      request.response.close();
     });
 
     pub.shouldExit();
 
-    credentialsFile(server, 'new access token', refreshToken: 'refresh token')
-        .scheduleValidate();
+    d.credentialsFile(server, 'new access token', refreshToken: 'refresh token')
+        .validate();
   });
 
   integration('with an expired credentials.json without a refresh token, '
        'authenticates again and saves credentials.json', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token',
+    d.credentialsFile(server, 'access token',
         expiration: new DateTime.now().subtract(new Duration(hours: 1)))
-        .scheduleCreate();
+        .create();
 
-    var pub = startPubLish(server);
+    var pub = startPublish(server);
     confirmPublish(pub);
 
-    expectLater(pub.nextErrLine(), equals("Pub's authorization to upload "
-          "packages has expired and can't be automatically refreshed."));
+    expect(pub.nextErrLine(), completion(equals("Pub's authorization to upload "
+          "packages has expired and can't be automatically refreshed.")));
     authorizePub(pub, server, "new access token");
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
+    server.handle('GET', '/packages/versions/new.json', (request) {
       expect(request.headers.value('authorization'),
           equals('Bearer new access token'));
 
-      response.close();
+      request.response.close();
     });
 
     // After we give pub an invalid response, it should crash. We wait for it to
     // do so rather than killing it so it'll write out the credentials file.
     pub.shouldExit(1);
 
-    credentialsFile(server, 'new access token').scheduleValidate();
+    d.credentialsFile(server, 'new access token').validate();
   });
 
   integration('with a malformed credentials.json, authenticates again and '
       'saves credentials.json', () {
     var server = new ScheduledServer();
-    dir(cachePath, [
-      file('credentials.json', '{bad json')
-    ]).scheduleCreate();
+    d.dir(cachePath, [
+      d.file('credentials.json', '{bad json')
+    ]).create();
 
-    var pub = startPubLish(server);
+    var pub = startPublish(server);
     confirmPublish(pub);
     authorizePub(pub, server, "new access token");
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
+    server.handle('GET', '/packages/versions/new.json', (request) {
       expect(request.headers.value('authorization'),
           equals('Bearer new access token'));
 
-      response.close();
+      request.response.close();
     });
 
-
     // After we give pub an invalid response, it should crash. We wait for it to
     // do so rather than killing it so it'll write out the credentials file.
     pub.shouldExit(1);
 
-    credentialsFile(server, 'new access token').scheduleValidate();
+    d.credentialsFile(server, 'new access token').validate();
   });
 
   // Regression test for issue 8849.
   integration('with a server-rejected refresh token, authenticates again and '
       'saves credentials.json', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token',
+    d.credentialsFile(server, 'access token',
         refreshToken: 'bad refresh token',
         expiration: new DateTime.now().subtract(new Duration(hours: 1)))
-        .scheduleCreate();
+        .create();
 
-    var pub = startPubLish(server);
+    var pub = startPublish(server);
     confirmPublish(pub);
 
-    server.handle('POST', '/token', (request, response) {
+    server.handle('POST', '/token', (request) {
       return new ByteStream(request).toBytes().then((bytes) {
+        var response = request.response;
         response.statusCode = 400;
         response.reasonPhrase = 'Bad request';
         response.headers.contentType = new ContentType("application", "json");
@@ -171,11 +178,11 @@
 
     authorizePub(pub, server, 'new access token');
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
+    server.handle('GET', '/packages/versions/new.json', (request) {
       expect(request.headers.value('authorization'),
           equals('Bearer new access token'));
 
-      response.close();
+      request.response.close();
     });
 
     pub.kill();
@@ -184,12 +191,13 @@
   integration('with server-rejected credentials, authenticates again and saves '
       'credentials.json', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
+    server.handle('GET', '/packages/versions/new.json', (request) {
+      var response = request.response;
       response.statusCode = 401;
       response.headers.set('www-authenticate', 'Bearer error="invalid_token",'
           ' error_description="your token sucks"');
@@ -199,14 +207,14 @@
       response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('OAuth2 authorization failed (your '
-        'token sucks).'));
+    expect(pub.nextErrLine(), completion(equals('OAuth2 authorization failed '
+        '(your token sucks).')));
     // TODO(rnystrom): The confirm line is run together with this one because
     // in normal usage, the user will have entered a newline on stdin which
     // gets echoed to the terminal. Do something better here?
-    expectLater(pub.nextLine(), equals(
+    expect(pub.nextLine(), completion(equals(
         'Looks great! Are you ready to upload your package (y/n)? '
-        'Pub needs your authorization to upload packages on your behalf.'));
+        'Pub needs your authorization to upload packages on your behalf.')));
     pub.kill();
   });
 }
@@ -216,11 +224,11 @@
   // TODO(rnystrom): The confirm line is run together with this one because
   // in normal usage, the user will have entered a newline on stdin which
   // gets echoed to the terminal. Do something better here?
-  expectLater(pub.nextLine(), equals(
+  expect(pub.nextLine(), completion(equals(
       'Looks great! Are you ready to upload your package (y/n)? '
-      'Pub needs your authorization to upload packages on your behalf.'));
+      'Pub needs your authorization to upload packages on your behalf.')));
 
-  expectLater(pub.nextLine().then((line) {
+  expect(pub.nextLine().then((line) {
     var match = new RegExp(r'[?&]redirect_uri=([0-9a-zA-Z%+-]+)[$&]')
         .firstMatch(line);
     expect(match, isNotNull);
@@ -232,23 +240,24 @@
   }).then((response) {
     expect(response.headers['location'],
         equals('http://pub.dartlang.org/authorized'));
-  }), anything);
+  }), completes);
 
   handleAccessTokenRequest(server, accessToken);
 }
 
 void handleAccessTokenRequest(ScheduledServer server, String accessToken) {
-  server.handle('POST', '/token', (request, response) {
+  server.handle('POST', '/token', (request) {
     return new ByteStream(request).toBytes().then((bytes) {
       var body = new String.fromCharCodes(bytes);
       expect(body, matches(new RegExp(r'(^|&)code=access\+code(&|$)')));
 
-      response.headers.contentType = new ContentType("application", "json");
-      response.write(json.stringify({
+      request.response.headers.contentType =
+          new ContentType("application", "json");
+      request.response.write(json.stringify({
         "access_token": accessToken,
         "token_type": "bearer"
       }));
-      response.close();
+      request.response.close();
     });
   });
 }
diff --git a/utils/tests/pub/pub.status b/utils/tests/pub/pub.status
index f3a3259..b60d685 100644
--- a/utils/tests/pub/pub.status
+++ b/utils/tests/pub/pub.status
@@ -2,13 +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.
 
-# TODO(rnystrom): These tests are still flaky. # Issue 8511
-oauth2_test: Pass,Fail
-pub_uploader_test: Pass,Fail
-
-pub_lish_test: Pass, Fail # Issue 8868
-
-install/broken_symlink_test: Fail # Issue 8343
+pub_uploader_test: Pass, Fail # Issue 9357
 
 # Pub only runs on the VM, so just rule out all compilers.
 [ $compiler == dart2js || $compiler == dart2dart ]
@@ -20,3 +14,4 @@
 
 [ $system == windows ]
 io_test: Fail # Issue 7505
+install/broken_symlink_test: Fail # Issue 9192
diff --git a/utils/tests/pub/pub_cache_test.dart b/utils/tests/pub/pub_cache_test.dart
index b59717b..0dc1d38 100644
--- a/utils/tests/pub/pub_cache_test.dart
+++ b/utils/tests/pub/pub_cache_test.dart
@@ -6,8 +6,12 @@
 
 import 'dart:io';
 import 'dart:json' as json;
-import 'test_pub.dart';
+
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
 import '../../pub/io.dart';
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
 
 main() {
   initConfig();
@@ -40,34 +44,36 @@
   
   integration('running pub cache list on empty cache', () {      
     // Set up a cache.
-    dir(cachePath, [
-      dir('hosted', [
-         dir('pub.dartlang.org', [
+    d.dir(cachePath, [
+      d.dir('hosted', [
+         d.dir('pub.dartlang.org', [
         ])
       ])
-    ]).scheduleCreate();
+    ]).create();
     
     schedulePub(args: ['cache', 'list'], output: '{"packages":{}}');
   });
   
   integration('running pub cache list', () {
     // Set up a cache.
-    dir(cachePath, [
-      dir('hosted', [
-         dir('pub.dartlang.org', [
-          dir("foo-1.2.3", [
-            libPubspec("foo", "1.2.3"),
-            libDir("foo")
+    d.dir(cachePath, [
+      d.dir('hosted', [
+         d.dir('pub.dartlang.org', [
+          d.dir("foo-1.2.3", [
+            d.libPubspec("foo", "1.2.3"),
+            d.libDir("foo")
           ]),
-          dir("bar-2.0.0", [
-            libPubspec("bar", "2.0.0"),
-            libDir("bar") ])
+          d.dir("bar-2.0.0", [
+            d.libPubspec("bar", "2.0.0"),
+            d.libDir("bar") ])
         ])
       ])
-    ]).scheduleCreate();
+    ]).create();
     
     schedulePub(args: ['cache', 'list'], output: 
-      new RegExp(r'\{"packages":\{"bar":\{"version":"2\.0\.0","location":"[^"]+bar-2\.0\.0"\},"foo":\{"version":"1\.2\.3","location":"[^"]+foo-1\.2\.3"\}\}\}$'));
+      new RegExp(r'\{"packages":\{"bar":\{"version":"2\.0\.0","location":'
+          r'"[^"]+bar-2\.0\.0"\},"foo":\{"version":"1\.2\.3","location":'
+          r'"[^"]+foo-1\.2\.3"\}\}\}$'));
   });
   
 }
\ No newline at end of file
diff --git a/utils/tests/pub/pub_lish_test.dart b/utils/tests/pub/pub_lish_test.dart
index 4950554..8b38f2e8 100644
--- a/utils/tests/pub/pub_lish_test.dart
+++ b/utils/tests/pub/pub_lish_test.dart
@@ -7,13 +7,16 @@
 import 'dart:io';
 import 'dart:json' as json;
 
-import 'test_pub.dart';
-import '../../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_server.dart';
+
 import '../../pub/exit_codes.dart' as exit_codes;
 import '../../pub/io.dart';
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
 
 void handleUploadForm(ScheduledServer server, [Map body]) {
-  server.handle('GET', '/packages/versions/new.json', (request, response) {
+  server.handle('GET', '/packages/versions/new.json', (request) {
     return server.url.then((url) {
       expect(request.headers.value('authorization'),
           equals('Bearer access token'));
@@ -28,53 +31,55 @@
         };
       }
 
-      response.headers.contentType = new ContentType("application", "json");
-      response.write(json.stringify(body));
-      response.close();
+      request.response.headers.contentType =
+          new ContentType("application", "json");
+      request.response.write(json.stringify(body));
+      request.response.close();
     });
   });
 }
 
 void handleUpload(ScheduledServer server) {
-  server.handle('POST', '/upload', (request, response) {
+  server.handle('POST', '/upload', (request) {
     // TODO(nweiz): Once a multipart/form-data parser in Dart exists, validate
     // that the request body is correctly formatted. See issue 6952.
     return drainStream(request).then((_) {
       return server.url;
     }).then((url) {
-      response.statusCode = 302;
-      response.headers.set('location', url.resolve('/create').toString());
-      response.close();
+      request.response.statusCode = 302;
+      request.response.headers.set(
+          'location', url.resolve('/create').toString());
+      request.response.close();
     });
   });
 }
 
 main() {
   initConfig();
-  setUp(() => normalPackage.scheduleCreate());
+  setUp(() => d.validPackage.create());
 
   integration('archives and uploads a package', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
     handleUploadForm(server);
     handleUpload(server);
 
-    server.handle('GET', '/create', (request, response) {
-      response.write(json.stringify({
+    server.handle('GET', '/create', (request) {
+      request.response.write(json.stringify({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
-      response.close();
+      request.response.close();
     });
 
     // TODO(rnystrom): The confirm line is run together with this one because
     // in normal usage, the user will have entered a newline on stdin which
     // gets echoed to the terminal. Do something better here?
-    expectLater(pub.nextLine(), equals(
+    expect(pub.nextLine(), completion(equals(
         'Looks great! Are you ready to upload your package (y/n)?'
-        ' Package test_pkg 1.0.0 uploaded!'));
+        ' Package test_pkg 1.0.0 uploaded!')));
     pub.shouldExit(0);
   });
 
@@ -82,125 +87,126 @@
   // test that "pub lish" chooses the correct files to publish.
 
   integration('package validation has an error', () {
-    var pkg = package("test_pkg", "1.0.0");
+    var pkg = packageMap("test_pkg", "1.0.0");
     pkg.remove("homepage");
-    dir(appPath, [pubspec(pkg)]).scheduleCreate();
+    d.dir(appPath, [d.pubspec(pkg)]).create();
 
     var server = new ScheduledServer();
-    var pub = startPubLish(server);
+    var pub = startPublish(server);
 
     pub.shouldExit(0);
-    expectLater(pub.remainingStderr(),
-        contains("Sorry, your package is missing a requirement and can't be "
-            "published yet."));
+    expect(pub.remainingStderr(), completion(contains(
+        "Sorry, your package is missing a requirement and can't be published "
+        "yet.")));
   });
 
   integration('preview package validation has a warning', () {
-    var pkg = package("test_pkg", "1.0.0");
+    var pkg = packageMap("test_pkg", "1.0.0");
     pkg["author"] = "Nathan Weizenbaum";
-    dir(appPath, [pubspec(pkg)]).scheduleCreate();
+    d.dir(appPath, [d.pubspec(pkg)]).create();
 
     var server = new ScheduledServer();
-    var pub = startPubLish(server, args: ['--dry-run']);
+    var pub = startPublish(server, args: ['--dry-run']);
 
     pub.shouldExit(0);
-    expectLater(pub.remainingStderr(),
-        contains('Suggestions:\n* Author "Nathan Weizenbaum" in pubspec.yaml'
-                  ' should have an email address\n'
-                  '  (e.g. "name <email>").\n\n'
-                  'Package has 1 warning.'));
+    expect(pub.remainingStderr(), completion(contains(
+        'Suggestions:\n* Author "Nathan Weizenbaum" in pubspec.yaml should '
+            'have an email address\n'
+        '  (e.g. "name <email>").\n\n'
+        'Package has 1 warning.')));
   });
 
   integration('preview package validation has no warnings', () {
-    var pkg = package("test_pkg", "1.0.0");
+    var pkg = packageMap("test_pkg", "1.0.0");
     pkg["author"] = "Nathan Weizenbaum <nweiz@google.com>";
-    dir(appPath, [pubspec(pkg)]).scheduleCreate();
+    d.dir(appPath, [d.pubspec(pkg)]).create();
 
     var server = new ScheduledServer();
-    var pub = startPubLish(server, args: ['--dry-run']);
+    var pub = startPublish(server, args: ['--dry-run']);
 
     pub.shouldExit(0);
-    expectLater(pub.remainingStderr(),
-        contains('Package has 0 warnings.'));
+    expect(pub.remainingStderr(),
+        completion(contains('Package has 0 warnings.')));
   });
 
   integration('package validation has a warning and is canceled', () {
-    var pkg = package("test_pkg", "1.0.0");
+    var pkg = packageMap("test_pkg", "1.0.0");
     pkg["author"] = "Nathan Weizenbaum";
-    dir(appPath, [pubspec(pkg)]).scheduleCreate();
+    d.dir(appPath, [d.pubspec(pkg)]).create();
 
     var server = new ScheduledServer();
-    var pub = startPubLish(server);
+    var pub = startPublish(server);
 
     pub.writeLine("n");
     pub.shouldExit(0);
-    expectLater(pub.remainingStderr(), contains("Package upload canceled."));
+    expect(pub.remainingStderr(),
+        completion(contains("Package upload canceled.")));
   });
 
   integration('package validation has a warning and continues', () {
-    var pkg = package("test_pkg", "1.0.0");
+    var pkg = packageMap("test_pkg", "1.0.0");
     pkg["author"] = "Nathan Weizenbaum";
-    dir(appPath, [pubspec(pkg)]).scheduleCreate();
+    d.dir(appPath, [d.pubspec(pkg)]).create();
 
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
     pub.writeLine("y");
     handleUploadForm(server);
     handleUpload(server);
 
-    server.handle('GET', '/create', (request, response) {
-      response.write(json.stringify({
+    server.handle('GET', '/create', (request) {
+      request.response.write(json.stringify({
         'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
       }));
-      response.close();
+      request.response.close();
     });
 
     pub.shouldExit(0);
-    expectLater(pub.remainingStdout(),
-        contains('Package test_pkg 1.0.0 uploaded!'));
+    expect(pub.remainingStdout(),
+        completion(contains('Package test_pkg 1.0.0 uploaded!')));
   });
 
   integration('upload form provides an error', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
-      response.statusCode = 400;
-      response.write(json.stringify({
+    server.handle('GET', '/packages/versions/new.json', (request) {
+      request.response.statusCode = 400;
+      request.response.write(json.stringify({
         'error': {'message': 'your request sucked'}
       }));
-      response.close();
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('your request sucked'));
+    expect(pub.nextErrLine(), completion(equals('your request sucked')));
     pub.shouldExit(1);
   });
 
   integration('upload form provides invalid JSON', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
 
-    server.handle('GET', '/packages/versions/new.json', (request, response) {
-      response.write('{not json');
-      response.close();
+    server.handle('GET', '/packages/versions/new.json', (request) {
+      request.response.write('{not json');
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals('{not json'));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals('{not json')));
     pub.shouldExit(1);
   });
 
   integration('upload form is missing url', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
 
@@ -212,15 +218,15 @@
     };
 
     handleUploadForm(server, body);
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals(json.stringify(body)));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals(json.stringify(body))));
     pub.shouldExit(1);
   });
 
   integration('upload form url is not a string', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
 
@@ -233,43 +239,43 @@
     };
 
     handleUploadForm(server, body);
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals(json.stringify(body)));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals(json.stringify(body))));
     pub.shouldExit(1);
   });
 
   integration('upload form is missing fields', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
 
     var body = {'url': 'http://example.com/upload'};
     handleUploadForm(server, body);
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals(json.stringify(body)));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals(json.stringify(body))));
     pub.shouldExit(1);
   });
 
   integration('upload form fields is not a map', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
 
     var body = {'url': 'http://example.com/upload', 'fields': 12};
     handleUploadForm(server, body);
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals(json.stringify(body)));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals(json.stringify(body))));
     pub.shouldExit(1);
   });
 
   integration('upload form fields has a non-string value', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
 
@@ -278,137 +284,141 @@
       'fields': {'field': 12}
     };
     handleUploadForm(server, body);
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals(json.stringify(body)));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals(json.stringify(body))));
     pub.shouldExit(1);
   });
 
   integration('cloud storage upload provides an error', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
     handleUploadForm(server);
 
-    server.handle('POST', '/upload', (request, response) {
+    server.handle('POST', '/upload', (request) {
       return drainStream(request).then((_) {
-        response.statusCode = 400;
-        response.headers.contentType = new ContentType('application', 'xml');
-        response.write('<Error><Message>Your request sucked.'
+        request.response.statusCode = 400;
+        request.response.headers.contentType =
+            new ContentType('application', 'xml');
+        request.response.write('<Error><Message>Your request sucked.'
             '</Message></Error>');
-        response.close();
+        request.response.close();
       });
     });
 
     // TODO(nweiz): This should use the server's error message once the client
     // can parse the XML.
-    expectLater(pub.nextErrLine(), equals('Failed to upload the package.'));
+    expect(pub.nextErrLine(),
+        completion(equals('Failed to upload the package.')));
     pub.shouldExit(1);
   });
 
   integration("cloud storage upload doesn't redirect", () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
     handleUploadForm(server);
 
-    server.handle('POST', '/upload', (request, response) {
+    server.handle('POST', '/upload', (request) {
       return drainStream(request).then((_) {
         // Don't set the location header.
-        response.close();
+        request.response.close();
       });
     });
 
-    expectLater(pub.nextErrLine(), equals('Failed to upload the package.'));
+    expect(pub.nextErrLine(),
+        completion(equals('Failed to upload the package.')));
     pub.shouldExit(1);
   });
 
   integration('package creation provides an error', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
     handleUploadForm(server);
     handleUpload(server);
 
-    server.handle('GET', '/create', (request, response) {
-      response.statusCode = 400;
-      response.write(json.stringify({
+    server.handle('GET', '/create', (request) {
+      request.response.statusCode = 400;
+      request.response.write(json.stringify({
         'error': {'message': 'Your package was too boring.'}
       }));
-      response.close();
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Your package was too boring.'));
+    expect(pub.nextErrLine(),
+        completion(equals('Your package was too boring.')));
     pub.shouldExit(1);
   });
 
   integration('package creation provides invalid JSON', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
     handleUploadForm(server);
     handleUpload(server);
 
-    server.handle('GET', '/create', (request, response) {
-      response.write('{not json');
-      response.close();
+    server.handle('GET', '/create', (request) {
+      request.response.write('{not json');
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals('{not json'));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals('{not json')));
     pub.shouldExit(1);
   });
 
   integration('package creation provides a malformed error', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
     handleUploadForm(server);
     handleUpload(server);
 
     var body = {'error': 'Your package was too boring.'};
-    server.handle('GET', '/create', (request, response) {
-      response.statusCode = 400;
-      response.write(json.stringify(body));
-      response.close();
+    server.handle('GET', '/create', (request) {
+      request.response.statusCode = 400;
+      request.response.write(json.stringify(body));
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals(json.stringify(body)));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals(json.stringify(body))));
     pub.shouldExit(1);
   });
 
   integration('package creation provides a malformed success', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
-    var pub = startPubLish(server);
+    d.credentialsFile(server, 'access token').create();
+    var pub = startPublish(server);
 
     confirmPublish(pub);
     handleUploadForm(server);
     handleUpload(server);
 
     var body = {'success': 'Your package was awesome.'};
-    server.handle('GET', '/create', (request, response) {
-      response.write(json.stringify(body));
-      response.close();
+    server.handle('GET', '/create', (request) {
+      request.response.write(json.stringify(body));
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals(json.stringify(body)));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals(json.stringify(body))));
     pub.shouldExit(1);
   });
 
   group('--force', () {
-    setUp(() => normalPackage.scheduleCreate());
+    setUp(() => d.validPackage.create());
 
     integration('cannot be combined with --dry-run', () {
       schedulePub(args: ['lish', '--force', '--dry-run'],
@@ -418,64 +428,64 @@
 
     integration('publishes if there are no warnings or errors', () {
       var server = new ScheduledServer();
-      credentialsFile(server, 'access token').scheduleCreate();
-      var pub = startPubLish(server, args: ['--force']);
+      d.credentialsFile(server, 'access token').create();
+      var pub = startPublish(server, args: ['--force']);
 
       handleUploadForm(server);
       handleUpload(server);
 
-      server.handle('GET', '/create', (request, response) {
-        response.write(json.stringify({
+      server.handle('GET', '/create', (request) {
+        request.response.write(json.stringify({
           'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
         }));
-        response.close();
+        request.response.close();
       });
 
       pub.shouldExit(0);
-      expectLater(pub.remainingStdout(), contains(
-          'Package test_pkg 1.0.0 uploaded!'));
+      expect(pub.remainingStdout(), completion(contains(
+          'Package test_pkg 1.0.0 uploaded!')));
     });
 
     integration('publishes if there are warnings', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg["author"] = "Nathan Weizenbaum";
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       var server = new ScheduledServer();
-      credentialsFile(server, 'access token').scheduleCreate();
-      var pub = startPubLish(server, args: ['--force']);
+      d.credentialsFile(server, 'access token').create();
+      var pub = startPublish(server, args: ['--force']);
 
       handleUploadForm(server);
       handleUpload(server);
 
-      server.handle('GET', '/create', (request, response) {
-        response.write(json.stringify({
+      server.handle('GET', '/create', (request) {
+        request.response.write(json.stringify({
           'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
         }));
-        response.close();
+        request.response.close();
       });
 
       pub.shouldExit(0);
-      expectLater(pub.remainingStderr(), contains(
+      expect(pub.remainingStderr(), completion(contains(
           'Suggestions:\n* Author "Nathan Weizenbaum" in pubspec.yaml'
           ' should have an email address\n'
-          '  (e.g. "name <email>").'));
-      expectLater(pub.remainingStdout(), contains(
-          'Package test_pkg 1.0.0 uploaded!'));
+          '  (e.g. "name <email>").')));
+      expect(pub.remainingStdout(), completion(contains(
+          'Package test_pkg 1.0.0 uploaded!')));
     });
 
     integration('does not publish if there are errors', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg.remove("homepage");
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       var server = new ScheduledServer();
-      var pub = startPubLish(server, args: ['--force']);
+      var pub = startPublish(server, args: ['--force']);
 
       pub.shouldExit(0);
-      expectLater(pub.remainingStderr(), contains(
+      expect(pub.remainingStderr(), completion(contains(
           "Sorry, your package is missing a requirement and can't be "
-          "published yet."));
+          "published yet.")));
     });
   });
 }
diff --git a/utils/tests/pub/pub_test.dart b/utils/tests/pub/pub_test.dart
index 0696344..49d7063 100644
--- a/utils/tests/pub/pub_test.dart
+++ b/utils/tests/pub/pub_test.dart
@@ -6,8 +6,10 @@
 
 import 'dart:io';
 
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
+import 'descriptor.dart' as d;
 import 'test_pub.dart';
-import '../../../pkg/unittest/lib/unittest.dart';
 
 final USAGE_STRING = """
     Pub is a package manager for Dart.
@@ -130,9 +132,9 @@
     });
 
     integration('parses a release-style version', () {
-      dir(sdkPath, [
-        file('version', '0.1.2.0_r17645'),
-      ]).scheduleCreate();
+      d.dir(sdkPath, [
+        d.file('version', '0.1.2.0_r17645'),
+      ]).create();
 
       schedulePub(args: ['version'], output: "Pub 0.1.2+0.r17645\n");
     });
@@ -140,9 +142,9 @@
     integration('parses a dev-only style version', () {
       // The "version" file generated on developer builds is a little funky and
       // we need to make sure we don't choke on it.
-      dir(sdkPath, [
-        file('version', '0.1.2.0_r16279_bobross'),
-      ]).scheduleCreate();
+      d.dir(sdkPath, [
+        d.file('version', '0.1.2.0_r16279_bobross'),
+      ]).create();
 
       schedulePub(args: ['version'], output: "Pub 0.1.2+0.r16279.bobross\n");
     });
diff --git a/utils/tests/pub/pub_uploader_test.dart b/utils/tests/pub/pub_uploader_test.dart
index 3cbb997..f065cf0 100644
--- a/utils/tests/pub/pub_uploader_test.dart
+++ b/utils/tests/pub/pub_uploader_test.dart
@@ -7,10 +7,14 @@
 import 'dart:io';
 import 'dart:json' as json;
 
-import 'test_pub.dart';
-import '../../../pkg/unittest/lib/unittest.dart';
-import '../../pub/utils.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_process.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_server.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
 import '../../pub/io.dart';
+import '../../pub/utils.dart';
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
 
 final USAGE_STRING = '''
     Manage uploaders for a package on pub.dartlang.org.
@@ -50,129 +54,130 @@
 
   integration('adds an uploader', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
+    d.credentialsFile(server, 'access token').create();
     var pub = startPubUploader(server, ['--package', 'pkg', 'add', 'email']);
 
-    server.handle('POST', '/packages/pkg/uploaders.json', (request, response) {
+    server.handle('POST', '/packages/pkg/uploaders.json', (request) {
       expect(new ByteStream(request).toBytes().then((bodyBytes) {
         expect(new String.fromCharCodes(bodyBytes), equals('email=email'));
 
-        response.headers.contentType = new ContentType("application", "json");
-        response.write(json.stringify({
+        request.response.headers.contentType =
+            new ContentType("application", "json");
+        request.response.write(json.stringify({
           'success': {'message': 'Good job!'}
         }));
-        response.close();
+        request.response.close();
       }), completes);
     });
 
-    expectLater(pub.nextLine(), equals('Good job!'));
+    expect(pub.nextLine(), completion(equals('Good job!')));
     pub.shouldExit(0);
   });
 
   integration('removes an uploader', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
+    d.credentialsFile(server, 'access token').create();
     var pub = startPubUploader(server, ['--package', 'pkg', 'remove', 'email']);
 
-    server.handle('DELETE', '/packages/pkg/uploaders/email.json',
-        (request, response) {
-      response.headers.contentType = new ContentType("application", "json");
-      response.write(json.stringify({
+    server.handle('DELETE', '/packages/pkg/uploaders/email.json', (request) {
+      request.response.headers.contentType =
+          new ContentType("application", "json");
+      request.response.write(json.stringify({
         'success': {'message': 'Good job!'}
       }));
-      response.close();
+      request.response.close();
     });
 
-    expectLater(pub.nextLine(), equals('Good job!'));
+    expect(pub.nextLine(), completion(equals('Good job!')));
     pub.shouldExit(0);
   });
 
   integration('defaults to the current package', () {
-    normalPackage.scheduleCreate();
+    d.validPackage.create();
 
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
+    d.credentialsFile(server, 'access token').create();
     var pub = startPubUploader(server, ['add', 'email']);
 
-    server.handle('POST', '/packages/test_pkg/uploaders.json',
-        (request, response) {
-      response.headers.contentType = new ContentType("application", "json");
-      response.write(json.stringify({
+    server.handle('POST', '/packages/test_pkg/uploaders.json', (request) {
+      request.response.headers.contentType =
+          new ContentType("application", "json");
+      request.response.write(json.stringify({
         'success': {'message': 'Good job!'}
       }));
-      response.close();
+      request.response.close();
     });
 
-    expectLater(pub.nextLine(), equals('Good job!'));
+    expect(pub.nextLine(), completion(equals('Good job!')));
     pub.shouldExit(0);
   });
 
   integration('add provides an error', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
+    d.credentialsFile(server, 'access token').create();
     var pub = startPubUploader(server, ['--package', 'pkg', 'add', 'email']);
 
-    server.handle('POST', '/packages/pkg/uploaders.json', (request, response) {
-      response.statusCode = 400;
-      response.headers.contentType = new ContentType("application", "json");
-      response.write(json.stringify({
+    server.handle('POST', '/packages/pkg/uploaders.json', (request) {
+      request.response.statusCode = 400;
+      request.response.headers.contentType =
+          new ContentType("application", "json");
+      request.response.write(json.stringify({
         'error': {'message': 'Bad job!'}
       }));
-      response.close();
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Bad job!'));
+    expect(pub.nextErrLine(), completion(equals('Bad job!')));
     pub.shouldExit(1);
   });
 
   integration('remove provides an error', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
+    d.credentialsFile(server, 'access token').create();
     var pub = startPubUploader(server,
         ['--package', 'pkg', 'remove', 'e/mail']);
 
-    server.handle('DELETE', '/packages/pkg/uploaders/e%2Fmail.json',
-        (request, response) {
-      response.statusCode = 400;
-      response.headers.contentType = new ContentType("application", "json");
-      response.write(json.stringify({
+    server.handle('DELETE', '/packages/pkg/uploaders/e%2Fmail.json', (request) {
+      request.response.statusCode = 400;
+      request.response.headers.contentType =
+          new ContentType("application", "json");
+      request.response.write(json.stringify({
         'error': {'message': 'Bad job!'}
       }));
-      response.close();
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Bad job!'));
+    expect(pub.nextErrLine(), completion(equals('Bad job!')));
     pub.shouldExit(1);
   });
 
   integration('add provides invalid JSON', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
+    d.credentialsFile(server, 'access token').create();
     var pub = startPubUploader(server, ['--package', 'pkg', 'add', 'email']);
 
-    server.handle('POST', '/packages/pkg/uploaders.json', (request, response) {
-      response.write("{not json");
-      response.close();
+    server.handle('POST', '/packages/pkg/uploaders.json', (request) {
+      request.response.write("{not json");
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals('{not json'));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals('{not json')));
     pub.shouldExit(1);
   });
 
   integration('remove provides invalid JSON', () {
     var server = new ScheduledServer();
-    credentialsFile(server, 'access token').scheduleCreate();
+    d.credentialsFile(server, 'access token').create();
     var pub = startPubUploader(server, ['--package', 'pkg', 'remove', 'email']);
 
-    server.handle('DELETE', '/packages/pkg/uploaders/email.json',
-        (request, response) {
-      response.write("{not json");
-      response.close();
+    server.handle('DELETE', '/packages/pkg/uploaders/email.json', (request) {
+      request.response.write("{not json");
+      request.response.close();
     });
 
-    expectLater(pub.nextErrLine(), equals('Invalid server response:'));
-    expectLater(pub.nextErrLine(), equals('{not json'));
+    expect(pub.nextErrLine(), completion(equals('Invalid server response:')));
+    expect(pub.nextErrLine(), completion(equals('{not json')));
     pub.shouldExit(1);
   });
 }
diff --git a/utils/tests/pub/sdk_constraint_test.dart b/utils/tests/pub/sdk_constraint_test.dart
index 77ea854..db6c769 100644
--- a/utils/tests/pub/sdk_constraint_test.dart
+++ b/utils/tests/pub/sdk_constraint_test.dart
@@ -4,8 +4,10 @@
 
 library check_sdk_test;
 
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
+import 'descriptor.dart' as d;
 import "test_pub.dart";
-import "../../../pkg/unittest/lib/unittest.dart";
 
 main() {
   initConfig();
@@ -17,20 +19,20 @@
     }
 
     integration("gives a friendly message if there are no constraints", () {
-      dir(appPath, [
-        pubspec({"name": "myapp"}),
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.pubspec({"name": "myapp"}),
+      ]).create();
 
       schedulePub(args: [command], output: success);
     });
 
     integration("gives an error if the root package does not match", () {
-      dir(appPath, [
-        pubspec({
+      d.dir(appPath, [
+        d.pubspec({
           "name": "myapp",
           "environment": {"sdk": ">2.0.0"}
         })
-      ]).scheduleCreate();
+      ]).create();
 
       schedulePub(args: [command],
           error:
@@ -45,17 +47,17 @@
 
     integration("gives an error if some dependencies do not match", () {
       // Using a path source, but this should be true of all sources.
-      dir("foo", [
-        libPubspec("foo", "0.0.1", sdk: ">0.1.3"),
-        libDir("foo")
-      ]).scheduleCreate();
-      dir("bar", [
-        libPubspec("bar", "0.0.1", sdk: ">0.1.1"),
-        libDir("bar")
-      ]).scheduleCreate();
+      d.dir("foo", [
+        d.libPubspec("foo", "0.0.1", sdk: ">0.1.3"),
+        d.libDir("foo")
+      ]).create();
+      d.dir("bar", [
+        d.libPubspec("bar", "0.0.1", sdk: ">0.1.1"),
+        d.libDir("bar")
+      ]).create();
 
-      dir(appPath, [
-        pubspec({
+      d.dir(appPath, [
+        d.pubspec({
           "name": "myapp",
           "dependencies": {
             "foo": {"path": "../foo"},
@@ -63,7 +65,7 @@
           },
           "environment": {"sdk": ">2.0.0"}
         })
-      ]).scheduleCreate();
+      ]).create();
 
       schedulePub(args: [command],
           error:
@@ -79,25 +81,25 @@
 
     integration("gives an error if a transitive dependency doesn't match", () {
       // Using a path source, but this should be true of all sources.
-      dir("foo", [
-        libPubspec("foo", "0.0.1", deps: [
+      d.dir("foo", [
+        d.libPubspec("foo", "0.0.1", deps: [
           {"path": "../bar"}
         ]),
-        libDir("foo")
-      ]).scheduleCreate();
-      dir("bar", [
-        libPubspec("bar", "0.0.1", sdk: "<0.1.1"),
-        libDir("bar")
-      ]).scheduleCreate();
+        d.libDir("foo")
+      ]).create();
+      d.dir("bar", [
+        d.libPubspec("bar", "0.0.1", sdk: "<0.1.1"),
+        d.libDir("bar")
+      ]).create();
 
-      dir(appPath, [
-        pubspec({
+      d.dir(appPath, [
+        d.pubspec({
           "name": "myapp",
           "dependencies": {
             "foo": {"path": "../foo"}
           }
         })
-      ]).scheduleCreate();
+      ]).create();
 
       schedulePub(args: [command],
           error:
@@ -112,22 +114,22 @@
 
     integration("handles a circular dependency on the root package", () {
       // Using a path source, but this should be true of all sources.
-      dir("foo", [
-        libPubspec("foo", "0.0.1", sdk: ">3.0.0", deps: [
+      d.dir("foo", [
+        d.libPubspec("foo", "0.0.1", sdk: ">3.0.0", deps: [
           {"path": "../myapp"}
         ]),
-        libDir("foo")
-      ]).scheduleCreate();
+        d.libDir("foo")
+      ]).create();
 
-      dir(appPath, [
-        pubspec({
+      d.dir(appPath, [
+        d.pubspec({
           "name": "myapp",
           "dependencies": {
             "foo": {"path": "../foo"}
           },
           "environment": {"sdk": ">2.0.0"}
         })
-      ]).scheduleCreate();
+      ]).create();
 
       schedulePub(args: [command],
           error:
diff --git a/utils/tests/pub/test_pub.dart b/utils/tests/pub/test_pub.dart
index bf573fd..2073f42 100644
--- a/utils/tests/pub/test_pub.dart
+++ b/utils/tests/pub/test_pub.dart
@@ -19,8 +19,11 @@
 import '../../../pkg/http/lib/testing.dart';
 import '../../../pkg/oauth2/lib/oauth2.dart' as oauth2;
 import '../../../pkg/pathos/lib/path.dart' as path;
-import '../../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_process.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_server.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
 import '../../../pkg/yaml/lib/yaml.dart';
+
 import '../../lib/file_system.dart' as fs;
 import '../../pub/entrypoint.dart';
 // TODO(rnystrom): Using "gitlib" as the prefix here is ugly, but "git" collides
@@ -37,6 +40,7 @@
 import '../../pub/utils.dart';
 import '../../pub/validator.dart';
 import 'command_line_config.dart';
+import 'descriptor.dart' as d;
 
 /// This should be called at the top of a test file to set up an appropriate
 /// test configuration for the machine running the tests.
@@ -47,33 +51,6 @@
   }
 }
 
-/// Creates a new [FileDescriptor] with [name] and [contents].
-FileDescriptor file(Pattern name, String contents) =>
-    new FileDescriptor(name, contents);
-
-/// Creates a new [FileDescriptor] with [name] and [contents].
-FileDescriptor binaryFile(Pattern name, List<int> contents) =>
-    new FileDescriptor.bytes(name, contents);
-
-/// Creates a new [DirectoryDescriptor] with [name] and [contents].
-DirectoryDescriptor dir(Pattern name, [List<Descriptor> contents]) =>
-    new DirectoryDescriptor(name, contents);
-
-/// Creates a new [FutureDescriptor] wrapping [future].
-FutureDescriptor async(Future<Descriptor> future) =>
-    new FutureDescriptor(future);
-
-/// Creates a new [GitRepoDescriptor] with [name] and [contents].
-GitRepoDescriptor git(Pattern name, [List<Descriptor> contents]) =>
-    new GitRepoDescriptor(name, contents);
-
-/// Creates a new [TarFileDescriptor] with [name] and [contents].
-TarFileDescriptor tar(Pattern name, [List<Descriptor> contents]) =>
-    new TarFileDescriptor(name, contents);
-
-/// Creates a new [NothingDescriptor] with [name].
-NothingDescriptor nothing(String name) => new NothingDescriptor(name);
-
 /// The current [HttpServer] created using [serve].
 var _server;
 
@@ -84,9 +61,9 @@
 Completer<int> get _portCompleter {
   if (_portCompleterCache != null) return _portCompleterCache;
   _portCompleterCache = new Completer<int>();
-  _scheduleCleanup((_) {
+  currentSchedule.onComplete.schedule(() {
     _portCompleterCache = null;
-  });
+  }, 'clearing the port completer');
   return _portCompleterCache;
 }
 
@@ -97,45 +74,43 @@
 /// exist only for the duration of the pub run.
 ///
 /// Subsequent calls to [serve] will replace the previous server.
-void serve([List<Descriptor> contents]) {
-  var baseDir = dir("serve-dir", contents);
+void serve([List<d.Descriptor> contents]) {
+  var baseDir = d.dir("serve-dir", contents);
 
-  _schedule((_) {
+  schedule(() {
     return _closeServer().then((_) {
       return SafeHttpServer.bind("127.0.0.1", 0).then((server) {
         _server = server;
         server.listen((request) {
           var response = request.response;
-          var path = request.uri.path.replaceFirst("/", "").split("/");
-          response.persistentConnection = false;
-          var stream;
           try {
-            stream = baseDir.load(path);
+            var path = request.uri.path.replaceFirst("/", "");
+            response.persistentConnection = false;
+            var stream = baseDir.load(path);
+
+            new ByteStream(stream).toBytes().then((data) {
+              response.statusCode = 200;
+              response.contentLength = data.length;
+              response.writeBytes(data);
+              response.close();
+            }).catchError((e) {
+              response.statusCode = 404;
+              response.contentLength = 0;
+              response.close();
+            });
           } catch (e) {
-            response.statusCode = 404;
-            response.contentLength = 0;
+            currentSchedule.signalError(e);
+            response.statusCode = 500;
             response.close();
             return;
           }
-
-          stream.toBytes().then((data) {
-            response.statusCode = 200;
-            response.contentLength = data.length;
-            response.writeBytes(data);
-            response.close();
-          }).catchError((e) {
-            print("Exception while handling ${request.uri}: $e");
-            response.statusCode = 500;
-            response.reasonPhrase = e.message;
-            response.close();
-          });
         });
         _portCompleter.complete(_server.port);
-        _scheduleCleanup((_) => _closeServer());
+        currentSchedule.onComplete.schedule(_closeServer);
         return null;
       });
     });
-  });
+  }, 'starting a server serving:\n${baseDir.describe()}');
 }
 
 /// Closes [_server]. Returns a [Future] that will complete after the [_server]
@@ -151,10 +126,10 @@
   return sleep(10);
 }
 
-/// The [DirectoryDescriptor] describing the server layout of packages that are
-/// being served via [servePackages]. This is `null` if [servePackages] has not
-/// yet been called for this test.
-DirectoryDescriptor _servedPackageDir;
+/// The [d.DirectoryDescriptor] describing the server layout of packages that
+/// are being served via [servePackages]. This is `null` if [servePackages] has
+/// not yet been called for this test.
+d.DirectoryDescriptor _servedPackageDir;
 
 /// A map from package names to version numbers to YAML-serialized pubspecs for
 /// those packages. This represents the packages currently being served by
@@ -171,17 +146,17 @@
 void servePackages(List<Map> pubspecs) {
   if (_servedPackages == null || _servedPackageDir == null) {
     _servedPackages = <String, Map<String, String>>{};
-    _servedPackageDir = dir('packages', []);
+    _servedPackageDir = d.dir('packages', []);
     serve([_servedPackageDir]);
 
-    _scheduleCleanup((_) {
+    currentSchedule.onComplete.schedule(() {
       _servedPackages = null;
       _servedPackageDir = null;
-    });
+    }, 'cleaning up served packages');
   }
 
-  _schedule((_) {
-    return _awaitObject(pubspecs).then((resolvedPubspecs) {
+  schedule(() {
+    return awaitObject(pubspecs).then((resolvedPubspecs) {
       for (var spec in resolvedPubspecs) {
         var name = spec['name'];
         var version = spec['version'];
@@ -194,15 +169,14 @@
       for (var name in _servedPackages.keys) {
         var versions = _servedPackages[name].keys.toList();
         _servedPackageDir.contents.addAll([
-          file('$name.json',
-              json.stringify({'versions': versions})),
-          dir(name, [
-            dir('versions', flatten(versions.map((version) {
+          d.file('$name.json', json.stringify({'versions': versions})),
+          d.dir(name, [
+            d.dir('versions', flatten(versions.map((version) {
               return [
-                file('$version.yaml', _servedPackages[name][version]),
-                tar('$version.tar.gz', [
-                  file('pubspec.yaml', _servedPackages[name][version]),
-                  libDir(name, '$name $version')
+                d.file('$version.yaml', _servedPackages[name][version]),
+                d.tar('$version.tar.gz', [
+                  d.file('pubspec.yaml', _servedPackages[name][version]),
+                  d.libDir(name, '$name $version')
                 ])
               ];
             })))
@@ -210,71 +184,225 @@
         ]);
       }
     });
-  });
+  }, 'initializing the package server');
 }
 
 /// Converts [value] into a YAML string.
 String yaml(value) => json.stringify(value);
 
-/// Describes a package that passes all validation.
-Descriptor get normalPackage => dir(appPath, [
-  libPubspec("test_pkg", "1.0.0"),
-  file("LICENSE", "Eh, do what you want."),
-  dir("lib", [
-    file("test_pkg.dart", "int i = 1;")
-  ])
-]);
+/// The full path to the created sandbox directory for an integration test.
+String get sandboxDir => _sandboxDir;
+String _sandboxDir;
 
-/// Describes a file named `pubspec.yaml` with the given YAML-serialized
-/// [contents], which should be a serializable object.
-///
-/// [contents] may contain [Future]s that resolve to serializable objects,
-/// which may in turn contain [Future]s recursively.
-Descriptor pubspec(Map contents) {
-  return async(_awaitObject(contents).then((resolvedContents) =>
-      file("pubspec.yaml", yaml(resolvedContents))));
-}
+/// The path of the package cache directory used for tests. Relative to the
+/// sandbox directory.
+final String cachePath = "cache";
 
-/// Describes a file named `pubspec.yaml` for an application package with the
-/// given [dependencies].
-Descriptor appPubspec(List dependencies) {
-  return pubspec({
-    "name": "myapp",
-    "dependencies": _dependencyListToMap(dependencies)
+/// The path of the mock SDK directory used for tests. Relative to the sandbox
+/// directory.
+final String sdkPath = "sdk";
+
+/// The path of the mock app directory used for tests. Relative to the sandbox
+/// directory.
+final String appPath = "myapp";
+
+/// The path of the packages directory in the mock app used for tests. Relative
+/// to the sandbox directory.
+final String packagesPath = "$appPath/packages";
+
+/// Set to true when the current batch of scheduled events should be aborted.
+bool _abortScheduled = false;
+
+/// The time (in milliseconds) to wait for the entire scheduled test to
+/// complete.
+final _TIMEOUT = 30000;
+
+/// Defines an integration test. The [body] should schedule a series of
+/// operations which will be run asynchronously.
+void integration(String description, void body()) =>
+  _integration(description, body, test);
+
+/// Like [integration], but causes only this test to run.
+void solo_integration(String description, void body()) =>
+  _integration(description, body, solo_test);
+
+void _integration(String description, void body(), [Function testFn]) {
+  testFn(description, () {
+    // Ensure the SDK version is always available.
+    d.dir(sdkPath, [
+      d.file('version', '0.1.2.3')
+    ]).create();
+
+    _sandboxDir = createTempDir();
+    d.defaultRoot = sandboxDir;
+    currentSchedule.onComplete.schedule(() => deleteDir(_sandboxDir),
+        'deleting the sandbox directory');
+
+    // Schedule the test.
+    body();
   });
 }
 
-/// Describes a file named `pubspec.yaml` for a library package with the given
-/// [name], [version], and [deps]. If "sdk" is given, then it adds an SDK
-/// constraint on that version.
-Descriptor libPubspec(String name, String version, {List deps, String sdk}) {
-  var map = package(name, version, deps);
+/// Get the path to the root "util/test/pub" directory containing the pub
+/// tests.
+String get testDirectory {
+  var dir = new Options().script;
+  while (path.basename(dir) != 'pub') dir = path.dirname(dir);
 
-  if (sdk != null) {
-    map["environment"] = {
-      "sdk": sdk
-    };
-  }
-
-  return pubspec(map);
+  return path.absolute(dir);
 }
 
-/// Describes a directory named `lib` containing a single dart file named
-/// `<name>.dart` that contains a line of Dart code.
-Descriptor libDir(String name, [String code]) {
-  // Default to printing the name if no other code was given.
-  if (code == null) {
-    code = name;
+/// Schedules renaming (moving) the directory at [from] to [to], both of which
+/// are assumed to be relative to [sandboxDir].
+void scheduleRename(String from, String to) {
+  schedule(
+      () => renameDir(
+          path.join(sandboxDir, from),
+          path.join(sandboxDir, to)),
+      'renaming $from to $to');
+}
+
+/// Schedules creating a symlink at path [symlink] that points to [target],
+/// both of which are assumed to be relative to [sandboxDir].
+void scheduleSymlink(String target, String symlink) {
+  schedule(
+      () => createSymlink(
+          path.join(sandboxDir, target),
+          path.join(sandboxDir, symlink)),
+      'symlinking $target to $symlink');
+}
+
+/// Schedules a call to the Pub command-line utility. Runs Pub with [args] and
+/// validates that its results match [output], [error], and [exitCode].
+void schedulePub({List args, Pattern output, Pattern error,
+    Future<Uri> tokenEndpoint, int exitCode: 0}) {
+  var pub = startPub(args: args, tokenEndpoint: tokenEndpoint);
+  pub.shouldExit(exitCode);
+
+  expect(Future.wait([
+    pub.remainingStdout(),
+    pub.remainingStderr()
+  ]).then((results) {
+    var failures = [];
+    _validateOutput(failures, 'stdout', output, results[0].split('\n'));
+    _validateOutput(failures, 'stderr', error, results[1].split('\n'));
+    if (!failures.isEmpty) throw new TestFailure(failures.join('\n'));
+  }), completes);
+}
+
+/// Like [startPub], but runs `pub lish` in particular with [server] used both
+/// as the OAuth2 server (with "/token" as the token endpoint) and as the
+/// package server.
+///
+/// Any futures in [args] will be resolved before the process is started.
+ScheduledProcess startPublish(ScheduledServer server, {List args}) {
+  var tokenEndpoint = server.url.then((url) =>
+      url.resolve('/token').toString());
+  if (args == null) args = [];
+  args = flatten(['lish', '--server', tokenEndpoint, args]);
+  return startPub(args: args, tokenEndpoint: tokenEndpoint);
+}
+
+/// Handles the beginning confirmation process for uploading a packages.
+/// Ensures that the right output is shown and then enters "y" to confirm the
+/// upload.
+void confirmPublish(ScheduledProcess pub) {
+  // TODO(rnystrom): This is overly specific and inflexible regarding different
+  // test packages. Should validate this a little more loosely.
+  expect(pub.nextLine(), completion(equals('Publishing "test_pkg" 1.0.0:')));
+  expect(pub.nextLine(), completion(equals("|-- LICENSE")));
+  expect(pub.nextLine(), completion(equals("|-- lib")));
+  expect(pub.nextLine(), completion(equals("|   '-- test_pkg.dart")));
+  expect(pub.nextLine(), completion(equals("'-- pubspec.yaml")));
+  expect(pub.nextLine(), completion(equals("")));
+
+  pub.writeLine("y");
+}
+
+/// Starts a Pub process and returns a [ScheduledProcess] that supports
+/// interaction with that process.
+///
+/// Any futures in [args] will be resolved before the process is started.
+ScheduledProcess startPub({List args, Future<Uri> tokenEndpoint}) {
+  String pathInSandbox(String relPath) {
+    return path.join(path.absolute(sandboxDir), relPath);
   }
 
-  return dir("lib", [
-    file("$name.dart", 'main() => "$code";')
-  ]);
+  ensureDir(pathInSandbox(appPath));
+
+  // Find a Dart executable we can use to spawn. Use the same one that was
+  // used to run this script itself.
+  var dartBin = new Options().executable;
+
+  // If the executable looks like a path, get its full path. That way we
+  // can still find it when we spawn it with a different working directory.
+  if (dartBin.contains(Platform.pathSeparator)) {
+    dartBin = new File(dartBin).fullPathSync();
+  }
+
+  // Find the main pub entrypoint.
+  var pubPath = fs.joinPaths(testDirectory, '../../pub/pub.dart');
+
+  var dartArgs = ['--checked', pubPath, '--trace'];
+  dartArgs.addAll(args);
+
+  if (tokenEndpoint == null) tokenEndpoint = new Future.immediate(null);
+  var optionsFuture = tokenEndpoint.then((tokenEndpoint) {
+    var options = new ProcessOptions();
+    options.workingDirectory = pathInSandbox(appPath);
+    // TODO(nweiz): remove this when issue 9294 is fixed.
+    options.environment = new Map.from(Platform.environment);
+    options.environment['PUB_CACHE'] = pathInSandbox(cachePath);
+    options.environment['DART_SDK'] = pathInSandbox(sdkPath);
+    if (tokenEndpoint != null) {
+      options.environment['_PUB_TEST_TOKEN_ENDPOINT'] =
+        tokenEndpoint.toString();
+    }
+    return options;
+  });
+
+  return new ScheduledProcess.start(dartBin, dartArgs, options: optionsFuture,
+      description: args.isEmpty ? 'pub' : 'pub ${args.first}');
+}
+
+/// Skips the current test if Git is not installed. This validates that the
+/// current test is running on a buildbot in which case we expect git to be
+/// installed. If we are not running on the buildbot, we will instead see if
+/// git is installed and skip the test if not. This way, users don't need to
+/// have git installed to run the tests locally (unless they actually care
+/// about the pub git tests).
+///
+/// This will also increase the [Schedule] timeout to 30 seconds on Windows,
+/// where Git runs really slowly.
+void ensureGit() {
+  if (Platform.operatingSystem == "windows") {
+    currentSchedule.timeout = new Duration(seconds: 30);
+  }
+
+  schedule(() {
+    return gitlib.isInstalled.then((installed) {
+      if (installed) return;
+      if (Platform.environment.containsKey('BUILDBOT_BUILDERNAME')) return;
+      currentSchedule.abort();
+    });
+  }, 'ensuring that Git is installed');
+}
+
+/// Use [client] as the mock HTTP client for this test.
+///
+/// Note that this will only affect HTTP requests made via http.dart in the
+/// parent process.
+void useMockClient(MockClient client) {
+  var oldInnerClient = httpClient.inner;
+  httpClient.inner = client;
+  currentSchedule.onComplete.schedule(() {
+    httpClient.inner = oldInnerClient;
+  }, 'de-activating the mock client');
 }
 
 /// Describes a map representing a library package with the given [name],
 /// [version], and [dependencies].
-Map package(String name, String version, [List dependencies]) {
+Map packageMap(String name, String version, [List dependencies]) {
   var package = {
     "name": name,
     "version": version,
@@ -283,118 +411,24 @@
     "description": "A package, I guess."
   };
   if (dependencies != null) {
-    package["dependencies"] = _dependencyListToMap(dependencies);
+    package["dependencies"] = dependencyListToMap(dependencies);
   }
   return package;
 }
 
 /// Describes a map representing a dependency on a package in the package
 /// repository.
-Map dependency(String name, [String versionConstraint]) {
+Map dependencyMap(String name, [String versionConstraint]) {
   var url = port.then((p) => "http://localhost:$p");
   var dependency = {"hosted": {"name": name, "url": url}};
   if (versionConstraint != null) dependency["version"] = versionConstraint;
   return dependency;
 }
 
-/// Describes a directory for a package installed from the mock package server.
-/// This directory is of the form found in the global package cache.
-DirectoryDescriptor packageCacheDir(String name, String version) {
-  return dir("$name-$version", [
-    libDir(name, '$name $version')
-  ]);
-}
-
-/// Describes a directory for a Git package. This directory is of the form
-/// found in the revision cache of the global package cache.
-DirectoryDescriptor gitPackageRevisionCacheDir(String name, [int modifier]) {
-  var value = name;
-  if (modifier != null) value = "$name $modifier";
-  return dir(new RegExp("$name${r'-[a-f0-9]+'}"), [
-    libDir(name, value)
-  ]);
-}
-
-/// Describes a directory for a Git package. This directory is of the form
-/// found in the repo cache of the global package cache.
-DirectoryDescriptor gitPackageRepoCacheDir(String name) {
-  return dir(new RegExp("$name${r'-[a-f0-9]+'}"), [
-    dir('hooks'),
-    dir('info'),
-    dir('objects'),
-    dir('refs')
-  ]);
-}
-
-/// Describes the `packages/` directory containing all the given [packages],
-/// which should be name/version pairs. The packages will be validated against
-/// the format produced by the mock package server.
-///
-/// A package with a null version should not be installed.
-DirectoryDescriptor packagesDir(Map<String, String> packages) {
-  var contents = <Descriptor>[];
-  packages.forEach((name, version) {
-    if (version == null) {
-      contents.add(nothing(name));
-    } else {
-      contents.add(dir(name, [
-        file("$name.dart", 'main() => "$name $version";')
-      ]));
-    }
-  });
-  return dir(packagesPath, contents);
-}
-
-/// Describes the global package cache directory containing all the given
-/// [packages], which should be name/version pairs. The packages will be
-/// validated against the format produced by the mock package server.
-///
-/// A package's value may also be a list of versions, in which case all
-/// versions are expected to be installed.
-DirectoryDescriptor cacheDir(Map packages) {
-  var contents = <Descriptor>[];
-  packages.forEach((name, versions) {
-    if (versions is! List) versions = [versions];
-    for (var version in versions) {
-      contents.add(packageCacheDir(name, version));
-    }
-  });
-  return dir(cachePath, [
-    dir('hosted', [
-      async(port.then((p) => dir('localhost%58$p', contents)))
-    ])
-  ]);
-}
-
-/// Describes the file in the system cache that contains the client's OAuth2
-/// credentials. The URL "/token" on [server] will be used as the token
-/// endpoint for refreshing the access token.
-Descriptor credentialsFile(
-    ScheduledServer server,
-    String accessToken,
-    {String refreshToken,
-     DateTime expiration}) {
-  return async(server.url.then((url) {
-    return dir(cachePath, [
-      file('credentials.json', new oauth2.Credentials(
-          accessToken,
-          refreshToken,
-          url.resolve('/token'),
-          ['https://www.googleapis.com/auth/userinfo.email'],
-          expiration).toJson())
-    ]);
-  }));
-}
-
-/// Describes the application directory, containing only a pubspec specifying
-/// the given [dependencies].
-DirectoryDescriptor appDir(List dependencies) =>
-  dir(appPath, [appPubspec(dependencies)]);
-
 /// Converts a list of dependencies as passed to [package] into a hash as used
 /// in a pubspec.
-Future<Map> _dependencyListToMap(List<Map> dependencies) {
-  return _awaitObject(dependencies).then((resolvedDependencies) {
+Future<Map> dependencyListToMap(List<Map> dependencies) {
+  return awaitObject(dependencies).then((resolvedDependencies) {
     var result = <String, Map>{};
     for (var dependency in resolvedDependencies) {
       var keys = dependency.keys.where((key) => key != "version");
@@ -441,298 +475,6 @@
   }
 }
 
-/// The full path to the created sandbox directory for an integration test.
-String get sandboxDir => _sandboxDir;
-String _sandboxDir;
-
-/// The path of the package cache directory used for tests. Relative to the
-/// sandbox directory.
-final String cachePath = "cache";
-
-/// The path of the mock SDK directory used for tests. Relative to the sandbox
-/// directory.
-final String sdkPath = "sdk";
-
-/// The path of the mock app directory used for tests. Relative to the sandbox
-/// directory.
-final String appPath = "myapp";
-
-/// The path of the packages directory in the mock app used for tests. Relative
-/// to the sandbox directory.
-final String packagesPath = "$appPath/packages";
-
-/// The type for callbacks that will be fired during [schedulePub]. Takes the
-/// sandbox directory as a parameter.
-typedef Future _ScheduledEvent(String parentDir);
-
-/// The list of events that are scheduled to run as part of the test case.
-Queue<_ScheduledEvent> _scheduled;
-
-/// The list of events that are scheduled to run after the test case, even if
-/// it failed.
-Queue<_ScheduledEvent> _scheduledCleanup;
-
-/// The list of events that are scheduled to run after the test case only if it
-/// failed.
-Queue<_ScheduledEvent> _scheduledOnException;
-
-/// Set to true when the current batch of scheduled events should be aborted.
-bool _abortScheduled = false;
-
-/// The time (in milliseconds) to wait for the entire scheduled test to
-/// complete.
-final _TIMEOUT = 30000;
-
-/// Defines an integration test. The [body] should schedule a series of
-/// operations which will be run asynchronously.
-void integration(String description, void body()) =>
-  _integration(description, body, test);
-
-/// Like [integration], but causes only this test to run.
-void solo_integration(String description, void body()) =>
-  _integration(description, body, solo_test);
-
-void _integration(String description, void body(), [Function testFn]) {
-  testFn(description, () {
-    // Ensure the SDK version is always available.
-    dir(sdkPath, [
-      file('version', '0.1.2.3')
-    ]).scheduleCreate();
-
-    _sandboxDir = createTempDir();
-
-    // Schedule the test.
-    body();
-
-    // Run all of the scheduled tasks. If an error occurs, it will propagate
-    // through the futures back up to here where we can hand it off to unittest.
-    var asyncDone = expectAsync0(() {});
-    return timeout(_runScheduled(_scheduled),
-          _TIMEOUT, 'waiting for a test to complete').catchError((e) {
-      return _runScheduled(_scheduledOnException).then((_) {
-        // Rethrow the original error so it keeps propagating.
-        throw e;
-      });
-    }).whenComplete(() {
-      // Clean up after ourselves. Do this first before reporting back to
-      // unittest because it will advance to the next test immediately.
-      return _runScheduled(_scheduledCleanup).then((_) {
-        _scheduled = null;
-        _scheduledCleanup = null;
-        _scheduledOnException = null;
-        if (_sandboxDir != null) {
-          var dir = _sandboxDir;
-          _sandboxDir = null;
-          return deleteDir(dir);
-        }
-      });
-    }).then((_) {
-      // If we got here, the test completed successfully so tell unittest so.
-      asyncDone();
-    }).catchError((e) {
-      // If we got here, an error occurred. We will register it with unittest
-      // directly so that the error message isn't wrapped in any matcher stuff.
-      // We do this call last because it will cause unittest to *synchronously*
-      // advance to the next test and run it.
-      registerException(e.error, e.stackTrace);
-    });
-  });
-}
-
-/// Get the path to the root "util/test/pub" directory containing the pub
-/// tests.
-String get testDirectory {
-  var dir = new Options().script;
-  while (path.basename(dir) != 'pub') dir = path.dirname(dir);
-
-  return path.absolute(dir);
-}
-
-/// Schedules renaming (moving) the directory at [from] to [to], both of which
-/// are assumed to be relative to [sandboxDir].
-void scheduleRename(String from, String to) {
-  _schedule((sandboxDir) {
-    return renameDir(path.join(sandboxDir, from), path.join(sandboxDir, to));
-  });
-}
-
-
-/// Schedules creating a symlink at path [symlink] that points to [target],
-/// both of which are assumed to be relative to [sandboxDir].
-void scheduleSymlink(String target, String symlink) {
-  _schedule((sandboxDir) {
-    return createSymlink(path.join(sandboxDir, target),
-        path.join(sandboxDir, symlink));
-  });
-}
-
-/// Schedules a call to the Pub command-line utility. Runs Pub with [args] and
-/// validates that its results match [output], [error], and [exitCode].
-void schedulePub({List args, Pattern output, Pattern error,
-    Future<Uri> tokenEndpoint, int exitCode: 0}) {
-  _schedule((sandboxDir) {
-    return _doPub(runProcess, sandboxDir, args, tokenEndpoint).then((result) {
-      var failures = [];
-
-      _validateOutput(failures, 'stdout', output, result.stdout);
-      _validateOutput(failures, 'stderr', error, result.stderr);
-
-      if (result.exitCode != exitCode) {
-        failures.add(
-            'Pub returned exit code ${result.exitCode}, expected $exitCode.');
-      }
-
-      if (failures.length > 0) {
-        if (error == null) {
-          // If we aren't validating the error, still show it on failure.
-          failures.add('Pub stderr:');
-          failures.addAll(result.stderr.map((line) => '| $line'));
-        }
-
-        throw new TestFailure(failures.join('\n'));
-      }
-
-      return null;
-    });
-  });
-}
-
-/// Starts a Pub process and returns a [ScheduledProcess] that supports
-/// interaction with that process.
-///
-/// Any futures in [args] will be resolved before the process is started.
-ScheduledProcess startPub({List args, Future<Uri> tokenEndpoint}) {
-  var process = _scheduleValue((sandboxDir) =>
-      _doPub(startProcess, sandboxDir, args, tokenEndpoint));
-  return new ScheduledProcess("pub", process);
-}
-
-/// Like [startPub], but runs `pub lish` in particular with [server] used both
-/// as the OAuth2 server (with "/token" as the token endpoint) and as the
-/// package server.
-///
-/// Any futures in [args] will be resolved before the process is started.
-ScheduledProcess startPubLish(ScheduledServer server, {List args}) {
-  var tokenEndpoint = server.url.then((url) =>
-      url.resolve('/token').toString());
-  if (args == null) args = [];
-  args = flatten(['lish', '--server', tokenEndpoint, args]);
-  return startPub(args: args, tokenEndpoint: tokenEndpoint);
-}
-
-/// Handles the beginning confirmation process for uploading a packages.
-/// Ensures that the right output is shown and then enters "y" to confirm the
-/// upload.
-void confirmPublish(ScheduledProcess pub) {
-  // TODO(rnystrom): This is overly specific and inflexible regarding different
-  // test packages. Should validate this a little more loosely.
-  expectLater(pub.nextLine(), equals('Publishing "test_pkg" 1.0.0:'));
-  expectLater(pub.nextLine(), equals("|-- LICENSE"));
-  expectLater(pub.nextLine(), equals("|-- lib"));
-  expectLater(pub.nextLine(), equals("|   '-- test_pkg.dart"));
-  expectLater(pub.nextLine(), equals("'-- pubspec.yaml"));
-  expectLater(pub.nextLine(), equals(""));
-
-  pub.writeLine("y");
-}
-
-/// Calls [fn] with appropriately modified arguments to run a pub process. [fn]
-/// should have the same signature as [startProcess], except that the returned
-/// [Future] may have a type other than [Process].
-Future _doPub(Function fn, sandboxDir, List args, Future<Uri> tokenEndpoint) {
-  String pathInSandbox(String relPath) {
-    return path.join(path.absolute(sandboxDir), relPath);
-  }
-
-  return defer(() {
-    ensureDir(pathInSandbox(appPath));
-    return Future.wait([
-      _awaitObject(args),
-      tokenEndpoint == null ? new Future.immediate(null) : tokenEndpoint
-    ]);
-  }).then((results) {
-    var args = results[0];
-    var tokenEndpoint = results[1];
-    // Find a Dart executable we can use to spawn. Use the same one that was
-    // used to run this script itself.
-    var dartBin = new Options().executable;
-
-    // If the executable looks like a path, get its full path. That way we
-    // can still find it when we spawn it with a different working directory.
-    if (dartBin.contains(Platform.pathSeparator)) {
-      dartBin = new File(dartBin).fullPathSync();
-    }
-
-    // Find the main pub entrypoint.
-    var pubPath = fs.joinPaths(testDirectory, '../../pub/pub.dart');
-
-    var dartArgs = ['--checked', pubPath, '--trace'];
-    dartArgs.addAll(args);
-
-    var environment = {
-      'PUB_CACHE': pathInSandbox(cachePath),
-      'DART_SDK': pathInSandbox(sdkPath)
-    };
-
-    if (tokenEndpoint != null) {
-      environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint.toString();
-    }
-
-    return fn(dartBin, dartArgs, workingDir: pathInSandbox(appPath),
-        environment: environment);
-  });
-}
-
-/// Skips the current test if Git is not installed. This validates that the
-/// current test is running on a buildbot in which case we expect git to be
-/// installed. If we are not running on the buildbot, we will instead see if
-/// git is installed and skip the test if not. This way, users don't need to
-/// have git installed to run the tests locally (unless they actually care
-/// about the pub git tests).
-void ensureGit() {
-  _schedule((_) {
-    return gitlib.isInstalled.then((installed) {
-      if (!installed &&
-          !Platform.environment.containsKey('BUILDBOT_BUILDERNAME')) {
-        _abortScheduled = true;
-      }
-      return null;
-    });
-  });
-}
-
-/// Use [client] as the mock HTTP client for this test.
-///
-/// Note that this will only affect HTTP requests made via http.dart in the
-/// parent process.
-void useMockClient(MockClient client) {
-  var oldInnerClient = httpClient.inner;
-  httpClient.inner = client;
-  _scheduleCleanup((_) {
-    httpClient.inner = oldInnerClient;
-  });
-}
-
-Future _runScheduled(Queue<_ScheduledEvent> scheduled) {
-  if (scheduled == null) return new Future.immediate(null);
-
-  Future runNextEvent(_) {
-    if (_abortScheduled || scheduled.isEmpty) {
-      _abortScheduled = false;
-      return new Future.immediate(null);
-    }
-
-    var future = scheduled.removeFirst()(_sandboxDir);
-    if (future != null) {
-      return future.then(runNextEvent);
-    } else {
-      return runNextEvent(null);
-    }
-  }
-
-  return runNextEvent(null);
-}
-
 /// Compares the [actual] output from running pub with [expected]. For [String]
 /// patterns, ignores leading and trailing whitespace differences and tries to
 /// report the offending difference in a nice way. For other [Pattern]s, just
@@ -810,392 +552,6 @@
   }
 }
 
-/// Base class for [FileDescriptor] and [DirectoryDescriptor] so that a
-/// directory can contain a heterogeneous collection of files and
-/// subdirectories.
-abstract class Descriptor {
-  /// The name of this file or directory. This must be a [String] if the file
-  /// or directory is going to be created.
-  final Pattern name;
-
-  Descriptor(this.name);
-
-  /// Creates the file or directory within [dir]. Returns a [Future] that is
-  /// completed after the creation is done.
-  Future create(dir);
-
-  /// Validates that this descriptor correctly matches the corresponding file
-  /// system entry within [dir]. Returns a [Future] that completes to `null` if
-  /// the entry is valid, or throws an error if it failed.
-  Future validate(String dir);
-
-  /// Deletes the file or directory within [dir]. Returns a [Future] that is
-  /// completed after the deletion is done.
-  Future delete(String dir);
-
-  /// Loads the file at [path] from within this descriptor. If [path] is empty,
-  /// loads the contents of the descriptor itself.
-  ByteStream load(List<String> path);
-
-  /// Schedules the directory to be created before Pub is run with
-  /// [schedulePub]. The directory will be created relative to the sandbox
-  /// directory.
-  // TODO(nweiz): Use implicit closurization once issue 2984 is fixed.
-  void scheduleCreate() => _schedule((dir) => this.create(dir));
-
-  /// Schedules the file or directory to be deleted recursively.
-  void scheduleDelete() => _schedule((dir) => this.delete(dir));
-
-  /// Schedules the directory to be validated after Pub is run with
-  /// [schedulePub]. The directory will be validated relative to the sandbox
-  /// directory.
-  void scheduleValidate() => _schedule((parentDir) => validate(parentDir));
-
-  /// Asserts that the name of the descriptor is a [String] and returns it.
-  String get _stringName {
-    if (name is String) return name;
-    throw 'Pattern $name must be a string.';
-  }
-
-  /// Validates that at least one file in [dir] matching [name] is valid
-  /// according to [validate]. [validate] should throw or complete to an
-  /// exception if the input path is invalid.
-  Future _validateOneMatch(String dir, Future validate(String entry)) {
-    // Special-case strings to support multi-level names like "myapp/packages".
-    if (name is String) {
-      var entry = path.join(dir, name);
-      return defer(() {
-        if (!entryExists(entry)) {
-          throw new TestFailure('Entry $entry not found.');
-        }
-        return validate(entry);
-      });
-    }
-
-    // TODO(nweiz): remove this when issue 4061 is fixed.
-    var stackTrace;
-    try {
-      throw "";
-    } catch (_, localStackTrace) {
-      stackTrace = localStackTrace;
-    }
-
-    return listDir(dir).then((files) {
-      var matches = files.where((file) => endsWithPattern(file, name)).toList();
-      if (matches.isEmpty) {
-        throw new TestFailure('No files in $dir match pattern $name.');
-      }
-      if (matches.length == 1) return validate(matches[0]);
-
-      var failures = [];
-      var successes = 0;
-      var completer = new Completer();
-      checkComplete() {
-        if (failures.length + successes != matches.length) return;
-        if (successes > 0) {
-          completer.complete();
-          return;
-        }
-
-        var error = new StringBuffer();
-        error.write("No files named $name in $dir were valid:\n");
-        for (var failure in failures) {
-          error.write("  $failure\n");
-        }
-        completer.completeError(
-            new TestFailure(error.toString()), stackTrace);
-      }
-
-      for (var match in matches) {
-        var future = validate(match).then((_) {
-          successes++;
-          checkComplete();
-        }).catchError((e) {
-          failures.add(e);
-          checkComplete();
-        });
-      }
-      return completer.future;
-    });
-  }
-}
-
-/// Describes a file. These are used both for setting up an expected directory
-/// tree before running a test, and for validating that the file system matches
-/// some expectations after running it.
-class FileDescriptor extends Descriptor {
-  /// The contents of the file, in bytes.
-  final List<int> contents;
-
-  String get textContents => new String.fromCharCodes(contents);
-
-  FileDescriptor.bytes(Pattern name, this.contents) : super(name);
-
-  FileDescriptor(Pattern name, String contents) :
-      this.bytes(name, encodeUtf8(contents));
-
-  /// Creates the file within [dir]. Returns a [Future] that is completed after
-  /// the creation is done.
-  Future<String> create(dir) =>
-      defer(() => writeBinaryFile(path.join(dir, _stringName), contents));
-
-  /// Deletes the file within [dir]. Returns a [Future] that is completed after
-  /// the deletion is done.
-  Future delete(dir) =>
-      defer(() => deleteFile(path.join(dir, _stringName)));
-
-  /// Validates that this file correctly matches the actual file at [path].
-  Future validate(String path) {
-    return _validateOneMatch(path, (file) {
-      var text = readTextFile(file);
-      if (text == textContents) return null;
-
-      throw new TestFailure(
-          'File $file should contain:\n\n$textContents\n\n'
-          'but contained:\n\n$text');
-    });
-  }
-
-  /// Loads the contents of the file.
-  ByteStream load(List<String> path) {
-    if (!path.isEmpty) {
-      throw "Can't load ${path.join('/')} from within $name: not a directory.";
-    }
-
-    return new ByteStream.fromBytes(contents);
-  }
-}
-
-/// Describes a directory and its contents. These are used both for setting up
-/// an expected directory tree before running a test, and for validating that
-/// the file system matches some expectations after running it.
-class DirectoryDescriptor extends Descriptor {
-  /// The files and directories contained in this directory.
-  final List<Descriptor> contents;
-
-  DirectoryDescriptor(Pattern name, List<Descriptor> contents)
-    : this.contents = contents == null ? <Descriptor>[] : contents,
-      super(name);
-
-  /// Creates the file within [dir]. Returns a [Future] that is completed after
-  /// the creation is done.
-  Future<String> create(parentDir) {
-    return defer(() {
-      // Create the directory.
-      var dir = ensureDir(path.join(parentDir, _stringName));
-      if (contents == null) return dir;
-
-      // Recursively create all of its children.
-      var childFutures = contents.map((child) => child.create(dir)).toList();
-      // Only complete once all of the children have been created too.
-      return Future.wait(childFutures).then((_) => dir);
-    });
-  }
-
-  /// Deletes the directory within [dir]. Returns a [Future] that is completed
-  /// after the deletion is done.
-  Future delete(dir) {
-    return deleteDir(path.join(dir, _stringName));
-  }
-
-  /// Validates that the directory at [path] contains all of the expected
-  /// contents in this descriptor. Note that this does *not* check that the
-  /// directory doesn't contain other unexpected stuff, just that it *does*
-  /// contain the stuff we do expect.
-  Future validate(String path) {
-    return _validateOneMatch(path, (dir) {
-      // Validate each of the items in this directory.
-      final entryFutures =
-          contents.map((entry) => entry.validate(dir)).toList();
-
-      // If they are all valid, the directory is valid.
-      return Future.wait(entryFutures).then((entries) => null);
-    });
-  }
-
-  /// Loads [path] from within this directory.
-  ByteStream load(List<String> path) {
-    if (path.isEmpty) {
-      throw "Can't load the contents of $name: is a directory.";
-    }
-
-    for (var descriptor in contents) {
-      if (descriptor.name == path[0]) {
-        return descriptor.load(path.sublist(1));
-      }
-    }
-
-    throw "Directory $name doesn't contain ${path.join('/')}.";
-  }
-}
-
-/// Wraps a [Future] that will complete to a [Descriptor] and makes it behave
-/// like a concrete [Descriptor]. This is necessary when the contents of the
-/// descriptor depends on information that's not available until part of the
-/// test run is completed.
-class FutureDescriptor extends Descriptor {
-  Future<Descriptor> _future;
-
-  FutureDescriptor(this._future) : super('<unknown>');
-
-  Future create(dir) => _future.then((desc) => desc.create(dir));
-
-  Future validate(dir) => _future.then((desc) => desc.validate(dir));
-
-  Future delete(dir) => _future.then((desc) => desc.delete(dir));
-
-  ByteStream load(List<String> path) {
-    var controller = new StreamController<List<int>>();
-    _future.then((desc) => store(desc.load(path), controller));
-    return new ByteStream(controller.stream);
-  }
-}
-
-/// Describes a Git repository and its contents.
-class GitRepoDescriptor extends DirectoryDescriptor {
-  GitRepoDescriptor(Pattern name, List<Descriptor> contents)
-  : super(name, contents);
-
-  /// Creates the Git repository and commits the contents.
-  Future create(parentDir) {
-    return _runGitCommands(parentDir, [
-      ['init'],
-      ['add', '.'],
-      ['commit', '-m', 'initial commit']
-    ]);
-  }
-
-  /// Commits any changes to the Git repository.
-  Future commit(parentDir) {
-    return _runGitCommands(parentDir, [
-      ['add', '.'],
-      ['commit', '-m', 'update']
-    ]);
-  }
-
-  /// Schedules changes to be committed to the Git repository.
-  void scheduleCommit() => _schedule((dir) => this.commit(dir));
-
-  /// Return a Future that completes to the commit in the git repository
-  /// referred to by [ref] at the current point in the scheduled test run.
-  Future<String> revParse(String ref) {
-    return _scheduleValue((parentDir) {
-      return super.create(parentDir).then((rootDir) {
-        return _runGit(['rev-parse', ref], rootDir);
-      }).then((output) => output[0]);
-    });
-  }
-
-  /// Schedule a Git command to run in this repository.
-  void scheduleGit(List<String> args) {
-    _schedule((parentDir) => _runGit(args, path.join(parentDir, name)));
-  }
-
-  Future _runGitCommands(parentDir, List<List<String>> commands) {
-    var workingDir;
-
-    Future runGitStep(_) {
-      if (commands.isEmpty) return new Future.immediate(workingDir);
-      var command = commands.removeAt(0);
-      return _runGit(command, workingDir).then(runGitStep);
-    }
-
-    return super.create(parentDir).then((rootDir) {
-      workingDir = rootDir;
-      return runGitStep(null);
-    });
-  }
-
-  Future<List<String>> _runGit(List<String> args, String workingDir) {
-    // Explicitly specify the committer information. Git needs this to commit
-    // and we don't want to rely on the buildbots having this already set up.
-    var environment = {
-      'GIT_AUTHOR_NAME': 'Pub Test',
-      'GIT_AUTHOR_EMAIL': 'pub@dartlang.org',
-      'GIT_COMMITTER_NAME': 'Pub Test',
-      'GIT_COMMITTER_EMAIL': 'pub@dartlang.org'
-    };
-
-    return gitlib.run(args, workingDir: workingDir, environment: environment);
-  }
-}
-
-/// Describes a gzipped tar file and its contents.
-class TarFileDescriptor extends Descriptor {
-  final List<Descriptor> contents;
-
-  TarFileDescriptor(Pattern name, this.contents)
-  : super(name);
-
-  /// Creates the files and directories within this tar file, then archives
-  /// them, compresses them, and saves the result to [parentDir].
-  Future<String> create(parentDir) {
-    return withTempDir((tempDir) {
-      return Future.wait(contents.map((child) => child.create(tempDir)))
-          .then((createdContents) {
-        return createTarGz(createdContents, baseDir: tempDir).toBytes();
-      }).then((bytes) {
-        var file = path.join(parentDir, _stringName);
-        writeBinaryFile(file, bytes);
-        return file;
-      });
-    });
-  }
-
-  /// Validates that the `.tar.gz` file at [path] contains the expected
-  /// contents.
-  Future validate(String path) {
-    throw "TODO(nweiz): implement this";
-  }
-
-  Future delete(dir) {
-    throw new UnsupportedError('');
-  }
-
-  /// Loads the contents of this tar file.
-  ByteStream load(List<String> path) {
-    if (!path.isEmpty) {
-      throw "Can't load ${path.join('/')} from within $name: not a directory.";
-    }
-
-    var controller = new StreamController<List<int>>();
-    // TODO(nweiz): propagate any errors to the return value. See issue 3657.
-    withTempDir((tempDir) {
-      return create(tempDir).then((tar) {
-        var sourceStream = new File(tar).openRead();
-        return store(sourceStream, controller);
-      });
-    });
-    return new ByteStream(controller.stream);
-  }
-}
-
-/// A descriptor that validates that no file or directory exists with the given
-/// name.
-class NothingDescriptor extends Descriptor {
-  NothingDescriptor(String name) : super(name);
-
-  Future create(dir) => new Future.immediate(null);
-  Future delete(dir) => new Future.immediate(null);
-
-  Future validate(String dir) {
-    return defer(() {
-      if (entryExists(path.join(dir, name))) {
-        throw new TestFailure('Entry $name in $dir should not exist.');
-      }
-    });
-  }
-
-  ByteStream load(List<String> path) {
-    if (path.isEmpty) {
-      throw "Can't load the contents of $name: it doesn't exist.";
-    } else {
-      throw "Can't load ${path.join('/')} from within $name: $name doesn't "
-        "exist.";
-    }
-  }
-}
-
 /// A function that creates a [Validator] subclass.
 typedef Validator ValidatorCreator(Entrypoint entrypoint);
 
@@ -1203,7 +559,7 @@
 /// Future that contains the errors and warnings produced by that validator.
 Future<Pair<List<String>, List<String>>> schedulePackageValidation(
     ValidatorCreator fn) {
-  return _scheduleValue((sandboxDir) {
+  return schedule(() {
     var cache = new SystemCache.withSources(path.join(sandboxDir, cachePath));
 
     return defer(() {
@@ -1212,7 +568,7 @@
         return new Pair(validator.errors, validator.warnings);
       });
     });
-  });
+  }, "validating package");
 }
 
 /// A matcher that matches a Pair.
@@ -1235,406 +591,3 @@
     description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]);
   }
 }
-
-/// The time (in milliseconds) to wait for scheduled events that could run
-/// forever.
-const _SCHEDULE_TIMEOUT = 10000;
-
-/// A class representing a [Process] that is scheduled to run in the course of
-/// the test. This class allows actions on the process to be scheduled
-/// synchronously. All operations on this class are scheduled.
-///
-/// Before running the test, either [shouldExit] or [kill] must be called on
-/// this to ensure that the process terminates when expected.
-///
-/// If the test fails, this will automatically print out any remaining stdout
-/// and stderr from the process to aid debugging.
-class ScheduledProcess {
-  /// The name of the process. Used for error reporting.
-  final String name;
-
-  /// The process future that's scheduled to run.
-  Future<PubProcess> _processFuture;
-
-  /// The process that's scheduled to run. It may be null.
-  PubProcess _process;
-
-  /// The exit code of the scheduled program. It may be null.
-  int _exitCode;
-
-  /// A future that will complete to a list of all the lines emitted on the
-  /// process's standard output stream. This is independent of what data is read
-  /// from [_stdout].
-  Future<List<String>> _stdoutLines;
-
-  /// A [Stream] of stdout lines emitted by the process that's scheduled to run.
-  /// It may be null.
-  Stream<String> _stdout;
-
-  /// A [Future] that will resolve to [_stdout] once it's available.
-  Future get _stdoutFuture => _processFuture.then((_) => _stdout);
-
-  /// A [StreamSubscription] that controls [_stdout].
-  StreamSubscription _stdoutSubscription;
-
-  /// A future that will complete to a list of all the lines emitted on the
-  /// process's standard error stream. This is independent of what data is read
-  /// from [_stderr].
-  Future<List<String>> _stderrLines;
-
-  /// A [Stream] of stderr lines emitted by the process that's scheduled to run.
-  /// It may be null.
-  Stream<String> _stderr;
-
-  /// A [Future] that will resolve to [_stderr] once it's available.
-  Future get _stderrFuture => _processFuture.then((_) => _stderr);
-
-  /// A [StreamSubscription] that controls [_stderr].
-  StreamSubscription _stderrSubscription;
-
-  /// The exit code of the process that's scheduled to run. This will naturally
-  /// only complete once the process has terminated.
-  Future<int> get _exitCodeFuture => _exitCodeCompleter.future;
-
-  /// The completer for [_exitCode].
-  final Completer<int> _exitCodeCompleter = new Completer();
-
-  /// Whether the user has scheduled the end of this process by calling either
-  /// [shouldExit] or [kill].
-  bool _endScheduled = false;
-
-  /// Whether the process is expected to terminate at this point.
-  bool _endExpected = false;
-
-  /// Wraps a [Process] [Future] in a scheduled process.
-  ScheduledProcess(this.name, Future<PubProcess> process)
-    : _processFuture = process {
-    var pairFuture = process.then((p) {
-      _process = p;
-
-      byteStreamToLines(stream) {
-        return streamToLines(new ByteStream(stream.handleError((e) {
-          registerException(e.error, e.stackTrace);
-        })).toStringStream());
-      }
-
-      var stdoutTee = tee(byteStreamToLines(p.stdout));
-      var stdoutPair = streamWithSubscription(stdoutTee.last);
-      _stdout = stdoutPair.first;
-      _stdoutSubscription = stdoutPair.last;
-
-      var stderrTee = tee(byteStreamToLines(p.stderr));
-      var stderrPair = streamWithSubscription(stderrTee.last);
-      _stderr = stderrPair.first;
-      _stderrSubscription = stderrPair.last;
-
-      return new Pair(stdoutTee.first, stderrTee.first);
-    });
-
-    _stdoutLines = pairFuture.then((pair) => pair.first.toList());
-    _stderrLines = pairFuture.then((pair) => pair.last.toList());
-
-    _schedule((_) {
-      if (!_endScheduled) {
-        throw new StateError("Scheduled process $name must have shouldExit() "
-            "or kill() called before the test is run.");
-      }
-
-      process.then((p) => p.exitCode).then((exitCode) {
-        if (_endExpected) {
-          _exitCode = exitCode;
-          _exitCodeCompleter.complete(exitCode);
-          return;
-        }
-
-        // Sleep for half a second in case _endExpected is set in the next
-        // scheduled event.
-        return sleep(500).then((_) {
-          if (_endExpected) {
-            _exitCodeCompleter.complete(exitCode);
-            return;
-          }
-
-          return _printStreams();
-        }).then((_) {
-          registerException(new TestFailure("Process $name ended "
-              "earlier than scheduled with exit code $exitCode"));
-        });
-      }).catchError((e) => registerException(e.error, e.stackTrace));
-    });
-
-    _scheduleOnException((_) {
-      if (_process == null) return;
-
-      if (_exitCode == null) {
-        print("\nKilling process $name prematurely.");
-        _endExpected = true;
-        _process.kill();
-      }
-
-      return _printStreams();
-    });
-
-    _scheduleCleanup((_) {
-      if (_process == null) return;
-      // Ensure that the process is dead and we aren't waiting on any IO.
-      _process.kill();
-      _stdoutSubscription.cancel();
-      _stderrSubscription.cancel();
-    });
-  }
-
-  /// Reads the next line of stdout from the process.
-  Future<String> nextLine() {
-    return _scheduleValue((_) {
-      return timeout(_stdoutFuture.then((stream) => streamFirst(stream)),
-          _SCHEDULE_TIMEOUT,
-          "waiting for the next stdout line from process $name");
-    });
-  }
-
-  /// Reads the next line of stderr from the process.
-  Future<String> nextErrLine() {
-    return _scheduleValue((_) {
-      return timeout(_stderrFuture.then((stream) => streamFirst(stream)),
-          _SCHEDULE_TIMEOUT,
-          "waiting for the next stderr line from process $name");
-    });
-  }
-
-  /// Reads the remaining stdout from the process. This should only be called
-  /// after kill() or shouldExit().
-  Future<String> remainingStdout() {
-    if (!_endScheduled) {
-      throw new StateError("remainingStdout() should only be called after "
-          "kill() or shouldExit().");
-    }
-
-    return _scheduleValue((_) {
-      return timeout(_stdoutFuture.then((stream) => stream.toList())
-              .then((lines) => lines.join("\n")),
-          _SCHEDULE_TIMEOUT,
-          "waiting for the last stdout line from process $name");
-    });
-  }
-
-  /// Reads the remaining stderr from the process. This should only be called
-  /// after kill() or shouldExit().
-  Future<String> remainingStderr() {
-    if (!_endScheduled) {
-      throw new StateError("remainingStderr() should only be called after "
-          "kill() or shouldExit().");
-    }
-
-    return _scheduleValue((_) {
-      return timeout(_stderrFuture.then((stream) => stream.toList())
-              .then((lines) => lines.join("\n")),
-          _SCHEDULE_TIMEOUT,
-          "waiting for the last stderr line from process $name");
-    });
-  }
-
-  /// Writes [line] to the process as stdin.
-  void writeLine(String line) {
-    _schedule((_) => _processFuture.then(
-        (p) => p.stdin.add(encodeUtf8('$line\n'))));
-  }
-
-  /// Kills the process, and waits until it's dead.
-  void kill() {
-    _endScheduled = true;
-    _schedule((_) {
-      _endExpected = true;
-      _process.kill();
-      timeout(_exitCodeFuture, _SCHEDULE_TIMEOUT,
-          "waiting for process $name to die");
-    });
-  }
-
-  /// Waits for the process to exit, and verifies that the exit code matches
-  /// [expectedExitCode] (if given).
-  void shouldExit([int expectedExitCode]) {
-    _endScheduled = true;
-    _schedule((_) {
-      _endExpected = true;
-      return timeout(_exitCodeFuture, _SCHEDULE_TIMEOUT,
-          "waiting for process $name to exit").then((exitCode) {
-        if (expectedExitCode != null) {
-          expect(exitCode, equals(expectedExitCode));
-        }
-      });
-    });
-  }
-
-  /// Prints the remaining data in the process's stdout and stderr streams.
-  /// Prints nothing if the streams are empty.
-  Future _printStreams() {
-    void printStream(String streamName, List<String> lines) {
-      if (lines.isEmpty) return;
-
-      print('\nProcess $name $streamName:');
-      for (var line in lines) {
-        print('| $line');
-      }
-    }
-
-    return _stdoutLines.then((stdoutLines) {
-      printStream('stdout', stdoutLines);
-      return _stderrLines.then((stderrLines) {
-        printStream('stderr', stderrLines);
-      });
-    });
-  }
-}
-
-/// A class representing an [HttpServer] that's scheduled to run in the course
-/// of the test. This class allows the server's request handling to be
-/// scheduled synchronously. All operations on this class are scheduled.
-class ScheduledServer {
-  /// The wrapped server.
-  final Future<HttpServer> _server;
-
-  /// The queue of handlers to run for upcoming requests.
-  final _handlers = new Queue<Future>();
-
-  /// The requests to be ignored.
-  final _ignored = new Set<Pair<String, String>>();
-
-  ScheduledServer._(this._server);
-
-  /// Creates a new server listening on an automatically-allocated port on
-  /// localhost.
-  factory ScheduledServer() {
-    var scheduledServer;
-    scheduledServer = new ScheduledServer._(_scheduleValue((_) {
-      return SafeHttpServer.bind("127.0.0.1", 0).then((server) {
-        server.listen(scheduledServer._awaitHandle);
-        _scheduleCleanup((_) => server.close());
-        return server;
-      });
-    }));
-    return scheduledServer;
-  }
-
-  /// The port on which the server is listening.
-  Future<int> get port => _server.then((s) => s.port);
-
-  /// The base URL of the server, including its port.
-  Future<Uri> get url =>
-    port.then((p) => Uri.parse("http://localhost:$p"));
-
-  /// Assert that the next request has the given [method] and [path], and pass
-  /// it to [handler] to handle. If [handler] returns a [Future], wait until
-  /// it's completed to continue the schedule.
-  void handle(String method, String path,
-      Future handler(HttpRequest request, HttpResponse response)) {
-    var handlerCompleter = new Completer<Function>();
-    _scheduleValue((_) {
-      var requestCompleteCompleter = new Completer();
-      handlerCompleter.complete((request, response) {
-        expect(request.method, equals(method));
-        expect(request.uri.path, equals(path));
-
-        var future = handler(request, response);
-        if (future == null) future = new Future.immediate(null);
-        chainToCompleter(future, requestCompleteCompleter);
-      });
-      return timeout(requestCompleteCompleter.future,
-          _SCHEDULE_TIMEOUT, "waiting for $method $path");
-    });
-    _handlers.add(handlerCompleter.future);
-  }
-
-  /// Ignore all requests with the given [method] and [path]. If one is
-  /// received, don't respond to it.
-  void ignore(String method, String path) =>
-    _ignored.add(new Pair(method, path));
-
-  /// Raises an error complaining of an unexpected request.
-  void _awaitHandle(HttpRequest request) {
-    HttpResponse response = request.response;
-    if (_ignored.contains(new Pair(request.method, request.uri.path))) return;
-    var future = timeout(defer(() {
-      if (_handlers.isEmpty) {
-        fail('Unexpected ${request.method} request to ${request.uri.path}.');
-      }
-      return _handlers.removeFirst();
-    }).then((handler) {
-      handler(request, response);
-    }), _SCHEDULE_TIMEOUT, "waiting for a handler for ${request.method} "
-        "${request.uri.path}");
-    expect(future, completes);
-  }
-}
-
-/// Takes a simple data structure (composed of [Map]s, [List]s, scalar objects,
-/// and [Future]s) and recursively resolves all the [Future]s contained within.
-/// Completes with the fully resolved structure.
-Future _awaitObject(object) {
-  // Unroll nested futures.
-  if (object is Future) return object.then(_awaitObject);
-  if (object is Collection) {
-    return Future.wait(object.map(_awaitObject).toList());
-  }
-  if (object is! Map) return new Future.immediate(object);
-
-  var pairs = <Future<Pair>>[];
-  object.forEach((key, value) {
-    pairs.add(_awaitObject(value)
-        .then((resolved) => new Pair(key, resolved)));
-  });
-  return Future.wait(pairs).then((resolvedPairs) {
-    var map = {};
-    for (var pair in resolvedPairs) {
-      map[pair.first] = pair.last;
-    }
-    return map;
-  });
-}
-
-/// Schedules a callback to be called as part of the test case.
-void _schedule(_ScheduledEvent event) {
-  if (_scheduled == null) _scheduled = new Queue();
-  _scheduled.addLast(event);
-}
-
-/// Like [_schedule], but pipes the return value of [event] to a returned
-/// [Future].
-Future _scheduleValue(_ScheduledEvent event) {
-  var completer = new Completer();
-  _schedule((parentDir) {
-    chainToCompleter(event(parentDir), completer);
-    return completer.future;
-  });
-  return completer.future;
-}
-
-/// Schedules a callback to be called after the test case has completed, even
-/// if it failed.
-void _scheduleCleanup(_ScheduledEvent event) {
-  if (_scheduledCleanup == null) _scheduledCleanup = new Queue();
-  _scheduledCleanup.addLast(event);
-}
-
-/// Schedules a callback to be called after the test case has completed, but
-/// only if it failed.
-void _scheduleOnException(_ScheduledEvent event) {
-  if (_scheduledOnException == null) _scheduledOnException = new Queue();
-  _scheduledOnException.addLast(event);
-}
-
-/// Like [expect], but for [Future]s that complete as part of the scheduled
-/// test. This is necessary to ensure that the exception thrown by the
-/// expectation failing is handled by the scheduler.
-///
-/// Note that [matcher] matches against the completed value of [actual], so
-/// calling [completion] is unnecessary.
-void expectLater(Future actual, matcher, {String reason,
-    FailureHandler failureHandler, bool verbose: false}) {
-  _schedule((_) {
-    return actual.then((value) {
-      expect(value, matcher, reason: reason, failureHandler: failureHandler,
-          verbose: false);
-    });
-  });
-}
diff --git a/utils/tests/pub/update/git/do_not_update_if_unneeded_test.dart b/utils/tests/pub/update/git/do_not_update_if_unneeded_test.dart
index 3f0f909..062e6b4 100644
--- a/utils/tests/pub/update/git/do_not_update_if_unneeded_test.dart
+++ b/utils/tests/pub/update/git/do_not_update_if_unneeded_test.dart
@@ -6,6 +6,7 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
@@ -13,50 +14,50 @@
       "not necessary", () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec("foo", "1.0.0", deps: [{"git": "../foo-dep.git"}])
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec("foo", "1.0.0", deps: [{"git": "../foo-dep.git"}])
+    ]).create();
 
-    git('foo-dep.git', [
-      libDir('foo-dep'),
-      libPubspec('foo-dep', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo-dep.git', [
+      d.libDir('foo-dep'),
+      d.libPubspec('foo-dep', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ]),
-      dir('foo-dep', [
-        file('foo-dep.dart', 'main() => "foo-dep";')
+      d.dir('foo-dep', [
+        d.file('foo-dep.dart', 'main() => "foo-dep";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    git('foo.git', [
-      libDir('foo', 'foo 2'),
-      libPubspec("foo", "1.0.0", deps: [{"git": "../foo-dep.git"}])
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 2'),
+      d.libPubspec("foo", "1.0.0", deps: [{"git": "../foo-dep.git"}])
+    ]).create();
 
-    git('foo-dep.git', [
-      libDir('foo-dep', 'foo-dep 2'),
-      libPubspec('foo-dep', '1.0.0')
-    ]).scheduleCommit();
+    d.git('foo-dep.git', [
+      d.libDir('foo-dep', 'foo-dep 2'),
+      d.libPubspec('foo-dep', '1.0.0')
+    ]).commit();
 
     schedulePub(args: ['update', 'foo'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 2";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 2";')
       ]),
-      dir('foo-dep', [
-        file('foo-dep.dart', 'main() => "foo-dep";')
+      d.dir('foo-dep', [
+        d.file('foo-dep.dart', 'main() => "foo-dep";')
       ]),
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/update/git/update_locked_test.dart b/utils/tests/pub/update/git/update_locked_test.dart
index 1fd9718..300f531 100644
--- a/utils/tests/pub/update/git/update_locked_test.dart
+++ b/utils/tests/pub/update/git/update_locked_test.dart
@@ -6,56 +6,57 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("updates locked Git packages", () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
+    ]).create();
 
-    git('bar.git', [
-      libDir('bar'),
-      libPubspec('bar', '1.0.0')
-    ]).scheduleCreate();
+    d.git('bar.git', [
+      d.libDir('bar'),
+      d.libPubspec('bar', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}, {"git": "../bar.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}, {"git": "../bar.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ]),
-      dir('bar', [
-        file('bar.dart', 'main() => "bar";')
+      d.dir('bar', [
+        d.file('bar.dart', 'main() => "bar";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    git('foo.git', [
-      libDir('foo', 'foo 2'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCommit();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 2'),
+      d.libPubspec('foo', '1.0.0')
+    ]).commit();
 
-    git('bar.git', [
-      libDir('bar', 'bar 2'),
-      libPubspec('bar', '1.0.0')
-    ]).scheduleCommit();
+    d.git('bar.git', [
+      d.libDir('bar', 'bar 2'),
+      d.libPubspec('bar', '1.0.0')
+    ]).commit();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 2";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 2";')
       ]),
-      dir('bar', [
-        file('bar.dart', 'main() => "bar 2";')
+      d.dir('bar', [
+        d.file('bar.dart', 'main() => "bar 2";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/update/git/update_one_locked_test.dart b/utils/tests/pub/update/git/update_one_locked_test.dart
index 3c06726..21d239f 100644
--- a/utils/tests/pub/update/git/update_one_locked_test.dart
+++ b/utils/tests/pub/update/git/update_one_locked_test.dart
@@ -6,56 +6,57 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("updates one locked Git package but no others", () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
+    ]).create();
 
-    git('bar.git', [
-      libDir('bar'),
-      libPubspec('bar', '1.0.0')
-    ]).scheduleCreate();
+    d.git('bar.git', [
+      d.libDir('bar'),
+      d.libPubspec('bar', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}, {"git": "../bar.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}, {"git": "../bar.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ]),
-      dir('bar', [
-        file('bar.dart', 'main() => "bar";')
+      d.dir('bar', [
+        d.file('bar.dart', 'main() => "bar";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    git('foo.git', [
-      libDir('foo', 'foo 2'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCommit();
+    d.git('foo.git', [
+      d.libDir('foo', 'foo 2'),
+      d.libPubspec('foo', '1.0.0')
+    ]).commit();
 
-    git('bar.git', [
-      libDir('bar', 'bar 2'),
-      libPubspec('bar', '1.0.0')
-    ]).scheduleCommit();
+    d.git('bar.git', [
+      d.libDir('bar', 'bar 2'),
+      d.libPubspec('bar', '1.0.0')
+    ]).commit();
 
     schedulePub(args: ['update', 'foo'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo 2";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo 2";')
       ]),
-      dir('bar', [
-        file('bar.dart', 'main() => "bar";')
+      d.dir('bar', [
+        d.file('bar.dart', 'main() => "bar";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/update/git/update_to_incompatible_pubspec_test.dart b/utils/tests/pub/update/git/update_to_incompatible_pubspec_test.dart
index aa4ef46..67d7ec2 100644
--- a/utils/tests/pub/update/git/update_to_incompatible_pubspec_test.dart
+++ b/utils/tests/pub/update/git/update_to_incompatible_pubspec_test.dart
@@ -6,42 +6,43 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("updates Git packages to an incompatible pubspec", () {
     ensureGit();
 
-    git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
-    ]).scheduleCreate();
+    d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
+    ]).create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    git('foo.git', [
-      libDir('zoo'),
-      libPubspec('zoo', '1.0.0')
-    ]).scheduleCommit();
+    d.git('foo.git', [
+      d.libDir('zoo'),
+      d.libPubspec('zoo', '1.0.0')
+    ]).commit();
 
     schedulePub(args: ['update'],
         error: new RegExp(r'The name you specified for your dependency, '
             r'"foo", doesn' "'" r't match the name "zoo" in its pubspec.'),
         exitCode: 1);
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/update/git/update_to_nonexistent_pubspec_test.dart b/utils/tests/pub/update/git/update_to_nonexistent_pubspec_test.dart
index 21951ab..c4bf53d 100644
--- a/utils/tests/pub/update/git/update_to_nonexistent_pubspec_test.dart
+++ b/utils/tests/pub/update/git/update_to_nonexistent_pubspec_test.dart
@@ -6,41 +6,42 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("updates Git packages to a nonexistent pubspec", () {
     ensureGit();
 
-    var repo = git('foo.git', [
-      libDir('foo'),
-      libPubspec('foo', '1.0.0')
+    var repo = d.git('foo.git', [
+      d.libDir('foo'),
+      d.libPubspec('foo', '1.0.0')
     ]);
-    repo.scheduleCreate();
+    repo.create();
 
-    appDir([{"git": "../foo.git"}]).scheduleCreate();
+    d.appDir([{"git": "../foo.git"}]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
 
-    repo.scheduleGit(['rm', 'pubspec.yaml']);
-    repo.scheduleGit(['commit', '-m', 'delete']);
+    repo.runGit(['rm', 'pubspec.yaml']);
+    repo.runGit(['commit', '-m', 'delete']);
 
     schedulePub(args: ['update'],
         error: new RegExp(r'Package "foo" doesn' "'" r't have a '
             r'pubspec.yaml file.'),
         exitCode: 1);
 
-    dir(packagesPath, [
-      dir('foo', [
-        file('foo.dart', 'main() => "foo";')
+    d.dir(packagesPath, [
+      d.dir('foo', [
+        d.file('foo.dart', 'main() => "foo";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 }
diff --git a/utils/tests/pub/update/hosted/fail_gracefully_on_missing_package_test.dart b/utils/tests/pub/update/hosted/fail_gracefully_on_missing_package_test.dart
index 6bbb45c..8de4886 100644
--- a/utils/tests/pub/update/hosted/fail_gracefully_on_missing_package_test.dart
+++ b/utils/tests/pub/update/hosted/fail_gracefully_on_missing_package_test.dart
@@ -6,13 +6,14 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('fails gracefully if the package does not exist', () {
     servePackages([]);
 
-    appDir([dependency("foo", "1.2.3")]).scheduleCreate();
+    d.appDir([dependencyMap("foo", "1.2.3")]).create();
 
     schedulePub(args: ['update'],
         error: new RegExp('Could not find package "foo" at '
diff --git a/utils/tests/pub/update/hosted/fail_gracefully_on_url_resolve_test.dart b/utils/tests/pub/update/hosted/fail_gracefully_on_url_resolve_test.dart
index d7f8cbd..fbf9043 100644
--- a/utils/tests/pub/update/hosted/fail_gracefully_on_url_resolve_test.dart
+++ b/utils/tests/pub/update/hosted/fail_gracefully_on_url_resolve_test.dart
@@ -6,12 +6,13 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration('fails gracefully if the url does not resolve', () {
-    dir(appPath, [
-      pubspec({
+    d.dir(appPath, [
+      d.pubspec({
         "name": "myapp",
         "dependencies": {
           "foo": {
@@ -22,7 +23,7 @@
           }
          }
       })
-    ]).scheduleCreate();
+    ]).create();
 
     schedulePub(args: ['update'],
         error: new RegExp('Could not resolve URL "http://pub.invalid".'),
diff --git a/utils/tests/pub/update/hosted/remove_removed_dependency_test.dart b/utils/tests/pub/update/hosted/remove_removed_dependency_test.dart
index e39c184..4841a97 100644
--- a/utils/tests/pub/update/hosted/remove_removed_dependency_test.dart
+++ b/utils/tests/pub/update/hosted/remove_removed_dependency_test.dart
@@ -6,33 +6,34 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("removes a dependency that's been removed from the pubspec", () {
     servePackages([
-      package("foo", "1.0.0"),
-      package("bar", "1.0.0")
+      packageMap("foo", "1.0.0"),
+      packageMap("bar", "1.0.0")
     ]);
 
-    appDir([dependency("foo"), dependency("bar")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": null
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/update/hosted/remove_removed_transitive_dependency_test.dart b/utils/tests/pub/update/hosted/remove_removed_transitive_dependency_test.dart
index fa54439..4a4658c 100644
--- a/utils/tests/pub/update/hosted/remove_removed_transitive_dependency_test.dart
+++ b/utils/tests/pub/update/hosted/remove_removed_transitive_dependency_test.dart
@@ -6,43 +6,44 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("removes a transitive dependency that's no longer depended "
       "on", () {
     servePackages([
-      package("foo", "1.0.0", [dependency("shared-dep")]),
-      package("bar", "1.0.0", [
-        dependency("shared-dep"),
-        dependency("bar-dep")
+      packageMap("foo", "1.0.0", [dependencyMap("shared-dep")]),
+      packageMap("bar", "1.0.0", [
+        dependencyMap("shared-dep"),
+        dependencyMap("bar-dep")
       ]),
-      package("shared-dep", "1.0.0"),
-      package("bar-dep", "1.0.0")
+      packageMap("shared-dep", "1.0.0"),
+      packageMap("bar-dep", "1.0.0")
     ]);
 
-    appDir([dependency("foo"), dependency("bar")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0",
       "shared-dep": "1.0.0",
       "bar-dep": "1.0.0",
-    }).scheduleValidate();
+    }).validate();
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": null,
       "shared-dep": "1.0.0",
       "bar-dep": null,
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/update/hosted/unlock_dependers_test.dart b/utils/tests/pub/update/hosted/unlock_dependers_test.dart
index b1436e9..2c3b728 100644
--- a/utils/tests/pub/update/hosted/unlock_dependers_test.dart
+++ b/utils/tests/pub/update/hosted/unlock_dependers_test.dart
@@ -6,37 +6,38 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("updates a locked package's dependers in order to get it to max "
       "version", () {
     servePackages([
-      package("foo", "1.0.0", [dependency("bar", "<2.0.0")]),
-      package("bar", "1.0.0")
+      packageMap("foo", "1.0.0", [dependencyMap("bar", "<2.0.0")]),
+      packageMap("bar", "1.0.0")
     ]);
 
-    appDir([dependency("foo"), dependency("bar")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
 
     servePackages([
-      package("foo", "2.0.0", [dependency("bar", "<3.0.0")]),
-      package("bar", "2.0.0")
+      packageMap("foo", "2.0.0", [dependencyMap("bar", "<3.0.0")]),
+      packageMap("bar", "2.0.0")
     ]);
 
     schedulePub(args: ['update', 'bar'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "2.0.0",
       "bar": "2.0.0"
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/update/hosted/unlock_if_necessary_test.dart b/utils/tests/pub/update/hosted/unlock_if_necessary_test.dart
index 1c1b95d..ca7355b 100644
--- a/utils/tests/pub/update/hosted/unlock_if_necessary_test.dart
+++ b/utils/tests/pub/update/hosted/unlock_if_necessary_test.dart
@@ -6,37 +6,38 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("updates one locked pub server package's dependencies if it's "
       "necessary", () {
     servePackages([
-      package("foo", "1.0.0", [dependency("foo-dep")]),
-      package("foo-dep", "1.0.0")
+      packageMap("foo", "1.0.0", [dependencyMap("foo-dep")]),
+      packageMap("foo-dep", "1.0.0")
     ]);
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['install'],
         output: new RegExp(r"Dependencies installed!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "foo-dep": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
 
     servePackages([
-      package("foo", "2.0.0", [dependency("foo-dep", ">1.0.0")]),
-      package("foo-dep", "2.0.0")
+      packageMap("foo", "2.0.0", [dependencyMap("foo-dep", ">1.0.0")]),
+      packageMap("foo-dep", "2.0.0")
     ]);
 
     schedulePub(args: ['update', 'foo'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "2.0.0",
       "foo-dep": "2.0.0"
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/update/hosted/update_removed_constraints_test.dart b/utils/tests/pub/update/hosted/update_removed_constraints_test.dart
index 06dadff..7bd3965 100644
--- a/utils/tests/pub/update/hosted/update_removed_constraints_test.dart
+++ b/utils/tests/pub/update/hosted/update_removed_constraints_test.dart
@@ -6,37 +6,38 @@
 
 import 'dart:io';
 
+import '../../descriptor.dart' as d;
 import '../../test_pub.dart';
 
 main() {
   integration("updates dependencies whose constraints have been removed", () {
     servePackages([
-      package("foo", "1.0.0", [dependency("shared-dep")]),
-      package("bar", "1.0.0", [dependency("shared-dep", "<2.0.0")]),
-      package("shared-dep", "1.0.0"),
-      package("shared-dep", "2.0.0")
+      packageMap("foo", "1.0.0", [dependencyMap("shared-dep")]),
+      packageMap("bar", "1.0.0", [dependencyMap("shared-dep", "<2.0.0")]),
+      packageMap("shared-dep", "1.0.0"),
+      packageMap("shared-dep", "2.0.0")
     ]);
 
-    appDir([dependency("foo"), dependency("bar")]).scheduleCreate();
+    d.appDir([dependencyMap("foo"), dependencyMap("bar")]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": "1.0.0",
       "shared-dep": "1.0.0"
-    }).scheduleValidate();
+    }).validate();
 
-    appDir([dependency("foo")]).scheduleCreate();
+    d.appDir([dependencyMap("foo")]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({
+    d.packagesDir({
       "foo": "1.0.0",
       "bar": null,
       "shared-dep": "2.0.0"
-    }).scheduleValidate();
+    }).validate();
   });
 }
diff --git a/utils/tests/pub/update/pub_update_test.dart b/utils/tests/pub/update/pub_update_test.dart
index a32b636..997f145 100644
--- a/utils/tests/pub/update/pub_update_test.dart
+++ b/utils/tests/pub/update/pub_update_test.dart
@@ -6,14 +6,16 @@
 
 import 'dart:io';
 
-import '../../../../pkg/unittest/lib/unittest.dart';
+import '../../../../pkg/scheduled_test/lib/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
 import '../test_pub.dart';
 
 main() {
   initConfig();
   group('requires', () {
     integration('a pubspec', () {
-      dir(appPath, []).scheduleCreate();
+      d.dir(appPath, []).create();
 
       schedulePub(args: ['update'],
           error: new RegExp(r'^Could not find a file named "pubspec.yaml"'),
@@ -21,9 +23,9 @@
     });
 
     integration('a pubspec with a "name" key', () {
-      dir(appPath, [
-        pubspec({"dependencies": {"foo": null}})
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.pubspec({"dependencies": {"foo": null}})
+      ]).create();
 
       schedulePub(args: ['update'],
           error: new RegExp(r'^pubspec.yaml is missing the required "name" '
@@ -35,51 +37,51 @@
   integration('adds itself to the packages', () {
     // The symlink should use the name in the pubspec, not the name of the
     // directory.
-    dir(appPath, [
-      pubspec({"name": "myapp_name"}),
-      libDir('myapp_name')
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.pubspec({"name": "myapp_name"}),
+      d.libDir('myapp_name')
+    ]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    dir(packagesPath, [
-      dir("myapp_name", [
-        file('myapp_name.dart', 'main() => "myapp_name";')
+    d.dir(packagesPath, [
+      d.dir("myapp_name", [
+        d.file('myapp_name.dart', 'main() => "myapp_name";')
       ])
-    ]).scheduleValidate();
+    ]).validate();
   });
 
   integration('does not adds itself to the packages if it has no "lib" '
       'directory', () {
     // The symlink should use the name in the pubspec, not the name of the
     // directory.
-    dir(appPath, [
-      pubspec({"name": "myapp_name"}),
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.pubspec({"name": "myapp_name"}),
+    ]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    dir(packagesPath, [
-      nothing("myapp_name")
-    ]).scheduleValidate();
+    d.dir(packagesPath, [
+      d.nothing("myapp_name")
+    ]).validate();
   });
 
   integration('does not add a package if it does not have a "lib" '
       'directory', () {
     // Using a path source, but this should be true of all sources.
-    dir('foo', [
-      libPubspec('foo', '0.0.0-not.used')
-    ]).scheduleCreate();
+    d.dir('foo', [
+      d.libPubspec('foo', '0.0.0-not.used')
+    ]).create();
 
-    dir(appPath, [
-      pubspec({"name": "myapp", "dependencies": {"foo": {"path": "../foo"}}})
-    ]).scheduleCreate();
+    d.dir(appPath, [
+      d.pubspec({"name": "myapp", "dependencies": {"foo": {"path": "../foo"}}})
+    ]).create();
 
     schedulePub(args: ['update'],
         output: new RegExp(r"Dependencies updated!$"));
 
-    packagesDir({"foo": null}).scheduleValidate();
+    d.packagesDir({"foo": null}).validate();
   });
 }
diff --git a/utils/tests/pub/validator_test.dart b/utils/tests/pub/validator_test.dart
index 2c36945..12dbd82 100644
--- a/utils/tests/pub/validator_test.dart
+++ b/utils/tests/pub/validator_test.dart
@@ -12,9 +12,8 @@
 import '../../../pkg/http/lib/http.dart' as http;
 import '../../../pkg/http/lib/testing.dart';
 import '../../../pkg/pathos/lib/path.dart' as path;
-import '../../../pkg/unittest/lib/unittest.dart';
+import '../../../pkg/scheduled_test/lib/scheduled_test.dart';
 
-import 'test_pub.dart';
 import '../../pub/entrypoint.dart';
 import '../../pub/io.dart';
 import '../../pub/validator.dart';
@@ -27,27 +26,31 @@
 import '../../pub/validator/pubspec_field.dart';
 import '../../pub/validator/size.dart';
 import '../../pub/validator/utf8_readme.dart';
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
 
 void expectNoValidationError(ValidatorCreator fn) {
-  expectLater(schedulePackageValidation(fn), pairOf(isEmpty, isEmpty));
+  expect(schedulePackageValidation(fn), completion(pairOf(isEmpty, isEmpty)));
 }
 
 void expectValidationError(ValidatorCreator fn) {
-  expectLater(schedulePackageValidation(fn), pairOf(isNot(isEmpty), anything));
+  expect(schedulePackageValidation(fn),
+      completion(pairOf(isNot(isEmpty), anything)));
 }
 
 void expectValidationWarning(ValidatorCreator fn) {
-  expectLater(schedulePackageValidation(fn), pairOf(isEmpty, isNot(isEmpty)));
+  expect(schedulePackageValidation(fn),
+      completion(pairOf(isEmpty, isNot(isEmpty))));
 }
 
 expectDependencyValidationError(String error) {
-  expectLater(schedulePackageValidation(dependency),
-      pairOf(someElement(contains(error)), isEmpty));
+  expect(schedulePackageValidation(dependency),
+      completion(pairOf(someElement(contains(error)), isEmpty)));
 }
 
 expectDependencyValidationWarning(String warning) {
-  expectLater(schedulePackageValidation(dependency),
-      pairOf(isEmpty, someElement(contains(warning))));
+  expect(schedulePackageValidation(dependency),
+      completion(pairOf(isEmpty, someElement(contains(warning)))));
 }
 
 Validator compiledDartdoc(Entrypoint entrypoint) =>
@@ -76,7 +79,9 @@
 Validator utf8Readme(Entrypoint entrypoint) =>
   new Utf8ReadmeValidator(entrypoint);
 
-void scheduleNormalPackage() => normalPackage.scheduleCreate();
+void scheduleNormalPackage() {
+  d.validPackage.create();
+}
 
 /// Sets up a test package with dependency [dep] and mocks a server with
 /// [hostedVersions] of the package available.
@@ -96,9 +101,9 @@
     }
   }));
 
-  dir(appPath, [
-    libPubspec("test_pkg", "1.0.0", deps: [dep])
-  ]).scheduleCreate();
+  d.dir(appPath, [
+    d.libPubspec("test_pkg", "1.0.0", deps: [dep])
+  ]).create();
 }
 
 main() {
@@ -107,7 +112,7 @@
     setUp(scheduleNormalPackage);
 
     integration('looks normal', () {
-      dir(appPath, [libPubspec("test_pkg", "1.0.0")]).scheduleCreate();
+      d.dir(appPath, [d.libPubspec("test_pkg", "1.0.0")]).create();
       expectNoValidationError(dependency);
       expectNoValidationError(lib);
       expectNoValidationError(license);
@@ -116,55 +121,55 @@
     });
 
     integration('has a COPYING file', () {
-      file(path.join(appPath, 'LICENSE'), '').scheduleDelete();
-      file(path.join(appPath, 'COPYING'), '').scheduleCreate();
+      schedule(() => deleteFile(path.join(sandboxDir, appPath, 'LICENSE')));
+      d.file(path.join(appPath, 'COPYING'), '').create();
       expectNoValidationError(license);
     });
 
     integration('has a prefixed LICENSE file', () {
-      file(path.join(appPath, 'LICENSE'), '').scheduleDelete();
-      file(path.join(appPath, 'MIT_LICENSE'), '').scheduleCreate();
+      schedule(() => deleteFile(path.join(sandboxDir, appPath, 'LICENSE')));
+      d.file(path.join(appPath, 'MIT_LICENSE'), '').create();
       expectNoValidationError(license);
     });
 
     integration('has a suffixed LICENSE file', () {
-      file(path.join(appPath, 'LICENSE'), '').scheduleDelete();
-      file(path.join(appPath, 'LICENSE.md'), '').scheduleCreate();
+      schedule(() => deleteFile(path.join(sandboxDir, appPath, 'LICENSE')));
+      d.file(path.join(appPath, 'LICENSE.md'), '').create();
       expectNoValidationError(license);
     });
 
     integration('has "authors" instead of "author"', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg["authors"] = [pkg.remove("author")];
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
       expectNoValidationError(pubspecField);
     });
 
     integration('has a badly-named library in lib/src', () {
-      dir(appPath, [
-        libPubspec("test_pkg", "1.0.0"),
-        dir("lib", [
-          file("test_pkg.dart", "int i = 1;"),
-          dir("src", [file("8ball.dart", "int j = 2;")])
+      d.dir(appPath, [
+        d.libPubspec("test_pkg", "1.0.0"),
+        d.dir("lib", [
+          d.file("test_pkg.dart", "int i = 1;"),
+          d.dir("src", [d.file("8ball.dart", "int j = 2;")])
         ])
-      ]).scheduleCreate();
+      ]).create();
       expectNoValidationError(name);
     });
 
     integration('has a non-Dart file in lib', () {
-      dir(appPath, [
-        libPubspec("test_pkg", "1.0.0"),
-        dir("lib", [
-          file("thing.txt", "woo hoo")
+      d.dir(appPath, [
+        d.libPubspec("test_pkg", "1.0.0"),
+        d.dir("lib", [
+          d.file("thing.txt", "woo hoo")
         ])
-      ]).scheduleCreate();
+      ]).create();
       expectNoValidationError(lib);
     });
 
     integration('has a nested directory named "tools"', () {
-      dir(appPath, [
-        dir("foo", [dir("tools")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.dir("foo", [d.dir("tools")])
+      ]).create();
       expectNoValidationError(directory);
     });
 
@@ -174,22 +179,22 @@
     });
 
     integration('has most but not all files from compiling dartdoc', () {
-      dir(appPath, [
-        dir("doc-out", [
-          file("nav.json", ""),
-          file("index.html", ""),
-          file("styles.css", ""),
-          file("dart-logo-small.png", "")
+      d.dir(appPath, [
+        d.dir("doc-out", [
+          d.file("nav.json", ""),
+          d.file("index.html", ""),
+          d.file("styles.css", ""),
+          d.file("dart-logo-small.png", "")
         ])
-      ]).scheduleCreate();
+      ]).create();
       expectNoValidationError(compiledDartdoc);
     });
 
     integration('has a non-primary readme with invalid utf-8', () {
-      dir(appPath, [
-        file("README", "Valid utf-8"),
-        binaryFile("README.invalid", [192])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.file("README", "Valid utf-8"),
+        d.binaryFile("README.invalid", [192])
+      ]).create();
       expectNoValidationError(utf8Readme);
     });
   });
@@ -198,158 +203,161 @@
     setUp(scheduleNormalPackage);
 
     integration('is missing the "homepage" field', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg.remove("homepage");
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       expectValidationError(pubspecField);
     });
 
     integration('is missing the "description" field', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg.remove("description");
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       expectValidationError(pubspecField);
     });
 
     integration('is missing the "author" field', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg.remove("author");
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       expectValidationError(pubspecField);
     });
 
     integration('has a single author without an email', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg["author"] = "Nathan Weizenbaum";
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       expectValidationWarning(pubspecField);
     });
 
     integration('has one of several authors without an email', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg.remove("author");
       pkg["authors"] = [
         "Bob Nystrom <rnystrom@google.com>",
         "Nathan Weizenbaum",
         "John Messerly <jmesserly@google.com>"
       ];
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       expectValidationWarning(pubspecField);
     });
 
     integration('has a single author without a name', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg["author"] = "<nweiz@google.com>";
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       expectValidationWarning(pubspecField);
     });
 
     integration('has one of several authors without a name', () {
-      var pkg = package("test_pkg", "1.0.0");
+      var pkg = packageMap("test_pkg", "1.0.0");
       pkg.remove("author");
       pkg["authors"] = [
         "Bob Nystrom <rnystrom@google.com>",
         "<nweiz@google.com>",
         "John Messerly <jmesserly@google.com>"
       ];
-      dir(appPath, [pubspec(pkg)]).scheduleCreate();
+      d.dir(appPath, [d.pubspec(pkg)]).create();
 
       expectValidationWarning(pubspecField);
     });
 
     integration('has no LICENSE file', () {
-      file(path.join(appPath, 'LICENSE'), '').scheduleDelete();
+      schedule(() => deleteFile(path.join(sandboxDir, appPath, 'LICENSE')));
       expectValidationError(license);
     });
 
     integration('has an empty package name', () {
-      dir(appPath, [libPubspec("", "1.0.0")]).scheduleCreate();
+      d.dir(appPath, [d.libPubspec("", "1.0.0")]).create();
       expectValidationError(name);
     });
 
     integration('has a package name with an invalid character', () {
-      dir(appPath, [libPubspec("test-pkg", "1.0.0")]).scheduleCreate();
+      d.dir(appPath, [d.libPubspec("test-pkg", "1.0.0")]).create();
       expectValidationError(name);
     });
 
     integration('has a package name that begins with a number', () {
-      dir(appPath, [libPubspec("8ball", "1.0.0")]).scheduleCreate();
+      d.dir(appPath, [d.libPubspec("8ball", "1.0.0")]).create();
       expectValidationError(name);
     });
 
     integration('has a package name that contains upper-case letters', () {
-      dir(appPath, [libPubspec("TestPkg", "1.0.0")]).scheduleCreate();
+      d.dir(appPath, [d.libPubspec("TestPkg", "1.0.0")]).create();
       expectValidationWarning(name);
     });
 
     integration('has a package name that is a Dart reserved word', () {
-      dir(appPath, [libPubspec("final", "1.0.0")]).scheduleCreate();
+      d.dir(appPath, [d.libPubspec("final", "1.0.0")]).create();
       expectValidationError(name);
     });
 
     integration('has a library name with an invalid character', () {
-      dir(appPath, [
-        libPubspec("test_pkg", "1.0.0"),
-        dir("lib", [file("test-pkg.dart", "int i = 0;")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.libPubspec("test_pkg", "1.0.0"),
+        d.dir("lib", [d.file("test-pkg.dart", "int i = 0;")])
+      ]).create();
       expectValidationWarning(name);
     });
 
     integration('has a library name that begins with a number', () {
-      dir(appPath, [
-        libPubspec("test_pkg", "1.0.0"),
-        dir("lib", [file("8ball.dart", "int i = 0;")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.libPubspec("test_pkg", "1.0.0"),
+        d.dir("lib", [d.file("8ball.dart", "int i = 0;")])
+      ]).create();
       expectValidationWarning(name);
     });
 
     integration('has a library name that contains upper-case letters', () {
-      dir(appPath, [
-        libPubspec("test_pkg", "1.0.0"),
-        dir("lib", [file("TestPkg.dart", "int i = 0;")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.libPubspec("test_pkg", "1.0.0"),
+        d.dir("lib", [d.file("TestPkg.dart", "int i = 0;")])
+      ]).create();
       expectValidationWarning(name);
     });
 
     integration('has a library name that is a Dart reserved word', () {
-      dir(appPath, [
-        libPubspec("test_pkg", "1.0.0"),
-        dir("lib", [file("for.dart", "int i = 0;")])
-      ]).scheduleCreate();
+      d.dir(appPath, [
+        d.libPubspec("test_pkg", "1.0.0"),
+        d.dir("lib", [d.file("for.dart", "int i = 0;")])
+      ]).create();
       expectValidationWarning(name);
     });
 
     integration('has a single library named differently than the package', () {
-      file(path.join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete();
-      dir(appPath, [
-        dir("lib", [file("best_pkg.dart", "int i = 0;")])
-      ]).scheduleCreate();
+      schedule(() =>
+          deleteFile(path.join(sandboxDir, appPath, "lib", "test_pkg.dart")));
+      d.dir(appPath, [
+        d.dir("lib", [d.file("best_pkg.dart", "int i = 0;")])
+      ]).create();
       expectValidationWarning(name);
     });
 
     integration('has no lib directory', () {
-      dir(path.join(appPath, "lib")).scheduleDelete();
+      schedule(() => deleteDir(path.join(sandboxDir, appPath, "lib")));
       expectValidationError(lib);
     });
 
     integration('has an empty lib directory', () {
-      file(path.join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete();
+      schedule(() =>
+          deleteFile(path.join(sandboxDir, appPath, "lib", "test_pkg.dart")));
       expectValidationError(lib);
     });
 
     integration('has a lib directory containing only src', () {
-      file(path.join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete();
-      dir(appPath, [
-        dir("lib", [
-          dir("src", [file("test_pkg.dart", "int i = 0;")])
+      schedule(() =>
+          deleteFile(path.join(sandboxDir, appPath, "lib", "test_pkg.dart")));
+      d.dir(appPath, [
+        d.dir("lib", [
+          d.dir("src", [d.file("test_pkg.dart", "int i = 0;")])
         ])
-      ]).scheduleCreate();
+      ]).create();
       expectValidationError(lib);
     });
 
@@ -442,23 +450,23 @@
     group('has an unconstrained dependency', () {
       group('and it should not suggest a version', () {
         integration("if there's no lockfile", () {
-          dir(appPath, [
-            libPubspec("test_pkg", "1.0.0", deps: [
+          d.dir(appPath, [
+            d.libPubspec("test_pkg", "1.0.0", deps: [
               {'hosted': 'foo'}
             ])
-          ]).scheduleCreate();
+          ]).create();
 
-          expectLater(schedulePackageValidation(dependency),
-              pairOf(isEmpty, everyElement(isNot(contains("\n  foo:")))));
+          expect(schedulePackageValidation(dependency), completion(
+              pairOf(isEmpty, everyElement(isNot(contains("\n  foo:"))))));
         });
 
         integration("if the lockfile doesn't have an entry for the "
             "dependency", () {
-          dir(appPath, [
-            libPubspec("test_pkg", "1.0.0", deps: [
+          d.dir(appPath, [
+            d.libPubspec("test_pkg", "1.0.0", deps: [
               {'hosted': 'foo'}
             ]),
-            file("pubspec.lock", json.stringify({
+            d.file("pubspec.lock", json.stringify({
               'packages': {
                 'bar': {
                   'version': '1.2.3',
@@ -470,21 +478,21 @@
                 }
               }
             }))
-          ]).scheduleCreate();
+          ]).create();
 
-          expectLater(schedulePackageValidation(dependency),
-              pairOf(isEmpty, everyElement(isNot(contains("\n  foo:")))));
+          expect(schedulePackageValidation(dependency), completion(
+              pairOf(isEmpty, everyElement(isNot(contains("\n  foo:"))))));
         });
       });
 
       group('with a lockfile', () {
         integration('and it should suggest a constraint based on the locked '
             'version', () {
-          dir(appPath, [
-            libPubspec("test_pkg", "1.0.0", deps: [
+          d.dir(appPath, [
+            d.libPubspec("test_pkg", "1.0.0", deps: [
               {'hosted': 'foo'}
             ]),
-            file("pubspec.lock", json.stringify({
+            d.file("pubspec.lock", json.stringify({
               'packages': {
                 'foo': {
                   'version': '1.2.3',
@@ -496,18 +504,18 @@
                 }
               }
             }))
-          ]).scheduleCreate();
+          ]).create();
 
           expectDependencyValidationWarning('  foo: ">=1.2.3 <2.0.0"');
         });
 
         integration('and it should suggest a concrete constraint if the locked '
             'version is pre-1.0.0', () {
-          dir(appPath, [
-            libPubspec("test_pkg", "1.0.0", deps: [
+          d.dir(appPath, [
+            d.libPubspec("test_pkg", "1.0.0", deps: [
               {'hosted': 'foo'}
             ]),
-            file("pubspec.lock", json.stringify({
+            d.file("pubspec.lock", json.stringify({
               'packages': {
                 'foo': {
                   'version': '0.1.2',
@@ -519,7 +527,7 @@
                 }
               }
             }))
-          ]).scheduleCreate();
+          ]).create();
 
           expectDependencyValidationWarning('  foo: ">=0.1.2 <0.1.3"');
         });
@@ -527,11 +535,11 @@
     });
 
     integration('has a hosted dependency on itself', () {
-      dir(appPath, [
-        libPubspec("test_pkg", "1.0.0", deps: [
+      d.dir(appPath, [
+        d.libPubspec("test_pkg", "1.0.0", deps: [
           {'hosted': {'name': 'test_pkg', 'version': '>=1.0.0'}}
         ])
-      ]).scheduleCreate();
+      ]).create();
 
       expectValidationWarning(dependency);
     });
@@ -542,7 +550,7 @@
       var names = ["tools", "tests", "docs", "examples", "sample", "samples"];
       for (var name in names) {
         integration('"$name"', () {
-          dir(appPath, [dir(name)]).scheduleCreate();
+          d.dir(appPath, [d.dir(name)]).create();
           expectValidationWarning(directory);
         });
       }
@@ -552,24 +560,24 @@
       expectValidationError(size(10 * math.pow(2, 20) + 1));
     });
 
-    test('contains compiled dartdoc', () {
-      dir(appPath, [
-        dir('doc-out', [
-          file('nav.json', ''),
-          file('index.html', ''),
-          file('styles.css', ''),
-          file('dart-logo-small.png', ''),
-          file('client-live-nav.js', '')
+    integration('contains compiled dartdoc', () {
+      d.dir(appPath, [
+        d.dir('doc-out', [
+          d.file('nav.json', ''),
+          d.file('index.html', ''),
+          d.file('styles.css', ''),
+          d.file('dart-logo-small.png', ''),
+          d.file('client-live-nav.js', '')
         ])
-      ]).scheduleCreate();
+      ]).create();
 
       expectValidationWarning(compiledDartdoc);
     });
 
-    test('has a README with invalid utf-8', () {
-      dir(appPath, [
-        binaryFile("README", [192])
-      ]).scheduleCreate();
+    integration('has a README with invalid utf-8', () {
+      d.dir(appPath, [
+        d.binaryFile("README", [192])
+      ]).create();
       expectValidationWarning(utf8Readme);
     });
   });