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 @@