Version 0.4.1.0 .

svn merge -r 18904:19417 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 19424 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@19425 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/compiler/build.xml b/compiler/build.xml
index 6db056d..99e2bb6 100644
--- a/compiler/build.xml
+++ b/compiler/build.xml
@@ -43,7 +43,7 @@
   -->
   <path id="classpath.compile">
     <pathelement location="${third_party.dir}/args4j/2.0.12/args4j-2.0.12.jar"/>
-    <pathelement location="${third_party.dir}/guava/r09/guava-r09.jar"/>
+    <pathelement location="${third_party.dir}/guava/r13/guava-13.0.1.jar"/>
     <pathelement location="${third_party.dir}/json/r2_20080312/json.jar"/>
   </path>
 
diff --git a/compiler/dart-compiler.gyp b/compiler/dart-compiler.gyp
index 2dd44c0..7e589e9 100644
--- a/compiler/dart-compiler.gyp
+++ b/compiler/dart-compiler.gyp
@@ -38,7 +38,7 @@
             'scripts/dart_analyzer.bat',
             'scripts/analyzer_metrics.sh',
             '../third_party/args4j/2.0.12/args4j-2.0.12.jar',
-            '../third_party/guava/r09/guava-r09.jar',
+            '../third_party/guava/r13/guava-13.0.1.jar',
             '../third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar',
             '../third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar',
             '../third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar',
@@ -50,7 +50,7 @@
             '<(PRODUCT_DIR)/analyzer/bin/dart_analyzer.bat',
             '<(PRODUCT_DIR)/analyzer/util/analyzer/dart_analyzer.jar',
             '<(PRODUCT_DIR)/analyzer/util/analyzer/args4j/2.0.12/args4j-2.0.12.jar',
-            '<(PRODUCT_DIR)/analyzer/util/analyzer/guava/r09/guava-r09.jar',
+            '<(PRODUCT_DIR)/analyzer/util/analyzer/guava/r13/guava-13.0.1.jar',
           ],
           'action' : [
             '../third_party/apache_ant/1.8.4/bin/ant<(script_suffix)',
diff --git a/compiler/dart_analyzer.xml b/compiler/dart_analyzer.xml
index 01a5adc..ff63f2f 100644
--- a/compiler/dart_analyzer.xml
+++ b/compiler/dart_analyzer.xml
@@ -36,7 +36,7 @@
   -->
   <path id="classpath.compile">
     <pathelement location="${third_party.dir}/args4j/2.0.12/args4j-2.0.12.jar"/>
-    <pathelement location="${third_party.dir}/guava/r09/guava-r09.jar"/>
+    <pathelement location="${third_party.dir}/guava/r13/guava-13.0.1.jar"/>
     <pathelement location="${third_party.dir}/json/r2_20080312/json.jar"/>
   </path>
 
diff --git a/compiler/eclipse.workspace/dartc/.classpath b/compiler/eclipse.workspace/dartc/.classpath
index 30fd5cf..12f7079 100644
--- a/compiler/eclipse.workspace/dartc/.classpath
+++ b/compiler/eclipse.workspace/dartc/.classpath
@@ -3,7 +3,7 @@
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="var" path="DART_TRUNK/third_party/args4j/2.0.12/args4j-2.0.12.jar" sourcepath="/DART_TRUNK/third_party/args4j/2.0.12/args4j-2.0.12-src.jar"/>
-	<classpathentry kind="var" path="DART_TRUNK/third_party/guava/r09/guava-r09.jar" sourcepath="/DART_TRUNK/third_party/guava/r09/guava-src-r09.zip"/>
+	<classpathentry kind="var" path="DART_TRUNK/third_party/guava/r13/guava-13.0.1.jar" sourcepath="/DART_TRUNK/third_party/guava/r13/guava-13.0.1-sources.zip"/>
 	<classpathentry kind="var" path="DART_TRUNK/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar"/>
 	<classpathentry kind="var" path="DART_TRUNK/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar"/>
 	<classpathentry kind="var" path="DART_TRUNK/third_party/hamcrest/v1_3/hamcrest-integration-1.3.0RC2.jar"/>
diff --git a/compiler/eclipse.workspace/tests/.classpath b/compiler/eclipse.workspace/tests/.classpath
index b16c307..704cbcd 100644
--- a/compiler/eclipse.workspace/tests/.classpath
+++ b/compiler/eclipse.workspace/tests/.classpath
@@ -7,6 +7,6 @@
 	<classpathentry combineaccessrules="false" kind="src" path="/dartc"/>
 	<classpathentry kind="var" path="DART_TRUNK/third_party/args4j/2.0.12/args4j-2.0.12.jar" sourcepath="/DART_TRUNK/third_party/args4j/2.0.12/args4j-2.0.12-src.jar"/>
 	<classpathentry kind="var" path="DART_TRUNK/third_party/junit/v4_8_2/junit.jar"/>
-	<classpathentry kind="var" path="DART_TRUNK/third_party/guava/r09/guava-r09.jar"/>
+	<classpathentry kind="var" path="DART_TRUNK/third_party/guava/r13/guava-13.0.1.jar"/>
 	<classpathentry kind="output" path="output"/>
 </classpath>
diff --git a/compiler/java/com/google/dart/compiler/SystemLibrariesReader.java b/compiler/java/com/google/dart/compiler/SystemLibrariesReader.java
index 10b66c1..56d3bbf 100644
--- a/compiler/java/com/google/dart/compiler/SystemLibrariesReader.java
+++ b/compiler/java/com/google/dart/compiler/SystemLibrariesReader.java
@@ -13,6 +13,7 @@
  */
 package com.google.dart.compiler;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.io.CharStreams;
 import com.google.common.io.Closeables;
 import com.google.dart.compiler.CompilerConfiguration.ErrorFormat;
@@ -53,7 +54,8 @@
  */
 public class SystemLibrariesReader {
 
-  class DartLibrary {
+  @VisibleForTesting
+  public class DartLibrary {
 
     private String shortName = null;
     private String path = null;
diff --git a/compiler/java/com/google/dart/compiler/resolver/ClassScope.java b/compiler/java/com/google/dart/compiler/resolver/ClassScope.java
index f5625c6..e5c393f 100644
--- a/compiler/java/com/google/dart/compiler/resolver/ClassScope.java
+++ b/compiler/java/com/google/dart/compiler/resolver/ClassScope.java
@@ -76,7 +76,7 @@
       InterfaceType mixin = mixins.get(i);
       ClassElement mixinElement = mixin.getElement();
       if (!examinedTypes.contains(mixinElement)) {
-        MixinScope scope = new MixinScope(mixinElement, null);
+        MixinScope scope = new MixinScope(mixinElement);
         element = scope.findElement(inLibrary, name);
         if (element != null) {
           return element;
diff --git a/compiler/java/com/google/dart/compiler/resolver/ElementMap.java b/compiler/java/com/google/dart/compiler/resolver/ElementMap.java
index 1c3b39f..5a186a6 100644
--- a/compiler/java/com/google/dart/compiler/resolver/ElementMap.java
+++ b/compiler/java/com/google/dart/compiler/resolver/ElementMap.java
@@ -4,8 +4,9 @@
 
 package com.google.dart.compiler.resolver;
 
-import com.google.dart.compiler.ast.DartObsoleteMetadata;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.dart.compiler.ast.DartNode;
+import com.google.dart.compiler.ast.DartObsoleteMetadata;
 import com.google.dart.compiler.ast.Modifiers;
 import com.google.dart.compiler.common.SourceInfo;
 import com.google.dart.compiler.type.Type;
@@ -17,7 +18,8 @@
  * A more efficient version of {@link com.google.common.collect.Multimap} specifically for
  * {@link NodeElement}
  */
-class ElementMap {
+@VisibleForTesting
+public class ElementMap {
 
   /**
    * A synthetic place holder for an element where the name given to the element map does not match
@@ -98,7 +100,8 @@
   private NodeElement[] elements;
   private List<NodeElement> ordered = new ArrayList<NodeElement>();
 
-  ElementMap() {
+  @VisibleForTesting
+  public ElementMap() {
     clear();
   }
 
@@ -106,7 +109,8 @@
    * Associate the specified element with the specified name. If the element is already associated
    * with that name, do not associate it again.
    */
-  void add(String name, NodeElement element) {
+  @VisibleForTesting
+  public void add(String name, NodeElement element) {
 
     // Most of the time name equals getName() thus holder == element
     NodeElement newHolder;
@@ -161,7 +165,8 @@
    * 
    * @return the element or <code>null</code> if none
    */
-  NodeElement get(String name) {
+  @VisibleForTesting
+  public NodeElement get(String name) {
     NodeElement element = internalGet(name);
     if (element instanceof ElementHolder) {
       return ((ElementHolder) element).element;
@@ -175,7 +180,8 @@
    * 
    * @return the element of that kind or <code>null</code> if none
    */
-  NodeElement get(String name, ElementKind kind) {
+  @VisibleForTesting
+  public NodeElement get(String name, ElementKind kind) {
     NodeElement element = internalGet(name);
     if (element instanceof ElementHolder) {
       ElementHolder holder = (ElementHolder) element;
@@ -197,15 +203,18 @@
     return null;
   }
 
-  boolean isEmpty() {
+  @VisibleForTesting
+  public boolean isEmpty() {
     return ordered.isEmpty();
   }
 
-  int size() {
+  @VisibleForTesting
+  public int size() {
     return ordered.size();
   }
 
-  List<NodeElement> values() {
+  @VisibleForTesting
+  public List<NodeElement> values() {
     return ordered;
   }
 
diff --git a/compiler/java/com/google/dart/compiler/resolver/MixinScope.java b/compiler/java/com/google/dart/compiler/resolver/MixinScope.java
index aafa480..e40ff71 100644
--- a/compiler/java/com/google/dart/compiler/resolver/MixinScope.java
+++ b/compiler/java/com/google/dart/compiler/resolver/MixinScope.java
@@ -8,11 +8,11 @@
  * Lexical scope corresponding to a mixin.
  */
 class MixinScope extends Scope {
-  private final ClassElement classElement;
+  private final ClassElement mixinElement;
 
-  MixinScope(ClassElement classElement, Scope parent) {
-    super(classElement.getName(), parent.getLibrary(), parent);
-    this.classElement = classElement;
+  MixinScope(ClassElement mixinElement) {
+    super(mixinElement.getName(), mixinElement.getLibrary(), null);
+    this.mixinElement = mixinElement;
   }
 
   @Override
@@ -22,6 +22,6 @@
 
   @Override
   public Element findLocalElement(String name) {
-    return Elements.findElement(classElement, name);
+    return Elements.findElement(mixinElement, name);
   }
 }
diff --git a/compiler/java/com/google/dart/compiler/resolver/TopLevelElementBuilder.java b/compiler/java/com/google/dart/compiler/resolver/TopLevelElementBuilder.java
index e97667b..891afb1 100644
--- a/compiler/java/com/google/dart/compiler/resolver/TopLevelElementBuilder.java
+++ b/compiler/java/com/google/dart/compiler/resolver/TopLevelElementBuilder.java
@@ -195,7 +195,7 @@
   }
   
   @VisibleForTesting
-  void fillInUnitScope(DartUnit unit, DartCompilerListener listener, Scope scope,
+  public void fillInUnitScope(DartUnit unit, DartCompilerListener listener, Scope scope,
       List<Element> exportedElements) {
     for (DartNode node : unit.getTopLevelNodes()) {
       if (node instanceof DartFieldDefinition) {
diff --git a/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java b/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
index d1dad43..c9f05fd 100644
--- a/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
+++ b/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
@@ -4,6 +4,7 @@
 
 package com.google.dart.compiler.type;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Lists;
 import com.google.common.collect.MapMaker;
 import com.google.dart.compiler.resolver.ClassElement;
@@ -22,7 +23,8 @@
 /**
  * An interface type.
  */
-class InterfaceTypeImplementation extends AbstractType implements InterfaceType {
+@VisibleForTesting
+public class InterfaceTypeImplementation extends AbstractType implements InterfaceType {
   private final ClassElement element;
   private final List<Type> arguments;
   private final Map<ClassElement, Object> subClasses = new MapMaker().weakKeys().makeMap();
diff --git a/compiler/javatests/com/google/dart/compiler/TestAll.java b/compiler/javatests/com/google/dart/compiler/TestAll.java
new file mode 100644
index 0000000..249e544
--- /dev/null
+++ b/compiler/javatests/com/google/dart/compiler/TestAll.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, the Dart project authors.
+ *
+ * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.dart.compiler;
+
+import com.google.dart.compiler.ast.AstTests;
+import com.google.dart.compiler.common.CommonTests;
+import com.google.dart.compiler.end2end.End2EndTests;
+import com.google.dart.compiler.parser.ParserTests;
+import com.google.dart.compiler.resolver.ResolverTests;
+import com.google.dart.compiler.util.UtilTests;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class TestAll {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite("Tests in " + TestAll.class.getPackage().getName());
+
+    suite.addTest(CompilerTests.suite());
+    suite.addTest(AstTests.suite());
+    suite.addTest(CommonTests.suite());
+    suite.addTest(End2EndTests.suite());
+    suite.addTest(ParserTests.suite());
+    suite.addTest(ResolverTests.suite());
+    //suite.addTest(TypeTests.suite());
+    suite.addTest(UtilTests.suite());
+
+    return suite;
+  }
+
+}
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
index ebf9907..d84e226 100644
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
@@ -255,7 +255,7 @@
         errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 10, 1, 27),
         errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 11, 1, 17));
   }
-  
+
   /**
    * Type parameters should not conflict with formal parameters.
    * <p>
@@ -433,7 +433,7 @@
         libraryResult.getErrors(),
         errEx(ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION, 6, 10, 8));
   }
-  
+
   /**
    * It is a compile-time error if the class C implements the operator ==.
    * <p>
@@ -477,7 +477,7 @@
         libraryResult.getErrors(),
         errEx(TypeErrorCode.CASE_EXPRESSIONS_SHOULD_BE_SAME_TYPE, 5, 10, 3));
   }
-  
+
   public void test_switchExpression_case_constLocalVariable() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -490,7 +490,7 @@
         "");
     assertErrors(libraryResult.getErrors());
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=2862
@@ -634,7 +634,7 @@
       assertTrue(message.contains("void foo()"));
     }
   }
-  
+
   /**
    * In contrast, if A is intended to be concrete, the checker should warn about all unimplemented
    * methods, but allow clients to instantiate it freely.
@@ -791,7 +791,7 @@
         libraryResult.getErrors(),
         errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 5, 7, 1));
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=5327
@@ -998,7 +998,7 @@
         errEx(TypeErrorCode.NO_SUCH_NAMED_PARAMETER, 15, 18, 4),
         errEx(ResolverErrorCode.DUPLICATE_NAMED_ARGUMENT, 16, 25, 5));
   }
-  
+
   /**
    * Test that optional positional and named parameters are handled separately.
    */
@@ -1364,7 +1364,7 @@
         libraryResult.getErrors(),
         errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 4, 3, 1));
   }
-  
+
   public void test_assignFinal_topLevelVariable() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -1377,7 +1377,7 @@
         libraryResult.getErrors(),
         errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 4, 3, 1));
   }
-  
+
   public void test_assignFinal_instanceVariable_inConstructor() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -1407,7 +1407,7 @@
         "");
     assertErrors(libraryResult.getErrors());
   }
-  
+
   public void test_constantEvaluationException_divZero() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -1473,7 +1473,7 @@
         libraryResult.getErrors(),
         errEx(ResolverErrorCode.NO_SUCH_TYPE_CONST, 3, 9, 10));
   }
-  
+
   public void test_constInstanceCreation_noSuchConstructor() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -1486,7 +1486,7 @@
         libraryResult.getErrors(),
         errEx(ResolverErrorCode.NEW_EXPRESSION_NOT_CONST_CONSTRUCTOR, 4, 11, 10));
   }
-  
+
   public void test_constInstanceCreation_notType() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -1669,7 +1669,7 @@
         result.getErrors(),
         errEx(ResolverErrorCode.CANNOT_OVERRIDE_METHOD_OPTIONAL_PARAMS, 5, 3, 3));
   }
-  
+
   public void test_implementsAndOverrides_moreOptionalPositionalParameter() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "abstract class A {",
@@ -1725,7 +1725,7 @@
         errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 11, 7, 5),
         errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 12, 7, 7));
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=3183
@@ -1879,7 +1879,7 @@
             "}");
     assertErrors(result.getErrors());
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=7597
@@ -2067,7 +2067,7 @@
             "");
     assertErrors(result.getErrors());
   }
-  
+
   public void test_inferredTypes_noMemberWarnings() throws Exception {
     // disabled by default
     {
@@ -2214,7 +2214,7 @@
     assertInferredElementTypeString(testUnit, "v6", "Map<String, int>", INFERRED);
     assertInferredElementTypeString(testUnit, "v7", "int", INFERRED);
   }
-  
+
   public void test_typesPropagation_arrayAccess() throws Exception {
     analyzeLibrary(
         "class A {}",
@@ -2365,7 +2365,7 @@
     assertInferredElementTypeString(testUnit, "v3", "int", INFERRED_EXACT);
     assertInferredElementTypeString(testUnit, "v4", "Object", INFERRED);
   }
-  
+
   public void test_typesPropagation_multiAssign_DoWhile() throws Exception {
     analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -2449,7 +2449,7 @@
     assertInferredElementTypeString(testUnit, "a1", "List<Object>", INFERRED);
     assertInferredElementTypeString(testUnit, "b1", "List<Object>", INFERRED);
   }
-  
+
   /**
    * Prefer specific type, not "dynamic" type argument.
    * <p>
@@ -2472,7 +2472,7 @@
     assertInferredElementTypeString(testUnit, "a1", "List<String>", INFERRED);
     assertInferredElementTypeString(testUnit, "b1", "List<String>", INFERRED);
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=4791
@@ -2943,7 +2943,7 @@
     // we exited "if" Block, so "assert" may be was not executed, so we don't know type
     assertInferredElementTypeString(testUnit, "v5", "dynamic", EXACT);
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=4410
@@ -3029,7 +3029,7 @@
     assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT);
     assertInferredElementTypeString(testUnit, "v2", "double", INFERRED_EXACT);
   }
-  
+
   /**
    * If field is not final, we don't know if is will be assigned somewhere else, may be even not in
    * there same unit, so we cannot be sure about its type.
@@ -3063,7 +3063,7 @@
     assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT);
     assertInferredElementTypeString(testUnit, "v2", "double", INFERRED_EXACT);
   }
-  
+
   /**
    * If field is not final, we don't know if is will be assigned somewhere else, may be even not in
    * there same unit, so we cannot be sure about its type.
@@ -3980,7 +3980,7 @@
         errEx(TypeErrorCode.DEPRECATED_ELEMENT, 11, 7, 1),
         errEx(TypeErrorCode.DEPRECATED_ELEMENT, 11, 9, 7));
   }
-  
+
   public void test_metadata_resolving() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -4260,7 +4260,7 @@
       assertHasFieldElement(binary.getArg1(), "A", "b");
     }
   }
-  
+
   /**
    * Test for resolving variants of top-level property access and unary/binary expressions.
    * <p>
@@ -4330,7 +4330,7 @@
     FieldElement fieldElement = (FieldElement) element;
     assertHasFieldElement(fieldElement, className, fieldName);
   }
-  
+
   private static void assertHasFieldElement(FieldElement element, String className, String fieldName) {
     EnclosingElement enclosingElement = element.getEnclosingElement();
     String enclosingName;
@@ -4344,14 +4344,14 @@
     String elementName = element.getName();
     assertEquals(fieldName, elementName);
   }
-  
+
   private static void assertHasMethodElement(DartNode node, String className, String methodName) {
     Element element = node.getElement();
     assertTrue("" + node + " " + element, element instanceof MethodElement);
     MethodElement methodElement = (MethodElement) element;
     assertMethodElement(methodElement, className, methodName);
   }
-  
+
   private static void assertMethodElement(MethodElement element, String className, String methodName) {
     EnclosingElement enclosingElement = element.getEnclosingElement();
     String enclosingName;
@@ -4406,7 +4406,7 @@
         errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 10, 3, 3),
         errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 11, 3, 9));
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=3223
@@ -4420,7 +4420,7 @@
         "}");
     assertErrors(libraryResult.getErrors());
   }
-  
+
   public void test_invokeNonFunction_getter() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -4632,7 +4632,7 @@
         "");
     assertErrors(result.getErrors());
   }
-  
+
   /**
    * There should be no problem reported, because assignment of "a" cascade to "b" with type "B"
    * implicitly set type of "a" to "B".
@@ -4674,7 +4674,7 @@
         "");
     assertErrors(result.getErrors());
   }
-  
+
   /**
    * We assign "a" to field "Holder.b" of type "B", so implicitly set type of "a" to "B".
    * <p>
@@ -4814,7 +4814,7 @@
         errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 11, 3, 7),
         errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 12, 11, 7));
   }
-  
+
   /**
    * If "unknown" is separate identifier, it is handled as "this.unknown", but "this" is not
    * accessible in static context.
@@ -4854,7 +4854,7 @@
         errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 4, 3, 7),
         errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 11, 7));
   }
-  
+
   /**
    * Unresolved constructor is warning.
    * <p>
@@ -4877,7 +4877,7 @@
         errEx(TypeErrorCode.NO_SUCH_TYPE, 7, 7, 1),
         errEx(TypeErrorCode.NEW_EXPRESSION_NOT_CONSTRUCTOR, 7, 9, 17));
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=4383
@@ -4893,7 +4893,7 @@
         libraryResult.getErrors(),
         errEx(ResolverErrorCode.USE_ASSIGNMENT_ON_SETTER, 4, 3, 12));
   }
-  
+
   /**
    * Every {@link DartExpression} should have {@link Type} set. Just to don't guess this type at
    * many other points in the Editor.
@@ -4908,6 +4908,7 @@
         "  process(aaa);",
         "}");
     testUnit.accept(new ASTVisitor<Void>() {
+      @Override
       public Void visitIdentifier(DartIdentifier node) {
         // ignore declaration
         if (node.getParent() instanceof DartDeclaration) {
@@ -4923,7 +4924,7 @@
       }
     });
   }
-  
+
   /**
    * Every {@link DartExpression} should have {@link Type} set. Just to don't guess this type at
    * many other points in the Editor.
@@ -4938,6 +4939,7 @@
         "  AAA.foo();",
         "}");
     testUnit.accept(new ASTVisitor<Void>() {
+      @Override
       public Void visitIdentifier(DartIdentifier node) {
         // ignore declaration
         if (node.getParent() instanceof DartDeclaration) {
@@ -4976,7 +4978,7 @@
         errEx(TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, 5, 5, 12),
         errEx(TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, 10, 5, 12));
   }
-  
+
   private abstract static class ArgumentsBindingTester {
     static List<DartExpression> arguments;
     void doTest(DartUnit unit) {
@@ -5034,7 +5036,7 @@
       }
     }.doTest(testUnit);
   }
-  
+
   public void test_formalParameters_positional_named() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5097,7 +5099,7 @@
         libraryResult.getErrors(),
         errEx(ResolverErrorCode.CONSTRUCTOR_WITH_NAME_OF_MEMBER, 3, 3, 5));
   }
-  
+
   /**
    * It is a compile-time error if M is not the name of the immediately enclosing class.
    * It is a static warning if M.id is not a constructor name.
@@ -5173,7 +5175,7 @@
       assertSame(elementA.lookupConstructor("named"), nameElement);
     }
   }
-  
+
   public void test_redirectingFactoryConstructor_cycle() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5245,7 +5247,7 @@
         "");
     assertErrors(libraryResult.getErrors());
   }
-  
+
   public void test_redirectingFactoryConstructor_shouldBeSubType3() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5259,7 +5261,7 @@
         "");
     assertErrors(libraryResult.getErrors());
   }
-  
+
   public void test_redirectingFactoryConstructor_notSubType_typeParameterBounds() throws Exception {
     AnalyzeLibraryResult libraryResult = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5463,7 +5465,7 @@
         "");
     assertErrors(result.getErrors(), errEx(ResolverErrorCode.DUPLICATE_IMPLEMENTS_TYPE, 3, 23, 1));
   }
-  
+
   /**
    * It is a compile-time error if the superclass of a class C appears in the implements clause of C.
    * <p>
@@ -5477,7 +5479,7 @@
         "");
     assertErrors(result.getErrors(), errEx(ResolverErrorCode.SUPER_CLASS_IN_IMPLEMENTS, 3, 30, 1));
   }
-  
+
   /**
    * We should report only "no such type", but not duplicate.
    * <p>
@@ -5562,7 +5564,7 @@
         result.getErrors(),
         errEx(ResolverErrorCode.DUPLICATE_INITIALIZATION, 4, 9, 5));
   }
-  
+
   public void test_getOverridden_method() throws Exception {
     analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5614,7 +5616,7 @@
       assertClassMembers(superElements, "field A.foo");
     }
   }
-  
+
   public void test_getOverridden_field_withGetter() throws Exception {
     analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5667,7 +5669,7 @@
     Set<Element> superElements = node.getElement().getOverridden();
     assertClassMembers(superElements, "field A.foo");
   }
-  
+
   public void test_getOverridden_getter_withField() throws Exception {
     analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5682,7 +5684,7 @@
     Set<Element> superElements = node.getElement().getOverridden();
     assertClassMembers(superElements, "field A.foo");
   }
-  
+
   public void test_getOverridden_setter_withField() throws Exception {
     analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5697,7 +5699,7 @@
     Set<Element> superElements = node.getElement().getOverridden();
     assertClassMembers(superElements, "field A.setter foo");
   }
-  
+
   public void test_getOverridden_setter_withSetter() throws Exception {
     analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5742,7 +5744,7 @@
         "");
     assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER, 6, 11, 1));
   }
-  
+
   public void test_fieldAccess_notDeclared() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5754,7 +5756,7 @@
         "");
     assertErrors(result.getErrors(), errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 11, 1));
   }
-  
+
   public void test_fieldAssign_declared_noSetter() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5767,7 +5769,7 @@
         "");
     assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER, 6, 5, 1));
   }
-  
+
   public void test_fieldAssign_notDeclared() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5792,7 +5794,7 @@
         "");
     assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER, 5, 13, 1));
   }
-  
+
   public void test_field_unqualifiedAccess_write() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5855,7 +5857,7 @@
         result.getErrors(),
         errEx(ResolverErrorCode.CANNOT_RESOLVE_METHOD, 4, 5, 3));
   }
-  
+
   /**
    * Developers unfamiliar with Dart frequently write (x/y).toInt() instead of x ~/ y. The editor
    * should recognize that pattern.
@@ -5873,7 +5875,7 @@
         "");
     assertErrors(result.getErrors(), errEx(TypeErrorCode.USE_INTEGER_DIVISION, 5, 10, 15));
   }
-  
+
   /**
    * We need to report warning only when arguments are integers.
    * <p>
@@ -5923,7 +5925,7 @@
         "");
     assertErrors(result.getErrors());
   }
-  
+
   /**
    * We should resolve sub-type member only if there is only sub-type with such member.
    * <p>
@@ -5959,7 +5961,7 @@
     // don't report error, because there IS member, we just don't know which one
     assertErrors(result.getErrors());
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=6491
@@ -6027,7 +6029,7 @@
       assertEquals("bbb", element.getName());
     }
   }
-  
+
   public void test_resolveRefInComment_ofMethod() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -6052,7 +6054,7 @@
       assertEquals("bar", element.getName());
     }
   }
-  
+
   public void test_resolveNewInComment() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -6100,7 +6102,7 @@
         errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 11, 3, 1),
         errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 13, 7, 1));
   }
-  
+
   public void test_notGenerativeConstructor_explicitNamed() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -6132,7 +6134,7 @@
     assertErrors(result.getErrors(),
         errEx(ResolverErrorCode.INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR, 4, 9, 5));
   }
-  
+
   public void test_variableReferencesItselfInInitializer() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -6287,7 +6289,7 @@
     assertNotNull(expectedElement);
     assertSame(nameInInvocation.getElement(), expectedElement);
   }
-  
+
   public void test_mixin_1() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -6303,7 +6305,7 @@
         "");
     assertErrors(result.getErrors());
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=8022
@@ -6321,7 +6323,7 @@
         errEx(ResolverErrorCode.ONLY_OBJECT_MIXIN_SUPERCLASS, 4, 25, 1),
         errEx(ResolverErrorCode.ONLY_OBJECT_MIXIN_SUPERCLASS, 5, 29, 1));
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=8025
@@ -6338,7 +6340,7 @@
         errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_CONSTRUCTOR, 3, 25, 1),
         errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_CONSTRUCTOR, 4, 29, 1));
   }
-  
+
   /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=8059
@@ -6355,7 +6357,24 @@
         errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_SUPER, 3, 25, 1),
         errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_SUPER, 4, 29, 1));
   }
-  
+
+  /**
+   * <p>
+   * http://code.google.com/p/dart/issues/detail?id=8705
+   */
+  public void test_mixin_useInScope() throws Exception {
+    AnalyzeLibraryResult result = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class M { foo() {} }",
+        "class A extends Object with M {",
+        "  bar() {",
+        "    foo();",
+        "  }",
+        "}",
+        "");
+    assertErrors(result.getErrors());
+  }
+
   /**
    * 20130122. Currently it is not allowed to have mixin with superclass other than Object.
    */
@@ -6408,7 +6427,7 @@
         errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 12, 9, 1),
         errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 15, 5, 7));
   }
-  
+
   /**
    * 20130122. Currently it is not allowed to have mixin with superclass other than Object.
    */
@@ -6455,7 +6474,7 @@
         result.getErrors(),
         errEx(TypeErrorCode.NOT_A_MEMBER_OF, 13, 11, 2));
   }
-  
+
   /**
    * 20130122. Currently it is not allowed to have mixin with superclass other than Object.
    */
@@ -6490,5 +6509,5 @@
         result.getErrors(),
         errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_MIXINS, 2, 25, 1));
   }
-  
+
 }
diff --git a/pkg/analyzer-experimental/lib/src/generated/ast.dart b/pkg/analyzer-experimental/lib/src/generated/ast.dart
index c7e03c7..3c842d7 100644
--- a/pkg/analyzer-experimental/lib/src/generated/ast.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/ast.dart
@@ -2408,7 +2408,7 @@
     } else if (parserErrors.length == 0) {
       return resolverErrors;
     } else {
-      List<AnalysisError> allErrors = new List<AnalysisError>.fixedLength(parserErrors.length + resolverErrors.length);
+      List<AnalysisError> allErrors = new List<AnalysisError>(parserErrors.length + resolverErrors.length);
       System.arraycopy(parserErrors, 0, allErrors, 0, parserErrors.length);
       System.arraycopy(resolverErrors, 0, allErrors, parserErrors.length, resolverErrors.length);
       return allErrors;
@@ -4791,7 +4791,7 @@
    */
   List<ParameterElement> get elements {
     int count = _parameters.length;
-    List<ParameterElement> types = new List<ParameterElement>.fixedLength(count);
+    List<ParameterElement> types = new List<ParameterElement>(count);
     for (int i = 0; i < count; i++) {
       types[i] = _parameters[i].element;
     }
diff --git a/pkg/analyzer-experimental/lib/src/generated/element.dart b/pkg/analyzer-experimental/lib/src/generated/element.dart
index 407dd69..9be35da 100644
--- a/pkg/analyzer-experimental/lib/src/generated/element.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/element.dart
@@ -399,7 +399,7 @@
   /**
    * An empty array of export elements.
    */
-  static List<ExportElement> EMPTY_ARRAY = new List<ExportElement>.fixedLength(0);
+  static List<ExportElement> EMPTY_ARRAY = new List<ExportElement>(0);
   /**
    * Return an array containing the combinators that were specified as part of the export directive
    * in the order in which they were specified.
@@ -498,7 +498,7 @@
   /**
    * An empty array of import elements.
    */
-  static List<ImportElement> EMPTY_ARRAY = new List<ImportElement>.fixedLength(0);
+  static List<ImportElement> EMPTY_ARRAY = new List<ImportElement>(0);
   /**
    * Return an array containing the combinators that were specified as part of the import directive
    * in the order in which they were specified.
@@ -629,7 +629,7 @@
   /**
    * An empty array of namespace combinators.
    */
-  static List<NamespaceCombinator> EMPTY_ARRAY = new List<NamespaceCombinator>.fixedLength(0);
+  static List<NamespaceCombinator> EMPTY_ARRAY = new List<NamespaceCombinator>(0);
 }
 /**
  * The interface {@code ParameterElement} defines the behavior of elements representing a parameter
@@ -815,7 +815,7 @@
   /**
    * An empty array of annotations.
    */
-  static List<AnnotationImpl> EMPTY_ARRAY = new List<AnnotationImpl>.fixedLength(0);
+  static List<AnnotationImpl> EMPTY_ARRAY = new List<AnnotationImpl>(0);
   /**
    * Initialize a newly created annotation.
    * @param element the element representing the field, variable, or constructor being used as an
@@ -871,7 +871,7 @@
   /**
    * An empty array of type elements.
    */
-  static List<ClassElement> EMPTY_ARRAY = new List<ClassElement>.fixedLength(0);
+  static List<ClassElement> EMPTY_ARRAY = new List<ClassElement>(0);
   /**
    * Initialize a newly created class element to have the given name.
    * @param name the name of this element
@@ -1213,7 +1213,7 @@
   /**
    * An empty array of compilation unit elements.
    */
-  static List<CompilationUnitElement> EMPTY_ARRAY = new List<CompilationUnitElement>.fixedLength(0);
+  static List<CompilationUnitElement> EMPTY_ARRAY = new List<CompilationUnitElement>(0);
   /**
    * Initialize a newly created compilation unit element to have the given name.
    * @param name the name of this element
@@ -1332,7 +1332,7 @@
   /**
    * An empty array of constructor elements.
    */
-  static List<ConstructorElement> EMPTY_ARRAY = new List<ConstructorElement>.fixedLength(0);
+  static List<ConstructorElement> EMPTY_ARRAY = new List<ConstructorElement>(0);
   /**
    * Initialize a newly created constructor element to have the given name.
    * @param name the name of this element
@@ -1689,7 +1689,7 @@
   /**
    * An empty array of executable elements.
    */
-  static List<ExecutableElement> EMPTY_ARRAY = new List<ExecutableElement>.fixedLength(0);
+  static List<ExecutableElement> EMPTY_ARRAY = new List<ExecutableElement>(0);
   /**
    * Initialize a newly created executable element to have the given name.
    * @param name the name of this element
@@ -1858,7 +1858,7 @@
   /**
    * An empty array of field elements.
    */
-  static List<FieldElement> EMPTY_ARRAY = new List<FieldElement>.fixedLength(0);
+  static List<FieldElement> EMPTY_ARRAY = new List<FieldElement>(0);
   /**
    * Initialize a newly created field element to have the given name.
    * @param name the name of this element
@@ -1920,7 +1920,7 @@
   /**
    * An empty array of function elements.
    */
-  static List<FunctionElement> EMPTY_ARRAY = new List<FunctionElement>.fixedLength(0);
+  static List<FunctionElement> EMPTY_ARRAY = new List<FunctionElement>(0);
   /**
    * Initialize a newly created synthetic function element.
    */
@@ -2009,7 +2009,7 @@
   /**
    * An empty array of HTML file elements.
    */
-  static List<HtmlElement> EMPTY_ARRAY = new List<HtmlElement>.fixedLength(0);
+  static List<HtmlElement> EMPTY_ARRAY = new List<HtmlElement>(0);
   /**
    * The analysis context in which this library is defined.
    */
@@ -2129,7 +2129,7 @@
   /**
    * An empty array of label elements.
    */
-  static List<LabelElement> EMPTY_ARRAY = new List<LabelElement>.fixedLength(0);
+  static List<LabelElement> EMPTY_ARRAY = new List<LabelElement>(0);
   /**
    * Initialize a newly created label element to have the given name.
    * @param name the name of this element
@@ -2160,7 +2160,7 @@
   /**
    * An empty array of library elements.
    */
-  static List<LibraryElement> EMPTY_ARRAY = new List<LibraryElement>.fixedLength(0);
+  static List<LibraryElement> EMPTY_ARRAY = new List<LibraryElement>(0);
   /**
    * The analysis context in which this library is defined.
    */
@@ -2316,7 +2316,7 @@
   /**
    * An empty array of method elements.
    */
-  static List<MethodElement> EMPTY_ARRAY = new List<MethodElement>.fixedLength(0);
+  static List<MethodElement> EMPTY_ARRAY = new List<MethodElement>(0);
   /**
    * Initialize a newly created method element to have the given name.
    * @param name the name of this element
@@ -2484,7 +2484,7 @@
   /**
    * An empty array of field elements.
    */
-  static List<ParameterElement> EMPTY_ARRAY = new List<ParameterElement>.fixedLength(0);
+  static List<ParameterElement> EMPTY_ARRAY = new List<ParameterElement>(0);
   /**
    * Initialize a newly created parameter element to have the given name.
    * @param name the name of this element
@@ -2528,7 +2528,7 @@
   /**
    * An empty array of prefix elements.
    */
-  static List<PrefixElement> EMPTY_ARRAY = new List<PrefixElement>.fixedLength(0);
+  static List<PrefixElement> EMPTY_ARRAY = new List<PrefixElement>(0);
   /**
    * Initialize a newly created prefix element to have the given name.
    * @param name the name of this element
@@ -2564,7 +2564,7 @@
   /**
    * An empty array of property accessor elements.
    */
-  static List<PropertyAccessorElement> EMPTY_ARRAY = new List<PropertyAccessorElement>.fixedLength(0);
+  static List<PropertyAccessorElement> EMPTY_ARRAY = new List<PropertyAccessorElement>(0);
   /**
    * Initialize a newly created synthetic property accessor element to be associated with the given
    * field.
@@ -2677,7 +2677,7 @@
   /**
    * An empty array of type alias elements.
    */
-  static List<TypeAliasElement> EMPTY_ARRAY = new List<TypeAliasElement>.fixedLength(0);
+  static List<TypeAliasElement> EMPTY_ARRAY = new List<TypeAliasElement>(0);
   /**
    * Initialize a newly created type alias element to have the given name.
    * @param name the name of this element
@@ -2776,7 +2776,7 @@
   /**
    * An empty array of type variable elements.
    */
-  static List<TypeVariableElement> EMPTY_ARRAY = new List<TypeVariableElement>.fixedLength(0);
+  static List<TypeVariableElement> EMPTY_ARRAY = new List<TypeVariableElement>(0);
   /**
    * Initialize a newly created type variable element to have the given name.
    * @param name the name of this element
@@ -2833,7 +2833,7 @@
   /**
    * An empty array of variable elements.
    */
-  static List<VariableElement> EMPTY_ARRAY = new List<VariableElement>.fixedLength(0);
+  static List<VariableElement> EMPTY_ARRAY = new List<VariableElement>(0);
   /**
    * Initialize a newly created variable element to have the given name.
    * @param name the name of this element
@@ -3244,7 +3244,7 @@
   /**
    * An empty array of types.
    */
-  static List<InterfaceType> EMPTY_ARRAY = new List<InterfaceType>.fixedLength(0);
+  static List<InterfaceType> EMPTY_ARRAY = new List<InterfaceType>(0);
   /**
    * This method computes the longest inheritance path from some passed {@link Type} to Object.
    * @param type the {@link Type} to compute the longest inheritance path of from the passed{@link Type} to Object
@@ -3367,7 +3367,7 @@
     si.retainAll(sj);
     Set<InterfaceType> s = si;
     List<InterfaceType> sn = new List.from(s);
-    List<int> depths = new List<int>.fixedLength(sn.length);
+    List<int> depths = new List<int>(sn.length);
     int maxDepth = 0;
     for (int n = 0; n < sn.length; n++) {
       depths[n] = computeLongestInheritancePathToObject(sn[n]);
@@ -3557,7 +3557,7 @@
    */
   static List<Type2> substitute(List<Type2> types, List<Type2> argumentTypes, List<Type2> parameterTypes) {
     int length6 = types.length;
-    List<Type2> newTypes = new List<Type2>.fixedLength(length6);
+    List<Type2> newTypes = new List<Type2>(length6);
     for (int i = 0; i < length6; i++) {
       newTypes[i] = types[i].substitute2(argumentTypes, parameterTypes);
     }
@@ -3575,7 +3575,7 @@
   /**
    * An empty array of types.
    */
-  static List<Type2> EMPTY_ARRAY = new List<Type2>.fixedLength(0);
+  static List<Type2> EMPTY_ARRAY = new List<Type2>(0);
   /**
    * Initialize a newly created type to be declared by the given element and to have the given name.
    * @param element the element representing the declaration of the type
@@ -3621,7 +3621,7 @@
    */
   static List<TypeVariableType> getTypes(List<TypeVariableElement> typeVariables) {
     int count = typeVariables.length;
-    List<TypeVariableType> types = new List<TypeVariableType>.fixedLength(count);
+    List<TypeVariableType> types = new List<TypeVariableType>(count);
     for (int i = 0; i < count; i++) {
       types[i] = typeVariables[i].type;
     }
@@ -3967,4 +3967,4 @@
  */
 abstract class VoidType implements Type2 {
   VoidType substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes);
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/engine.dart b/pkg/analyzer-experimental/lib/src/generated/engine.dart
index 20ab924..b1f1265 100644
--- a/pkg/analyzer-experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/engine.dart
@@ -513,7 +513,7 @@
   }
   CompilationUnit resolve(Source source, LibraryElement library) => parse(source);
   Token scan(Source source, AnalysisErrorListener errorListener) {
-    List<Token> tokens = new List<Token>.fixedLength(1);
+    List<Token> tokens = new List<Token>(1);
     Source_ContentReceiver receiver = new Source_ContentReceiver_1(source, errorListener, tokens);
     try {
       source.getContents(receiver);
@@ -657,4 +657,4 @@
   }
   void logInformation2(String message, Exception exception) {
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/error.dart b/pkg/analyzer-experimental/lib/src/generated/error.dart
index 17a0466..d107954 100644
--- a/pkg/analyzer-experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/error.dart
@@ -120,7 +120,7 @@
   /**
    * An empty array of errors used when no errors are expected.
    */
-  static List<AnalysisError> NO_ERRORS = new List<AnalysisError>.fixedLength(0);
+  static List<AnalysisError> NO_ERRORS = new List<AnalysisError>(0);
   /**
    * The error code associated with the error.
    */
@@ -226,4 +226,4 @@
     builder.add(_message);
     return builder.toString();
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/java_engine.dart b/pkg/analyzer-experimental/lib/src/generated/java_engine.dart
index 9254fdc..b1c131a4 100644
--- a/pkg/analyzer-experimental/lib/src/generated/java_engine.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/java_engine.dart
@@ -45,7 +45,7 @@
 //}
 
 class StringUtilities {
-  static List<String> EMPTY_ARRAY = new List.fixedLength(0);
+  static List<String> EMPTY_ARRAY = new List(0);
 }
 
 File createFile(String path) => new File(path);
@@ -53,4 +53,4 @@
 class OSUtilities {
   static bool isWindows() => Platform.operatingSystem == 'windows';
   static bool isMac() => Platform.operatingSystem == 'macos';
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/lib/src/generated/resolver.dart b/pkg/analyzer-experimental/lib/src/generated/resolver.dart
index ed1a436..2e576fc 100644
--- a/pkg/analyzer-experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/resolver.dart
@@ -125,7 +125,7 @@
     element.typeVariables = typeVariables4;
     InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
     int typeVariableCount = typeVariables4.length;
-    List<Type2> typeArguments = new List<Type2>.fixedLength(typeVariableCount);
+    List<Type2> typeArguments = new List<Type2>(typeVariableCount);
     for (int i = 0; i < typeVariableCount; i++) {
       TypeVariableElementImpl typeVariable = (typeVariables4[i] as TypeVariableElementImpl);
       TypeVariableTypeImpl typeArgument = new TypeVariableTypeImpl(typeVariable);
@@ -148,7 +148,7 @@
     element.typeVariables = typeVariables5;
     InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
     int typeVariableCount = typeVariables5.length;
-    List<Type2> typeArguments = new List<Type2>.fixedLength(typeVariableCount);
+    List<Type2> typeArguments = new List<Type2>(typeVariableCount);
     for (int i = 0; i < typeVariableCount; i++) {
       TypeVariableElementImpl typeVariable = (typeVariables5[i] as TypeVariableElementImpl);
       TypeVariableTypeImpl typeArgument = new TypeVariableTypeImpl(typeVariable);
@@ -1996,7 +1996,7 @@
    */
   List<String> getIdentifiers(NodeList<SimpleIdentifier> names) {
     int count = names.length;
-    List<String> identifiers = new List<String>.fixedLength(count);
+    List<String> identifiers = new List<String>(count);
     for (int i = 0; i < count; i++) {
       identifiers[i] = names[i].name;
     }
@@ -3536,7 +3536,7 @@
       int parameterCount = parameters.length;
       if (parameterCount > 0) {
         DynamicTypeImpl dynamicType = DynamicTypeImpl.instance;
-        List<Type2> arguments = new List<Type2>.fixedLength(parameterCount);
+        List<Type2> arguments = new List<Type2>(parameterCount);
         for (int i = 0; i < parameterCount; i++) {
           arguments[i] = dynamicType;
         }
diff --git a/pkg/analyzer-experimental/lib/src/generated/scanner.dart b/pkg/analyzer-experimental/lib/src/generated/scanner.dart
index 5251003..f2bd02d 100644
--- a/pkg/analyzer-experimental/lib/src/generated/scanner.dart
+++ b/pkg/analyzer-experimental/lib/src/generated/scanner.dart
@@ -1771,7 +1771,7 @@
   /**
    * An empty transition table used by leaf states.
    */
-  static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>.fixedLength(26);
+  static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>(26);
   /**
    * The initial state in the state machine.
    */
@@ -1789,7 +1789,7 @@
    * @return the state that was created
    */
   static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length12) {
-    List<KeywordState> result = new List<KeywordState>.fixedLength(26);
+    List<KeywordState> result = new List<KeywordState>(26);
     assert(length12 != 0);
     int chunk = 0x0;
     int chunkStart = -1;
@@ -1828,7 +1828,7 @@
    */
   static KeywordState createKeywordStateTable() {
     List<Keyword> values2 = Keyword.values;
-    List<String> strings = new List<String>.fixedLength(values2.length);
+    List<String> strings = new List<String>(values2.length);
     for (int i = 0; i < values2.length; i++) {
       strings[i] = values2[i].syntax;
     }
@@ -1867,4 +1867,4 @@
    * @return the state that follows this state on a transition of the given character
    */
   KeywordState next(int c) => _table[c - 0x61];
-}
\ No newline at end of file
+}
diff --git a/pkg/analyzer-experimental/test/generated/element_test.dart b/pkg/analyzer-experimental/test/generated/element_test.dart
index 384d332..0610a55 100644
--- a/pkg/analyzer-experimental/test/generated/element_test.dart
+++ b/pkg/analyzer-experimental/test/generated/element_test.dart
@@ -613,8 +613,8 @@
     element.type = type;
     int count = parameterNames.length;
     if (count > 0) {
-      List<TypeVariableElementImpl> typeVariables = new List<TypeVariableElementImpl>.fixedLength(count);
-      List<TypeVariableTypeImpl> typeArguments = new List<TypeVariableTypeImpl>.fixedLength(count);
+      List<TypeVariableElementImpl> typeVariables = new List<TypeVariableElementImpl>(count);
+      List<TypeVariableTypeImpl> typeArguments = new List<TypeVariableTypeImpl>(count);
       for (int i = 0; i < count; i++) {
         TypeVariableElementImpl variable = new TypeVariableElementImpl(ASTFactory.identifier2(parameterNames[i]));
         typeVariables[i] = variable;
@@ -664,7 +664,7 @@
     }
     int count = normalParameters == null ? 0 : normalParameters.length;
     if (count > 0) {
-      List<InterfaceType> normalParameterTypes = new List<InterfaceType>.fixedLength(count);
+      List<InterfaceType> normalParameterTypes = new List<InterfaceType>(count);
       for (int i = 0; i < count; i++) {
         normalParameterTypes[i] = normalParameters[i].type;
       }
@@ -672,7 +672,7 @@
     }
     count = optionalParameters == null ? 0 : optionalParameters.length;
     if (count > 0) {
-      List<InterfaceType> optionalParameterTypes = new List<InterfaceType>.fixedLength(count);
+      List<InterfaceType> optionalParameterTypes = new List<InterfaceType>(count);
       for (int i = 0; i < count; i++) {
         optionalParameterTypes[i] = optionalParameters[i].type;
       }
@@ -689,7 +689,7 @@
     }
     int count = normalParameters == null ? 0 : normalParameters.length;
     if (count > 0) {
-      List<InterfaceType> normalParameterTypes = new List<InterfaceType>.fixedLength(count);
+      List<InterfaceType> normalParameterTypes = new List<InterfaceType>(count);
       for (int i = 0; i < count; i++) {
         normalParameterTypes[i] = normalParameters[i].type;
       }
@@ -747,7 +747,7 @@
   static MethodElement methodElement(String methodName, Type2 returnType9, List<Type2> argumentTypes) {
     MethodElementImpl method = new MethodElementImpl.con1(ASTFactory.identifier2(methodName));
     int count = argumentTypes.length;
-    List<ParameterElement> parameters = new List<ParameterElement>.fixedLength(count);
+    List<ParameterElement> parameters = new List<ParameterElement>(count);
     for (int i = 0; i < count; i++) {
       ParameterElementImpl parameter = new ParameterElementImpl(ASTFactory.identifier2("a${i}"));
       parameter.type = argumentTypes[i];
diff --git a/pkg/analyzer-experimental/test/generated/parser_test.dart b/pkg/analyzer-experimental/test/generated/parser_test.dart
index b8ba2d3..421feee 100644
--- a/pkg/analyzer-experimental/test/generated/parser_test.dart
+++ b/pkg/analyzer-experimental/test/generated/parser_test.dart
@@ -21,7 +21,7 @@
   /**
    * An empty array of objects used as arguments to zero-argument methods.
    */
-  static List<Object> _EMPTY_ARGUMENTS = new List<Object>.fixedLength(0);
+  static List<Object> _EMPTY_ARGUMENTS = new List<Object>(0);
   /**
    * Invoke a parse method in {@link Parser}. The method is assumed to have the given number and
    * type of parameters and will be invoked with the given arguments.
@@ -35,7 +35,7 @@
    * @throws Exception if the method could not be invoked or throws an exception
    * @throws AssertionFailedError if the result is {@code null} or if any errors are produced
    */
-  static Object parse(String methodName, List<Object> objects, String source) => parse3(methodName, objects, source, new List<AnalysisError>.fixedLength(0));
+  static Object parse(String methodName, List<Object> objects, String source) => parse3(methodName, objects, source, new List<AnalysisError>(0));
   /**
    * Invoke a parse method in {@link Parser}. The method is assumed to have the given number and
    * type of parameters and will be invoked with the given arguments.
@@ -2888,7 +2888,7 @@
     JUnitTestCase.assertNotNull(functionBody.semicolon);
   }
   void test_parseFunctionDeclaration_function() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     FunctionDeclaration declaration = ParserTestCase.parse("parseFunctionDeclaration", <Object> [commentAndMetadata(comment, []), null, returnType, false], "f() {}");
     JUnitTestCase.assertEquals(comment, declaration.documentationComment);
@@ -2901,7 +2901,7 @@
     JUnitTestCase.assertNull(declaration.propertyKeyword);
   }
   void test_parseFunctionDeclaration_function_inStatement() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     FunctionDeclaration declaration = ParserTestCase.parse("parseFunctionDeclaration", <Object> [commentAndMetadata(comment, []), null, returnType, true], "f() {};");
     JUnitTestCase.assertEquals(comment, declaration.documentationComment);
@@ -2914,7 +2914,7 @@
     JUnitTestCase.assertNull(declaration.propertyKeyword);
   }
   void test_parseFunctionDeclaration_getter() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     FunctionDeclaration declaration = ParserTestCase.parse("parseFunctionDeclaration", <Object> [commentAndMetadata(comment, []), null, returnType, false], "get p => 0;");
     JUnitTestCase.assertEquals(comment, declaration.documentationComment);
@@ -2927,7 +2927,7 @@
     JUnitTestCase.assertNotNull(declaration.propertyKeyword);
   }
   void test_parseFunctionDeclaration_setter() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     FunctionDeclaration declaration = ParserTestCase.parse("parseFunctionDeclaration", <Object> [commentAndMetadata(comment, []), null, returnType, false], "set p(v) {}");
     JUnitTestCase.assertEquals(comment, declaration.documentationComment);
@@ -2955,7 +2955,7 @@
     JUnitTestCase.assertNotNull(expression.parameters);
   }
   void test_parseGetter_nonStatic() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     MethodDeclaration method = ParserTestCase.parse("parseGetter", <Object> [commentAndMetadata(comment, []), null, null, returnType], "get a;");
     JUnitTestCase.assertNotNull(method.body);
@@ -2969,7 +2969,7 @@
     JUnitTestCase.assertEquals(returnType, method.returnType);
   }
   void test_parseGetter_static() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     Token staticKeyword = TokenFactory.token(Keyword.STATIC);
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     MethodDeclaration method = ParserTestCase.parse("parseGetter", <Object> [commentAndMetadata(comment, []), null, staticKeyword, returnType], "get a;");
@@ -3096,7 +3096,7 @@
     JUnitTestCase.assertNotNull(directive.semicolon);
   }
   void test_parseInitializedIdentifierList_type() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     Token staticKeyword = TokenFactory.token(Keyword.STATIC);
     TypeName type = new TypeName.full(new SimpleIdentifier.full(null), null);
     FieldDeclaration declaration = ParserTestCase.parse("parseInitializedIdentifierList", <Object> [commentAndMetadata(comment, []), staticKeyword, null, type], "a = 1, b, c = 3;");
@@ -3110,7 +3110,7 @@
     JUnitTestCase.assertNotNull(declaration.semicolon);
   }
   void test_parseInitializedIdentifierList_var() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     Token staticKeyword = TokenFactory.token(Keyword.STATIC);
     Token varKeyword = TokenFactory.token(Keyword.VAR);
     FieldDeclaration declaration = ParserTestCase.parse("parseInitializedIdentifierList", <Object> [commentAndMetadata(comment, []), staticKeyword, varKeyword, null], "a = 1, b, c = 3;");
@@ -3515,7 +3515,7 @@
     JUnitTestCase.assertNotNull(parameter.identifier);
   }
   void test_parseOperator() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     MethodDeclaration method = ParserTestCase.parse("parseOperator", <Object> [commentAndMetadata(comment, []), null, returnType], "operator +(A a);");
     JUnitTestCase.assertNotNull(method.body);
@@ -3759,7 +3759,7 @@
     JUnitTestCase.assertNull(typeName.typeArguments);
   }
   void test_parseSetter_nonStatic() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     MethodDeclaration method = ParserTestCase.parse("parseSetter", <Object> [commentAndMetadata(comment, []), null, null, returnType], "set a(var x);");
     JUnitTestCase.assertNotNull(method.body);
@@ -3773,7 +3773,7 @@
     JUnitTestCase.assertEquals(returnType, method.returnType);
   }
   void test_parseSetter_static() {
-    Comment comment = Comment.createDocumentationComment(new List<Token>.fixedLength(0));
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
     Token staticKeyword = TokenFactory.token(Keyword.STATIC);
     TypeName returnType = new TypeName.full(new SimpleIdentifier.full(null), null);
     MethodDeclaration method = ParserTestCase.parse("parseSetter", <Object> [commentAndMetadata(comment, []), null, staticKeyword, returnType], "set a(var x) {}");
diff --git a/pkg/analyzer-experimental/test/generated/scanner_test.dart b/pkg/analyzer-experimental/test/generated/scanner_test.dart
index 21ce0e8..8506de2 100644
--- a/pkg/analyzer-experimental/test/generated/scanner_test.dart
+++ b/pkg/analyzer-experimental/test/generated/scanner_test.dart
@@ -797,7 +797,7 @@
   void test_KeywordState() {
     List<Keyword> keywords = Keyword.values;
     int keywordCount = keywords.length;
-    List<String> textToTest = new List<String>.fixedLength(keywordCount * 3);
+    List<String> textToTest = new List<String>(keywordCount * 3);
     for (int i = 0; i < keywordCount; i++) {
       String syntax3 = keywords[i].syntax;
       textToTest[i] = syntax3;
diff --git a/pkg/analyzer-experimental/test/generated/test_support.dart b/pkg/analyzer-experimental/test/generated/test_support.dart
index a559098..987ff38 100644
--- a/pkg/analyzer-experimental/test/generated/test_support.dart
+++ b/pkg/analyzer-experimental/test/generated/test_support.dart
@@ -37,7 +37,7 @@
   /**
    * An empty array of errors used when no errors are expected.
    */
-  static List<AnalysisError> _NO_ERRORS = new List<AnalysisError>.fixedLength(0);
+  static List<AnalysisError> _NO_ERRORS = new List<AnalysisError>(0);
   /**
    * Initialize a newly created error listener to collect errors.
    */
@@ -351,7 +351,7 @@
     JUnitTestCase.assertNotNull(actualValues);
     int expectedLength = expectedValues.length;
     JUnitTestCase.assertEquals(expectedLength, actualValues.length);
-    List<bool> found = new List<bool>.fixedLength(expectedLength);
+    List<bool> found = new List<bool>(expectedLength);
     for (int i = 0; i < expectedLength; i++) {
       found[i] = false;
     }
diff --git a/pkg/args/lib/args.dart b/pkg/args/lib/args.dart
index 29da1e2..6bdcb7e 100644
--- a/pkg/args/lib/args.dart
+++ b/pkg/args/lib/args.dart
@@ -397,6 +397,6 @@
   }
 
   /** Get the names of the options as a [Collection]. */
-  Collection<String> get options => _options.keys.toList();
+  Collection<String> get options => _options.keys.toList(growable: false);
 }
 
diff --git a/pkg/args/lib/src/usage.dart b/pkg/args/lib/src/usage.dart
index b83a2d5..45893a5 100644
--- a/pkg/args/lib/src/usage.dart
+++ b/pkg/args/lib/src/usage.dart
@@ -73,7 +73,7 @@
       if (option.help != null) write(2, option.help);
 
       if (option.allowedHelp != null) {
-        var allowedNames = option.allowedHelp.keys.toList();
+        var allowedNames = option.allowedHelp.keys.toList(growable: false);
         allowedNames.sort();
         newline();
         for (var name in allowedNames) {
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index 2aad272..02eb213 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -38,12 +38,12 @@
   static int32 TWO = const int32._internal(2);
 
   // Hex digit char codes
-  static const int _CC_0 = 48; // '0'.charCodeAt(0)
-  static const int _CC_9 = 57; // '9'.charCodeAt(0)
-  static const int _CC_a = 97; // 'a'.charCodeAt(0)
-  static const int _CC_z = 122; // 'z'.charCodeAt(0)
-  static const int _CC_A = 65; // 'A'.charCodeAt(0)
-  static const int _CC_Z = 90; // 'Z'.charCodeAt(0)
+  static const int _CC_0 = 48; // '0'.codeUnitAt(0)
+  static const int _CC_9 = 57; // '9'.codeUnitAt(0)
+  static const int _CC_a = 97; // 'a'.codeUnitAt(0)
+  static const int _CC_z = 122; // 'z'.codeUnitAt(0)
+  static const int _CC_A = 65; // 'A'.codeUnitAt(0)
+  static const int _CC_Z = 90; // 'Z'.codeUnitAt(0)
 
   static int _decodeHex(int c) {
     if (c >= _CC_0 && c <= _CC_9) {
@@ -68,10 +68,10 @@
     }
     int32 x = ZERO;
     for (int i = 0; i < s.length; i++) {
-      int c = s.charCodeAt(i);
+      int c = s.codeUnitAt(i);
       int digit = _decodeHex(c);
       if (digit < 0 || digit >= radix) {
-        throw new Exception("Non-radix char code: $c");
+        throw new Exception("Non-radix code unit: $c");
       }
       x = (x * radix) + digit;
     }
@@ -288,7 +288,7 @@
     return _i == _convert(other);
   }
 
-  int compareTo(other) {
+  int compareTo(Comparable other) {
     if (other is int64) {
       return this.toInt64().compareTo(other);
     }
@@ -338,7 +338,7 @@
   int numberOfTrailingZeros() => _numberOfTrailingZeros(_i);
 
   List<int> toBytes() {
-    List<int> result = new List<int>.fixedLength(4);
+    List<int> result = new List<int>(4);
     result[0] = _i & 0xff;
     result[1] = (_i >> 8) & 0xff;
     result[2] = (_i >> 16) & 0xff;
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
index b2a263f..81607de 100644
--- a/pkg/fixnum/lib/src/int64.dart
+++ b/pkg/fixnum/lib/src/int64.dart
@@ -130,7 +130,7 @@
       i++;
     }
     for (; i < s.length; i++) {
-      int c = s.charCodeAt(i);
+      int c = s.codeUnitAt(i);
       int digit = int32._decodeHex(c);
       if (digit < 0 || digit >= radix) {
         throw new Exception("Non-radix char code: $c");
@@ -625,7 +625,7 @@
   }
 
   List<int> toBytes() {
-    List<int> result = new List<int>.fixedLength(8);
+    List<int> result = new List<int>(8);
     result[0] = _l & 0xff;
     result[1] = (_l >> 8) & 0xff;
     result[2] = ((_m << 6) & 0xfc) | ((_l >> 16) & 0x3f);
diff --git a/pkg/fixnum/test/int_64_vm_test.dart b/pkg/fixnum/test/int_64_vm_test.dart
index 03ce112..ee1fd74 100644
--- a/pkg/fixnum/test/int_64_vm_test.dart
+++ b/pkg/fixnum/test/int_64_vm_test.dart
@@ -174,7 +174,7 @@
       testSet.add(new int64.fromInt(pow));
     }
 
-    TEST_VALUES = new List<int64>.fixedLength(testSet.length);
+    TEST_VALUES = new List<int64>(testSet.length);
     int index = 0;
     for (int64 val in testSet) {
       TEST_VALUES[index++] = val;
diff --git a/pkg/http/lib/src/byte_stream.dart b/pkg/http/lib/src/byte_stream.dart
index f6d87ff..96af221 100644
--- a/pkg/http/lib/src/byte_stream.dart
+++ b/pkg/http/lib/src/byte_stream.dart
@@ -35,5 +35,5 @@
       toBytes().then((bytes) => decodeString(bytes, encoding));
 
   Stream<String> toStringStream([Encoding encoding=Encoding.UTF_8]) =>
-      wrapStream(map((bytes) => decodeString(bytes, encoding)));
+      map((bytes) => decodeString(bytes, encoding));
 }
diff --git a/pkg/http/lib/src/multipart_file.dart b/pkg/http/lib/src/multipart_file.dart
index 50f4704..aa30fc3 100644
--- a/pkg/http/lib/src/multipart_file.dart
+++ b/pkg/http/lib/src/multipart_file.dart
@@ -7,6 +7,8 @@
 import 'dart:async';
 import 'dart:io';
 
+import '../../../../pkg/pathos/lib/path.dart' as path;
+
 import 'byte_stream.dart';
 import 'utils.dart';
 
@@ -78,14 +80,15 @@
   }
 
   // TODO(nweiz): Infer the content-type from the filename.
-  /// Creates a new [MultipartFile] from a [File].
+  /// Creates a new [MultipartFile] from a path to a file on disk.
   ///
-  /// [filename] defaults to the name of the file on disk. [contentType]
-  /// currently defaults to `application/octet-stream`, but in the future may be
-  /// inferred from [filename].
-  static Future<MultipartFile> fromFile(String field, File file,
+  /// [filename] defaults to the basename of [filePath]. [contentType] currently
+  /// defaults to `application/octet-stream`, but in the future may be inferred
+  /// from [filename].
+  static Future<MultipartFile> fromPath(String field, String filePath,
       {String filename, ContentType contentType}) {
-    if (filename == null) filename = new Path(file.name).filename;
+    if (filename == null) filename = path.basename(filePath);
+    var file = new File(filePath);
     return file.length().then((length) {
       var stream = new ByteStream(file.openRead());
       return new MultipartFile(field, stream, length,
diff --git a/pkg/http/lib/src/multipart_request.dart b/pkg/http/lib/src/multipart_request.dart
index b89c839..0855063 100644
--- a/pkg/http/lib/src/multipart_request.dart
+++ b/pkg/http/lib/src/multipart_request.dart
@@ -98,7 +98,7 @@
 
     void writeAscii(String string) {
       assert(isPlainAscii(string));
-      controller.add(string.charCodes);
+      controller.add(string.codeUnits);
     }
 
     writeUtf8(String string) => controller.add(encodeUtf8(string));
@@ -165,7 +165,7 @@
   /// [length].
   String _boundaryString(int length) {
     var prefix = "dart-http-boundary-";
-    var list = new List<int>.fixedLength(length - prefix.length);
+    var list = new List<int>(length - prefix.length);
     for (var i = 0; i < list.length; i++) {
       list[i] = _BOUNDARY_CHARACTERS[
           _random.nextInt(_BOUNDARY_CHARACTERS.length)];
diff --git a/pkg/http/lib/src/utils.dart b/pkg/http/lib/src/utils.dart
index 739a567..65c4799 100644
--- a/pkg/http/lib/src/utils.dart
+++ b/pkg/http/lib/src/utils.dart
@@ -111,7 +111,7 @@
 /// Converts [string] into a byte array according to [encoding].
 List<int> encodeString(String string, Encoding encoding) {
   // TODO(nweiz): implement this once issue 6284 is fixed.
-  return string.charCodes;
+  return string.codeUnits;
 }
 
 /// A regular expression that matches strings that are composed entirely of
@@ -149,65 +149,6 @@
   return pair.last;
 }
 
-// TODO(nweiz): remove this once issue 7785 is fixed.
-/// Wraps [stream] in a single-subscription [ByteStream] that emits the same
-/// data.
-ByteStream wrapInputStream(InputStream stream) {
-  if (stream.closed) return emptyStream;
-
-  var controller = new StreamController();
-  stream.onClosed = controller.close;
-  stream.onData = () => controller.add(stream.read());
-  stream.onError = (e) => controller.signalError(new AsyncError(e));
-  return new ByteStream(controller.stream);
-}
-
-// TODO(nweiz): remove this once issue 7785 is fixed.
-/// Wraps [stream] in a [StreamConsumer] so that [Stream]s can by piped into it
-/// using [Stream.pipe].
-StreamConsumer<List<int>, dynamic> wrapOutputStream(OutputStream stream) =>
-  new _OutputStreamConsumer(stream);
-
-/// A [StreamConsumer] that pipes data into an [OutputStream].
-class _OutputStreamConsumer implements StreamConsumer<List<int>, dynamic> {
-  final OutputStream _outputStream;
-
-  _OutputStreamConsumer(this._outputStream);
-
-  Future consume(Stream<List<int>> stream) {
-    // TODO(nweiz): we have to manually keep track of whether or not the
-    // completer has completed since the output stream could signal an error
-    // after close() has been called but before it has shut down internally. See
-    // the following TODO.
-    var completed = false;
-    var completer = new Completer();
-    stream.listen((data) {
-      // Writing empty data to a closed stream can cause errors.
-      if (data.isEmpty) return;
-
-      // TODO(nweiz): remove this try/catch when issue 7836 is fixed.
-      try {
-        _outputStream.write(data);
-      } catch (e, stack) {
-        if (!completed) completer.completeError(e, stack);
-        completed = true;
-      }
-    }, onDone: () => _outputStream.close());
-
-    _outputStream.onError = (e) {
-      if (!completed) completer.completeError(e);
-      completed = true;
-    };
-
-    _outputStream.onClosed = () {
-      if (!completed) completer.complete();
-      completed = true;
-    };
-
-    return completer.future;
-  }
-}
-
 // TODO(nweiz): remove this when issue 7786 is fixed.
 /// Pipes all data and errors from [stream] into [sink]. When [stream] is done,
 /// [sink] is closed and the returned [Future] is completed.
@@ -309,16 +250,3 @@
   }
   return nextElement(null);
 }
-
-// TODO(nweiz): remove this when issue 8310 is fixed.
-/// Returns a [Stream] identical to [stream], but piped through a new
-/// [StreamController]. This exists to work around issue 8310.
-Stream wrapStream(Stream stream) {
-  var controller = stream.isBroadcast
-      ? new StreamController.broadcast()
-      : new StreamController();
-  stream.listen(controller.add,
-      onError: (e) => controller.signalError(e),
-      onDone: controller.close);
-  return controller.stream;
-}
diff --git a/pkg/http/test/client_test.dart b/pkg/http/test/client_test.dart
index e101f28..27cd0b9 100644
--- a/pkg/http/test/client_test.dart
+++ b/pkg/http/test/client_test.dart
@@ -8,8 +8,8 @@
 import 'dart:uri';
 
 import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/src/utils.dart';
+import '../lib/src/utils.dart';
+import '../lib/http.dart' as http;
 import 'utils.dart';
 
 void main() {
@@ -41,7 +41,7 @@
         'body': '{"hello": "world"}'
       }))));
 
-      request.sink.add('{"hello": "world"}'.charCodes);
+      request.sink.add('{"hello": "world"}'.codeUnits);
       request.sink.close();
     }), completes);
   });
@@ -56,7 +56,7 @@
 
       expect(client.send(request), throwsSocketIOException);
 
-      request.sink.add('{"hello": "world"}'.charCodes);
+      request.sink.add('{"hello": "world"}'.codeUnits);
       request.sink.close();
     }), completes);
   });
diff --git a/pkg/http/test/http_test.dart b/pkg/http/test/http_test.dart
index 9c567cf..1fc7f57 100644
--- a/pkg/http/test/http_test.dart
+++ b/pkg/http/test/http_test.dart
@@ -7,7 +7,7 @@
 import 'dart:io';
 
 import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
+import '../lib/http.dart' as http;
 import 'utils.dart';
 
 main() {
diff --git a/pkg/http/test/mock_client_test.dart b/pkg/http/test/mock_client_test.dart
index 59be93f..0c3c578 100644
--- a/pkg/http/test/mock_client_test.dart
+++ b/pkg/http/test/mock_client_test.dart
@@ -10,9 +10,9 @@
 import 'dart:uri';
 
 import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/testing.dart';
-import 'package:http/src/utils.dart';
+import '../lib/http.dart' as http;
+import '../lib/testing.dart';
+import '../lib/src/utils.dart';
 import 'utils.dart';
 
 void main() {
@@ -37,7 +37,7 @@
       return bodyStream.bytesToString().then((bodyString) {
         var controller = new StreamController<List<int>>();
         async.then((_) {
-          controller.add('Request body was "$bodyString"'.charCodes);
+          controller.add('Request body was "$bodyString"'.codeUnits);
           controller.close();
         });
 
diff --git a/pkg/http/test/multipart_test.dart b/pkg/http/test/multipart_test.dart
index 64fd330..c3c3dd9 100644
--- a/pkg/http/test/multipart_test.dart
+++ b/pkg/http/test/multipart_test.dart
@@ -8,11 +8,10 @@
 import 'dart:io';
 import 'dart:utf';
 
-// TODO(nweiz): get rid of this import before packaging this
-import '../../../tests/utils/test_utils.dart';
 import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/src/utils.dart';
+import '../../pathos/lib/path.dart' as path;
+import '../lib/http.dart' as http;
+import '../lib/src/utils.dart';
 
 import 'utils.dart';
 
@@ -204,4 +203,33 @@
         --{{boundary}}--
         '''));
   });
+
+  group('in a temp directory', () {
+    var tempDir;
+    setUp(() {
+      tempDir = new Directory('').createTempSync();
+    });
+
+    tearDown(() => tempDir.deleteSync(recursive: true));
+
+    test('with a file from disk', () {
+      expect(new Future.of(() {
+        var filePath = path.join(tempDir.path, 'test-file');
+        new File(filePath).writeAsStringSync('hello');
+        return http.MultipartFile.fromPath('file', filePath);
+      }).then((file) {
+        var request = new http.MultipartRequest('POST', dummyUrl);
+        request.files.add(file);
+
+        expect(request, bodyMatches('''
+        --{{boundary}}
+        content-type: application/octet-stream
+        content-disposition: form-data; name="file"; filename="test-file"
+
+        hello
+        --{{boundary}}--
+        '''));
+      }), completes);
+    });
+  });
 }
diff --git a/pkg/http/test/request_test.dart b/pkg/http/test/request_test.dart
index 1f009b9..551f694 100644
--- a/pkg/http/test/request_test.dart
+++ b/pkg/http/test/request_test.dart
@@ -7,8 +7,8 @@
 import 'dart:io';
 
 import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/src/utils.dart';
+import '../lib/http.dart' as http;
+import '../lib/src/utils.dart';
 import 'utils.dart';
 
 void main() {
diff --git a/pkg/http/test/response_test.dart b/pkg/http/test/response_test.dart
index 252df4a..097e0f8 100644
--- a/pkg/http/test/response_test.dart
+++ b/pkg/http/test/response_test.dart
@@ -8,7 +8,7 @@
 import 'dart:io';
 
 import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
+import '../lib/http.dart' as http;
 
 void main() {
   group('()', () {
diff --git a/pkg/http/test/streamed_request_test.dart b/pkg/http/test/streamed_request_test.dart
index 4ded631..6a62bdc 100644
--- a/pkg/http/test/streamed_request_test.dart
+++ b/pkg/http/test/streamed_request_test.dart
@@ -7,7 +7,7 @@
 import 'dart:io';
 
 import 'package:unittest/unittest.dart';
-import 'package:http/http.dart' as http;
+import '../lib/http.dart' as http;
 import 'utils.dart';
 
 void main() {
diff --git a/pkg/http/test/utils.dart b/pkg/http/test/utils.dart
index 606bb77..8b404a5 100644
--- a/pkg/http/test/utils.dart
+++ b/pkg/http/test/utils.dart
@@ -10,9 +10,9 @@
 import 'dart:uri';
 
 import 'package:unittest/unittest.dart';
-import 'package:http/src/byte_stream.dart';
-import 'package:http/http.dart' as http;
-import 'package:http/src/utils.dart';
+import '../lib/src/byte_stream.dart';
+import '../lib/http.dart' as http;
+import '../lib/src/utils.dart';
 
 /// The current server instance.
 HttpServer _server;
@@ -109,6 +109,33 @@
   _server = null;
 }
 
+/// Removes eight spaces of leading indentation from a multiline string.
+///
+/// Note that this is very sensitive to how the literals are styled. They should
+/// be:
+///     '''
+///     Text starts on own line. Lines up with subsequent lines.
+///     Lines are indented exactly 8 characters from the left margin.
+///     Close is on the same line.'''
+///
+/// This does nothing if text is only a single line.
+// TODO(nweiz): Make this auto-detect the indentation level from the first
+// non-whitespace line.
+String cleanUpLiteral(String text) {
+  var lines = text.split('\n');
+  if (lines.length <= 1) return text;
+
+  for (var j = 0; j < lines.length; j++) {
+    if (lines[j].length > 8) {
+      lines[j] = lines[j].substring(8, lines[j].length);
+    } else {
+      lines[j] = '';
+    }
+  }
+
+  return lines.join('\n');
+}
+
 /// A matcher that matches JSON that parses to a value that matches the inner
 /// matcher.
 Matcher parse(matcher) => new _Parse(matcher);
diff --git a/pkg/intl/lib/bidi_utils.dart b/pkg/intl/lib/bidi_utils.dart
index 35d62b7..e4599da 100644
--- a/pkg/intl/lib/bidi_utils.dart
+++ b/pkg/intl/lib/bidi_utils.dart
@@ -244,11 +244,11 @@
       var startIndex = 0;
       Match match = new RegExp('<\\w+').firstMatch(html);
       if (match != null) {
-        buffer..add(html.substring(startIndex, match.end))
-              ..add(' dir=$direction');
+        buffer..write(html.substring(startIndex, match.end))
+              ..write(' dir=$direction');
         startIndex = match.end;
       }
-      return (buffer..add(html.substring(startIndex))).toString();
+      return (buffer..write(html.substring(startIndex))).toString();
     }
     // '\n' is important for FF so that it won't incorrectly merge span groups.
     return '\n<span dir=$direction>$html</span>';
@@ -298,13 +298,13 @@
     var startIndex = 0;
     Iterable matches = regexp.allMatches(str);
     for (Match match in matches) {
-      buffer..add(str.substring(startIndex, match.start))
-            ..add(before)
-            ..add(str.substring(match.start, match.end))
-            ..add(after);
+      buffer..write(str.substring(startIndex, match.start))
+            ..write(before)
+            ..write(str.substring(match.start, match.end))
+            ..write(after);
       startIndex = match.end;
     }
-    return (buffer..add(str.substring(startIndex))).toString();
+    return (buffer..write(str.substring(startIndex))).toString();
   }
 
   /**
@@ -359,19 +359,19 @@
   static String normalizeHebrewQuote(String str) {
     StringBuffer buf = new StringBuffer();
     if (str.length > 0) {
-      buf.add(str.substring(0, 1));
+      buf.write(str.substring(0, 1));
     }
     // Start at 1 because we're looking for the patterns [\u0591-\u05f2])" or
     // [\u0591-\u05f2]'.
     for (int i = 1; i < str.length; i++) {
       if (str.substring(i, i+1) == '"'
           && new RegExp('[\u0591-\u05f2]').hasMatch(str.substring(i-1, i))) {
-        buf.add('\u05f4');
+        buf.write('\u05f4');
       } else if (str.substring(i, i+1) == "'"
           && new RegExp('[\u0591-\u05f2]').hasMatch(str.substring(i-1, i))) {
-        buf.add('\u05f3');
+        buf.write('\u05f3');
       } else {
-        buf.add(str.substring(i, i+1));
+        buf.write(str.substring(i, i+1));
       }
     }
     return buf.toString();
diff --git a/pkg/intl/lib/date_format.dart b/pkg/intl/lib/date_format.dart
index 4c9ee28..a0d964f 100644
--- a/pkg/intl/lib/date_format.dart
+++ b/pkg/intl/lib/date_format.dart
@@ -225,7 +225,7 @@
   String format(DateTime date) {
     // TODO(efortuna): read optional TimeZone argument (or similar)?
     var result = new StringBuffer();
-    _formatFields.forEach((field) => result.add(field.format(date)));
+    _formatFields.forEach((field) => result.write(field.format(date)));
     return result.toString();
   }
 
diff --git a/pkg/intl/lib/number_format.dart b/pkg/intl/lib/number_format.dart
index 76f8afa..567fb99 100644
--- a/pkg/intl/lib/number_format.dart
+++ b/pkg/intl/lib/number_format.dart
@@ -166,10 +166,10 @@
     // to be printed as an integer and pad the remainder with zeros.
     var paddingDigits = new StringBuffer();
     while ((intValue & 0x7fffffff) != intValue) {
-      paddingDigits.add(symbols.ZERO_DIGIT);
+      paddingDigits.write(symbols.ZERO_DIGIT);
       intValue = intValue ~/ 10;
     }
-    var integerDigits = "${intValue}${paddingDigits}".charCodes;
+    var integerDigits = "${intValue}${paddingDigits}".codeUnits;
     var digitLength = integerDigits.length;
 
     if (_hasPrintableIntegerPart(intValue)) {
@@ -191,7 +191,7 @@
    * Format the part after the decimal place in a fixed point number.
    */
   void _formatFractionPart(String fractionPart) {
-    var fractionCodes = fractionPart.charCodes;
+    var fractionCodes = fractionPart.codeUnits;
     var fractionLength = fractionPart.length;
     while (fractionPart[fractionLength - 1] == '0' &&
            fractionLength > _minimumFractionDigits + 1) {
@@ -227,17 +227,17 @@
   /** A group of methods that provide support for writing digits and other
    * required characters into [_buffer] easily.
    */
-  void _add(String x) { _buffer.add(x);}
-  void _addCharCode(int x) { _buffer.addCharCode(x); }
-  void _addZero() { _buffer.add(symbols.ZERO_DIGIT); }
-  void _addDigit(int x) { _buffer.addCharCode(_localeZero + x - _zero); }
+  void _add(String x) { _buffer.write(x);}
+  void _addCharCode(int x) { _buffer.writeCharCode(x); }
+  void _addZero() { _buffer.write(symbols.ZERO_DIGIT); }
+  void _addDigit(int x) { _buffer.writeCharCode(_localeZero + x - _zero); }
 
   /** Print padding up to [numberOfDigits] above what's included in [basic]. */
   void _pad(int numberOfDigits, [String basic = '']) {
     for (var i = 0; i < numberOfDigits - basic.length; i++) {
       _add(symbols.ZERO_DIGIT);
     }
-    for (var x in basic.charCodes) {
+    for (var x in basic.codeUnits) {
       _addDigit(x);
     }
   }
diff --git a/pkg/intl/lib/src/date_format_field.dart b/pkg/intl/lib/src/date_format_field.dart
index 1d37490..843b6dc 100644
--- a/pkg/intl/lib/src/date_format_field.dart
+++ b/pkg/intl/lib/src/date_format_field.dart
@@ -398,9 +398,9 @@
     if (basicString.length >= width) return basicString;
     var buffer = new StringBuffer();
     for (var i = 0; i < width - basicString.length; i++) {
-      buffer.add('0');
+      buffer.write('0');
      }
-    buffer.add(basicString);
+    buffer.write(basicString);
     return buffer.toString();
   }
 }
diff --git a/pkg/logging/lib/logging.dart b/pkg/logging/lib/logging.dart
index 935b3ae..1bf617c 100644
--- a/pkg/logging/lib/logging.dart
+++ b/pkg/logging/lib/logging.dart
@@ -9,6 +9,10 @@
  */
 library logging;
 
+import 'dart:async';
+
+import '../../meta/lib/meta.dart';
+
 /**
  * Whether to allow fine-grain logging and configuration of loggers in a
  * hierarchy. When false, all logging is merged in the root logger.
@@ -43,8 +47,11 @@
   /** Children in the hierarchy of loggers, indexed by their simple names. */
   Map<String, Logger> children;
 
-  /** Handlers used to process log entries in this logger. */
-  List<LoggerHandler> _handlers;
+  /** Controller used to notify when log entries are added to this logger. */
+  StreamController<LogRecord> _controller;
+
+  // TODO(sigmund): remove together with the deprecated [on] API.
+  Map<LoggerHandler, StreamSubscription> _deprecatedSubscriptions;
 
   /**
    * Singleton constructor. Calling `new Logger(name)` will return the same
@@ -91,7 +98,7 @@
   }
 
   /** Override the level for this particular [Logger] and its children. */
-  set level(value) {
+  set level(Level value) {
     if (hierarchicalLoggingEnabled && parent != null) {
       _level = value;
     } else {
@@ -109,38 +116,27 @@
    * by adding a [LoggerHandler] to an event from the event manager, for
    * instance:
    *    logger.on.record.add((record) { ... });
+   *
+   * This API is Deprecated. Use [onRecord] instead.
    */
+  @deprecated
   LoggerEvents get on => new LoggerEvents(this);
 
-  /** Adds a handler to listen whenever a log record is added to this logger. */
-  void _addHandler(LoggerHandler handler) {
+  /**
+   * Returns an stream of messages added to this [Logger]. You can listen for
+   * messages using the standard stream APIs, for instance:
+   *    logger.onRecord.listen((record) { ... });
+   */
+  Stream<LogRecord> get onRecord => _getStream();
+
+  void clearListeners() {
     if (hierarchicalLoggingEnabled || parent == null) {
-      if (_handlers == null) {
-        _handlers = new List<LoggerHandler>();
+      if (_controller != null) {
+        _controller.close();
+        _controller = null;
       }
-      _handlers.add(handler);
     } else {
-      root._addHandler(handler);
-    }
-  }
-
-  /** Remove a previously added handler. */
-  void _removeHandler(LoggerHandler handler) {
-    if (hierarchicalLoggingEnabled || parent == null) {
-      if (_handlers == null) return;
-      int index = _handlers.indexOf(handler);
-      if (index != -1) _handlers.removeRange(index, 1);
-    } else {
-      root._removeHandler(handler);
-    }
-  }
-
-  /** Removes all handlers previously added to this logger. */
-  void _clearHandlers() {
-    if (hierarchicalLoggingEnabled || parent == null) {
-      _handlers = null;
-    } else {
-      root._clearHandlers();
+      root.clearListeners();
     }
   }
 
@@ -194,14 +190,46 @@
   /** Log message at level [Level.SHOUT]. */
   void shout(String message) => log(Level.SHOUT, message);
 
+  Stream<LogRecord> _getStream() {
+    if (hierarchicalLoggingEnabled || parent == null) {
+      if (_controller == null) {
+        _controller = new StreamController<LogRecord>.broadcast();
+      }
+      return _controller.stream;
+    } else {
+      return root._getStream();
+    }
+  }
+
+  /** Adds a handler to listen whenever a log record is added to this logger. */
+  void _addHandler(LoggerHandler handler) {
+    if (_deprecatedSubscriptions == null) {
+      _deprecatedSubscriptions = new Map<LoggerHandler, StreamSubscription>();
+    }
+
+    _deprecatedSubscriptions[handler] = onRecord.listen(handler);
+  }
+
+  void _removeHandler(LoggerHandler handler) {
+    if (_deprecatedSubscriptions != null) {
+      var sub = _deprecatedSubscriptions.remove(handler);
+      if (sub != null) {
+        sub.cancel();
+      }
+      if (_deprecatedSubscriptions.isEmpty) {
+        _deprecatedSubscriptions = null;
+      }
+    }
+  }
+
   void _publish(LogRecord record) {
-    if (_handlers != null) {
-      _handlers.forEach((h) => h(record));
+    if (_controller != null) {
+      _controller.add(record);
     }
   }
 
   /** Top-level root [Logger]. */
-  static get root => new Logger('');
+  static Logger get root => new Logger('');
 
   /** All [Logger]s in the system. */
   static Map<String, Logger> _loggers;
@@ -231,7 +259,7 @@
 
   void add(LoggerHandler handler) => _logger._addHandler(handler);
   void remove(LoggerHandler handler) => _logger._removeHandler(handler);
-  void clear() => _logger._clearHandlers();
+  void clear() => _logger.clearListeners();
 }
 
 
diff --git a/pkg/logging/pubspec.yaml b/pkg/logging/pubspec.yaml
index 208667b..6e6a540 100644
--- a/pkg/logging/pubspec.yaml
+++ b/pkg/logging/pubspec.yaml
@@ -8,5 +8,7 @@
  Logger and java.util.logging.Logger.
 
 dependencies:
+  meta:
+    sdk: meta
   unittest:
     sdk: unittest
diff --git a/pkg/logging/test/logging_deprecated_test.dart b/pkg/logging/test/logging_deprecated_test.dart
new file mode 100644
index 0000000..10ab616
--- /dev/null
+++ b/pkg/logging/test/logging_deprecated_test.dart
@@ -0,0 +1,336 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+
+library logging_test;
+
+import '../../../pkg/logging/lib/logging.dart';
+import 'package:unittest/unittest.dart';
+
+main() {
+  test('level comparison is a valid comparator', () {
+    var level1 = const Level('NOT_REAL1', 253);
+    expect(level1 == level1, isTrue);
+    expect(level1 <= level1, isTrue);
+    expect(level1 >= level1, isTrue);
+    expect(level1 < level1, isFalse);
+    expect(level1 > level1, isFalse);
+
+    var level2 = const Level('NOT_REAL2', 455);
+    expect(level1 <= level2, isTrue);
+    expect(level1 < level2, isTrue);
+    expect(level2 >= level1, isTrue);
+    expect(level2 > level1, isTrue);
+
+    var level3 = const Level('NOT_REAL3', 253);
+    expect(!identical(level1, level3), isTrue); // different instances
+    expect(level1 == level3, isTrue); // same value.
+  });
+
+  test('default levels are in order', () {
+    final levels = const [
+        Level.ALL, Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG,
+        Level.INFO, Level.WARNING, Level.SEVERE, Level.SHOUT, Level.OFF
+      ];
+
+    for (int i = 0; i < levels.length; i++) {
+      for (int j = i + 1; j < levels.length; j++) {
+        expect(levels[i] < levels[j], isTrue);
+      }
+    }
+  });
+
+  test('levels are comparable', () {
+    final unsorted = [
+        Level.INFO, Level.CONFIG, Level.FINE, Level.SHOUT, Level.OFF,
+        Level.FINER, Level.ALL, Level.WARNING, Level.FINEST,  Level.SEVERE,
+      ];
+    final sorted = const [
+        Level.ALL, Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG,
+        Level.INFO, Level.WARNING, Level.SEVERE, Level.SHOUT, Level.OFF
+      ];
+    expect(unsorted, isNot(orderedEquals(sorted)));
+
+    unsorted.sort((a, b) => a.compareTo(b));
+    expect(unsorted, orderedEquals(sorted));
+  });
+
+  test('levels are hashable', () {
+    var map = new Map<Level, String>();
+    map[Level.INFO] = 'info';
+    map[Level.SHOUT] = 'shout';
+    expect(map[Level.INFO], equals('info'));
+    expect(map[Level.SHOUT], equals('shout'));
+  });
+
+  test('logger name cannot start with a "." ', () {
+    expect(() => new Logger('.c'), throws);
+  });
+
+  test('logger naming is hierarchical', () {
+    Logger c = new Logger('a.b.c');
+    expect(c.name, equals('c'));
+    expect(c.parent.name, equals('b'));
+    expect(c.parent.parent.name, equals('a'));
+    expect(c.parent.parent.parent.name, equals(''));
+    expect(c.parent.parent.parent.parent, isNull);
+  });
+
+  test('logger full name', () {
+    Logger c = new Logger('a.b.c');
+    expect(c.fullName, equals('a.b.c'));
+    expect(c.parent.fullName, equals('a.b'));
+    expect(c.parent.parent.fullName, equals('a'));
+    expect(c.parent.parent.parent.fullName, equals(''));
+    expect(c.parent.parent.parent.parent, isNull);
+  });
+
+  test('logger parent-child links are correct', () {
+    Logger a = new Logger('a');
+    Logger b = new Logger('a.b');
+    Logger c = new Logger('a.c');
+    expect(a == b.parent, isTrue);
+    expect(a == c.parent, isTrue);
+    expect(a.children['b'] == b, isTrue);
+    expect(a.children['c'] == c, isTrue);
+  });
+
+  test('loggers are singletons', () {
+    Logger a1 = new Logger('a');
+    Logger a2 = new Logger('a');
+    Logger b = new Logger('a.b');
+    Logger root = Logger.root;
+    expect(identical(a1, a2), isTrue);
+    expect(identical(a1, b.parent), isTrue);
+    expect(identical(root, a1.parent), isTrue);
+    expect(identical(root, new Logger('')), isTrue);
+  });
+
+  group('mutating levels', () {
+    Logger root = Logger.root;
+    Logger a = new Logger('a');
+    Logger b = new Logger('a.b');
+    Logger c = new Logger('a.b.c');
+    Logger d = new Logger('a.b.c.d');
+    Logger e = new Logger('a.b.c.d.e');
+
+    setUp(() {
+      hierarchicalLoggingEnabled = true;
+      root.level = Level.INFO;
+      a.level = null;
+      b.level = null;
+      c.level = null;
+      d.level = null;
+      e.level = null;
+      root.on.record.clear();
+      a.on.record.clear();
+      b.on.record.clear();
+      c.on.record.clear();
+      d.on.record.clear();
+      e.on.record.clear();
+      hierarchicalLoggingEnabled = false;
+      root.level = Level.INFO;
+    });
+
+    test('cannot set level if hierarchy is disabled', () {
+      expect(() {a.level = Level.FINE;}, throws);
+    });
+
+    test('loggers effective level - no hierarchy', () {
+      expect(root.level, equals(Level.INFO));
+      expect(a.level, equals(Level.INFO));
+      expect(b.level, equals(Level.INFO));
+
+      root.level = Level.SHOUT;
+
+      expect(root.level, equals(Level.SHOUT));
+      expect(a.level, equals(Level.SHOUT));
+      expect(b.level, equals(Level.SHOUT));
+    });
+
+    test('loggers effective level - with hierarchy', () {
+      hierarchicalLoggingEnabled = true;
+      expect(root.level, equals(Level.INFO));
+      expect(a.level, equals(Level.INFO));
+      expect(b.level, equals(Level.INFO));
+      expect(c.level, equals(Level.INFO));
+
+      root.level = Level.SHOUT;
+      b.level = Level.FINE;
+
+      expect(root.level, equals(Level.SHOUT));
+      expect(a.level, equals(Level.SHOUT));
+      expect(b.level, equals(Level.FINE));
+      expect(c.level, equals(Level.FINE));
+    });
+
+    test('isLoggable is appropriate', () {
+      hierarchicalLoggingEnabled = true;
+      root.level = Level.SEVERE;
+      c.level = Level.ALL;
+      e.level = Level.OFF;
+
+      expect(root.isLoggable(Level.SHOUT), isTrue);
+      expect(root.isLoggable(Level.SEVERE), isTrue);
+      expect(root.isLoggable(Level.WARNING), isFalse);
+      expect(c.isLoggable(Level.FINEST), isTrue);
+      expect(c.isLoggable(Level.FINE), isTrue);
+      expect(!e.isLoggable(Level.SHOUT), isTrue);
+    });
+
+    test('add/remove handlers - no hierarchy', () {
+      int calls = 0;
+      var handler = (_) { calls++; };
+      c.on.record.add(handler);
+      root.info("foo");
+      root.info("foo");
+      expect(calls, equals(2));
+      c.on.record.remove(handler);
+      root.info("foo");
+      expect(calls, equals(2));
+    });
+
+    test('add/remove handlers - with hierarchy', () {
+      hierarchicalLoggingEnabled = true;
+      int calls = 0;
+      var handler = (_) { calls++; };
+      c.on.record.add(handler);
+      root.info("foo");
+      root.info("foo");
+      expect(calls, equals(0));
+    });
+
+    test('logging methods store appropriate level', () {
+      root.level = Level.ALL;
+      var rootMessages = [];
+      root.on.record.add((record) {
+        rootMessages.add('${record.level}: ${record.message}');
+      });
+
+      root.finest('1');
+      root.finer('2');
+      root.fine('3');
+      root.config('4');
+      root.info('5');
+      root.warning('6');
+      root.severe('7');
+      root.shout('8');
+
+      expect(rootMessages, equals([
+        'FINEST: 1',
+        'FINER: 2',
+        'FINE: 3',
+        'CONFIG: 4',
+        'INFO: 5',
+        'WARNING: 6',
+        'SEVERE: 7',
+        'SHOUT: 8']));
+    });
+
+    test('message logging - no hierarchy', () {
+      root.level = Level.WARNING;
+      var rootMessages = [];
+      var aMessages = [];
+      var cMessages = [];
+      c.on.record.add((record) {
+        cMessages.add('${record.level}: ${record.message}');
+      });
+      a.on.record.add((record) {
+        aMessages.add('${record.level}: ${record.message}');
+      });
+      root.on.record.add((record) {
+        rootMessages.add('${record.level}: ${record.message}');
+      });
+
+      root.info('1');
+      root.fine('2');
+      root.shout('3');
+
+      b.info('4');
+      b.severe('5');
+      b.warning('6');
+      b.fine('7');
+
+      c.fine('8');
+      c.warning('9');
+      c.shout('10');
+
+      expect(rootMessages, equals([
+            // 'INFO: 1' is not loggable
+            // 'FINE: 2' is not loggable
+            'SHOUT: 3',
+            // 'INFO: 4' is not loggable
+            'SEVERE: 5',
+            'WARNING: 6',
+            // 'FINE: 7' is not loggable
+            // 'FINE: 8' is not loggable
+            'WARNING: 9',
+            'SHOUT: 10']));
+
+      // no hierarchy means we all hear the same thing.
+      expect(aMessages, equals(rootMessages));
+      expect(cMessages, equals(rootMessages));
+    });
+
+    test('message logging - with hierarchy', () {
+      hierarchicalLoggingEnabled = true;
+
+      b.level = Level.WARNING;
+
+      var rootMessages = [];
+      var aMessages = [];
+      var cMessages = [];
+      c.on.record.add((record) {
+        cMessages.add('${record.level}: ${record.message}');
+      });
+      a.on.record.add((record) {
+        aMessages.add('${record.level}: ${record.message}');
+      });
+      root.on.record.add((record) {
+        rootMessages.add('${record.level}: ${record.message}');
+      });
+
+      root.info('1');
+      root.fine('2');
+      root.shout('3');
+
+      b.info('4');
+      b.severe('5');
+      b.warning('6');
+      b.fine('7');
+
+      c.fine('8');
+      c.warning('9');
+      c.shout('10');
+
+      expect(rootMessages, equals([
+            'INFO: 1',
+            // 'FINE: 2' is not loggable
+            'SHOUT: 3',
+            // 'INFO: 4' is not loggable
+            'SEVERE: 5',
+            'WARNING: 6',
+            // 'FINE: 7' is not loggable
+            // 'FINE: 8' is not loggable
+            'WARNING: 9',
+            'SHOUT: 10']));
+
+      expect(aMessages, equals([
+            // 1,2 and 3 are lower in the hierarchy
+            // 'INFO: 4' is not loggable
+            'SEVERE: 5',
+            'WARNING: 6',
+            // 'FINE: 7' is not loggable
+            // 'FINE: 8' is not loggable
+            'WARNING: 9',
+            'SHOUT: 10']));
+
+      expect(cMessages, equals([
+            // 1 - 7 are lower in the hierarchy
+            // 'FINE: 8' is not loggable
+            'WARNING: 9',
+            'SHOUT: 10']));
+    });
+  });
+}
diff --git a/pkg/logging/test/logging_test.dart b/pkg/logging/test/logging_test.dart
index 6444e3a..5102c42 100644
--- a/pkg/logging/test/logging_test.dart
+++ b/pkg/logging/test/logging_test.dart
@@ -5,7 +5,7 @@
 
 library logging_test;
 
-import 'package:logging/logging.dart';
+import '../../../pkg/logging/lib/logging.dart';
 import 'package:unittest/unittest.dart';
 
 main() {
@@ -123,12 +123,12 @@
       c.level = null;
       d.level = null;
       e.level = null;
-      root.on.record.clear();
-      a.on.record.clear();
-      b.on.record.clear();
-      c.on.record.clear();
-      d.on.record.clear();
-      e.on.record.clear();
+      root.clearListeners();
+      a.clearListeners();
+      b.clearListeners();
+      c.clearListeners();
+      d.clearListeners();
+      e.clearListeners();
       hierarchicalLoggingEnabled = false;
       root.level = Level.INFO;
     });
@@ -182,11 +182,11 @@
     test('add/remove handlers - no hierarchy', () {
       int calls = 0;
       var handler = (_) { calls++; };
-      c.on.record.add(handler);
+      final sub = c.onRecord.listen(handler);
       root.info("foo");
       root.info("foo");
       expect(calls, equals(2));
-      c.on.record.remove(handler);
+      sub.cancel();
       root.info("foo");
       expect(calls, equals(2));
     });
@@ -195,7 +195,7 @@
       hierarchicalLoggingEnabled = true;
       int calls = 0;
       var handler = (_) { calls++; };
-      c.on.record.add(handler);
+      c.onRecord.listen(handler);
       root.info("foo");
       root.info("foo");
       expect(calls, equals(0));
@@ -204,7 +204,7 @@
     test('logging methods store appropriate level', () {
       root.level = Level.ALL;
       var rootMessages = [];
-      root.on.record.add((record) {
+      root.onRecord.listen((record) {
         rootMessages.add('${record.level}: ${record.message}');
       });
 
@@ -233,13 +233,13 @@
       var rootMessages = [];
       var aMessages = [];
       var cMessages = [];
-      c.on.record.add((record) {
+      c.onRecord.listen((record) {
         cMessages.add('${record.level}: ${record.message}');
       });
-      a.on.record.add((record) {
+      a.onRecord.listen((record) {
         aMessages.add('${record.level}: ${record.message}');
       });
-      root.on.record.add((record) {
+      root.onRecord.listen((record) {
         rootMessages.add('${record.level}: ${record.message}');
       });
 
@@ -281,13 +281,13 @@
       var rootMessages = [];
       var aMessages = [];
       var cMessages = [];
-      c.on.record.add((record) {
+      c.onRecord.listen((record) {
         cMessages.add('${record.level}: ${record.message}');
       });
-      a.on.record.add((record) {
+      a.onRecord.listen((record) {
         aMessages.add('${record.level}: ${record.message}');
       });
-      root.on.record.add((record) {
+      root.onRecord.listen((record) {
         rootMessages.add('${record.level}: ${record.message}');
       });
 
diff --git a/pkg/oauth2/lib/src/credentials.dart b/pkg/oauth2/lib/src/credentials.dart
index 26112c6..acc5690 100644
--- a/pkg/oauth2/lib/src/credentials.dart
+++ b/pkg/oauth2/lib/src/credentials.dart
@@ -50,7 +50,8 @@
   /// credentials will expire shortly after this is called. However, since the
   /// client's expiration date is kept a few seconds earlier than the server's,
   /// there should be enough leeway to rely on this.
-  bool get isExpired => expiration != null && new DateTime.now() > expiration;
+  bool get isExpired => expiration != null &&
+      new DateTime.now().isAfter(expiration);
 
   /// Whether it's possible to refresh these credentials.
   bool get canRefresh => refreshToken != null && tokenEndpoint != null;
diff --git a/pkg/path/README.md b/pkg/pathos/README.md
similarity index 100%
rename from pkg/path/README.md
rename to pkg/pathos/README.md
diff --git a/pkg/path/lib/path.dart b/pkg/pathos/lib/path.dart
similarity index 97%
rename from pkg/path/lib/path.dart
rename to pkg/pathos/lib/path.dart
index 9e540b2..0fe031d 100644
--- a/pkg/path/lib/path.dart
+++ b/pkg/pathos/lib/path.dart
@@ -194,11 +194,11 @@
 
     // Show the arguments.
     var message = new StringBuffer();
-    message.add("$method(");
-    message.add(args.take(numArgs)
+    message.write("$method(");
+    message.write(args.take(numArgs)
         .map((arg) => arg == null ? "null" : '"$arg"')
         .join(", "));
-    message.add("): part ${i - 1} was null, but part $i was not.");
+    message.write("): part ${i - 1} was null, but part $i was not.");
     throw new ArgumentError(message.toString());
   }
 }
@@ -245,7 +245,7 @@
   ///
   /// Trailing separators are ignored.
   ///
-  ///     builder.dirname('path/to/'); // -> 'to'
+  ///     builder.basename('path/to/'); // -> 'to'
   String basename(String path) => _parse(path).basename;
 
   /// Gets the part of [path] after the last separator on the builder's
@@ -255,7 +255,7 @@
   ///
   /// Trailing separators are ignored.
   ///
-  ///     builder.dirname('path/to/foo.dart/'); // -> 'foo'
+  ///     builder.basenameWithoutExtension('path/to/foo.dart/'); // -> 'foo'
   String basenameWithoutExtension(String path) =>
     _parse(path).basenameWithoutExtension;
 
@@ -364,16 +364,16 @@
     for (var part in parts) {
       if (this.isAbsolute(part)) {
         // An absolute path discards everything before it.
-        buffer.clear();
-        buffer.add(part);
+        buffer = new StringBuffer();
+        buffer.write(part);
       } else {
         if (part.length > 0 && part[0].contains(style.separatorPattern)) {
           // The part starts with a separator, so we don't need to add one.
         } else if (needsSeparator) {
-          buffer.add(separator);
+          buffer.write(separator);
         }
 
-        buffer.add(part);
+        buffer.write(part);
       }
 
       // Unless this part ends with a separator, we'll need to add one before
@@ -406,7 +406,8 @@
   List<String> split(String path) {
     var parsed = _parse(path);
     // Filter out empty parts that exist due to multiple separators in a row.
-    parsed.parts = parsed.parts.where((part) => !part.isEmpty).toList();
+    parsed.parts = parsed.parts.where((part) => !part.isEmpty)
+                               .toList();
     if (parsed.root != null) parsed.parts.insertRange(0, 1, parsed.root);
     return parsed.parts;
   }
@@ -701,10 +702,10 @@
 
   String toString() {
     var builder = new StringBuffer();
-    if (root != null) builder.add(root);
+    if (root != null) builder.write(root);
     for (var i = 0; i < parts.length; i++) {
-      builder.add(parts[i]);
-      builder.add(separators[i]);
+      builder.write(parts[i]);
+      builder.write(separators[i]);
     }
 
     return builder.toString();
diff --git a/pkg/path/pubspec.yaml b/pkg/pathos/pubspec.yaml
similarity index 100%
rename from pkg/path/pubspec.yaml
rename to pkg/pathos/pubspec.yaml
diff --git a/pkg/path/test/path_posix_test.dart b/pkg/pathos/test/pathos_posix_test.dart
similarity index 99%
rename from pkg/path/test/path_posix_test.dart
rename to pkg/pathos/test/pathos_posix_test.dart
index 763035f..d6bfb91 100644
--- a/pkg/path/test/path_posix_test.dart
+++ b/pkg/pathos/test/pathos_posix_test.dart
@@ -2,12 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library path_test;
+library pathos_posix_test;
 
 import 'dart:io' as io;
 
 import 'package:unittest/unittest.dart';
-import 'package:path/path.dart' as path;
+import 'package:pathos/path.dart' as path;
 
 main() {
   var builder = new path.Builder(style: path.Style.posix, root: '/root/path');
diff --git a/pkg/path/test/path_test.dart b/pkg/pathos/test/pathos_test.dart
similarity index 95%
rename from pkg/path/test/path_test.dart
rename to pkg/pathos/test/pathos_test.dart
index eea906a..c820a47 100644
--- a/pkg/path/test/path_test.dart
+++ b/pkg/pathos/test/pathos_test.dart
@@ -2,12 +2,12 @@
 // for 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 all_test;
+library pathos_test;
 
 import 'dart:io' as io;
 
 import 'package:unittest/unittest.dart';
-import 'package:path/path.dart' as path;
+import 'package:pathos/path.dart' as path;
 
 main() {
   group('path.Style', () {
diff --git a/pkg/path/test/path_windows_test.dart b/pkg/pathos/test/pathos_windows_test.dart
similarity index 99%
rename from pkg/path/test/path_windows_test.dart
rename to pkg/pathos/test/pathos_windows_test.dart
index 8164224..8419b53 100644
--- a/pkg/path/test/path_windows_test.dart
+++ b/pkg/pathos/test/pathos_windows_test.dart
@@ -2,12 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library path_test;
+library pathos_windows_test;
 
 import 'dart:io' as io;
 
 import 'package:unittest/unittest.dart';
-import 'package:path/path.dart' as path;
+import 'package:pathos/path.dart' as path;
 
 main() {
   var builder = new path.Builder(style: path.Style.windows,
diff --git a/pkg/pkg.status b/pkg/pkg.status
index cdaed72..d139d96 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -19,9 +19,9 @@
 [ $compiler == dart2js || $compiler == dart2dart ]
 http/test/*: Skip
 oauth2/test/*: Skip
-path/test/*: Skip
+pathos/test/*: Skip
 
-# Issue 8440 forces us to use path in the scheduled_test tests, which would
+# Issue 8440 forces us to use pathos in the scheduled_test tests, which would
 # otherwise be dart2js-compatible.
 scheduled_test/test/*: Skip
 
@@ -29,7 +29,7 @@
 [ $runtime == opera || $runtime == ff || $runtime == ie9 || $runtime == dartium || $runtime == chrome || $runtime == safari || $runtime == drt  || $runtime == jsshell]
 http/test/*: Skip
 oauth2/test/*: Skip
-path/test/*: Skip
+pathos/test/*: Skip
 intl/test/date_time_format_file_even_test: Skip
 intl/test/date_time_format_file_odd_test: Skip
 intl/test/find_default_locale_standalone_test: Skip
@@ -39,7 +39,7 @@
 analyzer-experimental/test/generated/element_test: Skip # Imports dart:io.
 analyzer-experimental/test/generated/ast_test: Skip # Imports dart:io.
 
-# Issue 8440 forces us to use path in the scheduled_test tests, which would
+# Issue 8440 forces us to use pathos in the scheduled_test tests, which would
 # otherwise be dart2js-compatible.
 scheduled_test/test/*: Skip
 
@@ -78,9 +78,6 @@
 unittest/test/mock_regexp_negative_test: Fail
 unittest/test/mock_stepwise_negative_test: Fail
 
-# pkg/http issue 7458
-http/test/multipart_test: Fail
-
 
 [ $compiler == dart2js ]
 unittest/test/instance_test: Skip
diff --git a/pkg/scheduled_test/lib/descriptor.dart b/pkg/scheduled_test/lib/descriptor.dart
new file mode 100644
index 0000000..60210f6
--- /dev/null
+++ b/pkg/scheduled_test/lib/descriptor.dart
@@ -0,0 +1,110 @@
+// 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.
+
+/// A library for declaratively describing a filesystem structure, usually for
+/// 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:
+///
+///     import 'package:scheduled_test/descriptor.dart' as d;
+///     import 'package:scheduled_test/scheduled_test.dart';
+///
+///     void main() {
+///       test('Directory.rename', () {
+///         d.dir('parent', [
+///           d.file('sibling', 'sibling-contents'),
+///           d.dir('old-name', [
+///             d.file('child', 'child-contents')
+///           ])
+///         ]).create();
+///
+///         schedule(() =>
+///             new Directory('parent/old-name').rename('parent/new-name'));
+///
+///         d.dir('parent', [
+///           d.file('sibling', 'sibling-contents'),
+///           d.dir('new-name', [
+///             d.file('child', 'child-contents')
+///           ])
+///         ]).validate();
+///       })
+///     }
+///
+/// Usually you don't want your tests cluttering up your working directory with
+/// fake filesystem entities. You can set [defaultRoot] to configure where
+/// filesystem descriptors are rooted on the physical filesystem. For example,
+/// to create a temporary directory for each test:
+///
+///     import 'package:scheduled_test/descriptor.dart' as d;
+///     import 'package:scheduled_test/scheduled_test.dart';
+///
+///     void main() {
+///       setUp(() {
+///         var tempDir;
+///         schedule(() {
+///           return new Directory('').createTemp().then((dir) {
+///             tempDir = dir;
+///             d.defaultRoot = tempDir.path;
+///           });
+///         });
+///
+///         currentSchedule.onComplete.schedule(() {
+///           d.defaultRoot = null;
+///           return tempDir.delete(recursive: true);
+///         });
+///       });
+///
+///       // ...
+///     }
+library descriptor;
+
+import 'dart:async';
+
+import 'package:pathos/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';
+
+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';
+
+/// The root path for descriptors. Top-level descriptors will be created and
+/// validated at this path. Defaults to the current working directory.
+///
+/// If this is set to `null`, it will reset itself to the current working
+/// directory.
+String get defaultRoot => _defaultRoot == null ? path.current : _defaultRoot;
+set defaultRoot(String value) {
+  _defaultRoot = value;
+}
+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 binary [File] descriptor with [name] and [contents].
+File binaryFile(Pattern name, List<int> contents) =>
+    new File.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 descriptor wrapping a [Future]. This descriptor forwards all
+/// asynchronous operations to the result of [future].
+Async async(Future<Entry> future) => new Async(future);
+
+/// Creates a new [Nothing] descriptor that asserts that no entry named [name]
+/// exists.
+Nothing nothing(Pattern name) => new Nothing(name);
diff --git a/pkg/scheduled_test/lib/scheduled_test.dart b/pkg/scheduled_test/lib/scheduled_test.dart
index 456e50b3..587abb7 100644
--- a/pkg/scheduled_test/lib/scheduled_test.dart
+++ b/pkg/scheduled_test/lib/scheduled_test.dart
@@ -183,7 +183,7 @@
 
 export 'package:unittest/matcher.dart';
 export 'package:unittest/unittest.dart' show
-    config, configure, Configuration, logMessage, expectThrow, fail;
+    config, configure, Configuration, logMessage, expectThrow;
 
 export 'src/schedule.dart';
 export 'src/schedule_error.dart';
@@ -316,7 +316,7 @@
 /// initialized.
 void _ensureInitialized() {
   unittest.ensureInitialized();
-  unittest.wrapAsync = (f) {
+  unittest.wrapAsync = (f, [id = '']) {
     if (currentSchedule == null) {
       throw new StateError("Unexpected call to wrapAsync with no current "
           "schedule.");
diff --git a/pkg/scheduled_test/lib/src/descriptor/async.dart b/pkg/scheduled_test/lib/src/descriptor/async.dart
new file mode 100644
index 0000000..c33a68c
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/async.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+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/directory.dart b/pkg/scheduled_test/lib/src/descriptor/directory.dart
new file mode 100644
index 0000000..978daef
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/directory.dart
@@ -0,0 +1,96 @@
+// 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 'package:pathos/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.getRange(1, split.length - 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.add(lastEntryString);
+    return buffer.toString();
+  }
+}
diff --git a/pkg/scheduled_test/lib/src/descriptor/entry.dart b/pkg/scheduled_test/lib/src/descriptor/entry.dart
new file mode 100644
index 0000000..9605a1c
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/entry.dart
@@ -0,0 +1,70 @@
+// 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.entry;
+
+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;
+
+  Entry(this.name);
+
+  /// Schedules the creation of the described entry within the [parent]
+  /// directory. Returns a [Future] that completes after the creation is done.
+  ///
+  /// [parent] defaults to [defaultRoot].
+  Future create([String parent]);
+
+  /// Schedules the validation of the described entry. This validates that the
+  /// physical file system under [parent] contains an entry that matches the one
+  /// described by [this]. Returns a [Future] that completes to `null` if the
+  /// entry is valid, or throws an error if it failed.
+  ///
+  /// [parent] defaults to [defaultRoot].
+  Future validate([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.
+  ///
+  /// This method uses POSIX paths regardless of the underlying operating
+  /// system.
+  ///
+  /// 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.");
+
+  /// Returns the contents of [this] as a stream. This only works if [this] is a
+  /// file entry. This operation is not [schedule]d.
+  ///
+  /// All errors in loading the file will be passed through the returned
+  /// [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/file.dart b/pkg/scheduled_test/lib/src/descriptor/file.dart
new file mode 100644
index 0000000..2fefb89
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/file.dart
@@ -0,0 +1,107 @@
+// 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 'package:pathos/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/nothing.dart b/pkg/scheduled_test/lib/src/descriptor/nothing.dart
new file mode 100644
index 0000000..048297e
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/nothing.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library descriptor.async;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:pathos/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/utils.dart b/pkg/scheduled_test/lib/src/descriptor/utils.dart
new file mode 100644
index 0000000..c649019
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/descriptor/utils.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.
+
+library descriptor.utils;
+
+import 'dart:io';
+
+import 'package:pathos/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.add('i');
+  if (pattern.isMultiLine) flags.add('m');
+  return '/${pattern.pattern}/$flags';
+}
diff --git a/pkg/scheduled_test/lib/src/mock_clock.dart b/pkg/scheduled_test/lib/src/mock_clock.dart
index efcc7eb..bda216f 100644
--- a/pkg/scheduled_test/lib/src/mock_clock.dart
+++ b/pkg/scheduled_test/lib/src/mock_clock.dart
@@ -30,7 +30,7 @@
   return _clock;
 }
 
-typedef void TimerCallback(Timer timer);
+typedef void TimerCallback();
 
 /// Returns a new (possibly mocked) [Timer]. Works the same as [new Timer].
 Timer newTimer(Duration duration, TimerCallback callback) =>
@@ -94,7 +94,7 @@
     _subscription = _clock.onTick.listen((time) {
       if (_cancelled || time < _time) return;
       _subscription.cancel();
-      _callback(this);
+      _callback();
     });
   }
 
diff --git a/pkg/scheduled_test/lib/src/schedule.dart b/pkg/scheduled_test/lib/src/schedule.dart
index ac601ea..17ab86a 100644
--- a/pkg/scheduled_test/lib/src/schedule.dart
+++ b/pkg/scheduled_test/lib/src/schedule.dart
@@ -292,7 +292,7 @@
 
   /// The callback to run when the timeout timer fires. Notifies the current
   /// queue that a timeout has occurred.
-  void _signalTimeout(_) {
+  void _signalTimeout() {
     // Reset the timer so that we can detect timeouts in the onException and
     // onComplete queues.
     _timeoutTimer = null;
diff --git a/pkg/scheduled_test/lib/src/utils.dart b/pkg/scheduled_test/lib/src/utils.dart
index b5e086e..b880a2d 100644
--- a/pkg/scheduled_test/lib/src/utils.dart
+++ b/pkg/scheduled_test/lib/src/utils.dart
@@ -20,7 +20,43 @@
 /// Returns a [Future] that completes after pumping the event queue [times]
 /// times. By default, this should pump the event queue enough times to allow
 /// any code to run, as long as it's not waiting on some external event.
-Future pumpEventQueue([int times=200]) {
+Future pumpEventQueue([int times=20]) {
   if (times == 0) return new Future.immediate(null);
   return new Future.immediate(null).then((_) => pumpEventQueue(times - 1));
 }
+
+/// Returns whether [iterable1] has the same elements in the same order as
+/// [iterable2]. The elements are compared using `==`.
+bool orderedIterableEquals(Iterable iterable1, Iterable iterable2) {
+  var iter1 = iterable1.iterator;
+  var iter2 = iterable2.iterator;
+
+  while (true) {
+    var hasNext1 = iter1.moveNext();
+    var hasNext2 = iter2.moveNext();
+    if (hasNext1 != hasNext2) return false;
+    if (!hasNext1) return true;
+    if (iter1.current != iter2.current) return false;
+  }
+}
+
+// TODO(nweiz): remove this when issue 8731 is fixed.
+/// Returns a [Stream] that will immediately emit [error] and then close.
+Stream errorStream(error) => new Future.immediateError(error).asStream();
+
+/// Returns a buffered stream that will emit the same values as the stream
+/// returned by [future] once [future] completes. If [future] completes to an
+/// error, the return value will emit that error and then close.
+Stream futureStream(Future<Stream> future) {
+  var controller = new StreamController();
+  future.then((stream) {
+    stream.listen(
+        controller.add,
+        onError: (error) => controller.signalError(error),
+        onDone: controller.close);
+  }).catchError((e) {
+    controller.signalError(e);
+    controller.close();
+  });
+  return controller.stream;
+}
diff --git a/pkg/scheduled_test/test/descriptor_test.dart b/pkg/scheduled_test/test/descriptor_test.dart
new file mode 100644
index 0000000..1f5b42a
--- /dev/null
+++ b/pkg/scheduled_test/test/descriptor_test.dart
@@ -0,0 +1,1142 @@
+// 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_test;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:pathos/path.dart' as path;
+import 'package:scheduled_test/descriptor.dart' as d;
+import 'package:scheduled_test/scheduled_test.dart';
+
+import 'metatest.dart';
+import 'utils.dart';
+
+String sandbox;
+
+void main() {
+  expectTestsPass('file().create() creates a file', () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.file('name.txt', 'contents').create();
+
+      schedule(() {
+        expect(new File(path.join(sandbox, 'name.txt')).readAsString(),
+            completion(equals('contents')));
+      });
+    });
+  });
+
+  expectTestsPass('file().create() overwrites an existing file', () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.file('name.txt', 'contents1').create();
+
+      d.file('name.txt', 'contents2').create();
+
+      schedule(() {
+        expect(new File(path.join(sandbox, 'name.txt')).readAsString(),
+            completion(equals('contents2')));
+      });
+    });
+  });
+
+  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', () {
+      scheduleSandbox();
+
+      schedule(() {
+        return new File(path.join(sandbox, 'name.txt'))
+            .writeAsString('contents');
+      });
+
+      d.file('name.txt', 'contents').validate();
+    });
+  });
+
+  expectTestsPass("file().validate() 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('wrongtents');
+      });
+
+      d.file('name.txt', 'contents').validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.map((e) => e.error), equals([
+        "File 'name.txt' should contain:\n"
+        "| contents\n"
+        "but actually contained:\n"
+        "X wrongtents"
+      ]), verbose: true);
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("file().validate() fails if there's no file", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.file('name.txt', 'contents').validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.length, equals(1));
+      expect(errors.first.error,
+          matches(r"^File not found: '[^']+[\\/]name\.txt'\.$"));
+    });
+  }, 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', () {
+      expect(byteStreamToString(d.file('name.txt', 'contents').read()),
+          completion(equals('contents')));
+    });
+  });
+
+  expectTestsPass("file().load() throws an error", () {
+    test('test', () {
+      expect(d.file('name.txt', 'contents').load('path').toList(),
+          throwsA(equals("Can't load 'path' from within 'name.txt': not a "
+                         "directory.")));
+    });
+  });
+
+  expectTestsPass("file().describe() returns the filename", () {
+    test('test', () {
+      expect(d.file('name.txt', 'contents').describe(), equals('name.txt'));
+    });
+  });
+
+  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();
+
+      d.binaryFile('name.bin', [1, 2, 3, 4, 5]).create();
+
+      schedule(() {
+        expect(new File(path.join(sandbox, 'name.bin')).readAsBytes(),
+            completion(equals([1, 2, 3, 4, 5])));
+      });
+    });
+  });
+
+  expectTestsPass('binaryFile().validate() completes successfully if the '
+      'filesystem matches the descriptor', () {
+    test('test', () {
+      scheduleSandbox();
+
+      schedule(() {
+        return new File(path.join(sandbox, 'name.bin'))
+            .writeAsBytes([1, 2, 3, 4, 5]);
+      });
+
+      d.binaryFile('name.bin', [1, 2, 3, 4, 5]).validate();
+    });
+  });
+
+  expectTestsPass("binaryFile().validate() 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.bin'))
+            .writeAsBytes([2, 4, 6, 8, 10]);
+      });
+
+      d.binaryFile('name.bin', [1, 2, 3, 4, 5]).validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.map((e) => e.error), equals([
+        "File 'name.bin' didn't contain the expected binary data."
+      ]), verbose: true);
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("directory().create() creates a directory and its contents",
+      () {
+    test('test', () {
+      scheduleSandbox();
+
+      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')
+      ]).create();
+
+      schedule(() {
+        expect(new File(path.join(sandbox, 'dir', 'file1.txt')).readAsString(),
+            completion(equals('contents1')));
+        expect(new File(path.join(sandbox, 'dir', 'file2.txt')).readAsString(),
+            completion(equals('contents2')));
+        expect(new File(path.join(sandbox, 'dir', 'subdir', 'subfile1.txt'))
+                .readAsString(),
+            completion(equals('subcontents1')));
+        expect(new File(path.join(sandbox, 'dir', 'subdir', 'subfile2.txt'))
+                .readAsString(),
+            completion(equals('subcontents2')));
+      });
+    });
+  });
+
+  expectTestsPass("directory().create() works if the directory already exists",
+      () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.dir('dir').create();
+      d.dir('dir', [d.file('name.txt', 'contents')]).create();
+
+      schedule(() {
+        expect(new File(path.join(sandbox, 'dir', 'name.txt')).readAsString(),
+            completion(equals('contents')));
+      });
+    });
+  });
+
+  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', () {
+      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('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();
+    });
+  });
+
+  expectTestsPass("directory().validate() fails if a directory isn't found"
+      , () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      schedule(() {
+        var dirPath = path.join(sandbox, 'dir');
+        return new Directory(dirPath).create().then((_) {
+          return Future.wait([
+            new File(path.join(dirPath, 'file1.txt'))
+                .writeAsString('contents1'),
+            new File(path.join(dirPath, 'file2.txt'))
+                .writeAsString('contents2')
+          ]);
+        });
+      });
+
+      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,
+          matches(r"^Directory not found: '[^']+[\\/]dir[\\/]subdir'\.$"));
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("directory().validate() fails if a file isn't found", () {
+    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('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,
+          matches(r"^File not found: '[^']+[\\/]dir[\\/]file2\.txt'\.$"));
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("directory().validate() fails if a file has 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(dirPath, 'file2.txt'))
+                .writeAsString('contents2'),
+            new File(path.join(subdirPath, 'subfile1.txt'))
+                .writeAsString('wrongtents1'),
+            new File(path.join(subdirPath, 'subfile2.txt'))
+                .writeAsString('subcontents2')
+          ]);
+        });
+      });
+
+      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.map((e) => e.error), equals([
+        "File 'subfile1.txt' should contain:\n"
+        "| subcontents1\n"
+        "but actually contained:\n"
+        "X wrongtents1"
+      ]));
+    });
+  }, 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')]);
+      expect(byteStreamToString(dir.load('name.txt')),
+          completion(equals('contents')));
+    });
+  });
+
+  expectTestsPass("directory().load() loads a deeply-nested file", () {
+    test('test', () {
+      var dir = d.dir('dir', [
+        d.dir('subdir', [
+          d.file('name.txt', 'subcontents')
+        ]),
+        d.file('name.txt', 'contents')
+      ]);
+
+      expect(byteStreamToString(dir.load('subdir/name.txt')),
+          completion(equals('subcontents')));
+    });
+  });
+
+  expectTestsPass("directory().read() fails", () {
+    test('test', () {
+      var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+      expect(dir.read().toList(),
+          throwsA(equals("Can't read the contents of 'dir': is a directory.")));
+    });
+  });
+
+  expectTestsPass("directory().load() fails to load a nested directory", () {
+    test('test', () {
+      var dir = d.dir('dir', [
+        d.dir('subdir', [
+          d.file('name.txt', 'subcontents')
+        ]),
+        d.file('name.txt', 'contents')
+      ]);
+
+      expect(dir.load('subdir').toList(),
+          throwsA(equals("Can't read the contents of 'subdir': is a "
+              "directory.")));
+    });
+  });
+
+  expectTestsPass("directory().load() fails to load an absolute path", () {
+    test('test', () {
+      var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+
+      expect(dir.load('/name.txt').toList(),
+          throwsA(equals("Can't load absolute path '/name.txt'.")));
+    });
+  });
+
+  expectTestsPass("directory().load() fails to load '.', '..', or ''", () {
+    test('test', () {
+      var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+
+      expect(dir.load('.').toList(),
+          throwsA(equals("Can't load '.' from within 'dir'.")));
+
+      expect(dir.load('..').toList(),
+          throwsA(equals("Can't load '..' from within 'dir'.")));
+
+      expect(dir.load('').toList(),
+          throwsA(equals("Can't load '' from within 'dir'.")));
+    });
+  });
+
+  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', () {
+      var dir = d.dir('dir', [d.file('name.txt', 'contents')]);
+
+      expect(dir.load('not-name.txt').toList(),
+          throwsA(equals("Couldn't find an entry named 'not-name.txt' within "
+              "'dir'.")));
+    });
+  });
+
+  expectTestsPass("directory().load() fails to load a file that exists "
+      "multiple times", () {
+    test('test', () {
+      var dir = d.dir('dir', [
+        d.file('name.txt', 'contents'),
+        d.file('name.txt', 'contents')
+      ]);
+
+      expect(dir.load('name.txt').toList(),
+          throwsA(equals("Found multiple entries named 'name.txt' within "
+              "'dir'.")));
+    });
+  });
+
+  expectTestsPass("directory().describe() lists the contents of the directory",
+      () {
+    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')
+      ]);
+
+      expect(dir.describe(), equals(
+          "dir\n"
+          "|-- file1.txt\n"
+          "|-- file2.txt\n"
+          "'-- file matching /re\\.txt/"));
+    });
+  });
+
+  expectTestsPass("directory().describe() lists the contents of nested "
+      "directories", () {
+    test('test', () {
+      var dir = d.dir('dir', [
+        d.file('file1.txt', 'contents1'),
+        d.dir('subdir', [
+          d.file('subfile1.txt', 'subcontents1'),
+          d.file('subfile2.txt', 'subcontents2'),
+          d.dir('subsubdir', [
+            d.file('subsubfile.txt', 'subsubcontents')
+          ])
+        ]),
+        d.file('file2.txt', 'contents2')
+      ]);
+
+      expect(dir.describe(), equals(
+          "dir\n"
+          "|-- file1.txt\n"
+          "|-- subdir\n"
+          "|   |-- subfile1.txt\n"
+          "|   |-- subfile2.txt\n"
+          "|   '-- subsubdir\n"
+          "|       '-- subsubfile.txt\n"
+          "'-- file2.txt"));
+    });
+  });
+
+  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', () {
+      expect(d.dir('dir').describe(), equals('dir'));
+    });
+  });
+
+  expectTestsPass("async().create() forwards to file().create", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.async(pumpEventQueue().then((_) {
+        return d.file('name.txt', 'contents');
+      })).create();
+
+      d.file('name.txt', 'contents').validate();
+    });
+  });
+
+  expectTestsPass("async().create() forwards to directory().create", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.async(pumpEventQueue().then((_) {
+        return d.dir('dir', [
+          d.file('file1.txt', 'contents1'),
+          d.file('file2.txt', 'contents2')
+        ]);
+      })).create();
+
+      d.dir('dir', [
+        d.file('file1.txt', 'contents1'),
+        d.file('file2.txt', 'contents2')
+      ]).validate();
+    });
+  });
+
+  expectTestsPass("async().validate() forwards to file().validate", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.file('name.txt', 'contents').create();
+
+      d.async(pumpEventQueue().then((_) {
+        return d.file('name.txt', 'contents');
+      })).validate();
+    });
+  });
+
+  expectTestsPass("async().validate() fails if file().validate fails", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.async(pumpEventQueue().then((_) {
+        return d.file('name.txt', 'contents');
+      })).validate();
+    });
+
+    test('test 2', () {
+      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
+      expect(errors.length, equals(1));
+      expect(errors.first.error,
+          matches(r"^File not found: '[^']+[\\/]name\.txt'\.$"));
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("async().validate() forwards to directory().validate", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.dir('dir', [
+        d.file('file1.txt', 'contents1'),
+        d.file('file2.txt', 'contents2')
+      ]).create();
+
+      d.async(pumpEventQueue().then((_) {
+        return d.dir('dir', [
+          d.file('file1.txt', 'contents1'),
+          d.file('file2.txt', 'contents2')
+        ]);
+      })).validate();
+    });
+  });
+
+  expectTestsPass("async().create() fails if directory().create fails", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.async(pumpEventQueue().then((_) {
+        return d.dir('dir', [
+          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"^Directory not found: '[^']+[\\/]dir'\.$"));
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("async().load() fails", () {
+    test('test', () {
+      scheduleSandbox();
+
+      expect(d.async(new Future.immediate(d.file('name.txt')))
+              .load('path').toList(),
+          throwsA(equals("Async descriptors don't support load().")));
+    });
+  });
+
+  expectTestsPass("async().read() fails", () {
+    test('test', () {
+      scheduleSandbox();
+
+      expect(d.async(new Future.immediate(d.file('name.txt'))).read().toList(),
+          throwsA(equals("Async descriptors don't support read().")));
+    });
+  });
+
+  expectTestsPass("nothing().create() does nothing", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.nothing('foo').create();
+
+      schedule(() {
+        expect(new File(path.join(sandbox, 'foo')).exists(),
+            completion(isFalse));
+      });
+
+      schedule(() {
+        expect(new Directory(path.join(sandbox, 'foo')).exists(),
+            completion(isFalse));
+      });
+    });
+  });
+
+  expectTestsPass("nothing().validate() succeeds if nothing's there", () {
+    test('test', () {
+      scheduleSandbox();
+
+      d.nothing('foo').validate();
+    });
+  });
+
+  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', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.file('name.txt', 'contents').create();
+      d.nothing('name.txt').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 at '[^']+[\\/]name.txt', but "
+              r"found a file\.$"));
+    });
+  }, passing: ['test 2']);
+
+  expectTestsPass("nothing().validate() fails if there's a directory", () {
+    var errors;
+    test('test 1', () {
+      scheduleSandbox();
+
+      currentSchedule.onException.schedule(() {
+        errors = currentSchedule.errors;
+      });
+
+      d.dir('dir').create();
+      d.nothing('dir').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 at '[^']+[\\/]dir', but found a "
+              r"directory\.$"));
+    });
+  }, 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();
+
+      expect(d.nothing('name.txt').load('path').toList(),
+          throwsA(equals("Nothing descriptors don't support load().")));
+    });
+  });
+
+  expectTestsPass("nothing().read() fails", () {
+    test('test', () {
+      scheduleSandbox();
+
+      expect(d.nothing('name.txt').read().toList(),
+          throwsA(equals("Nothing descriptors don't support read().")));
+    });
+  });
+}
+
+void scheduleSandbox() {
+  schedule(() {
+    return new Directory('').createTemp().then((dir) {
+      sandbox = dir.path;
+      d.defaultRoot = sandbox;
+    });
+  });
+
+  currentSchedule.onComplete.schedule(() {
+    d.defaultRoot = null;
+    if (sandbox == null) return;
+    var oldSandbox = sandbox;
+    sandbox = null;
+    return new Directory(oldSandbox).delete(recursive: true);
+  });
+}
+
+Future<List<int>> byteStreamToList(Stream<List<int>> stream) {
+  return stream.reduce(<int>[], (buffer, chunk) {
+    buffer.addAll(chunk);
+    return buffer;
+  });
+}
+
+Future<String> byteStreamToString(Stream<List<int>> stream) =>
+  byteStreamToList(stream).then((bytes) => new String.fromCharCodes(bytes));
diff --git a/pkg/scheduled_test/test/metatest.dart b/pkg/scheduled_test/test/metatest.dart
index 2a83015..9850fff 100644
--- a/pkg/scheduled_test/test/metatest.dart
+++ b/pkg/scheduled_test/test/metatest.dart
@@ -12,7 +12,7 @@
 import 'dart:async';
 import 'dart:isolate';
 
-import '../../../pkg/path/lib/path.dart' as path;
+import 'package:pathos/path.dart' as path;
 import 'package:unittest/unittest.dart';
 
 import 'utils.dart';
diff --git a/pkg/scheduled_test/test/scheduled_test_test.dart b/pkg/scheduled_test/test/scheduled_test_test.dart
index f07024d..79d2e37 100644
--- a/pkg/scheduled_test/test/scheduled_test_test.dart
+++ b/pkg/scheduled_test/test/scheduled_test_test.dart
@@ -877,7 +877,7 @@
     test('test 2', () {
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
       expect(errors.map((e) => e.error), equals(["The schedule timed out after "
-        "0:00:00.001 of inactivity."]));
+        "0:00:00.001000 of inactivity."]));
     });
   }, passing: ['test 2']);
 
@@ -898,7 +898,7 @@
     test('test 2', () {
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
       expect(errors.map((e) => e.error), equals(["The schedule timed out after "
-        "0:00:00.001 of inactivity."]));
+        "0:00:00.001000 of inactivity."]));
     });
   }, passing: ['test 2']);
 
@@ -943,7 +943,7 @@
     test('test 2', () {
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
       expect(errors.map((e) => e.error), equals([
-        "The schedule timed out after 0:00:00.003 of inactivity.",
+        "The schedule timed out after 0:00:00.003000 of inactivity.",
         "out-of-band"
       ]));
     });
@@ -998,7 +998,7 @@
       expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
       expect(errors.map((e) => e.error), equals([
         "out-of-band",
-        "The schedule timed out after 0:00:00.002 of inactivity."
+        "The schedule timed out after 0:00:00.002000 of inactivity."
       ]));
     });
   }, passing: ['test 2']);
diff --git a/pkg/scheduled_test/test/utils.dart b/pkg/scheduled_test/test/utils.dart
index bd87edf..3d59e66 100644
--- a/pkg/scheduled_test/test/utils.dart
+++ b/pkg/scheduled_test/test/utils.dart
@@ -20,19 +20,16 @@
 /// Note that timing out will not cancel the asynchronous operation behind
 /// [input].
 Future timeout(Future input, int milliseconds, onTimeout()) {
-  bool completed = false;
   var completer = new Completer();
-  var timer = new Timer(milliseconds, (_) {
-    completed = true;
-    chainToCompleter(new Future.immediate(null).then((_) => onTimeout()),
-        completer);
+  var timer = new Timer(new Duration(milliseconds: milliseconds), () {
+    chainToCompleter(new Future.of(onTimeout), completer);
   });
   input.then((value) {
-    if (completed) return;
+    if (completer.isCompleted) return;
     timer.cancel();
     completer.complete(value);
   }).catchError((e) {
-    if (completed) return;
+    if (completer.isCompleted) return;
     timer.cancel();
     completer.completeError(e.error, e.stackTrace);
   });
@@ -42,7 +39,7 @@
 /// Returns a [Future] that will complete in [milliseconds].
 Future sleep(int milliseconds) {
   var completer = new Completer();
-  mock_clock.newTimer(new Duration(milliseconds: milliseconds), (_) {
+  mock_clock.newTimer(new Duration(milliseconds: milliseconds), () {
     completer.complete();
   });
   return completer.future;
diff --git a/pkg/serialization/lib/src/basic_rule.dart b/pkg/serialization/lib/src/basic_rule.dart
index 19a8bca..fe9428f 100644
--- a/pkg/serialization/lib/src/basic_rule.dart
+++ b/pkg/serialization/lib/src/basic_rule.dart
@@ -130,12 +130,19 @@
     useMaps = false;
   }
 
-  /** Create either a list or a map to hold the object's state, depending
+  /**
+   * Create either a list or a map to hold the object's state, depending
    * on the [useMaps] variable. If using a Map, we wrap it in order to keep
    * the protocol compatible. See [configureForLists]/[configureForMaps].
+   *
+   * If a list is returned, it is growable.
    */
-   createStateHolder() =>
-     useMaps ? new _MapWrapper(fields.contents) : new List(fields.length);
+   createStateHolder() {
+     if (useMaps) return new _MapWrapper(fields.contents);
+     List list = [];
+     list.length = fields.length;
+     return list;
+   }
 
   /**
    * Wrap the state if it's passed in as a map, and if the keys are references,
diff --git a/pkg/serialization/lib/src/format.dart b/pkg/serialization/lib/src/format.dart
index 68f6094..4e57384 100644
--- a/pkg/serialization/lib/src/format.dart
+++ b/pkg/serialization/lib/src/format.dart
@@ -187,7 +187,7 @@
     var rules = reader.selfDescribing ? data[RULES] : null;
     var actualData = reader.selfDescribing ? data[DATA] : data;
     reader.readRules(rules);
-    var ruleData = new List(reader.rules.length).map((x) => []).toList();
+    var ruleData = new List.generate(reader.rules.length, (_) => []);
     var top = recursivelyFixUp(actualData, reader, ruleData);
     result["data"] = ruleData;
     result["roots"] = [top];
@@ -257,7 +257,7 @@
     }
     result[0] = w.serializedRules();
     result[1] = flatData;
-    result[2] = new List();
+    result[2] = [];
     w._rootReferences().forEach((x) => x.writeToList(result[2]));
     return result;
   }
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index 8c58af6..de5113c 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -542,6 +542,8 @@
   indexOf(x, [pos = 0]) => _inflated.toList().indexOf(x);
   lastIndexOf(x, [pos]) => _inflated.toList().lastIndexOf(x);
 
+  Map<int, dynamic> asMap() => IterableMixinWorkaround.asMapList(this);
+
   // These operations are all invalid
   _throw() {
     throw new UnsupportedError("Not modifiable");
diff --git a/pkg/serialization/test/polyfill_identity_map_test.dart b/pkg/serialization/test/polyfill_identity_map_test.dart
index 9988dca..bfc8fef 100644
--- a/pkg/serialization/test/polyfill_identity_map_test.dart
+++ b/pkg/serialization/test/polyfill_identity_map_test.dart
@@ -40,9 +40,9 @@
   test('uniquing primitives', () {
     var map = new IdentityMap();
     var one = 'one';
-    var two = new String.fromCharCodes(one.charCodes);
+    var two = new String.fromCharCodes(one.codeUnits);
     map[one] = 1;
     expect(map[two], 1);
     expect(map[one], 1);
   });
-}
\ No newline at end of file
+}
diff --git a/pkg/serialization/test/serialization_test.dart b/pkg/serialization/test/serialization_test.dart
index 5a9cc49..7b43793 100644
--- a/pkg/serialization/test/serialization_test.dart
+++ b/pkg/serialization/test/serialization_test.dart
@@ -154,7 +154,7 @@
     var l = keysAndValues(list);
     var s = keysAndValues(set);
 
-    m.forEach((key, value) {expect(key.charCodes[0], value + 96);});
+    m.forEach((key, value) {expect(key.codeUnits[0], value + 96);});
     l.forEach((key, value) {expect(key + 1, value);});
     var index = 0;
     var seen = new Set();
diff --git a/pkg/unittest/lib/compact_vm_config.dart b/pkg/unittest/lib/compact_vm_config.dart
index ede7010..ae8ec97 100644
--- a/pkg/unittest/lib/compact_vm_config.dart
+++ b/pkg/unittest/lib/compact_vm_config.dart
@@ -101,6 +101,9 @@
     buffer.write(': ');
     buffer.write(color);
 
+    // Ensure the line fits under MAX_LINE. [buffer] includes the color escape
+    // sequences too. Because these sequences are not visible characters, we
+    // make sure they are not counted towards the limit.
     int nonVisible = _nonVisiblePrefix + color.length  +
         (failed != 0 ? (_RED.length + _NONE.length) : 0);
     int len = buffer.length - nonVisible;
diff --git a/pkg/unittest/lib/html_config.dart b/pkg/unittest/lib/html_config.dart
index 9c64b53..2246bf3 100644
--- a/pkg/unittest/lib/html_config.dart
+++ b/pkg/unittest/lib/html_config.dart
@@ -126,8 +126,6 @@
     window.postMessage('unittest-suite-wait-for-done', '*');
   }
 
-  void onTestResult(TestCase testCase) {}
-
   void onSummary(int passed, int failed, int errors, List<TestCase> results,
       String uncaughtError) {
     _showResultsInPage(passed, failed, errors, results, _isLayoutTest,
diff --git a/pkg/unittest/lib/html_enhanced_config.dart b/pkg/unittest/lib/html_enhanced_config.dart
index 64c7a57..f9b9088 100644
--- a/pkg/unittest/lib/html_enhanced_config.dart
+++ b/pkg/unittest/lib/html_enhanced_config.dart
@@ -82,8 +82,6 @@
     _installOnErrorHandler();
   }
 
-  void onTestResult(TestCase testCase) {}
-
   void onSummary(int passed, int failed, int errors, List<TestCase> results,
       String uncaughtError) {
     _showInteractiveResultsInPage(passed, failed, errors, results,
diff --git a/pkg/unittest/lib/src/collection_matchers.dart b/pkg/unittest/lib/src/collection_matchers.dart
index 80ac428..30e38f6 100644
--- a/pkg/unittest/lib/src/collection_matchers.dart
+++ b/pkg/unittest/lib/src/collection_matchers.dart
@@ -142,7 +142,7 @@
     } else if (expectedLength < actualLength) {
       return 'has too many elements (${actualLength} > ${expectedLength})';
     }
-    List<bool> matched = new List<bool>.fixedLength(actualLength);
+    List<bool> matched = new List<bool>(actualLength);
     for (var i = 0; i < actualLength; i++) {
       matched[i] = false;
     }
diff --git a/pkg/unittest/lib/src/config.dart b/pkg/unittest/lib/src/config.dart
index 2cd2334..29adfc8 100644
--- a/pkg/unittest/lib/src/config.dart
+++ b/pkg/unittest/lib/src/config.dart
@@ -15,19 +15,19 @@
   // The VM won't shut down if a receive port is open. Use this to make sure
   // we correctly wait for asynchronous tests.
   ReceivePort _receivePort;
-  TestCase currentTestCase = null;
 
   /**
    * Subclasses can override this with something useful for diagnostics.
    * Particularly useful in cases where we have parent/child configurations
    * such as layout tests.
    */
-  get name => 'Configuration';
+  String get name => 'Configuration';
+
   /**
    * If true, then tests are started automatically (otherwise [runTests]
    * must be called explicitly after the tests are set up.
    */
-  get autoStart => true;
+  bool get autoStart => true;
 
   /**
    * Called as soon as the unittest framework becomes initialized. This is done
@@ -49,15 +49,24 @@
    * a test suite.
    */
   void onTestStart(TestCase testCase) {
-    currentTestCase = testCase;
+    assert(testCase != null);	
   }
 
   /**
-   * Called when each test is completed. Useful to show intermediate progress on
-   * a test suite.
+   * Called when each test is first completed. Useful to show intermediate
+   * progress on a test suite.
    */
   void onTestResult(TestCase testCase) {
-    currentTestCase = null;
+    assert(testCase != null);	
+  }
+
+  /**
+   * Called when an already completed test changes state; for example a test
+   * that was marked as passing may later be marked as being in error because
+   * it still had callbacks being invoked.
+   */
+  void onTestResultChanged(TestCase testCase) {
+    assert(testCase != null);
   }
 
   /**
@@ -66,12 +75,9 @@
    * should instead override logMessage which is passed the test case.
    */
   void logMessage(String message) {
-    if (currentTestCase == null || _currentTest >= _tests.length ||
-        currentTestCase.id != _tests[_currentTest].id) {
-      // Before or after tests run, or with a mismatch between what the
-      // config and the test harness think is the current test. In this
-      // case we pass null for the test case reference and let the config
-      // decide what to do with this.
+    if (currentTestCase == null) {
+      // Before or after tests run. In this case we pass null for the test
+      // case reference and let the config decide what to do with this.
       logTestCaseMessage(null, message);
     } else {
       logTestCaseMessage(currentTestCase, message);
@@ -152,24 +158,9 @@
   /** Handle errors that happen outside the tests. */
   // TODO(vsm): figure out how to expose the stack trace here
   // Currently e.message works in dartium, but not in dartc.
-  handleExternalError(e, String message) =>
+  void handleExternalError(e, String message) =>
       _reportTestError('$message\nCaught $e', '');
 
-  /**
-   * Send messages to the test controller code (see 'test_controller.js'). This
-   * is only needed to support browser tests with dart2js. Note: we could wrap
-   * tests and send the appropriate messages to the controller through the
-   * wrapper, but using wrappers has a noticeable overhead in the testing bots,
-   * so we use this approach instead.
-   *
-   * Configurations that will not run in DRT (such as vm_config and
-   * compact_vm_config), can safely override this method to avoid printing extra
-   * mesages in the console.
-   */
-  // TODO(sigmund): find a way to unify notifyController and _postMessage
-  void notifyController(String message) {
-  }
-
   _postMessage(String message) {
     // In dart2js browser tests, the JavaScript-based test controller
     // intercepts calls to print and listens for "secret" messages.
diff --git a/pkg/unittest/lib/src/core_matchers.dart b/pkg/unittest/lib/src/core_matchers.dart
index 44356d2..236da4e 100644
--- a/pkg/unittest/lib/src/core_matchers.dart
+++ b/pkg/unittest/lib/src/core_matchers.dart
@@ -325,8 +325,7 @@
       // Queue up an asynchronous expectation that validates when the future
       // completes.
       item.then((value) {
-        done(() => expect(false, isTrue, reason:
-            "Expected future to fail, but succeeded with '$value'."));
+        done(() => fail("Expected future to fail, but succeeded with '$value'."));
       }, onError: (e) {
         done(() {
           if (_matcher == null) return;
@@ -483,18 +482,6 @@
   bool matches(item, MatchState matchState) => item is ArgumentError;
 }
 
-/** A matcher for IllegalJSRegExpExceptions. */
-const isIllegalJSRegExpException = const _IllegalJSRegExpException();
-
-/** A matcher for functions that throw IllegalJSRegExpException. */
-const Matcher throwsIllegalJSRegExpException =
-    const Throws(isIllegalJSRegExpException);
-
-class _IllegalJSRegExpException extends TypeMatcher {
-  const _IllegalJSRegExpException() : super("IllegalJSRegExpException");
-  bool matches(item, MatchState matchState) => item is IllegalJSRegExpException;
-}
-
 /** A matcher for RangeErrors. */
 const isRangeError = const _RangeError();
 
diff --git a/pkg/unittest/lib/src/expect.dart b/pkg/unittest/lib/src/expect.dart
index 5cc56fd..3542f7a 100644
--- a/pkg/unittest/lib/src/expect.dart
+++ b/pkg/unittest/lib/src/expect.dart
@@ -4,6 +4,18 @@
 
 part of matcher;
 
+/** The objects thrown by the default failure handler. */
+class TestFailure {
+  String _message;
+
+  get message => _message;
+  set message(String value) => _message = value;
+
+  TestFailure(String message) : _message = message;
+
+  String toString() => _message;
+}
+
 /**
  * Some matchers, like those for Futures and exception testing,
  * can fail in asynchronous sections, and throw exceptions.
@@ -13,7 +25,7 @@
  * used safely. For example, the unittest library will set this
  * to be expectAsync1. By default this is an identity function.
  */
-Function wrapAsync = (f) => f;
+Function wrapAsync = (f, [id]) => f;
 
 /**
  * This is the main assertion function. It asserts that [actual]
@@ -24,8 +36,8 @@
  * [matcher] can be a value in which case it will be wrapped in an
  * [equals] matcher.
  *
- * If the assertion fails, then the default behavior is to throw an
- * [ExpectException], but this behavior can be changed by calling
+ * If the assertion fails, then the default behavior is to throw a
+ * [TestFailure], but this behavior can be changed by calling
  * [configureExpectFailureHandler] and providing an alternative handler that
  * implements the [IFailureHandler] interface. It is also possible to
  * pass a [failureHandler] to [expect] as a final parameter for fine-
@@ -56,6 +68,13 @@
   }
 }
 
+void fail(String message, {FailureHandler failureHandler}) {
+  if (failureHandler == null) {
+    failureHandler = getOrCreateExpectFailureHandler();
+  }
+  failureHandler.fail(message);
+}
+
 /**
  * Takes an argument and returns an equivalent matcher.
  * If the argument is already a matcher this does nothing,
@@ -75,7 +94,7 @@
 // The handler for failed asserts.
 FailureHandler _assertFailureHandler = null;
 
-// The default failure handler that throws ExpectExceptions.
+// The default failure handler that throws [TestFailure]s.
 class DefaultFailureHandler implements FailureHandler {
   DefaultFailureHandler() {
     if (_assertErrorFormatter == null) {
@@ -83,7 +102,7 @@
     }
   }
   void fail(String reason) {
-    throw new ExpectException(reason);
+    throw new TestFailure(reason);
   }
   void failMatch(actual, Matcher matcher, String reason,
       MatchState matchState, bool verbose) {
@@ -95,7 +114,7 @@
  * Changes or resets to the default the failure handler for expect()
  * [handler] is a reference to the new handler; if this is omitted
  * or null then the failure handler is reset to the default, which
- * throws [ExpectExceptions] on [expect] assertion failures.
+ * throws [TestFailure]s on [expect] assertion failures.
  */
 void configureExpectFailureHandler([FailureHandler handler = null]) {
   if (handler == null) {
diff --git a/pkg/unittest/lib/src/future_matchers.dart b/pkg/unittest/lib/src/future_matchers.dart
index 77ba8bf..cfc0518 100644
--- a/pkg/unittest/lib/src/future_matchers.dart
+++ b/pkg/unittest/lib/src/future_matchers.dart
@@ -13,7 +13,7 @@
  * To test that a Future completes with an exception, you can use [throws] and
  * [throwsA].
  */
-Matcher completes = const _Completes(null);
+Matcher completes = const _Completes(null, '');
 
 /**
  * Matches a [Future] that completes succesfully with a value that matches
@@ -23,29 +23,35 @@
  *
  * To test that a Future completes with an exception, you can use [throws] and
  * [throwsA].
+ *
+ * [id] is an optional tag that can be used to identify the completion matcher
+ * in error messages.
  */
-Matcher completion(matcher) => new _Completes(wrapMatcher(matcher));
+Matcher completion(matcher, [String id = '']) =>
+    new _Completes(wrapMatcher(matcher), id);
 
 class _Completes extends BaseMatcher {
   final Matcher _matcher;
+  final String _id;
 
-  const _Completes(this._matcher);
+  const _Completes(this._matcher, this._id);
 
   bool matches(item, MatchState matchState) {
     if (item is! Future) return false;
-    var done = wrapAsync((fn) => fn());
+    var done = wrapAsync((fn) => fn(), _id);
 
     item.then((value) {
       done(() { if (_matcher != null) expect(value, _matcher); });
     }, onError: (e) {
-      var reason = 'Expected future to complete successfully, but it failed '
-                   'with ${e.error}';
+      var id = _id == '' ? '' : '${_id} ';
+      var reason = 'Expected future ${id}to complete successfully, '
+                   'but it failed with ${e.error}';
       if (e.stackTrace != null) {
         var stackTrace = e.stackTrace.toString();
         stackTrace = '  ${stackTrace.replaceAll('\n', '\n  ')}';
         reason = '$reason\nStack trace:\n$stackTrace';
       }
-      done(() => expect(false, isTrue, reason: reason));
+      done(() => fail(reason));
     });
 
     return true;
diff --git a/pkg/unittest/lib/src/interfaces.dart b/pkg/unittest/lib/src/interfaces.dart
index 960cfbf..909c93e 100644
--- a/pkg/unittest/lib/src/interfaces.dart
+++ b/pkg/unittest/lib/src/interfaces.dart
@@ -79,7 +79,7 @@
 
 /**
  * Failed matches are reported using a default IFailureHandler.
- * The default implementation simply throws ExpectExceptions;
+ * The default implementation simply throws [TestFailure]s;
  * this can be replaced by some other implementation of
  * IFailureHandler by calling configureExpectHandler.
  */
diff --git a/pkg/unittest/lib/src/test_case.dart b/pkg/unittest/lib/src/test_case.dart
index 8efa694..da85f80 100644
--- a/pkg/unittest/lib/src/test_case.dart
+++ b/pkg/unittest/lib/src/test_case.dart
@@ -76,9 +76,25 @@
     runningTime = null;
   }
 
-  void _runTest() {
+  Future _runTest() {
     _prepTest();
-    test();
+    // Increment/decrement callbackFunctionsOutstanding to prevent
+    // synchronous 'async' callbacks from causing the  test to be
+    // marked as complete before the body is completely executed.
+    ++callbackFunctionsOutstanding;
+    var f = test();
+    --callbackFunctionsOutstanding;
+    if (f is Future) {
+      f.then((_) => _finishTest())
+       .catchError((e) => fail("${e.error}"));
+      return f;
+    } else {
+      _finishTest();
+      return null;
+    }
+  }
+
+  void _finishTest() {
     if (result == null && callbackFunctionsOutstanding == 0) {
       pass();
     }
@@ -98,19 +114,21 @@
     _doneTeardown = false;
     var rtn = _setUp == null ? null : _setUp();
     if (rtn is Future) {
-      rtn.then(expectAsync1((_) =>_runTest(),
-          id: '[Async setUp completion handler]'))
-      .catchError((e) {
-        _prepTest();
-        // Calling error() will result in the tearDown being done.
-        // One could debate whether tearDown should be done after
-        // a failed setUp. There is no right answer, but doing it
-        // seems to be the more conservative approach, because 
-        // unittest will not stop at a test failure.
-        error("$description: Test setup failed: ${e.error}");
-      });
+      rtn.then((_) => _runTest())
+         .catchError((e) {
+          _prepTest();
+          // Calling error() will result in the tearDown being done.
+          // One could debate whether tearDown should be done after
+          // a failed setUp. There is no right answer, but doing it
+          // seems to be the more conservative approach, because 
+          // unittest will not stop at a test failure.
+          error("$description: Test setup failed: ${e.error}");
+        });
     } else {
-      _runTest();
+      var f = _runTest();
+      if (f != null) {
+        return f;
+      }
     }
     if (result == null) { // Not complete.
       _testComplete = new Completer();
@@ -126,71 +144,75 @@
     }
   }
 
-  void _complete() {
+  // Set the results, notify the config, and return true if this
+  // is the first time the result is being set.
+  void _setResult(String testResult, String messageText, String stack) {
+    message = messageText;
+    stackTrace = stack;
+    if (result == null) {
+      result = testResult;
+      _config.onTestResult(this);
+    } else {
+      result = testResult;
+      _config.onTestResultChanged(this);
+    }
+  }
+
+  void _complete(String testResult,
+                [String messageText = '',
+                 String stack = '']) {
     if (runningTime == null) {
       // TODO(gram): currently the duration measurement code is blocked
       // by issue 4437. When that is fixed replace the line below with:
       //    runningTime = new DateTime.now().difference(startTime);
       runningTime = new Duration(milliseconds: 0);
     }
+    _setResult(testResult, messageText, stack);
     if (!_doneTeardown) {
       _doneTeardown = true;
       if (_tearDown != null) {
         var rtn = _tearDown();
         if (rtn is Future) {
           rtn.then((_) {
-            if (result == null) {
-              // The test passed. In some cases we will already
-              // have set this result (e.g. if the test was async
-              // and all callbacks completed). If not, we do it here.
-              pass();
-            } else {
-              // The test has already been marked as pass/fail.
-              // Just report the updated result.
-              _config.onTestResult(this);
-            }
             _notifyComplete();
           })
           .catchError((e) {
             // We don't call fail() as that will potentially result in
             // spurious messages like 'test failed more than once'.
-            result = ERROR;
-            message = "$description: Test teardown failed: ${e.error}";
-            _config.onTestResult(this);
+            _setResult(ERROR, "$description: Test teardown failed: ${e.error}",
+                e.stackTrace.toString());
             _notifyComplete();
           });
           return;
         }
       }
     }
-    _config.onTestResult(this);
     _notifyComplete();
   }
 
   void pass() {
-    result = PASS;
-    _complete();
+    _complete(PASS);
   }
 
   void fail(String messageText, [String stack = '']) {
     if (result != null) {
-      if (result == PASS) {
-        error('Test failed after initially passing: $messageText', stack);
-      } else if (result == FAIL) {
-        error('Test failed more than once: $messageText', stack);
-      }
+      String newMessage = (result == PASS)
+          ? 'Test failed after initially passing: $messageText'
+          : 'Test failed more than once: $messageText';
+      // TODO(gram): Should we combine the stack with the old one?
+      _complete(ERROR, newMessage, stack);
     } else {
-      result = FAIL;
-      message = messageText;
-      stackTrace = stack;
-      _complete();
+      _complete(FAIL, messageText, stack);
     }
   }
 
   void error(String messageText, [String stack = '']) {
-    result = ERROR;
-    message = messageText;
-    stackTrace = stack;
-    _complete();
+    _complete(ERROR, messageText, stack);
+  }
+
+  void markCallbackComplete() {
+    if (--callbackFunctionsOutstanding == 0 && !isComplete) {
+      pass();
+    }
   }
 }
diff --git a/pkg/unittest/lib/unittest.dart b/pkg/unittest/lib/unittest.dart
index de9cc45..1177de5 100644
--- a/pkg/unittest/lib/unittest.dart
+++ b/pkg/unittest/lib/unittest.dart
@@ -113,6 +113,19 @@
  * callback should be protected within a call to guardAsync(); this will ensure
  * that exceptions are properly handled.
  *
+ * A variation on this is expectAsyncUntilX(), which takes a callback as the
+ * first parameter and a predicate function as the second parameter; after each
+ * time * the callback is called, the predicate function will be called; if it
+ * returns false the test will still be considered incomplete.
+ *
+ * Test functions can return [Future]s, which provide another way of doing
+ * asynchronous tests. The test framework will handle exceptions thrown by
+ * the Future, and will advance to the next test when the Future is complete.
+ * It is still important to use expectAsync/guardAsync with any parts of the
+ * test that may be invoked from a top level context (for example, with
+ * Timer.run()], as the Future exception handler may not capture exceptions
+ * in such code.
+ *
  * Note: due to some language limitations we have to use different functions
  * depending on the number of positional arguments of the callback. In the
  * future, we plan to expose a single `expectAsync` function that can be used
@@ -189,7 +202,7 @@
 List<TestCase> _tests;
 
 /** Get the list of tests. */
-get testCases => _tests;
+List<TestCase> get testCases => _tests;
 
 /**
  * Callback used to run tests. Entrypoints can replace this with their own
@@ -205,6 +218,12 @@
 
 /** Current test being executed. */
 int _currentTest = 0;
+TestCase _currentTestCase;
+
+TestCase get currentTestCase =>
+    (_currentTest >= 0 && _currentTest < _tests.length)
+        ? _tests[_currentTest]
+        : null;
 
 /** Whether the framework is in an initialized state. */
 bool _initialized = false;
@@ -274,18 +293,27 @@
 // TODO(sigmund): remove this class and simply use a closure with named
 // arguments (if still applicable).
 class _SpreadArgsHelper {
-  Function _callback;
-  int _expectedCalls;
-  int _actualCalls = 0;
-  int _testNum;
-  TestCase _testCase;
-  Function _shouldCallBack;
-  Function _isDone;
-  String _id;
-  static const _sentinel = const _Sentinel();
+  final Function callback;
+  final int minExpectedCalls;
+  final int maxExpectedCalls;
+  final Function isDone;
+  final int testNum;
+  final String id;
+  int actualCalls = 0;
+  TestCase testCase;
+  bool complete;
+  static const sentinel = const _Sentinel();
 
-  _init(Function callback, Function shouldCallBack, Function isDone,
-       [expectedCalls = 0]) {
+  _SpreadArgsHelper(Function callback, int minExpected, int maxExpected,
+      Function isDone, String id)
+      : this.callback = callback,
+        minExpectedCalls = minExpected,
+        maxExpectedCalls = (maxExpected == 0 && minExpected > 0)
+            ? minExpected
+            : maxExpected,
+        this.isDone = isDone,
+        testNum = _currentTest,
+        this.id = _makeCallbackId(id, callback) {
     ensureInitialized();
     if (!(_currentTest >= 0 &&
            _currentTest < _tests.length &&
@@ -296,137 +324,121 @@
     assert(_currentTest >= 0 &&
            _currentTest < _tests.length &&
            _tests[_currentTest] != null);
-    _callback = callback;
-    _shouldCallBack = shouldCallBack;
-    _isDone = isDone;
-    _expectedCalls = expectedCalls;
-    _testNum = _currentTest;
-    _testCase = _tests[_currentTest];
-    if (expectedCalls > 0) {
-      _testCase.callbackFunctionsOutstanding++;
+    testCase = _tests[_currentTest];
+    if (isDone != null || minExpected > 0) {
+      testCase.callbackFunctionsOutstanding++;
+      complete = false;
+    } else {
+      complete = true;
     }
-    _id = '';
-    // If the callback is not an anonymous closure, try to get the
-    // name.
-    var fname = callback.toString();
-    var prefix = "Function '";
-    var pos = fname.indexOf(prefix);
-    if (pos > 0) {
-      pos += prefix.length;
-      var epos = fname.indexOf("'", pos);
-      if (epos > 0) {
-        _id = "${fname.substring(pos, epos)} ";
+  }
+
+  static _makeCallbackId(String id, Function callback) {
+    // Try to create a reasonable id.
+    if (id != null) {
+      return "$id ";
+    } else {
+      // If the callback is not an anonymous closure, try to get the
+      // name.
+      var fname = callback.toString();
+      var prefix = "Function '";
+      var pos = fname.indexOf(prefix);
+      if (pos > 0) {
+        pos += prefix.length;
+        var epos = fname.indexOf("'", pos);
+        if (epos > 0) {
+          return "${fname.substring(pos, epos)} ";
+        }
       }
     }
+    return '';
   }
 
-  _SpreadArgsHelper(callback, shouldCallBack, isDone) {
-    _init(callback, shouldCallBack, isDone);
-  }
-
-  _SpreadArgsHelper.fixedCallCount(callback, expectedCalls, id) {
-    _init(callback, _checkCallCount, _allCallsDone, expectedCalls);
-    if (id != null) {
-      _id = "$id ";
-    }
-  }
-
-  _SpreadArgsHelper.variableCallCount(callback, isDone) {
-    _init(callback, _always, isDone, 1);
-   }
-
-  _SpreadArgsHelper.optionalCalls(callback) {
-    _init(callback, _always, () => false, 0);
-   }
-
-  _after() {
-    if (_isDone()) {
-      _handleCallbackFunctionComplete(_testNum, _id);
-    }
-  }
-
-  _allCallsDone() => _actualCalls == _expectedCalls;
-
-  _always() {
-    // Always run except if the test is done.
-    if (_testCase.isComplete) {
-      _testCase.error(
-          'Callback ${_id}called after already being marked '
-          'as done ($_actualCalls).',
-          '');
+  shouldCallBack() {
+    ++actualCalls;
+    if (testCase.isComplete) {
+      // Don't run if the test is done. We don't throw here as this is not
+      // the current test, but we do mark the old test as having an error
+      // if it previously passed.
+      if (testCase.result == PASS) {
+        testCase.error(
+            'Callback ${id}called ($actualCalls) after test case '
+            '${testCase.description} has already been marked as '
+            '${testCase.result}.', '');
+      }
       return false;
-    } else {
-      return true;
+    } else if (maxExpectedCalls >= 0 && actualCalls > maxExpectedCalls) {
+      throw new TestFailure('Callback ${id}called more times than expected '
+                            '($maxExpectedCalls).');
+    }
+    return true;
+  }
+
+  after() {
+    if (!complete) {
+      if (minExpectedCalls > 0 && actualCalls < minExpectedCalls) return;
+      if (isDone != null && !isDone()) return;
+
+      // Mark this callback as complete and remove it from the testcase
+      // oustanding callback count; if that hits zero the testcase is done.
+      complete = true;
+      testCase.markCallbackComplete();
     }
   }
 
-  invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel,
-          arg3 = _sentinel, arg4 = _sentinel]) {
-    return guardAsync(() {
-      ++_actualCalls;
-      if (!_shouldCallBack()) {
+  invoke([arg0 = sentinel, arg1 = sentinel, arg2 = sentinel,
+          arg3 = sentinel, arg4 = sentinel]) {
+    return _guardAsync(() {
+      if (!shouldCallBack()) {
         return;
-      } else if (arg0 == _sentinel) {
-        return _callback();
-      } else if (arg1 == _sentinel) {
-        return _callback(arg0);
-      } else if (arg2 == _sentinel) {
-        return _callback(arg0, arg1);
-      } else if (arg3 == _sentinel) {
-        return _callback(arg0, arg1, arg2);
-      } else if (arg4 == _sentinel) {
-        return _callback(arg0, arg1, arg2, arg3);
+      } else if (arg0 == sentinel) {
+        return callback();
+      } else if (arg1 == sentinel) {
+        return callback(arg0);
+      } else if (arg2 == sentinel) {
+        return callback(arg0, arg1);
+      } else if (arg3 == sentinel) {
+        return callback(arg0, arg1, arg2);
+      } else if (arg4 == sentinel) {
+        return callback(arg0, arg1, arg2, arg3);
       } else {
-        _testCase.error(
+        testCase.error(
            'unittest lib does not support callbacks with more than'
               ' 4 arguments.',
            '');
       }
     },
-    _after, _testNum);
+    after, testNum);
   }
 
   invoke0() {
-    return guardAsync(
+    return _guardAsync(
         () {
-          ++_actualCalls;
-          if (_shouldCallBack()) {
-            return _callback();
+          if (shouldCallBack()) {
+            return callback();
           }
         },
-        _after, _testNum);
+        after, testNum);
   }
 
   invoke1(arg1) {
-    return guardAsync(
+    return _guardAsync(
         () {
-          ++_actualCalls;
-          if (_shouldCallBack()) {
-            return _callback(arg1);
+          if (shouldCallBack()) {
+            return callback(arg1);
           }
         },
-        _after, _testNum);
+        after, testNum);
   }
 
   invoke2(arg1, arg2) {
-    return guardAsync(
+    return _guardAsync(
         () {
-          ++_actualCalls;
-          if (_shouldCallBack()) {
-            return _callback(arg1, arg2);
+          if (shouldCallBack()) {
+            return callback(arg1, arg2);
           }
         },
-        _after, _testNum);
-  }
-
-  /** Returns false if we exceded the number of expected calls. */
-  bool _checkCallCount() {
-    if (_actualCalls > _expectedCalls) {
-      _testCase.error('Callback ${_id}called more times than expected '
-             '($_actualCalls > $_expectedCalls).', '');
-      return false;
-    }
-    return true;
+        after, testNum);
   }
 }
 
@@ -440,9 +452,9 @@
  * to provide more descriptive error messages if the callback is called more
  * often than expected.
  */
-Function _expectAsync(Function callback, {int count: 1, String id}) {
-  return new _SpreadArgsHelper.
-      fixedCallCount(callback, count, id).invoke;
+Function _expectAsync(Function callback,
+                     {int count: 1, int max: 0, String id}) {
+  return new _SpreadArgsHelper(callback, count, max, null, id).invoke;
 }
 
 /**
@@ -453,26 +465,31 @@
  * tracked and reported. [callback] should take 0 positional arguments (named
  * arguments are not supported). [id] can be used to provide more
  * descriptive error messages if the callback is called more often than
- * expected.
+ * expected. [max] can be used to specify an upper bound on the number of
+ * calls; if this is exceeded the test will fail (or be marked as in error if
+ * it was already complete). A value of 0 for [max] (the default) will set
+ * the upper bound to the same value as [count]; i.e. the callback should be
+ * called exactly [count] times. A value of -1 for [max] will mean no upper
+ * bound.
  */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync0(Function callback, {int count: 1, String id}) {
-  return new _SpreadArgsHelper.
-      fixedCallCount(callback, count, id).invoke0;
+Function expectAsync0(Function callback,
+                     {int count: 1, int max: 0, String id}) {
+  return new _SpreadArgsHelper(callback, count, max, null, id).invoke0;
 }
 
 /** Like [expectAsync0] but [callback] should take 1 positional argument. */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync1(Function callback, {int count: 1, String id}) {
-  return new _SpreadArgsHelper.
-      fixedCallCount(callback, count, id).invoke1;
+Function expectAsync1(Function callback,
+                     {int count: 1, int max: 0, String id}) {
+  return new _SpreadArgsHelper(callback, count, max, null, id).invoke1;
 }
 
 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync2(Function callback, {int count: 1, String id}) {
-  return new _SpreadArgsHelper.
-      fixedCallCount(callback, count, id).invoke2;
+Function expectAsync2(Function callback,
+                     {int count: 1, int max: 0, String id}) {
+  return new _SpreadArgsHelper(callback, count, max, null, id).invoke2;
 }
 
 /**
@@ -481,10 +498,12 @@
  * when it returns true will it continue with the following test. Using
  * [expectAsyncUntil] will also ensure that errors that occur within
  * [callback] are tracked and reported. [callback] should take between 0 and
- * 4 positional arguments (named arguments are not supported).
+ * 4 positional arguments (named arguments are not supported). [id] can be
+ * used to identify the callback in error messages (for example if it is called
+ * after the test case is complete).
  */
-Function _expectAsyncUntil(Function callback, Function isDone) {
-  return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke;
+Function _expectAsyncUntil(Function callback, Function isDone, {String id}) {
+  return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke;
 }
 
 /**
@@ -493,27 +512,29 @@
  * when it returns true will it continue with the following test. Using
  * [expectAsyncUntil0] will also ensure that errors that occur within
  * [callback] are tracked and reported. [callback] should take 0 positional
- * arguments (named arguments are not supported).
+ * arguments (named arguments are not supported). [id] can be used to
+ * identify the callback in error messages (for example if it is called
+ * after the test case is complete).
  */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil0(Function callback, Function isDone) {
-  return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke0;
+Function expectAsyncUntil0(Function callback, Function isDone, {String id}) {
+  return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke0;
 }
 
 /**
  * Like [expectAsyncUntil0] but [callback] should take 1 positional argument.
  */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil1(Function callback, Function isDone) {
-  return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke1;
+Function expectAsyncUntil1(Function callback, Function isDone, {String id}) {
+  return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke1;
 }
 
 /**
  * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments.
  */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil2(Function callback, Function isDone) {
-  return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2;
+Function expectAsyncUntil2(Function callback, Function isDone, {String id}) {
+  return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2;
 }
 
 /**
@@ -522,10 +543,11 @@
  * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
  * might optionally be called but may never be called during the test.
  * [callback] should take between 0 and 4 positional arguments (named arguments
- * are not supported).
+ * are not supported). [id] can be used to identify the callback in error
+ * messages (for example if it is called after the test case is complete).
  */
-Function _protectAsync(Function callback) {
-  return new _SpreadArgsHelper.optionalCalls(callback).invoke;
+Function _protectAsync(Function callback, {String id}) {
+  return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke;
 }
 
 /**
@@ -534,27 +556,28 @@
  * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
  * might optionally be called but may never be called during the test.
  * [callback] should take 0 positional arguments (named arguments are not
- * supported).
+ * supported). [id] can be used to identify the callback in error
+ * messages (for example if it is called after the test case is complete).
  */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync0(Function callback) {
-  return new _SpreadArgsHelper.optionalCalls(callback).invoke0;
+Function protectAsync0(Function callback, {String id}) {
+  return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke0;
 }
 
 /**
  * Like [protectAsync0] but [callback] should take 1 positional argument.
  */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync1(Function callback) {
-  return new _SpreadArgsHelper.optionalCalls(callback).invoke1;
+Function protectAsync1(Function callback, {String id}) {
+  return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke1;
 }
 
 /**
  * Like [protectAsync0] but [callback] should take 2 positional arguments.
  */
 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync2(Function callback) {
-  return new _SpreadArgsHelper.optionalCalls(callback).invoke2;
+Function protectAsync2(Function callback, {String id}) {
+  return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke2;
 }
 
 /**
@@ -617,38 +640,6 @@
   _testTeardown = teardownTest;
 }
 
-/**
- * Called when one of the callback functions is done with all expected
- * calls.
- */
-void _handleCallbackFunctionComplete(testNum, [id = '']) {
-  // TODO (gram): we defer this to give the nextBatch recursive
-  // stack a chance to unwind. This is a temporary hack but
-  // really a bunch of code here needs to be fixed. We have a
-  // single array that is being iterated through by nextBatch(),
-  // which is recursively invoked in the case of async tests that
-  // run synchronously. Bad things can then happen.
-  _defer(() {
-    if (_currentTest != testNum) {
-      if (_tests[testNum].result == PASS) {
-        _tests[testNum].error("${id}Unexpected extra callbacks", '');
-      }
-    } else if (_currentTest < _tests.length) {
-      final testCase = _tests[_currentTest];
-      --testCase.callbackFunctionsOutstanding;
-      if (testCase.callbackFunctionsOutstanding < 0) {
-        // TODO(gram): Check: Can this even happen?
-        testCase.error(
-            'More calls to _handleCallbackFunctionComplete() than expected.',
-             '');
-      } else if (testCase.callbackFunctionsOutstanding == 0 &&
-                 !testCase.isComplete) {
-        testCase.pass();
-      }
-    }
-  });
-}
-
 /** Advance to the next test case. */
 void _nextTestCase() {
   _defer(() {
@@ -658,14 +649,6 @@
 }
 
 /**
- * Temporary hack: expose old API.
- * TODO(gram) remove this when WebKit tests are working with new framework
- */
-void callbackDone() {
-  _handleCallbackFunctionComplete(_currentTest);
-}
-
-/**
  * Utility function that can be used to notify the test framework that an
  *  error was caught outside of this library.
  */
@@ -678,20 +661,20 @@
   }
 }
 
-/** Runs [callback] at the end of the event loop. */
+/**
+ * Runs [callback] at the end of the event loop. Note that we don't wrap
+ * the callback in guardAsync; this is for test framework functions which
+ * should not be throwing unexpected exceptions that end up failing test
+ * cases! Furthermore, we need the final exception to be thrown but not
+ * caught by the test framework if any test cases failed. However, tests
+ * that make use of a similar defer function *should* wrap the callback
+ * (as we do in unitttest_test.dart).
+ */
 _defer(void callback()) {
-  // Exploit isolate ports as a platform-independent mechanism to queue a
-  // message at the end of the event loop.
-  // TODO(sigmund): expose this functionality somewhere in our libraries.
-  final port = new ReceivePort();
-  port.receive((msg, reply) {
-    callback();
-    port.close();
-  });
-  port.toSendPort().send(null, null);
+  (new Future.immediate(null)).then((_) => callback());
 }
 
-rerunTests() {
+void rerunTests() {
   _uncaughtErrorMessage = null;
   _initialized = true; // We don't want to reset the test array.
   runTests();
@@ -712,11 +695,11 @@
   } else if (testFilter is Function) {
     filterFunction = testFilter;
   }
-  _tests = _tests.where(filterFunction).toList();
+  _tests.retainMatching(filterFunction);
 }
 
 /** Runs all queued tests, one at a time. */
-runTests() {
+void runTests() {
   _currentTest = 0;
   _currentGroup = '';
 
@@ -733,11 +716,17 @@
 }
 
 /**
- * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update
- * the [_currentTest] status accordingly.
+ * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is
+ * passed to the corresponding test.
+ *
+ * The value returned by [tryBody] (if any) is returned by [guardAsync].
  */
-guardAsync(tryBody, [finallyBody, testNum = -1]) {
-  if (testNum < 0) testNum = _currentTest;
+guardAsync(Function tryBody) {
+  return _guardAsync(tryBody, null, _currentTest);
+}
+
+_guardAsync(Function tryBody, Function finallyBody, int testNum) {
+  assert(testNum >= 0);
   try {
     return tryBody();
   } catch (e, trace) {
@@ -750,7 +739,7 @@
 /**
  * Registers that an exception was caught for the current test.
  */
-registerException(e, [trace]) {
+void registerException(e, [trace]) {
   _registerException(_currentTest, e, trace);
 }
 
@@ -759,11 +748,11 @@
  */
 _registerException(testNum, e, [trace]) {
   trace = trace == null ? '' : trace.toString();
+  String message = (e is TestFailure) ? e.message : 'Caught $e';
   if (_tests[testNum].result == null) {
-    String message = (e is ExpectException) ? e.message : 'Caught $e';
     _tests[testNum].fail(message, trace);
   } else {
-    _tests[testNum].error('Caught $e', trace);
+    _tests[testNum].error(message, trace);
   }
 }
 
@@ -779,13 +768,9 @@
       break;
     }
     final testCase = _tests[_currentTest];
-    var f = guardAsync(testCase.run, null, _currentTest);
+    var f = _guardAsync(testCase.run, null, _currentTest);
     if (f != null) {
-      f.then((_){})
-       .catchError((e) {
-        testCase.error(e.toString(), e.stackTrace);
-      })
-      .whenComplete(() {
+      f.whenComplete(() {
         _nextTestCase(); // Schedule the next test.
       });
       break;
@@ -819,20 +804,16 @@
   return _currentGroup != '' ? '$_currentGroup$groupSep$spec' : spec;
 }
 
-void fail(String message) {
-  throw new ExpectException(message);
-}
-
 /**
  * Lazily initializes the test library if not already initialized.
  */
-ensureInitialized() {
+void ensureInitialized() {
   if (_initialized) {
     return;
   }
   _initialized = true;
   // Hook our async guard into the matcher library.
-  wrapAsync = expectAsync1;
+  wrapAsync = (f, [id]) => expectAsync1(f, id: id);
 
   _tests = <TestCase>[];
   _testRunner = _nextBatch;
@@ -882,4 +863,4 @@
 void disableTest(int testId) => _setTestEnabledState(testId, false);
 
 /** Signature for a test function. */
-typedef void TestFunction();
+typedef dynamic TestFunction();
diff --git a/pkg/unittest/lib/vm_config.dart b/pkg/unittest/lib/vm_config.dart
index 1aabe06..d75cb2a 100644
--- a/pkg/unittest/lib/vm_config.dart
+++ b/pkg/unittest/lib/vm_config.dart
@@ -21,8 +21,6 @@
       exit(1);
     }
   }
-
-  void notifyController(String msg) {}
 }
 
 void useVMConfiguration() {
diff --git a/pkg/unittest/test/matchers_test.dart b/pkg/unittest/test/matchers_test.dart
index 71cdb6b..b11f7a6 100644
--- a/pkg/unittest/test/matchers_test.dart
+++ b/pkg/unittest/test/matchers_test.dart
@@ -158,16 +158,6 @@
             "ArgumentError.");
     });
 
-    test('throwsIllegalJSRegExpException', () {
-      shouldPass(() { throw new IllegalJSRegExpException('',''); },
-          throwsIllegalJSRegExpException);
-      shouldFail(() { throw new Exception(); },
-          throwsIllegalJSRegExpException,
-        "Expected: throws an exception which matches IllegalJSRegExpException "
-        "but:  exception <Exception> does not match "
-            "IllegalJSRegExpException.");
-    });
-
     test('throwsRangeError', () {
       shouldPass(() { throw new RangeError(0); },
           throwsRangeError);
diff --git a/pkg/unittest/test/unittest_test.dart b/pkg/unittest/test/unittest_test.dart
index 0ee50c2..c6ab7a0 100644
--- a/pkg/unittest/test/unittest_test.dart
+++ b/pkg/unittest/test/unittest_test.dart
@@ -20,14 +20,7 @@
 var _testconfig; // test configuration to capture onDone
 
 _defer(void fn()) {
-  // Exploit isolate ports as a platform-independent mechanism to queue a
-  // message at the end of the event loop. Stolen from unittest.dart.
-  final port = new ReceivePort();
-  port.receive((msg, reply) {
-    fn();
-    port.close();
-  });
-  port.toSendPort().send(null, null);
+  return (new Future.immediate(null)).then((_) => guardAsync(fn));
 }
 
 String buildStatusString(int passed, int failed, int errors,
@@ -115,9 +108,14 @@
         () =>_defer(expectAsync0((){ ++_testconfig.count;})));
     } else if (testName == 'excess callback test') {
       test(testName, () {
-        var _callback = expectAsync0(() => ++_testconfig.count);
-        _defer(_callback);
-        _defer(_callback);
+        var _callback0 = expectAsync0(() => ++_testconfig.count);
+        var _callback1 = expectAsync0(() => ++_testconfig.count);
+        var _callback2 = expectAsync0(() {
+          _callback1();
+          _callback1();
+          _callback0();
+        });
+        _defer(_callback2);
       });
     } else if (testName == 'completion test') {
       test(testName, () {
@@ -136,15 +134,13 @@
         _defer(() => guardAsync(() { throw "error!"; }));
       });
     } else if (testName == 'late exception test') {
+      var f;
       test('testOne', () {
-        var f = expectAsync0(() {});
-        _defer(protectAsync0(() {
-          _defer(protectAsync0(() => expect(false, isTrue)));
-          expect(false, isTrue);
-        }));
+        f = expectAsync0(() {});
+        _defer(f);
       });
       test('testTwo', () {
-        _defer(expectAsync0(() {}));
+        _defer(expectAsync0(() { f(); }));
       });
     } else if (testName == 'middle exception test') {
       test('testOne', () { expect(true, isTrue); });
@@ -234,6 +230,107 @@
       // The next test is just to make sure we make steady progress 
       // through the tests.
       test('post groups', () {});
+    } else if (testName == 'test returning future') {
+      test("successful", () {
+        return _defer(() {
+          expect(true, true);
+        });
+      });
+      // We repeat the fail and error tests, because during development
+      // I had a situation where either worked fine on their own, and
+      // error/fail worked, but fail/error would time out.
+      test("error1", () {
+        var callback = expectAsync0((){});
+        var excesscallback = expectAsync0((){});
+        return _defer(() {
+          excesscallback();
+          excesscallback();
+          excesscallback();
+          callback();
+        });
+      });
+      test("fail1", () {
+        return _defer(() {
+          expect(true, false);
+        });
+      });
+      test("error2", () {
+        var callback = expectAsync0((){});
+        var excesscallback = expectAsync0((){});
+        return _defer(() {
+          excesscallback();
+          excesscallback();
+          callback();
+        });
+      });
+      test("fail2", () {
+        return _defer(() {
+          fail('failure');
+        });
+      });
+      test('foo5', () {
+      });
+    } else if (testName == 'test returning future using Timer') {
+      test("successful", () {
+        return _defer(() {
+          Timer.run(() {
+            guardAsync(() {
+              expect(true, true);
+            });
+          });
+        });
+      });
+      test("fail1", () {
+        var callback = expectAsync0((){});
+        return _defer(() {
+          Timer.run(() {
+            guardAsync(() {
+              expect(true, false);
+              callback();
+            });
+          });
+        });
+      });
+      test('error1', () {
+        var callback = expectAsync0((){});
+        var excesscallback = expectAsync0((){});
+        return _defer(() {
+          Timer.run(() {
+            guardAsync(() {
+              excesscallback();
+              excesscallback();
+              callback();
+            });
+          });
+        });
+      });
+      test("fail2", () {
+        var callback = expectAsync0((){});
+        return _defer(() {
+          Timer.run(() {
+            guardAsync(() {
+              fail('failure');
+              callback();
+            });
+          });
+        });
+      });
+      test('error2', () {
+        var callback = expectAsync0((){});
+        var excesscallback = expectAsync0((){});
+        return _defer(() {
+          Timer.run(() {
+            guardAsync(() {
+              excesscallback();
+              excesscallback();
+              excesscallback();
+              callback();
+            });
+          });
+        });
+      });
+      test('foo6', () {
+      });
     }
   });
 }
@@ -267,7 +364,9 @@
     'async exception test',
     'late exception test',
     'middle exception test',
-    'async setup/teardown test'
+    'async setup/teardown test',
+    'test returning future',
+    'test returning future using Timer'
   ];
 
   expected = [
@@ -282,13 +381,13 @@
     buildStatusString(1, 0, 0, 'a ${tests[6]}', count: 0,
         setup: 'setup', teardown: 'teardown'),
     buildStatusString(1, 0, 0, tests[7], count: 1),
-    buildStatusString(0, 0, 1, tests[8], count: 1,
-        message: 'Callback called more times than expected (2 > 1).'),
+    buildStatusString(0, 1, 0, tests[8], count: 1,
+        message: 'Callback called more times than expected (1).'),
     buildStatusString(1, 0, 0, tests[9], count: 10),
     buildStatusString(0, 1, 0, tests[10], message: 'Caught error!'),
     buildStatusString(1, 0, 1, 'testOne',
-        message: 'Callback called after already being marked as done '
-                 '(1).:testTwo:'),
+        message: 'Callback called (2) after test case testOne has already '
+                 'been marked as pass.:testTwo:'),
     buildStatusString(2, 1, 0,
         'testOne::testTwo:Expected: false but: was <true>.:testThree'),
     buildStatusString(2, 0, 3, 
@@ -299,7 +398,21 @@
         'foo3: Test setup failed: Failed to complete setUp:'
         'bad setup/bad teardown foo4:bad setup/bad teardown '
         'foo4: Test teardown failed: Failed to complete tearDown:'
-        'post groups')
+        'post groups'),
+    buildStatusString(2, 4, 0,
+        'successful::'
+        'error1:Callback called more times than expected (1).:'
+        'fail1:Expected: <false> but: was <true>.:'
+        'error2:Callback called more times than expected (1).:'
+        'fail2:failure:'
+        'foo5'),
+    buildStatusString(2, 4, 0,
+        'successful::'
+        'fail1:Expected: <false> but: was <true>.:'
+        'error1:Callback called more times than expected (1).:'
+        'fail2:failure:'
+        'error2:Callback called more times than expected (1).:'
+        'foo6'),
   ];
 
   actual = [];
diff --git a/pkg/webdriver/lib/src/base64decoder.dart b/pkg/webdriver/lib/src/base64decoder.dart
index 616f2f4..7e9175b 100644
--- a/pkg/webdriver/lib/src/base64decoder.dart
+++ b/pkg/webdriver/lib/src/base64decoder.dart
@@ -11,7 +11,7 @@
 class Base64Decoder {
 
   static int getVal(String s, pos) {
-    int code = s.charCodeAt(pos);
+    int code = s.codeUnitAt(pos);
     if (code >= 65 && code < (65+26)) { // 'A'..'Z'
       return code - 65;
     } else if (code >= 97 && code < (97+26)) { // 'a'..'z'
diff --git a/pkg/webdriver/lib/webdriver.dart b/pkg/webdriver/lib/webdriver.dart
index ffb0dff..41d0cbc 100644
--- a/pkg/webdriver/lib/webdriver.dart
+++ b/pkg/webdriver/lib/webdriver.dart
@@ -276,15 +276,14 @@
           results  = sbuf.toString().trim();
           // For some reason we get a bunch of NULs on the end
           // of the text and the json.parse blows up on these, so
-          // strip them. We have to do this the hard way as
-          // replaceAll('\0', '') does not work.
+          // strip them.
           // These NULs can be seen in the TCP packet, so it is not
           // an issue with character encoding; it seems to be a bug
           // in WebDriver stack.
           for (var i = results.length; --i >= 0;) {
-            var code = results.charCodeAt(i);
+            var code = results.codeUnitAt(i);
             if (code != 0) {
-              results = results.substring(0, i+1);
+              results = results.substring(0, i + 1);
               break;
             }
           }
diff --git a/pkg/yaml/lib/composer.dart b/pkg/yaml/lib/composer.dart
index e9c1879..e22159f 100644
--- a/pkg/yaml/lib/composer.dart
+++ b/pkg/yaml/lib/composer.dart
@@ -120,12 +120,7 @@
 
     match = new RegExp("^0o([0-7]+)\$").firstMatch(content);
     if (match != null) {
-      // TODO(nweiz): clean this up when Dart can parse an octal string
-      var n = 0;
-      for (var c in match.group(1).charCodes) {
-        n *= 8;
-        n += c - 48;
-      }
+      int n = int.parse(match.group(1), radix: 8);
       return new _ScalarNode(_Tag.yaml("int"), value: n);
     }
 
@@ -153,15 +148,13 @@
 
     match = new RegExp("^([+-]?)\.(inf|Inf|INF)\$").firstMatch(content);
     if (match != null) {
-      var infinityStr = match.group(1) == "-" ? "-Infinity" : "Infinity";
-      return new _ScalarNode(_Tag.yaml("float"),
-          value: double.parse(infinityStr));
+      var value = match.group(1) == "-" ? -double.INFINITY : double.INFINITY;
+      return new _ScalarNode(_Tag.yaml("float"), value: value);
     }
 
     match = new RegExp("^\.(nan|NaN|NAN)\$").firstMatch(content);
     if (match != null) {
-      return new _ScalarNode(_Tag.yaml("float"),
-          value: double.parse("NaN"));
+      return new _ScalarNode(_Tag.yaml("float"), value: double.NAN);
     }
 
     return null;
diff --git a/pkg/yaml/lib/model.dart b/pkg/yaml/lib/model.dart
index 9f1474e..5c09aa5 100644
--- a/pkg/yaml/lib/model.dart
+++ b/pkg/yaml/lib/model.dart
@@ -149,7 +149,7 @@
       // TODO(nweiz): This could be faster if we used a RegExp to check for
       // special characters and short-circuited if they didn't exist.
 
-      var escapedValue = value.charCodes.map((c) {
+      var escapedValue = value.codeUnits.map((c) {
         switch (c) {
         case _Parser.TAB: return "\\t";
         case _Parser.LF: return "\\n";
diff --git a/pkg/yaml/lib/parser.dart b/pkg/yaml/lib/parser.dart
index f2f255e..386bb59 100644
--- a/pkg/yaml/lib/parser.dart
+++ b/pkg/yaml/lib/parser.dart
@@ -172,7 +172,7 @@
   /// forward one character. Also updates the current line and column numbers.
   int next() {
     if (pos == len) return -1;
-    var char = s.charCodeAt(pos++);
+    var char = s.codeUnitAt(pos++);
     if (isBreak(char)) {
       line++;
       column = 0;
@@ -193,14 +193,14 @@
     return char;
   }
 
-  /// Returns the character at the current position, or the character [i]
+  /// Returns the code unit at the current position, or the character [i]
   /// characters after the current position.
   ///
   /// Returns -1 if this would return a character after the end or before the
   /// beginning of the input string.
   int peek([int i = 0]) {
     var peekPos = pos + i;
-    return (peekPos >= len || peekPos < 0) ? -1 : s.charCodeAt(peekPos);
+    return (peekPos >= len || peekPos < 0) ? -1 : s.codeUnitAt(peekPos);
   }
 
   /// The truthiness operator. Returns `false` if [obj] is `null` or `false`,
@@ -304,7 +304,7 @@
   ///
   /// Returns whether or not the string was consumed.
   bool rawString(String str) =>
-    nAtOnce(str.length, (c, i) => str.charCodeAt(i) == c);
+    nAtOnce(str.length, (c, i) => str.codeUnitAt(i) == c);
 
   /// Consumes and returns a string of characters matching [matcher], or null if
   /// there are no such characters.
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 51d6740..8f41e50 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -345,6 +345,9 @@
       'sources': [
         'main.cc',
         'builtin_nolib.cc',
+        'vmstats.h',
+        'vmstats_impl.cc',
+        'vmstats_impl.h',
         '<(snapshot_cc_file)',
       ],
       'conditions': [
@@ -384,6 +387,9 @@
       'sources': [
         'main.cc',
         'builtin.cc',
+        'vmstats.h',
+        'vmstats_impl.cc',
+        'vmstats_impl.h',
         # Include generated source files.
         '<(builtin_cc_file)',
         '<(io_cc_file)',
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 85bb4d7..75b4edf 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -37,7 +37,7 @@
   V(File_SetPosition, 2)                                                       \
   V(File_Truncate, 2)                                                          \
   V(File_Length, 1)                                                            \
-  V(File_LengthFromName, 1)                                                    \
+  V(File_LengthFromPath, 1)                                                    \
   V(File_LastModified, 1)                                                      \
   V(File_Flush, 1)                                                             \
   V(File_Create, 1)                                                            \
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index ea53472..a780780 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -15,7 +15,7 @@
 const char* DartUtils::original_working_directory = NULL;
 const char* DartUtils::kDartScheme = "dart:";
 const char* DartUtils::kDartExtensionScheme = "dart-ext:";
-const char* DartUtils::kASyncLibURL = "dart:async";
+const char* DartUtils::kAsyncLibURL = "dart:async";
 const char* DartUtils::kBuiltinLibURL = "dart:builtin";
 const char* DartUtils::kCoreLibURL = "dart:core";
 const char* DartUtils::kIOLibURL = "dart:io";
@@ -394,7 +394,7 @@
                                      print);
 
   // Setup the 'timer' factory.
-  Dart_Handle url = NewString(kASyncLibURL);
+  Dart_Handle url = NewString(kAsyncLibURL);
   DART_CHECK_VALID(url);
   Dart_Handle async_lib = Dart_LookupLibrary(url);
   DART_CHECK_VALID(async_lib);
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 07404e5..7f539de 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -159,7 +159,7 @@
 
   static const char* kDartScheme;
   static const char* kDartExtensionScheme;
-  static const char* kASyncLibURL;
+  static const char* kAsyncLibURL;
   static const char* kBuiltinLibURL;
   static const char* kCoreLibURL;
   static const char* kIOLibURL;
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index e366fc2..3a2c455 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -180,12 +180,25 @@
       Dart_SetReturnValue(args, err);
     } else {
       if (bytes_read < length) {
-        // TODO(ager): cache the 'length' string if this becomes a bottle neck.
-        Dart_SetField(external_array,
-                      DartUtils::NewString("length"),
-                      Dart_NewInteger(bytes_read));
+        const int kNumArgs = 3;
+        Dart_Handle dart_args[kNumArgs];
+        dart_args[0] = external_array;
+        dart_args[1] = Dart_NewInteger(0);
+        dart_args[2] = Dart_NewInteger(bytes_read);
+        // TODO(sgjesse): Cache the _makeUint8ListView function somewhere.
+        Dart_Handle io_lib =
+            Dart_LookupLibrary(DartUtils::NewString("dart:io"));
+        if (Dart_IsError(io_lib)) Dart_PropagateError(io_lib);
+        Dart_Handle array_view =
+            Dart_Invoke(io_lib,
+                        DartUtils::NewString("_makeUint8ListView"),
+                        kNumArgs,
+                        dart_args);
+        if (Dart_IsError(array_view)) Dart_PropagateError(array_view);
+        Dart_SetReturnValue(args, array_view);
+      } else {
+        Dart_SetReturnValue(args, external_array);
       }
-      Dart_SetReturnValue(args, external_array);
     }
   } else {
     OSError os_error(-1, "Invalid argument", OSError::kUnknown);
@@ -349,11 +362,11 @@
 }
 
 
-void FUNCTION_NAME(File_LengthFromName)(Dart_NativeArguments args) {
+void FUNCTION_NAME(File_LengthFromPath)(Dart_NativeArguments args) {
   Dart_EnterScope();
-  const char* name =
+  const char* path =
       DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
-  intptr_t return_value = File::LengthFromName(name);
+  intptr_t return_value = File::LengthFromPath(path);
   if (return_value >= 0) {
     Dart_SetReturnValue(args, Dart_NewInteger(return_value));
   } else {
@@ -689,10 +702,10 @@
 }
 
 
-static CObject* FileLengthFromNameRequest(const CObjectArray& request) {
+static CObject* FileLengthFromPathRequest(const CObjectArray& request) {
   if (request.Length() == 2 && request[1]->IsString()) {
-    CObjectString filename(request[1]);
-    intptr_t return_value = File::LengthFromName(filename.CString());
+    CObjectString filepath(request[1]);
+    intptr_t return_value = File::LengthFromPath(filepath.CString());
     if (return_value >= 0) {
       return new CObjectIntptr(CObject::NewIntptr(return_value));
     } else {
@@ -705,8 +718,8 @@
 
 static CObject* FileLastModifiedRequest(const CObjectArray& request) {
   if (request.Length() == 2 && request[1]->IsString()) {
-    CObjectString filename(request[1]);
-    int64_t return_value = File::LastModified(filename.CString());
+    CObjectString filepath(request[1]);
+    int64_t return_value = File::LastModified(filepath.CString());
     if (return_value >= 0) {
       return new CObjectIntptr(CObject::NewInt64(return_value * kMSPerSecond));
     } else {
@@ -933,8 +946,8 @@
         case File::kLengthRequest:
           response = FileLengthRequest(request);
           break;
-        case File::kLengthFromNameRequest:
-          response = FileLengthFromNameRequest(request);
+        case File::kLengthFromPathRequest:
+          response = FileLengthFromPathRequest(request);
           break;
         case File::kLastModifiedRequest:
           response = FileLastModifiedRequest(request);
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 53a1e44..05be61c 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -56,7 +56,7 @@
     kSetPositionRequest = 8,
     kTruncateRequest = 9,
     kLengthRequest = 10,
-    kLengthFromNameRequest = 11,
+    kLengthFromPathRequest = 11,
     kLastModifiedRequest = 12,
     kFlushRequest = 13,
     kReadByteRequest = 14,
@@ -103,25 +103,25 @@
   // Returns whether the file has been closed.
   bool IsClosed();
 
-  // Open the file with the given name. The file is always opened for
+  // Open the file with the given path. The file is always opened for
   // reading. If mode contains kWrite the file is opened for both
   // reading and writing. If mode contains kWrite and the file does
   // not exist the file is created. The file is truncated to length 0 if
   // mode contains kTruncate.
-  static File* Open(const char* name, FileOpenMode mode);
+  static File* Open(const char* path, FileOpenMode mode);
 
   // Create a file object for the specified stdio file descriptor
   // (stdin, stout or stderr).
   static File* OpenStdio(int fd);
 
-  static bool Exists(const char* name);
-  static bool Create(const char* name);
-  static bool Delete(const char* name);
-  static off_t LengthFromName(const char* name);
-  static time_t LastModified(const char* name);
-  static bool IsAbsolutePath(const char* pathname);
-  static char* GetCanonicalPath(const char* name);
-  static char* GetContainingDirectory(char* name);
+  static bool Exists(const char* path);
+  static bool Create(const char* path);
+  static bool Delete(const char* path);
+  static off_t LengthFromPath(const char* path);
+  static time_t LastModified(const char* path);
+  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 StdioHandleType GetStdioHandleType(int fd);
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index 7ae6415..390ef4d 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -168,7 +168,7 @@
 }
 
 
-off_t File::LengthFromName(const char* name) {
+off_t File::LengthFromPath(const char* name) {
   struct stat st;
   if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
     return st.st_size;
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 3a73135..459a692 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -168,7 +168,7 @@
 }
 
 
-off_t File::LengthFromName(const char* name) {
+off_t File::LengthFromPath(const char* name) {
   struct stat st;
   if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
     return st.st_size;
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 14b2fd8..37b5328 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -170,7 +170,7 @@
 }
 
 
-off_t File::LengthFromName(const char* name) {
+off_t File::LengthFromPath(const char* name) {
   struct stat st;
   if (TEMP_FAILURE_RETRY(stat(name, &st)) == 0) {
     return st.st_size;
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index eb55dae..2355f9d 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -7,15 +7,15 @@
 }
 
 patch class _File {
-  /* patch */ static _exists(String name) native "File_Exists";
-  /* patch */ static _create(String name) native "File_Create";
-  /* patch */ static _delete(String name) native "File_Delete";
-  /* patch */ static _directory(String name) native "File_Directory";
-  /* patch */ static _lengthFromName(String name) native "File_LengthFromName";
-  /* patch */ static _lastModified(String name) native "File_LastModified";
-  /* patch */ static _open(String name, int mode) native "File_Open";
+  /* patch */ static _exists(String path) native "File_Exists";
+  /* patch */ static _create(String path) native "File_Create";
+  /* patch */ static _delete(String path) native "File_Delete";
+  /* patch */ static _directory(String path) native "File_Directory";
+  /* patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
+  /* patch */ static _lastModified(String path) native "File_LastModified";
+  /* patch */ static _open(String path, int mode) native "File_Open";
   /* patch */ static int _openStdio(int fd) native "File_OpenStdio";
-  /* patch */ static _fullPath(String name) native "File_FullPath";
+  /* patch */ static _fullPath(String path) native "File_FullPath";
 }
 
 patch class _RandomAccessFile {
@@ -34,3 +34,7 @@
   /* patch */ static _length(int id) native "File_Length";
   /* patch */ static _flush(int id) native "File_Flush";
 }
+
+List<int> _makeUint8ListView(List<int> source, int from, int to) {
+  return new Uint8List.view(source.asByteArray(), from, to);
+}
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 2ce097d..e18071a 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -165,7 +165,7 @@
 }
 
 
-off_t File::LengthFromName(const char* name) {
+off_t File::LengthFromPath(const char* name) {
   struct _stat st;
   const wchar_t* system_name = StringUtils::Utf8ToWide(name);
   int stat_status = _wstat(system_name, &st);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 6a06bf3..4ccc87a 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -20,6 +20,7 @@
 #include "bin/log.h"
 #include "bin/platform.h"
 #include "bin/process.h"
+#include "bin/vmstats_impl.h"
 #include "platform/globals.h"
 
 // snapshot_buffer points to a snapshot if we link in a snapshot otherwise
@@ -47,6 +48,9 @@
 static const char* debug_ip = DEFAULT_DEBUG_IP;
 static int debug_port = 0;
 
+// Global state that defines the VmStats web server port and root directory.
+static int vmstats_port = -1;
+static const char* vmstats_root = NULL;
 
 // Value of the --package-root flag.
 // (This pointer points into an argv buffer and does not need to be
@@ -164,6 +168,31 @@
 }
 
 
+static bool ProcessVmStatsOption(const char* port) {
+  ASSERT(port != NULL);
+  if (*port == '\0') {
+    vmstats_port = 0;  // Dynamically assigned port number.
+  } else {
+    if ((*port == '=') || (*port == ':')) {
+      vmstats_port = atoi(port + 1);
+    }
+  }
+  if (vmstats_port < 0) {
+    Log::PrintErr("unrecognized --stats option syntax. "
+                    "Use --stats[:<port number>]\n");
+    return false;
+  }
+  return true;
+}
+
+
+static bool ProcessVmStatsRootOption(const char* arg) {
+  ASSERT(arg != NULL);
+  vmstats_root = arg;
+  return true;
+}
+
+
 static bool ProcessGenScriptSnapshotOption(const char* filename) {
   if (filename != NULL && strlen(filename) != 0) {
     // Ensure that are already running using a full snapshot.
@@ -207,6 +236,8 @@
   { "--debug", ProcessDebugOption },
   { "--use-script-snapshot=", ProcessUseScriptSnapshotOption },
   { "--generate-script-snapshot=", ProcessGenScriptSnapshotOption },
+  { "--stats-root=", ProcessVmStatsRootOption },
+  { "--stats", ProcessVmStatsOption },
   { NULL, NULL }
 };
 
@@ -489,6 +520,7 @@
     return false;
   }
   Dart_ExitScope();
+  VmStats::AddIsolate(reinterpret_cast<IsolateData*>(data), isolate);
   return true;
 }
 
@@ -551,6 +583,14 @@
 "--generate-script-snapshot=<file_name>\n"
 "  loads Dart script and generates a snapshot in the specified file\n"
 "\n"
+"--stats[:<port number>]\n"
+"  enables VM stats service and listens on specified port for HTTP requests\n"
+"  (default port number is dynamically assigned)\n"
+"\n"
+"--stats-root=<path>\n"
+"  where to find static files used by the vmstats application\n"
+"  (used during vmstats plug-in development)\n"
+"\n"
 "The following options are only used for VM development and may\n"
 "be changed in any future version:\n");
     const char* print_flags = "--print_flags";
@@ -628,6 +668,7 @@
 
 static void ShutdownIsolate(void* callback_data) {
   IsolateData* isolate_data = reinterpret_cast<IsolateData*>(callback_data);
+  VmStats::RemoveIsolate(isolate_data);
   EventHandler* handler = isolate_data->event_handler;
   if (handler != NULL) handler->Shutdown();
   delete isolate_data;
@@ -714,6 +755,10 @@
 
   Dart_EnterScope();
 
+  if (vmstats_port >= 0) {
+    VmStats::Start(vmstats_port, vmstats_root);
+  }
+
   if (generate_script_snapshot) {
     // First create a snapshot.
     Dart_Handle result;
@@ -774,6 +819,9 @@
   }
 
   Dart_ExitScope();
+  if (vmstats_port >= 0) {
+    VmStats::Stop();
+  }
   // Shutdown the isolate.
   Dart_ShutdownIsolate();
   // Terminate process exit-code handler.
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 29913b1..4468ec0 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -53,7 +53,7 @@
       throw new ArgumentError("Arguments is not a List: $arguments");
     }
     int len = arguments.length;
-    _arguments = new List<String>.fixedLength(len);
+    _arguments = new List<String>(len);
     for (int i = 0; i < len; i++) {
       var arg = arguments[i];
       if (arg is !String) {
@@ -107,14 +107,14 @@
 
       // Replace any number of '\' followed by '"' with
       // twice as many '\' followed by '\"'.
-      var backslash = '\\'.charCodeAt(0);
+      var backslash = '\\'.codeUnitAt(0);
       var sb = new StringBuffer();
       var nextPos = 0;
       var quotePos = argument.indexOf('"', nextPos);
       while (quotePos != -1) {
         var numBackslash = 0;
         var pos = quotePos - 1;
-        while (pos >= 0 && argument.charCodeAt(pos) == backslash) {
+        while (pos >= 0 && argument.codeUnitAt(pos) == backslash) {
           numBackslash++;
           pos--;
         }
@@ -134,7 +134,7 @@
       sb = new StringBuffer('"');
       sb.add(result);
       nextPos = argument.length - 1;
-      while (argument.charCodeAt(nextPos) == backslash) {
+      while (argument.codeUnitAt(nextPos) == backslash) {
         sb.add('\\');
         nextPos--;
       }
@@ -156,7 +156,7 @@
     var completer = new Completer();
     // TODO(ager): Make the actual process starting really async instead of
     // simulating it with a timer.
-    new Timer(0, (_) {
+    Timer.run(() {
       var status = new _ProcessStartStatus();
       bool success = _startNative(_path,
                                   _arguments,
@@ -181,7 +181,7 @@
       // callback when a process terminates.
       int exitDataRead = 0;
       final int EXIT_DATA_SIZE = 8;
-      List<int> exitDataBuffer = new List<int>.fixedLength(EXIT_DATA_SIZE);
+      List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE);
       _exitHandler.listen((data) {
 
         int exitCode(List<int> ints) {
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 31e55a3..db68c32 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -41,6 +41,8 @@
   static int GetType(intptr_t fd);
   static intptr_t GetStdioHandle(int num);
   static void Close(intptr_t fd);
+  static bool SetNonBlocking(intptr_t fd);
+  static bool SetBlocking(intptr_t fd);
 
   // Perform a IPv4 hostname lookup. Returns the hostname string in
   // IPv4 dotted-decimal format.
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 8bd9683..07a7a10 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -34,7 +34,7 @@
   }
 
   FDUtils::SetCloseOnExec(fd);
-  FDUtils::SetNonBlocking(fd);
+  Socket::SetNonBlocking(fd);
 
   server = gethostbyname(host);
   if (server == NULL) {
@@ -218,7 +218,7 @@
     return -1;
   }
 
-  FDUtils::SetNonBlocking(fd);
+  Socket::SetNonBlocking(fd);
   return fd;
 }
 
@@ -247,7 +247,7 @@
       socket = kTemporaryFailure;
     }
   } else {
-    FDUtils::SetNonBlocking(socket);
+    Socket::SetNonBlocking(socket);
   }
   return socket;
 }
@@ -264,4 +264,14 @@
   }
 }
 
+
+bool Socket::SetNonBlocking(intptr_t fd) {
+  return FDUtils::SetNonBlocking(fd);
+}
+
+
+bool Socket::SetBlocking(intptr_t fd) {
+  return FDUtils::SetBlocking(fd);
+}
+
 #endif  // defined(TARGET_OS_ANDROID)
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 746adcf..cdaab92 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -36,7 +36,7 @@
   }
 
   FDUtils::SetCloseOnExec(fd);
-  FDUtils::SetNonBlocking(fd);
+  Socket::SetNonBlocking(fd);
 
   static const size_t kTempBufSize = 1024;
   char temp_buf[kTempBufSize];
@@ -230,7 +230,7 @@
     return -1;
   }
 
-  FDUtils::SetNonBlocking(fd);
+  Socket::SetNonBlocking(fd);
   return fd;
 }
 
@@ -259,7 +259,7 @@
       socket = kTemporaryFailure;
     }
   } else {
-    FDUtils::SetNonBlocking(socket);
+    Socket::SetNonBlocking(socket);
   }
   return socket;
 }
@@ -276,4 +276,14 @@
   }
 }
 
+
+bool Socket::SetNonBlocking(intptr_t fd) {
+  return FDUtils::SetNonBlocking(fd);
+}
+
+
+bool Socket::SetBlocking(intptr_t fd) {
+  return FDUtils::SetBlocking(fd);
+}
+
 #endif  // defined(TARGET_OS_LINUX)
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 50ad16f..849e1fa 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -36,7 +36,7 @@
   }
 
   FDUtils::SetCloseOnExec(fd);
-  FDUtils::SetNonBlocking(fd);
+  Socket::SetNonBlocking(fd);
 
   server = gethostbyname(host);
   if (server == NULL) {
@@ -226,7 +226,7 @@
     return -1;
   }
 
-  FDUtils::SetNonBlocking(fd);
+  Socket::SetNonBlocking(fd);
   return fd;
 }
 
@@ -245,7 +245,7 @@
       socket = kTemporaryFailure;
     }
   } else {
-    FDUtils::SetNonBlocking(socket);
+    Socket::SetNonBlocking(socket);
   }
   return socket;
 }
@@ -262,4 +262,14 @@
   }
 }
 
+
+bool Socket::SetNonBlocking(intptr_t fd) {
+  return FDUtils::SetNonBlocking(fd);
+}
+
+
+bool Socket::SetBlocking(intptr_t fd) {
+  return FDUtils::SetBlocking(fd);
+}
+
 #endif  // defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 15dd4c7..3b9aaae 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -123,17 +123,17 @@
   }
 
   _NativeSocket.normal() : typeFlags = TYPE_NORMAL_SOCKET {
-    eventHandlers = new List.fixedLength(EVENT_COUNT + 1);
+    eventHandlers = new List(EVENT_COUNT + 1);
     _EventHandler._start();
   }
 
   _NativeSocket.listen() : typeFlags = TYPE_LISTENING_SOCKET {
-    eventHandlers = new List.fixedLength(EVENT_COUNT + 1);
+    eventHandlers = new List(EVENT_COUNT + 1);
     _EventHandler._start();
   }
 
   _NativeSocket.pipe() : typeFlags = TYPE_PIPE {
-    eventHandlers = new List.fixedLength(EVENT_COUNT + 1);
+    eventHandlers = new List(EVENT_COUNT + 1);
     _EventHandler._start();
   }
 
@@ -152,6 +152,7 @@
     if (len != null && len <= 0) {
       throw new ArgumentError("Illegal length $len");
     }
+    if (isClosed) return null;
     var result = nativeRead(len == null ? -1 : len);
     if (result is OSError) {
       reportError(result, "Read failed");
@@ -395,7 +396,7 @@
   nativeRead(int len) native "Socket_Read";
   nativeWrite(List<int> buffer, int offset, int bytes)
       native "Socket_WriteList";
-  bool nativeCreateConnect(String host, int port) native "Socket_CreateConnect";
+  nativeCreateConnect(String host, int port) native "Socket_CreateConnect";
   nativeCreateBindListen(String address, int port, int backlog)
       native "ServerSocket_CreateBindListen";
   nativeAccept(_NativeSocket socket) native "ServerSocket_Accept";
@@ -658,17 +659,23 @@
   _SocketStreamConsumer(this.socket);
 
   Future<Socket> consume(Stream<List<int>> stream) {
-    subscription = stream.listen(
-        (data) {
-          assert(!paused);
-          assert(buffer == null);
-          buffer = data;
-          offset = 0;
-          write();
-        },
-        onDone: () {
-          socket._consumerDone();
-        });
+    if (socket._raw != null) {
+      subscription = stream.listen(
+          (data) {
+            assert(!paused);
+            assert(buffer == null);
+            buffer = data;
+            offset = 0;
+            write();
+          },
+          onError: (error) {
+            socket._consumerDone(error);
+          },
+          onDone: () {
+            socket._consumerDone();
+          },
+          unsubscribeOnError: true);
+    }
     return socket._doneFuture;
   }
 
@@ -697,6 +704,7 @@
         }
       }
     } catch (e) {
+      stop();
       socket._consumerDone(e);
     }
   }
@@ -778,8 +786,8 @@
   void destroy() {
     // Destroy can always be called to get rid of a socket.
     if (_raw == null) return;
-    _closeRawSocket();
     _consumer.stop();
+    _closeRawSocket();
     _controllerClosed = true;
     _controller.close();
   }
@@ -895,11 +903,11 @@
   }
 
   void _consumerDone([error]) {
+    _done(error);
     if (_raw != null) {
       _raw.shutdown(SocketDirection.SEND);
       _disableWriteEvent();
     }
-    _done(error);
   }
 }
 
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index a60f1e4..4fcf156 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -288,4 +288,26 @@
   client_socket->Close();
 }
 
+
+static bool SetBlockingHelper(intptr_t fd, bool blocking) {
+  SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
+  u_long iMode = blocking ? 0 : 1;
+  int status = ioctlsocket(handle->socket(), FIONBIO, &iMode);
+  if (status != NO_ERROR) {
+    Log::PrintErr("ioctlsocket FIONBIO failed: %d\n", status);
+    return false;
+  }
+  return true;
+}
+
+
+bool Socket::SetNonBlocking(intptr_t fd) {
+  return SetBlockingHelper(fd, false);
+}
+
+
+bool Socket::SetBlocking(intptr_t fd) {
+  return SetBlockingHelper(fd, true);
+}
+
 #endif  // defined(TARGET_OS_WINDOWS)
diff --git a/runtime/bin/vmstats.h b/runtime/bin/vmstats.h
new file mode 100644
index 0000000..14716e8
--- /dev/null
+++ b/runtime/bin/vmstats.h
@@ -0,0 +1,37 @@
+// 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.
+
+#ifndef BIN_VMSTATS_H_
+#define BIN_VMSTATS_H_
+
+#include "include/dart_api.h"
+
+/**
+ * A VM status callback. Status plug-ins implement and register this
+ * function using Dart_RegisterStatusPlugin. When Dart_GetVMStatus is
+ * called, each callback is invoked to provide the requested information,
+ * and the first one to do so "wins".
+ *
+ * Note: status requests execute outside of an isolate (which is why
+ * handles aren't used).
+ *
+ * \param request an optional string that defines REST-like parameters
+ *     to define what information is requested.
+ *
+ * \return Returns a valid JSON string, allocated from C heap. The caller
+ *     is responsible for releasing this string. NULL is returned if the
+ *     callback didn't handle that request.
+ */
+typedef char* (*Dart_VmStatusCallback)(const char* request);
+
+
+/**
+ * Register a VM status plug-in. The specified status type must not already
+ * have a registered plug-in.
+ *
+ * \return 0 if the plug-in was registered, or -1 if there is an error.
+ */
+DART_EXPORT int Dart_RegisterVmStatusPlugin(Dart_VmStatusCallback callback);
+
+#endif  // BIN_VMSTATS_H_
diff --git a/runtime/bin/vmstats_impl.cc b/runtime/bin/vmstats_impl.cc
new file mode 100644
index 0000000..e7e2812
--- /dev/null
+++ b/runtime/bin/vmstats_impl.cc
@@ -0,0 +1,332 @@
+// 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.
+
+#include "bin/vmstats_impl.h"
+
+#include <sstream>
+
+#include "bin/file.h"
+#include "bin/log.h"
+#include "bin/platform.h"
+#include "bin/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+#include "include/dart_debugger_api.h"
+#include "platform/json.h"
+
+#define BUFSIZE 8192
+#define RETRY_PAUSE 100  // milliseconds
+
+static const char* INDEX_HTML = "index.html";
+static const char* VMSTATS_HTML = "vmstats.html";
+static const char* DEFAULT_HOST = "localhost";
+
+// Global static pointer used to ensure a single instance of the class.
+VmStats* VmStats::instance_ = NULL;
+dart::Monitor* VmStats::instance_monitor_;
+dart::Mutex* VmStatusService::mutex_;
+
+
+void VmStats::Start(int port, const char* root_dir) {
+  if (instance_ != NULL) {
+    FATAL("VmStats already started.");
+  }
+  instance_ = new VmStats();
+  instance_monitor_ = new dart::Monitor();
+  VmStatusService::InitOnce();
+  Socket::Initialize();
+
+  if (root_dir != NULL) {
+    instance_->root_directory_ = root_dir;
+  }
+
+  // TODO(tball): allow host to be specified.
+  char* host = const_cast<char*>(DEFAULT_HOST);
+  OSError* os_error;
+  const char* host_ip = Socket::LookupIPv4Address(host, &os_error);
+  if (host_ip == NULL) {
+    Log::PrintErr("Failed IP lookup of VmStats host %s: %s\n",
+                  host, os_error->message());
+    return;
+  }
+
+  const intptr_t BACKLOG = 128;  // Default value from HttpServer.dart
+  int64_t address = ServerSocket::CreateBindListen(host_ip, port, BACKLOG);
+  if (address < 0) {
+    Log::PrintErr("Failed binding VmStats socket: %s:%d\n", host, port);
+    return;
+  }
+  instance_->bind_address_ = address;
+  Log::Print("VmStats URL: http://%s:%"Pd"/\n", host, Socket::GetPort(address));
+
+  MonitorLocker ml(instance_monitor_);
+  instance_->running_ = true;
+  int err = dart::Thread::Start(WebServer, address);
+  if (err != 0) {
+    Log::PrintErr("Failed starting VmStats thread: %d\n", err);
+    Shutdown();
+  }
+}
+
+
+void VmStats::Stop() {
+  ASSERT(instance_ != NULL);
+  MonitorLocker ml(instance_monitor_);
+  instance_->running_ = false;
+}
+
+
+void VmStats::Shutdown() {
+  ASSERT(instance_ != NULL);
+  MonitorLocker ml(instance_monitor_);
+  Socket::Close(instance_->bind_address_);
+  delete instance_;
+  instance_ = NULL;
+}
+
+
+void VmStats::AddIsolate(IsolateData* isolate_data,
+                         Dart_Isolate isolate) {
+  if (instance_ != NULL) {
+    MonitorLocker ml(instance_monitor_);
+    instance_->isolate_table_[isolate_data] = isolate;
+  }
+}
+
+
+void VmStats::RemoveIsolate(IsolateData* isolate_data) {
+  if (instance_ != NULL) {
+    MonitorLocker ml(instance_monitor_);
+    instance_->isolate_table_.erase(isolate_data);
+  }
+}
+
+
+static const char* ContentType(const char* url) {
+  const char* suffix = strrchr(url, '.');
+  if (suffix != NULL) {
+    if (!strcmp(suffix, ".html")) {
+      return "text/html; charset=UTF-8";
+    }
+    if (!strcmp(suffix, ".dart")) {
+      return "application/dart; charset=UTF-8";
+    }
+    if (!strcmp(suffix, ".js")) {
+      return "application/javascript; charset=UTF-8";
+    }
+    if (!strcmp(suffix, ".css")) {
+      return "text/css; charset=UTF-8";
+    }
+    if (!strcmp(suffix, ".gif")) {
+      return "image/gif";
+    }
+    if (!strcmp(suffix, ".png")) {
+      return "image/png";
+    }
+    if (!strcmp(suffix, ".jpg") || !strcmp(suffix, ".jpeg")) {
+      return "image/jpeg";
+    }
+  }
+  return "text/plain";
+}
+
+
+void VmStats::WebServer(uword bind_address) {
+  while (true) {
+    intptr_t socket = ServerSocket::Accept(bind_address);
+    if (socket == ServerSocket::kTemporaryFailure) {
+      // Not a real failure, woke up but no connection available.
+
+      // Use MonitorLocker.Wait(), since it has finer granularity than sleep().
+      dart::Monitor m;
+      MonitorLocker ml(&m);
+      ml.Wait(RETRY_PAUSE);
+
+      continue;
+    }
+    if (socket < 0) {
+      // Stop() closed the socket.
+      return;
+    }
+    Socket::SetBlocking(socket);
+
+    // TODO(tball): rewrite this to use STL, so as to eliminate the static
+    // buffer and support resource URLs that are longer than BUFSIZE.
+
+    // Read request.
+    char buffer[BUFSIZE + 1];
+    intptr_t len = Socket::Read(socket, buffer, BUFSIZE);
+    if (len <= 0) {
+      // Invalid HTTP request, ignore.
+      continue;
+    }
+    buffer[len] = '\0';
+
+    // Verify it's a GET request.
+    // TODO(tball): support POST requests.
+    if (strncmp("GET ", buffer, 4) != 0 && strncmp("get ", buffer, 4) != 0) {
+      Log::PrintErr("Unsupported HTTP request type");
+      const char* response = "HTTP/1.1 403 Forbidden\n"
+          "Content-Length: 120\n"
+          "Connection: close\n"
+          "Content-Type: text/html\n\n"
+          "<html><head>\n<title>403 Forbidden</title>\n</head>"
+          "<body>\n<h1>Forbidden</h1>\nUnsupported HTTP request type\n</body>"
+          "</html>\n";
+      Socket::Write(socket, response, strlen(response));
+      Socket::Close(socket);
+      continue;
+    }
+
+    // Extract GET URL, and null-terminate URL in case request line has
+    // HTTP version.
+    for (int i = 4; i < len; i++) {
+      if (buffer[i] == ' ') {
+        buffer[i] = '\0';
+      }
+    }
+    char* url = &buffer[4];
+
+    Log::Print("vmstats: %s requested\n", url);
+    char* content = NULL;
+
+    // Check for VmStats-specific URLs.
+    if (strcmp(url, "/isolates") == 0) {
+      content = instance_->IsolatesStatus();
+    } else {
+      // Check plug-ins.
+      content = VmStatusService::GetVmStatus(url);
+    }
+
+    if (content != NULL) {
+      size_t content_len = strlen(content);
+      len = snprintf(buffer, BUFSIZE,
+          "HTTP/1.1 200 OK\nContent-Type: application/json; charset=UTF-8\n"
+          "Content-Length: %"Pu"\n\n",
+          content_len);
+      Socket::Write(socket, buffer, strlen(buffer));
+      Socket::Write(socket, content, content_len);
+      Socket::Write(socket, "\n", 1);
+      Socket::Write(socket, buffer, strlen(buffer));
+      free(content);
+    } else {
+      // No status content with this URL, return file or resource content.
+      std::string path(instance_->root_directory_);
+      path.append(url);
+
+      // Expand directory URLs.
+      if (strcmp(url, "/") == 0) {
+        path.append(VMSTATS_HTML);
+      } else if (url[strlen(url) - 1] == '/') {
+        path.append(INDEX_HTML);
+      }
+
+      bool success = false;
+      if (File::Exists(path.c_str())) {
+        File* f = File::Open(path.c_str(), File::kRead);
+        if (f != NULL) {
+          intptr_t len = f->Length();
+          char* text_buffer = reinterpret_cast<char*>(malloc(len));
+          if (f->ReadFully(text_buffer, len)) {
+            const char* content_type = ContentType(path.c_str());
+            snprintf(buffer, BUFSIZE,
+                "HTTP/1.1 200 OK\nContent-Type: %s\n"
+                "Content-Length: %"Pu"\n\n",
+                content_type, len);
+            Socket::Write(socket, buffer, strlen(buffer));
+            Socket::Write(socket, text_buffer, len);
+            Socket::Write(socket, "\n", 1);
+            success = true;
+          }
+          free(text_buffer);
+          delete f;
+        }
+      } else {
+        // TODO(tball): look up linked in resource.
+      }
+      if (!success) {
+        const char* response = "HTTP/1.1 404 Not Found\n\n";
+        Socket::Write(socket, response, strlen(response));
+      }
+    }
+    Socket::Close(socket);
+  }
+
+  Shutdown();
+}
+
+
+char* VmStats::IsolatesStatus() {
+  std::ostringstream stream;
+  stream << '{' << std::endl;
+  stream << "\"isolates\": [" << std::endl;
+  IsolateTable::iterator itr;
+  bool first = true;
+  for (itr = isolate_table_.begin(); itr != isolate_table_.end(); ++itr) {
+    Dart_Isolate isolate = itr->second;
+    static char request[512];
+    snprintf(request, sizeof(request),
+             "/isolate/0x%"Px,
+             reinterpret_cast<intptr_t>(isolate));
+    char* status = VmStatusService::GetVmStatus(request);
+    if (status != NULL) {
+      stream << status;
+      if (!first) {
+        stream << "," << std::endl;
+      }
+      first = false;
+    }
+    free(status);
+  }
+  stream << std::endl << "]";
+  stream << std::endl << '}' << std::endl;
+  return strdup(stream.str().c_str());
+}
+
+
+// Global static pointer used to ensure a single instance of the class.
+VmStatusService* VmStatusService::instance_ = NULL;
+
+
+void VmStatusService::InitOnce() {
+  ASSERT(VmStatusService::instance_ == NULL);
+  VmStatusService::instance_ = new VmStatusService();
+  VmStatusService::mutex_ = new dart::Mutex();
+
+  // Register built-in status plug-ins. RegisterPlugin is not used because
+  // this isn't called within an isolate, and because parameter checking
+  // isn't necessary.
+  instance_->RegisterPlugin(&Dart_GetVmStatus);
+
+  // TODO(tball): dynamically load any additional plug-ins.
+}
+
+
+int VmStatusService::RegisterPlugin(Dart_VmStatusCallback callback) {
+  MutexLocker ml(mutex_);
+  if (callback == NULL) {
+    return -1;
+  }
+  VmStatusPlugin* plugin = new VmStatusPlugin(callback);
+  VmStatusPlugin* list = instance_->registered_plugin_list_;
+  if (list == NULL) {
+    instance_->registered_plugin_list_ = plugin;
+  } else {
+    list->Append(plugin);
+  }
+  return 0;
+}
+
+
+char* VmStatusService::GetVmStatus(const char* request) {
+  VmStatusPlugin* plugin = instance_->registered_plugin_list_;
+  while (plugin != NULL) {
+    char* result = (plugin->callback())(request);
+    if (result != NULL) {
+      return result;
+    }
+    plugin = plugin->next();
+  }
+  return NULL;
+}
diff --git a/runtime/bin/vmstats_impl.h b/runtime/bin/vmstats_impl.h
new file mode 100644
index 0000000..63749b3
--- /dev/null
+++ b/runtime/bin/vmstats_impl.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_VMSTATS_IMPL_H_
+#define BIN_VMSTATS_IMPL_H_
+
+#include "bin/vmstats.h"
+
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "bin/isolate_data.h"
+#include "platform/thread.h"
+
+// VmStats is a HTTP singleton service that reports status information
+// of the running VM.
+
+class VmStats {
+ public:
+  static void Start(int port, const char* root_dir);
+  static void Stop();
+
+  // Add and remove functions for the isolate_table, called by main.cc.
+  static void AddIsolate(IsolateData* isolate_data, Dart_Isolate isolate);
+  static void RemoveIsolate(IsolateData* isolate_data);
+
+ private:
+  VmStats() : running_(false), bind_address_(0) {}
+
+  static void WebServer(uword bind_address);
+  static void Shutdown();
+
+  // Status text generators.
+  char* IsolatesStatus();
+
+  typedef std::map<IsolateData*, Dart_Isolate> IsolateTable;
+
+  std::string root_directory_;
+  IsolateTable isolate_table_;
+  bool running_;
+  int64_t bind_address_;
+
+  static VmStats* instance_;
+  static dart::Monitor* instance_monitor_;
+
+  // Disallow copy constructor.
+  DISALLOW_COPY_AND_ASSIGN(VmStats);
+};
+
+
+// Status plug-in and linked-list node.
+class VmStatusPlugin {
+ public:
+  explicit VmStatusPlugin(Dart_VmStatusCallback callback)
+      : callback_(callback), next_(NULL) {}
+
+  void Append(VmStatusPlugin* plugin) {
+    VmStatusPlugin* list = this;
+    while (list->next_ != NULL) {
+      list = list->next_;
+    }
+    list->next_ = plugin;
+  }
+
+  Dart_VmStatusCallback callback() { return callback_; }
+  VmStatusPlugin* next() { return next_; }
+
+ private:
+  Dart_VmStatusCallback callback_;
+  VmStatusPlugin* next_;
+};
+
+
+// Singleton service managing VM status gathering and status plug-in
+// registration.
+class VmStatusService {
+ public:
+  static int RegisterPlugin(Dart_VmStatusCallback callback);
+
+  // Returns VM status for a specified request. The caller is responsible
+  // for releasing the heap memory after use.
+  static char* GetVmStatus(const char* request);
+
+  static void InitOnce();
+
+ private:
+  VmStatusService() : registered_plugin_list_(NULL) {}
+
+  static VmStatusService* instance_;
+  static dart::Mutex* mutex_;
+
+  VmStatusPlugin* registered_plugin_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(VmStatusService);
+};
+
+#endif  // BIN_VMSTATS_IMPL_H_
diff --git a/runtime/embedders/openglui/android/android_graphics_handler.cc b/runtime/embedders/openglui/android/android_graphics_handler.cc
index e96febe..f2c0ea2 100644
--- a/runtime/embedders/openglui/android/android_graphics_handler.cc
+++ b/runtime/embedders/openglui/android/android_graphics_handler.cc
@@ -5,8 +5,9 @@
 #include "embedders/openglui/android/android_graphics_handler.h"
 #include "embedders/openglui/common/log.h"
 
-AndroidGraphicsHandler::AndroidGraphicsHandler(android_app* application)
-    : GraphicsHandler(),
+AndroidGraphicsHandler::AndroidGraphicsHandler(android_app* application,
+                                               const char* resource_path)
+    : GraphicsHandler(resource_path),
       application_(application),
       display_(EGL_NO_DISPLAY),
       surface_(EGL_NO_SURFACE),
diff --git a/runtime/embedders/openglui/android/android_graphics_handler.h b/runtime/embedders/openglui/android/android_graphics_handler.h
index 6849ac3..c157d95 100644
--- a/runtime/embedders/openglui/android/android_graphics_handler.h
+++ b/runtime/embedders/openglui/android/android_graphics_handler.h
@@ -10,7 +10,8 @@
 
 class AndroidGraphicsHandler : public GraphicsHandler {
   public:
-    explicit AndroidGraphicsHandler(android_app* application);
+    AndroidGraphicsHandler(android_app* application,
+                           const char* resource_path);
 
     int32_t Start();
     void Stop();
diff --git a/runtime/embedders/openglui/android/android_sound_handler.cc b/runtime/embedders/openglui/android/android_sound_handler.cc
index 6e97833..8d0b2b7 100644
--- a/runtime/embedders/openglui/android/android_sound_handler.cc
+++ b/runtime/embedders/openglui/android/android_sound_handler.cc
@@ -55,23 +55,48 @@
 }
 
 void AndroidSoundHandler::Stop() {
-  StopBackground();
-  if (output_mix_ != NULL) {
-    (*output_mix_)->Destroy(output_mix_);
-    output_mix_ = NULL;
-  }
-  if (engine_ != NULL) {
-    (*engine_)->Destroy(engine_);
-    engine_ = NULL;
-    engine_if_ = NULL;
-  }
+  LOGI("Stopping SoundService");
   if (sample_player_ != NULL) {
+    LOGI("Destroying sample player");
     (*sample_player_)->Destroy(sample_player_);
     sample_player_ = NULL;
     sample_player_if_ = NULL;
     sample_player_queue_ = NULL;
   }
   samples_.clear();
+  if (output_mix_ != NULL) {
+    LOGI("Destroying output mix");
+    (*output_mix_)->Destroy(output_mix_);
+    output_mix_ = NULL;
+  }
+  if (engine_ != NULL) {
+    LOGI("Destroying engine");
+    (*engine_)->Destroy(engine_);
+    engine_ = NULL;
+    engine_if_ = NULL;
+  }
+}
+
+int32_t AndroidSoundHandler::SetBackgroundPlayerState(int state) {
+  if (background_player_if_ != NULL) {
+    SLuint32 state;
+    (*background_player_)->GetState(background_player_, &state);
+    if (state == SL_OBJECT_STATE_REALIZED) {
+      (*background_player_if_)->SetPlayState(background_player_if_,
+                                             state);
+      return 0;
+    }
+  }
+  return -1;
+}
+
+int32_t AndroidSoundHandler::Pause() {
+  return SetBackgroundPlayerState(SL_PLAYSTATE_PAUSED);
+}
+
+
+int32_t AndroidSoundHandler::Resume() {
+  return SetBackgroundPlayerState(SL_PLAYSTATE_PLAYING);
 }
 
 int32_t AndroidSoundHandler::CreateAudioPlayer(SLEngineItf engine_if,
@@ -171,18 +196,11 @@
 }
 
 void AndroidSoundHandler::StopBackground() {
-  if (background_player_if_ != NULL) {
-    SLuint32 state;
-    (*background_player_)->GetState(background_player_, &state);
-    if (state == SL_OBJECT_STATE_REALIZED) {
-      (*background_player_if_)->SetPlayState(background_player_if_,
-                                           SL_PLAYSTATE_PAUSED);
-
-      (*background_player_)->Destroy(background_player_);
-      background_player_ = NULL;
-      background_player_if_ = NULL;
-      background_player_seek_if_ = NULL;
-    }
+  if (Pause() == 0) {
+    (*background_player_)->Destroy(background_player_);
+    background_player_ = NULL;
+    background_player_if_ = NULL;
+    background_player_seek_if_ = NULL;
   }
 }
 
diff --git a/runtime/embedders/openglui/android/android_sound_handler.h b/runtime/embedders/openglui/android/android_sound_handler.h
index 027d644..e699a69 100644
--- a/runtime/embedders/openglui/android/android_sound_handler.h
+++ b/runtime/embedders/openglui/android/android_sound_handler.h
@@ -20,6 +20,8 @@
     explicit AndroidSoundHandler(android_app* application);
     int32_t Start();
     void Stop();
+    int32_t Pause();
+    int32_t Resume();
 
     int32_t PlayBackground(const char* path);
     void StopBackground();
@@ -34,6 +36,7 @@
                               SLObjectItf& player_out,
                               SLPlayItf& player_if_out);
 
+    int32_t SetBackgroundPlayerState(int state);
     int32_t StartSamplePlayer();
 
     android_app* application_;
diff --git a/runtime/embedders/openglui/android/eventloop.cc b/runtime/embedders/openglui/android/eventloop.cc
index 2d3bf6c..ea536fe 100644
--- a/runtime/embedders/openglui/android/eventloop.cc
+++ b/runtime/embedders/openglui/android/eventloop.cc
@@ -6,9 +6,152 @@
 
 #include "embedders/openglui/common/log.h"
 
+/*
+ * The Android lifecycle events are:
+ *
+ * OnCreate: In NDK this is the call to android_main
+ *
+ * OnStart: technically, called to initiate the “visible” lifespan of the
+ *     app; at any time between OnStart and OnStop, the app may be visible.
+ *     We can either be OnResume’d or OnStop’ped from this state. Note that
+ *     there is also an event for OnRestart, which is called before OnStart
+ *     if the application is transitioning from OnStop to OnStart instead of
+ *     being started from scratch.
+ *
+ * OnResume: technically, the start of the “foreground” lifespan of the app, 
+ *     but this does not mean that the app is fully visible and should be 
+ *     rendering – more on that later
+ *
+ * OnPause: the app is losing its foregrounded state; this is normally an 
+ *     indication that something is fully covering the app. On versions of 
+ *     Android before Honeycomb, once we returned from this callback, we 
+ *     could be killed at any time with no further app code called. We can
+ *     either be OnResume’d or OnStop’ped from this state. OnPause halts the 
+ *     visible UI thread and so should be handled as quickly as possible.
+ *
+ * OnStop: the end of the current visible lifespan of the app – we may
+ *     transition to On(Re)Start to become visible again, or to OnDestroy if
+ *      we are shutting down entirely. Once we return from this callback, we
+ *      can be killed at any time with no further app code called on any
+ *      version of Android.
+ *
+ * OnDestroy: this can only be followed by the application being killed or
+ *     restarted with OnCreate.
+ *
+ * The above events occur in fixed orders. The events below can occur at 
+ * various times:
+ *
+ * OnGainedFocus: happens between OnResume and OnPause.
+ * OnLostFocus:  may occur at arbitrary times, and may in fact not happen
+ *     at all if the app is being destroyed. So OnPause and OnGainedFocus/
+ *     OnLostFocus must be used together to determine the visible and
+ *     interactable state of the app.
+ *
+ * OnCreateWindow: usually happens in the resumed state
+ * OnDestroyWindow: can happen after OnPause or OnDestroy, so apps may
+ *     need to handle shutting down EGL before their surfaces are
+ *     destroyed.
+ * OnConfigurationChanged: typically means the size has changed
+ *
+ * An application's EGL surface may only exist between the OnCreateWindow
+ * and OnDestroyWindow callbacks.
+ *
+ * An application is "killable" after OnStop or OnDestroy (in earlier 
+ * Android versions, after OnPause too). That means any critical state
+ * or resources must be handled by any of these callbacks.
+ *
+ * These callbacks run on the main thread. If they block any event
+ * processing for more than 5 seconds this will result in an ANR
+ * (Application Not Responding message).
+ *
+ * On application launch, this sequence will occur:
+ *
+ * - OnCreate
+ * - OnStart
+ * - OnResume
+ * - OnCreateWindow
+ * - OnConfigurationChanged
+ * - OnGainedFocus
+ *
+ * If the back button is pressed, and the app does not handle it,
+ * Android will pop the app of the UI stack and destroy the application's
+ * activity:
+ *
+ * - OnPause
+ * - OnLostFocus
+ * - OnDestroyWindow
+ * - OnStop
+ * - OnDestroy
+ *
+ * If the home button is pressed, the app is sent down in the UI stack.
+ * The app's Activity still exists but may be killed at any time, and
+ * it loses its rendering surface:
+ *
+ * - OnPause
+ * - OnLostFocus
+ * - OnDestroyWindow
+ * - OnStop
+ *
+ * If the app is then restarted (without having been killed in between):
+ *
+ * - OnRestart
+ * - OnStart
+ * - OnResume
+ * - OnCreateWindow
+ * - OnConfigurationChanged
+ * - OnGainedFocus
+ *
+ * If a status icon pop up is opened, the app is still visible and can render
+ * but is not focused and cannot receive input:
+ *
+ * - OnLostFocus
+ *
+ * When the popup is dismissed, the app regains focus:
+ *
+ * - OnGainedFocus
+ *
+ * When the device is suspended (power button or screen saver), the application
+ * will typically be paused and lose focus:
+ *
+ * - OnPause
+ * - OnLostFocus (sometimes this will only come when the device is resumed
+ *       to the lock screen)
+ *
+ * The application should have stopped all rendering and sound and any
+ * non-critical background processing.
+ *
+ * When the device is resumed but not yet unlocked, the app will be resumed:
+ * 
+ * - OnResume
+ *
+ * The application should not perform sound or graphics yet. If the lock 
+ * screen times out, the app will be paused again. If the screen is
+ * unlocked, the app will regain focus.
+ *
+ * Turning all of this into a general framework, we can use the following:
+ *
+ * 1. In OnCreate/android_main, set up the main classes and possibly
+ *    load some lightweight resources.
+ * 2. In OnCreateWindow, create the EGLSurface, bind the context, load 
+ *    OpenGL resources. No rendering.
+ * 3. When we are between OnResume and OnPause, and between OnCreateWindow
+ *    and OnDestroyWindow, and between OnGainedFocus and OnLostFocus,
+ *    we can render and process input.
+ * 4. In OnLostFocus, stop sounds from playing, and stop rendering.
+ * 5. In OnPause, stop all rendering
+ * 6. In OnResume, prepare to start rendering again, but don't render.
+ * 7. In OnGainedFocus after OnResume, start rendering and sound again.
+ * 8. In OnStop, free all graphic resources, either through GLES calls
+ *    if the EGLContext is still bound, or via eglDestroyContext if the
+ *    context has been unbound because the rendering surface was destroyed.
+ * 9. In OnDestroy, release all other resources.
+ */
 EventLoop::EventLoop(android_app* application)
     : enabled_(false),
       quit_(false),
+      isResumed_(false),
+      hasSurface_(false),
+      hasFocus_(false),
       application_(application),
       lifecycle_handler_(NULL),
       input_handler_(NULL) {
@@ -25,97 +168,86 @@
 
   lifecycle_handler_ = lifecycle_handler;
   input_handler_ = input_handler;
-  LOGI("Starting event loop");
-  while (true) {
-    // If not enabled, block indefinitely on events. If enabled, block
-    // briefly so we can do useful work in onStep. Ultimately this is
-    // where we would want to look at elapsed time since the last call
-    // to onStep completed and use a delay that gives us ~60fps.
-    while ((result = ALooper_pollAll(enabled_ ? (1000/60) : -1,
-                                     NULL,
-                                     &events,
-                                     reinterpret_cast<void**>(&source))) >= 0) {
-      if (source != NULL) {
-        source->process(application_, source);
+  if (lifecycle_handler_->OnStart() == 0) {
+    LOGI("Starting event loop");
+    while (!quit_) {
+      // If not enabled, block indefinitely on events. If enabled, block
+      // briefly so we can do useful work in onStep. Ultimately this is
+      // where we would want to look at elapsed time since the last call
+      // to onStep completed and use a delay that gives us ~60fps.
+      while ((result = ALooper_pollAll(enabled_ ? (1000/60) : -1, NULL,
+          &events, reinterpret_cast<void**>(&source))) >= 0) {
+        if (source != NULL) {
+          source->process(application_, source);
+        }
+        if (application_->destroyRequested) {
+          return;
+        }
       }
-      if (application_->destroyRequested) {
-        return;
-      }
-    }
-    if (enabled_ && !quit_) {
-      LOGI("step");
-      if (lifecycle_handler_->OnStep() != 0) {
-        quit_ = true;
-        ANativeActivity_finish(application_->activity);
+      if (enabled_ && !quit_) {
+        LOGI("step");
+        if (lifecycle_handler_->OnStep() != 0) {
+          quit_ = true;
+        }
       }
     }
   }
-}
-
-// Called when we gain focus.
-void EventLoop::Activate() {
-  LOGI("activate");
-  if (!enabled_ && application_->window != NULL) {
-    quit_ = false;
-    enabled_ = true;
-    if (lifecycle_handler_->OnActivate() != 0) {
-      quit_ = true;
-      ANativeActivity_finish(application_->activity);
-    }
-  }
-}
-
-// Called when we lose focus.
-void EventLoop::Deactivate() {
-  LOGI("deactivate");
-  if (enabled_) {
-    lifecycle_handler_->OnDeactivate();
-    enabled_ = false;
-  }
+  ANativeActivity_finish(application_->activity);
 }
 
 void EventLoop::ProcessActivityEvent(int32_t command) {
   switch (command) {
+    case APP_CMD_INIT_WINDOW:
+      if (lifecycle_handler_->Activate() != 0) {
+        quit_ = true;
+      } else {
+        hasSurface_ = true;
+      }
+      break;
     case APP_CMD_CONFIG_CHANGED:
       lifecycle_handler_->OnConfigurationChanged();
       break;
-    case APP_CMD_INIT_WINDOW:
-      lifecycle_handler_->OnCreateWindow();
-      break;
     case APP_CMD_DESTROY:
-      lifecycle_handler_->OnDestroy();
+      hasFocus_ = false;
+      lifecycle_handler_->FreeAllResources();
       break;
     case APP_CMD_GAINED_FOCUS:
-      Activate();
-      lifecycle_handler_->OnGainedFocus();
+      hasFocus_ = true;
+      if (hasSurface_ && isResumed_ && hasFocus_) {
+        enabled_ = (lifecycle_handler_->Resume() == 0);
+      }
       break;
     case APP_CMD_LOST_FOCUS:
-      lifecycle_handler_->OnLostFocus();
-      Deactivate();
+      hasFocus_ = false;
+      enabled_ = false;
+      lifecycle_handler_->Pause();
       break;
     case APP_CMD_LOW_MEMORY:
       lifecycle_handler_->OnLowMemory();
       break;
     case APP_CMD_PAUSE:
-      lifecycle_handler_->OnPause();
-      Deactivate();
+      isResumed_ = false;
+      enabled_ = false;
+      lifecycle_handler_->Pause();
       break;
     case APP_CMD_RESUME:
-      lifecycle_handler_->OnResume();
+      isResumed_ = true;
       break;
     case APP_CMD_SAVE_STATE:
       lifecycle_handler_->OnSaveState(&application_->savedState,
                                     &application_->savedStateSize);
       break;
     case APP_CMD_START:
-      lifecycle_handler_->OnStart();
       break;
     case APP_CMD_STOP:
-      lifecycle_handler_->OnStop();
+      hasFocus_ = false;
+      lifecycle_handler_->Deactivate();
       break;
     case APP_CMD_TERM_WINDOW:
-      lifecycle_handler_->OnDestroyWindow();
-      Deactivate();
+      hasFocus_ = false;
+      hasSurface_ = false;
+      enabled_ = false;
+      lifecycle_handler_->Pause();
       break;
     default:
       break;
diff --git a/runtime/embedders/openglui/android/eventloop.h b/runtime/embedders/openglui/android/eventloop.h
index 23b16db..2c548c8 100644
--- a/runtime/embedders/openglui/android/eventloop.h
+++ b/runtime/embedders/openglui/android/eventloop.h
@@ -17,8 +17,6 @@
              InputHandler* input_handler);
 
   protected:
-    void Activate();
-    void Deactivate();
     void ProcessActivityEvent(int32_t command);
     int32_t ProcessInputEvent(AInputEvent* event);
     bool OnTouchEvent(AInputEvent* event);
@@ -28,8 +26,8 @@
     static int32_t InputCallback(android_app* application, AInputEvent* event);
 
   private:
-    bool enabled_;
-    bool quit_;
+    bool enabled_, quit_;
+    bool isResumed_, hasSurface_, hasFocus_;
     android_app* application_;
     LifeCycleHandler* lifecycle_handler_;
     InputHandler* input_handler_;
diff --git a/runtime/embedders/openglui/android/main.cc b/runtime/embedders/openglui/android/main.cc
index 4cd8790..5569627 100644
--- a/runtime/embedders/openglui/android/main.cc
+++ b/runtime/embedders/openglui/android/main.cc
@@ -12,8 +12,9 @@
 
 void android_main(android_app* application) {
   app_dummy();  // Link in native_app_glue.
-  AndroidGraphicsHandler graphics_handler(application);
-  VMGlue vm_glue(&graphics_handler, "/data/data/com.google.dartndk/app_dart");
+  const char* resource_path = "/data/data/com.google.dartndk/app_dart";
+  AndroidGraphicsHandler graphics_handler(application, resource_path);
+  VMGlue vm_glue(&graphics_handler, resource_path);
   AndroidInputHandler input_handler(&vm_glue, &graphics_handler);
   AndroidSoundHandler sound_handler(application);
   Timer timer;
diff --git a/runtime/embedders/openglui/common/canvas_context.cc b/runtime/embedders/openglui/common/canvas_context.cc
index 3750344..851a30d 100644
--- a/runtime/embedders/openglui/common/canvas_context.cc
+++ b/runtime/embedders/openglui/common/canvas_context.cc
@@ -6,7 +6,7 @@
 
 #include <ctype.h>
 #include <string.h>
-
+#include "core/SkStream.h"
 #include "embedders/openglui/common/support.h"
 
 // TODO(gram): this should be dynamic.
@@ -15,11 +15,25 @@
 
 CanvasContext* Context2D(int handle) {
   if (handle < 0 || handle >= MAX_CONTEXTS) {
+    LOGE("Request for out-of-range handle %d", handle);
     return NULL;
   }
+  if (contexts[handle] == NULL) {
+    LOGE("Warning: request for context with handle %d returns NULL", handle);
+  }
   return contexts[handle];
 }
 
+void FreeContexts() {
+  extern CanvasContext* display_context;
+  for (int i = 0; i < MAX_CONTEXTS; i++) {
+    delete contexts[i];
+    contexts[i] = NULL;
+  }
+  display_context = NULL;
+}
+
+
 CanvasContext::CanvasContext(int handle, int16_t widthp, int16_t heightp)
   : canvas_(NULL),
     width_(widthp),
@@ -33,6 +47,7 @@
   }
   state_ = new CanvasState(canvas_);
   contexts[handle] = this;
+  LOGI("Created context with handle %d", handle);
 }
 
 CanvasContext::~CanvasContext() {
@@ -52,18 +67,45 @@
     SkDevice* device = otherContext->canvas_->getDevice();
     bm = device->accessBitmap(false);
   } else {
-    // TODO(gram): We need a way to remap URLs to local file names.
-    // For now I am just using the characters after the last '/'.
-    // Note also that if we want to support URLs and network fetches,
-    // then we introduce more complexity; this can't just be an URL.
-    int pos = strlen(src_url);
-    while (--pos >= 0 && src_url[pos] != '/');
-    const char *path = src_url + pos + 1;
-    if (!SkImageDecoder::DecodeFile(path, &bm)) {
-      LOGI("Image decode of %s failed", path);
-      return;
+    const char* filepath;
+    if (strncmp(src_url, "file://", 7) == 0) {
+      filepath = src_url + 7;
     } else {
-      LOGI("Decode image: width=%d,height=%d", bm.width(), bm.height());
+      // TODO(gram): We need a way to remap URLs to local file names.
+      // For now I am just using the characters after the last '/'.
+      // Note also that if we want to support URLs and network fetches,
+      // then we introduce more complexity; this can't just be an URL.
+      int pos = strlen(src_url);
+      while (--pos >= 0 && src_url[pos] != '/');
+      filepath = src_url + pos + 1;
+    }
+    char* path;
+    if (filepath[0] == '/') {
+      path = const_cast<char*>(filepath);
+    } else {
+      size_t len1 = strlen(graphics->resource_path());
+      size_t len2 = strlen(filepath);
+      path = new char[len1 + 1 + len2 + 1];
+      strncpy(path, graphics->resource_path(), len1+1);
+      strncat(path, "/", 1);
+      strncat(path, filepath, len2);
+    }
+    SkFILEStream stream(path);
+    if (stream.isValid()) {
+      // We could use DecodeFile and pass the path, but by creating the
+      // SkStream here we can produce better error log messages.
+      if (!SkImageDecoder::DecodeStream(&stream, &bm)) {
+        LOGI("Image decode of %s failed", path);
+        return;
+      } else {
+        LOGI("Decode image %s: width=%d,height=%d",
+            path, bm.width(), bm.height());
+      }
+    } else {
+      LOGI("Path %s is invalid", path);
+    }
+    if (path != filepath) {
+      delete[] path;
     }
   }
   if (!has_src_dimensions) {
@@ -75,6 +117,7 @@
     dh = bm.height();
   }
   state_->DrawImage(bm, sx, sy, sw, sh, dx, dy, dw, dh);
+  isDirty_ = true;
 }
 
 void CanvasContext::ClearRect(float left, float top,
@@ -83,5 +126,6 @@
   paint.setStyle(SkPaint::kFill_Style);
   paint.setColor(0xFFFFFFFF);
   canvas_->drawRectCoords(left, top, left + width, top + height, paint);
+  isDirty_ = true;
 }
 
diff --git a/runtime/embedders/openglui/common/canvas_context.h b/runtime/embedders/openglui/common/canvas_context.h
index 72b3852..3fc44ef 100644
--- a/runtime/embedders/openglui/common/canvas_context.h
+++ b/runtime/embedders/openglui/common/canvas_context.h
@@ -27,11 +27,9 @@
 class CanvasContext {
  protected:
   SkCanvas* canvas_;
-
   int16_t width_, height_;
-
   bool imageSmoothingEnabled_;
-
+  bool isDirty_;
   CanvasState* state_;
 
   static inline float Radians2Degrees(float angle) {
@@ -46,6 +44,14 @@
   CanvasContext(int handle, int16_t width, int16_t height);
   virtual ~CanvasContext();
 
+  inline bool isDirty() {
+    return isDirty_;
+  }
+
+  inline void clearDirty() {
+    isDirty_ = false;
+  }
+
   inline void setGlobalAlpha(float alpha) {
     state_->setGlobalAlpha(alpha);
   }
@@ -165,6 +171,7 @@
 
   inline void Clear() {
     canvas_->drawColor(0xFFFFFFFF);
+    isDirty_ = true;
   }
 
   void ClearRect(float left, float top, float width, float height);
@@ -172,11 +179,13 @@
   inline void FillRect(float left, float top, float width, float height) {
     // Does not affect the path.
     state_->FillRect(left, top, width, height);
+    isDirty_ = true;
   }
 
   inline void StrokeRect(float left, float top, float width, float height) {
     // Does not affect the path.
     state_->StrokeRect(left, top, width, height);
+    isDirty_ = true;
   }
 
   inline void BeginPath() {
@@ -185,10 +194,12 @@
 
   inline void Fill() {
     state_->Fill();
+    isDirty_ = true;
   }
 
   inline void Stroke() {
     state_->Stroke();
+    isDirty_ = true;
   }
 
   inline void ClosePath() {
@@ -269,11 +280,13 @@
   inline void FillText(const char* text, float x, float y,
                        float maxWidth = -1) {
     state_->FillText(text, x, y, maxWidth);
+    isDirty_ = true;
   }
 
   inline void StrokeText(const char* text, float x, float y,
                          float maxWidth = -1) {
     state_->StrokeText(text, x, y, maxWidth);
+    isDirty_ = true;
   }
 
   inline float MeasureText(const char *text) {
@@ -296,6 +309,7 @@
 };
 
 CanvasContext* Context2D(int handle);
+void FreeContexts();
 
 #endif  // EMBEDDERS_OPENGLUI_COMMON_CANVAS_CONTEXT_H_
 
diff --git a/runtime/embedders/openglui/common/dart_host.cc b/runtime/embedders/openglui/common/dart_host.cc
index 8e8c2a6..af886b0 100644
--- a/runtime/embedders/openglui/common/dart_host.cc
+++ b/runtime/embedders/openglui/common/dart_host.cc
@@ -15,85 +15,90 @@
       sound_handler_(context->sound_handler),
       timer_(context->timer),
       vm_glue_(context->vm_glue),
+      has_context_(false),
+      started_(false),
       active_(false) {
-  LOGI("Creating DartHost");
 }
 
 DartHost::~DartHost() {
-  LOGI("Freeing DartHost");
 }
 
-int32_t DartHost::OnActivate() {
-  return Activate();
+int32_t DartHost::OnStart() {
+  int result = vm_glue_->StartMainIsolate();
+  if (result != 0) {
+    LOGE("startMainIsolate returned %d", result);
+    return -1;
+  }
+  started_ = true;
+  return 0;
 }
 
 int32_t DartHost::Activate() {
-  if (!active_) {
-    LOGI("Activating DartHost");
+  if (!has_context_) {
     if (graphics_handler_->Start() != 0) {
       return -1;
     }
     if (sound_handler_->Start() != 0) {
+      graphics_handler_->Stop();
       return -1;
     }
     if (input_handler_->Start() != 0) {
+      sound_handler_->Stop();
+      graphics_handler_->Stop();
       return -1;
     }
+    int32_t rtn = vm_glue_->CallSetup(true);
     timer_->Reset();
-    LOGI("Starting main isolate");
-    int result = vm_glue_->StartMainIsolate();
-    if (result != 0) {
-      LOGE("startMainIsolate returned %d", result);
-      return -1;
-    }
-    active_ = true;
-    return vm_glue_->CallSetup();
+    has_context_ = true;
+    return rtn;
   }
   return 0;
 }
 
-void DartHost::OnDeactivate() {
-  Deactivate();
-}
-
 void DartHost::Deactivate() {
-  if (active_) {
-    active_ = false;
-    vm_glue_->FinishMainIsolate();
-    LOGI("Deactivating DartHost");
+  Pause();
+  if (has_context_) {
+    vm_glue_->CallShutdown();
     input_handler_->Stop();
     sound_handler_->Stop();
     graphics_handler_->Stop();
+    has_context_ = false;
   }
 }
 
 int32_t DartHost::OnStep() {
-  timer_->Update();
-  if (vm_glue_->CallUpdate() != 0 ||
-      graphics_handler_->Update() != 0) {
-    return -1;
+  if (active_) {
+    timer_->Update();
+    if (vm_glue_->CallUpdate() != 0 ||
+        graphics_handler_->Update() != 0) {
+      return -1;
+    }
   }
   return 0;
 }
 
-void DartHost::OnStart() {
-  LOGI("Starting DartHost");
+int32_t DartHost::Resume() {
+  if (!active_) {
+    if (Activate() == 0) {
+      sound_handler_->Resume();
+      active_ = true;
+    }
+  }
+  return 0;
 }
 
-void DartHost::OnResume() {
-  LOGI("Resuming DartHost");
+void DartHost::Pause() {
+  if (active_) {
+    active_ = false;  // This stops update() calls.
+    sound_handler_->Suspend();
+  }
 }
 
-void DartHost::OnPause() {
-  LOGI("Pausing DartHost");
-}
-
-void DartHost::OnStop() {
-  LOGI("Stopping DartHost");
-}
-
-void DartHost::OnDestroy() {
-  LOGI("Destroying DartHost");
+void DartHost::FreeAllResources() {
+  if (started_) {
+    vm_glue_->FinishMainIsolate();
+    started_ = false;
+  }
 }
 
 void DartHost::OnSaveState(void** data, size_t* size) {
@@ -108,19 +113,3 @@
   LOGI("DartHost low on memory");
 }
 
-void DartHost::OnCreateWindow() {
-  LOGI("DartHost creating window");
-}
-
-void DartHost::OnDestroyWindow() {
-  LOGI("DartHost destroying window");
-}
-
-void DartHost::OnGainedFocus() {
-  LOGI("DartHost gained focus");
-}
-
-void DartHost::OnLostFocus() {
-  LOGI("DartHost lost focus");
-}
-
diff --git a/runtime/embedders/openglui/common/dart_host.h b/runtime/embedders/openglui/common/dart_host.h
index 7c85d15..9233aa2f 100644
--- a/runtime/embedders/openglui/common/dart_host.h
+++ b/runtime/embedders/openglui/common/dart_host.h
@@ -14,43 +14,32 @@
 #include "embedders/openglui/common/vm_glue.h"
 #include "include/dart_api.h"
 
-// Currently the life cycle management is very crude. We conservatively
-// shutdown the main isolate when we lose focus and create a new one when
-// we resume. This needs to be improved later when we understand this better,
-// and we need some hooks to tell the Dart script to save/restore state
-// (and an API that will support that).
-
 class DartHost : public LifeCycleHandler {
  public:
   explicit DartHost(Context* context);
   virtual ~DartHost();
 
-  void OnStart();
-  void OnResume();
-  void OnPause();
-  void OnStop();
-  void OnDestroy();
+  int32_t OnStart();
   void OnSaveState(void** data, size_t* size);
   void OnConfigurationChanged();
   void OnLowMemory();
-  void OnCreateWindow();
-  void OnDestroyWindow();
-  void OnGainedFocus();
-  void OnLostFocus();
-  int32_t OnActivate();
-  void OnDeactivate();
+  int32_t Activate();
+  void Deactivate();
+  void Pause();
+  int32_t Resume();
+  void FreeAllResources();
   int32_t OnStep();
 
  private:
   void Clear();
-  int32_t Activate();
-  void Deactivate();
 
   GraphicsHandler* graphics_handler_;
   InputHandler* input_handler_;
   SoundHandler* sound_handler_;
   Timer* timer_;
   VMGlue* vm_glue_;
+  bool has_context_;
+  bool started_;
   bool active_;
 };
 
diff --git a/runtime/embedders/openglui/common/extension.cc b/runtime/embedders/openglui/common/extension.cc
index d0c24b3..abe627d 100644
--- a/runtime/embedders/openglui/common/extension.cc
+++ b/runtime/embedders/openglui/common/extension.cc
@@ -923,7 +923,7 @@
 
 // 2D Canvas.
 
-CanvasContext* display_context;
+CanvasContext* display_context = NULL;
 
 void C2DCreateNativeContext(Dart_NativeArguments arguments) {
   LOGI("In C2DCreateNativeContext");
@@ -935,6 +935,7 @@
 
   CanvasContext* rtn = new CanvasContext(handle, width, height);
   if (display_context == NULL) {
+    LOGI("Created display context");
     display_context = rtn;
   }
   Dart_ExitScope();
diff --git a/runtime/embedders/openglui/common/gl.dart b/runtime/embedders/openglui/common/gl.dart
index 071f128..1cb506d 100644
--- a/runtime/embedders/openglui/common/gl.dart
+++ b/runtime/embedders/openglui/common/gl.dart
@@ -395,11 +395,15 @@
   TextMetrics(this.width);
 }
 
+void shutdown() {
+  CanvasRenderingContext2D.next_handle = 0;
+}
+
 class CanvasRenderingContext2D extends CanvasRenderingContext {
   // TODO(gram): We need to support multiple contexts, for cached content
   // prerendered to an offscreen buffer. For this we will use handles, with
   // handle 0 being the physical display.
-  static int _next_handle = 0;
+  static int next_handle = 0;
   int _handle = 0;
   get handle => _handle;
 
@@ -412,7 +416,7 @@
   CanvasRenderingContext2D(canvas, width, height) : super(canvas) {
     _width = width;
     _height = height;
-    C2DCreateNativeContext(_handle = _next_handle++, width, height);
+    C2DCreateNativeContext(_handle = next_handle++, width, height);
   }
 
   double _alpha = 1.0;
diff --git a/runtime/embedders/openglui/common/graphics_handler.cc b/runtime/embedders/openglui/common/graphics_handler.cc
index c68da4b..98d3461 100644
--- a/runtime/embedders/openglui/common/graphics_handler.cc
+++ b/runtime/embedders/openglui/common/graphics_handler.cc
@@ -9,13 +9,38 @@
 extern void CheckGLError(const char *function);
 
 GraphicsHandler* graphics;
+extern CanvasContext* display_context;
 
-GraphicsHandler::GraphicsHandler()
-  : ag(),
+GraphicsHandler::GraphicsHandler(const char* resource_path)
+  : resource_path_(resource_path),
+    ag(),
     grcontext(NULL),
     width_(0),
     height_(0) {
   graphics = this;
+  DecoderHack(0, NULL);
+}
+
+void GraphicsHandler::DecoderHack(int x, SkStream* s) {
+  if (x) {  // hack to keep the linker from throwing these out
+    extern SkImageDecoder* sk_libpng_dfactory(SkStream* s);
+    sk_libpng_dfactory(s);
+
+    // TODO(gram): For some reason I get linker errors on these, even though
+    // they are defined in libskia_images. Figure out why...
+    /*
+    extern SkImageDecoder* sk_libjpeg_dfactory(SkStream* s);
+    extern SkImageDecoder* sk_libbmp_dfactory(SkStream* s);
+    extern SkImageDecoder* sk_libgif_dfactory(SkStream* s);
+    extern SkImageDecoder* sk_libico_dfactory(SkStream* s);
+    extern SkImageDecoder* sk_libwbmp_dfactory(SkStream* s);
+    sk_libjpeg_dfactory(s);
+    sk_libbmp_dfactory(s);
+    sk_libgif_dfactory(s);
+    sk_libico_dfactory(s);
+    sk_libwbmp_dfactory(s);
+    */
+  }
 }
 
 // Kludge to get around an issue with Android emulator, which returns
@@ -31,7 +56,6 @@
 }
 
 int32_t GraphicsHandler::Start() {
-  SkGraphics::Init();
   GrGLInterface* fGL = const_cast<GrGLInterface*>(GrGLCreateNativeInterface());
   LOGI("Created native interface %s\n", fGL ? "succeeded" : "failed");
   fGL->fGetString = myGLGetString;
@@ -41,7 +65,10 @@
 }
 
 void GraphicsHandler::Stop() {
-  SkGraphics::Term();
+  LOGI("Releasing display context");
+  FreeContexts();
+  grcontext->unref();
+  grcontext = NULL;
 }
 
 SkCanvas* GraphicsHandler::CreateDisplayCanvas() {
@@ -82,15 +109,12 @@
 }
 
 int32_t GraphicsHandler::Update() {
-  extern CanvasContext* display_context;
-  if (display_context != NULL) {
+  if (display_context != NULL && display_context->isDirty()) {
     LOGI("Flushing display context\n");
     display_context->Flush();
+    SwapBuffers();
+    display_context->clearDirty();
   }
-  SwapBuffers();
   return 0;
 }
 
-
-
-
diff --git a/runtime/embedders/openglui/common/graphics_handler.h b/runtime/embedders/openglui/common/graphics_handler.h
index 25fae53..77f57ec 100644
--- a/runtime/embedders/openglui/common/graphics_handler.h
+++ b/runtime/embedders/openglui/common/graphics_handler.h
@@ -11,8 +11,11 @@
 #include "embedders/openglui/common/timer.h"
 
 class GraphicsHandler : public ISized {
+  private:
+    void DecoderHack(int x, SkStream* s);
+
   public:
-    GraphicsHandler();
+    explicit GraphicsHandler(const char* resource_path);
 
     const int32_t& height() {
       return height_;
@@ -39,10 +42,15 @@
     SkCanvas* CreateDisplayCanvas();
     SkCanvas* CreateBitmapCanvas(int width, int height);
 
+    inline const char* resource_path() {
+      return resource_path_;
+    }
+
     virtual ~GraphicsHandler() {
     }
 
   protected:
+    const char* resource_path_;
     SkAutoGraphics ag;
     GrContext* grcontext;
     int32_t width_, height_;
diff --git a/runtime/embedders/openglui/common/lifecycle_handler.h b/runtime/embedders/openglui/common/lifecycle_handler.h
index 801e6d8..cc1a659 100644
--- a/runtime/embedders/openglui/common/lifecycle_handler.h
+++ b/runtime/embedders/openglui/common/lifecycle_handler.h
@@ -7,21 +7,18 @@
 
 class LifeCycleHandler {
   public:
-    virtual int32_t OnActivate() = 0;
-    virtual void OnDeactivate() = 0;
+    virtual int32_t OnStart() = 0;
+    virtual int32_t Activate() = 0;
+    virtual void Deactivate() = 0;
     virtual int32_t OnStep() = 0;
-    virtual void OnStart() {}
-    virtual void OnResume() {}
-    virtual void OnPause() {}
-    virtual void OnStop() {}
-    virtual void OnDestroy() {}
+    virtual void Pause() {}
+    virtual int32_t Resume() {
+      return 0;
+    }
+    virtual void FreeAllResources() {}
     virtual void OnSaveState(void** data, size_t* size) {}
     virtual void OnConfigurationChanged() {}
     virtual void OnLowMemory() {}
-    virtual void OnCreateWindow() {}
-    virtual void OnDestroyWindow() {}
-    virtual void OnGainedFocus() {}
-    virtual void OnLostFocus() {}
     virtual ~LifeCycleHandler() {}
 };
 
diff --git a/runtime/embedders/openglui/common/log.h b/runtime/embedders/openglui/common/log.h
index 5bfa782..f816792 100644
--- a/runtime/embedders/openglui/common/log.h
+++ b/runtime/embedders/openglui/common/log.h
@@ -7,8 +7,16 @@
 
 #ifndef ANDROID
 #include <stdio.h>
-#define LOGI(...)       fprintf(stdout, __VA_ARGS__)
-#define LOGE(...)       fprintf(stderr, __VA_ARGS__)
+#define LOGI(...)       do {\
+                          fprintf(stdout, __VA_ARGS__);\
+                          fprintf(stdout, "\n");\
+                          fflush(stdout);\
+                        } while (0)
+#define LOGE(...)       do { \
+                          fprintf(stderr, __VA_ARGS__);\
+                          fprintf(stderr, "\n");\
+                          fflush(stderr);\
+                        } while (0)
 #else
 #include "embedders/openglui/android/android_log.h"
 #endif
diff --git a/runtime/embedders/openglui/common/sound_handler.h b/runtime/embedders/openglui/common/sound_handler.h
index 100d0a5..0110db9 100644
--- a/runtime/embedders/openglui/common/sound_handler.h
+++ b/runtime/embedders/openglui/common/sound_handler.h
@@ -24,6 +24,14 @@
     virtual void Stop() {
     }
 
+    virtual int32_t Suspend() {
+      return 0;
+    }
+
+    virtual int32_t Resume() {
+      return 0;
+    }
+
     virtual int32_t PlayBackground(const char* path) {
       return 0;
     }
diff --git a/runtime/embedders/openglui/common/vm_glue.cc b/runtime/embedders/openglui/common/vm_glue.cc
index b5e33e0..39ee799 100644
--- a/runtime/embedders/openglui/common/vm_glue.cc
+++ b/runtime/embedders/openglui/common/vm_glue.cc
@@ -198,8 +198,10 @@
   return 0;
 }
 
-int VMGlue::CallSetup() {
-  if (!initialized_script_) {
+int VMGlue::CallSetup(bool force) {
+  // TODO(gram): See if we actually need this flag guard here, or if
+  // we can eliminate it along with the need for the force parameter.
+  if (!initialized_script_ || force) {
     initialized_script_ = true;
     LOGI("Invoking setup(NULL, %d,%d)", surface_->width(), surface_->height());
     Dart_EnterIsolate(isolate_);
@@ -233,13 +235,23 @@
 
 int VMGlue::CallUpdate() {
   if (initialized_script_) {
-    LOGI("Invoking update");
     Dart_EnterIsolate(isolate_);
     Dart_EnterScope();
     int rtn = Invoke("update", 0, 0);
     Dart_ExitScope();
     Dart_ExitIsolate();
-    LOGI("Done update");
+    return rtn;
+  }
+  return -1;
+}
+
+int VMGlue::CallShutdown() {
+  if (initialized_script_) {
+    Dart_EnterIsolate(isolate_);
+    Dart_EnterScope();
+    int rtn = Invoke("shutdown", 0, 0);
+    Dart_ExitScope();
+    Dart_ExitIsolate();
     return rtn;
   }
   return -1;
@@ -289,10 +301,7 @@
                    int argc,
                    Dart_Handle* args,
                    bool failIfNotDefined) {
-  LOGI("in invoke(%s)", function);
-
   // Lookup the library of the root script.
-  LOGI("looking up the root library");
   Dart_Handle library = Dart_RootLibrary();
   if (Dart_IsNull(library)) {
      LOGE("Unable to find root library\n");
@@ -301,7 +310,6 @@
 
   Dart_Handle nameHandle = Dart_NewStringFromCString(function);
 
-  LOGI("invoking %s", function);
   Dart_Handle result = Dart_Invoke(library, nameHandle, argc, args);
 
   if (Dart_IsError(result)) {
@@ -314,14 +322,12 @@
 
   // TODO(vsm): I don't think we need this.
   // Keep handling messages until the last active receive port is closed.
-  LOGI("Entering Dart message loop");
   result = Dart_RunLoop();
   if (Dart_IsError(result)) {
     LOGE("Dart_RunLoop: %s\n", Dart_GetError(result));
     return -1;
   }
 
-  LOGI("out invoke");
   return 0;
 }
 
diff --git a/runtime/embedders/openglui/common/vm_glue.h b/runtime/embedders/openglui/common/vm_glue.h
index fc353a6..72db660 100644
--- a/runtime/embedders/openglui/common/vm_glue.h
+++ b/runtime/embedders/openglui/common/vm_glue.h
@@ -24,8 +24,9 @@
 
   int InitializeVM();
   int StartMainIsolate();
-  int CallSetup();
+  int CallSetup(bool force = false);
   int CallUpdate();
+  int CallShutdown();
   int OnMotionEvent(const char* funtion, int64_t when,
                     float move_x, float move_y);
   int OnKeyEvent(const char* funtion, int64_t when, int32_t flags,
diff --git a/runtime/embedders/openglui/emulator/emulator_embedder.cc b/runtime/embedders/openglui/emulator/emulator_embedder.cc
index 4f53b42..01c5188 100644
--- a/runtime/embedders/openglui/emulator/emulator_embedder.cc
+++ b/runtime/embedders/openglui/emulator/emulator_embedder.cc
@@ -11,6 +11,7 @@
 #include "embedders/openglui/common/dart_host.h"
 #include "embedders/openglui/common/events.h"
 #include "embedders/openglui/common/input_handler.h"
+#include "embedders/openglui/common/log.h"
 #include "embedders/openglui/common/sound_handler.h"
 #include "embedders/openglui/common/vm_glue.h"
 #include "embedders/openglui/emulator/emulator_graphics_handler.h"
@@ -55,7 +56,24 @@
   input_handler_ptr->OnKeyEvent(kKeyDown, time(0), 0, key, 0, 0);
   input_handler_ptr->OnKeyEvent(kKeyUp, time(0), 0, key, 0, 0);
   if (key == 27) {
+    lifecycle_handler_ptr->Pause();
+    lifecycle_handler_ptr->Deactivate();
+    lifecycle_handler_ptr->FreeAllResources();
     exit(0);
+  } else if (key == '0') {
+    LOGI("Simulating suspend");
+    lifecycle_handler_ptr->Pause();
+    lifecycle_handler_ptr->Deactivate();
+  } else if (key == '1') {
+    LOGI("Simulating resume");
+    lifecycle_handler_ptr->Activate();
+    lifecycle_handler_ptr->Resume();
+  } else if (key == '+') {
+    LOGI("Simulating focus gain");
+    lifecycle_handler_ptr->Resume();
+  } else if (key == '-') {
+    LOGI("Simulating focus loss");
+    lifecycle_handler_ptr->Pause();
   }
 }
 
@@ -84,7 +102,9 @@
   glutReshapeFunc(reshape);
   glutDisplayFunc(display);
   glutKeyboardFunc(keyboard);
-  lifecycle_handler_ptr->OnActivate();
+  lifecycle_handler_ptr->OnStart();
+  lifecycle_handler_ptr->Activate();
+  lifecycle_handler_ptr->Resume();
   gettimeofday(&tvStart, NULL);
   glutTimerFunc(1, tick, 0);
   glutMainLoop();
diff --git a/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc b/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc
index b552813..451e909 100644
--- a/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc
+++ b/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc
@@ -9,7 +9,7 @@
 
 EmulatorGraphicsHandler::EmulatorGraphicsHandler(int argc,
                                                  char** argv)
-  : GraphicsHandler() {
+  : GraphicsHandler(".") {
   glutInit(&argc, argv);
   SetViewport(0, 0, 480, 800);
   for (int i = 1; i < argc; i++) {
@@ -33,6 +33,5 @@
 
 void EmulatorGraphicsHandler::Stop() {
   GraphicsHandler::Stop();
-  exit(0);
 }
 
diff --git a/runtime/embedders/openglui/openglui_embedder.gypi b/runtime/embedders/openglui/openglui_embedder.gypi
index ab66125..a9ca5dd 100644
--- a/runtime/embedders/openglui/openglui_embedder.gypi
+++ b/runtime/embedders/openglui/openglui_embedder.gypi
@@ -26,6 +26,7 @@
               '../../../third_party/skia/trunk/include/config',
               '../../../third_party/skia/trunk/include/core',
               '../../../third_party/skia/trunk/include/gpu',
+              '../../../third_party/skia/trunk/include/lazy',
               '../../../third_party/skia/trunk/include/utils',
             ],
             'defines': [
@@ -182,6 +183,7 @@
               '../../../third_party/skia/trunk/include/config',
               '../../../third_party/skia/trunk/include/core',
               '../../../third_party/skia/trunk/include/gpu',
+              '../../../third_party/skia/trunk/include/lazy',
               '../../../third_party/skia/trunk/include/utils',
             ],
             'defines': [
diff --git a/runtime/include/dart_debugger_api.h b/runtime/include/dart_debugger_api.h
index 09033c6..5d71e4d 100755
--- a/runtime/include/dart_debugger_api.h
+++ b/runtime/include/dart_debugger_api.h
@@ -578,4 +578,28 @@
 */
 DART_EXPORT Dart_Isolate Dart_GetIsolate(Dart_IsolateId isolate_id);
 
+
+/**
+ * Returns VM status information. VM status is implemented using a
+ * different status plug-in for each type of status; for example, there
+ * might be an "isolate" plug-in that returns information about the
+ * current isolates.
+ *
+ * To get a list of status types, this function is called with a
+ * status_type parameter of "statustypes". This list is useful when
+ * building a status dashboard.
+ *
+ * TODO(tball): we need to figure out which isolate this command needs
+ * to be sent to after parsing the string and then send an OOB message
+ * to that isolate.
+ *
+ * \param request A REST-like string, which uses '/' to separate
+ *     parameters. The first parameter is always the status type.
+ *
+ * \return The requested status as a JSON formatted string, with the
+ *     contents defined by the status plug-in. The caller is responsible
+ *     for freeing this string.
+ */
+DART_EXPORT char* Dart_GetVmStatus(const char* request);
+
 #endif  // INCLUDE_DART_DEBUGGER_API_H_
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc
index 6be9093..ac879d3 100644
--- a/runtime/lib/array.cc
+++ b/runtime/lib/array.cc
@@ -14,20 +14,29 @@
 
 DEFINE_NATIVE_ENTRY(ObjectArray_allocate, 2) {
   const AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::CheckedHandle(arguments->NativeArgAt(0));
+      AbstractTypeArguments::CheckedHandle(isolate, arguments->NativeArgAt(0));
   ASSERT(type_arguments.IsNull() ||
          (type_arguments.IsInstantiated() && (type_arguments.Length() == 1)));
-  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1));
-  intptr_t len = length.Value();
+  const Instance& length = Instance::CheckedHandle(
+      isolate, arguments->NativeArgAt(1));
+  if (!length.IsSmi()) {
+    const String& error = String::Handle(String::NewFormatted(
+        "Length must be an integer in the range [0..%"Pd"].",
+        Array::kMaxElements));
+    const Array& args = Array::Handle(Array::New(1));
+    args.SetAt(0, error);
+    Exceptions::ThrowByType(Exceptions::kArgument, args);
+  }
+  intptr_t len = Smi::Cast(length).Value();
   if (len < 0 || len > Array::kMaxElements) {
     const String& error = String::Handle(String::NewFormatted(
-        "length (%"Pd") must be in the range [0..%"Pd"]",
+        "Length (%"Pd") must be an integer in the range [0..%"Pd"].",
         len, Array::kMaxElements));
     const Array& args = Array::Handle(Array::New(1));
     args.SetAt(0, error);
     Exceptions::ThrowByType(Exceptions::kArgument, args);
   }
-  const Array& new_array = Array::Handle(Array::New(length.Value()));
+  const Array& new_array = Array::Handle(Array::New(len));
   new_array.SetTypeArguments(type_arguments);
   return new_array.raw();
 }
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index 1441dc2..eb7bc70 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -6,7 +6,7 @@
 // TODO(srdjan): Use shared array implementation.
 class _ObjectArray<E> implements List<E> {
 
-  factory _ObjectArray(int length) native "ObjectArray_allocate";
+  factory _ObjectArray(length) native "ObjectArray_allocate";
 
   E operator [](int index) native "ObjectArray_getIndexed";
 
@@ -228,13 +228,17 @@
 
   E max([int compare(E a, E b)]) => IterableMixinWorkaround.max(this, compare);
 
-  List<E> toList() {
-    return new List<E>.from(this);
+  List<E> toList({ bool growable: true}) {
+    return new List<E>.from(this, growable: growable);
   }
 
   Set<E> toSet() {
     return new Set<E>.from(this);
   }
+
+  Map<int, E> asMap() {
+    return IterableMixinWorkaround.asMapList(this);
+  }
 }
 
 
@@ -467,13 +471,17 @@
 
   E max([int compare(E a, E b)]) => IterableMixinWorkaround.max(this, compare);
 
-  List<E> toList() {
-    return new List<E>.from(this);
+  List<E> toList({ bool growable: true }) {
+    return new List<E>.from(this, growable: growable);
   }
 
   Set<E> toSet() {
     return new Set<E>.from(this);
   }
+
+  Map<int, E> asMap() {
+    return IterableMixinWorkaround.asMapList(this);
+  }
 }
 
 
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index da5bf73..386e8ac 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -2,23 +2,28 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Note that the optimizing compiler depends on the algorithm which
-// returns a _GrowableObjectArray if length is null, otherwise returns
-// fixed size array.
+// The _GrowableArrayMarker class is used to signal to the List() factory
+// whether a parameter was passed.
+class _GrowableArrayMarker implements int {
+  const _GrowableArrayMarker();
+}
+
+const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
+
 patch class List<E> {
-  /* patch */ factory List([int length = 0]) {
-    if ((length is! int) || (length < 0)) {
-      _throwArgumentError(length);
+  /* patch */ factory List([int length = _GROWABLE_ARRAY_MARKER]) {
+    if (identical(length, _GROWABLE_ARRAY_MARKER)) {
+      return new _GrowableObjectArray<E>(0);
     }
-    _GrowableObjectArray<E> result = new _GrowableObjectArray<E>(length);
-    return result;
+    // All error handling on the length parameter is done at the implementation
+    // of new _ObjectArray.
+    return new _ObjectArray<E>(length);
   }
 
-  /* patch */ factory List.fixedLength(int length, {E fill: null}) {
-    if ((length is! int) || (length < 0)) {
-      _throwArgumentError(length);
-    }
-    _ObjectArray<E> result = new _ObjectArray<E>(length);
+  /* patch */ factory List.filled(int length, E fill) {
+    // All error handling on the length parameter is done at the implementation
+    // of new _ObjectArray.
+    var result = new _ObjectArray<E>(length);
     if (fill != null) {
       for (int i = 0; i < length; i++) {
         result[i] = fill;
@@ -37,8 +42,4 @@
     result._setLength(elements.length);
     return result;
   }
-
-  static void _throwArgumentError(int length) {
-    throw new ArgumentError("Length must be a positive integer: $length.");
-  }
 }
diff --git a/runtime/lib/byte_array.cc b/runtime/lib/byte_array.cc
index a96d211..08e0bc8 100644
--- a/runtime/lib/byte_array.cc
+++ b/runtime/lib/byte_array.cc
@@ -251,6 +251,16 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(ByteArray_getFloat32x4, 2) {
+  UNALIGNED_GETTER(ByteArray, Float32x4, simd_value_t);
+}
+
+
+DEFINE_NATIVE_ENTRY(ByteArray_setFloat32x4, 3) {
+  UNALIGNED_SETTER(ByteArray, Float32x4, value, simd_value_t);
+}
+
+
 DEFINE_NATIVE_ENTRY(ByteArray_getFloat32, 2) {
   UNALIGNED_GETTER(ByteArray, Double, float);
 }
@@ -596,6 +606,38 @@
   SETTER_UINT64(Uint64Array);
 }
 
+// Float32x4Array
+
+DEFINE_NATIVE_ENTRY(Float32x4Array_new, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0));
+  intptr_t len = length.Value();
+  LengthCheck(len, Float32x4Array::kMaxElements);
+  return Float32x4Array::New(len);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4List_newTransferable, 1) {
+  const int kAlignment = 16;
+  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);
+  const ExternalFloat32x4Array& obj =
+      ExternalFloat32x4Array::Handle(ExternalFloat32x4Array::New(bytes, len));
+  obj.AddFinalizer(bytes, PeerFinalizer);
+  return obj.raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4Array_getIndexed, 2) {
+  GETTER(Float32x4Array, Float32x4, simd_value_t);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4Array_setIndexed, 3) {
+  SETTER(Float32x4Array, Float32x4, value, simd_value_t);
+}
+
 
 // Float32Array
 
@@ -771,6 +813,18 @@
 }
 
 
+// ExternalFloat32x4Array
+
+DEFINE_NATIVE_ENTRY(ExternalFloat32x4Array_getIndexed, 2) {
+  GETTER(ExternalFloat32x4Array, Float32x4, simd_value_t);
+}
+
+
+DEFINE_NATIVE_ENTRY(ExternalFloat32x4Array_setIndexed, 3) {
+  SETTER(ExternalFloat32x4Array, Float32x4, value, simd_value_t);
+}
+
+
 // ExternalFloat32Array
 
 DEFINE_NATIVE_ENTRY(ExternalFloat32Array_getIndexed, 2) {
diff --git a/runtime/lib/byte_array.dart b/runtime/lib/byte_array.dart
index 7eb126a..2323fdf 100644
--- a/runtime/lib/byte_array.dart
+++ b/runtime/lib/byte_array.dart
@@ -325,12 +325,11 @@
   }
 
   int indexOf(element, [int start = 0]) {
-    return Arrays.indexOf(this, element, start, this.length);
+    return IterableMixinWorkaround.indexOfList(this, element, start);
   }
 
   int lastIndexOf(element, [int start = null]) {
-    if (start == null) start = length - 1;
-    return Arrays.lastIndexOf(this, element, start);
+    return IterableMixinWorkaround.lastIndexOfList(this, element, start);
   }
 
   void clear() {
@@ -408,8 +407,8 @@
                               length * this.bytesPerElement());
   }
 
-  List<int> toList() {
-    return new List<int>.from(this);
+  List<int> toList({ bool growable: true }) {
+    return new List<int>.from(this, growable: growable);
   }
 
   Set<int> toSet() {
@@ -446,6 +445,10 @@
   int _getUint64(int byteOffset) native "ByteArray_getUint64";
   int _setUint64(int byteOffset, int value) native "ByteArray_setUint64";
 
+  Float32x4 _getFloat32x4(int byteOffset) native "ByteArray_getFloat32x4";
+  int _setFloat32x4(int byteOffset, Float32x4 value)
+      native "ByteArray_setFloat32x4";
+
   double _getFloat32(int byteOffset) native "ByteArray_getFloat32";
   int _setFloat32(int byteOffset, double value) native "ByteArray_setFloat32";
 
@@ -567,7 +570,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+         this, start, length, from, startFrom);
     }
   }
 
@@ -631,7 +635,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -696,7 +701,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -759,7 +765,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -822,7 +829,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -885,7 +893,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -949,7 +958,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1012,7 +1022,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1075,7 +1086,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1138,7 +1150,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1201,7 +1214,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1253,7 +1267,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1303,7 +1318,7 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
     }
   }
 
@@ -1355,7 +1370,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1405,7 +1421,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1455,7 +1472,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1507,7 +1525,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1559,7 +1578,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1611,7 +1631,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1663,7 +1684,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1715,7 +1737,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1767,7 +1790,8 @@
                 from,
                 startFrom * _BYTES_PER_ELEMENT);
     } else {
-      Arrays.copy(from, startFrom, this, start, length);
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
     }
   }
 
@@ -1894,6 +1918,13 @@
     return _array._setUint64(_offset + byteOffset, value);
   }
 
+  Float32x4 getFloat32x4(int byteOffset) {
+    return _array._getFloat32x4(_offset + byteOffset);
+  }
+  int setFloat32x4(int byteOffset, Float32x4 value) {
+    return _array._setFloat32x4(_offset + byteOffset, value);
+  }
+
   double getFloat32(int byteOffset) {
     return _array._getFloat32(_offset + byteOffset);
   }
@@ -1962,12 +1993,11 @@
   }
 
   int indexOf(element, [int start = 0]) {
-    return Arrays.indexOf(this, element, start, this.length);
+    return IterableMixinWorkaround.indexOfList(this, element, start);
   }
 
   int lastIndexOf(element, [int start = null]) {
-    if (start == null) start = length - 1;
-    return Arrays.lastIndexOf(this, element, start);
+    return IterableMixinWorkaround.lastIndexOfList(this, element, start);
   }
 
   void clear() {
@@ -2036,6 +2066,10 @@
         "Cannot add to a non-extendable array");
   }
 
+  Map<int, int> asMap() {
+    return IterableMixinWorkaround.asMapList(this);
+  }
+
   final ByteArray _array;
   final int _offset;
   final int length;
@@ -2079,7 +2113,7 @@
   }
 
   void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2143,7 +2177,7 @@
   }
 
   void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2207,7 +2241,7 @@
   }
 
   void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2271,7 +2305,7 @@
   }
 
   void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2335,7 +2369,7 @@
   }
 
   void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2399,7 +2433,7 @@
   }
 
   void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2463,7 +2497,7 @@
   }
 
   void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2527,7 +2561,7 @@
   }
 
   void setRange(int start, int length, List<int> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2591,7 +2625,7 @@
   }
 
   void setRange(int start, int length, List<double> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
@@ -2655,7 +2689,7 @@
   }
 
   void setRange(int start, int length, List<double> from, [int startFrom = 0]) {
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   String toString() {
diff --git a/tests/language/script_negative_lib.dart b/runtime/lib/core_patch.dart
similarity index 63%
rename from tests/language/script_negative_lib.dart
rename to runtime/lib/core_patch.dart
index 72ea4f9..abaaea2 100644
--- a/tests/language/script_negative_lib.dart
+++ b/runtime/lib/core_patch.dart
@@ -1,7 +1,5 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-class A {
-  var a;
-}
+import "dart:math";
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index e133681..3fc2261 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -200,6 +200,36 @@
 
 DEFINE_NATIVE_ENTRY(Double_parse, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
+  if (value.IsOneByteString()) {
+    // Quick conversion for unpadded doubles in strings.
+    const intptr_t len = value.Length();
+    if (len > 0) {
+      const char* cstr = value.ToCString();
+      ASSERT(cstr != NULL);
+      // Dart differences from strtod:
+      // a) '5.' is not a valid double (no digit after period).
+      // b) '+5.0' is not a valid double (leading plus).
+      if (cstr[0] != '+') {
+        bool dot_ok = true;
+        const char* tmp = cstr;
+        while (*tmp != '\0') {
+          const char ch = *tmp++;
+          if (ch == '.') {
+            const char nextCh = *tmp;
+            dot_ok = ('0' <= nextCh) && (nextCh <= '9');
+            break;
+          }
+        }
+        if (dot_ok) {
+          char* p_end = NULL;
+          const double double_value = strtod(cstr, &p_end);
+          if (p_end == (cstr + len)) {
+            return Double::New(double_value);
+          }
+        }
+      }
+    }
+  }
   Scanner scanner(value, Symbols::Empty());
   const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
   String* number_string;
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index b821791..6f3fb4a 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -16,15 +16,11 @@
 DEFINE_NATIVE_ENTRY(Function_apply, 2) {
   const Array& fun_arguments = Array::CheckedHandle(arguments->NativeArgAt(0));
   const Array& fun_arg_names = Array::CheckedHandle(arguments->NativeArgAt(1));
-  Instance& instance = Instance::Handle();
-  instance ^= fun_arguments.At(0);
   const Array& fun_args_desc =
       Array::Handle(ArgumentsDescriptor::New(fun_arguments.Length(),
                                              fun_arg_names));
   const Object& result =
-      Object::Handle(DartEntry::InvokeClosure(instance,
-                                              fun_arguments,
-                                              fun_args_desc));
+      Object::Handle(DartEntry::InvokeClosure(fun_arguments, fun_args_desc));
   if (result.IsError()) {
     Exceptions::PropagateError(Error::Cast(result));
   }
diff --git a/runtime/lib/function_patch.dart b/runtime/lib/function_patch.dart
index cb5a0c27..56b817d 100644
--- a/runtime/lib/function_patch.dart
+++ b/runtime/lib/function_patch.dart
@@ -13,10 +13,10 @@
         (positionalArguments != null ? positionalArguments.length : 0);
     int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
     int numArguments = numPositionalArguments + numNamedArguments;
-    List arguments = new List.fixedLength(numArguments);
+    List arguments = new List(numArguments);
     arguments[0] = function;
     arguments.setRange(1, numPositionalArguments - 1, positionalArguments);
-    List names = new List.fixedLength(numNamedArguments);
+    List names = new List(numNamedArguments);
     int argumentIndex = numPositionalArguments;
     int nameIndex = 0;
     if (numNamedArguments > 0) {
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index 27699e2..5759178 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -48,10 +48,7 @@
   }
 
   void setRange(int start, int length, List<T> from, [int startFrom = 0]) {
-    if (length < 0) {
-      throw new ArgumentError("negative length $length");
-    }
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   void removeRange(int start, int length) {
@@ -194,12 +191,11 @@
   T max([int compare(T a, T b)]) => IterableMixinWorkaround.max(this, compare);
 
   int indexOf(T element, [int start = 0]) {
-    return Arrays.indexOf(this, element, start, length);
+    return IterableMixinWorkaround.indexOfList(this, element, start);
   }
 
   int lastIndexOf(T element, [int start = null]) {
-    if (start == null) start = length - 1;
-    return Arrays.lastIndexOf(this, element, start);
+    return IterableMixinWorkaround.lastIndexOfList(this, element, start);
   }
 
   void _grow(int new_length) {
@@ -320,11 +316,15 @@
     return new ListIterator<T>(this);
   }
 
-  List<T> toList() {
-    return new List<T>.from(this);
+  List<T> toList({ bool growable: true }) {
+    return new List<T>.from(this, growable: growable);
   }
 
   Set<T> toSet() {
     return new Set<T>.from(this);
   }
+
+  Map<int, T> asMap() {
+    return IterableMixinWorkaround.asMapList(this);
+  }
 }
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index c0eb573..f6133dd 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -183,6 +183,26 @@
 
 DEFINE_NATIVE_ENTRY(Integer_parse, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
+  if (value.IsOneByteString()) {
+    // Quick conversion for unpadded integers in strings.
+    const intptr_t len = value.Length();
+    if (len > 0) {
+      const char* cstr = value.ToCString();
+      ASSERT(cstr != NULL);
+      // Dart differences from strtol:
+      // a) '+5' is not a valid integer (leading plus).
+      if (cstr[0] != '+') {
+        char* p_end = NULL;
+        const int64_t int_value = strtol(cstr, &p_end, 10);
+        if (p_end == (cstr + len)) {
+          if ((Smi::kMinValue <= int_value) && (int_value <= Smi::kMaxValue)) {
+            return Smi::New(int_value);
+          }
+        }
+      }
+    }
+  }
+
   Scanner scanner(value, Symbols::Empty());
   const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
   String* int_string;
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index c6485ab..de4abdb 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -15,9 +15,14 @@
   /* patch */ static int parse(String source,
                                { int radix,
                                  int onError(String str) }) {
+    if ((radix == null) && (onError == null)) return _parse(source);
+    return _slowParse(source, radix, onError);
+  }
+
+  static int _slowParse(String source, int radix, int onError(String str)) {
     if (source is! String) throw new ArgumentError(source);
     if (radix == null) {
-      if (onError == null) return _parse(source);
+      assert(onError != null);
       try {
         return _parse(source);
       } on FormatException {
@@ -50,12 +55,12 @@
     ];
 
     int i = 0;
-    int code = source.charCodeAt(i);
+    int code = source.codeUnitAt(i);
     if (code == 0x2d || code == 0x2b) { // Starts with a plus or minus-sign.
       negative = (code == 0x2d);
       if (source.length == 1) return onError(source);
       i = 1;
-      code = source.charCodeAt(i);
+      code = source.codeUnitAt(i);
     }
     do {
       if (code < 0x30 || code > 0x7f) return onError(source);
@@ -64,7 +69,7 @@
       result = result * radix + digit;
       i++;
       if (i == source.length) break;
-      code = source.charCodeAt(i);
+      code = source.codeUnitAt(i);
     } while (true);
     return negative ? -result : result;
   }
diff --git a/runtime/lib/invocation_mirror.cc b/runtime/lib/invocation_mirror.cc
index 8e0880a..a8c70b3 100644
--- a/runtime/lib/invocation_mirror.cc
+++ b/runtime/lib/invocation_mirror.cc
@@ -44,9 +44,9 @@
                                            invoke_arguments,
                                            fun_args_desc);
   } else {
-    result = DartEntry::InvokeDynamic(function,
-                                      invoke_arguments,
-                                      fun_args_desc);
+    result = DartEntry::InvokeFunction(function,
+                                       invoke_arguments,
+                                       fun_args_desc);
   }
   if (result.IsError()) {
     Exceptions::PropagateError(Error::Cast(result));
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index e7edbe0..ea975ca 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -74,7 +74,7 @@
   const Array& args = Array::Handle(isolate, Array::New(kNumArguments));
   args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id)));
   const Object& result =
-      Object::Handle(isolate, DartEntry::InvokeStatic(func, args));
+      Object::Handle(isolate, DartEntry::InvokeFunction(func, args));
   if (!result.IsError()) {
     PortMap::SetLive(port_id);
   }
@@ -374,7 +374,7 @@
     ASSERT(result.IsFunction());
     Function& func = Function::Handle(isolate);
     func ^= result.raw();
-    result = DartEntry::InvokeStatic(func, Object::empty_array());
+    result = DartEntry::InvokeFunction(func, Object::empty_array());
     if (result.IsError()) {
       StoreError(isolate, result);
       return false;
diff --git a/runtime/lib/json_patch.dart b/runtime/lib/json_patch.dart
new file mode 100644
index 0000000..0b637a1
--- /dev/null
+++ b/runtime/lib/json_patch.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// JSON parsing and serialization.
+
+patch parse(String json, [reviver(var key, var value)]) {
+  return _parse(json, reviver);
+}
diff --git a/runtime/lib/json_sources.gypi b/runtime/lib/json_sources.gypi
new file mode 100644
index 0000000..1622f7b
--- /dev/null
+++ b/runtime/lib/json_sources.gypi
@@ -0,0 +1,9 @@
+# Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+{
+  'sources': [
+    'json_patch.dart',
+  ],
+}
diff --git a/runtime/lib/lib_sources.gypi b/runtime/lib/lib_sources.gypi
index f5b6c04..27e36a9 100644
--- a/runtime/lib/lib_sources.gypi
+++ b/runtime/lib/lib_sources.gypi
@@ -6,6 +6,8 @@
 
 {
   'sources': [
+    'core_patch.dart',
+    # The above file needs to be first as it imports required libraries.
     'bool_patch.dart',
     'date.cc',
     'date_patch.dart',
@@ -41,6 +43,8 @@
     'regexp_jsc.cc',
     'regexp_jsc.h',
     'regexp_patch.dart',
+    'stacktrace.cc',
+    'stacktrace_patch.dart',
     'stopwatch_patch.dart',
     'stopwatch.cc',
     'string.cc',
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index fa9dc7e..0be4213 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -51,7 +51,7 @@
 
 class _Random implements Random {
   // Internal state of the random number generator.
-  final _state = new List.fixedLength(2);
+  final _state = new List(2);
   static const kSTATE_LO = 0;
   static const kSTATE_HI = 1;
 
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 7ece160..d8c78e1 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -244,7 +244,8 @@
         output = r'\v';
         break;
       default:
-        int code = input.charCodeAt(0);
+        // TODO(lrn): Someone decide if this should combine surrogate pairs.
+        int code = input.codeUnitAt(0);
         if (isNice(code)) {
           output = input;
         } else {
diff --git a/runtime/lib/mirrors_patch.dart b/runtime/lib/mirrors_patch.dart
index 9b61edb..78bbbd6 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/runtime/lib/mirrors_patch.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import "dart:nativewrappers";
+
 /**
  * Returns a [MirrorSystem] for the current isolate.
  */
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 674ab64..3416698 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -54,12 +54,12 @@
     return regexp.num_bracket_expressions();
   }
   const String& pattern = String::Handle(regexp.pattern());
-  const String& errmsg =
-      String::Handle(String::New("Regular expression is not initialized yet"));
-  const Array& args = Array::Handle(Array::New(2));
-  args.SetAt(0, pattern);
-  args.SetAt(1, errmsg);
-  Exceptions::ThrowByType(Exceptions::kIllegalJSRegExp, args);
+  const String& errmsg = String::Handle(
+      String::New("Regular expression is not initialized yet. "));
+  const String& message = String::Handle(String::Concat(errmsg, pattern));
+  const Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0, message);
+  Exceptions::ThrowByType(Exceptions::kFormat, args);
   return Object::null();
 }
 
diff --git a/runtime/lib/regexp_jsc.cc b/runtime/lib/regexp_jsc.cc
index cb3ec68..158579f 100644
--- a/runtime/lib/regexp_jsc.cc
+++ b/runtime/lib/regexp_jsc.cc
@@ -41,13 +41,13 @@
 static void ThrowExceptionOnError(const String& pattern,
                                   const char* error_msg) {
   if (error_msg == NULL) {
-    error_msg = "Unknown regexp compile error";
+    error_msg = "Unknown regexp compile error. ";
   }
   const String& errmsg = String::Handle(String::New(error_msg));
-  const Array& args = Array::Handle(Array::New(2));
-  args.SetAt(0, pattern);
-  args.SetAt(1, errmsg);
-  Exceptions::ThrowByType(Exceptions::kIllegalJSRegExp, args);
+  const String& message = String::Handle(String::Concat(errmsg, pattern));
+  const Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0, message);
+  Exceptions::ThrowByType(Exceptions::kFormat, args);
 }
 
 
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index 2eab296..e365f30 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -44,7 +44,7 @@
   }
 
   List<String> groups(List<int> groupsSpec) {
-    var groupsList = new List<String>.fixedLength(groupsSpec.length);
+    var groupsList = new List<String>(groupsSpec.length);
     for (int i = 0; i < groupsSpec.length; i++) {
       groupsList[i] = group(groupsSpec[i]);
     }
diff --git a/runtime/lib/scalarlist_sources.gypi b/runtime/lib/scalarlist_sources.gypi
index cb7c3dd..678ceb6 100644
--- a/runtime/lib/scalarlist_sources.gypi
+++ b/runtime/lib/scalarlist_sources.gypi
@@ -8,6 +8,8 @@
   'sources': [
     'byte_array.cc',
     'byte_array.dart',
+    'simd128.cc',
+    'simd128.dart',
   ],
 }
 
diff --git a/runtime/lib/simd128.cc b/runtime/lib/simd128.cc
new file mode 100644
index 0000000..25e8db7
--- /dev/null
+++ b/runtime/lib/simd128.cc
@@ -0,0 +1,612 @@
+// 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.
+
+#include "vm/bootstrap_natives.h"
+
+#include "vm/exceptions.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+#include "vm/symbols.h"
+
+namespace dart {
+
+DEFINE_NATIVE_ENTRY(Float32x4_fromDoubles, 5) {
+  ASSERT(AbstractTypeArguments::CheckedHandle(
+      arguments->NativeArgAt(0)).IsNull());
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, x, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, y, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, z, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, w, arguments->NativeArgAt(4));
+  float _x = x.value();
+  float _y = y.value();
+  float _z = z.value();
+  float _w = w.value();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_zero, 1) {
+  ASSERT(AbstractTypeArguments::CheckedHandle(
+      arguments->NativeArgAt(0)).IsNull());
+  return Float32x4::New(0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_add, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
+  float _x = self.x() + other.x();
+  float _y = self.y() + other.y();
+  float _z = self.z() + other.z();
+  float _w = self.w() + other.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_negate, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float _x = -self.x();
+  float _y = -self.y();
+  float _z = -self.z();
+  float _w = -self.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_sub, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
+  float _x = self.x() - other.x();
+  float _y = self.y() - other.y();
+  float _z = self.z() - other.z();
+  float _w = self.w() - other.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_mul, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other,
+                               arguments->NativeArgAt(1));
+  float _x = self.x() * other.x();
+  float _y = self.y() * other.y();
+  float _z = self.z() * other.z();
+  float _w = self.w() * other.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_div, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other, arguments->NativeArgAt(1));
+  float _x = self.x() / other.x();
+  float _y = self.y() / other.y();
+  float _z = self.z() / other.z();
+  float _w = self.w() / other.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmplt, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+  uint32_t _x = a.x() < b.x() ? 0xFFFFFFFF : 0x0;
+  uint32_t _y = a.y() < b.y() ? 0xFFFFFFFF : 0x0;
+  uint32_t _z = a.z() < b.z() ? 0xFFFFFFFF : 0x0;
+  uint32_t _w = a.w() < b.w() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmplte, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+  uint32_t _x = a.x() <= b.x() ? 0xFFFFFFFF : 0x0;
+  uint32_t _y = a.y() <= b.y() ? 0xFFFFFFFF : 0x0;
+  uint32_t _z = a.z() <= b.z() ? 0xFFFFFFFF : 0x0;
+  uint32_t _w = a.w() <= b.w() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmpgt, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+  uint32_t _x = a.x() > b.x() ? 0xFFFFFFFF : 0x0;
+  uint32_t _y = a.y() > b.y() ? 0xFFFFFFFF : 0x0;
+  uint32_t _z = a.z() > b.z() ? 0xFFFFFFFF : 0x0;
+  uint32_t _w = a.w() > b.w() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmpgte, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+  uint32_t _x = a.x() >= b.x() ? 0xFFFFFFFF : 0x0;
+  uint32_t _y = a.y() >= b.y() ? 0xFFFFFFFF : 0x0;
+  uint32_t _z = a.z() >= b.z() ? 0xFFFFFFFF : 0x0;
+  uint32_t _w = a.w() >= b.w() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmpequal, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+  uint32_t _x = a.x() == b.x() ? 0xFFFFFFFF : 0x0;
+  uint32_t _y = a.y() == b.y() ? 0xFFFFFFFF : 0x0;
+  uint32_t _z = a.z() == b.z() ? 0xFFFFFFFF : 0x0;
+  uint32_t _w = a.w() == b.w() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_cmpnequal, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, b, arguments->NativeArgAt(1));
+  uint32_t _x = a.x() != b.x() ? 0xFFFFFFFF : 0x0;
+  uint32_t _y = a.y() != b.y() ? 0xFFFFFFFF : 0x0;
+  uint32_t _z = a.z() != b.z() ? 0xFFFFFFFF : 0x0;
+  uint32_t _w = a.w() != b.w() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_scale, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, scale, arguments->NativeArgAt(1));
+  float _s = static_cast<float>(scale.value());
+  float _x = self.x() * _s;
+  float _y = self.y() * _s;
+  float _z = self.z() * _s;
+  float _w = self.w() * _s;
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_abs, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float _x = fabsf(self.x());
+  float _y = fabsf(self.y());
+  float _z = fabsf(self.z());
+  float _w = fabsf(self.w());
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_clamp, 3) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, lo, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, hi, arguments->NativeArgAt(2));
+  float _x = self.x() > lo.x() ? self.x() : lo.x();
+  float _y = self.y() > lo.y() ? self.y() : lo.y();
+  float _z = self.z() > lo.z() ? self.z() : lo.z();
+  float _w = self.w() > lo.w() ? self.w() : lo.w();
+  _x = _x > hi.x() ? hi.x() : _x;
+  _y = _y > hi.y() ? hi.y() : _y;
+  _z = _z > hi.z() ? hi.z() : _z;
+  _w = _w > hi.w() ? hi.w() : _w;
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getX, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  double value = static_cast<double>(self.x());
+  return Double::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getY, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  double value = static_cast<double>(self.y());
+  return Double::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getZ, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  double value = static_cast<double>(self.z());
+  return Double::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getW, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  double value = static_cast<double>(self.w());
+  return Double::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getXXXX, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float value = self.x();
+  return Float32x4::New(value, value, value, value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getYYYY, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float value = self.y();
+  return Float32x4::New(value, value, value, value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getZZZZ, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float value = self.z();
+  return Float32x4::New(value, value, value, value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_getWWWW, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float value = self.w();
+  return Float32x4::New(value, value, value, value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_setX, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, x, arguments->NativeArgAt(1));
+  float _x = static_cast<float>(x.value());
+  float _y = self.y();
+  float _z = self.z();
+  float _w = self.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_setY, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, y, arguments->NativeArgAt(1));
+  float _x = self.x();
+  float _y = static_cast<float>(y.value());
+  float _z = self.z();
+  float _w = self.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_setZ, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, z, arguments->NativeArgAt(1));
+  float _x = self.x();
+  float _y = self.y();
+  float _z = static_cast<float>(z.value());
+  float _w = self.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_setW, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Double, w, arguments->NativeArgAt(1));
+  float _x = self.x();
+  float _y = self.y();
+  float _z = self.z();
+  float _w = static_cast<float>(w.value());
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_min, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other,
+                               arguments->NativeArgAt(1));
+  float _x = self.x() < other.x() ? self.x() : other.x();
+  float _y = self.y() < other.y() ? self.y() : other.y();
+  float _z = self.z() < other.z() ? self.z() : other.z();
+  float _w = self.w() < other.w() ? self.w() : other.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_max, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, other,
+                               arguments->NativeArgAt(1));
+  float _x = self.x() > other.x() ? self.x() : other.x();
+  float _y = self.y() > other.y() ? self.y() : other.y();
+  float _z = self.z() > other.z() ? self.z() : other.z();
+  float _w = self.w() > other.w() ? self.w() : other.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_sqrt, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float _x = sqrtf(self.x());
+  float _y = sqrtf(self.y());
+  float _z = sqrtf(self.z());
+  float _w = sqrtf(self.w());
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_reciprocal, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float _x = 1.0f / self.x();
+  float _y = 1.0f / self.y();
+  float _z = 1.0f / self.z();
+  float _w = 1.0f / self.w();
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_reciprocalSqrt, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, self, arguments->NativeArgAt(0));
+  float _x = sqrtf(1.0f / self.x());
+  float _y = sqrtf(1.0f / self.y());
+  float _z = sqrtf(1.0f / self.z());
+  float _w = sqrtf(1.0f / self.w());
+  return Float32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Float32x4_toUint32x4, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(0));
+  return Uint32x4::New(v.value());
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_fromInts, 5) {
+  ASSERT(AbstractTypeArguments::CheckedHandle(
+      arguments->NativeArgAt(0)).IsNull());
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, x, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, y, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, z, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, w, arguments->NativeArgAt(4));
+  uint32_t _x = static_cast<uint32_t>(x.AsInt64Value() & 0xFFFFFFFF);
+  uint32_t _y = static_cast<uint32_t>(y.AsInt64Value() & 0xFFFFFFFF);
+  uint32_t _z = static_cast<uint32_t>(z.AsInt64Value() & 0xFFFFFFFF);
+  uint32_t _w = static_cast<uint32_t>(w.AsInt64Value() & 0xFFFFFFFF);
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_fromBools, 5) {
+  ASSERT(AbstractTypeArguments::CheckedHandle(
+      arguments->NativeArgAt(0)).IsNull());
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, x, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, y, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, z, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, w, arguments->NativeArgAt(4));
+  uint32_t _x = x.value() ? 0xFFFFFFFF : 0x0;
+  uint32_t _y = y.value() ? 0xFFFFFFFF : 0x0;
+  uint32_t _z = z.value() ? 0xFFFFFFFF : 0x0;
+  uint32_t _w = w.value() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_or, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, other, arguments->NativeArgAt(1));
+  uint32_t _x = self.x() | other.x();
+  uint32_t _y = self.y() | other.y();
+  uint32_t _z = self.z() | other.z();
+  uint32_t _w = self.w() | other.w();
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_and, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, other, arguments->NativeArgAt(1));
+  uint32_t _x = self.x() & other.x();
+  uint32_t _y = self.y() & other.y();
+  uint32_t _z = self.z() & other.z();
+  uint32_t _w = self.w() & other.w();
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_xor, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, other, arguments->NativeArgAt(1));
+  uint32_t _x = self.x() ^ other.x();
+  uint32_t _y = self.y() ^ other.y();
+  uint32_t _z = self.z() ^ other.z();
+  uint32_t _w = self.w() ^ other.w();
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getX, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  uint32_t value = self.x();
+  return Integer::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getY, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  uint32_t value = self.y();
+  return Integer::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getZ, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  uint32_t value = self.z();
+  return Integer::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getW, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  uint32_t value = self.w();
+  return Integer::New(value);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setX, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, x, arguments->NativeArgAt(1));
+  uint32_t _x = static_cast<uint32_t>(x.AsInt64Value() & 0xFFFFFFFF);
+  uint32_t _y = self.y();
+  uint32_t _z = self.z();
+  uint32_t _w = self.w();
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setY, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, y, arguments->NativeArgAt(1));
+  uint32_t _x = self.x();
+  uint32_t _y = static_cast<uint32_t>(y.AsInt64Value() & 0xFFFFFFFF);
+  uint32_t _z = self.z();
+  uint32_t _w = self.w();
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setZ, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, z, arguments->NativeArgAt(1));
+  uint32_t _x = self.x();
+  uint32_t _y = self.y();
+  uint32_t _z = static_cast<uint32_t>(z.AsInt64Value() & 0xFFFFFFFF);
+  uint32_t _w = self.w();
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setW, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, w, arguments->NativeArgAt(1));
+  uint32_t _x = self.x();
+  uint32_t _y = self.y();
+  uint32_t _z = self.z();
+  uint32_t _w = static_cast<uint32_t>(w.AsInt64Value() & 0xFFFFFFFF);
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getFlagX, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  uint32_t value = self.x();
+  return value != 0 ? Bool::True().raw() : Bool::False().raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getFlagY, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  uint32_t value = self.y();
+  return value != 0 ? Bool::True().raw() : Bool::False().raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getFlagZ, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  uint32_t value = self.z();
+  return value != 0 ? Bool::True().raw() : Bool::False().raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_getFlagW, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  uint32_t value = self.w();
+  return value != 0 ? Bool::True().raw() : Bool::False().raw();
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setFlagX, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, flagX, arguments->NativeArgAt(1));
+  uint32_t _x = self.x();
+  uint32_t _y = self.y();
+  uint32_t _z = self.z();
+  uint32_t _w = self.w();
+  _x = flagX.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setFlagY, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, flagY, arguments->NativeArgAt(1));
+  uint32_t _x = self.x();
+  uint32_t _y = self.y();
+  uint32_t _z = self.z();
+  uint32_t _w = self.w();
+  _y = flagY.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setFlagZ, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, flagZ, arguments->NativeArgAt(1));
+  uint32_t _x = self.x();
+  uint32_t _y = self.y();
+  uint32_t _z = self.z();
+  uint32_t _w = self.w();
+  _z = flagZ.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_setFlagW, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, flagW, arguments->NativeArgAt(1));
+  uint32_t _x = self.x();
+  uint32_t _y = self.y();
+  uint32_t _z = self.z();
+  uint32_t _w = self.w();
+  _w = flagW.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+  return Uint32x4::New(_x, _y, _z, _w);
+}
+
+
+// Used to convert between uint32_t and float32 without breaking strict
+// aliasing rules.
+union float32_uint32 {
+  float f;
+  uint32_t u;
+  float32_uint32(float v) {
+    f = v;
+  }
+  float32_uint32(uint32_t v) {
+    u = v;
+  }
+};
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_select, 3) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, self, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, tv, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, fv, arguments->NativeArgAt(2));
+  uint32_t _maskX = self.x();
+  uint32_t _maskY = self.y();
+  uint32_t _maskZ = self.z();
+  uint32_t _maskW = self.w();
+  // Extract floats and interpret them as masks.
+  float32_uint32 tvx(tv.x());
+  float32_uint32 tvy(tv.y());
+  float32_uint32 tvz(tv.z());
+  float32_uint32 tvw(tv.w());
+  float32_uint32 fvx(fv.x());
+  float32_uint32 fvy(fv.y());
+  float32_uint32 fvz(fv.z());
+  float32_uint32 fvw(fv.w());
+  // Perform select.
+  float32_uint32 tempX((_maskX & tvx.u) | (~_maskX & fvx.u));
+  float32_uint32 tempY((_maskY & tvy.u) | (~_maskY & fvy.u));
+  float32_uint32 tempZ((_maskZ & tvz.u) | (~_maskZ & fvz.u));
+  float32_uint32 tempW((_maskW & tvw.u) | (~_maskW & fvw.u));
+  return Float32x4::New(tempX.f, tempY.f, tempZ.f, tempW.f);
+}
+
+
+DEFINE_NATIVE_ENTRY(Uint32x4_toFloat32x4, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Uint32x4, v, arguments->NativeArgAt(0));
+  return Float32x4::New(v.value());
+}
+
+
+}  // namespace dart
diff --git a/runtime/lib/simd128.dart b/runtime/lib/simd128.dart
new file mode 100644
index 0000000..5052773
--- /dev/null
+++ b/runtime/lib/simd128.dart
@@ -0,0 +1,758 @@
+// 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.
+
+patch class Float32x4 {
+  /* patch */ factory Float32x4(double x, double y, double z, double w) {
+    return new _Float32x4(x, y, z, w);
+  }
+  /* patch */ factory Float32x4.zero() {
+    return new _Float32x4.zero();
+  }
+}
+
+patch class Uint32x4 {
+  /* patch */ factory Uint32x4(int x, int y, int z, int w) {
+    return new _Uint32x4(x, y, z, w);
+  }
+  /* patch */ factory Uint32x4.bool(bool x, bool y, bool z, bool w) {
+    return new _Uint32x4.bool(x, y, z, w);
+  }
+}
+
+
+patch class Float32x4List {
+  /* patch */ factory Float32x4List(int length) {
+    return new _Float32x4Array(length);
+  }
+
+  /* patch */ factory Float32x4List.transferable(int length) {
+    return _newTransferable(length);
+  }
+
+  /* patch */ factory Float32x4List.view(ByteArray array,
+                                                [int start = 0, int length]) {
+    return new _Float32x4ArrayView(array, start, length);
+  }
+
+  static _ExternalFloat32x4Array _newTransferable(int length)
+      native "Float32x4List_newTransferable";
+}
+
+
+// Expose native square root.
+double _sqrt(double x) native "Math_sqrt";
+class _Float32x4Dart implements Float32x4 {
+  final Float32List _storage = new Float32List(4);
+  _Float32x4Dart.empty() {
+  }
+  _Float32x4Dart.copy(Float32List other) {
+    _storage[0] = other._storage[0];
+    _storage[1] = other._storage[1];
+    _storage[2] = other._storage[2];
+    _storage[3] = other._storage[3];
+  }
+  factory _Float32x4Dart(double x, double y, double z, double w) {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = x;
+    instance._storage[1] = y;
+    instance._storage[2] = z;
+    instance._storage[3] = w;
+    return instance;
+  }
+  factory _Float32x4Dart.zero() {
+    var instance = new _Float32x4Dart.empty();
+    return instance;
+  }
+  Float32x4 operator +(Float32x4 other) {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _storage[0] + other._storage[0];
+    instance._storage[1] = _storage[1] + other._storage[1];
+    instance._storage[2] = _storage[2] + other._storage[2];
+    instance._storage[3] = _storage[3] + other._storage[3];
+    return instance;
+  }
+  Float32x4 operator -() {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = -_storage[0];
+    instance._storage[1] = -_storage[1];
+    instance._storage[2] = -_storage[2];
+    instance._storage[3] = -_storage[3];
+    return instance;
+  }
+  Float32x4 operator -(Float32x4 other) {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _storage[0] - other._storage[0];
+    instance._storage[1] = _storage[1] - other._storage[1];
+    instance._storage[2] = _storage[2] - other._storage[2];
+    instance._storage[3] = _storage[3] - other._storage[3];
+    return instance;
+  }
+  Float32x4 operator *(Float32x4 other) {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _storage[0] * other._storage[0];
+    instance._storage[1] = _storage[1] * other._storage[1];
+    instance._storage[2] = _storage[2] * other._storage[2];
+    instance._storage[3] = _storage[3] * other._storage[3];
+    return instance;
+  }
+  Float32x4 operator /(Float32x4 other) {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _storage[0] / other._storage[0];
+    instance._storage[1] = _storage[1] / other._storage[1];
+    instance._storage[2] = _storage[2] / other._storage[2];
+    instance._storage[3] = _storage[3] / other._storage[3];
+    return instance;
+  }
+  Uint32x4 lessThan(Float32x4 other) {
+    bool _x = _storage[0] < other._storage[0];
+    bool _y = _storage[1] < other._storage[1];
+    bool _z = _storage[2] < other._storage[2];
+    bool _w = _storage[3] < other._storage[3];
+    return new Uint32x4.bool(_x, _y, _z, _w);
+  }
+  Uint32x4 lessThanOrEqual(Float32x4 other) {
+    bool _x = _storage[0] <= other._storage[0];
+    bool _y = _storage[1] <= other._storage[1];
+    bool _z = _storage[2] <= other._storage[2];
+    bool _w = _storage[3] <= other._storage[3];
+    return new Uint32x4.bool(_x, _y, _z, _w);
+  }
+  Uint32x4 greaterThan(Float32x4 other) {
+    bool _x = _storage[0] > other._storage[0];
+    bool _y = _storage[1] > other._storage[1];
+    bool _z = _storage[2] > other._storage[2];
+    bool _w = _storage[3] > other._storage[3];
+    return new Uint32x4.bool(_x, _y, _z, _w);
+  }
+  Uint32x4 greaterThanOrEqual(Float32x4 other) {
+    bool _x = _storage[0] >= other._storage[0];
+    bool _y = _storage[1] >= other._storage[1];
+    bool _z = _storage[2] >= other._storage[2];
+    bool _w = _storage[3] >= other._storage[3];
+    return new Uint32x4.bool(_x, _y, _z, _w);
+  }
+  Uint32x4 equal(Float32x4 other) {
+    bool _x = _storage[0] == other._storage[0];
+    bool _y = _storage[1] == other._storage[1];
+    bool _z = _storage[2] == other._storage[2];
+    bool _w = _storage[3] == other._storage[3];
+    return new Uint32x4.bool(_x, _y, _z, _w);
+  }
+  Uint32x4 notEqual(Float32x4 other) {
+    bool _x = _storage[0] != other._storage[0];
+    bool _y = _storage[1] != other._storage[1];
+    bool _z = _storage[2] != other._storage[2];
+    bool _w = _storage[3] != other._storage[3];
+    return new Uint32x4.bool(_x, _y, _z, _w);
+  }
+  Float32x4 scale(double s) {
+    var instance = new _Float32x4Dart.copy(this);
+    instance._storage[0] *= s;
+    instance._storage[1] *= s;
+    instance._storage[2] *= s;
+    instance._storage[3] *= s;
+    return instance;
+  }
+  Float32x4 abs() {
+    var instance = new _Float32x4Dart.copy(this);
+    instance._storage[0] = instance._storage[0].abs();
+    instance._storage[1] = instance._storage[1].abs();
+    instance._storage[2] = instance._storage[2].abs();
+    instance._storage[3] = instance._storage[3].abs();
+    return instance;
+  }
+  Float32x4 clamp(Float32x4 lowerLimit,
+                         Float32x4 upperLimit) {
+    var instance = new _Float32x4Dart.copy(this);
+    if (instance._storage[0] > upperLimit._storage[0]) {
+      instance._storage[0] = upperLimit._storage[0];
+    }
+    if (instance._storage[1] > upperLimit._storage[1]) {
+      instance._storage[1] = upperLimit._storage[1];
+    }
+    if (instance._storage[2] > upperLimit._storage[2]) {
+      instance._storage[2] = upperLimit._storage[2];
+    }
+    if (instance._storage[3] > upperLimit._storage[3]) {
+      instance._storage[3] = upperLimit._storage[3];
+    }
+    if (instance._storage[0] < lowerLimit._storage[0]) {
+      instance._storage[0] = lowerLimit._storage[0];
+    }
+    if (instance._storage[1] < lowerLimit._storage[1]) {
+      instance._storage[1] = lowerLimit._storage[1];
+    }
+    if (instance._storage[2] < lowerLimit._storage[2]) {
+      instance._storage[2] = lowerLimit._storage[2];
+    }
+    if (instance._storage[3] < lowerLimit._storage[3]) {
+      instance._storage[3] = lowerLimit._storage[3];
+    }
+    return instance;
+  }
+  double get x => _storage[0];
+  double get y => _storage[1];
+  double get z => _storage[2];
+  double get w => _storage[3];
+  Float32x4 get xxxx {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _storage[0];
+    instance._storage[1] = _storage[0];
+    instance._storage[2] = _storage[0];
+    instance._storage[3] = _storage[0];
+    return instance;
+  }
+  Float32x4 get yyyy {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _storage[1];
+    instance._storage[1] = _storage[1];
+    instance._storage[2] = _storage[1];
+    instance._storage[3] = _storage[1];
+    return instance;
+  }
+  Float32x4 get zzzz {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _storage[2];
+    instance._storage[1] = _storage[2];
+    instance._storage[2] = _storage[2];
+    instance._storage[3] = _storage[2];
+    return instance;
+  }
+  Float32x4 get wwww {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _storage[3];
+    instance._storage[1] = _storage[3];
+    instance._storage[2] = _storage[3];
+    instance._storage[3] = _storage[3];
+    return instance;
+  }
+  Float32x4 withX(double x) {
+    var instance = new _Float32x4Dart.copy(this);
+    instance._storage[0] = x;
+    return instance;
+  }
+  Float32x4 withY(double y) {
+    var instance = new _Float32x4Dart.copy(this);
+    instance._storage[1] = y;
+    return instance;
+  }
+  Float32x4 withZ(double z) {
+    var instance = new _Float32x4Dart.copy(this);
+    instance._storage[2] = z;
+    return instance;
+  }
+  Float32x4 withW(double w) {
+    var instance = new _Float32x4Dart.copy(this);
+    instance._storage[3] = w;
+    return instance;
+  }
+  Float32x4 min(Float32x4 other) {
+    var instance = new _Float32x4Dart.copy(this);
+    if (instance._storage[0] > other._storage[0]) {
+      instance._storage[0] = other._storage[0];
+    }
+    if (instance._storage[1] > other._storage[1]) {
+      instance._storage[1] = other._storage[1];
+    }
+    if (instance._storage[2] > other._storage[2]) {
+      instance._storage[2] = other._storage[2];
+    }
+    if (instance._storage[3] > other._storage[3]) {
+      instance._storage[3] = other._storage[3];
+    }
+    return instance;
+  }
+  Float32x4 max(Float32x4 other) {
+    var instance = new _Float32x4Dart.copy(this);
+    if (instance._storage[0] < other._storage[0]) {
+      instance._storage[0] = other._storage[0];
+    }
+    if (instance._storage[1] < other._storage[1]) {
+      instance._storage[1] = other._storage[1];
+    }
+    if (instance._storage[2] < other._storage[2]) {
+      instance._storage[2] = other._storage[2];
+    }
+    if (instance._storage[3] < other._storage[3]) {
+      instance._storage[3] = other._storage[3];
+    }
+    return instance;
+  }
+  Float32x4 sqrt() {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _sqrt(_storage[0]);
+    instance._storage[1] = _sqrt(_storage[1]);
+    instance._storage[2] = _sqrt(_storage[2]);
+    instance._storage[3] = _sqrt(_storage[3]);
+    return instance;
+  }
+  Float32x4 reciprocal() {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = (1.0 / _storage[0]);
+    instance._storage[1] = (1.0 / _storage[1]);
+    instance._storage[2] = (1.0 / _storage[2]);
+    instance._storage[3] = (1.0 / _storage[3]);
+    return instance;
+  }
+  Float32x4 reciprocalSqrt() {
+    var instance = new _Float32x4Dart.empty();
+    instance._storage[0] = _sqrt(1.0 / _storage[0]);
+    instance._storage[1] = _sqrt(1.0 / _storage[1]);
+    instance._storage[2] = _sqrt(1.0 / _storage[2]);
+    instance._storage[3] = _sqrt(1.0 / _storage[3]);
+    return instance;
+  }
+  Uint32x4 toUint32x4() {
+    Uint32List view = new Uint32List.view(_storage.asByteArray());
+    return new Uint32x4(view[0], view[1], view[2], view[3]);
+  }
+}
+
+class _Uint32x4Dart implements Uint32x4 {
+  final Uint32List _storage = new Uint32List(4);
+  _Uint32x4Dart.empty() {
+  }
+  _Uint32x4Dart.copy(_Uint32x4Dart other) {
+    _storage[0] = other._storage[0];
+    _storage[1] = other._storage[1];
+    _storage[2] = other._storage[2];
+    _storage[3] = other._storage[3];
+  }
+  factory _Uint32x4Dart(int x, int y, int z, int w) {
+    var instance = new _Uint32x4Dart.empty();
+    instance._storage[0] = x;
+    instance._storage[1] = y;
+    instance._storage[2] = z;
+    instance._storage[3] = w;
+    return instance;
+  }
+  factory _Uint32x4Dart.bool(bool x, bool y, bool z, bool w) {
+    var instance = new _Uint32x4Dart.empty();
+    instance._storage[0] = x ? 0xFFFFFFFF : 0x0;
+    instance._storage[1] = y ? 0xFFFFFFFF : 0x0;
+    instance._storage[2] = z ? 0xFFFFFFFF : 0x0;
+    instance._storage[3] = w ? 0xFFFFFFFF : 0x0;
+    return instance;
+  }
+  Uint32x4 operator |(Uint32x4 other) {
+    var instance = new _Uint32x4Dart.empty();
+    instance._storage[0] = _storage[0] | other._storage[0];
+    instance._storage[1] = _storage[1] | other._storage[1];
+    instance._storage[2] = _storage[2] | other._storage[2];
+    instance._storage[3] = _storage[3] | other._storage[3];
+    return instance;
+  }
+  Uint32x4 operator &(Uint32x4 other) {
+    var instance = new _Uint32x4Dart.empty();
+    instance._storage[0] = _storage[0] & other._storage[0];
+    instance._storage[1] = _storage[1] & other._storage[1];
+    instance._storage[2] = _storage[2] & other._storage[2];
+    instance._storage[3] = _storage[3] & other._storage[3];
+    return instance;
+  }
+  Uint32x4 operator ^(Uint32x4 other) {
+    var instance = new _Uint32x4Dart.empty();
+    instance._storage[0] = _storage[0] ^ other._storage[0];
+    instance._storage[1] = _storage[1] ^ other._storage[1];
+    instance._storage[2] = _storage[2] ^ other._storage[2];
+    instance._storage[3] = _storage[3] ^ other._storage[3];
+    return instance;
+  }
+  int get x => _storage[0];
+  int get y => _storage[1];
+  int get z => _storage[2];
+  int get w => _storage[3];
+  Uint32x4 withX(int x) {
+    var instance = new _Uint32x4Dart.copy(this);
+    instance._storage[0] = x & 0xFFFFFFFF;
+    return instance;
+  }
+  Uint32x4 withY(int y) {
+    var instance = new _Uint32x4Dart.copy(this);
+    instance._storage[1] = y & 0xFFFFFFFF;
+    return instance;
+  }
+  Uint32x4 withZ(int z) {
+    var instance = new _Uint32x4Dart.copy(this);
+    instance._storage[2] = z & 0xFFFFFFFF;
+    return instance;
+  }
+  Uint32x4 withW(int w) {
+    var instance = new _Uint32x4Dart.copy(this);
+    instance._storage[3] = w & 0xFFFFFFFF;
+    return instance;
+  }
+  bool get flagX => _storage[0] != 0x0;
+  bool get flagY => _storage[1] != 0x0;
+  bool get flagZ => _storage[2] != 0x0;
+  bool get flagW => _storage[3] != 0x0;
+  Uint32x4 withFlagX(bool x) {
+    var instance = new _Uint32x4Dart.copy(this);
+    instance._storage[0] = x ? 0xFFFFFFFF : 0x0;
+    return instance;
+  }
+  Uint32x4 withFlagY(bool y) {
+    var instance = new _Uint32x4Dart.copy(this);
+    instance._storage[1] = y ? 0xFFFFFFFF : 0x0;
+    return instance;
+  }
+  Uint32x4 withFlagZ(bool z) {
+    var instance = new _Uint32x4Dart.copy(this);
+    instance._storage[2] = z ? 0xFFFFFFFF : 0x0;
+    return instance;
+  }
+  Uint32x4 withFlagW(bool w) {
+    var instance = new _Uint32x4Dart.copy(this);
+    instance._storage[3] = w ? 0xFFFFFFFF : 0x0;
+    return instance;
+  }
+  Float32x4 select(Float32x4 trueValue,
+                          Float32x4 falseValue) {
+    Uint32x4 trueMask = trueValue.toUint32x4();
+    Uint32x4 falseMask = falseValue.toUint32x4();
+    var instance = new _Uint32x4Dart.empty();
+    instance._storage[0] = (_storage[0] & trueMask._storage[0]);
+    instance._storage[1] = (_storage[1] & trueMask._storage[1]);
+    instance._storage[2] = (_storage[2] & trueMask._storage[2]);
+    instance._storage[3] = (_storage[3] & trueMask._storage[3]);
+    instance._storage[0] |= (~_storage[0] & falseMask._storage[0]);
+    instance._storage[1] |= (~_storage[1] & falseMask._storage[1]);
+    instance._storage[2] |= (~_storage[2] & falseMask._storage[2]);
+    instance._storage[3] |= (~_storage[3] & falseMask._storage[3]);
+    return instance.toFloat32x4();
+  }
+  Float32x4 toFloat32x4() {
+    Float32List view = new Float32List.view(_storage.asByteArray());
+    return new Float32x4(view[0], view[1], view[2], view[3]);
+  }
+}
+
+class _Float32x4 implements Float32x4 {
+  factory _Float32x4(double x, double y, double z, double w)
+      native "Float32x4_fromDoubles";
+  factory _Float32x4.zero() native "Float32x4_zero";
+  Float32x4 operator +(Float32x4 other) {
+    return _add(other);
+  }
+  Float32x4 _add(Float32x4 other) native "Float32x4_add";
+  Float32x4 operator -() {
+    return _negate();
+  }
+  Float32x4 _negate() native "Float32x4_negate";
+  Float32x4 operator -(Float32x4 other) {
+    return _sub(other);
+  }
+  Float32x4 _sub(Float32x4 other) native "Float32x4_sub";
+  Float32x4 operator *(Float32x4 other) {
+    return _mul(other);
+  }
+  Float32x4 _mul(Float32x4 other) native "Float32x4_mul";
+  Float32x4 operator /(Float32x4 other) {
+    return _div(other);
+  }
+  Float32x4 _div(Float32x4 other) native "Float32x4_div";
+  Uint32x4 lessThan(Float32x4 other) {
+    return _cmplt(other);
+  }
+  Uint32x4 _cmplt(Float32x4 other) native "Float32x4_cmplt";
+  Uint32x4 lessThanOrEqual(Float32x4 other) {
+    return _cmplte(other);
+  }
+  Uint32x4 _cmplte(Float32x4 other) native "Float32x4_cmplte";
+  Uint32x4 greaterThan(Float32x4 other) {
+    return _cmpgt(other);
+  }
+  Uint32x4 _cmpgt(Float32x4 other) native "Float32x4_cmpgt";
+  Uint32x4 greaterThanOrEqual(Float32x4 other) {
+    return _cmpgte(other);
+  }
+  Uint32x4 _cmpgte(Float32x4 other) native "Float32x4_cmpgte";
+  Uint32x4 equal(Float32x4 other) {
+    return _cmpequal(other);
+  }
+  Uint32x4 _cmpequal(Float32x4 other)
+      native "Float32x4_cmpequal";
+  Uint32x4 notEqual(Float32x4 other) {
+    return _cmpnequal(other);
+  }
+  Uint32x4 _cmpnequal(Float32x4 other)
+      native "Float32x4_cmpnequal";
+  Float32x4 scale(double s) {
+    return _scale(s);
+  }
+  Float32x4 _scale(double s) native "Float32x4_scale";
+  Float32x4 abs() {
+    return _abs();
+  }
+  Float32x4 _abs() native "Float32x4_abs";
+  Float32x4 clamp(Float32x4 lowerLimit,
+                         Float32x4 upperLimit) {
+    return _clamp(lowerLimit, upperLimit);
+  }
+  Float32x4 _clamp(Float32x4 lowerLimit,
+                          Float32x4 upperLimit)
+      native "Float32x4_clamp";
+  double get x native "Float32x4_getX";
+  double get y native "Float32x4_getY";
+  double get z native "Float32x4_getZ";
+  double get w native "Float32x4_getW";
+  Float32x4 get xxxx native "Float32x4_getXXXX";
+  Float32x4 get yyyy native "Float32x4_getYYYY";
+  Float32x4 get zzzz native "Float32x4_getZZZZ";
+  Float32x4 get wwww native "Float32x4_getWWWW";
+  Float32x4 withX(double x) native "Float32x4_setX";
+  Float32x4 withY(double y) native "Float32x4_setY";
+  Float32x4 withZ(double z) native "Float32x4_setZ";
+  Float32x4 withW(double w) native "Float32x4_setW";
+  Float32x4 min(Float32x4 other) {
+    return _min(other);
+  }
+  Float32x4 _min(Float32x4 other) native "Float32x4_min";
+  Float32x4 max(Float32x4 other) {
+    return _max(other);
+  }
+  Float32x4 _max(Float32x4 other) native "Float32x4_max";
+  Float32x4 sqrt() {
+    return _sqrt();
+  }
+  Float32x4 _sqrt() native "Float32x4_sqrt";
+  Float32x4 reciprocal() {
+    return _reciprocal();
+  }
+  Float32x4 _reciprocal() native "Float32x4_reciprocal";
+  Float32x4 reciprocalSqrt() {
+    return _reciprocalSqrt();
+  }
+  Float32x4 _reciprocalSqrt() native "Float32x4_reciprocalSqrt";
+  Uint32x4 toUint32x4() {
+      return _toUint32x4();
+  }
+  Uint32x4 _toUint32x4() native "Float32x4_toUint32x4";
+}
+
+class _Uint32x4 implements Uint32x4 {
+  factory _Uint32x4(int x, int y, int z, int w)
+      native "Uint32x4_fromInts";
+  factory _Uint32x4.bool(bool x, bool y, bool z, bool w)
+      native "Uint32x4_fromBools";
+  Uint32x4 operator |(Uint32x4 other) {
+    return _or(other);
+  }
+  Uint32x4 _or(Uint32x4 other) native "Uint32x4_or";
+  Uint32x4 operator &(Uint32x4 other) {
+    return _and(other);
+  }
+  Uint32x4 _and(Uint32x4 other) native "Uint32x4_and";
+  Uint32x4 operator ^(Uint32x4 other) {
+    return _xor(other);
+  }
+  Uint32x4 _xor(Uint32x4 other) native "Uint32x4_xor";
+  int get x native "Uint32x4_getX";
+  int get y native "Uint32x4_getY";
+  int get z native "Uint32x4_getZ";
+  int get w native "Uint32x4_getW";
+  Uint32x4 withX(int x) native "Uint32x4_setX";
+  Uint32x4 withY(int y) native "Uint32x4_setY";
+  Uint32x4 withZ(int z) native "Uint32x4_setZ";
+  Uint32x4 withW(int w) native "Uint32x4_setW";
+  bool get flagX native "Uint32x4_getFlagX";
+  bool get flagY native "Uint32x4_getFlagY";
+  bool get flagZ native "Uint32x4_getFlagZ";
+  bool get flagW native "Uint32x4_getFlagW";
+  Uint32x4 withFlagX(bool x) native "Uint32x4_setFlagX";
+  Uint32x4 withFlagY(bool y) native "Uint32x4_setFlagY";
+  Uint32x4 withFlagZ(bool z) native "Uint32x4_setFlagZ";
+  Uint32x4 withFlagW(bool w) native "Uint32x4_setFlagW";
+  Float32x4 select(Float32x4 trueValue,
+                          Float32x4 falseValue) {
+    return _select(trueValue, falseValue);
+  }
+  Float32x4 _select(Float32x4 trueValue,
+                           Float32x4 falseValue)
+      native "Uint32x4_select";
+  Float32x4 toFloat32x4() {
+      return _toFloat32x4();
+  }
+  Float32x4 _toFloat32x4() native "Uint32x4_toFloat32x4";
+}
+
+
+class _Float32x4Array extends _ByteArrayBase
+    implements Float32x4List {
+  factory _Float32x4Array(int length) {
+    return _new(length);
+  }
+  factory _Float32x4Array.view(ByteArray array,
+                                    [int start = 0, int length]) {
+    if (length == null) {
+      length = (array.lengthInBytes() - start) ~/ _BYTES_PER_ELEMENT;
+    }
+    return new _Float32x4ArrayView(array, start, length);
+  }
+  Float32x4 operator [](int index) {
+    return _getIndexed(index);
+  }
+  int operator []=(int index, Float32x4 value) {
+    _setIndexed(index, value);
+  }
+  Iterator<Float32x4> get iterator {
+    return new _ByteArrayIterator<Float32x4>(this);
+  }
+  List<Float32x4> getRange(int start, int length) {
+    _rangeCheck(this.length, start, length);
+    List<Float32x4> result = _new(length);
+    result.setRange(0, length, this, start);
+    return result;
+  }
+  void setRange(int start, int length, List<Float32x4> from,
+                [int startFrom = 0]) {
+    if (from is _Float32x4Array) {
+      _setRange(start * _BYTES_PER_ELEMENT,
+                length * _BYTES_PER_ELEMENT,
+                from,
+                startFrom * _BYTES_PER_ELEMENT);
+    } else {
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
+    }
+  }
+  String toString() {
+    return Collections.collectionToString(this);
+  }
+  int bytesPerElement() {
+    return _BYTES_PER_ELEMENT;
+  }
+  int lengthInBytes() {
+    return _length() * _BYTES_PER_ELEMENT;
+  }
+  static const int _BYTES_PER_ELEMENT = 16;
+  static _Float32x4Array _new(int length)
+      native "Float32x4Array_new";
+  Float32x4 _getIndexed(int index)
+      native "Float32x4Array_getIndexed";
+  int _setIndexed(int index, Float32x4 value)
+      native "Float32x4Array_setIndexed";
+}
+
+
+class _Float32x4ArrayView extends _ByteArrayViewBase
+    implements Float32x4List {
+  _Float32x4ArrayView(ByteArray array,
+                           [int offsetInBytes = 0, int _length])
+    : super(array, _requireInteger(offsetInBytes),
+      _requireIntegerOrNull(
+        _length,
+        ((array.lengthInBytes() - offsetInBytes) ~/ _BYTES_PER_ELEMENT))) {
+    _rangeCheck(array.lengthInBytes(), _offset, length * _BYTES_PER_ELEMENT);
+  }
+
+  Float32x4 operator [](int index) {
+    if (index < 0 || index >= length) {
+      String message = "$index must be in the range [0..$length)";
+      throw new RangeError(message);
+    }
+    return _array.getFloat32x4(_offset + (index * _BYTES_PER_ELEMENT));
+  }
+
+  void operator []=(int index, Float32x4 value) {
+    if (index < 0 || index >= length) {
+      String message = "$index must be in the range [0..$length)";
+      throw new RangeError(message);
+    }
+    _array.setFloat32x4(_offset + (index * _BYTES_PER_ELEMENT), value);
+  }
+
+  Iterator<Float32x4> get iterator {
+    return new _ByteArrayIterator<Float32x4>(this);
+  }
+
+  List<Float32x4> getRange(int start, int length) {
+    _rangeCheck(this.length, start, length);
+    List<Float32x4> result = new Float32List(length);
+    result.setRange(0, length, this, start);
+    return result;
+  }
+
+  void setRange(int start, int length, List<Float32x4> from,
+               [int startFrom = 0]) {
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
+  }
+
+  String toString() {
+    return Collections.collectionToString(this);
+  }
+
+  int bytesPerElement() {
+    return _BYTES_PER_ELEMENT;
+  }
+
+  int lengthInBytes() {
+    return length * _BYTES_PER_ELEMENT;
+  }
+
+  ByteArray asByteArray([int start = 0, int length]) {
+    if (length == null) {
+      length = this.lengthInBytes();
+    }
+    _rangeCheck(this.length, start, length);
+    return _array.subByteArray(_offset + start, length);
+  }
+
+  static const int _BYTES_PER_ELEMENT = 16;
+}
+
+
+class _ExternalFloat32x4Array extends _ByteArrayBase
+  implements Float32x4List {
+  Float32x4 operator [](int index) {
+    return _getIndexed(index);
+  }
+
+  int operator []=(int index, Float32x4 value) {
+    _setIndexed(index, value);
+  }
+
+  Iterator<Float32x4> get iterator {
+    return new _ByteArrayIterator<Float32x4>(this);
+  }
+
+  List<Float32x4> getRange(int start, int length) {
+    _rangeCheck(this.length, start, length);
+    List<Float32x4> result = new Float32x4List(length);
+    result.setRange(0, length, this, start);
+    return result;
+  }
+
+  void setRange(int start, int length, List<Float32x4> from,
+                [int startFrom = 0]) {
+    if (from is _ExternalFloat32x4Array) {
+      _setRange(start * _BYTES_PER_ELEMENT,
+                length * _BYTES_PER_ELEMENT,
+                from,
+                startFrom * _BYTES_PER_ELEMENT);
+    } else {
+      IterableMixinWorkaround.setRangeList(
+          this, start, length, from, startFrom);
+    }
+  }
+
+  String toString() {
+    return Collections.collectionToString(this);
+  }
+
+  int bytesPerElement() {
+    return _BYTES_PER_ELEMENT;
+  }
+
+  int lengthInBytes() {
+    return _length() * _BYTES_PER_ELEMENT;
+  }
+
+  static const int _BYTES_PER_ELEMENT = 16;
+
+  Float32x4 _getIndexed(int index)
+      native "ExternalFloat32x4Array_getIndexed";
+  int _setIndexed(int index, Float32x4 value)
+      native "ExternalFloat32x4Array_setIndexed";
+}
diff --git a/runtime/lib/stacktrace.cc b/runtime/lib/stacktrace.cc
new file mode 100644
index 0000000..085d9dc
--- /dev/null
+++ b/runtime/lib/stacktrace.cc
@@ -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.
+
+#include "lib/error.h"
+
+#include "vm/bootstrap_natives.h"
+#include "vm/exceptions.h"
+#include "vm/object_store.h"
+#include "vm/runtime_entry.h"
+#include "vm/stack_frame.h"
+
+namespace dart {
+
+// Get a full stack trace.
+// Arg0: stack trace object.
+// Return value: String that represents the full stack trace.
+DEFINE_NATIVE_ENTRY(Stacktrace_getFullStacktrace, 1) {
+  const Stacktrace& trace =
+      Stacktrace::CheckedHandle(arguments->NativeArgAt(0));
+  return trace.FullStacktrace();
+}
+
+
+// Get a concise and pertinent stack trace.
+// Arg0: stack trace object.
+// Return value: String that represents the concise and pertinent stack trace.
+DEFINE_NATIVE_ENTRY(Stacktrace_getStacktrace, 1) {
+  const Stacktrace& trace =
+      Stacktrace::CheckedHandle(arguments->NativeArgAt(0));
+  return String::New(trace.ToCStringInternal(0));
+}
+
+
+// Setup a full stack trace.
+// Arg0: stack trace object.
+// Return value: None.
+DEFINE_NATIVE_ENTRY(Stacktrace_setupFullStacktrace, 1) {
+  const Stacktrace& trace =
+      Stacktrace::CheckedHandle(arguments->NativeArgAt(0));
+  const GrowableObjectArray& func_list =
+      GrowableObjectArray::Handle(GrowableObjectArray::New());
+  const GrowableObjectArray& code_list =
+      GrowableObjectArray::Handle(GrowableObjectArray::New());
+  const GrowableObjectArray& pc_offset_list =
+      GrowableObjectArray::Handle(GrowableObjectArray::New());
+  StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
+  StackFrame* frame = frames.NextFrame();
+  ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
+  Function& func = Function::Handle();
+  Code& code = Code::Handle();
+  Smi& offset = Smi::Handle();
+  bool catch_frame_skipped = false;  // Tracks if catch frame has been skipped.
+  while (!frame->IsEntryFrame()) {
+    if (frame->IsDartFrame()) {
+      code = frame->LookupDartCode();
+      if (code.is_optimized()) {
+        // For optimized frames, extract all the inlined functions if any
+        // into the stack trace.
+        for (InlinedFunctionsIterator it(frame); !it.Done(); it.Advance()) {
+          func = it.function();
+          code = it.code();
+          uword pc = it.pc();
+          ASSERT(pc != 0);
+          ASSERT(code.EntryPoint() <= pc);
+          ASSERT(pc < (code.EntryPoint() + code.Size()));
+          if (func.is_visible()) {
+            if (!catch_frame_skipped) {
+              catch_frame_skipped = true;
+            } else {
+              offset = Smi::New(pc - code.EntryPoint());
+              func_list.Add(func);
+              code_list.Add(code);
+              pc_offset_list.Add(offset);
+            }
+          }
+        }
+      } else {
+        offset = Smi::New(frame->pc() - code.EntryPoint());
+        func = code.function();
+        if (func.is_visible()) {
+          if (!catch_frame_skipped) {
+            catch_frame_skipped = true;
+          } else {
+            func_list.Add(func);
+            code_list.Add(code);
+            pc_offset_list.Add(offset);
+          }
+        }
+      }
+    }
+    frame = frames.NextFrame();
+    ASSERT(frame != NULL);
+  }
+  const Array& func_array = Array::Handle(Array::MakeArray(func_list));
+  const Array& code_array = Array::Handle(Array::MakeArray(code_list));
+  const Array& pc_offset_array =
+      Array::Handle(Array::MakeArray(pc_offset_list));
+  trace.SetCatchStacktrace(func_array, code_array, pc_offset_array);
+  return Object::null();
+}
+
+}  // namespace dart
diff --git a/runtime/lib/stacktrace_patch.dart b/runtime/lib/stacktrace_patch.dart
new file mode 100644
index 0000000..2d5fdc5
--- /dev/null
+++ b/runtime/lib/stacktrace_patch.dart
@@ -0,0 +1,13 @@
+// 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.
+
+patch class StackTrace {
+  /* patch */ String get fullStackTrace native "Stacktrace_getFullStacktrace";
+
+  /* patch */ String get stackTrace native "Stacktrace_getStacktrace";
+
+  /* patch */ void _setupFullStackTrace()
+      native "Stacktrace_setupFullStacktrace";
+}
+
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index d17b9134..3b5b633 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -149,13 +149,13 @@
   return Symbols::FromCharCode(value);
 }
 
-DEFINE_NATIVE_ENTRY(String_charCodeAt, 2) {
+DEFINE_NATIVE_ENTRY(String_codeUnitAt, 2) {
   const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
 
   int32_t value = StringValueAt(receiver, index);
   ASSERT(value >= 0);
-  ASSERT(value <= 0x10FFFF);
+  ASSERT(value <= 0xFFFF);
   return Smi::New(value);
 }
 
diff --git a/runtime/lib/string_base.dart b/runtime/lib/string_base.dart
index 8b28aae..8ed74b6 100644
--- a/runtime/lib/string_base.dart
+++ b/runtime/lib/string_base.dart
@@ -38,11 +38,7 @@
 
   String operator [](int index) native "String_charAt";
 
-  int charCodeAt(int index) native "String_charCodeAt";
-
-  int codeUnitAt(int index) {
-    return charCodeAt(index);
-  }
+  int codeUnitAt(int index) native "String_codeUnitAt";
 
   int get length native "String_getLength";
 
@@ -73,8 +69,8 @@
     int otherLength = other.length;
     int len = (thisLength < otherLength) ? thisLength : otherLength;
     for (int i = 0; i < len; i++) {
-      int thisCodePoint = this.charCodeAt(i);
-      int otherCodePoint = other.charCodeAt(i);
+      int thisCodePoint = this.codeUnitAt(i);
+      int otherCodePoint = other.codeUnitAt(i);
       if (thisCodePoint < otherCodePoint) {
         return -1;
       }
@@ -97,7 +93,7 @@
       return false;
     }
     for (int i = 0; i < len; i++) {
-      if (this.charCodeAt(i + start) != other.charCodeAt(i)) {
+      if (this.codeUnitAt(i + start) != other.codeUnitAt(i)) {
         return false;
       }
     }
@@ -216,7 +212,7 @@
     final int len = this.length;
     int first = 0;
     for (; first < len; first++) {
-      if (!_isWhitespace(this.charCodeAt(first))) {
+      if (!_isWhitespace(this.codeUnitAt(first))) {
         break;
       }
     }
@@ -226,7 +222,7 @@
     }
     int last = len - 1;
     for (; last >= first; last--) {
-      if (!_isWhitespace(this.charCodeAt(last))) {
+      if (!_isWhitespace(this.codeUnitAt(last))) {
         break;
       }
     }
@@ -300,10 +296,10 @@
     while (i < length) {
       buffer.add(onMatch(new _StringMatch(i, this, "")));
       // Special case to avoid splitting a surrogate pair.
-      int code = this.charCodeAt(i);
+      int code = this.codeUnitAt(i);
       if ((code & ~0x3FF) == 0xD800 && length > i + 1) {
         // Leading surrogate;
-        code = this.charCodeAt(i + 1);
+        code = this.codeUnitAt(i + 1);
         if ((code & ~0x3FF) == 0xDC00) {
           // Matching trailing surrogate.
           buffer.add(onNonMatch(this.substring(i, i + 2)));
@@ -351,7 +347,7 @@
    */
   static String _interpolate(List values) {
     int numValues = values.length;
-    var stringList = new List.fixedLength(numValues);
+    var stringList = new List(numValues);
     for (int i = 0; i < numValues; i++) {
       stringList[i] = values[i].toString();
     }
@@ -383,7 +379,11 @@
 
   List<String> split(Pattern pattern) {
     if ((pattern is String) && pattern.isEmpty) {
-      return splitChars();
+      List<String> result = new List<String>(length);
+      for (int i = 0; i < length; i++) {
+        result[i] = this[i];
+      }
+      return result;
     }
     int length = this.length;
     Iterator iterator = pattern.allMatches(this).iterator;
@@ -415,25 +415,7 @@
     return result;
   }
 
-  List<String> splitChars() {
-    int len = this.length;
-    final result = new List<String>.fixedLength(len);
-    for (int i = 0; i < len; i++) {
-      result[i] = this[i];
-    }
-    return result;
-  }
-
-  List<int> get charCodes {
-    int len = this.length;
-    final result = new List<int>.fixedLength(len);
-    for (int i = 0; i < len; i++) {
-      result[i] = this.charCodeAt(i);
-    }
-    return result;
-  }
-
-  Iterable<int> get codeUnits => new CodeUnits(this);
+  List<int> get codeUnits => new CodeUnits(this);
 
   Runes get runes => new Runes(this);
 
@@ -490,6 +472,8 @@
         "_OneByteString can only be allocated by the VM");
   }
 
+  int get hashCode native "String_getHashCode";
+
   // Checks for one-byte whitespaces only.
   // TODO(srdjan): Investigate if 0x85 (NEL) and 0xA0 (NBSP) are valid
   // whitespaces for one byte strings.
@@ -507,7 +491,7 @@
 
   List<String> split(Pattern pattern) {
     if ((pattern is _OneByteString) && (pattern.length == 1)) {
-      return _splitWithCharCode(pattern.charCodeAt(0));
+      return _splitWithCharCode(pattern.codeUnitAt(0));
     }
     return super.split(pattern);
   }
diff --git a/runtime/lib/timer_patch.dart b/runtime/lib/timer_patch.dart
index 1024915..fd3efbd 100644
--- a/runtime/lib/timer_patch.dart
+++ b/runtime/lib/timer_patch.dart
@@ -2,39 +2,22 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-typedef void _TimerCallback0();
-typedef void _TimerCallback1(Timer timer);
-
 patch class Timer {
-  /* patch */ factory Timer(var duration, Function callback) {
-    // TODO(floitsch): remove these checks when we remove the deprecated
-    // millisecond argument and the 1-argument callback. Also remove
-    // the int-test below.
-    if (callback is! _TimerCallback0 && callback is! _TimerCallback1) {
-      throw new ArgumentError(callback);
-    }
-    int milliseconds = duration is int ? duration : duration.inMilliseconds;
-    if (milliseconds < 0) milliseconds = 0;
-    _TimerCallback1 oneArgumentCallback =
-        callback is _TimerCallback1 ? callback : (_) { callback(); };
+  /* patch */ factory Timer(Duration duration, void callback()) {
     if (_TimerFactory._factory == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
-    return _TimerFactory._factory(milliseconds, oneArgumentCallback, false);
+    int milliseconds = duration.inMilliseconds;
+    if (milliseconds < 0) milliseconds = 0;
+    return _TimerFactory._factory(milliseconds, (_) { callback(); }, false);
   }
 
-  /**
-   * Creates a new repeating timer. The [callback] is invoked every
-   * [milliseconds] millisecond until cancelled.
-   */
-  /* patch */ factory Timer.repeating(var duration,
+  /* patch */ factory Timer.repeating(Duration duration,
                                       void callback(Timer timer)) {
     if (_TimerFactory._factory == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
-    // TODO(floitsch): remove this check when we remove the deprecated
-    // millisecond argument.
-    int milliseconds = duration is int ? duration : duration.inMilliseconds;
+    int milliseconds = duration.inMilliseconds;
     if (milliseconds < 0) milliseconds = 0;
     return _TimerFactory._factory(milliseconds, callback, true);
   }
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 4c5d053..f06f04c 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -124,6 +124,19 @@
 #error Architecture was not detected as supported by Dart.
 #endif
 
+// DART_FORCE_INLINE strongly hints to the compiler that a function should
+// be inlined. Your function is not guaranteed to be inlined but this is
+// stronger than just using "inline".
+// See: http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx for an
+// explanation of some the cases when a function can never be inlined.
+#ifdef _MSC_VER
+#define DART_FORCE_INLINE __forceinline
+#elif __GNUC__
+#define DART_FORCE_INLINE inline __attribute__((always_inline))
+#else
+#error Automatic compiler detection failed.
+#endif
+
 #if !defined(TARGET_ARCH_MIPS)
 #if !defined(TARGET_ARCH_ARM)
 #if !defined(TARGET_ARCH_X64)
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index 26bc3dd..94eaa3f 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -286,26 +286,26 @@
   // Test function type mirrors.
   var func_cls_mirror = typedef_mirror.referent;
   Expect.isTrue(func_cls_mirror is FunctionTypeMirror);
-  Expect.equals('void (dart:core.String)', func_cls_mirror.simpleName);
+  Expect.equals('void (dart.core.String)', func_cls_mirror.simpleName);
   Expect.equals('void', func_cls_mirror.returnType.simpleName);
 }
 
 void testLibrariesMap(Map libraries) {
   // Just look for a couple of well-known libs.
-  LibraryMirror core_lib = libraries['dart:core'];
+  LibraryMirror core_lib = libraries['dart.core'];
   Expect.isTrue(core_lib is LibraryMirror);
 
-  LibraryMirror mirror_lib = libraries['dart:mirrors'];
+  LibraryMirror mirror_lib = libraries['dart.mirrors'];
   Expect.isTrue(mirror_lib is LibraryMirror);
 
   // Lookup an interface from a library and make sure it is sane.
   ClassMirror list_intf = core_lib.members['List'];
   Expect.isTrue(list_intf is ClassMirror);
   Expect.equals('List', list_intf.simpleName);
-  Expect.equals('dart:core.List', list_intf.qualifiedName);
+  Expect.equals('dart.core.List', list_intf.qualifiedName);
   Expect.isFalse(list_intf.isPrivate);
   Expect.equals('Object', list_intf.superclass.simpleName);
-  Expect.equals('dart:core', list_intf.owner.simpleName);
+  Expect.equals('dart.core', list_intf.owner.simpleName);
   Expect.isTrue(list_intf.isClass);
   Expect.equals('Collection', list_intf.superinterfaces[0].simpleName);
   Expect.equals("ClassMirror on 'List'", list_intf.toString());
@@ -314,11 +314,11 @@
   ClassMirror oom_cls = core_lib.members['OutOfMemoryError'];
   Expect.isTrue(oom_cls is ClassMirror);
   Expect.equals('OutOfMemoryError', oom_cls.simpleName);
-  Expect.equals('dart:core.OutOfMemoryError', oom_cls.qualifiedName);
+  Expect.equals('dart.core.OutOfMemoryError', oom_cls.qualifiedName);
   Expect.isFalse(oom_cls.isPrivate);
   Expect.equals('Object', oom_cls.superclass.simpleName);
   Expect.isTrue(oom_cls.defaultFactory == null);
-  Expect.equals('dart:core', oom_cls.owner.simpleName);
+  Expect.equals('dart.core', oom_cls.owner.simpleName);
   Expect.isTrue(oom_cls.isClass);
   Expect.equals('Error', oom_cls.superinterfaces[0].simpleName);
   Expect.equals("ClassMirror on 'OutOfMemoryError'",
diff --git a/runtime/tests/vm/dart/simd128float32_array_test.dart b/runtime/tests/vm/dart/simd128float32_array_test.dart
new file mode 100644
index 0000000..44f4591
--- /dev/null
+++ b/runtime/tests/vm/dart/simd128float32_array_test.dart
@@ -0,0 +1,66 @@
+// 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 tag to be able to run in html test framework.
+library simd128float32_array_test;
+
+import 'dart:scalarlist';
+
+testLoadStore(array) {
+  Expect.equals(8, array.length);
+  Expect.isTrue(array is List<Float32x4>);
+  array[0] = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  Expect.equals(1.0, array[0].x);
+  Expect.equals(2.0, array[0].y);
+  Expect.equals(3.0, array[0].z);
+  Expect.equals(4.0, array[0].w);
+  array[1] = array[0];
+  array[0] = array[0].withX(9.0);
+  Expect.equals(9.0, array[0].x);
+  Expect.equals(2.0, array[0].y);
+  Expect.equals(3.0, array[0].z);
+  Expect.equals(4.0, array[0].w);
+  Expect.equals(1.0, array[1].x);
+  Expect.equals(2.0, array[1].y);
+  Expect.equals(3.0, array[1].z);
+  Expect.equals(4.0, array[1].w);
+}
+
+testView(array) {
+  Expect.equals(8, array.length);
+  Expect.isTrue(array is List<Float32x4>);
+  Expect.equals(0.0, array[0].x);
+  Expect.equals(1.0, array[0].y);
+  Expect.equals(2.0, array[0].z);
+  Expect.equals(3.0, array[0].w);
+  Expect.equals(4.0, array[1].x);
+  Expect.equals(5.0, array[1].y);
+  Expect.equals(6.0, array[1].z);
+  Expect.equals(7.0, array[1].w);
+}
+
+main() {
+  var list;
+
+  list = new Float32x4List(8);
+  for (int i = 0; i < 3000; i++) {
+    testLoadStore(list);
+  }
+
+  list = new Float32x4List.transferable(8);
+  for (int i = 0; i < 3000; i++) {
+    testLoadStore(list);
+  }
+  Float32List floatList = new Float32List(32);
+  for (int i = 0; i < floatList.length; i++) {
+    floatList[i] = i.toDouble();
+  }
+  list = new Float32x4List.view(floatList.asByteArray());
+  for (int i = 0; i < 3000; i++) {
+    testView(list);
+  }
+  for (int i = 0; i < 3000; i++) {
+    testLoadStore(list);
+  }
+}
diff --git a/runtime/tests/vm/dart/simd128float32_test.dart b/runtime/tests/vm/dart/simd128float32_test.dart
new file mode 100644
index 0000000..cac2b63
--- /dev/null
+++ b/runtime/tests/vm/dart/simd128float32_test.dart
@@ -0,0 +1,375 @@
+// 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 tag to be able to run in html test framework.
+library simd128_float32_test;
+
+import 'dart:scalarlist';
+
+testAdd() {
+  var m = new Float32x4(-1.0, -2.0, -3.0, -4.0);
+  var n = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var o = m + n;
+  Expect.equals(0.0, o.x);
+  Expect.equals(0.0, o.y);
+  Expect.equals(0.0, o.z);
+  Expect.equals(0.0, o.w);
+}
+
+testNegate() {
+  var m = new Float32x4(1.0, 2.0, -3.0, -4.0);
+  m = -m;
+  Expect.equals(-1.0, m.x);
+  Expect.equals(-2.0, m.y);
+  Expect.equals(3.0, m.z);
+  Expect.equals(4.0, m.w);
+}
+
+testSub() {
+  var m = new Float32x4(-1.0, -2.0, -3.0, -4.0);
+  var n = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var o = m - n;
+  Expect.equals(-2.0, o.x);
+  Expect.equals(-4.0, o.y);
+  Expect.equals(-6.0, o.z);
+  Expect.equals(-8.0, o.w);
+}
+
+testMul() {
+  var m = new Float32x4(-1.0, -2.0, -3.0, -4.0);
+  var n = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var o = m * n;
+  Expect.equals(-1.0, o.x);
+  Expect.equals(-4.0, o.y);
+  Expect.equals(-9.0, o.z);
+  Expect.equals(-16.0, o.w);
+}
+
+testDiv() {
+  var m = new Float32x4(-1.0, -2.0, -3.0, -4.0);
+  var n = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var o = m / n;
+  Expect.equals(-1.0, o.x);
+  Expect.equals(-1.0, o.y);
+  Expect.equals(-1.0, o.z);
+  Expect.equals(-1.0, o.w);
+}
+
+testComparison() {
+  var m = new Float32x4(1.0, 2.0, 0.1, 0.001);
+  var n = new Float32x4(2.0, 2.0, 0.001, 0.1);
+  var cmp;
+  cmp = m.lessThan(n);
+  Expect.equals(0xFFFFFFFF, cmp.x);
+  Expect.equals(0x0, cmp.y);
+  Expect.equals(0x0, cmp.z);
+  Expect.equals(0xFFFFFFFF, cmp.w);
+
+  cmp = m.lessThanOrEqual(n);
+  Expect.equals(0xFFFFFFFF, cmp.x);
+  Expect.equals(0xFFFFFFFF, cmp.y);
+  Expect.equals(0x0, cmp.z);
+  Expect.equals(0xFFFFFFFF, cmp.w);
+
+  cmp = m.equal(n);
+  Expect.equals(0x0, cmp.x);
+  Expect.equals(0xFFFFFFFF, cmp.y);
+  Expect.equals(0x0, cmp.z);
+  Expect.equals(0x0, cmp.w);
+
+  cmp = m.notEqual(n);
+  Expect.equals(0xFFFFFFFF, cmp.x);
+  Expect.equals(0x0, cmp.y);
+  Expect.equals(0xFFFFFFFF, cmp.z);
+  Expect.equals(0xFFFFFFFF, cmp.w);
+
+  cmp = m.greaterThanOrEqual(n);
+  Expect.equals(0x0, cmp.x);
+  Expect.equals(0xFFFFFFFF, cmp.y);
+  Expect.equals(0xFFFFFFFF, cmp.z);
+  Expect.equals(0x0, cmp.w);
+
+  cmp = m.greaterThan(n);
+  Expect.equals(0x0, cmp.x);
+  Expect.equals(0x0, cmp.y);
+  Expect.equals(0xFFFFFFFF, cmp.z);
+  Expect.equals(0x0, cmp.w);
+}
+
+testAbs() {
+  var m = new Float32x4(1.0, -2.0, 3.0, -4.0);
+  m = m.abs();
+  Expect.equals(1.0, m.x);
+  Expect.equals(2.0, m.y);
+  Expect.equals(3.0, m.z);
+  Expect.equals(4.0, m.w);
+}
+
+testScale() {
+  var m = new Float32x4(1.0, -2.0, 3.0, -4.0);
+  m = m.scale(20.0);
+  Expect.equals(20.0, m.x);
+  Expect.equals(-40.0, m.y);
+  Expect.equals(60.0, m.z);
+  Expect.equals(-80.0, m.w);
+}
+
+testClamp() {
+  var m = new Float32x4(1.0, -2.0, 3.0, -4.0);
+  var lo = new Float32x4(0.0, 0.0, 0.0, 0.0);
+  var hi = new Float32x4(2.0, 2.0, 2.0, 2.0);
+  m = m.clamp(lo, hi);
+  Expect.equals(1.0, m.x);
+  Expect.equals(0.0, m.y);
+  Expect.equals(2.0, m.z);
+  Expect.equals(0.0, m.w);
+}
+
+testShuffle() {
+  var m = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var xxxx = m.xxxx;
+  Expect.equals(1.0, xxxx.x);
+  Expect.equals(1.0, xxxx.y);
+  Expect.equals(1.0, xxxx.z);
+  Expect.equals(1.0, xxxx.w);
+  var yyyy = m.yyyy;
+  Expect.equals(2.0, yyyy.x);
+  Expect.equals(2.0, yyyy.y);
+  Expect.equals(2.0, yyyy.z);
+  Expect.equals(2.0, yyyy.w);
+  var zzzz = m.zzzz;
+  Expect.equals(3.0, zzzz.x);
+  Expect.equals(3.0, zzzz.y);
+  Expect.equals(3.0, zzzz.z);
+  Expect.equals(3.0, zzzz.w);
+  var wwww = m.wwww;
+  Expect.equals(4.0, wwww.x);
+  Expect.equals(4.0, wwww.y);
+  Expect.equals(4.0, wwww.z);
+  Expect.equals(4.0, wwww.w);
+}
+
+testMin() {
+  var m = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var n = new Float32x4(1.0, 0.0, 2.5, 5.0);
+  m = m.min(n);
+  Expect.equals(1.0, m.x);
+  Expect.equals(0.0, m.y);
+  Expect.equals(2.5, m.z);
+  Expect.equals(4.0, m.w);
+}
+
+testMax() {
+  var m = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var n = new Float32x4(1.0, 0.0, 2.5, 5.0);
+  m = m.max(n);
+  Expect.equals(1.0, m.x);
+  Expect.equals(2.0, m.y);
+  Expect.equals(3.0, m.z);
+  Expect.equals(5.0, m.w);
+}
+
+testSqrt() {
+  var m = new Float32x4(1.0, 4.0, 9.0, 16.0);
+  m = m.sqrt();
+  Expect.equals(1.0, m.x);
+  Expect.equals(2.0, m.y);
+  Expect.equals(3.0, m.z);
+  Expect.equals(4.0, m.w);
+}
+
+testReciprocal() {
+  var m = new Float32x4(1.0, 4.0, 9.0, 16.0);
+  m = m.reciprocal();
+  Expect.approxEquals(1.0, m.x);
+  Expect.approxEquals(0.25, m.y);
+  Expect.approxEquals(0.1111111, m.z);
+  Expect.approxEquals(0.0625, m.w);
+}
+
+testReciprocalSqrt() {
+  var m = new Float32x4(1.0, 0.25, 0.111111, 0.0625);
+  m = m.reciprocalSqrt();
+  Expect.approxEquals(1.0, m.x);
+  Expect.approxEquals(2.0, m.y);
+  Expect.approxEquals(3.0, m.z);
+  Expect.approxEquals(4.0, m.w);
+}
+
+testSelect() {
+  var m = new Uint32x4.bool(true, true, false, false);
+  var t = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  var f = new Float32x4(5.0, 6.0, 7.0, 8.0);
+  var s = m.select(t, f);
+  Expect.equals(1.0, s.x);
+  Expect.equals(2.0, s.y);
+  Expect.equals(7.0, s.z);
+  Expect.equals(8.0, s.w);
+}
+
+testConversions() {
+  var m = new Uint32x4(0x3F800000, 0x40000000, 0x40400000, 0x40800000);
+  var n = m.toFloat32x4();
+  Expect.equals(1.0, n.x);
+  Expect.equals(2.0, n.y);
+  Expect.equals(3.0, n.z);
+  Expect.equals(4.0, n.w);
+  n = new Float32x4(5.0, 6.0, 7.0, 8.0);
+  m = n.toUint32x4();
+  Expect.equals(0x40A00000, m.x);
+  Expect.equals(0x40C00000, m.y);
+  Expect.equals(0x40E00000, m.z);
+  Expect.equals(0x41000000, m.w);
+  // Flip sign using bit-wise operators.
+  n = new Float32x4(9.0, 10.0, 11.0, 12.0);
+  m = new Uint32x4(0x80000000, 0x80000000, 0x80000000, 0x80000000);
+  var nMask = n.toUint32x4();
+  nMask = nMask ^ m; // flip sign.
+  n = nMask.toFloat32x4();
+  Expect.equals(-9.0, n.x);
+  Expect.equals(-10.0, n.y);
+  Expect.equals(-11.0, n.z);
+  Expect.equals(-12.0, n.w);
+  nMask = n.toUint32x4();
+  nMask = nMask ^ m; // flip sign.
+  n = nMask.toFloat32x4();
+  Expect.equals(9.0, n.x);
+  Expect.equals(10.0, n.y);
+  Expect.equals(11.0, n.z);
+  Expect.equals(12.0, n.w);
+}
+
+
+testBitOperators() {
+  var m = new Uint32x4(0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA);
+  var n = new Uint32x4(0x55555555, 0x55555555, 0x55555555, 0x55555555);
+  Expect.equals(0xAAAAAAAA, m.x);
+  Expect.equals(0xAAAAAAAA, m.y);
+  Expect.equals(0xAAAAAAAA, m.z);
+  Expect.equals(0xAAAAAAAA, m.w);
+  Expect.equals(0x55555555, n.x);
+  Expect.equals(0x55555555, n.y);
+  Expect.equals(0x55555555, n.z);
+  Expect.equals(0x55555555, n.w);
+  Expect.equals(true, n.flagX);
+  Expect.equals(true, n.flagY);
+  Expect.equals(true, n.flagZ);
+  Expect.equals(true, n.flagW);
+  var o = m|n;  // or
+  Expect.equals(0xFFFFFFFF, o.x);
+  Expect.equals(0xFFFFFFFF, o.y);
+  Expect.equals(0xFFFFFFFF, o.z);
+  Expect.equals(0xFFFFFFFF, o.w);
+  Expect.equals(true, o.flagX);
+  Expect.equals(true, o.flagY);
+  Expect.equals(true, o.flagZ);
+  Expect.equals(true, o.flagW);
+  o = m&n;  // and
+  Expect.equals(0x0, o.x);
+  Expect.equals(0x0, o.y);
+  Expect.equals(0x0, o.z);
+  Expect.equals(0x0, o.w);
+  n = n.withX(0xAAAAAAAA);
+  n = n.withY(0xAAAAAAAA);
+  n = n.withZ(0xAAAAAAAA);
+  n = n.withW(0xAAAAAAAA);
+  Expect.equals(0xAAAAAAAA, n.x);
+  Expect.equals(0xAAAAAAAA, n.y);
+  Expect.equals(0xAAAAAAAA, n.z);
+  Expect.equals(0xAAAAAAAA, n.w);
+  o = m^n;  // xor
+  Expect.equals(0x0, o.x);
+  Expect.equals(0x0, o.y);
+  Expect.equals(0x0, o.z);
+  Expect.equals(0x0, o.w);
+  Expect.equals(false, o.flagX);
+  Expect.equals(false, o.flagY);
+  Expect.equals(false, o.flagZ);
+  Expect.equals(false, o.flagW);
+}
+
+testSetters() {
+  var f = new Float32x4.zero();
+  Expect.equals(0.0, f.x);
+  Expect.equals(0.0, f.y);
+  Expect.equals(0.0, f.z);
+  Expect.equals(0.0, f.w);
+  f = f.withX(4.0);
+  Expect.equals(4.0, f.x);
+  f = f.withY(3.0);
+  Expect.equals(3.0, f.y);
+  f = f.withZ(2.0);
+  Expect.equals(2.0, f.z);
+  f = f.withW(1.0);
+  Expect.equals(1.0, f.w);
+  f = new Float32x4.zero();
+  f = f.withX(4.0).withZ(2.0).withW(1.0).withY(3.0);
+  Expect.equals(4.0, f.x);
+  Expect.equals(3.0, f.y);
+  Expect.equals(2.0, f.z);
+  Expect.equals(1.0, f.w);
+  var m = new Uint32x4.bool(false, false, false, false);
+  Expect.equals(false, m.flagX);
+  Expect.equals(false, m.flagY);
+  Expect.equals(false, m.flagZ);
+  Expect.equals(false, m.flagW);
+  m = m.withFlagX(true);
+  Expect.equals(true, m.flagX);
+  Expect.equals(false, m.flagY);
+  Expect.equals(false, m.flagZ);
+  Expect.equals(false, m.flagW);
+  m = m.withFlagY(true);
+  Expect.equals(true, m.flagX);
+  Expect.equals(true, m.flagY);
+  Expect.equals(false, m.flagZ);
+  Expect.equals(false, m.flagW);
+  m = m.withFlagZ(true);
+  Expect.equals(true, m.flagX);
+  Expect.equals(true, m.flagY);
+  Expect.equals(true, m.flagZ);
+  Expect.equals(false, m.flagW);
+  m = m.withFlagW(true);
+  Expect.equals(true, m.flagX);
+  Expect.equals(true, m.flagY);
+  Expect.equals(true, m.flagZ);
+  Expect.equals(true, m.flagW);
+}
+
+testGetters() {
+  var f = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  Expect.equals(1.0, f.x);
+  Expect.equals(2.0, f.y);
+  Expect.equals(3.0, f.z);
+  Expect.equals(4.0, f.w);
+  var m = new Uint32x4.bool(false, true, true, false);
+  Expect.equals(false, m.flagX);
+  Expect.equals(true, m.flagY);
+  Expect.equals(true, m.flagZ);
+  Expect.equals(false, m.flagW);
+}
+
+main() {
+  for (int i = 0; i < 3000; i++) {
+    testGetters();
+    testSetters();
+    testBitOperators();
+    testConversions();
+    testSelect();
+    testShuffle();
+    testAdd();
+    testSub();
+    testNegate();
+    testMul();
+    testDiv();
+    testComparison();
+    testScale();
+    testClamp();
+    testAbs();
+    testMin();
+    testMax();
+    testSqrt();
+    testReciprocal();
+    testReciprocalSqrt();
+  }
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index c4537b6..86c53f32 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -13,6 +13,10 @@
 
 cc/SNPrint_BadArgs: Skip
 
+# These tests are skipped because of the workaround to open issue 8594.
+cc/Debug_StackTraceDump1: Skip
+cc/Debug_StackTraceDump2: Skip
+
 [ $arch == x64 ]
 cc/IsolateInterrupt: Skip
 
@@ -33,6 +37,8 @@
 dart/isolate_mirror*: Skip # compilers not aware of dart:mirrors
 dart/byte_array_test: Skip # compilers not aware of byte arrays
 dart/byte_array_optimized_test: Skip # compilers not aware of byte arrays
+dart/simd128float32_array_test: Skip # compilers not aware of Simd128
+dart/simd128float32_test: Skip # compilers not aware of Simd128
 dart/isolate_unhandled*: Skip
 
 [ $compiler == dart2js ]
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 2bd4737..3331a6f 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -7,6 +7,7 @@
 
 #include "vm/assembler.h"
 
+#include "vm/runtime_entry.h"
 #include "vm/stub_code.h"
 
 namespace dart {
@@ -23,6 +24,7 @@
   W   = 1 << 21,  // writeback base register (or leave unchanged)
   A   = 1 << 21,  // accumulate in multiply instruction (or not)
   B   = 1 << 22,  // unsigned byte (or word)
+  D   = 1 << 22,  // high/lo bit of start of s/d register range
   N   = 1 << 22,  // long (or short)
   U   = 1 << 23,  // positive (or negative) offset/index
   P   = 1 << 24,  // offset/pre-indexed addressing (or post-indexed addressing)
@@ -64,6 +66,7 @@
 
 
 uint32_t Address::encoding3() const {
+  ASSERT(kind_ == Immediate);
   const uint32_t offset_mask = (1 << 12) - 1;
   uint32_t offset = encoding_ & offset_mask;
   ASSERT(offset < 256);
@@ -72,6 +75,7 @@
 
 
 uint32_t Address::vencoding() const {
+  ASSERT(kind_ == Immediate);
   const uint32_t offset_mask = (1 << 12) - 1;
   uint32_t offset = encoding_ & offset_mask;
   ASSERT(offset < (1 << 10));  // In the range 0 to +1020.
@@ -140,7 +144,7 @@
   ASSERT(rd != kNoRegister);
   ASSERT(cond != kNoCondition);
   int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
-                     B26 |
+                     B26 | (ad.kind() == Address::Immediate ? 0 : B25) |
                      (load ? L : 0) |
                      (byte ? B : 0) |
                      (static_cast<int32_t>(rd) << kRdShift) |
@@ -702,6 +706,83 @@
   Emit(encoding);
 }
 
+void Assembler::EmitMultiVSMemOp(Condition cond,
+                                BlockAddressMode am,
+                                bool load,
+                                Register base,
+                                SRegister start,
+                                uint32_t count) {
+  ASSERT(base != kNoRegister);
+  ASSERT(cond != kNoCondition);
+  ASSERT(start != kNoSRegister);
+  ASSERT(static_cast<int32_t>(start) + count <= kNumberOfSRegisters);
+
+  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+                     B27 | B26 | B11 | B9 |
+                     am |
+                     (load ? L : 0) |
+                     (static_cast<int32_t>(base) << kRnShift) |
+                     ((static_cast<int32_t>(start) & 0x1) ? D : 0) |
+                     ((static_cast<int32_t>(start) >> 1) << 12) |
+                     count;
+  Emit(encoding);
+}
+
+
+void Assembler::EmitMultiVDMemOp(Condition cond,
+                                BlockAddressMode am,
+                                bool load,
+                                Register base,
+                                DRegister start,
+                                int32_t count) {
+  ASSERT(base != kNoRegister);
+  ASSERT(cond != kNoCondition);
+  ASSERT(start != kNoDRegister);
+  ASSERT(static_cast<int32_t>(start) + count <= kNumberOfDRegisters);
+
+  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+                     B27 | B26 | B11 | B9 | B8 |
+                     am |
+                     (load ? L : 0) |
+                     (static_cast<int32_t>(base) << kRnShift) |
+                     ((static_cast<int32_t>(start) & 0x10) ? D : 0) |
+                     ((static_cast<int32_t>(start) & 0xf) << 12) |
+                     (count << 1);
+  Emit(encoding);
+}
+
+
+void Assembler::vldms(BlockAddressMode am, Register base,
+                      SRegister first, SRegister last, Condition cond) {
+  ASSERT((am == IA) || (am == IA_W) || (am == DB_W));
+  ASSERT(last > first);
+  EmitMultiVSMemOp(cond, am, true, base, first, last - first + 1);
+}
+
+
+void Assembler::vstms(BlockAddressMode am, Register base,
+                      SRegister first, SRegister last, Condition cond) {
+  ASSERT((am == IA) || (am == IA_W) || (am == DB_W));
+  ASSERT(last > first);
+  EmitMultiVSMemOp(cond, am, false, base, first, last - first + 1);
+}
+
+
+void Assembler::vldmd(BlockAddressMode am, Register base,
+                      DRegister first, DRegister last, Condition cond) {
+  ASSERT((am == IA) || (am == IA_W) || (am == DB_W));
+  ASSERT(last > first);
+  EmitMultiVDMemOp(cond, am, true, base, first, last - first + 1);
+}
+
+
+void Assembler::vstmd(BlockAddressMode am, Register base,
+                      DRegister first, DRegister last, Condition cond) {
+  ASSERT((am == IA) || (am == IA_W) || (am == DB_W));
+  ASSERT(last > first);
+  EmitMultiVDMemOp(cond, am, false, base, first, last - first + 1);
+}
+
 
 void Assembler::EmitVFPsss(Condition cond, int32_t opcode,
                            SRegister sd, SRegister sn, SRegister sm) {
@@ -990,15 +1071,17 @@
 }
 
 
-void Assembler::svc(uint32_t imm24) {
+void Assembler::svc(uint32_t imm24, Condition cond) {
+  ASSERT(cond != kNoCondition);
   ASSERT(imm24 < (1 << 24));
-  int32_t encoding = (AL << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
+  int32_t encoding = (cond << kConditionShift) | B27 | B26 | B25 | B24 | imm24;
   Emit(encoding);
 }
 
 
-void Assembler::bkpt(uint16_t imm16) {
-  int32_t encoding = (AL << kConditionShift) | B24 | B21 |
+void Assembler::bkpt(uint16_t imm16, Condition cond) {
+  ASSERT(cond != kNoCondition);
+  int32_t encoding = (cond << kConditionShift) | B24 | B21 |
                      ((imm16 >> 4) << 8) | B6 | B5 | B4 | (imm16 & 0xf);
   Emit(encoding);
 }
@@ -1014,6 +1097,16 @@
 }
 
 
+void Assembler::bx(Register rm, Condition cond) {
+  ASSERT(rm != kNoRegister);
+  ASSERT(cond != kNoCondition);
+  int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+                     B24 | B21 | (0xfff << 8) | B4 |
+                     (static_cast<int32_t>(rm) << kRmShift);
+  Emit(encoding);
+}
+
+
 void Assembler::blx(Register rm, Condition cond) {
   ASSERT(rm != kNoRegister);
   ASSERT(cond != kNoCondition);
@@ -1033,9 +1126,23 @@
 }
 
 
+void Assembler::Drop(intptr_t stack_elements) {
+  ASSERT(stack_elements >= 0);
+  if (stack_elements > 0) {
+    AddImmediate(SP, SP, stack_elements * kWordSize);
+  }
+}
+
+
 void Assembler::LoadObject(Register rd, const Object& object) {
-  // TODO(regis): If the object is never relocated (null, true, false, ...),
-  // load as immediate.
+  if (object.IsNull() ||
+      object.IsSmi() ||
+      (object.raw() == Bool::True().raw()) ||
+      (object.raw() == Bool::False().raw())) {
+    // This object is never relocated; do not use object pool.
+    LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()));
+    return;
+  }
   const int32_t offset =
       Array::data_offset() + 4*AddObject(object) - kHeapObjectTag;
   if (Address::CanHoldLoadOffset(kLoadWord, offset)) {
@@ -1043,7 +1150,7 @@
   } else {
     int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
     uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
-    AddConstant(rd, PP, offset12_hi);
+    AddImmediate(rd, PP, offset12_hi);
     ldr(rd, Address(rd, offset12_lo));
   }
 }
@@ -1163,9 +1270,9 @@
 }
 
 
-void Assembler::Branch(const ExternalLabel* label) {
-  LoadImmediate(IP, label->address());  // Target address is never patched.
-  mov(PC, ShifterOperand(IP));
+void Assembler::Branch(const ExternalLabel* label, Condition cond) {
+  LoadImmediate(IP, label->address(), cond);  // Address is never patched.
+  mov(PC, ShifterOperand(IP), cond);
 }
 
 
@@ -1187,7 +1294,7 @@
   } else {
     int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
     uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
-    // Inline a simplified version of AddConstant(LR, CP, offset12_hi).
+    // Inline a simplified version of AddImmediate(LR, CP, offset12_hi).
     ShifterOperand shifter_op;
     if (ShifterOperand::CanHold(offset12_hi, &shifter_op)) {
       add(LR, PP, shifter_op);
@@ -1412,12 +1519,12 @@
 }
 
 
-void Assembler::AddConstant(Register rd, int32_t value, Condition cond) {
-  AddConstant(rd, rd, value, cond);
+void Assembler::AddImmediate(Register rd, int32_t value, Condition cond) {
+  AddImmediate(rd, rd, value, cond);
 }
 
 
-void Assembler::AddConstant(Register rd, Register rn, int32_t value,
+void Assembler::AddImmediate(Register rd, Register rn, int32_t value,
                             Condition cond) {
   if (value == 0) {
     if (rd != rn) {
@@ -1453,7 +1560,7 @@
 }
 
 
-void Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value,
+void Assembler::AddImmediateSetFlags(Register rd, Register rn, int32_t value,
                                     Condition cond) {
   ShifterOperand shifter_op;
   if (ShifterOperand::CanHold(value, &shifter_op)) {
@@ -1480,7 +1587,7 @@
 }
 
 
-void Assembler::AddConstantWithCarry(Register rd, Register rn, int32_t value,
+void Assembler::AddImmediateWithCarry(Register rd, Register rn, int32_t value,
                                      Condition cond) {
   ShifterOperand shifter_op;
   if (ShifterOperand::CanHold(value, &shifter_op)) {
@@ -1507,6 +1614,102 @@
 }
 
 
+void Assembler::CompareImmediate(Register rn, int32_t value, Condition cond) {
+  ShifterOperand shifter_op;
+  if (ShifterOperand::CanHold(value, &shifter_op)) {
+    cmp(rn, shifter_op, cond);
+  } else {
+    ASSERT(rn != IP);
+    LoadImmediate(IP, cond);
+    cmp(rn, ShifterOperand(IP), cond);
+  }
+}
+
+
+static int NumRegsBelowFP(RegList regs) {
+  int count = 0;
+  for (int i = 0; i < FP; i++) {
+    if ((regs & (1 << i)) != 0) {
+      count++;
+    }
+  }
+  return count;
+}
+
+
+void Assembler::EnterFrame(RegList regs, intptr_t frame_size) {
+  if (prologue_offset_ == -1) {
+    prologue_offset_ = CodeSize();
+  }
+  PushList(regs);
+  if ((regs & (1 << FP)) != 0) {
+    // Set FP to the saved previous FP.
+    add(FP, SP, ShifterOperand(4 * NumRegsBelowFP(regs)));
+  }
+  AddImmediate(SP, -frame_size);
+}
+
+
+void Assembler::LeaveFrame(RegList regs) {
+  ASSERT((regs & (1 << PC)) == 0);  // Must not pop PC.
+  if ((regs & (1 << FP)) != 0) {
+    // Use FP to set SP.
+    sub(SP, FP, ShifterOperand(4 * NumRegsBelowFP(regs)));
+  }
+  PopList(regs);
+}
+
+
+void Assembler::Ret() {
+  bx(LR);
+}
+
+
+void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
+  // Reserve space for arguments and align frame before entering
+  // the C++ world.
+  AddImmediate(SP, -frame_space);
+  if (OS::ActivationFrameAlignment() > 0) {
+    bic(SP, SP, ShifterOperand(OS::ActivationFrameAlignment() - 1));
+  }
+}
+
+
+void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) {
+  // Preserve volatile CPU registers.
+  EnterFrame(kDartVolatileCpuRegs | (1 << FP), 0);
+
+  // Preserve all volatile FPU registers.
+  // TODO(regis): Use vstmd instruction once supported.
+  // vstmd(DB_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg);
+
+  ReserveAlignedFrameSpace(frame_space);
+}
+
+
+void Assembler::LeaveCallRuntimeFrame() {
+  // SP might have been modified to reserve space for arguments
+  // and ensure proper alignment of the stack frame.
+  // We need to restore it before restoring registers.
+  const intptr_t kPushedRegistersSize =
+      kDartVolatileCpuRegCount * kWordSize;
+  // TODO(regis): + kDartVolatileFpuRegCount * 2 * kWordSize;
+  AddImmediate(SP, FP, -kPushedRegistersSize);
+
+  // Restore all volatile FPU registers.
+  // TODO(regis): Use vldmd instruction once supported.
+  // vldmd(IA_W, SP, kDartFirstVolatileFpuReg, kDartLastVolatileFpuReg);
+
+  // Restore volatile CPU registers.
+  LeaveFrame(kDartVolatileCpuRegs | (1 << FP));
+}
+
+
+void Assembler::CallRuntime(const RuntimeEntry& entry) {
+  entry.Call(this);
+}
+
+
 void Assembler::Stop(const char* message) {
   if (FLAG_print_stop_message) {
     PushList((1 << R0) | (1 << IP) | (1 << LR));  // Preserve R0, IP, LR.
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 76f20a1..f2203d6 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -15,6 +15,9 @@
 
 namespace dart {
 
+// Forward declarations.
+class RuntimeEntry;
+
 class Label : public ValueObject {
  public:
   Label() : position_(0) { }
@@ -159,6 +162,7 @@
   uint32_t encoding_;
 
   friend class Assembler;
+  friend class Address;
 };
 
 
@@ -200,6 +204,11 @@
 
 class Address : public ValueObject {
  public:
+  enum OffsetKind {
+    Immediate,
+    ShiftedRegister,
+  };
+
   // Memory operand addressing mode
   enum Mode {
     // bit encoding P U W
@@ -211,15 +220,19 @@
     NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
   };
 
-  Address(const Address& other) : ValueObject(), encoding_(other.encoding_) { }
+  Address(const Address& other)
+      : ValueObject(), encoding_(other.encoding_), kind_(other.kind_) {
+  }
 
   Address& operator=(const Address& other) {
     encoding_ = other.encoding_;
+    kind_ = other.kind_;
     return *this;
   }
 
   explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
     ASSERT(Utils::IsAbsoluteUint(12, offset));
+    kind_ = Immediate;
     if (offset < 0) {
       encoding_ = (am ^ (1 << kUShift)) | -offset;  // Flip U to adjust sign.
     } else {
@@ -228,6 +241,14 @@
     encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
   }
 
+  explicit Address(Register rn, Register rm, Shift shift = LSL,
+                   uint32_t shift_imm = 0, Mode am = Offset) {
+    ShifterOperand so(rm, shift, shift_imm);
+
+    kind_ = ShiftedRegister;
+    encoding_ = so.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift);
+  }
+
   static bool CanHoldLoadOffset(LoadOperandType type, int offset);
   static bool CanHoldStoreOffset(StoreOperandType type, int offset);
 
@@ -240,8 +261,12 @@
   // Encoding for vfp load/store addressing.
   uint32_t vencoding() const;
 
+  OffsetKind kind() const { return kind_; }
+
   uint32_t encoding_;
 
+  OffsetKind kind_;
+
   friend class Assembler;
 };
 
@@ -391,8 +416,8 @@
   void nop(Condition cond = AL);
 
   // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
-  void bkpt(uint16_t imm16);
-  void svc(uint32_t imm24);
+  void bkpt(uint16_t imm16, Condition cond = AL);
+  void svc(uint32_t imm24, Condition cond = AL);
 
   // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
   void vmovsr(SRegister sn, Register rt, Condition cond = AL);
@@ -413,6 +438,16 @@
   void vldrd(DRegister dd, Address ad, Condition cond = AL);
   void vstrd(DRegister dd, Address ad, Condition cond = AL);
 
+  void vldms(BlockAddressMode am, Register base,
+             SRegister first, SRegister last, Condition cond = AL);
+  void vstms(BlockAddressMode am, Register base,
+             SRegister first, SRegister last, Condition cond = AL);
+
+  void vldmd(BlockAddressMode am, Register base,
+             DRegister first, DRegister last, Condition cond = AL);
+  void vstmd(BlockAddressMode am, Register base,
+             DRegister first, DRegister last, Condition cond = AL);
+
   void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
   void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
   void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
@@ -453,11 +488,12 @@
   // Branch instructions.
   void b(Label* label, Condition cond = AL);
   void bl(Label* label, Condition cond = AL);
+  void bx(Register rm, Condition cond = AL);
   void blx(Register rm, Condition cond = AL);
 
   // Macros.
   // Branch to an entry address. Call sequence is never patched.
-  void Branch(const ExternalLabel* label);
+  void Branch(const ExternalLabel* label, Condition cond = AL);
 
   // Branch and link to an entry address. Call sequence is never patched.
   void BranchLink(const ExternalLabel* label);
@@ -472,14 +508,17 @@
   // Branch and link to [base + offset]. Call sequence is never patched.
   void BranchLinkOffset(Register base, int offset);
 
-  // Add signed constant value to rd. May clobber IP.
-  void AddConstant(Register rd, int32_t value, Condition cond = AL);
-  void AddConstant(Register rd, Register rn, int32_t value,
-                   Condition cond = AL);
-  void AddConstantSetFlags(Register rd, Register rn, int32_t value,
-                           Condition cond = AL);
-  void AddConstantWithCarry(Register rd, Register rn, int32_t value,
+  // Add signed immediate value to rd. May clobber IP.
+  void AddImmediate(Register rd, int32_t value, Condition cond = AL);
+  void AddImmediate(Register rd, Register rn, int32_t value,
+                    Condition cond = AL);
+  void AddImmediateSetFlags(Register rd, Register rn, int32_t value,
                             Condition cond = AL);
+  void AddImmediateWithCarry(Register rd, Register rn, int32_t value,
+                             Condition cond = AL);
+
+  // Compare rn with signed immediate value. May clobber IP.
+  void CompareImmediate(Register rn, int32_t value, Condition cond = AL);
 
   // Load and Store. May clobber IP.
   void LoadImmediate(Register rd, int32_t value, Condition cond = AL);
@@ -487,6 +526,7 @@
   void LoadDImmediate(DRegister dd, double value,
                       Register scratch, Condition cond = AL);
   void MarkExceptionHandler(Label* label);
+  void Drop(intptr_t stack_elements);
   void LoadObject(Register rd, const Object& object);
   void LoadFromOffset(LoadOperandType type,
                       Register reg,
@@ -531,6 +571,28 @@
   void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL);
   void Rrx(Register rd, Register rm, Condition cond = AL);
 
+  void SmiTag(Register reg, Condition cond = AL) {
+    Lsl(reg, reg, kSmiTagSize, cond);
+  }
+
+  void SmiUntag(Register reg, Condition cond = AL) {
+    Asr(reg, reg, kSmiTagSize, cond);
+  }
+
+  // Function frame setup and tear down.
+  void EnterFrame(RegList regs, intptr_t frame_space);
+  void LeaveFrame(RegList regs);
+  void Ret();
+  void ReserveAlignedFrameSpace(intptr_t frame_space);
+
+  // Create a frame for calling into runtime that preserves all volatile
+  // registers.  Frame's SP is guaranteed to be correctly aligned and
+  // frame_space bytes are reserved under it.
+  void EnterCallRuntimeFrame(intptr_t frame_space);
+  void LeaveCallRuntimeFrame();
+
+  void CallRuntime(const RuntimeEntry& entry);
+
   // Emit data (e.g encoded instruction or immediate) in instruction stream.
   void Emit(int32_t value);
 
@@ -605,6 +667,20 @@
                  Register rm,
                  Register rs);
 
+  void EmitMultiVSMemOp(Condition cond,
+                        BlockAddressMode am,
+                        bool load,
+                        Register base,
+                        SRegister start,
+                        uint32_t count);
+
+  void EmitMultiVDMemOp(Condition cond,
+                        BlockAddressMode am,
+                        bool load,
+                        Register base,
+                        DRegister start,
+                        int32_t count);
+
   void EmitVFPsss(Condition cond,
                   int32_t opcode,
                   SRegister sd,
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 1c6297e..bdd0837 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -130,6 +130,31 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(SingleVShiftLoadStore, assembler) {
+  __ LoadImmediate(R0, bit_cast<int32_t, float>(12.3f));
+  __ mov(R2, ShifterOperand(SP));
+  // Expressing __str(R0, Address(SP, (-kWordSize * 32), Address::PreIndex));
+  // as:
+  __ mov(R1, ShifterOperand(kWordSize));
+  __ str(R0, Address(SP, R1, LSL, 5, Address::NegPreIndex));
+  __ vldrs(S0, Address(R2, (-kWordSize * 32)));
+  __ vadds(S0, S0, S0);
+  __ vstrs(S0, Address(R2, (-kWordSize * 32)));
+  // Expressing __ldr(R0, Address(SP, (kWordSize * 32), Address::PostIndex));
+  // as:
+  __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(SingleVShiftLoadStore, test) {
+  EXPECT(test != NULL);
+  typedef float (*SingleVLoadStore)();
+  float res = EXECUTE_TEST_CODE_FLOAT(SingleVLoadStore, test->entry());
+  EXPECT_FLOAT_EQ(2*12.3f, res, 0.001f);
+}
+
+
 ASSEMBLER_TEST_GENERATE(DoubleVLoadStore, assembler) {
   int64_t value = bit_cast<int64_t, double>(12.3);
   __ LoadImmediate(R0, Utils::Low32Bits(value));
@@ -917,6 +942,425 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(AddressShiftStrLSL1NegOffset, assembler) {
+  __ mov(R2, ShifterOperand(42));
+  __ mov(R1, ShifterOperand(kWordSize));
+  __ str(R2, Address(SP, R1, LSL, 1, Address::NegOffset));
+  __ ldr(R0, Address(SP, (-kWordSize * 2), Address::Offset));
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftStrLSL1NegOffset, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftLdrLSL5NegOffset, assembler) {
+  __ mov(R2, ShifterOperand(42));
+  __ mov(R1, ShifterOperand(kWordSize));
+  __ str(R2, Address(SP, (-kWordSize * 32), Address::Offset));
+  __ ldr(R0, Address(SP, R1, LSL, 5, Address::NegOffset));
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftLdrLSL5NegOffset, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftStrLRS1NegOffset, assembler) {
+  __ mov(R2, ShifterOperand(42));
+  __ mov(R1, ShifterOperand(kWordSize * 2));
+  __ str(R2, Address(SP, R1, LSR, 1, Address::NegOffset));
+  __ ldr(R0, Address(SP, -kWordSize, Address::Offset));
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftStrLRS1NegOffset, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftLdrLRS1NegOffset, assembler) {
+  __ mov(R2, ShifterOperand(42));
+  __ mov(R1, ShifterOperand(kWordSize * 2));
+  __ str(R2, Address(SP, -kWordSize, Address::Offset));
+  __ ldr(R0, Address(SP, R1, LSR, 1, Address::NegOffset));
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftLdrLRS1NegOffset, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftStrLSLNegPreIndex, assembler) {
+  __ mov(R2, ShifterOperand(42));
+  __ mov(R1, ShifterOperand(kWordSize));
+  __ mov(R3, ShifterOperand(SP));
+  __ str(R2, Address(SP, R1, LSL, 5, Address::NegPreIndex));
+  __ ldr(R0, Address(R3, (-kWordSize * 32), Address::Offset));
+  __ mov(SP, ShifterOperand(R3));
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftStrLSLNegPreIndex, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddressShiftLdrLSLNegPreIndex, assembler) {
+  __ mov(R2, ShifterOperand(42));
+  __ mov(R1, ShifterOperand(kWordSize));
+  __ str(R2, Address(SP, (-kWordSize * 32), Address::PreIndex));
+  __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(AddressShiftLdrLSLNegPreIndex, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can store and reload the D registers using vstmd and vldmd
+ASSEMBLER_TEST_GENERATE(VstmdVldmd, assembler) {
+  __ LoadDImmediate(D0, 0.0, R0);
+  __ LoadDImmediate(D1, 1.0, R0);
+  __ LoadDImmediate(D2, 2.0, R0);
+  __ LoadDImmediate(D3, 3.0, R0);
+  __ LoadDImmediate(D4, 4.0, R0);
+  __ vstmd(DB_W, SP, D0, D4);  // Push D0 - D4 onto the stack, dec SP
+  __ LoadDImmediate(D0, 0.0, R0);
+  __ LoadDImmediate(D1, 0.0, R0);
+  __ LoadDImmediate(D2, 0.0, R0);
+  __ LoadDImmediate(D3, 0.0, R0);
+  __ LoadDImmediate(D4, 0.0, R0);
+  __ vldmd(IA_W, SP, D0, D4);  // Pop stack into D0 - D4, inc SP
+
+  // Load success value into R0
+  __ mov(R0, ShifterOperand(42));
+
+  // Check that 4.0 is back in D4
+  __ LoadDImmediate(D5, 4.0, R1);
+  __ vcmpd(D4, D5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  // Check that 3.0 is back in D3
+  __ LoadDImmediate(D5, 3.0, R1);
+  __ vcmpd(D3, D5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+
+  // Check that 2.0 is back in D2
+  __ LoadDImmediate(D5, 2.0, R1);
+  __ vcmpd(D2, D5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  // Check that 1.0 is back in D1
+  __ LoadDImmediate(D5, 1.0, R1);
+  __ vcmpd(D1, D5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmdVldmd, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can store and reload the S registers using vstms and vldms
+ASSEMBLER_TEST_GENERATE(VstmsVldms, assembler) {
+  __ LoadSImmediate(S0, 0.0);
+  __ LoadSImmediate(S1, 1.0);
+  __ LoadSImmediate(S2, 2.0);
+  __ LoadSImmediate(S3, 3.0);
+  __ LoadSImmediate(S4, 4.0);
+  __ vstms(DB_W, SP, S0, S4);  // Push S0 - S4 onto the stack, dec SP
+  __ LoadSImmediate(S0, 0.0);
+  __ LoadSImmediate(S1, 0.0);
+  __ LoadSImmediate(S2, 0.0);
+  __ LoadSImmediate(S3, 0.0);
+  __ LoadSImmediate(S4, 0.0);
+  __ vldms(IA_W, SP, S0, S4);  // Pop stack into S0 - S4, inc SP
+
+  // Load success value into R0
+  __ mov(R0, ShifterOperand(42));
+
+  // Check that 4.0 is back in S4
+  __ LoadSImmediate(S5, 4.0);
+  __ vcmps(S4, S5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 3.0 is back in S3
+  __ LoadSImmediate(S5, 3.0);
+  __ vcmps(S3, S5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 2.0 is back in S2
+  __ LoadSImmediate(S5, 2.0);
+  __ vcmps(S2, S5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 1.0 is back in S1
+  __ LoadSImmediate(S5, 1.0);
+  __ vcmps(S1, S5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmsVldms, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can start somewhere other than D0
+ASSEMBLER_TEST_GENERATE(VstmdVldmd1, assembler) {
+  __ LoadDImmediate(D1, 1.0, R0);
+  __ LoadDImmediate(D2, 2.0, R0);
+  __ LoadDImmediate(D3, 3.0, R0);
+  __ LoadDImmediate(D4, 4.0, R0);
+  __ vstmd(DB_W, SP, D1, D4);  // Push D1 - D4 onto the stack, dec SP
+  __ LoadDImmediate(D1, 0.0, R0);
+  __ LoadDImmediate(D2, 0.0, R0);
+  __ LoadDImmediate(D3, 0.0, R0);
+  __ LoadDImmediate(D4, 0.0, R0);
+  __ vldmd(IA_W, SP, D1, D4);  // Pop stack into D1 - D4, inc SP
+
+  // Load success value into R0
+  __ mov(R0, ShifterOperand(42));
+
+  // Check that 4.0 is back in D4
+  __ LoadDImmediate(D5, 4.0, R1);
+  __ vcmpd(D4, D5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  // Check that 3.0 is back in D3
+  __ LoadDImmediate(D5, 3.0, R1);
+  __ vcmpd(D3, D5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+
+  // Check that 2.0 is back in D2
+  __ LoadDImmediate(D5, 2.0, R1);
+  __ vcmpd(D2, D5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  // Check that 1.0 is back in D1
+  __ LoadDImmediate(D5, 1.0, R1);
+  __ vcmpd(D1, D5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmdVldmd1, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can start somewhere other than S0
+ASSEMBLER_TEST_GENERATE(VstmsVldms1, assembler) {
+  __ LoadSImmediate(S1, 1.0);
+  __ LoadSImmediate(S2, 2.0);
+  __ LoadSImmediate(S3, 3.0);
+  __ LoadSImmediate(S4, 4.0);
+  __ vstms(DB_W, SP, S1, S4);  // Push S0 - S4 onto the stack, dec SP
+  __ LoadSImmediate(S1, 0.0);
+  __ LoadSImmediate(S2, 0.0);
+  __ LoadSImmediate(S3, 0.0);
+  __ LoadSImmediate(S4, 0.0);
+  __ vldms(IA_W, SP, S1, S4);  // Pop stack into S0 - S4, inc SP
+
+  // Load success value into R0
+  __ mov(R0, ShifterOperand(42));
+
+  // Check that 4.0 is back in S4
+  __ LoadSImmediate(S5, 4.0);
+  __ vcmps(S4, S5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 3.0 is back in S3
+  __ LoadSImmediate(S5, 3.0);
+  __ vcmps(S3, S5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 2.0 is back in S2
+  __ LoadSImmediate(S5, 2.0);
+  __ vcmps(S2, S5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 1.0 is back in S1
+  __ LoadSImmediate(S5, 1.0);
+  __ vcmps(S1, S5);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmsVldms1, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can store the D registers using vstmd and
+// load them into a different set using vldmd
+ASSEMBLER_TEST_GENERATE(VstmdVldmd_off, assembler) {
+  __ LoadDImmediate(D0, 0.0, R0);
+  __ LoadDImmediate(D1, 1.0, R0);
+  __ LoadDImmediate(D2, 2.0, R0);
+  __ LoadDImmediate(D3, 3.0, R0);
+  __ LoadDImmediate(D4, 4.0, R0);
+  __ LoadDImmediate(D5, 5.0, R0);
+  __ vstmd(DB_W, SP, D0, D4);  // Push D0 - D4 onto the stack, dec SP
+  __ vldmd(IA_W, SP, D5, D9);  // Pop stack into D5 - D9, inc SP
+
+  // Load success value into R0
+  __ mov(R0, ShifterOperand(42));
+
+  // Check that 4.0 is in D9
+  __ LoadDImmediate(D10, 4.0, R1);
+  __ vcmpd(D9, D10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  // Check that 3.0 is in D8
+  __ LoadDImmediate(D10, 3.0, R1);
+  __ vcmpd(D8, D10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+
+  // Check that 2.0 is in D7
+  __ LoadDImmediate(D10, 2.0, R1);
+  __ vcmpd(D7, D10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  // Check that 1.0 is in D6
+  __ LoadDImmediate(D10, 1.0, R1);
+  __ vcmpd(D6, D10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  // Check that 0.0 is in D5
+  __ LoadDImmediate(D10, 0.0, R1);
+  __ vcmpd(D5, D10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure into R0 if NE
+
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmdVldmd_off, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+// Make sure we can start somewhere other than S0
+ASSEMBLER_TEST_GENERATE(VstmsVldms_off, assembler) {
+  __ LoadSImmediate(S0, 0.0);
+  __ LoadSImmediate(S1, 1.0);
+  __ LoadSImmediate(S2, 2.0);
+  __ LoadSImmediate(S3, 3.0);
+  __ LoadSImmediate(S4, 4.0);
+  __ LoadSImmediate(S5, 5.0);
+  __ vstms(DB_W, SP, S0, S4);  // Push S0 - S4 onto the stack, dec SP
+  __ vldms(IA_W, SP, S5, S9);  // Pop stack into S5 - S9, inc SP
+
+  // Load success value into R0
+  __ mov(R0, ShifterOperand(42));
+
+  // Check that 4.0 is in S9
+  __ LoadSImmediate(S10, 4.0);
+  __ vcmps(S9, S10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 3.0 is in S8
+  __ LoadSImmediate(S10, 3.0);
+  __ vcmps(S8, S10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 2.0 is in S7
+  __ LoadSImmediate(S10, 2.0);
+  __ vcmps(S7, S10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 1.0 is back in S6
+  __ LoadSImmediate(S10, 1.0);
+  __ vcmps(S6, S10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  // Check that 0.0 is back in S5
+  __ LoadSImmediate(S10, 0.0);
+  __ vcmps(S5, S10);
+  __ vmstat();
+  __ mov(R0, ShifterOperand(0), NE);  // Put failure value into R0 if NE
+
+  __ mov(PC, ShifterOperand(LR));
+}
+
+
+ASSEMBLER_TEST_RUN(VstmsVldms_off, test) {
+  EXPECT(test != NULL);
+  typedef int (*Tst)();
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index bef0afb..824b592 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -1979,38 +1979,6 @@
 }
 
 
-void Assembler::DoubleRound(XmmRegister dst, XmmRegister src, XmmRegister tmp) {
-  ASSERT(tmp != src);
-  static double kZeroFiveConst = 0.5;
-  static double kNegZeroFiveConst = -0.5;
-  static double kOneConst = 1.0;
-  static double kNegOneConst = -1.0;
-  Label is_negative, round;
-  if (src != dst) {
-    movsd(dst, src);
-  }
-  // Special handling: 0.5 -> 1.0, -0.5 -> -1.0;
-  Label done, equal_point5, equal_neg_point5;
-  movsd(tmp, Address::Absolute(reinterpret_cast<intptr_t>(&kZeroFiveConst)));
-  comisd(tmp, dst);
-  j(EQUAL, &equal_point5, Assembler::kNearJump);
-  movsd(tmp, Address::Absolute(reinterpret_cast<intptr_t>(&kNegZeroFiveConst)));
-  comisd(tmp, dst);
-  j(EQUAL, &equal_neg_point5, Assembler::kNearJump);
-
-  roundsd(dst, dst, Assembler::kRoundToNearest);
-  jmp(&done, Assembler::kNearJump);
-
-  Bind(&equal_point5);
-  movsd(dst, Address::Absolute(reinterpret_cast<intptr_t>(&kOneConst)));
-  jmp(&done);
-
-  Bind(&equal_neg_point5);
-  movsd(dst, Address::Absolute(reinterpret_cast<intptr_t>(&kNegOneConst)));
-  Bind(&done);
-}
-
-
 void Assembler::EnterFrame(intptr_t frame_size) {
   if (prologue_offset_ == -1) {
     prologue_offset_ = CodeSize();
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 8ab5b0c..adc9494 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -628,7 +628,6 @@
   void FloatNegate(XmmRegister f);
 
   void DoubleAbs(XmmRegister reg);
-  void DoubleRound(XmmRegister dst, XmmRegister src, XmmRegister tmp);
 
   void LockCmpxchgl(const Address& address, Register reg) {
     lock();
diff --git a/runtime/vm/assembler_ia32_test.cc b/runtime/vm/assembler_ia32_test.cc
index f3da046..7933061 100644
--- a/runtime/vm/assembler_ia32_test.cc
+++ b/runtime/vm/assembler_ia32_test.cc
@@ -1675,48 +1675,6 @@
 }
 
 
-ASSEMBLER_TEST_GENERATE(DoubleToDoubleRound, assembler) {
-  __ movsd(XMM3, Address(ESP, kWordSize));
-  __ DoubleRound(XMM2, XMM3, XMM0);
-  __ pushl(EAX);
-  __ pushl(EAX);
-  __ movsd(Address(ESP, 0), XMM2);
-  __ fldl(Address(ESP, 0));
-  __ popl(EAX);
-  __ popl(EAX);
-  __ ret();
-}
-
-
-ASSEMBLER_TEST_RUN(DoubleToDoubleRound, test) {
-  typedef double (*DoubleToDoubleRoundCode)(double d);
-  double res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(12.3);
-  EXPECT_EQ(12.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(12.8);
-  EXPECT_EQ(13.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(0.5);
-  EXPECT_EQ(1.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-12.3);
-  EXPECT_EQ(-12.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-12.8);
-  EXPECT_EQ(-13.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-0.5);
-  EXPECT_EQ(-1.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(
-      test->entry())(0.49999999999999994);
-  EXPECT_EQ(0.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(
-      test->entry())(-0.49999999999999994);
-  EXPECT_EQ(-0.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(
-      test->entry())(9007199254740991.0);
-  EXPECT_EQ(9007199254740991.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(
-      test->entry())(-9007199254740991.0);
-  EXPECT_EQ(-9007199254740991.0, res);
-}
-
-
 static const double kDoubleConst = 3.226;
 
 ASSEMBLER_TEST_GENERATE(GlobalAddress, assembler) {
diff --git a/runtime/vm/assembler_macros_arm.cc b/runtime/vm/assembler_macros_arm.cc
index f2266c2..38cd6a5 100644
--- a/runtime/vm/assembler_macros_arm.cc
+++ b/runtime/vm/assembler_macros_arm.cc
@@ -7,8 +7,13 @@
 
 #include "vm/assembler_macros.h"
 
+#include "vm/assembler.h"
+
 namespace dart {
 
+#define __ assembler->
+
+
 void AssemblerMacros::TryAllocate(Assembler* assembler,
                                   const Class& cls,
                                   Label* failure,
@@ -20,12 +25,49 @@
 
 void AssemblerMacros::EnterDartFrame(Assembler* assembler,
                                      intptr_t frame_size) {
-  UNIMPLEMENTED();
+  const intptr_t offset = assembler->CodeSize();
+  // Save PC in frame for fast identification of corresponding code.
+  // Note that callee-saved registers can be added to the register list.
+  __ EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0);
+
+  if (offset != 0) {
+    // Adjust saved PC for any intrinsic code that could have been generated
+    // before a frame is created. Use PP as temp register.
+    __ ldr(PP, Address(FP, 2 * kWordSize));
+    __ AddImmediate(PP, PP, -offset);
+    __ str(PP, Address(FP, 2 * kWordSize));
+  }
+
+  // Setup pool pointer for this dart function.
+  const intptr_t object_pool_pc_dist =
+     Instructions::HeaderSize() - Instructions::object_pool_offset() +
+     assembler->CodeSize() + Instr::kPCReadOffset;
+  __ ldr(PP, Address(PC, -object_pool_pc_dist));
+
+  // Reserve space for locals.
+  __ AddImmediate(SP, -frame_size);
+}
+
+
+void AssemblerMacros::LeaveDartFrame(Assembler* assembler) {
+  __ LeaveFrame((1 << PP) | (1 << FP) | (1 << LR));
+  // Adjust SP for PC pushed in EnterDartFrame.
+  __ AddImmediate(SP, kWordSize);
 }
 
 
 void AssemblerMacros::EnterStubFrame(Assembler* assembler) {
-  UNIMPLEMENTED();
+  // Push 0 as saved PC for stub frames.
+  __ mov(IP, ShifterOperand(LR));
+  __ mov(LR, ShifterOperand(0));
+  __ EnterFrame((1 << FP) | (1 << IP) | (1 << LR), 0);
+}
+
+
+void AssemblerMacros::LeaveStubFrame(Assembler* assembler) {
+  __ LeaveFrame((1 << FP) | (1 << LR));
+  // Adjust SP for null PC pushed in EnterStubFrame.
+  __ AddImmediate(SP, kWordSize);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/assembler_macros_arm.h b/runtime/vm/assembler_macros_arm.h
index 5bf1427..0a5119b 100644
--- a/runtime/vm/assembler_macros_arm.h
+++ b/runtime/vm/assembler_macros_arm.h
@@ -37,15 +37,17 @@
   // enable easy access to the RawInstruction object of code corresponding
   // to this frame.
   static void EnterDartFrame(Assembler* assembler, intptr_t frame_size);
+  static void LeaveDartFrame(Assembler* assembler);
 
   // Set up a stub frame so that the stack traversal code can easily identify
   // a stub frame.
   static void EnterStubFrame(Assembler* assembler);
+  static void LeaveStubFrame(Assembler* assembler);
 
   // Instruction pattern from entrypoint is used in dart frame prologs
   // to set up the frame and save a PC which can be used to figure out the
   // RawInstruction object corresponding to the code running in the frame.
-  static const intptr_t kOffsetOfSavedPCfromEntrypoint = -1;  // UNIMPLEMENTED.
+  static const intptr_t kOffsetOfSavedPCfromEntrypoint = Instr::kPCReadOffset;
 };
 
 }  // namespace dart.
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 8afb003..2db5f67 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -2081,42 +2081,6 @@
 }
 
 
-void Assembler::DoubleRound(XmmRegister dst, XmmRegister src, XmmRegister tmp) {
-  ASSERT(tmp != src);
-  static double kZeroFiveConst = 0.5;
-  static double kNegZeroFiveConst = -0.5;
-  static double kOneConst = 1.0;
-  static double kNegOneConst = -1.0;
-  Label is_negative, round;
-  if (src != dst) {
-    movsd(dst, src);
-  }
-  // Special handling: 0.5 -> 1.0, -0.5 -> -1.0;
-  Label done, equal_point5, equal_neg_point5;
-  movq(TMP, Immediate(reinterpret_cast<intptr_t>(&kZeroFiveConst)));
-  movsd(tmp, Address(TMP, 0));
-  comisd(tmp, dst);
-  j(EQUAL, &equal_point5, Assembler::kNearJump);
-  movq(TMP, Immediate(reinterpret_cast<intptr_t>(&kNegZeroFiveConst)));
-  movsd(tmp, Address(TMP, 0));
-  comisd(tmp, dst);
-  j(EQUAL, &equal_neg_point5, Assembler::kNearJump);
-
-  roundsd(dst, dst, Assembler::kRoundToNearest);
-  jmp(&done, Assembler::kNearJump);
-
-  Bind(&equal_point5);
-  movq(TMP, Immediate(reinterpret_cast<intptr_t>(&kOneConst)));
-  movsd(dst, Address(TMP, 0));
-  jmp(&done);
-
-  Bind(&equal_neg_point5);
-  movq(TMP, Immediate(reinterpret_cast<intptr_t>(&kNegOneConst)));
-  movsd(dst, Address(TMP, 0));
-  Bind(&done);
-}
-
-
 void Assembler::Stop(const char* message) {
   int64_t message_address = reinterpret_cast<int64_t>(message);
   if (FLAG_print_stop_message) {
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 64add15..61894c0 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -642,7 +642,6 @@
   void FloatNegate(XmmRegister f);
 
   void DoubleAbs(XmmRegister reg);
-  void DoubleRound(XmmRegister dst, XmmRegister src, XmmRegister tmp);
 
   void LockCmpxchgl(const Address& address, Register reg) {
     lock();
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc
index b035b6e..ba99591 100644
--- a/runtime/vm/assembler_x64_test.cc
+++ b/runtime/vm/assembler_x64_test.cc
@@ -2226,41 +2226,6 @@
 }
 
 
-ASSEMBLER_TEST_GENERATE(DoubleToDoubleRound, assembler) {
-  __ DoubleRound(XMM0, XMM0, XMM1);
-  __ ret();
-}
-
-
-ASSEMBLER_TEST_RUN(DoubleToDoubleRound, test) {
-  typedef double (*DoubleToDoubleRoundCode)(double d);
-  double res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(12.3);
-  EXPECT_EQ(12.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(12.8);
-  EXPECT_EQ(13.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(0.5);
-  EXPECT_EQ(1.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-12.3);
-  EXPECT_EQ(-12.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-12.8);
-  EXPECT_EQ(-13.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(test->entry())(-0.5);
-  EXPECT_EQ(-1.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(
-      test->entry())(0.49999999999999994);
-  EXPECT_EQ(0.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(
-      test->entry())(-0.49999999999999994);
-  EXPECT_EQ(-0.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(
-      test->entry())(9007199254740991.0);
-  EXPECT_EQ(9007199254740991.0, res);
-  res = reinterpret_cast<DoubleToDoubleRoundCode>(
-      test->entry())(-9007199254740991.0);
-  EXPECT_EQ(-9007199254740991.0, res);
-}
-
-
 ASSEMBLER_TEST_GENERATE(ExtractSignBits, assembler) {
   __ movmskpd(RAX, XMM0);
   __ andq(RAX, Immediate(0x1));
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index dbe70d9..4ac570b 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -429,7 +429,7 @@
     return NULL;
   }
   const Object& result = Object::Handle(
-      DartEntry::InvokeStatic(getter_func, Object::empty_array()));
+      DartEntry::InvokeFunction(getter_func, Object::empty_array()));
   if (result.IsError() || result.IsNull()) {
     // TODO(turnidge): We could get better error messages by returning
     // the Error object directly to the parser.  This will involve
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 1b1d8d0..4ff0081 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -22,11 +22,11 @@
                                  bool patch) {
   return Script::New(String::Handle(String::New(url, Heap::kOld)),
                      String::Handle(String::New(source, Heap::kOld)),
-                     patch ? RawScript::kPatchTag : RawScript::kSourceTag);
+                     patch ? RawScript::kPatchTag : RawScript::kLibraryTag);
 }
 
 
-RawScript* Bootstrap::LoadASyncScript(bool patch) {
+RawScript* Bootstrap::LoadAsyncScript(bool patch) {
   const char* url = patch ? "dart:async-patch" : "dart:async";
   const char* source = patch ? async_patch_ : async_source_;
   return LoadScript(url, source, patch);
@@ -72,7 +72,7 @@
 
 RawScript* Bootstrap::LoadJsonScript(bool patch) {
   const char* url = patch ? "dart:json-patch" : "dart:json";
-  const char* source = patch ? json_source_ : json_source_;
+  const char* source = patch ? json_patch_ : json_source_;
   return LoadScript(url, source, patch);
 }
 
diff --git a/runtime/vm/bootstrap.h b/runtime/vm/bootstrap.h
index 275c27d..56fdc8c 100644
--- a/runtime/vm/bootstrap.h
+++ b/runtime/vm/bootstrap.h
@@ -17,7 +17,7 @@
 
 class Bootstrap : public AllStatic {
  public:
-  static RawScript* LoadASyncScript(bool patch);
+  static RawScript* LoadAsyncScript(bool patch);
   static RawScript* LoadCoreScript(bool patch);
   static RawScript* LoadCollectionScript(bool patch);
   static RawScript* LoadCollectionDevScript(bool patch);
@@ -45,6 +45,7 @@
   static const char isolate_source_[];
   static const char isolate_patch_[];
   static const char json_source_[];
+  static const char json_patch_[];
   static const char math_source_[];
   static const char math_patch_[];
   static const char mirrors_source_[];
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index 3b65e03..2f9ade3 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -56,7 +56,7 @@
   Dart_NativeEntryResolver resolver =
       reinterpret_cast<Dart_NativeEntryResolver>(BootstrapNatives::Lookup);
 
-  library = Library::ASyncLibrary();
+  library = Library::AsyncLibrary();
   ASSERT(!library.IsNull());
   library.set_native_entry_resolver(resolver);
 
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index dd21318..9f0db00 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -83,7 +83,7 @@
   V(String_getHashCode, 1)                                                     \
   V(String_getLength, 1)                                                       \
   V(String_charAt, 2)                                                          \
-  V(String_charCodeAt, 2)                                                      \
+  V(String_codeUnitAt, 2)                                                      \
   V(String_concat, 2)                                                          \
   V(String_toLowerCase, 1)                                                     \
   V(String_toUpperCase, 1)                                                     \
@@ -106,8 +106,68 @@
   V(TypeError_throwNew, 5)                                                     \
   V(FallThroughError_throwNew, 1)                                              \
   V(AbstractClassInstantiationError_throwNew, 2)                               \
+  V(Stacktrace_getFullStacktrace, 1)                                           \
+  V(Stacktrace_getStacktrace, 1)                                               \
+  V(Stacktrace_setupFullStacktrace, 1)                                         \
   V(Stopwatch_now, 0)                                                          \
   V(Stopwatch_frequency, 0)                                                    \
+  V(Float32x4_fromDoubles, 5)                                                  \
+  V(Float32x4_zero, 1)                                                         \
+  V(Float32x4_add, 2)                                                          \
+  V(Float32x4_negate, 1)                                                       \
+  V(Float32x4_sub, 2)                                                          \
+  V(Float32x4_mul, 2)                                                          \
+  V(Float32x4_div, 2)                                                          \
+  V(Float32x4_cmplt, 2)                                                        \
+  V(Float32x4_cmplte, 2)                                                       \
+  V(Float32x4_cmpgt, 2)                                                        \
+  V(Float32x4_cmpgte, 2)                                                       \
+  V(Float32x4_cmpequal, 2)                                                     \
+  V(Float32x4_cmpnequal, 2)                                                    \
+  V(Float32x4_scale, 2)                                                        \
+  V(Float32x4_abs, 1)                                                          \
+  V(Float32x4_clamp, 3)                                                        \
+  V(Float32x4_getX, 1)                                                         \
+  V(Float32x4_getY, 1)                                                         \
+  V(Float32x4_getZ, 1)                                                         \
+  V(Float32x4_getW, 1)                                                         \
+  V(Float32x4_getXXXX, 1)                                                      \
+  V(Float32x4_getYYYY, 1)                                                      \
+  V(Float32x4_getZZZZ, 1)                                                      \
+  V(Float32x4_getWWWW, 1)                                                      \
+  V(Float32x4_setX, 2)                                                         \
+  V(Float32x4_setY, 2)                                                         \
+  V(Float32x4_setZ, 2)                                                         \
+  V(Float32x4_setW, 2)                                                         \
+  V(Float32x4_min, 2)                                                          \
+  V(Float32x4_max, 2)                                                          \
+  V(Float32x4_sqrt, 1)                                                         \
+  V(Float32x4_reciprocal, 1)                                                   \
+  V(Float32x4_reciprocalSqrt, 1)                                               \
+  V(Float32x4_toUint32x4, 1)                                                   \
+  V(Uint32x4_fromInts, 5)                                                      \
+  V(Uint32x4_fromBools, 5)                                                     \
+  V(Uint32x4_or, 2)                                                            \
+  V(Uint32x4_and, 2)                                                           \
+  V(Uint32x4_xor, 2)                                                           \
+  V(Uint32x4_getX, 1)                                                          \
+  V(Uint32x4_getY, 1)                                                          \
+  V(Uint32x4_getZ, 1)                                                          \
+  V(Uint32x4_getW, 1)                                                          \
+  V(Uint32x4_setX, 2)                                                          \
+  V(Uint32x4_setY, 2)                                                          \
+  V(Uint32x4_setZ, 2)                                                          \
+  V(Uint32x4_setW, 2)                                                          \
+  V(Uint32x4_getFlagX, 1)                                                      \
+  V(Uint32x4_getFlagY, 1)                                                      \
+  V(Uint32x4_getFlagZ, 1)                                                      \
+  V(Uint32x4_getFlagW, 1)                                                      \
+  V(Uint32x4_setFlagX, 2)                                                      \
+  V(Uint32x4_setFlagY, 2)                                                      \
+  V(Uint32x4_setFlagZ, 2)                                                      \
+  V(Uint32x4_setFlagW, 2)                                                      \
+  V(Uint32x4_select, 3)                                                        \
+  V(Uint32x4_toFloat32x4, 1)                                                   \
   V(ByteArray_getLength, 1)                                                    \
   V(ByteArray_getInt8, 2)                                                      \
   V(ByteArray_setInt8, 3)                                                      \
@@ -125,6 +185,8 @@
   V(ByteArray_setInt64, 3)                                                     \
   V(ByteArray_getUint64, 2)                                                    \
   V(ByteArray_setUint64, 3)                                                    \
+  V(ByteArray_getFloat32x4, 2)                                                 \
+  V(ByteArray_setFloat32x4, 3)                                                 \
   V(ByteArray_getFloat32, 2)                                                   \
   V(ByteArray_setFloat32, 3)                                                   \
   V(ByteArray_getFloat64, 2)                                                   \
@@ -166,6 +228,10 @@
   V(Uint64List_newTransferable, 1)                                             \
   V(Uint64Array_getIndexed, 2)                                                 \
   V(Uint64Array_setIndexed, 3)                                                 \
+  V(Float32x4Array_new, 1)                                                     \
+  V(Float32x4List_newTransferable, 1)                                          \
+  V(Float32x4Array_getIndexed, 2)                                              \
+  V(Float32x4Array_setIndexed, 3)                                              \
   V(Float32Array_new, 1)                                                       \
   V(Float32List_newTransferable, 1)                                            \
   V(Float32Array_getIndexed, 2)                                                \
@@ -192,6 +258,8 @@
   V(ExternalInt64Array_setIndexed, 3)                                          \
   V(ExternalUint64Array_getIndexed, 2)                                         \
   V(ExternalUint64Array_setIndexed, 3)                                         \
+  V(ExternalFloat32x4Array_getIndexed, 2)                                      \
+  V(ExternalFloat32x4Array_setIndexed, 3)                                      \
   V(ExternalFloat32Array_getIndexed, 2)                                        \
   V(ExternalFloat32Array_setIndexed, 3)                                        \
   V(ExternalFloat64Array_getIndexed, 2)                                        \
diff --git a/runtime/vm/bootstrap_nocorelib.cc b/runtime/vm/bootstrap_nocorelib.cc
index d838fc2..1e6799a 100644
--- a/runtime/vm/bootstrap_nocorelib.cc
+++ b/runtime/vm/bootstrap_nocorelib.cc
@@ -15,7 +15,7 @@
 DEFINE_FLAG(bool, print_bootstrap, false, "Print the bootstrap source.");
 
 
-RawScript* Bootstrap::LoadASyncScript(bool is_patch) {
+RawScript* Bootstrap::LoadAsyncScript(bool is_patch) {
   UNREACHABLE();
   return Script::null();
 }
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index b2253ee..81c7c87 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -771,11 +771,7 @@
   // Self referencing types may get finalized indirectly.
   if (!parameterized_type.IsFinalized()) {
     // Mark the type as finalized.
-    if (parameterized_type.IsInstantiated()) {
-      parameterized_type.set_is_finalized_instantiated();
-    } else {
-      parameterized_type.set_is_finalized_uninstantiated();
-    }
+    parameterized_type.SetIsFinalized();
   }
 
   // Upper bounds of the finalized type arguments are only verified in checked
@@ -1121,6 +1117,31 @@
                 class_name.ToCString());
   }
 
+  // Copy the type parameters of the mixin class to the mixin
+  // application class.
+  const int num_type_parameters = mixin_cls.NumTypeParameters();
+  if (num_type_parameters > 0) {
+    ASSERT(cls.NumTypeParameters() == 0);
+    const TypeArguments& type_params =
+        TypeArguments::Handle(mixin_cls.type_parameters());
+    const TypeArguments& cloned_type_params =
+        TypeArguments::Handle(TypeArguments::New(num_type_parameters));
+    ASSERT(!type_params.IsNull());
+    TypeParameter& param = TypeParameter::Handle();
+    TypeParameter& cloned_param = TypeParameter::Handle();
+    String& param_name = String::Handle();
+    AbstractType& param_bound = AbstractType::Handle();
+    for (int i = 0; i < num_type_parameters; i++) {
+      param ^= type_params.TypeAt(i);
+      param_name = param.name();
+      param_bound = param.bound();
+      cloned_param = TypeParameter::New(
+          cls, i, param_name, param_bound, param.token_pos());
+      cloned_type_params.SetTypeAt(i, cloned_param);
+    }
+    cls.set_type_parameters(cloned_type_params);
+  }
+
   const GrowableObjectArray& cloned_funcs =
       GrowableObjectArray::Handle(GrowableObjectArray::New());
   Array& functions = Array::Handle();
@@ -1194,6 +1215,12 @@
   if (!super_class.IsNull()) {
     FinalizeClass(super_class);
   }
+  if (cls.mixin() != Type::null()) {
+    // Copy instance methods and fields from the mixin class.
+    // This has to happen before the check whether the methods of
+    // the class conflict with inherited methods.
+    ApplyMixin(cls);
+  }
   // Finalize type parameters before finalizing the super type.
   FinalizeTypeParameters(cls);
   // Finalize super type.
@@ -1227,12 +1254,6 @@
     FinalizeType(cls, sig_type, kCanonicalizeWellFormed);
     return;
   }
-  if (cls.mixin() != Type::null()) {
-    // Copy instance methods and fields from the mixin class.
-    // This has to happen before the check whether the methods of
-    // the class conflict with inherited methods.
-    ApplyMixin(cls);
-  }
   // Finalize interface types (but not necessarily interface classes).
   Array& interface_types = Array::Handle(cls.interfaces());
   AbstractType& interface_type = AbstractType::Handle();
@@ -1607,7 +1628,7 @@
   }
   ASSERT(type.HasResolvedTypeClass());
   if (!type.IsFinalized()) {
-    type.set_is_finalized_instantiated();
+    type.SetIsFinalized();
     // Do not canonicalize malformed types, since they may not be resolved.
   } else {
     // The only case where the malformed type was already finalized is when its
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 261b0dd..e4fc7b8 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -278,7 +278,7 @@
   // is called, this should then cause the stack map of function 'A.foo'
   // to be traversed and the appropriate objects visited.
   const Object& result = Object::Handle(
-      DartEntry::InvokeStatic(function_foo, Object::empty_array()));
+      DartEntry::InvokeFunction(function_foo, Object::empty_array()));
   EXPECT(!result.IsError());
 }
 
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 75e1a03..94ff500 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1109,20 +1109,16 @@
 
 // A non-closure object was invoked as a closure, so call the "call" method
 // on it.
-// Arg0: non-closure object.
-// Arg1: arguments descriptor.
-// Arg2: arguments array, including non-closure object.
-DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 3) {
+// Arg0: arguments descriptor.
+// Arg1: arguments array, including non-closure object.
+DEFINE_RUNTIME_ENTRY(InvokeNonClosure, 2) {
   ASSERT(arguments.ArgCount() ==
          kInvokeNonClosureRuntimeEntry.argument_count());
-  const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0));
-  const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(1));
-  const Array& function_args = Array::CheckedHandle(arguments.ArgAt(2));
+  const Array& args_descriptor = Array::CheckedHandle(arguments.ArgAt(0));
+  const Array& function_args = Array::CheckedHandle(arguments.ArgAt(1));
 
   const Object& result = Object::Handle(
-      DartEntry::InvokeClosure(instance,
-                               function_args,
-                               args_descriptor));
+      DartEntry::InvokeClosure(function_args, args_descriptor));
   CheckResultError(result);
   arguments.SetReturn(result);
 }
@@ -1154,7 +1150,7 @@
   // 2. Invoke the getter.
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, receiver);
-  const Object& value = Object::Handle(DartEntry::InvokeDynamic(getter, args));
+  const Object& value = Object::Handle(DartEntry::InvokeFunction(getter, args));
 
   // 3. If the getter threw an exception, treat it as no such method.
   if (value.IsUnhandledException()) return false;
@@ -1166,9 +1162,7 @@
   Instance& instance = Instance::Handle();
   instance ^= value.raw();
   arguments.SetAt(0, instance);
-  *result = DartEntry::InvokeClosure(instance,
-                                     arguments,
-                                     arguments_descriptor);
+  *result = DartEntry::InvokeClosure(arguments, arguments_descriptor);
   CheckResultError(*result);
   return true;
 }
diff --git a/runtime/vm/code_generator_test.cc b/runtime/vm/code_generator_test.cc
index f2b4c62..cb86ed0 100644
--- a/runtime/vm/code_generator_test.cc
+++ b/runtime/vm/code_generator_test.cc
@@ -4,7 +4,9 @@
 
 #include "platform/assert.h"
 #include "vm/globals.h"
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
+#if defined(TARGET_ARCH_IA32) ||                                               \
+    defined(TARGET_ARCH_X64) ||                                                \
+    defined(TARGET_ARCH_ARM)
 
 #include "vm/ast.h"
 #include "vm/assembler.h"
@@ -23,14 +25,6 @@
 static const intptr_t kPos = Scanner::kDummyTokenIndex;
 
 
-// Helper to allocate and return a LocalVariable.
-static LocalVariable* NewTestLocalVariable(const char* name) {
-  const String& variable_name = String::ZoneHandle(Symbols::New(name));
-  const Type& variable_type = Type::ZoneHandle(Type::DynamicType());
-  return new LocalVariable(kPos, variable_name, variable_type);
-}
-
-
 CODEGEN_TEST_GENERATE(SimpleReturnCodegen, test) {
   test->node_sequence()->Add(new ReturnNode(kPos));
 }
@@ -53,6 +47,17 @@
 CODEGEN_TEST2_RUN(SimpleStaticCallCodegen, SmiReturnCodegen, Smi::New(3))
 
 
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
+
+
+// Helper to allocate and return a LocalVariable.
+static LocalVariable* NewTestLocalVariable(const char* name) {
+  const String& variable_name = String::ZoneHandle(Symbols::New(name));
+  const Type& variable_type = Type::ZoneHandle(Type::DynamicType());
+  return new LocalVariable(kPos, variable_name, variable_type);
+}
+
+
 CODEGEN_TEST_GENERATE(ReturnParameterCodegen, test) {
   SequenceNode* node_seq = test->node_sequence();
   const int num_params = 1;
@@ -545,7 +550,7 @@
 
 CODEGEN_TEST_RAW_RUN(AllocateNewObjectCodegen, function) {
   const Object& result = Object::Handle(
-      DartEntry::InvokeStatic(function, Object::empty_array()));
+      DartEntry::InvokeFunction(function, Object::empty_array()));
   EXPECT(!result.IsError());
   const GrowableObjectArray& libs =  GrowableObjectArray::Handle(
       Isolate::Current()->object_store()->libraries());
@@ -560,6 +565,8 @@
   EXPECT_EQ(cls.raw(), result.clazz());
 }
 
+#endif  // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
+
 }  // namespace dart
 
-#endif  // defined TARGET_ARCH_IA32 || defined(TARGET_ARCH_X64)
+#endif  // defined(TARGET_ARCH_IA32) || ..._ARCH_X64) || ..._ARCH_ARM)
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc
index 90582f8..8f75660 100644
--- a/runtime/vm/code_patcher_arm.cc
+++ b/runtime/vm/code_patcher_arm.cc
@@ -7,6 +7,7 @@
 
 #include "vm/code_patcher.h"
 
+#include "vm/instructions.h"
 #include "vm/object.h"
 
 namespace dart {
@@ -14,8 +15,8 @@
 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
                                          const Code& code) {
   ASSERT(code.ContainsInstructionAt(return_address));
-  UNIMPLEMENTED();
-  return 0;
+  CallPattern call(return_address, code);
+  return call.TargetAddress();
 }
 
 
@@ -23,7 +24,8 @@
                                     const Code& code,
                                     uword new_target) {
   ASSERT(code.ContainsInstructionAt(return_address));
-  UNIMPLEMENTED();
+  CallPattern call(return_address, code);
+  call.SetTargetAddress(new_target);
 }
 
 
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 149691b..4e19724 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -164,9 +164,7 @@
 
     if (FLAG_print_flow_graph ||
         (optimized && FLAG_print_flow_graph_optimized)) {
-      OS::Print("Before Optimizations\n");
-      FlowGraphPrinter printer(*flow_graph);
-      printer.PrintBlocks();
+      FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
     }
 
     if (optimized) {
@@ -183,6 +181,7 @@
       // TODO(srdjan): Moved before inlining until environment use list can
       // be used to detect when shift-left is outside the scope of bit-and.
       optimizer.TryOptimizeLeftShiftWithBitAndPattern();
+      DEBUG_ASSERT(flow_graph->VerifyUseLists());
 
       // Inlining (mutates the flow graph)
       if (FLAG_use_inlining) {
@@ -217,6 +216,13 @@
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
       }
 
+      // Propagate types and eliminate even more type tests.
+      if (FLAG_propagate_types) {
+        FlowGraphTypePropagator propagator(flow_graph);
+        propagator.Propagate();
+        DEBUG_ASSERT(flow_graph->VerifyUseLists());
+      }
+
       // Unbox doubles. Performed after constant propagation to minimize
       // interference from phis merging double values and tagged
       // values comming from dead paths.
@@ -236,7 +242,8 @@
       if (FLAG_loop_invariant_code_motion &&
           (parsed_function.function().deoptimization_counter() <
            (FLAG_deoptimization_counter_threshold - 1))) {
-        LICM::Optimize(flow_graph);
+        LICM licm(flow_graph);
+        licm.Optimize();
         DEBUG_ASSERT(flow_graph->VerifyUseLists());
       }
 
@@ -257,9 +264,7 @@
       allocator.AllocateRegisters();
 
       if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
-        OS::Print("After Optimizations:\n");
-        FlowGraphPrinter printer(*flow_graph);
-        printer.PrintBlocks();
+        FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph);
       }
     }
 
@@ -513,7 +518,9 @@
       DisassembleCode(function, optimized);
     } else if (FLAG_disassemble_optimized && optimized) {
       // TODO(fschneider): Print unoptimized code along with the optimized code.
+      OS::Print("*** BEGIN CODE\n");
       DisassembleCode(function, true);
+      OS::Print("*** END CODE\n");
     }
 
     isolate->set_long_jump_base(base);
@@ -550,6 +557,9 @@
   if (setjmp(*jump.Set()) == 0) {
     // Non-optimized code generator.
     CompileParsedFunctionHelper(parsed_function, false);
+    if (FLAG_disassemble) {
+      DisassembleCode(parsed_function.function(), false);
+    }
     isolate->set_long_jump_base(base);
     return Error::null();
   } else {
@@ -640,7 +650,7 @@
     CompileParsedFunctionHelper(*parsed_function, false);
 
     const Object& result = Object::Handle(
-        DartEntry::InvokeStatic(func, Object::empty_array()));
+        DartEntry::InvokeFunction(func, Object::empty_array()));
     isolate->set_long_jump_base(base);
     return result.raw();
   } else {
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 1ba6550..0a0c928 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -16,6 +16,7 @@
 
 
 enum Register {
+  kFirstFreeCpuRegister = 0,
   R0  =  0,
   R1  =  1,
   R2  =  2,
@@ -25,6 +26,7 @@
   R6  =  6,
   R7  =  7,
   R8  =  8,
+  kLastFreeCpuRegister = 8,
   R9  =  9,
   R10 = 10,
   R11 = 11,
@@ -132,11 +134,11 @@
 
 
 // Register aliases.
-const Register TMP = kNoRegister;  // No scratch register used by assembler.
+const Register TMP = IP;  // Used as scratch register by assembler.
 const Register CTX = R9;  // Caches current context in generated code.
 const Register PP = R10;  // Caches object pool pointer in generated code.
-const Register SPREG = SP;
-const Register FPREG = FP;
+const Register SPREG = SP;  // Stack pointer register.
+const Register FPREG = FP;  // Frame pointer register.
 
 
 // Exception object is passed in this register to the catch handlers when an
@@ -146,13 +148,32 @@
 
 // List of registers used in load/store multiple.
 typedef uint16_t RegList;
-const RegList kAllCoreRegistersList = 0xFFFF;
+const RegList kAllCpuRegistersList = 0xFFFF;
 
 
-// C++ ABI call registers
-const int kAbiRegisterCount = 4;
-const Register kAbiRegisters[kAbiRegisterCount] = { R0, R1, R2, R3 };
-const RegList kAbiRegisterList = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3);
+// C++ ABI call registers.
+const RegList kAbiArgumentCpuRegs =
+    (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3);
+const RegList kAbiPreservedCpuRegs =
+    (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) |
+    (1 << R8) | (1 << R9) | (1 << R10);
+const int kAbiPreservedCpuRegCount = 7;
+const DRegister kAbiFirstPreservedFpuReg = D8;
+const DRegister kAbiLastPreservedFpuReg =
+    static_cast<DRegister>(kNumberOfDRegisters - 1);
+
+// CPU registers available to Dart allocator.
+const RegList kDartAvailableCpuRegs =
+    (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) |
+    (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8);
+
+// Registers available to Dart that are not preserved by runtime calls.
+const RegList kDartVolatileCpuRegs =
+    kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
+const int kDartVolatileCpuRegCount = 4;
+const DRegister kDartFirstVolatileFpuReg = D0;
+const DRegister kDartLastVolatileFpuReg = D7;
+const int kDartVolatileFpuRegCount = 8;
 
 
 // Values for the condition field as defined in section A3.2.
@@ -431,12 +452,12 @@
 
   // Test for Supervisor Call instruction.
   inline bool IsSvc() const {
-    return ((InstructionBits() & 0xff000000) == 0xef000000);
+    return ((InstructionBits() & 0x0f000000) == 0x0f000000);
   }
 
   // Test for Breakpoint instruction.
   inline bool IsBkpt() const {
-    return ((InstructionBits() & 0xfff000f0) == 0xe1200070);
+    return ((InstructionBits() & 0x0ff000f0) == 0x01200070);
   }
 
   // VFP register fields.
@@ -483,6 +504,14 @@
     return ((Bits(20, 5) & 0x12) == 0x10) && (Bits(9, 3) == 5);
   }
 
+  // Test for VFP multiple load and store instructions of type 6.
+  inline bool IsVFPMultipleLoadStore() const {
+    ASSERT(ConditionField() != kSpecialCondition);
+    ASSERT(TypeField() == 6);
+    int32_t puw = (PUField() << 1) | Bit(21);  // don't care about D bit
+    return (Bits(9, 3) == 5) && ((puw == 2) || (puw == 3) || (puw == 5));
+  }
+
   // Special accessors that test for existence of a value.
   inline bool HasS()    const { return SField() == 1; }
   inline bool HasB()    const { return BField() == 1; }
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 467cdac..ad3f3c6 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -10,6 +10,7 @@
 namespace dart {
 
 enum Register {
+  kFirstFreeCpuRegister = 0,
   EAX = 0,
   ECX = 1,
   EDX = 2,
@@ -18,8 +19,8 @@
   EBP = 5,
   ESI = 6,
   EDI = 7,
+  kLastFreeCpuRegister = 7,
   kNumberOfCpuRegisters = 8,
-  kFirstByteUnsafeRegister = 4,
   kNoRegister = -1  // Signals an illegal register.
 };
 
@@ -59,9 +60,10 @@
 
 // Register aliases.
 const Register TMP = kNoRegister;  // No scratch register used by assembler.
-const Register CTX = ESI;          // Caches current context in generated code.
-const Register SPREG = ESP;
-const Register FPREG = EBP;
+const Register CTX = ESI;  // Caches current context in generated code.
+const Register PP = kNoRegister;  // No object pool pointer.
+const Register SPREG = ESP;  // Stack pointer register.
+const Register FPREG = EBP;  // Frame pointer register.
 
 // Exception object is passed in this register to the catch handlers when an
 // exception is thrown.
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index 6ff56ba..ea670bc 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -10,6 +10,7 @@
 enum Register {
   ZR =  0,
   AT =  1,
+  kFirstFreeCpuRegister = 2,
   V0 =  2,
   V1 =  3,
   A0 =  4,
@@ -34,6 +35,7 @@
   S7 = 23,
   T8 = 24,
   T9 = 25,
+  kLastFreeCpuRegister = 25,
   K0 = 26,
   K1 = 27,
   GP = 28,
@@ -91,10 +93,11 @@
 
 
 // Register aliases.
-const Register TMP = AT;
-const Register CTX = S7;  // Caches current context in generated code.
-const Register SPREG = SP;
-const Register FPREG = FP;
+const Register TMP = AT;  // Used as scratch register by assembler.
+const Register CTX = S6;  // Caches current context in generated code.
+const Register PP = S7;  // Caches object pool pointer in generated code.
+const Register SPREG = SP;  // Stack pointer register.
+const Register FPREG = FP;  // Frame pointer register.
 
 
 // Values for the condition field.  // UNIMPLEMENTED.
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 31b00b1..38a8793 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -8,6 +8,7 @@
 namespace dart {
 
 enum Register {
+  kFirstFreeCpuRegister = 0,
   RAX = 0,
   RCX = 1,
   RDX = 2,
@@ -24,6 +25,7 @@
   R13 = 13,
   R14 = 14,
   R15 = 15,
+  kLastFreeCpuRegister = 15,
   kNumberOfCpuRegisters = 16,
   kNoRegister = -1  // Signals an illegal register.
 };
@@ -83,8 +85,9 @@
 // Register aliases.
 const Register TMP = R11;  // Used as scratch register by the assembler.
 const Register CTX = R15;  // Caches current context in generated code.
-const Register SPREG = RSP;
-const Register FPREG = RBP;
+const Register PP = kNoRegister;  // No object pool pointer.
+const Register SPREG = RSP;  // Stack pointer register.
+const Register FPREG = RBP;  // Frame pointer register.
 
 // Exception object is passed in this register to the catch handlers when an
 // exception is thrown.
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index f4a9fa8..d8ba637 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1131,7 +1131,7 @@
   ASSERT(!function.IsNull());
   const Array& args = Array::Handle(isolate, Array::New(kNumArguments));
   args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id)));
-  return Api::NewHandle(isolate, DartEntry::InvokeStatic(function, args));
+  return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
 }
 
 
@@ -1924,7 +1924,7 @@
   const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
   args.SetAt(0, instance);  // Set up the receiver as the first argument.
   const Object& retval =
-    Object::Handle(isolate, DartEntry::InvokeDynamic(function, args));
+    Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
   if (retval.IsSmi()) {
     *len = Smi::Cast(retval).Value();
     return Api::Success(isolate);
@@ -1989,8 +1989,8 @@
         const Integer& indexobj = Integer::Handle(isolate, Integer::New(index));
         args.SetAt(0, instance);
         args.SetAt(1, indexobj);
-        return Api::NewHandle(isolate, DartEntry::InvokeDynamic(function,
-                                                                args));
+        return Api::NewHandle(isolate, DartEntry::InvokeFunction(function,
+                                                                 args));
       }
     }
     return Api::NewError("Object does not implement the 'List' interface");
@@ -2051,8 +2051,8 @@
         args.SetAt(0, instance);
         args.SetAt(1, index_obj);
         args.SetAt(2, value_obj);
-        return Api::NewHandle(isolate, DartEntry::InvokeDynamic(function,
-                                                                args));
+        return Api::NewHandle(isolate, DartEntry::InvokeFunction(function,
+                                                                 args));
       }
     }
     return Api::NewError("Object does not implement the 'List' interface");
@@ -2110,7 +2110,7 @@
   args.SetAt(1,
              Smi::Handle(isolate, Smi::New(Function::kCtorPhaseAll)));
   args.SetAt(2, String::Handle(String::New(exception_message)));
-  result = DartEntry::InvokeStatic(constructor, args);
+  result = DartEntry::InvokeFunction(constructor, args);
   if (result.IsError()) return result.raw();
   ASSERT(result.IsNull());
 
@@ -2211,7 +2211,7 @@
         for (int i = 0; i < length; i++) {
           intobj = Integer::New(offset + i);
           args.SetAt(1, intobj);
-          result = DartEntry::InvokeDynamic(function, args);
+          result = DartEntry::InvokeFunction(function, args);
           if (result.IsError()) {
             return Api::NewHandle(isolate, result.raw());
           }
@@ -2306,7 +2306,7 @@
           args.SetAt(1, indexobj);
           args.SetAt(2, valueobj);
           const Object& result = Object::Handle(
-              isolate, DartEntry::InvokeDynamic(function, args));
+              isolate, DartEntry::InvokeFunction(function, args));
           if (result.IsError()) {
             return Api::NewHandle(isolate, result.raw());
           }
@@ -2664,7 +2664,7 @@
     args.SetAt(i + 1, obj);
   }
   // Now try to invoke the closure.
-  return Api::NewHandle(isolate, DartEntry::InvokeClosure(closure_obj, args));
+  return Api::NewHandle(isolate, DartEntry::InvokeClosure(args));
 }
 
 
@@ -3570,7 +3570,7 @@
   }
 
   // Invoke the constructor and return the new object.
-  result = DartEntry::InvokeStatic(constructor, args);
+  result = DartEntry::InvokeFunction(constructor, args);
   if (result.IsError()) {
     return Api::NewHandle(isolate, result.raw());
   }
@@ -3644,7 +3644,7 @@
                            function_name.ToCString());
     }
     args.SetAt(0, instance);
-    return Api::NewHandle(isolate, DartEntry::InvokeDynamic(function, args));
+    return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
 
   } else if (obj.IsClass()) {
     // Finalize all classes.
@@ -3668,7 +3668,7 @@
                            cls_name.ToCString(),
                            function_name.ToCString());
     }
-    return Api::NewHandle(isolate, DartEntry::InvokeStatic(function, args));
+    return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
 
   } else if (obj.IsLibrary()) {
     // Check whether class finalization is needed.
@@ -3709,7 +3709,7 @@
                            function_name.ToCString(),
                            error_message.ToCString());
     }
-    return Api::NewHandle(isolate, DartEntry::InvokeStatic(function, args));
+    return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
 
   } else {
     return Api::NewError(
@@ -3773,7 +3773,7 @@
     const int kNumArgs = 1;
     const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
     args.SetAt(0, instance);
-    return Api::NewHandle(isolate, DartEntry::InvokeDynamic(getter, args));
+    return Api::NewHandle(isolate, DartEntry::InvokeFunction(getter, args));
 
   } else if (obj.IsClass()) {
     // Finalize all classes.
@@ -3794,7 +3794,7 @@
     if (!getter.IsNull()) {
       // Invoke the getter and return the result.
       return Api::NewHandle(
-          isolate, DartEntry::InvokeStatic(getter, Object::empty_array()));
+          isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
     } else if (!field.IsNull()) {
       return Api::NewHandle(isolate, field.value());
     } else {
@@ -3826,7 +3826,7 @@
     if (!getter.IsNull()) {
       // Invoke the getter and return the result.
       return Api::NewHandle(
-          isolate, DartEntry::InvokeStatic(getter, Object::empty_array()));
+          isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
     } else if (!field.IsNull()) {
       return Api::NewHandle(isolate, field.value());
     } else {
@@ -3901,7 +3901,7 @@
     const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
     args.SetAt(0, instance);
     args.SetAt(1, value_instance);
-    return Api::NewHandle(isolate, DartEntry::InvokeDynamic(setter, args));
+    return Api::NewHandle(isolate, DartEntry::InvokeFunction(setter, args));
 
   } else if (obj.IsClass()) {
     // To access a static field we may need to use the Field or the
@@ -3920,7 +3920,7 @@
       const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
       args.SetAt(0, value_instance);
       const Object& result =
-          Object::Handle(isolate, DartEntry::InvokeStatic(setter, args));
+          Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
       if (result.IsError()) {
         return Api::NewHandle(isolate, result.raw());
       } else {
@@ -3957,7 +3957,7 @@
       const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
       args.SetAt(0, value_instance);
       const Object& result =
-          Object::Handle(isolate, DartEntry::InvokeStatic(setter, args));
+          Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
       if (result.IsError()) {
         return Api::NewHandle(isolate, result.raw());
       } else {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index ea91a9e..77860db 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -7410,7 +7410,7 @@
       "  var result = 0;\n"
       "  for (var i = 0; i < s.length; i++) {\n"
       "    if (b && i == 0) A.change_str(str);\n"
-      "    result += s.charCodeAt(i);"
+      "    result += s.codeUnitAt(i);"
       "  }\n"
       "  return result;\n"
       "}\n"
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 66ae155..c6b5dc3 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -8,6 +8,7 @@
 #include "vm/compiler.h"
 #include "vm/object_store.h"
 #include "vm/resolver.h"
+#include "vm/simulator.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 
@@ -17,17 +18,28 @@
 RawArray* ArgumentsDescriptor::cached_args_descriptors_[kCachedDescriptorCount];
 
 
-RawObject* DartEntry::InvokeDynamic(const Function& function,
-                                    const Array& arguments) {
-  const Array& arg_desc =
+RawObject* DartEntry::InvokeFunction(const Function& function,
+                                     const Array& arguments) {
+  const Array& arguments_descriptor =
       Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
-  return InvokeDynamic(function, arguments, arg_desc);
+  return InvokeFunction(function, arguments, arguments_descriptor);
 }
 
 
-RawObject* DartEntry::InvokeDynamic(const Function& function,
-                                    const Array& arguments,
-                                    const Array& arguments_descriptor) {
+RawObject* DartEntry::InvokeFunction(const Function& function,
+                                     const Array& arguments,
+                                     const Array& arguments_descriptor) {
+  const Context& context =
+      Context::ZoneHandle(Isolate::Current()->object_store()->empty_context());
+  ASSERT(context.isolate() == Isolate::Current());
+  return InvokeFunction(function, arguments, arguments_descriptor, context);
+}
+
+
+RawObject* DartEntry::InvokeFunction(const Function& function,
+                                     const Array& arguments,
+                                     const Array& arguments_descriptor,
+                                     const Context& context) {
   // Get the entrypoint corresponding to the function specified, this
   // will result in a compilation of the function if it is not already
   // compiled.
@@ -37,72 +49,40 @@
       return error.raw();
     }
   }
-
   // Now Call the invoke stub which will invoke the dart function.
   invokestub entrypoint = reinterpret_cast<invokestub>(
       StubCode::InvokeDartCodeEntryPoint());
-  const Context& context =
-      Context::ZoneHandle(Isolate::Current()->object_store()->empty_context());
-  ASSERT(context.isolate() == Isolate::Current());
   const Code& code = Code::Handle(function.CurrentCode());
   ASSERT(!code.IsNull());
   ASSERT(Isolate::Current()->no_callback_scope_depth() == 0);
-  return entrypoint(code.EntryPoint(),
-                    arguments_descriptor,
-                    arguments,
-                    context);
+#ifdef USING_SIMULATOR
+    return bit_copy<RawObject*, int64_t>(Simulator::Current()->Call(
+        reinterpret_cast<int32_t>(entrypoint),
+        static_cast<int32_t>(code.EntryPoint()),
+        reinterpret_cast<int32_t>(&arguments_descriptor),
+        reinterpret_cast<int32_t>(&arguments),
+        reinterpret_cast<int32_t>(&context),
+        0));
+#else
+    return entrypoint(code.EntryPoint(),
+                      arguments_descriptor,
+                      arguments,
+                      context);
+#endif
 }
 
 
-RawObject* DartEntry::InvokeStatic(const Function& function,
-                                   const Array& arguments) {
+RawObject* DartEntry::InvokeClosure(const Array& arguments) {
   const Array& arguments_descriptor =
       Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
-  return InvokeStatic(function, arguments, arguments_descriptor);
+  return InvokeClosure(arguments, arguments_descriptor);
 }
 
 
-RawObject* DartEntry::InvokeStatic(const Function& function,
-                                   const Array& arguments,
-                                   const Array& arguments_descriptor) {
-  // Get the entrypoint corresponding to the function specified, this
-  // will result in a compilation of the function if it is not already
-  // compiled.
-  ASSERT(!function.IsNull());
-  if (!function.HasCode()) {
-    const Error& error = Error::Handle(Compiler::CompileFunction(function));
-    if (!error.IsNull()) {
-      return error.raw();
-    }
-  }
-  // Now Call the invoke stub which will invoke the dart function.
-  invokestub entrypoint = reinterpret_cast<invokestub>(
-      StubCode::InvokeDartCodeEntryPoint());
-  const Context& context =
-      Context::ZoneHandle(Isolate::Current()->object_store()->empty_context());
-  ASSERT(context.isolate() == Isolate::Current());
-  const Code& code = Code::Handle(function.CurrentCode());
-  ASSERT(!code.IsNull());
-  ASSERT(Isolate::Current()->no_callback_scope_depth() == 0);
-  return entrypoint(code.EntryPoint(),
-                    arguments_descriptor,
-                    arguments,
-                    context);
-}
-
-
-RawObject* DartEntry::InvokeClosure(const Instance& closure,
-                                    const Array& arguments) {
-  const Array& arguments_descriptor =
-      Array::Handle(ArgumentsDescriptor::New(arguments.Length()));
-  return InvokeClosure(closure, arguments, arguments_descriptor);
-}
-
-
-RawObject* DartEntry::InvokeClosure(const Instance& instance,
-                                    const Array& arguments,
+RawObject* DartEntry::InvokeClosure(const Array& arguments,
                                     const Array& arguments_descriptor) {
-  ASSERT(instance.raw() == arguments.At(0));
+  Instance& instance = Instance::Handle();
+  instance ^= arguments.At(0);
   // Get the entrypoint corresponding to the closure function or to the call
   // method of the instance. This will result in a compilation of the function
   // if it is not already compiled.
@@ -114,26 +94,9 @@
     if (function.AreValidArgumentCounts(args_desc.Count(),
                                         args_desc.NamedCount(),
                                         NULL)) {
-      if (!function.HasCode()) {
-        const Error& error = Error::Handle(Compiler::CompileFunction(function));
-        if (!error.IsNull()) {
-          return error.raw();
-        }
-      }
-      // Now call the invoke stub which will invoke the closure function or
-      // 'call' function.
       // The closure or non-closure object (receiver) is passed as implicit
       // first argument. It is already included in the arguments array.
-      invokestub entrypoint = reinterpret_cast<invokestub>(
-          StubCode::InvokeDartCodeEntryPoint());
-      ASSERT(context.isolate() == Isolate::Current());
-      const Code& code = Code::Handle(function.CurrentCode());
-      ASSERT(!code.IsNull());
-      ASSERT(Isolate::Current()->no_callback_scope_depth() == 0);
-      return entrypoint(code.EntryPoint(),
-                        arguments_descriptor,
-                        arguments,
-                        context);
+      return InvokeFunction(function, arguments, arguments_descriptor, context);
     }
   }
   // There is no compatible 'call' method, so invoke noSuchMethod.
@@ -169,7 +132,7 @@
   allocation_args.SetAt(1, arguments_descriptor);
   allocation_args.SetAt(2, arguments);
   const Object& invocation_mirror = Object::Handle(
-      InvokeStatic(allocation_function, allocation_args));
+      InvokeFunction(allocation_function, allocation_args));
 
   // Now use the invocation mirror object and invoke NoSuchMethod.
   const int kNumArguments = 2;
@@ -183,7 +146,7 @@
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, receiver);
   args.SetAt(1, invocation_mirror);
-  return InvokeDynamic(function, args);
+  return InvokeFunction(function, args);
 }
 
 
@@ -350,7 +313,8 @@
       Function::Handle(cls.LookupConstructorAllowPrivate(function_name));
   ASSERT(!constructor.IsNull());
   const Object& retval =
-    Object::Handle(DartEntry::InvokeStatic(constructor, constructor_arguments));
+    Object::Handle(DartEntry::InvokeFunction(constructor,
+                                             constructor_arguments));
   ASSERT(retval.IsNull() || retval.IsError());
   if (retval.IsError()) {
     return retval.raw();
@@ -370,8 +334,8 @@
   ASSERT(!function.IsNull());
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, receiver);
-  const Object& result = Object::Handle(DartEntry::InvokeDynamic(function,
-                                                                 args));
+  const Object& result = Object::Handle(DartEntry::InvokeFunction(function,
+                                                                  args));
   ASSERT(result.IsInstance() || result.IsError());
   return result.raw();
 }
@@ -391,8 +355,8 @@
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, left);
   args.SetAt(1, right);
-  const Object& result = Object::Handle(DartEntry::InvokeDynamic(function,
-                                                                 args));
+  const Object& result = Object::Handle(DartEntry::InvokeFunction(function,
+                                                                  args));
   ASSERT(result.IsInstance() || result.IsError());
   return result.raw();
 }
@@ -422,7 +386,7 @@
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, Integer::Handle(Integer::New(port_id)));
   const Object& result =
-      Object::Handle(DartEntry::InvokeStatic(function, args));
+      Object::Handle(DartEntry::InvokeFunction(function, args));
   return result.raw();
 }
 
@@ -455,7 +419,7 @@
   args.SetAt(1, Integer::Handle(isolate, Integer::New(reply_port_id)));
   args.SetAt(2, message);
   const Object& result =
-      Object::Handle(isolate, DartEntry::InvokeStatic(function, args));
+      Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
   ASSERT(result.IsNull() || result.IsError());
   return result.raw();
 }
@@ -478,7 +442,7 @@
                               Resolver::kIsQualified));
   const Array& args = Array::Handle(Array::New(kNumArguments));
   args.SetAt(0, Integer::Handle(Integer::New(port_id)));
-  return DartEntry::InvokeStatic(function, args);
+  return DartEntry::InvokeFunction(function, args);
 }
 
 
@@ -496,8 +460,8 @@
   args.SetAt(0, map);
   args.SetAt(1, key);
   args.SetAt(2, value);
-  const Object& result = Object::Handle(DartEntry::InvokeDynamic(function,
-                                                                 args));
+  const Object& result = Object::Handle(DartEntry::InvokeFunction(function,
+                                                                  args));
   return result.raw();
 }
 
@@ -512,7 +476,7 @@
   ASSERT(!func.IsNull());
   const Array& args = Array::Handle(Array::New(1));
   args.SetAt(0, port);
-  return DartEntry::InvokeDynamic(func, args);
+  return DartEntry::InvokeFunction(func, args);
 }
 
 
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index e4c6d5c..aeab904 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -105,43 +105,37 @@
                                    const Array& arguments,
                                    const Context& context);
 
-  // Invokes the specified instance function on the receiver.
+  // Invokes the specified instance function or static function.
+  // The first argument of an instance function is the receiver.
   // On success, returns a RawInstance.  On failure, a RawError.
   // This is used when there are no named arguments in the call.
-  static RawObject* InvokeDynamic(const Function& function,
-                                  const Array& arguments);
+  static RawObject* InvokeFunction(const Function& function,
+                                   const Array& arguments);
 
-  // Invokes the specified instance function on the receiver.
+  // Invokes the specified instance or static function.
   // On success, returns a RawInstance.  On failure, a RawError.
-  static RawObject* InvokeDynamic(const Function& function,
-                                  const Array& arguments,
+  static RawObject* InvokeFunction(const Function& function,
+                                   const Array& arguments,
+                                   const Array& arguments_descriptor);
+
+  // Invokes the specified instance, static, or closure function.
+  // On success, returns a RawInstance.  On failure, a RawError.
+  static RawObject* InvokeFunction(const Function& function,
+                                   const Array& arguments,
+                                   const Array& arguments_descriptor,
+                                   const Context& context);
+
+  // Invokes the closure object given as the first argument.
+  // On success, returns a RawInstance.  On failure, a RawError.
+  // This is used when there are no named arguments in the call.
+  static RawObject* InvokeClosure(const Array& arguments);
+
+  // Invokes the closure object given as the first argument.
+  // On success, returns a RawInstance.  On failure, a RawError.
+  static RawObject* InvokeClosure(const Array& arguments,
                                   const Array& arguments_descriptor);
 
-  // Invoke the specified static function.
-  // On success, returns a RawInstance.  On failure, a RawError.
-  // This is used when there are no named arguments in the call.
-  static RawObject* InvokeStatic(const Function& function,
-                                 const Array& arguments);
-
-  // Invoke the specified static function.
-  // On success, returns a RawInstance.  On failure, a RawError.
-  static RawObject* InvokeStatic(const Function& function,
-                                 const Array& arguments,
-                                 const Array& arguments_descriptor);
-
-  // Invoke the specified closure object.
-  // On success, returns a RawInstance.  On failure, a RawError.
-  // This is used when there are no named arguments in the call.
-  static RawObject* InvokeClosure(const Instance& closure,
-                                  const Array& arguments);
-
-  // Invoke the specified closure object.
-  // On success, returns a RawInstance.  On failure, a RawError.
-  static RawObject* InvokeClosure(const Instance& closure,
-                                  const Array& arguments,
-                                  const Array& arguments_descriptor);
-
-  // Invoke the noSuchMethod instance function on the receiver.
+  // Invokes the noSuchMethod instance function on the receiver.
   // On success, returns a RawInstance.  On failure, a RawError.
   static RawObject* InvokeNoSuchMethod(const Instance& receiver,
                                        const String& target_name,
diff --git a/runtime/vm/dart_entry_test.cc b/runtime/vm/dart_entry_test.cc
index 65a629f..f067736 100644
--- a/runtime/vm/dart_entry_test.cc
+++ b/runtime/vm/dart_entry_test.cc
@@ -40,7 +40,7 @@
   EXPECT(CompilerTest::TestCompileFunction(function));
   EXPECT(function.HasCode());
   const Smi& retval = Smi::Handle(reinterpret_cast<RawSmi*>(
-      DartEntry::InvokeStatic(function, Object::empty_array())));
+      DartEntry::InvokeFunction(function, Object::empty_array())));
   EXPECT_EQ(Smi::New(42), retval.raw());
 }
 
@@ -66,7 +66,7 @@
   EXPECT(!function.IsNull());
   GrowableArray<const Object*> arguments;
   const Object& retval = Object::Handle(
-      DartEntry::InvokeStatic(function, Object::empty_array()));
+      DartEntry::InvokeFunction(function, Object::empty_array()));
   EXPECT(retval.IsError());
   EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
 }
@@ -99,7 +99,7 @@
   Function& constructor =
     Function::Handle(cls.LookupConstructor(constructor_name));
   ASSERT(!constructor.IsNull());
-  DartEntry::InvokeStatic(constructor, constructor_arguments);
+  DartEntry::InvokeFunction(constructor, constructor_arguments);
 
   // Call foo.
   String& name = String::Handle(String::New("foo"));
@@ -107,8 +107,8 @@
   EXPECT(!function.IsNull());
   const Array& args = Array::Handle(Array::New(1));
   args.SetAt(0, instance);
-  const Object& retval = Object::Handle(DartEntry::InvokeDynamic(function,
-                                                                 args));
+  const Object& retval = Object::Handle(DartEntry::InvokeFunction(function,
+                                                                  args));
   EXPECT(retval.IsError());
   EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
 }
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index d75d5c0..dd814b7 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -218,7 +218,7 @@
     WriteByte(static_cast<uint8_t>(v + kEndByteMarker));
   }
 
-  void WriteByte(uint8_t value) {
+  DART_FORCE_INLINE void WriteByte(uint8_t value) {
     if (current_ >= end_) {
       Resize(1);
     }
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 61a9f69..388db67 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -493,6 +493,9 @@
   if (var_info.kind == RawLocalVarDescriptors::kStackVar) {
     *value = GetLocalVarValue(var_info.index);
   } else {
+    // TODO(tball): enable context variables once problem with VariableAt() is
+    // fixed, where frame_ctx_level is sometimes off by 1 (issues 8593 and 8594)
+    /*
     ASSERT(var_info.kind == RawLocalVarDescriptors::kContextVar);
     ASSERT(!ctx_.IsNull());
     // The context level at the PC/token index of this activation frame.
@@ -513,7 +516,8 @@
       }
       ASSERT(!ctx.IsNull());
       *value = ctx.At(ctx_slot);
-    }
+    } */
+    *value = Symbols::New("<unknown>");
   }
 }
 
@@ -881,7 +885,7 @@
                                                         frame->fp(),
                                                         frame->sp(),
                                                         code);
-      if (get_saved_context) {
+      if (get_saved_context && !activation->code().is_optimized()) {
         ctx = activation->GetSavedContext();
       }
       activation->SetContext(ctx);
@@ -1223,7 +1227,7 @@
   if (setjmp(*jump.Set()) == 0) {
     const Array& args = Array::Handle(Array::New(1));
     args.SetAt(0, object);
-    result = DartEntry::InvokeDynamic(getter_func, args);
+    result = DartEntry::InvokeFunction(getter_func, args);
   } else {
     result = isolate_->object_store()->sticky_error();
   }
@@ -1260,7 +1264,7 @@
   bool saved_ignore_flag = ignore_breakpoints_;
   ignore_breakpoints_ = true;
   if (setjmp(*jump.Set()) == 0) {
-    result = DartEntry::InvokeStatic(getter_func, Object::empty_array());
+    result = DartEntry::InvokeFunction(getter_func, Object::empty_array());
   } else {
     result = isolate_->object_store()->sticky_error();
   }
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 4a10822..b096c82 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -751,4 +751,12 @@
   return Api::CastIsolate(isolate);
 }
 
+
+DART_EXPORT char* Dart_GetVmStatus(const char* request) {
+  if (strncmp(request, "/isolate/", 9) == 0) {
+    return Isolate::GetStatus(request);
+  }
+  return NULL;
+}
+
 }  // namespace dart
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index b4e862e..9e098cc 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -101,10 +101,11 @@
 
 
 // These register names are defined in a way to match the native disassembler
-// formatting. See for example the command "objdump -d <binary file>".
+// formatting, except for register aliases ctx (r9) and pp (r10).
+// See for example the command "objdump -d <binary file>".
 static const char* reg_names[kNumberOfCpuRegisters] = {
   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
-  "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
+  "r8", "ctx", "pp", "fp", "ip", "sp", "lr", "pc",
 };
 
 
@@ -296,6 +297,19 @@
       PrintSRegister(reg);
       return 2;
     }
+  } else if (format[1] == 'l') {
+    ASSERT(STRING_STARTS_WITH(format, "slist"));
+    int reg_count = instr->Bits(0, 8);
+    int start = instr->Bit(22) | (instr->Bits(12, 4) << 1);
+    Print("{");
+    for (int i = start; i < start + reg_count; i++) {
+      PrintSRegister(i);
+      if (i != start + reg_count - 1) {
+        Print(", ");
+      }
+    }
+    Print("}");
+    return 5;
   }
   UNREACHABLE();
   return -1;
@@ -316,6 +330,19 @@
     int reg = instr->DmField();
     PrintDRegister(reg);
     return 2;
+  } else if (format[1] == 'l') {
+    ASSERT(STRING_STARTS_WITH(format, "dlist"));
+    int reg_count = instr->Bits(0, 8) >> 1;
+    int start = (instr->Bit(22) << 4) | instr->Bits(12, 4);
+    Print("{");
+    for (int i = start; i < start + reg_count; i++) {
+      PrintDRegister(i);
+      if (i != start + reg_count - 1) {
+        Print(", ");
+      }
+    }
+    Print("}");
+    return 5;
   }
   UNREACHABLE();
   return -1;
@@ -555,6 +582,8 @@
         case 1: {
           if (instr->Bits(21, 2) == 0x3) {
             Format(instr, "clz'cond 'rd, 'rm");
+          } else if (instr->Bits(21, 2) == 0x1) {
+            Format(instr, "bx'cond 'rm");
           } else {
             Unknown(instr);
           }
@@ -571,7 +600,7 @@
         }
         case 7: {
           if (instr->Bits(21, 2) == 0x1) {
-            Format(instr, "bkpt #'imm12_4");
+            Format(instr, "bkpt'cond #'imm12_4");
           } else {
              // Format(instr, "smc'cond");
             Unknown(instr);  // Not used.
@@ -918,6 +947,20 @@
         }
       }
     }
+  } else if (instr->IsVFPMultipleLoadStore()) {
+    if (instr->HasL()) {  // vldm
+      if (instr->Bit(8)) {  // vldmd
+        Format(instr, "vldmd'cond'pu 'rn'w, 'dlist");
+      } else {  // vldms
+        Format(instr, "vldms'cond'pu 'rn'w, 'slist");
+      }
+    } else {  // vstm
+      if (instr->Bit(8)) {  // vstmd
+        Format(instr, "vstmd'cond'pu 'rn'w, 'dlist");
+      } else {  // vstms
+        Format(instr, "vstms'cond'pu 'rn'w, 'slist");
+      }
+    }
   } else {
     Unknown(instr);
   }
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index f6413ba..b05dd6d 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -26,6 +26,106 @@
 const char* Exceptions::kCastErrorDstName = "type cast";
 
 
+class StacktraceBuilder : public ValueObject {
+ public:
+  StacktraceBuilder() { }
+  virtual ~StacktraceBuilder() { }
+
+  virtual void AddFrame(const Function& func,
+                        const Code& code,
+                        const Smi& offset) = 0;
+};
+
+
+class RegularStacktraceBuilder : public StacktraceBuilder {
+ public:
+  RegularStacktraceBuilder()
+      : func_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
+        code_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
+        pc_offset_list_(
+            GrowableObjectArray::Handle(GrowableObjectArray::New())) { }
+  ~RegularStacktraceBuilder() { }
+
+  const GrowableObjectArray& func_list() const { return func_list_; }
+  const GrowableObjectArray& code_list() const { return code_list_; }
+  const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; }
+
+  virtual void AddFrame(const Function& func,
+                        const Code& code,
+                        const Smi& offset) {
+    func_list_.Add(func);
+    code_list_.Add(code);
+    pc_offset_list_.Add(offset);
+  }
+
+ private:
+  const GrowableObjectArray& func_list_;
+  const GrowableObjectArray& code_list_;
+  const GrowableObjectArray& pc_offset_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder);
+};
+
+
+class PreallocatedStacktraceBuilder : public StacktraceBuilder {
+ public:
+  explicit PreallocatedStacktraceBuilder(const Stacktrace& stacktrace)
+      : stacktrace_(stacktrace),
+        cur_index_(0) {
+    ASSERT(stacktrace_.raw() ==
+           Isolate::Current()->object_store()->preallocated_stack_trace());
+  }
+  ~PreallocatedStacktraceBuilder() { }
+
+  virtual void AddFrame(const Function& func,
+                        const Code& code,
+                        const Smi& offset);
+
+ private:
+  static const int kNumTopframes = 3;
+
+  const Stacktrace& stacktrace_;
+  intptr_t cur_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(PreallocatedStacktraceBuilder);
+};
+
+
+void PreallocatedStacktraceBuilder::AddFrame(const Function& func,
+                                             const Code& code,
+                                             const Smi& offset) {
+  if (cur_index_ >= Stacktrace::kPreallocatedStackdepth) {
+    // The number of frames is overflowing the preallocated stack trace object.
+    Function& frame_func = Function::Handle();
+    Code& frame_code = Code::Handle();
+    Smi& frame_offset = Smi::Handle();
+    intptr_t start = Stacktrace::kPreallocatedStackdepth - (kNumTopframes - 1);
+    intptr_t null_slot = start - 2;
+    // Add an empty slot to indicate the overflow so that the toString
+    // method can account for the overflow.
+    if (stacktrace_.FunctionAtFrame(null_slot) != Function::null()) {
+      stacktrace_.SetFunctionAtFrame(null_slot, frame_func);
+      stacktrace_.SetCodeAtFrame(null_slot, frame_code);
+    }
+    // Move frames one slot down so that we can accomadate the new frame.
+    for (intptr_t i = start; i < Stacktrace::kPreallocatedStackdepth; i++) {
+      intptr_t prev = (i - 1);
+      frame_func = stacktrace_.FunctionAtFrame(i);
+      frame_code = stacktrace_.CodeAtFrame(i);
+      frame_offset = stacktrace_.PcOffsetAtFrame(i);
+      stacktrace_.SetFunctionAtFrame(prev, frame_func);
+      stacktrace_.SetCodeAtFrame(prev, frame_code);
+      stacktrace_.SetPcOffsetAtFrame(prev, frame_offset);
+    }
+    cur_index_ = (Stacktrace::kPreallocatedStackdepth - 1);
+  }
+  stacktrace_.SetFunctionAtFrame(cur_index_, func);
+  stacktrace_.SetCodeAtFrame(cur_index_, code);
+  stacktrace_.SetPcOffsetAtFrame(cur_index_, offset);
+  cur_index_ += 1;
+}
+
+
 static bool ShouldShowFunction(const Function& function) {
   if (FLAG_verbose_stacktrace) {
     return true;
@@ -40,9 +140,7 @@
 static bool FindExceptionHandler(uword* handler_pc,
                                  uword* handler_sp,
                                  uword* handler_fp,
-                                 const GrowableObjectArray& func_list,
-                                 const GrowableObjectArray& code_list,
-                                 const GrowableObjectArray& pc_offset_list) {
+                                 StacktraceBuilder* builder) {
   StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
   StackFrame* frame = frames.NextFrame();
   ASSERT(frame != NULL);  // We expect to find a dart invocation frame.
@@ -64,18 +162,14 @@
           ASSERT(pc < (code.EntryPoint() + code.Size()));
           if (ShouldShowFunction(func)) {
             offset = Smi::New(pc - code.EntryPoint());
-            func_list.Add(func);
-            code_list.Add(code);
-            pc_offset_list.Add(offset);
+            builder->AddFrame(func, code, offset);
           }
         }
       } else {
         offset = Smi::New(frame->pc() - code.EntryPoint());
         func = code.function();
         if (ShouldShowFunction(func)) {
-          func_list.Add(func);
-          code_list.Add(code);
-          pc_offset_list.Add(offset);
+          builder->AddFrame(func, code, offset);
         }
       }
       if (frame->FindExceptionHandler(handler_pc)) {
@@ -171,46 +265,74 @@
 
 static void ThrowExceptionHelper(const Instance& incoming_exception,
                                  const Instance& existing_stacktrace) {
-  Instance& exception = Instance::Handle(incoming_exception.raw());
+  bool use_preallocated_stacktrace = false;
+  Isolate* isolate = Isolate::Current();
+  Instance& exception = Instance::Handle(isolate, incoming_exception.raw());
   if (exception.IsNull()) {
     exception ^= Exceptions::Create(Exceptions::kNullThrown,
                                     Object::empty_array());
+  } else if (exception.raw() == isolate->object_store()->out_of_memory() ||
+             exception.raw() == isolate->object_store()->stack_overflow()) {
+    use_preallocated_stacktrace = true;
   }
   uword handler_pc = 0;
   uword handler_sp = 0;
   uword handler_fp = 0;
-  const GrowableObjectArray& func_list =
-      GrowableObjectArray::Handle(GrowableObjectArray::New());
-  const GrowableObjectArray& code_list =
-      GrowableObjectArray::Handle(GrowableObjectArray::New());
-  const GrowableObjectArray& pc_offset_list =
-      GrowableObjectArray::Handle(GrowableObjectArray::New());
-  bool handler_exists = FindExceptionHandler(&handler_pc,
-                                             &handler_sp,
-                                             &handler_fp,
-                                             func_list,
-                                             code_list,
-                                             pc_offset_list);
+  Stacktrace& stacktrace = Stacktrace::Handle(isolate);
+  bool handler_exists = false;
+  if (use_preallocated_stacktrace) {
+    stacktrace ^= isolate->object_store()->preallocated_stack_trace();
+    PreallocatedStacktraceBuilder frame_builder(stacktrace);
+    handler_exists = FindExceptionHandler(&handler_pc,
+                                          &handler_sp,
+                                          &handler_fp,
+                                          &frame_builder);
+  } else {
+    RegularStacktraceBuilder frame_builder;
+    handler_exists = FindExceptionHandler(&handler_pc,
+                                          &handler_sp,
+                                          &handler_fp,
+                                          &frame_builder);
+    // TODO(5411263): At some point we can optimize by figuring out if a
+    // stack trace is needed based on whether the catch code specifies a
+    // stack trace object or there is a rethrow in the catch clause.
+    if (frame_builder.pc_offset_list().Length() != 0) {
+      // Create arrays for function, code and pc_offset triplet for each frame.
+      const Array& func_array =
+          Array::Handle(isolate, Array::MakeArray(frame_builder.func_list()));
+      const Array& code_array =
+          Array::Handle(isolate, Array::MakeArray(frame_builder.code_list()));
+      const Array& pc_offset_array =
+          Array::Handle(isolate,
+                        Array::MakeArray(frame_builder.pc_offset_list()));
+      if (existing_stacktrace.IsNull()) {
+        stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
+      } else {
+        stacktrace ^= existing_stacktrace.raw();
+        stacktrace.Append(func_array, code_array, pc_offset_array);
+        // Since we are re throwing and appending to the existing stack trace
+        // we clear out the catch trace collected in the existing stack trace
+        // as that trace will not be valid anymore.
+        stacktrace.SetCatchStacktrace(Object::empty_array(),
+                                      Object::empty_array(),
+                                      Object::empty_array());
+      }
+    } else {
+      stacktrace ^= existing_stacktrace.raw();
+      // Since we are re throwing and appending to the existing stack trace
+      // we clear out the catch trace collected in the existing stack trace
+      // as that trace will not be valid anymore.
+      stacktrace.SetCatchStacktrace(Object::empty_array(),
+                                    Object::empty_array(),
+                                    Object::empty_array());
+    }
+  }
   // We expect to find a handler_pc, if the exception is unhandled
   // then we expect to at least have the dart entry frame on the
   // stack as Exceptions::Throw should happen only after a dart
   // invocation has been done.
   ASSERT(handler_pc != 0);
 
-  // TODO(5411263): At some point we can optimize by figuring out if a
-  // stack trace is needed based on whether the catch code specifies a
-  // stack trace object or there is a rethrow in the catch clause.
-  Stacktrace& stacktrace = Stacktrace::Handle();
-  if (pc_offset_list.Length() != 0) {
-    if (existing_stacktrace.IsNull()) {
-      stacktrace = Stacktrace::New(func_list, code_list, pc_offset_list);
-    } else {
-      stacktrace ^= existing_stacktrace.raw();
-      stacktrace.Append(func_list, code_list, pc_offset_list);
-    }
-  } else {
-    stacktrace ^= existing_stacktrace.raw();
-  }
   if (FLAG_print_stacktrace_at_throw) {
     OS::Print("Exception '%s' thrown:\n", exception.ToCString());
     OS::Print("%s\n", stacktrace.ToCString());
@@ -224,7 +346,6 @@
                            stacktrace);
   } else {
     if (FLAG_heap_profile_out_of_memory) {
-      Isolate* isolate = Isolate::Current();
       if (exception.raw() == isolate->object_store()->out_of_memory()) {
         isolate->heap()->ProfileToFile("out-of-memory");
       }
@@ -466,10 +587,6 @@
       library = Library::CoreLibrary();
       class_name = &Symbols::NullThrownError();
       break;
-    case kIllegalJSRegExp:
-      library = Library::CoreLibrary();
-      class_name = &Symbols::IllegalJSRegExpException();
-      break;
     case kIsolateSpawn:
       library = Library::IsolateLibrary();
       class_name = &Symbols::IsolateSpawnException();
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 9582034..6015369 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -58,7 +58,6 @@
     kOutOfMemory,
     kInternalError,
     kNullThrown,
-    kIllegalJSRegExp,
     kIsolateSpawn,
     kIsolateUnhandledException
   };
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index e7598ac..fe14079 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -72,19 +72,13 @@
                             Instruction* instr,
                             Environment* env,
                             Definition::UseKind use_kind) {
-  for (intptr_t i = instr->InputCount() - 1; i >= 0; --i) {
-    Value* input = instr->InputAt(i);
-    input->definition()->AddInputUse(input);
-    input->set_instruction(instr);
-    input->set_use_index(i);
-  }
-  ASSERT(instr->env() == NULL);
-  if (env != NULL) env->DeepCopyTo(instr);
   if (use_kind == Definition::kValue) {
     ASSERT(instr->IsDefinition());
     instr->AsDefinition()->set_ssa_temp_index(alloc_ssa_temp_index());
   }
   instr->InsertAfter(prev);
+  ASSERT(instr->env() == NULL);
+  if (env != NULL) env->DeepCopyTo(instr);
 }
 
 
@@ -151,18 +145,18 @@
   }
   Definition* defn = instr->AsDefinition();
   if (defn != NULL) {
+    // Used definitions must have an SSA name.  We use the name to index
+    // into bit vectors during analyses.  Some definitions without SSA names
+    // (e.g., PushArgument) have environment uses.
+    ASSERT((defn->input_use_list() == NULL) || defn->HasSSATemp());
     Value* prev = NULL;
     Value* curr = defn->input_use_list();
     while (curr != NULL) {
       ASSERT(prev == curr->previous_use());
       ASSERT(defn == curr->definition());
       Instruction* instr = curr->instruction();
-      // The instruction should not be removed from the graph.  Removed
-      // instructions have a NULL previous link.  Phis are not removed until
-      // register allocation.  Comparisons used only in a branch will have a
-      // NULL previous link though they are still in the graph.
-      ASSERT(instr->IsPhi() ||
-             (instr->IsDefinition() && instr->AsDefinition()->IsComparison()) ||
+      // The instruction should not be removed from the graph.
+      ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) ||
              (instr->previous() != NULL));
       ASSERT(curr == instr->InputAt(curr->use_index()));
       prev = curr;
@@ -176,8 +170,7 @@
       ASSERT(defn == curr->definition());
       Instruction* instr = curr->instruction();
       ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index()));
-      ASSERT(instr->IsPhi() ||
-             (instr->IsDefinition() && instr->AsDefinition()->IsComparison()) ||
+      ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) ||
              (instr->previous() != NULL));
       prev = curr;
       curr = curr->next_use();
@@ -196,10 +189,11 @@
   for (intptr_t i = 0; i < preorder_.length(); ++i) {
     BlockEntryInstr* entry = preorder_[i];
     JoinEntryInstr* join = entry->AsJoinEntry();
-    if (join != NULL && join->phis() != NULL) {
-      for (intptr_t i = 0; i < join->phis()->length(); ++i) {
-        PhiInstr* phi = (*join->phis())[i];
-        if (phi != NULL) VerifyUseListsInInstruction(phi);
+    if (join != NULL) {
+      for (PhiIterator it(join); !it.Done(); it.Advance()) {
+        PhiInstr* phi = it.Current();
+        ASSERT(phi != NULL);
+        VerifyUseListsInInstruction(phi);
       }
     }
     for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
@@ -222,8 +216,9 @@
   // Rename uses to reference inserted phis where appropriate.
   // Collect phis that reach a non-environment use.
   Rename(&live_phis, inlining_parameters);
-  // Propagate alive mark transitively from alive phis.
-  MarkLivePhis(&live_phis);
+  // Propagate alive mark transitively from alive phis and then remove
+  // non-live ones.
+  RemoveDeadPhis(&live_phis);
 }
 
 
@@ -474,12 +469,9 @@
           Environment::From(*env,
                             num_non_copied_params_,
                             parsed_function_.function());
-      current->set_env(deopt_env);
-      intptr_t use_index = 0;
+      current->SetEnvironment(deopt_env);
       for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
         Value* use = it.CurrentValue();
-        use->set_instruction(current);
-        use->set_use_index(use_index++);
         use->definition()->AddEnvUse(use);
       }
     }
@@ -501,15 +493,12 @@
       Definition* input_defn = v->definition();
       if (input_defn->IsLoadLocal() || input_defn->IsStoreLocal()) {
         // Remove the load/store from the graph.
-        input_defn->UnuseAllInputs();
         input_defn->RemoveFromGraph();
         // Assert we are not referencing nulls in the initial environment.
         ASSERT(reaching_defn->ssa_temp_index() != -1);
         v->set_definition(reaching_defn);
         input_defn = reaching_defn;
       }
-      v->set_instruction(current);
-      v->set_use_index(i);
       input_defn->AddInputUse(v);
     }
 
@@ -548,7 +537,6 @@
           env->Add((*env)[index]);
           // We remove load/store instructions when we find their use in 2a.
         } else {
-          definition->UnuseAllInputs();
           it.RemoveCurrentFromGraph();
         }
       } else {
@@ -591,9 +579,6 @@
           // Rename input operand.
           Value* use = new Value((*env)[i]);
           phi->SetInputAt(pred_index, use);
-          use->set_instruction(phi);
-          use->set_use_index(pred_index);
-          use->definition()->AddInputUse(use);
         }
       }
     }
@@ -601,7 +586,7 @@
 }
 
 
-void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) {
+void FlowGraph::RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis) {
   while (!live_phis->is_empty()) {
     PhiInstr* phi = live_phis->RemoveLast();
     for (intptr_t i = 0; i < phi->InputCount(); i++) {
@@ -613,6 +598,11 @@
       }
     }
   }
+
+  for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) {
+    JoinEntryInstr* join = it.Current()->AsJoinEntry();
+    if (join != NULL) join->RemoveDeadPhis(constant_null());
+  }
 }
 
 
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 59c0c0d..fa8c796 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -167,7 +167,7 @@
       const GrowableArray<BitVector*>& assigned_vars,
       const GrowableArray<BitVector*>& dom_frontier);
 
-  void MarkLivePhis(GrowableArray<PhiInstr*>* live_phis);
+  void RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis);
 
   void ReplacePredecessor(BlockEntryInstr* old_block,
                           BlockEntryInstr* new_block);
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index a2b0c36..02704b2 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -78,10 +78,21 @@
     cpu_spill_slot_count_(0) {
   for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL);
 
+  // All registers are marked as "not blocked" (array initialized to false).
+  // Mark the unavailable ones as "blocked" (true).
+  for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
+    blocked_cpu_registers_[i] = true;
+  }
+  for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) {
+    blocked_cpu_registers_[i] = true;
+  }
   blocked_cpu_registers_[CTX] = true;
   if (TMP != kNoRegister) {
     blocked_cpu_registers_[TMP] = true;
   }
+  if (PP != kNoRegister) {
+    blocked_cpu_registers_[PP] = true;
+  }
   blocked_cpu_registers_[SPREG] = true;
   blocked_cpu_registers_[FPREG] = true;
 
@@ -91,37 +102,12 @@
 
 
 // Remove environments from the instructions which can't deoptimize.
-// Replace dead phis uses with null values in environments.
-void FlowGraphAllocator::EliminateEnvironmentUses() {
-  ConstantInstr* constant_null =
-      postorder_.Last()->AsGraphEntry()->constant_null();
+void FlowGraphAllocator::EliminateEnvironments() {
   for (intptr_t i = 0; i < block_order_.length(); ++i) {
     BlockEntryInstr* block = block_order_[i];
-    if (block->IsJoinEntry()) block->AsJoinEntry()->RemoveDeadPhis();
     for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
       Instruction* current = it.Current();
-      if (current->CanDeoptimize()) {
-        ASSERT(current->env() != NULL);
-        for (Environment::DeepIterator it(current->env());
-             !it.Done();
-             it.Advance()) {
-          Value* use = it.CurrentValue();
-          Definition* def = use->definition();
-          PushArgumentInstr* push_argument = def->AsPushArgument();
-          if ((push_argument != NULL) && push_argument->WasEliminated()) {
-            it.SetCurrentValue(push_argument->value()->Copy());
-            continue;
-          }
-
-          PhiInstr* phi = def->AsPhi();
-          if ((phi != NULL) && !phi->is_alive()) {
-            it.SetCurrentValue(new Value(constant_null));
-            continue;
-          }
-        }
-      } else {
-        current->set_env(NULL);
-      }
+      if (!current->CanDeoptimize()) current->RemoveEnvironment();
     }
   }
 }
@@ -177,25 +163,22 @@
     // Handle phis.
     if (block->IsJoinEntry()) {
       JoinEntryInstr* join = block->AsJoinEntry();
-      if (join->phis() != NULL) {
-        for (intptr_t j = 0; j < join->phis()->length(); j++) {
-          PhiInstr* phi = (*join->phis())[j];
-          if (phi == NULL) continue;
+      for (PhiIterator it(join); !it.Done(); it.Advance()) {
+        PhiInstr* phi = it.Current();
+        ASSERT(phi != NULL);
+        kill->Add(phi->ssa_temp_index());
+        live_in->Remove(phi->ssa_temp_index());
 
-          kill->Add(phi->ssa_temp_index());
-          live_in->Remove(phi->ssa_temp_index());
+        // If a phi input is not defined by the corresponding predecessor it
+        // must be marked live-in for that predecessor.
+        for (intptr_t k = 0; k < phi->InputCount(); k++) {
+          Value* val = phi->InputAt(k);
+          if (val->BindsToConstant()) continue;
 
-          // If phi-operand is not defined by a predecessor it must be marked
-          // live-in for a predecessor.
-          for (intptr_t k = 0; k < phi->InputCount(); k++) {
-            Value* val = phi->InputAt(k);
-            if (val->BindsToConstant()) continue;
-
-            BlockEntryInstr* pred = block->PredecessorAt(k);
-            const intptr_t use = val->definition()->ssa_temp_index();
-            if (!kill_[pred->postorder_number()]->Contains(use)) {
-              live_in_[pred->postorder_number()]->Add(use);
-            }
+          BlockEntryInstr* pred = block->PredecessorAt(k);
+          const intptr_t use = val->definition()->ssa_temp_index();
+          if (!kill_[pred->postorder_number()]->Contains(use)) {
+            live_in_[pred->postorder_number()]->Add(use);
           }
         }
       }
@@ -696,12 +679,9 @@
   const intptr_t pred_idx = join->IndexOfPredecessor(block);
 
   // Record the corresponding phi input use for each phi.
-  ZoneGrowableArray<PhiInstr*>* phis = join->phis();
   intptr_t move_idx = 0;
-  for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) {
-    PhiInstr* phi = (*phis)[phi_idx];
-    if (phi == NULL) continue;
-
+  for (PhiIterator it(join); !it.Done(); it.Advance()) {
+    PhiInstr* phi = it.Current();
     Value* val = phi->InputAt(pred_idx);
     MoveOperands* move = parallel_move->MoveOperandsAt(move_idx);
 
@@ -744,19 +724,13 @@
 
   // All uses are recorded at the start position in the block.
   const intptr_t pos = join->start_pos();
-
-  ZoneGrowableArray<PhiInstr*>* phis = join->phis();
-  if (phis == NULL) return;
-
   const bool is_loop_header = BlockInfoAt(join->start_pos())->is_loop_header();
-
   intptr_t move_idx = 0;
-  for (intptr_t phi_idx = 0; phi_idx < phis->length(); phi_idx++) {
-    PhiInstr* phi = (*phis)[phi_idx];
-    if (phi == NULL) continue;
-
+  for (PhiIterator it(join); !it.Done(); it.Advance()) {
+    PhiInstr* phi = it.Current();
+    ASSERT(phi != NULL);
     const intptr_t vreg = phi->ssa_temp_index();
-    ASSERT(vreg != -1);
+    ASSERT(vreg >= 0);
 
     // Expected shape of live range:
     //
@@ -1183,8 +1157,10 @@
     // For join entry predecessors create phi resolution moves if
     // necessary. They will be populated by the register allocator.
     JoinEntryInstr* join = block->AsJoinEntry();
-    if ((join != NULL) && (join->phi_count() > 0)) {
-      const intptr_t phi_count = join->phi_count();
+    if ((join != NULL) &&
+        (join->phis() != NULL) &&
+        !join->phis()->is_empty()) {
+      const intptr_t phi_count = join->phis()->length();
       for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
         // Insert the move between the last two instructions of the
         // predecessor block (all such blocks have at least two instructions:
@@ -1756,15 +1732,14 @@
          !it.Done();
          it.Advance()) {
       PhiInstr* phi = it.Current();
-      if (phi->is_alive()) {
-        const intptr_t phi_vreg = phi->ssa_temp_index();
-        LiveRange* range = GetLiveRange(phi_vreg);
-        if (range->assigned_location().kind() == register_kind_) {
-          const intptr_t reg = range->assigned_location().register_code();
+      ASSERT(phi->is_alive());
+      const intptr_t phi_vreg = phi->ssa_temp_index();
+      LiveRange* range = GetLiveRange(phi_vreg);
+      if (range->assigned_location().kind() == register_kind_) {
+        const intptr_t reg = range->assigned_location().register_code();
 
-          if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
-            used_on_backedge[reg] = true;
-          }
+        if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
+          used_on_backedge[reg] = true;
         }
       }
     }
@@ -2446,7 +2421,7 @@
 void FlowGraphAllocator::AllocateRegisters() {
   CollectRepresentations();
 
-  EliminateEnvironmentUses();
+  EliminateEnvironments();
 
   AnalyzeLiveness();
 
diff --git a/runtime/vm/flow_graph_allocator.h b/runtime/vm/flow_graph_allocator.h
index 2c2447f..b191758 100644
--- a/runtime/vm/flow_graph_allocator.h
+++ b/runtime/vm/flow_graph_allocator.h
@@ -54,7 +54,7 @@
   void CollectRepresentations();
 
   // Eliminate unnecessary environments from the IL.
-  void EliminateEnvironmentUses();
+  void EliminateEnvironments();
 
   // Compute initial values for live-out, kill and live-in sets.
   void ComputeInitialSets();
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 8bcba37..f06d426 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -197,19 +197,14 @@
     }
     // If the call has uses, create a phi of the returns.
     if (call->HasUses()) {
-      // Environment count: length before call - argument count (+ return)
-      intptr_t env_count = call->env()->Length() - call->ArgumentCount();
       // Add a phi of the return values.
-      join->InsertPhi(env_count, env_count + 1);
-      PhiInstr* phi = join->phis()->Last();
+      PhiInstr* phi = new PhiInstr(join, num_exits);
       phi->set_ssa_temp_index(caller_graph->alloc_ssa_temp_index());
       phi->mark_alive();
       for (intptr_t i = 0; i < num_exits; ++i) {
-        Value* value = ValueAt(i);
-        phi->SetInputAt(i, value);
-        value->set_instruction(phi);
-        value->set_use_index(i);
+        phi->SetInputAt(i, ValueAt(i));
       }
+      join->InsertPhi(phi);
       // Replace uses of the call with the phi.
       call->ReplaceUsesWith(phi);
     } else {
@@ -1686,7 +1681,10 @@
     node->ElementAt(i)->Visit(&for_value);
     Append(for_value);
     // No store barrier needed for constants.
-    const bool emit_store_barrier = !for_value.value()->BindsToConstant();
+    const StoreBarrierType emit_store_barrier =
+        for_value.value()->BindsToConstant()
+            ? kNoStoreBarrier
+            : kEmitStoreBarrier;
     StoreIndexedInstr* store = new StoreIndexedInstr(
         array, index, for_value.value(),
         emit_store_barrier, class_id, deopt_id);
@@ -1978,22 +1976,40 @@
 }
 
 
-static bool IsRecognizedConstructor(const Function& function,
-                                    const String& expected) {
-  const Class& clazz = Class::Handle(function.Owner());
-  const Library& lib = Library::Handle(clazz.library());
+// List of recognized factories in core lib (factories with known result-cid):
+// (factory-name-symbol, result-cid, fingerprint).
+#define RECOGNIZED_FACTORY_LIST(V)                                             \
+  V(ObjectArrayDot, kArrayCid, 97987288)                                       \
+  V(GrowableObjectArrayWithData, kGrowableObjectArrayCid, 816132033)           \
+  V(GrowableObjectArrayDot, kGrowableObjectArrayCid, 1896741574)               \
 
-  const String& expected_class_name =
-      String::Handle(lib.PrivateName(expected));
-  if (!String::Handle(clazz.Name()).Equals(expected_class_name)) {
-    return false;
+
+// Class that recognizes factories and returns corresponding result cid.
+class FactoryRecognizer : public AllStatic {
+ public:
+  // Return kDynamicCid if factory is not recognized.
+  static intptr_t ResultCid(const Function& factory) {
+    ASSERT(factory.IsFactory());
+    const Class& function_class = Class::Handle(factory.Owner());
+    const Library& lib = Library::Handle(function_class.library());
+    if (lib.raw() != Library::CoreLibrary()) {
+      // Only core library factories recognized.
+      return kDynamicCid;
+    }
+    const String& factory_name = String::Handle(factory.name());
+#define RECOGNIZE_FACTORY(test_factory_symbol, cid, fp)                        \
+    if (String::EqualsIgnoringPrivateKey(                                      \
+        factory_name, Symbols::test_factory_symbol())) {                       \
+      ASSERT(factory.CheckSourceFingerprint(fp));                              \
+      return cid;                                                              \
+    }                                                                          \
+
+RECOGNIZED_FACTORY_LIST(RECOGNIZE_FACTORY);
+#undef RECOGNIZE_FACTORY
+
+    return kDynamicCid;
   }
-
-  const String& function_name = String::Handle(function.name());
-  const String& expected_function_name = String::Handle(
-      String::Concat(expected_class_name, Symbols::Dot()));
-  return function_name.Equals(expected_function_name);
-}
+};
 
 
 static intptr_t GetResultCidOfConstructor(ConstructorCallNode* node) {
@@ -2008,20 +2024,13 @@
   if (node->constructor().IsFactory()) {
     if ((function_class.Name() == Symbols::List().raw()) &&
         (function.name() == Symbols::ListFactory().raw())) {
-      return kGrowableObjectArrayCid;
-    } else if ((function_class.Name() == Symbols::List().raw()) &&
-               (function.name() == Symbols::ListFixedLengthFactory().raw())) {
-      return kArrayCid;
-    } else {
-      if (IsRecognizedConstructor(function, Symbols::ObjectArray()) &&
-          (node->arguments()->length() == 1)) {
-        return kArrayCid;
-      } else if (IsRecognizedConstructor(function,
-                                         Symbols::GrowableObjectArray()) &&
-                 (node->arguments()->length() == 0)) {
+      // Special recognition of 'new List()' vs 'new List(n)'.
+      if (node->arguments()->length() == 0) {
         return kGrowableObjectArrayCid;
       }
+      return kArrayCid;
     }
+    return FactoryRecognizer::ResultCid(function);
   }
   return kDynamicCid;   // Result cid not known.
 }
@@ -2569,7 +2578,6 @@
                                        type,
                                        dst_name);
   }
-  const bool kEmitStoreBarrier = true;
   StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
       node->field(), for_instance.value(), store_value, kEmitStoreBarrier);
   ReturnDefinition(store);
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 8319dd5..dc6d4ab 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -674,9 +674,15 @@
   bool blocked_registers[kNumberOfCpuRegisters];
 
   // Mark all available registers free.
-  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+  for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
+    blocked_registers[i] = true;
+  }
+  for (intptr_t i = kFirstFreeCpuRegister; i <= kLastFreeCpuRegister; i++) {
     blocked_registers[i] = false;
   }
+  for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) {
+    blocked_registers[i] = true;
+  }
 
   // Mark all fixed input, temp and output registers as used.
   for (intptr_t i = 0; i < locs->input_count(); i++) {
@@ -708,6 +714,9 @@
   if (TMP != kNoRegister) {
     blocked_registers[TMP] = true;
   }
+  if (PP != kNoRegister) {
+    blocked_registers[PP] = true;
+  }
 
   // Allocate all unallocated input locations.
   const bool should_pop = !instr->IsPushArgument();
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index d8b220c..502de90 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -7,10 +7,24 @@
 
 #include "vm/flow_graph_compiler.h"
 
-#include "vm/longjump.h"
+#include "lib/error.h"
+#include "vm/ast_printer.h"
+#include "vm/dart_entry.h"
+#include "vm/il_printer.h"
+#include "vm/locations.h"
+#include "vm/object_store.h"
+#include "vm/parser.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
 
 namespace dart {
 
+DECLARE_FLAG(int, optimization_counter_threshold);
+DECLARE_FLAG(bool, print_ast);
+DECLARE_FLAG(bool, print_scopes);
+DECLARE_FLAG(bool, enable_type_checks);
+
+
 FlowGraphCompiler::~FlowGraphCompiler() {
   // BlockInfos are zone-allocated, so their destructors are not called.
   // Verify the labels explicitly here.
@@ -31,6 +45,9 @@
 }
 
 
+#define __ assembler()->
+
+
 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
                                            Label* is_true,
                                            Label* is_false) {
@@ -128,12 +145,24 @@
 
 
 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) {
-  UNIMPLEMENTED();
+  if (!is_optimizing()) {
+    if (FLAG_enable_type_checks && instr->IsAssertAssignable()) {
+      AssertAssignableInstr* assert = instr->AsAssertAssignable();
+      AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
+                           assert->deopt_id(),
+                           assert->token_pos());
+    }
+    AllocateRegistersLocally(instr);
+  }
 }
 
 
 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
-  UNIMPLEMENTED();
+  if (is_optimizing()) return;
+  Definition* defn = instr->AsDefinition();
+  if ((defn != NULL) && defn->is_used()) {
+    __ Push(defn->locs()->out().reg());
+  }
 }
 
 
@@ -153,12 +182,191 @@
 
 
 void FlowGraphCompiler::EmitFrameEntry() {
-  UNIMPLEMENTED();
+  const Function& function = parsed_function().function();
+  if (CanOptimizeFunction() && function.is_optimizable()) {
+    const bool can_optimize = !is_optimizing() || may_reoptimize();
+    const Register function_reg = R6;
+    if (can_optimize) {
+      __ LoadObject(function_reg, function);
+    }
+    // Patch point is after the eventually inlined function object.
+    AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+                         Isolate::kNoDeoptId,
+                         0);  // No token position.
+    if (can_optimize) {
+      // Reoptimization of optimized function is triggered by counting in
+      // IC stubs, but not at the entry of the function.
+      if (!is_optimizing()) {
+        __ ldr(R7, FieldAddress(function_reg,
+                                Function::usage_counter_offset()));
+        __ add(R7, R7, ShifterOperand(1));
+        __ str(R7, FieldAddress(function_reg,
+                                Function::usage_counter_offset()));
+      } else {
+        __ ldr(R7, FieldAddress(function_reg,
+                                Function::usage_counter_offset()));
+      }
+      __ CompareImmediate(R7, FLAG_optimization_counter_threshold);
+      ASSERT(function_reg == R6);
+      __ Branch(&StubCode::OptimizeFunctionLabel(), GE);
+    }
+  } else {
+    AddCurrentDescriptor(PcDescriptors::kEntryPatch,
+                         Isolate::kNoDeoptId,
+                         0);  // No token position.
+  }
+  __ Comment("Enter frame");
+  AssemblerMacros::EnterDartFrame(assembler(), (StackSize() * kWordSize));
 }
 
 
 void FlowGraphCompiler::CompileGraph() {
-  UNIMPLEMENTED();
+  InitCompiler();
+  if (TryIntrinsify()) {
+    // Although this intrinsified code will never be patched, it must satisfy
+    // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum
+    // code size.
+    __ bkpt(0);
+    __ Branch(&StubCode::FixCallersTargetLabel());
+    return;
+  }
+
+  EmitFrameEntry();
+
+  const Function& function = parsed_function().function();
+
+  const int num_fixed_params = function.num_fixed_parameters();
+  const int num_copied_params = parsed_function().num_copied_params();
+  const int num_locals = parsed_function().num_stack_locals();
+
+  // For optimized code, keep a bitmap of the frame in order to build
+  // stackmaps for GC safepoints in the prologue.
+  LocationSummary* prologue_locs = NULL;
+  if (is_optimizing()) {
+    // Spill slots are allocated but not initialized.
+    prologue_locs = new LocationSummary(0, 0, LocationSummary::kCall);
+    prologue_locs->stack_bitmap()->SetLength(StackSize());
+  }
+
+  // We check the number of passed arguments when we have to copy them due to
+  // the presence of optional parameters.
+  // No such checking code is generated if only fixed parameters are declared,
+  // unless we are in debug mode or unless we are compiling a closure.
+  LocalVariable* saved_args_desc_var =
+      parsed_function().GetSavedArgumentsDescriptorVar();
+  if (num_copied_params == 0) {
+#ifdef DEBUG
+    ASSERT(!parsed_function().function().HasOptionalParameters());
+    const bool check_arguments = true;
+#else
+    const bool check_arguments = function.IsClosureFunction();
+#endif
+    if (check_arguments) {
+      __ Comment("Check argument count");
+      // Check that exactly num_fixed arguments are passed in.
+      Label correct_num_arguments, wrong_num_arguments;
+      __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+      __ CompareImmediate(R0, Smi::RawValue(num_fixed_params));
+      __ b(&wrong_num_arguments, NE);
+      __ ldr(R1, FieldAddress(R4,
+                              ArgumentsDescriptor::positional_count_offset()));
+      __ cmp(R0, ShifterOperand(R1));
+      __ b(&correct_num_arguments, EQ);
+      __ Bind(&wrong_num_arguments);
+      if (function.IsClosureFunction()) {
+        if (StackSize() != 0) {
+          // We need to unwind the space we reserved for locals and copied
+          // parameters. The NoSuchMethodFunction stub does not expect to see
+          // that area on the stack.
+          __ AddImmediate(SP, StackSize() * kWordSize);
+        }
+        // The call below has an empty stackmap because we have just
+        // dropped the spill slots.
+        BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
+
+        // Invoke noSuchMethod function passing "call" as the function name.
+        const int kNumArgsChecked = 1;
+        const ICData& ic_data = ICData::ZoneHandle(
+            ICData::New(function, Symbols::Call(),
+                        Isolate::kNoDeoptId, kNumArgsChecked));
+        __ LoadObject(R5, ic_data);
+        // FP - 4 : saved PP, object pool pointer of caller.
+        // FP + 0 : previous frame pointer.
+        // FP + 4 : return address.
+        // FP + 8 : PC marker, for easy identification of RawInstruction obj.
+        // FP + 12: last argument (arg n-1).
+        // SP + 0 : saved PP.
+        // SP + 16 + 4*(n-1) : first argument (arg 0).
+        // R5 : ic-data.
+        // R4 : arguments descriptor array.
+        __ BranchLink(&StubCode::CallNoSuchMethodFunctionLabel());
+        if (is_optimizing()) {
+          stackmap_table_builder_->AddEntry(assembler()->CodeSize(),
+                                            empty_stack_bitmap,
+                                            0);  // No registers.
+        }
+        // The noSuchMethod call may return.
+        AssemblerMacros::LeaveDartFrame(assembler());
+        __ Ret();
+      } else {
+        __ Stop("Wrong number of arguments");
+      }
+      __ Bind(&correct_num_arguments);
+    }
+    // The arguments descriptor is never saved in the absence of optional
+    // parameters, since any argument definition test would always yield true.
+    ASSERT(saved_args_desc_var == NULL);
+  } else {
+    if (saved_args_desc_var != NULL) {
+      __ Comment("Save arguments descriptor");
+      const Register kArgumentsDescriptorReg = R4;
+      // The saved_args_desc_var is allocated one slot before the first local.
+      const intptr_t slot = parsed_function().first_stack_local_index() + 1;
+      // If the saved_args_desc_var is captured, it is first moved to the stack
+      // and later to the context, once the context is allocated.
+      ASSERT(saved_args_desc_var->is_captured() ||
+             (saved_args_desc_var->index() == slot));
+      __ str(kArgumentsDescriptorReg, Address(FP, slot * kWordSize));
+    }
+    CopyParameters();
+  }
+
+  // In unoptimized code, initialize (non-argument) stack allocated slots to
+  // null. This does not cover the saved_args_desc_var slot.
+  if (!is_optimizing() && (num_locals > 0)) {
+    __ Comment("Initialize spill slots");
+    const intptr_t slot_base = parsed_function().first_stack_local_index();
+    __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+    for (intptr_t i = 0; i < num_locals; ++i) {
+      // Subtract index i (locals lie at lower addresses than FP).
+      __ str(R0, Address(FP, (slot_base - i) * kWordSize));
+    }
+  }
+
+  if (FLAG_print_scopes) {
+    // Print the function scope (again) after generating the prologue in order
+    // to see annotations such as allocation indices of locals.
+    if (FLAG_print_ast) {
+      // Second printing.
+      OS::Print("Annotated ");
+    }
+    AstPrinter::PrintFunctionScope(parsed_function());
+  }
+
+  VisitBlocks();
+
+  __ bkpt(0);
+  GenerateDeferredCode();
+  // Emit function patching code. This will be swapped with the first 5 bytes
+  // at entry point.
+  AddCurrentDescriptor(PcDescriptors::kPatchCode,
+                       Isolate::kNoDeoptId,
+                       0);  // No token position.
+  __ Branch(&StubCode::FixCallersTargetLabel());
+  AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
+                       Isolate::kNoDeoptId,
+                       0);  // No token position.
+  __ Branch(&StubCode::DeoptimizeLazyLabel());
 }
 
 
@@ -175,7 +383,20 @@
                                          const ExternalLabel* label,
                                          PcDescriptors::Kind kind,
                                          LocationSummary* locs) {
-  UNIMPLEMENTED();
+  __ BranchLinkPatchable(label);
+  AddCurrentDescriptor(kind, deopt_id, token_pos);
+  RecordSafepoint(locs);
+  // Marks either the continuation point in unoptimized code or the
+  // deoptimization point in optimized code, after call.
+  if (is_optimizing()) {
+    AddDeoptIndexAtCall(deopt_id, token_pos);
+  } else {
+    // Add deoptimization continuation point after the call and before the
+    // arguments are removed.
+    AddCurrentDescriptor(PcDescriptors::kDeoptAfter,
+                         deopt_id,
+                         token_pos);
+  }
 }
 
 
@@ -183,7 +404,7 @@
                                             intptr_t deopt_id,
                                             const RuntimeEntry& entry,
                                             LocationSummary* locs) {
-  UNIMPLEMENTED();
+  __ Unimplemented("call runtime");
 }
 
 
@@ -227,7 +448,16 @@
                                        intptr_t deopt_id,
                                        intptr_t token_pos,
                                        LocationSummary* locs) {
-  UNIMPLEMENTED();
+  __ LoadObject(R4, arguments_descriptor);
+  // Do not use the code from the function, but let the code be patched so that
+  // we can record the outgoing edges to other code.
+  GenerateDartCall(deopt_id,
+                   token_pos,
+                   &StubCode::CallStaticFunctionLabel(),
+                   PcDescriptors::kFuncCall,
+                   locs);
+  AddStaticCallTarget(function);
+  __ Drop(argument_count);
 }
 
 
@@ -252,12 +482,31 @@
 
 
 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
-  UNIMPLEMENTED();
+  // TODO(vegorov): consider saving only caller save (volatile) registers.
+  const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+  if (fpu_registers > 0) {
+    UNIMPLEMENTED();
+  }
+
+  // Store general purpose registers with the lowest register number at the
+  // lowest address.
+  const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
+  ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
+  __ PushList(cpu_registers);
 }
 
 
 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
-  UNIMPLEMENTED();
+  // General purpose registers have the lowest register number at the
+  // lowest address.
+  const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
+  ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
+  __ PopList(cpu_registers);
+
+  const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
+  if (fpu_registers > 0) {
+    UNIMPLEMENTED();
+  }
 }
 
 
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 3fc75b3..ebc2053 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -573,7 +573,6 @@
         for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
           PushArgumentInstr* push = call->PushArgumentAt(i);
           push->ReplaceUsesWith(push->value()->definition());
-          push->UnuseAllInputs();
           push->RemoveFromGraph();
         }
 
@@ -645,12 +644,27 @@
     return parsed_function;
   }
 
+  // Include special handling for List. factory: inlining it is not helpful
+  // if the incoming argument is a non-constant value.
+  // TODO(srdjan): Fix inlining of List. factory.
   void InlineStaticCalls() {
     const GrowableArray<StaticCallInstr*>& calls =
         inlining_call_sites_->static_calls();
     TRACE_INLINING(OS::Print("  Static Calls (%d)\n", calls.length()));
     for (intptr_t i = 0; i < calls.length(); ++i) {
       StaticCallInstr* call = calls[i];
+      if (call->function().name() == Symbols::ListFactory().raw()) {
+        // Inline only if no arguments or a constant was passed.
+        ASSERT(call->function().NumImplicitParameters() == 1);
+        ASSERT(call->ArgumentCount() <= 2);
+        // Arg 0: Instantiator type arguments.
+        // Arg 1: Length (optional).
+        if ((call->ArgumentCount() == 2) &&
+            (!call->PushArgumentAt(1)->value()->BindsToConstant())) {
+          // Do not inline since a non-constant argument was passed.
+          continue;
+        }
+      }
       GrowableArray<Value*> arguments(call->ArgumentCount());
       for (int i = 0; i < call->ArgumentCount(); ++i) {
         arguments.Add(call->PushArgumentAt(i)->value());
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 58cf837..522dee1 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -290,7 +290,6 @@
       OS::Print("Removing v%"Pd".\n", current_defn->ssa_temp_index());
     }
   }
-  current->UnuseAllInputs();
   iterator->RemoveCurrentFromGraph();
 }
 
@@ -333,9 +332,7 @@
     // Convert by boxing/unboxing.
     // TODO(fschneider): Implement direct unboxed mint-to-double conversion.
     BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType());
-    use->RemoveFromUseList();
-    use->set_definition(boxed);
-    boxed->AddInputUse(use);
+    use->BindTo(boxed);
     InsertBefore(insert_before, boxed, NULL, Definition::kValue);
 
     const intptr_t deopt_id = (deopt_target != NULL) ?
@@ -363,9 +360,7 @@
     }
   }
   ASSERT(converted != NULL);
-  use->RemoveFromUseList();
-  use->set_definition(converted);
-  converted->AddInputUse(use);
+  use->BindTo(converted);
   InsertBefore(insert_before, converted, use->instruction()->env(),
                Definition::kValue);
 }
@@ -388,8 +383,7 @@
     Instruction* deopt_target;
     PhiInstr* phi = use->instruction()->AsPhi();
     if (phi != NULL) {
-      if (!phi->is_alive()) continue;
-
+      ASSERT(phi->is_alive());
       // For phis conversions have to be inserted in the predecessor.
       insert_before =
           phi->block()->PredecessorAt(use->use_index())->last_instruction();
@@ -407,12 +401,10 @@
   // Convervatively unbox all phis that were proven to be of type Double.
   for (intptr_t i = 0; i < block_order_.length(); ++i) {
     JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
-    if (join_entry == NULL) continue;
-
-    if (join_entry->phis() != NULL) {
-      for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) {
-        PhiInstr* phi = (*join_entry->phis())[i];
-        if (phi == NULL) continue;
+    if (join_entry != NULL) {
+      for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
+        PhiInstr* phi = it.Current();
+        ASSERT(phi != NULL);
         if (phi->Type()->ToCid() == kDoubleCid) {
           phi->set_representation(kUnboxedDouble);
         }
@@ -430,17 +422,15 @@
 
   for (intptr_t i = 0; i < block_order_.length(); ++i) {
     BlockEntryInstr* entry = block_order_[i];
-
     JoinEntryInstr* join_entry = entry->AsJoinEntry();
-    if ((join_entry != NULL) && (join_entry->phis() != NULL)) {
-      for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) {
-        PhiInstr* phi = (*join_entry->phis())[i];
-        if ((phi != NULL) && (phi->is_alive())) {
-          InsertConversionsFor(phi);
-        }
+    if (join_entry != NULL) {
+      for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
+        PhiInstr* phi = it.Current();
+        ASSERT(phi != NULL);
+        ASSERT(phi->is_alive());
+        InsertConversionsFor(phi);
       }
     }
-
     for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
       Definition* def = it.Current()->AsDefinition();
       if (def != NULL) {
@@ -565,7 +555,6 @@
   for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
     PushArgumentInstr* push = call->PushArgumentAt(i);
     push->ReplaceUsesWith(push->value()->definition());
-    push->UnuseAllInputs();
     push->RemoveFromGraph();
   }
   call->ReplaceWith(replacement, current_iterator());
@@ -893,10 +882,15 @@
   }
 
   intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index);
-  // Check if store barrier is needed.
-  bool needs_store_barrier = !RawObject::IsByteArrayClassId(array_cid);
+  // Check if store barrier is needed. Byte arrays don't need a store barrier.
+  StoreBarrierType needs_store_barrier =
+      RawObject::IsByteArrayClassId(array_cid)
+          ? kNoStoreBarrier
+          : kEmitStoreBarrier;
   if (!value_check.IsNull()) {
-    needs_store_barrier = false;
+    // No store barrier needed because checked value is a smi, an unboxed mint
+    // or unboxed double.
+    needs_store_barrier = kNoStoreBarrier;
     AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
                   call);
   }
@@ -1240,12 +1234,9 @@
       field.Offset(),
       AbstractType::ZoneHandle(field.type()),
       field.is_final());
-  // Detach environment from the original instruction because it can't
-  // deoptimize.
-  for (Environment::DeepIterator it(call->env()); !it.Done(); it.Advance()) {
-    it.CurrentValue()->RemoveFromUseList();
-  }
-  call->set_env(NULL);
+  // Discard the environment from the original instruction because the load
+  // can't deoptimize.
+  call->RemoveEnvironment();
   ReplaceCall(call, load);
 }
 
@@ -1414,7 +1405,7 @@
 }
 
 
-LoadIndexedInstr* FlowGraphOptimizer::BuildStringCharCodeAt(
+LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt(
     InstanceCallInstr* call,
     intptr_t cid) {
   Definition* str = call->ArgumentAt(0);
@@ -1536,11 +1527,11 @@
       break;
   }
 
-  if ((recognized_kind == MethodRecognizer::kStringBaseCharCodeAt) &&
+  if ((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) &&
       (ic_data.NumberOfChecks() == 1) &&
       ((class_ids[0] == kOneByteStringCid) ||
        (class_ids[0] == kTwoByteStringCid))) {
-    LoadIndexedInstr* instr = BuildStringCharCodeAt(call, class_ids[0]);
+    LoadIndexedInstr* instr = BuildStringCodeUnitAt(call, class_ids[0]);
     ReplaceCall(call, instr);
     return true;
   }
@@ -1549,7 +1540,7 @@
       (class_ids[0] == kOneByteStringCid)) {
     // TODO(fschneider): Handle TwoByteString.
     LoadIndexedInstr* load_char_code =
-        BuildStringCharCodeAt(call, class_ids[0]);
+        BuildStringCodeUnitAt(call, class_ids[0]);
     InsertBefore(call, load_char_code, NULL, Definition::kValue);
     StringFromCharCodeInstr* char_at =
         new StringFromCharCodeInstr(new Value(load_char_code),
@@ -1587,10 +1578,10 @@
       }
       case MethodRecognizer::kDoubleMod:
       case MethodRecognizer::kDoublePow:
+      case MethodRecognizer::kDoubleRound:
         ReplaceWithMathCFunction(call, recognized_kind);
         return true;
       case MethodRecognizer::kDoubleTruncate:
-      case MethodRecognizer::kDoubleRound:
       case MethodRecognizer::kDoubleFloor:
       case MethodRecognizer::kDoubleCeil:
         if (!CPUFeatures::double_truncate_round_supported()) {
@@ -1906,26 +1897,23 @@
   if (InstanceCallNeedsClassCheck(instr)) {
     AddReceiverCheck(instr);
   }
-  bool needs_store_barrier = true;
+  StoreBarrierType needs_store_barrier = kEmitStoreBarrier;
   if (ArgIsAlwaysSmi(*instr->ic_data(), 1)) {
     InsertBefore(instr,
                  new CheckSmiInstr(new Value(instr->ArgumentAt(1)),
                                    instr->deopt_id()),
                  instr->env(),
                  Definition::kEffect);
-    needs_store_barrier = false;
+    needs_store_barrier = kNoStoreBarrier;
   }
   StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
       field,
       new Value(instr->ArgumentAt(0)),
       new Value(instr->ArgumentAt(1)),
       needs_store_barrier);
-  // Detach environment from the original instruction because it can't
-  // deoptimize.
-  for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
-    it.CurrentValue()->RemoveFromUseList();
-  }
-  instr->set_env(NULL);
+  // Discard the environment from the original instruction because the store
+  // can't deoptimize.
+  instr->RemoveEnvironment();
   ReplaceCall(instr, store);
   return true;
 }
@@ -2268,12 +2256,9 @@
 
     // Skip dead phis.
     PhiInstr* phi = use->instruction()->AsPhi();
-    if ((phi != NULL) && !phi->is_alive()) continue;
-
+    ASSERT((phi == NULL) || phi->is_alive());
     if (IsDominatedUse(dom, use)) {
-      use->RemoveFromUseList();
-      use->set_definition(other);
-      other->AddInputUse(use);
+      use->BindTo(other);
     }
   }
 }
@@ -2618,7 +2603,6 @@
       RangeBoundary array_length =
           RangeBoundary::FromDefinition(check->length()->definition());
       if (check->IsRedundant(array_length)) {
-        current->UnuseAllInputs();
         it.RemoveCurrentFromGraph();
       }
     }
@@ -2660,7 +2644,6 @@
       def = def->AsConstraint()->value()->definition();
     }
     constraints_[i]->ReplaceUsesWith(def);
-    constraints_[i]->UnuseAllInputs();
     constraints_[i]->RemoveFromGraph();
   }
 }
@@ -2683,6 +2666,10 @@
 }
 
 
+LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) {
+}
+
+
 void LICM::Hoist(ForwardInstructionIterator* it,
                  BlockEntryInstr* pre_header,
                  Instruction* current) {
@@ -2696,13 +2683,11 @@
               pre_header->block_id());
   }
   // Move the instruction out of the loop.
+  current->RemoveEnvironment();
   it->RemoveCurrentFromGraph();
   GotoInstr* last = pre_header->last_instruction()->AsGoto();
-  current->InsertBefore(last);
-  // Attach the environment of the Goto instruction to the hoisted
-  // instruction and set the correct deopt_id.
-  ASSERT(last->env() != NULL);
-  last->env()->DeepCopyTo(current);
+  // Using kind kEffect will not assign a fresh ssa temporary index.
+  flow_graph()->InsertBefore(last, current, last->env(), Definition::kEffect);
   current->deopt_id_ = last->GetDeoptId();
 }
 
@@ -2717,7 +2702,6 @@
   }
 
   if (phi->Type()->ToCid() == kSmiCid) {
-    current->UnuseAllInputs();
     it->RemoveCurrentFromGraph();
     return;
   }
@@ -2748,19 +2732,16 @@
   // Host CheckSmi instruction and make this phi smi one.
   Hoist(it, pre_header, current);
 
-  // Replace value we are checking with phi's input. Maintain use lists.
-  Definition* non_smi_input_defn = phi->InputAt(non_smi_input)->definition();
-  current->value()->RemoveFromUseList();
-  current->value()->set_definition(non_smi_input_defn);
-  non_smi_input_defn->AddInputUse(current->value());
+  // Replace value we are checking with phi's input.
+  current->value()->BindTo(phi->InputAt(non_smi_input)->definition());
 
   phi->UpdateType(CompileType::FromCid(kSmiCid));
 }
 
 
-void LICM::Optimize(FlowGraph* flow_graph) {
+void LICM::Optimize() {
   GrowableArray<BlockEntryInstr*> loop_headers;
-  flow_graph->ComputeLoops(&loop_headers);
+  flow_graph()->ComputeLoops(&loop_headers);
 
   for (intptr_t i = 0; i < loop_headers.length(); ++i) {
     BlockEntryInstr* header = loop_headers[i];
@@ -2771,7 +2752,7 @@
     for (BitVector::Iterator loop_it(header->loop_info());
          !loop_it.Done();
          loop_it.Advance()) {
-      BlockEntryInstr* block = flow_graph->preorder()[loop_it.Current()];
+      BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()];
       for (ForwardInstructionIterator it(block);
            !it.Done();
            it.Advance()) {
@@ -3127,7 +3108,6 @@
           }
 
           defn->ReplaceUsesWith(replacement);
-          defn->UnuseAllInputs();
           instr_it.RemoveCurrentFromGraph();
           continue;
         } else if (!kill->Contains(expr_id)) {
@@ -3289,10 +3269,6 @@
       Definition* replacement = (*pred_out_values)[expr_id]->Replacement();
       Value* input = new Value(replacement);
       phi->SetInputAt(i, input);
-
-      // TODO(vegorov): add a helper function to handle input insertion.
-      input->set_instruction(phi);
-      input->set_use_index(i);
       replacement->AddInputUse(input);
     }
 
@@ -3339,7 +3315,6 @@
           }
 
           load->ReplaceUsesWith(replacement);
-          load->UnuseAllInputs();
           load->RemoveFromGraph();
           load->SetReplacement(replacement);
         }
@@ -3400,13 +3375,19 @@
     return true;
   }
 
-  // Emit non-redundant phis created during ComputeOutValues and ForwardLoads.
+  // Phis have not yet been inserted into the graph but they have uses of
+  // their inputs.  Insert the non-redundant ones and clear the input uses
+  // of the redundant ones.
   void EmitPhis() {
     for (intptr_t i = 0; i < phis_.length(); i++) {
       PhiInstr* phi = phis_[i];
-      if ((phi->input_use_list() != NULL) && !EliminateRedundantPhi(phi)) {
+      if (phi->HasUses() && !EliminateRedundantPhi(phi)) {
         phi->mark_alive();
         phi->block()->InsertPhi(phi);
+      } else {
+        for (intptr_t j = phi->InputCount() - 1; j >= 0; --j) {
+          phi->InputAt(j)->RemoveFromUseList();
+        }
       }
     }
   }
@@ -4275,43 +4256,47 @@
       // Predecessors will be recomputed (in block id order) after removing
       // unreachable code so we merely have to keep the phi inputs in order.
       ZoneGrowableArray<PhiInstr*>* phis = join->phis();
-      if (phis != NULL) {
+      if ((phis != NULL) && !phis->is_empty()) {
         intptr_t pred_count = join->PredecessorCount();
         intptr_t live_count = 0;
         for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) {
           if (reachable_->Contains(
                   join->PredecessorAt(pred_idx)->preorder_number())) {
             if (live_count < pred_idx) {
-              for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
-                PhiInstr* phi = (*phis)[phi_idx];
-                if (phi == NULL) continue;
-                Value* input = phi->inputs_[pred_idx];
-                input->set_use_index(live_count);
-                phi->inputs_[live_count] = input;
+              for (PhiIterator it(join); !it.Done(); it.Advance()) {
+                PhiInstr* phi = it.Current();
+                ASSERT(phi != NULL);
+                phi->SetInputAt(live_count, phi->InputAt(pred_idx));
               }
             }
             ++live_count;
           } else {
-            for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
-              PhiInstr* phi = (*phis)[phi_idx];
-              if (phi == NULL) continue;
-              phi->inputs_[pred_idx]->RemoveFromUseList();
+            for (PhiIterator it(join); !it.Done(); it.Advance()) {
+              PhiInstr* phi = it.Current();
+              ASSERT(phi != NULL);
+              phi->InputAt(pred_idx)->RemoveFromUseList();
             }
           }
         }
         if (live_count < pred_count) {
-          for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
-            PhiInstr* phi = (*phis)[phi_idx];
-            if (phi == NULL) continue;
+          intptr_t to_idx = 0;
+          for (intptr_t from_idx = 0; from_idx < phis->length(); ++from_idx) {
+            PhiInstr* phi = (*phis)[from_idx];
+            ASSERT(phi != NULL);
             if (FLAG_remove_redundant_phis && (live_count == 1)) {
               Value* input = phi->InputAt(0);
               phi->ReplaceUsesWith(input->definition());
               input->RemoveFromUseList();
-              (*phis)[phi_idx] = NULL;
             } else {
               phi->inputs_.TruncateTo(live_count);
+              (*phis)[to_idx++] = phi;
             }
           }
+          if (to_idx == 0) {
+            join->phis_ = NULL;
+          } else {
+            phis->TruncateTo(to_idx);
+          }
         }
       }
     }
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 6ec0e35..83515bc 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -84,7 +84,7 @@
   bool TryInlineInstanceMethod(InstanceCallInstr* call);
   void ReplaceWithInstanceOf(InstanceCallInstr* instr);
 
-  LoadIndexedInstr* BuildStringCharCodeAt(InstanceCallInstr* call,
+  LoadIndexedInstr* BuildStringCodeUnitAt(InstanceCallInstr* call,
                                           intptr_t cid);
 
   LoadIndexedInstr* BuildByteArrayViewLoad(InstanceCallInstr* call,
@@ -162,19 +162,25 @@
 
 
 // Loop invariant code motion.
-class LICM : public AllStatic {
+class LICM : public ValueObject {
  public:
-  static void Optimize(FlowGraph* flow_graph);
+  explicit LICM(FlowGraph* flow_graph);
+
+  void Optimize();
 
  private:
-  static void Hoist(ForwardInstructionIterator* it,
-                    BlockEntryInstr* pre_header,
-                    Instruction* current);
+  FlowGraph* flow_graph() const { return flow_graph_; }
 
-  static void TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it,
-                                         BlockEntryInstr* header,
-                                         BlockEntryInstr* pre_header,
-                                         CheckSmiInstr* current);
+  void Hoist(ForwardInstructionIterator* it,
+             BlockEntryInstr* pre_header,
+             Instruction* current);
+
+  void TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it,
+                                  BlockEntryInstr* header,
+                                  BlockEntryInstr* pre_header,
+                                  CheckSmiInstr* current);
+
+  FlowGraph* const flow_graph_;
 };
 
 
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 8810fbc..09d6171 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -42,22 +42,21 @@
 
 void FlowGraphTypePropagator::Propagate() {
   if (FLAG_trace_type_propagation) {
-    OS::Print("Before type propagation:\n");
-    FlowGraphPrinter printer(*flow_graph_);
-    printer.PrintBlocks();
+    FlowGraphPrinter::PrintGraph("Before type propagation", flow_graph_);
   }
 
   // Walk the dominator tree and propagate reaching types to all Values.
   // Collect all phis for a fixed point iteration.
   PropagateRecursive(flow_graph_->graph_entry());
 
-#ifdef DEBUG
   // Initially the worklist contains only phis.
+  // Reset compile type of all phis to None to ensure that
+  // types are correctly propagated through the cycles of
+  // phis.
   for (intptr_t i = 0; i < worklist_.length(); i++) {
     ASSERT(worklist_[i]->IsPhi());
-    ASSERT(worklist_[i]->Type()->IsNone());
+    *worklist_[i]->Type() = CompileType::None();
   }
-#endif
 
   // Iterate until a fixed point is reached, updating the types of
   // definitions.
@@ -84,9 +83,7 @@
   }
 
   if (FLAG_trace_type_propagation) {
-    OS::Print("After type propagation:\n");
-    FlowGraphPrinter printer(*flow_graph_);
-    printer.PrintBlocks();
+    FlowGraphPrinter::PrintGraph("After type propagation", flow_graph_);
   }
 }
 
@@ -176,9 +173,7 @@
 
 void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join) {
   for (PhiIterator it(join); !it.Done(); it.Advance()) {
-    if (it.Current()->is_alive()) {
-      worklist_.Add(it.Current());
-    }
+    worklist_.Add(it.Current());
   }
 }
 
@@ -289,14 +284,8 @@
   }
   ASSERT(check_clone != NULL);
   ASSERT(assert->deopt_id() == assert->env()->deopt_id());
-
-  Value* use = check_clone->InputAt(0);
-  use->set_instruction(check_clone);
-  use->set_use_index(0);
-  use->definition()->AddInputUse(use);
-
-  assert->env()->DeepCopyTo(check_clone);
   check_clone->InsertBefore(assert);
+  assert->env()->DeepCopyTo(check_clone);
 
   (*asserts_)[defn->ssa_temp_index()] = kStrengthenedAssertMarker;
 }
@@ -352,7 +341,7 @@
 
 
 CompileType CompileType::FromAbstractType(const AbstractType& type,
-                                           bool is_nullable) {
+                                          bool is_nullable) {
   return CompileType(is_nullable, kIllegalCid, &type);
 }
 
@@ -400,9 +389,10 @@
     } else if (type_->IsVoidType()) {
       cid_ = kNullCid;
     } else if (FLAG_use_cha && type_->HasResolvedTypeClass()) {
-      const intptr_t cid = Class::Handle(type_->type_class()).id();
-      if (!CHA::HasSubclasses(cid)) {
-        cid_ = cid;
+      const Class& type_class = Class::Handle(type_->type_class());
+      if (!type_class.is_implemented() &&
+          !CHA::HasSubclasses(type_class.id())) {
+        cid_ = type_class.id();
       } else {
         cid_ = kDynamicCid;
       }
@@ -538,12 +528,7 @@
 
 
 bool PhiInstr::RecomputeType() {
-  if (!is_alive()) {
-    return false;
-  }
-
   CompileType result = CompileType::None();
-
   for (intptr_t i = 0; i < InputCount(); i++) {
     if (FLAG_trace_type_propagation) {
       OS::Print("  phi %"Pd" input %"Pd": v%"Pd" has reaching type %s\n",
@@ -564,17 +549,6 @@
 }
 
 
-static bool CanTrustParameterType(const Function& function, intptr_t index) {
-  // Parameter is receiver.
-  if (index == 0) {
-    return function.IsDynamicFunction() || function.IsConstructor();
-  }
-
-  // Parameter is the constructor phase.
-  return (index == 1) && function.IsConstructor();
-}
-
-
 CompileType ParameterInstr::ComputeType() const {
   // Note that returning the declared type of the formal parameter would be
   // incorrect, because ParameterInstr is used as input to the type check
@@ -582,14 +556,36 @@
   // always be wrongly eliminated.
   // However there are parameters that are known to match their declared type:
   // for example receiver and construction phase.
-  if (!CanTrustParameterType(block_->parsed_function().function(),
-                             index())) {
-    return CompileType::Dynamic();
+  const Function& function = block_->parsed_function().function();
+  LocalScope* scope = block_->parsed_function().node_sequence()->scope();
+  const AbstractType& type = scope->VariableAt(index())->type();
+
+  // Parameter is the constructor phase.
+  if ((index() == 1) && function.IsConstructor()) {
+    return CompileType::FromAbstractType(type, CompileType::kNonNullable);
   }
 
-  LocalScope* scope = block_->parsed_function().node_sequence()->scope();
-  return CompileType::FromAbstractType(scope->VariableAt(index())->type(),
-                                       CompileType::kNonNullable);
+  // Parameter is the receiver.
+  if ((index() == 0) &&
+      (function.IsDynamicFunction() || function.IsConstructor())) {
+    if (type.IsObjectType() || type.IsNullType()) {
+      // Receiver can be null.
+      return CompileType::FromAbstractType(type, CompileType::kNullable);
+    }
+
+    // Receiver can't be null but can be an instance of a subclass.
+    intptr_t cid = kDynamicCid;
+    if (FLAG_use_cha && type.HasResolvedTypeClass()) {
+      const Class& type_class = Class::Handle(type.type_class());
+      if (!CHA::HasSubclasses(type_class.id())) {
+        cid = type_class.id();
+      }
+    }
+
+    return CompileType(CompileType::kNonNullable, cid, &type);
+  }
+
+  return CompileType::Dynamic();
 }
 
 
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index c4d74e5..d938145 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -32,6 +32,14 @@
 }
 
 
+void FlowGraphPrinter::PrintGraph(const char* phase, FlowGraph* flow_graph) {
+  OS::Print("*** BEGIN CFG\n%s\n", phase);
+  FlowGraphPrinter printer(*flow_graph);
+  printer.PrintBlocks();
+  OS::Print("*** END CFG\n");
+}
+
+
 void FlowGraphPrinter::PrintBlocks() {
   if (!function_.IsNull()) {
     OS::Print("==== %s\n", function_.ToFullyQualifiedCString());
diff --git a/runtime/vm/il_printer.h b/runtime/vm/il_printer.h
index 3da0191..aaa62b7 100644
--- a/runtime/vm/il_printer.h
+++ b/runtime/vm/il_printer.h
@@ -54,6 +54,8 @@
                              const String& dst_name,
                              bool eliminated);
 
+  static void PrintGraph(const char* phase, FlowGraph* flow_graph);
+
  private:
   const Function& function_;
   const GrowableArray<BlockEntryInstr*>& block_order_;
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index ba7ec59..8dab5d9 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -60,14 +60,15 @@
 uword CallPattern::TargetAddress() const {
   const Object& target_address = Object::Handle(object_pool_.At(pool_index_));
   ASSERT(target_address.IsSmi());
-  return Smi::Cast(target_address).Value() << kSmiTagShift;
+  // The address is stored in the object array as a RawSmi.
+  return reinterpret_cast<uword>(target_address.raw());
 }
 
 
 void CallPattern::SetTargetAddress(uword target_address) const {
   ASSERT(Utils::IsAligned(target_address, 4));
   // The address is stored in the object array as a RawSmi.
-  const Smi& smi = Smi::Handle(Smi::New(target_address >> kSmiTagShift));
+  const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target_address));
   object_pool_.SetAt(pool_index_, smi);
 }
 
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 2b10211..dcb64cc 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -70,13 +70,12 @@
                                  intptr_t deopt_id,
                                  const ICData& unary_checks)
     : unary_checks_(unary_checks) {
-  ASSERT(value != NULL);
   ASSERT(unary_checks.IsZoneHandle());
   // Expected useful check data.
-  ASSERT(!unary_checks_.IsNull() &&
-         (unary_checks_.NumberOfChecks() > 0) &&
-         (unary_checks_.num_args_tested() == 1));
-  inputs_[0] = value;
+  ASSERT(!unary_checks_.IsNull());
+  ASSERT(unary_checks_.NumberOfChecks() > 0);
+  ASSERT(unary_checks_.num_args_tested() == 1);
+  SetInputAt(0, value);
   deopt_id_ = deopt_id;
   // Otherwise use CheckSmiInstr.
   ASSERT((unary_checks_.NumberOfChecks() != 1) ||
@@ -319,6 +318,25 @@
 #undef DEFINE_ACCEPT
 
 
+void Instruction::SetEnvironment(Environment* deopt_env) {
+  intptr_t use_index = 0;
+  for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
+    Value* use = it.CurrentValue();
+    use->set_instruction(this);
+    use->set_use_index(use_index++);
+  }
+  env_ = deopt_env;
+}
+
+
+void Instruction::RemoveEnvironment() {
+  for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) {
+    it.CurrentValue()->RemoveFromUseList();
+  }
+  env_ = NULL;
+}
+
+
 Instruction* Instruction::RemoveFromGraph(bool return_previous) {
   ASSERT(!IsBlockEntry());
   ASSERT(!IsControl());
@@ -327,29 +345,23 @@
   ASSERT(!IsReThrow());
   ASSERT(!IsGoto());
   ASSERT(previous() != NULL);
+  // We cannot assert that the instruction, if it is a definition, has no
+  // uses.  This function is used to remove instructions from the graph and
+  // reinsert them elsewhere (e.g., hoisting).
   Instruction* prev_instr = previous();
   Instruction* next_instr = next();
   ASSERT(next_instr != NULL);
   ASSERT(!next_instr->IsBlockEntry());
   prev_instr->LinkTo(next_instr);
-  // Reset successor and previous instruction to indicate
-  // that the instruction is removed from the graph.
+  UnuseAllInputs();
+  // Reset the successor and previous instruction to indicate that the
+  // instruction is removed from the graph.
   set_previous(NULL);
   set_next(NULL);
   return return_previous ? prev_instr : next_instr;
 }
 
 
-void Instruction::InsertBefore(Instruction* next) {
-  ASSERT(previous_ == NULL);
-  ASSERT(next_ == NULL);
-  next_ = next;
-  previous_ = next->previous_;
-  next->previous_ = this;
-  previous_->next_ = this;
-}
-
-
 void Instruction::InsertAfter(Instruction* prev) {
   ASSERT(previous_ == NULL);
   ASSERT(next_ == NULL);
@@ -357,6 +369,13 @@
   next_ = prev->next_;
   next_->previous_ = this;
   previous_->next_ = this;
+
+  // Update def-use chains whenever instructions are added to the graph
+  // after initial graph construction.
+  for (intptr_t i = InputCount() - 1; i >= 0; --i) {
+    Value* input = InputAt(i);
+    input->definition()->AddInputUse(input);
+  }
 }
 
 
@@ -473,7 +492,6 @@
     if (next != NULL) next->set_previous_use(prev);
   }
 
-  set_definition(NULL);
   set_previous_use(NULL);
   set_next_use(NULL);
 }
@@ -535,28 +553,18 @@
   for (intptr_t i = other->InputCount() - 1; i >= 0; --i) {
     Value* input = other->InputAt(i);
     input->definition()->AddInputUse(input);
-    input->set_instruction(other);
-    input->set_use_index(i);
   }
   // Take other's environment from this definition.
   ASSERT(other->env() == NULL);
-  intptr_t use_index = 0;
-  for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) {
-    Value* use = it.CurrentValue();
-    use->set_instruction(other);
-    use->set_use_index(use_index++);
-  }
-  other->set_env(env());
-  set_env(NULL);
+  other->SetEnvironment(env());
+  env_ = NULL;
   // Replace all uses of this definition with other.
   ReplaceUsesWith(other);
   // Reuse this instruction's SSA name for other.
   ASSERT(!other->HasSSATemp());
   if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index());
-  // Remove this definition's input uses.
-  UnuseAllInputs();
 
-  // Finally remove this definition from the graph.
+  // Finally insert the other definition in place of this one in the graph.
   previous()->LinkTo(other);
   if ((iterator != NULL) && (this == iterator->Current())) {
     // Remove through the iterator.
@@ -564,34 +572,42 @@
     iterator->RemoveCurrentFromGraph();
   } else {
     other->LinkTo(next());
+    // Remove this definition's input uses.
+    UnuseAllInputs();
   }
   set_previous(NULL);
   set_next(NULL);
 }
 
 
+BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked)
+    : comparison_(comparison), is_checked_(is_checked) {
+  for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
+    comparison->InputAt(i)->set_instruction(this);
+  }
+}
+
+
+void BranchInstr::RawSetInputAt(intptr_t i, Value* value) {
+  comparison()->RawSetInputAt(i, value);
+}
+
+
 // A misleadingly named function for use in template functions that replace
 // both definitions with definitions and branch comparisons with
 // comparisons.  In the branch case, leave the branch intact and replace its
-// comparison with another comparison.
+// comparison with a new comparison not currently in the graph.
 void BranchInstr::ReplaceWith(ComparisonInstr* other,
                               ForwardInstructionIterator* ignored) {
-  // Record the new comparison's input uses.
-  for (intptr_t i = other->InputCount() - 1; i >= 0; --i) {
-    Value* input = other->InputAt(i);
-    input->definition()->AddInputUse(input);
-  }
   SetComparison(other);
 }
 
 
 void BranchInstr::SetComparison(ComparisonInstr* comp) {
-  // The new comparison's input uses are already recorded in their
-  // definition's use lists.
   for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) {
     Value* input = comp->InputAt(i);
+    input->definition()->AddInputUse(input);
     input->set_instruction(this);
-    input->set_use_index(i);
   }
   // There should be no need to copy or unuse an environment.
   ASSERT(comparison()->env() == NULL);
@@ -744,9 +760,9 @@
     // If the new and old predecessor index match there is nothing to update.
     if ((join->phis() == NULL) || (old_index == new_index)) return;
     // Otherwise, reorder the predecessor uses in each phi.
-    for (intptr_t i = 0; i < join->phis()->length(); ++i) {
-      PhiInstr* phi = (*join->phis())[i];
-      if (phi == NULL) continue;
+    for (PhiIterator it(join); !it.Done(); it.Advance()) {
+      PhiInstr* phi = it.Current();
+      ASSERT(phi != NULL);
       ASSERT(pred_count == phi->InputCount());
       // Save the predecessor use.
       Value* pred_use = phi->InputAt(old_index);
@@ -755,13 +771,10 @@
       for (intptr_t use_idx = old_index;
            use_idx != new_index;
            use_idx += step) {
-        Value* use = phi->InputAt(use_idx + step);
-        phi->SetInputAt(use_idx, use);
-        use->set_use_index(use_idx);
+        phi->SetInputAt(use_idx, phi->InputAt(use_idx + step));
       }
       // Write the predecessor use.
       phi->SetInputAt(new_index, pred_use);
-      pred_use->set_use_index(new_index);
     }
   }
 }
@@ -780,7 +793,6 @@
   }
   ASSERT((*phis_)[var_index] == NULL);
   (*phis_)[var_index] = new PhiInstr(this, PredecessorCount());
-  phi_count_++;
 }
 
 
@@ -790,23 +802,32 @@
     phis_ = new ZoneGrowableArray<PhiInstr*>(1);
   }
   phis_->Add(phi);
-  phi_count_++;
 }
 
 
-void JoinEntryInstr::RemoveDeadPhis() {
+void JoinEntryInstr::RemoveDeadPhis(Definition* replacement) {
   if (phis_ == NULL) return;
 
-  for (intptr_t i = 0; i < phis_->length(); i++) {
-    PhiInstr* phi = (*phis_)[i];
-    if ((phi != NULL) && !phi->is_alive()) {
-      (*phis_)[i] = NULL;
-      phi_count_--;
+  intptr_t to_index = 0;
+  for (intptr_t from_index = 0; from_index < phis_->length(); ++from_index) {
+    PhiInstr* phi = (*phis_)[from_index];
+    if (phi != NULL) {
+      if (phi->is_alive()) {
+        (*phis_)[to_index++] = phi;
+        for (intptr_t i = phi->InputCount() - 1; i >= 0; --i) {
+          Value* input = phi->InputAt(i);
+          input->definition()->AddInputUse(input);
+        }
+      } else {
+        phi->ReplaceUsesWith(replacement);
+      }
     }
   }
-
-  // Check if we removed all phis.
-  if (phi_count_ == 0) phis_ = NULL;
+  if (to_index == 0) {
+    phis_ = NULL;
+  } else {
+    phis_->TruncateTo(to_index);
+  }
 }
 
 
@@ -1169,9 +1190,7 @@
     // It is ok to insert instructions before the current during
     // forward iteration.
     optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue);
-    instantiator_type_arguments()->RemoveFromUseList();
-    instantiator_type_arguments()->set_definition(null_constant);
-    null_constant->AddInputUse(instantiator_type_arguments());
+    instantiator_type_arguments()->BindTo(null_constant);
   }
   return this;
 }
@@ -1200,9 +1219,6 @@
         (comp->input_use_list()->next_use() == NULL) &&
         (comp->env_use_list() == NULL)) {
       comp->RemoveFromGraph();
-      // It is safe to pass a NULL iterator because we're replacing the
-      // comparison wrapped in a BranchInstr which does not modify the
-      // linked list of instructions.
       SetComparison(comp);
       if (FLAG_trace_optimization) {
         OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index());
@@ -1536,14 +1552,11 @@
   }
 
   Environment* copy = DeepCopy();
-  intptr_t use_index = 0;
+  instr->SetEnvironment(copy);
   for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
     Value* value = it.CurrentValue();
-    value->set_instruction(instr);
-    value->set_use_index(use_index++);
     value->definition()->AddEnvUse(value);
   }
-  instr->set_env(copy);
 }
 
 
@@ -1555,6 +1568,7 @@
   ASSERT(instr->env()->outer() == NULL);
   intptr_t argument_count = instr->env()->fixed_parameter_count();
   Environment* copy = DeepCopy(values_.length() - argument_count);
+  instr->env()->outer_ = copy;
   intptr_t use_index = instr->env()->Length();  // Start index after inner.
   for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
     Value* value = it.CurrentValue();
@@ -1562,7 +1576,6 @@
     value->set_use_index(use_index++);
     value->definition()->AddEnvUse(value);
   }
-  instr->env()->outer_ = copy;
 }
 
 
@@ -2171,16 +2184,34 @@
 }
 
 
+InvokeMathCFunctionInstr::InvokeMathCFunctionInstr(
+    ZoneGrowableArray<Value*>* inputs,
+    InstanceCallInstr* instance_call,
+    MethodRecognizer::Kind recognized_kind)
+    : inputs_(inputs),
+      locs_(NULL),
+      recognized_kind_(recognized_kind) {
+  ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_));
+  for (intptr_t i = 0; i < inputs_->length(); ++i) {
+    ASSERT((*inputs)[i] != NULL);
+    (*inputs)[i]->set_instruction(this);
+    (*inputs)[i]->set_use_index(i);
+  }
+  deopt_id_ = instance_call->deopt_id();
+}
+
+
 intptr_t InvokeMathCFunctionInstr::ArgumentCountFor(
     MethodRecognizer::Kind kind) {
   switch (kind) {
     case MethodRecognizer::kDoubleTruncate:
-    case MethodRecognizer::kDoubleRound:
     case MethodRecognizer::kDoubleFloor:
     case MethodRecognizer::kDoubleCeil: {
       ASSERT(!CPUFeatures::double_truncate_round_supported());
       return 1;
     }
+    case MethodRecognizer::kDoubleRound:
+      return 1;
     case MethodRecognizer::kDoubleMod:
     case MethodRecognizer::kDoublePow:
       return 2;
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 4d25a91..976fa13 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -73,7 +73,7 @@
   V(_GrowableObjectArray, get:_capacity, GrowableArrayCapacity, 725548050)     \
   V(_StringBase, get:length, StringBaseLength, 320803993)                      \
   V(_StringBase, get:isEmpty, StringBaseIsEmpty, 711547329)                    \
-  V(_StringBase, charCodeAt, StringBaseCharCodeAt, 984449525)                  \
+  V(_StringBase, codeUnitAt, StringBaseCodeUnitAt, 984449525)                  \
   V(_StringBase, [], StringBaseCharAt, 1062366987)                             \
   V(_IntegerImplementation, toDouble, IntegerToDouble, 733149324)              \
   V(_Double, toInt, DoubleToInteger, 362666636)                                \
@@ -113,11 +113,27 @@
 // Values of CompileType form a lattice with a None type as a bottom and a
 // nullable Dynamic type as a top element. Method Union provides a join
 // operation for the lattice.
-class CompileType {
+class CompileType : public ValueObject {
  public:
   static const bool kNullable = true;
   static const bool kNonNullable = false;
 
+  CompileType(bool is_nullable, intptr_t cid, const AbstractType* type)
+      : is_nullable_(is_nullable), cid_(cid), type_(type) { }
+
+  CompileType(const CompileType& other)
+      : ValueObject(),
+        is_nullable_(other.is_nullable_),
+        cid_(other.cid_),
+        type_(other.type_) { }
+
+  CompileType& operator=(const CompileType& other) {
+    is_nullable_ = other.is_nullable_;
+    cid_ = other.cid_;
+    type_ =  other.type_;
+    return *this;
+  }
+
   // Return type such that concrete value's type in runtime is guaranteed to
   // be subtype of it.
   const AbstractType* ToAbstractType();
@@ -197,9 +213,6 @@
   const char* ToCString() const;
 
  private:
-  CompileType(bool is_nullable, intptr_t cid, const AbstractType* type)
-      : is_nullable_(is_nullable), cid_(cid), type_(type) { }
-
   bool CanComputeIsInstanceOf(const AbstractType& type,
                               bool is_nullable,
                               bool* is_instance);
@@ -274,6 +287,9 @@
   static void AddToList(Value* value, Value** list);
   void RemoveFromUseList();
 
+  // Change the definition after use lists have been computed.
+  inline void BindTo(Definition* definition);
+
   Value* Copy() { return new Value(definition_); }
 
   // This function must only be used when the new Value is dominated by
@@ -336,9 +352,7 @@
 template<typename T, intptr_t N>
 class EmbeddedArray {
  public:
-  EmbeddedArray() {
-    for (intptr_t i = 0; i < N; i++) elements_[i] = NULL;
-  }
+  EmbeddedArray() : elements_() { }
 
   intptr_t length() const { return N; }
 
@@ -510,7 +524,12 @@
 
   virtual intptr_t InputCount() const = 0;
   virtual Value* InputAt(intptr_t i) const = 0;
-  virtual void SetInputAt(intptr_t i, Value* value) = 0;
+  void SetInputAt(intptr_t i, Value* value) {
+    ASSERT(value != NULL);
+    value->set_instruction(this);
+    value->set_use_index(i);
+    RawSetInputAt(i, value);
+  }
 
   // Remove all inputs (including in the environment) from their
   // definition's use lists.
@@ -561,7 +580,9 @@
     next->set_previous(this);
   }
 
-  // Removed this instruction from the graph.
+  // Removed this instruction from the graph, after use lists have been
+  // computed.  If the instruction is a definition with uses, those uses are
+  // unaffected (so the instruction can be reinserted, e.g., hoisting).
   Instruction* RemoveFromGraph(bool return_previous = true);
 
   // Normal instructions can have 0 (inside a block) or 1 (last instruction in
@@ -607,7 +628,8 @@
   }
 
   Environment* env() const { return env_; }
-  void set_env(Environment* env) { env_ = env; }
+  void SetEnvironment(Environment* deopt_env);
+  void RemoveEnvironment();
 
   intptr_t lifetime_position() const { return lifetime_position_; }
   void set_lifetime_position(intptr_t pos) {
@@ -641,10 +663,12 @@
   // change.
   virtual Instruction* Canonicalize(FlowGraphOptimizer* optimizer);
 
-  // Insert this instruction before 'next'.
-  void InsertBefore(Instruction* next);
+  // Insert this instruction before 'next' after use lists are computed.
+  // Instructions cannot be inserted before a block entry or any other
+  // instruction without a previous instruction.
+  void InsertBefore(Instruction* next) { InsertAfter(next->previous()); }
 
-  // Insert this instruction after 'prev'.
+  // Insert this instruction after 'prev' after use lists are computed.
   void InsertAfter(Instruction* prev);
 
   // Returns true if the instruction is affected by side effects.
@@ -708,6 +732,8 @@
   friend class FlowGraphOptimizer;
   friend class LoadIndexedInstr;
 
+  virtual void RawSetInputAt(intptr_t i, Value* value) = 0;
+
   intptr_t deopt_id_;
   intptr_t lifetime_position_;  // Position used by register allocator.
   Instruction* previous_;
@@ -726,10 +752,6 @@
 
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
-  virtual void SetInputAt(intptr_t i, Value* value) {
-    ASSERT(value != NULL);
-    inputs_[i] = value;
-  }
 
   virtual LocationSummary* locs() {
     if (locs_ == NULL) {
@@ -742,6 +764,10 @@
   EmbeddedArray<Value*, N> inputs_;
 
  private:
+  virtual void RawSetInputAt(intptr_t i, Value* value) {
+    inputs_[i] = value;
+  }
+
   LocationSummary* locs_;
 };
 
@@ -923,7 +949,6 @@
     UNREACHABLE();
     return NULL;
   }
-  virtual void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
 
   virtual intptr_t ArgumentCount() const { return 0; }
 
@@ -960,6 +985,8 @@
         loop_info_(NULL) { }
 
  private:
+  virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+
   virtual void ClearPredecessors() = 0;
   virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0;
 
@@ -1092,8 +1119,7 @@
   JoinEntryInstr(intptr_t block_id, intptr_t try_index)
       : BlockEntryInstr(block_id, try_index),
         predecessors_(2),  // Two is the assumed to be the common case.
-        phis_(NULL),
-        phi_count_(0) { }
+        phis_(NULL) { }
 
   DECLARE_INSTRUCTION(JoinEntry)
 
@@ -1110,12 +1136,10 @@
   virtual void PrepareEntry(FlowGraphCompiler* compiler);
 
   void InsertPhi(intptr_t var_index, intptr_t var_count);
-  void RemoveDeadPhis();
+  void RemoveDeadPhis(Definition* replacement);
 
   void InsertPhi(PhiInstr* phi);
 
-  intptr_t phi_count() const { return phi_count_; }
-
   virtual void PrintTo(BufferFormatter* f) const;
 
  private:
@@ -1123,12 +1147,14 @@
   friend class BlockEntryInstr;
   friend class ValueInliningContext;
 
+  // Direct access to phis_ in order to resize it due to phi elimination.
+  friend class ConstantPropagator;
+
   virtual void ClearPredecessors() { predecessors_.Clear(); }
   virtual void AddPredecessor(BlockEntryInstr* predecessor);
 
   GrowableArray<BlockEntryInstr*> predecessors_;
   ZoneGrowableArray<PhiInstr*>* phis_;
-  intptr_t phi_count_;
 
   DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr);
 };
@@ -1137,15 +1163,11 @@
 class PhiIterator : public ValueObject {
  public:
   explicit PhiIterator(JoinEntryInstr* join)
-      : phis_(join->phis()), index_(-1) {
-    if (!Done()) Advance();  // Advance to the first phi.
-  }
+      : phis_(join->phis()), index_(0) { }
 
   void Advance() {
     ASSERT(!Done());
-    do {
-      index_++;
-    } while (!Done() && (Current() == NULL));
+    index_++;
   }
 
   bool Done() const {
@@ -1369,9 +1391,17 @@
 };
 
 
+// Change a value's definition after use lists have been computed.
+inline void Value::BindTo(Definition* def) {
+  RemoveFromUseList();
+  set_definition(def);
+  def->AddInputUse(this);
+}
+
+
 class PhiInstr : public Definition {
  public:
-  explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
+  PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
     : block_(block),
       inputs_(num_inputs),
       is_alive_(false),
@@ -1395,8 +1425,6 @@
 
   Value* InputAt(intptr_t i) const { return inputs_[i]; }
 
-  void SetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
-
   virtual bool CanDeoptimize() const { return false; }
 
   virtual bool HasSideEffect() const { return false; }
@@ -1437,7 +1465,11 @@
   }
 
  private:
-  friend class ConstantPropagator;  // Direct access to inputs_.
+  // Direct access to inputs_ in order to resize it due to unreachable
+  // predecessors.
+  friend class ConstantPropagator;
+
+  void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
 
   JoinEntryInstr* block_;
   GrowableArray<Value*> inputs_;
@@ -1452,7 +1484,7 @@
 
 class ParameterInstr : public Definition {
  public:
-  explicit ParameterInstr(intptr_t index, GraphEntryInstr* block)
+  ParameterInstr(intptr_t index, GraphEntryInstr* block)
       : index_(index), block_(block) { }
 
   DECLARE_INSTRUCTION(Parameter)
@@ -1469,7 +1501,6 @@
     UNREACHABLE();
     return NULL;
   }
-  void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
 
   virtual bool CanDeoptimize() const { return false; }
 
@@ -1485,6 +1516,8 @@
   virtual CompileType ComputeType() const;
 
  private:
+  virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+
   const intptr_t index_;
   GraphEntryInstr* block_;
 
@@ -1494,8 +1527,8 @@
 
 class PushArgumentInstr : public Definition {
  public:
-  explicit PushArgumentInstr(Value* value) : value_(value), locs_(NULL) {
-    ASSERT(value != NULL);
+  explicit PushArgumentInstr(Value* value) : locs_(NULL) {
+    SetInputAt(0, value);
     set_use_kind(kEffect);  // Override the default.
   }
 
@@ -1506,10 +1539,6 @@
     ASSERT(i == 0);
     return value_;
   }
-  void SetInputAt(intptr_t i, Value* value) {
-    ASSERT(i == 0);
-    value_ = value;
-  }
 
   virtual intptr_t ArgumentCount() const { return 0; }
 
@@ -1536,6 +1565,11 @@
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
  private:
+  virtual void RawSetInputAt(intptr_t i, Value* value) {
+    ASSERT(i == 0);
+    value_ = value;
+  }
+
   Value* value_;
   LocationSummary* locs_;
 
@@ -1552,8 +1586,7 @@
  public:
   ReturnInstr(intptr_t token_pos, Value* value)
       : token_pos_(token_pos) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   DECLARE_INSTRUCTION(Return)
@@ -1691,15 +1724,13 @@
 
 class BranchInstr : public ControlInstruction {
  public:
-  explicit BranchInstr(ComparisonInstr* comparison, bool is_checked = false)
-      : comparison_(comparison), is_checked_(is_checked) { }
+  explicit BranchInstr(ComparisonInstr* comparison, bool is_checked = false);
 
   DECLARE_INSTRUCTION(Branch)
 
   virtual intptr_t ArgumentCount() const;
   intptr_t InputCount() const;
   Value* InputAt(intptr_t i) const;
-  void SetInputAt(intptr_t i, Value* value);
   virtual bool CanDeoptimize() const;
 
   virtual bool HasSideEffect() const;
@@ -1726,6 +1757,8 @@
   virtual void PrintTo(BufferFormatter* f) const;
 
  private:
+  virtual void RawSetInputAt(intptr_t i, Value* value);
+
   ComparisonInstr* comparison_;
   const bool is_checked_;
 
@@ -1736,8 +1769,7 @@
 class StoreContextInstr : public TemplateInstruction<1> {
  public:
   explicit StoreContextInstr(Value* value) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   DECLARE_INSTRUCTION(StoreContext);
@@ -1762,10 +1794,6 @@
 
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
-  virtual void SetInputAt(intptr_t i, Value* value) {
-    ASSERT(value != NULL);
-    inputs_[i] = value;
-  }
 
   // Returns a structure describing the location constraints required
   // to emit native code for this definition.
@@ -1782,6 +1810,10 @@
  private:
   friend class BranchInstr;
 
+  virtual void RawSetInputAt(intptr_t i, Value* value) {
+    inputs_[i] = value;
+  }
+
   LocationSummary* locs_;
 };
 
@@ -1949,8 +1981,7 @@
  public:
   ConstraintInstr(Value* value, Range* constraint)
       : constraint_(constraint) {
-    inputs_[0] = value;
-    inputs_[1] = NULL;  // Dependency.
+    SetInputAt(0, value);
   }
 
   DECLARE_INSTRUCTION(Constraint)
@@ -1979,10 +2010,8 @@
 
   void AddDependency(Definition* defn) {
     Value* val = new Value(defn);
-    val->set_use_index(1);
-    val->set_instruction(this);
     defn->AddInputUse(val);
-    set_dependency(val);
+    SetInputAt(1, val);
   }
 
  private:
@@ -1990,10 +2019,6 @@
     return inputs_[1];
   }
 
-  void set_dependency(Value* value) {
-    inputs_[1] = value;
-  }
-
   Range* constraint_;
 
   DISALLOW_COPY_AND_ASSIGN(ConstraintInstr);
@@ -2039,14 +2064,11 @@
       : token_pos_(token_pos),
         dst_type_(AbstractType::ZoneHandle(dst_type.raw())),
         dst_name_(dst_name) {
-    ASSERT(value != NULL);
-    ASSERT(instantiator != NULL);
-    ASSERT(instantiator_type_arguments != NULL);
     ASSERT(!dst_type.IsNull());
     ASSERT(!dst_name.IsNull());
-    inputs_[0] = value;
-    inputs_[1] = instantiator;
-    inputs_[2] = instantiator_type_arguments;
+    SetInputAt(0, value);
+    SetInputAt(1, instantiator);
+    SetInputAt(2, instantiator_type_arguments);
   }
 
   DECLARE_INSTRUCTION(AssertAssignable)
@@ -2088,8 +2110,7 @@
  public:
   AssertBooleanInstr(intptr_t token_pos, Value* value)
       : token_pos_(token_pos) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   DECLARE_INSTRUCTION(AssertBoolean)
@@ -2121,8 +2142,7 @@
   ArgumentDefinitionTestInstr(ArgumentDefinitionTestNode* node,
                               Value* saved_arguments_descriptor)
       : ast_node_(*node) {
-    ASSERT(saved_arguments_descriptor != NULL);
-    inputs_[0] = saved_arguments_descriptor;
+    SetInputAt(0, saved_arguments_descriptor);
   }
 
   DECLARE_INSTRUCTION(ArgumentDefinitionTest)
@@ -2314,10 +2334,8 @@
  public:
   ComparisonInstr(Token::Kind kind, Value* left, Value* right)
       : kind_(kind) {
-    ASSERT(left != NULL);
-    ASSERT(right != NULL);
-    inputs_[0] = left;
-    inputs_[1] = right;
+    SetInputAt(0, left);
+    SetInputAt(1, right);
   }
 
   Value* left() const { return inputs_[0]; }
@@ -2351,11 +2369,6 @@
 }
 
 
-inline void BranchInstr::SetInputAt(intptr_t i, Value* value) {
-  comparison()->SetInputAt(i, value);
-}
-
-
 inline bool BranchInstr::CanDeoptimize() const {
   // Branches need a deoptimization info in checked mode if they
   // can throw a type check error.
@@ -2657,8 +2670,7 @@
                   intptr_t context_level)
       : local_(local),
         context_level_(context_level) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   DECLARE_INSTRUCTION(StoreLocal)
@@ -2720,17 +2732,21 @@
 };
 
 
+enum StoreBarrierType {
+  kNoStoreBarrier,
+  kEmitStoreBarrier
+};
+
+
 class StoreInstanceFieldInstr : public TemplateDefinition<2> {
  public:
   StoreInstanceFieldInstr(const Field& field,
                           Value* instance,
                           Value* value,
-                          bool emit_store_barrier)
+                          StoreBarrierType emit_store_barrier)
       : field_(field), emit_store_barrier_(emit_store_barrier) {
-    ASSERT(instance != NULL);
-    ASSERT(value != NULL);
-    inputs_[0] = instance;
-    inputs_[1] = value;
+    SetInputAt(0, instance);
+    SetInputAt(1, value);
   }
 
   DECLARE_INSTRUCTION(StoreInstanceField)
@@ -2741,7 +2757,8 @@
   Value* instance() const { return inputs_[0]; }
   Value* value() const { return inputs_[1]; }
   bool ShouldEmitStoreBarrier() const {
-    return value()->NeedsStoreBuffer() && emit_store_barrier_;
+    return value()->NeedsStoreBuffer()
+        && (emit_store_barrier_ == kEmitStoreBarrier);
   }
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
@@ -2752,7 +2769,7 @@
 
  private:
   const Field& field_;
-  const bool emit_store_barrier_;
+  const StoreBarrierType emit_store_barrier_;
 
   DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldInstr);
 };
@@ -2788,8 +2805,7 @@
   StoreStaticFieldInstr(const Field& field, Value* value)
       : field_(field) {
     ASSERT(field.IsZoneHandle());
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   DECLARE_INSTRUCTION(StoreStaticField);
@@ -2819,10 +2835,8 @@
                    intptr_t class_id,
                    intptr_t deopt_id)
       : index_scale_(index_scale), class_id_(class_id) {
-    ASSERT(array != NULL);
-    ASSERT(index != NULL);
-    inputs_[0] = array;
-    inputs_[1] = index;
+    SetInputAt(0, array);
+    SetInputAt(1, index);
     deopt_id_ = deopt_id;
   }
 
@@ -2858,13 +2872,12 @@
 
 class StringFromCharCodeInstr : public TemplateDefinition<1> {
  public:
-  explicit StringFromCharCodeInstr(Value* char_code,
-                                   intptr_t cid) : cid_(cid) {
+  StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) {
     ASSERT(char_code != NULL);
     ASSERT(char_code->definition()->IsLoadIndexed() &&
            (char_code->definition()->AsLoadIndexed()->class_id() ==
             kOneByteStringCid));
-    inputs_[0] = char_code;
+    SetInputAt(0, char_code);
   }
 
   DECLARE_INSTRUCTION(StringFromCharCode)
@@ -2892,18 +2905,15 @@
   StoreIndexedInstr(Value* array,
                     Value* index,
                     Value* value,
-                    bool emit_store_barrier,
+                    StoreBarrierType emit_store_barrier,
                     intptr_t class_id,
                     intptr_t deopt_id)
       : emit_store_barrier_(emit_store_barrier),
         class_id_(class_id),
         deopt_id_(deopt_id) {
-    ASSERT(array != NULL);
-    ASSERT(index != NULL);
-    ASSERT(value != NULL);
-    inputs_[0] = array;
-    inputs_[1] = index;
-    inputs_[2] = value;
+    SetInputAt(0, array);
+    SetInputAt(1, index);
+    SetInputAt(2, value);
   }
 
   DECLARE_INSTRUCTION(StoreIndexed)
@@ -2914,7 +2924,8 @@
   intptr_t class_id() const { return class_id_; }
 
   bool ShouldEmitStoreBarrier() const {
-    return value()->NeedsStoreBuffer() && emit_store_barrier_;
+    return value()->NeedsStoreBuffer()
+        && (emit_store_barrier_ == kEmitStoreBarrier);
   }
 
   virtual bool CanDeoptimize() const { return false; }
@@ -2930,7 +2941,7 @@
   }
 
  private:
-  const bool emit_store_barrier_;
+  const StoreBarrierType emit_store_barrier_;
   const intptr_t class_id_;
   const intptr_t deopt_id_;
 
@@ -2942,8 +2953,7 @@
 class BooleanNegateInstr : public TemplateDefinition<1> {
  public:
   explicit BooleanNegateInstr(Value* value) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   DECLARE_INSTRUCTION(BooleanNegate)
@@ -2971,13 +2981,10 @@
       : token_pos_(token_pos),
         type_(type),
         negate_result_(negate_result) {
-    ASSERT(value != NULL);
-    ASSERT(instantiator != NULL);
-    ASSERT(instantiator_type_arguments != NULL);
     ASSERT(!type.IsNull());
-    inputs_[0] = value;
-    inputs_[1] = instantiator;
-    inputs_[2] = instantiator_type_arguments;
+    SetInputAt(0, value);
+    SetInputAt(1, instantiator);
+    SetInputAt(2, instantiator_type_arguments);
   }
 
   DECLARE_INSTRUCTION(InstanceOf)
@@ -3052,10 +3059,8 @@
                                      Value* type_arguments,
                                      Value* instantiator)
       : ast_node_(*node) {
-    ASSERT(type_arguments != NULL);
-    ASSERT(instantiator != NULL);
-    inputs_[0] = type_arguments;
-    inputs_[1] = instantiator;
+    SetInputAt(0, type_arguments);
+    SetInputAt(1, instantiator);
   }
 
   DECLARE_INSTRUCTION(AllocateObjectWithBoundsCheck)
@@ -3085,13 +3090,10 @@
       : token_pos_(token_pos),
         num_elements_(num_elements),
         type_(type) {
-#if defined(DEBUG)
-    ASSERT(element_type != NULL);
     ASSERT(type_.IsZoneHandle());
     ASSERT(!type_.IsNull());
     ASSERT(type_.IsFinalized());
-#endif
-    inputs_[0] = element_type;
+    SetInputAt(0, element_type);
   }
 
   DECLARE_INSTRUCTION(CreateArray)
@@ -3164,9 +3166,8 @@
         result_cid_(kDynamicCid),
         immutable_(immutable),
         recognized_kind_(MethodRecognizer::kUnknown) {
-    ASSERT(value != NULL);
     ASSERT(type.IsZoneHandle());  // May be null if field is not an instance.
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   DECLARE_INSTRUCTION(LoadField)
@@ -3222,11 +3223,9 @@
                     Value* value,
                     const AbstractType& type)
       : offset_in_bytes_(offset_in_bytes), type_(type) {
-    ASSERT(value != NULL);
-    ASSERT(dest != NULL);
     ASSERT(type.IsZoneHandle());  // May be null if field is not an instance.
-    inputs_[0] = value;
-    inputs_[1] = dest;
+    SetInputAt(0, value);
+    SetInputAt(1, dest);
   }
 
   DECLARE_INSTRUCTION(StoreVMField)
@@ -3259,8 +3258,7 @@
       : token_pos_(token_pos),
         type_arguments_(type_arguments) {
     ASSERT(type_arguments.IsZoneHandle());
-    ASSERT(instantiator != NULL);
-    inputs_[0] = instantiator;
+    SetInputAt(0, instantiator);
   }
 
   DECLARE_INSTRUCTION(InstantiateTypeArguments)
@@ -3293,8 +3291,7 @@
       Value* instantiator)
       : token_pos_(token_pos),
         type_arguments_(type_arguments) {
-    ASSERT(instantiator != NULL);
-    inputs_[0] = instantiator;
+    SetInputAt(0, instantiator);
   }
 
   DECLARE_INSTRUCTION(ExtractConstructorTypeArguments)
@@ -3324,8 +3321,7 @@
   ExtractConstructorInstantiatorInstr(ConstructorCallNode* ast_node,
                                       Value* instantiator)
       : ast_node_(*ast_node) {
-    ASSERT(instantiator != NULL);
-    inputs_[0] = instantiator;
+    SetInputAt(0, instantiator);
   }
 
   DECLARE_INSTRUCTION(ExtractConstructorInstantiator)
@@ -3378,8 +3374,7 @@
 class ChainContextInstr : public TemplateInstruction<1> {
  public:
   explicit ChainContextInstr(Value* context_value) {
-    ASSERT(context_value != NULL);
-    inputs_[0] = context_value;
+    SetInputAt(0, context_value);
   }
 
   DECLARE_INSTRUCTION(ChainContext)
@@ -3401,8 +3396,7 @@
  public:
   CloneContextInstr(intptr_t token_pos, Value* context_value)
       : token_pos_(token_pos) {
-    ASSERT(context_value != NULL);
-    inputs_[0] = context_value;
+    SetInputAt(0, context_value);
   }
 
   intptr_t token_pos() const { return token_pos_; }
@@ -3454,10 +3448,8 @@
   CheckEitherNonSmiInstr(Value* left,
                          Value* right,
                          InstanceCallInstr* instance_call) {
-    ASSERT(left != NULL);
-    ASSERT(right != NULL);
-    inputs_[0] = left;
-    inputs_[1] = right;
+    SetInputAt(0, left);
+    SetInputAt(1, right);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -3488,8 +3480,7 @@
  public:
   BoxDoubleInstr(Value* value, InstanceCallInstr* instance_call)
       : token_pos_((instance_call != NULL) ? instance_call->token_pos() : 0) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   Value* value() const { return inputs_[0]; }
@@ -3521,8 +3512,7 @@
 class BoxIntegerInstr : public TemplateDefinition<1> {
  public:
   explicit BoxIntegerInstr(Value* value) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   Value* value() const { return inputs_[0]; }
@@ -3550,8 +3540,7 @@
 class UnboxDoubleInstr : public TemplateDefinition<1> {
  public:
   UnboxDoubleInstr(Value* value, intptr_t deopt_id) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
     deopt_id_ = deopt_id;
   }
 
@@ -3582,8 +3571,7 @@
 class UnboxIntegerInstr : public TemplateDefinition<1> {
  public:
   UnboxIntegerInstr(Value* value, intptr_t deopt_id) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
     deopt_id_ = deopt_id;
   }
 
@@ -3616,8 +3604,7 @@
 class MathSqrtInstr : public TemplateDefinition<1> {
  public:
   MathSqrtInstr(Value* value, StaticCallInstr* instance_call) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -3661,10 +3648,8 @@
                       Value* right,
                       InstanceCallInstr* instance_call)
       : op_kind_(op_kind) {
-    ASSERT(left != NULL);
-    ASSERT(right != NULL);
-    inputs_[0] = left;
-    inputs_[1] = right;
+    SetInputAt(0, left);
+    SetInputAt(1, right);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -3720,10 +3705,8 @@
                            InstanceCallInstr* instance_call)
       : op_kind_(op_kind),
         instance_call_(instance_call) {
-    ASSERT(left != NULL);
-    ASSERT(right != NULL);
-    inputs_[0] = left;
-    inputs_[1] = right;
+    SetInputAt(0, left);
+    SetInputAt(1, right);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -3785,11 +3768,9 @@
                    Value* right,
                    InstanceCallInstr* instance_call)
       : op_kind_(op_kind) {
-    ASSERT(left != NULL);
-    ASSERT(right != NULL);
     ASSERT(op_kind == Token::kSHR || op_kind == Token::kSHL);
-    inputs_[0] = left;
-    inputs_[1] = right;
+    SetInputAt(0, left);
+    SetInputAt(1, right);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -3842,9 +3823,8 @@
                           Value* value,
                           InstanceCallInstr* instance_call)
       : op_kind_(op_kind) {
-    ASSERT(value != NULL);
     ASSERT(op_kind == Token::kBIT_NOT);
-    inputs_[0] = value;
+    SetInputAt(0, value);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -3900,10 +3880,8 @@
         instance_call_(instance_call),
         overflow_(true),
         is_truncating_(false) {
-    ASSERT(left != NULL);
-    ASSERT(right != NULL);
-    inputs_[0] = left;
-    inputs_[1] = right;
+    SetInputAt(0, left);
+    SetInputAt(1, right);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -3966,8 +3944,7 @@
                   Value* value)
       : op_kind_(op_kind) {
     ASSERT((op_kind == Token::kNEGATE) || (op_kind == Token::kBIT_NOT));
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -4039,8 +4016,7 @@
  public:
   DoubleToIntegerInstr(Value* value, InstanceCallInstr* instance_call)
       : instance_call_(instance_call) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
   }
 
   Value* value() const { return inputs_[0]; }
@@ -4067,8 +4043,7 @@
 class DoubleToSmiInstr : public TemplateDefinition<1> {
  public:
   DoubleToSmiInstr(Value* value, InstanceCallInstr* instance_call) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -4099,8 +4074,7 @@
                       InstanceCallInstr* instance_call,
                       MethodRecognizer::Kind recognized_kind)
     : recognized_kind_(recognized_kind) {
-    ASSERT(value != NULL);
-    inputs_[0] = value;
+    SetInputAt(0, value);
     deopt_id_ = instance_call->deopt_id();
   }
 
@@ -4137,11 +4111,7 @@
  public:
   InvokeMathCFunctionInstr(ZoneGrowableArray<Value*>* inputs,
                            InstanceCallInstr* instance_call,
-                           MethodRecognizer::Kind recognized_kind)
-    : inputs_(inputs), locs_(NULL), recognized_kind_(recognized_kind) {
-    ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_));
-    deopt_id_ = instance_call->deopt_id();
-  }
+                           MethodRecognizer::Kind recognized_kind);
 
   static intptr_t ArgumentCountFor(MethodRecognizer::Kind recognized_kind_);
 
@@ -4176,11 +4146,6 @@
     return (*inputs_)[i];
   }
 
-  virtual void SetInputAt(intptr_t i, Value* value) {
-    ASSERT(value != NULL);
-    (*inputs_)[i] = value;
-  }
-
   // Returns a structure describing the location constraints required
   // to emit native code for this definition.
   LocationSummary* locs() {
@@ -4191,6 +4156,10 @@
   }
 
  private:
+  virtual void RawSetInputAt(intptr_t i, Value* value) {
+    (*inputs_)[i] = value;
+  }
+
   ZoneGrowableArray<Value*>* inputs_;
 
   LocationSummary* locs_;
@@ -4237,9 +4206,8 @@
 class CheckSmiInstr : public TemplateInstruction<1> {
  public:
   CheckSmiInstr(Value* value, intptr_t original_deopt_id) {
-    ASSERT(value != NULL);
     ASSERT(original_deopt_id != Isolate::kNoDeoptId);
-    inputs_[0] = value;
+    SetInputAt(0, value);
     deopt_id_ = original_deopt_id;
   }
 
@@ -4271,10 +4239,8 @@
                        intptr_t array_type,
                        InstanceCallInstr* instance_call)
       : array_type_(array_type) {
-    ASSERT(length != NULL);
-    ASSERT(index != NULL);
-    inputs_[0] = length;
-    inputs_[1] = index;
+    SetInputAt(0, length);
+    SetInputAt(1, index);
     deopt_id_ = instance_call->deopt_id();
   }
 
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index f35ed33..6ca6c8f 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -16,14 +16,19 @@
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
 
+#define __ compiler->assembler()->
+
 namespace dart {
 
 DECLARE_FLAG(int, optimization_counter_threshold);
 DECLARE_FLAG(bool, propagate_ic_data);
 
+// Generic summary for call instructions that have all arguments pushed
+// on the stack and return the result in a fixed register R0.
 LocationSummary* Instruction::MakeCallSummary() {
-  UNIMPLEMENTED();
-  return NULL;
+  LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall);
+  result->set_out(Location::RegisterLocation(R0));
+  return result;
 }
 
 
@@ -39,13 +44,43 @@
 
 
 LocationSummary* ReturnInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(R0));
+  return locs;
 }
 
 
+// Attempt optimized compilation at return instruction instead of at the entry.
+// The entry needs to be patchable, no inlined objects are allowed in the area
+// that will be overwritten by the patch instructions: a branch macro sequence.
 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  Register result = locs()->in(0).reg();
+  ASSERT(result == R0);
+#if defined(DEBUG)
+  // TODO(srdjan): Fix for functions with finally clause.
+  // A finally clause may leave a previously pushed return value if it
+  // has its own return instruction. Method that have finally are currently
+  // not optimized.
+  if (!compiler->HasFinally()) {
+    __ sub(R2, FP, ShifterOperand(SP));
+    // + 1 for saved PP.
+    __ CompareImmediate(R2, (compiler->StackSize() + 1) * kWordSize);
+    __ bkpt(0, NE);
+  }
+#endif
+  AssemblerMacros::LeaveDartFrame(compiler->assembler());
+  __ Ret();
+
+  // Generate 2 NOP instructions so that the debugger can patch the return
+  // pattern (1 instruction) with a call to the debug stub (3 instructions).
+  __ nop();
+  __ nop();
+  compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
+                                 Isolate::kNoDeoptId,
+                                 token_pos());
 }
 
 
@@ -78,13 +113,18 @@
 
 
 LocationSummary* ConstantInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  return LocationSummary::Make(0,
+                               Location::RequiresRegister(),
+                               LocationSummary::kNoCall);
 }
 
 
 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  // The register allocator drops constant definitions that have no uses.
+  if (!locs()->out().IsInvalid()) {
+    Register result = locs()->out().reg();
+    __ LoadObject(result, value());
+  }
 }
 
 
@@ -364,13 +404,52 @@
 
 
 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary() const {
-  UNIMPLEMENTED();
-  return NULL;
+  const intptr_t kNumInputs = 0;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs,
+                          kNumTemps,
+                          LocationSummary::kCallOnSlowPath);
+  return summary;
 }
 
 
+class CheckStackOverflowSlowPath : public SlowPathCode {
+ public:
+  explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction)
+      : instruction_(instruction) { }
+
+  virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+    __ Comment("CheckStackOverflowSlowPath");
+    __ Bind(entry_label());
+    compiler->SaveLiveRegisters(instruction_->locs());
+    // pending_deoptimization_env_ is needed to generate a runtime call that
+    // may throw an exception.
+    ASSERT(compiler->pending_deoptimization_env_ == NULL);
+    compiler->pending_deoptimization_env_ = instruction_->env();
+    compiler->GenerateCallRuntime(instruction_->token_pos(),
+                                  instruction_->deopt_id(),
+                                  kStackOverflowRuntimeEntry,
+                                  instruction_->locs());
+    compiler->pending_deoptimization_env_ = NULL;
+    compiler->RestoreLiveRegisters(instruction_->locs());
+    __ b(exit_label());
+  }
+
+ private:
+  CheckStackOverflowInstr* instruction_;
+};
+
+
 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNIMPLEMENTED();
+  CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
+  compiler->AddSlowPathCode(slow_path);
+
+  __ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
+  __ ldr(IP, Address(IP));
+  __ cmp(SP, ShifterOperand(IP));
+  __ b(slow_path->entry_label(), LS);
+  __ Bind(slow_path->exit_label());
 }
 
 
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 50a4972..776f6dc 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -2714,15 +2714,11 @@
 
 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps =
-      (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* result =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   result->set_in(0, Location::RequiresFpuRegister());
   result->set_out(Location::RequiresFpuRegister());
-  if (recognized_kind() == MethodRecognizer::kDoubleRound) {
-    result->set_temp(0, Location::RequiresFpuRegister());
-  }
   return result;
 }
 
@@ -2740,11 +2736,6 @@
     case MethodRecognizer::kDoubleCeil:
       __ roundsd(result, value,  Assembler::kRoundUp);
       break;
-    case MethodRecognizer::kDoubleRound: {
-      XmmRegister temp = locs()->temp(0).fpu_reg();
-      __ DoubleRound(result, value, temp);
-      break;
-    }
     default:
       UNREACHABLE();
   }
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 7b8f669..7d023f8 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -2561,15 +2561,11 @@
 
 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps =
-      (recognized_kind() == MethodRecognizer::kDoubleRound) ? 1 : 0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* result =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
   result->set_in(0, Location::RequiresFpuRegister());
   result->set_out(Location::RequiresFpuRegister());
-  if (recognized_kind() == MethodRecognizer::kDoubleRound) {
-    result->set_temp(0, Location::RequiresFpuRegister());
-  }
   return result;
 }
 
@@ -2587,11 +2583,6 @@
     case MethodRecognizer::kDoubleCeil:
       __ roundsd(result, value,  Assembler::kRoundUp);
       break;
-    case MethodRecognizer::kDoubleRound: {
-      XmmRegister temp = locs()->temp(0).fpu_reg();
-      __ DoubleRound(result, value, temp);
-      break;
-    }
     default:
       UNREACHABLE();
   }
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 379c6c1..16b3893 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -60,7 +60,7 @@
   V(_Double, _mulFromInteger, Double_mulFromInteger, 815838159)                \
   V(_Double, .fromInteger, Double_fromInteger, 842078193)                      \
   V(_Double, toInt, Double_toInt, 362666636)                                   \
-  V(_ObjectArray, ., ObjectArray_Allocate, 577949617)                          \
+  V(_ObjectArray, ., ObjectArray_Allocate, 97987288)                           \
   V(_ObjectArray, get:length, Array_getLength, 405297088)                      \
   V(_ObjectArray, [], Array_getIndexed, 71937385)                              \
   V(_ObjectArray, []=, Array_setIndexed, 255863719)                            \
@@ -78,7 +78,8 @@
   V(_StringBase, get:hashCode, String_getHashCode, 320803993)                  \
   V(_StringBase, get:isEmpty, String_getIsEmpty, 711547329)                    \
   V(_StringBase, get:length, String_getLength, 320803993)                      \
-  V(_StringBase, charCodeAt, String_charCodeAt, 984449525)                     \
+  V(_StringBase, codeUnitAt, String_codeUnitAt, 984449525)                     \
+  V(_OneByteString, get:hashCode, OneByteString_getHashCode, 682660413)        \
 
 
 #define MATH_LIB_INTRINSIC_LIST(V)                                             \
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index c2b7c2b..2905a38 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -374,7 +374,7 @@
 }
 
 
-bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
+bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
   return false;
 }
 
@@ -383,6 +383,11 @@
   return false;
 }
 
+
+bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+  return false;
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 7bd0c89..c25075d 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -1435,7 +1435,7 @@
 
 
 // TODO(srdjan): Implement for two and four byte strings as well.
-bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
+bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
   Label fall_through;
   __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Index.
   __ movl(EAX, Address(ESP, + 2 * kWordSize));  // String.
@@ -1471,6 +1471,76 @@
   return true;
 }
 
+
+bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+  Label compute_hash;
+  __ movl(EBX, Address(ESP, + 1 * kWordSize));  // OneByteString object.
+  __ movl(EAX, FieldAddress(EBX, String::hash_offset()));
+  __ cmpl(EAX, Immediate(0));
+  __ j(EQUAL, &compute_hash, Assembler::kNearJump);
+  __ ret();
+
+  __ Bind(&compute_hash);
+  // Hash not yet computed, use algorithm of class StringHasher.
+  __ movl(ECX, FieldAddress(EBX, String::length_offset()));
+  __ SmiUntag(ECX);
+  __ xorl(EAX, EAX);
+  __ xorl(EDI, EDI);
+  // EBX: Instance of OneByteString.
+  // ECX: String length, untagged integer.
+  // EDI: Loop counter, untagged integer.
+  // EAX: Hash code, untagged integer.
+  Label loop, done, set_hash_code;
+  __ Bind(&loop);
+  __ cmpl(EDI, ECX);
+  __ j(EQUAL, &done, Assembler::kNearJump);
+  // Add to hash code: (hash_ is uint32)
+  // hash_ += ch;
+  // hash_ += hash_ << 10;
+  // hash_ ^= hash_ >> 6;
+  // Get one characters (ch).
+  __ movzxb(EDX, FieldAddress(EBX, EDI, TIMES_1, OneByteString::data_offset()));
+  // EDX: ch and temporary.
+  __ addl(EAX, EDX);
+  __ movl(EDX, EAX);
+  __ shll(EDX, Immediate(10));
+  __ addl(EAX, EDX);
+  __ movl(EDX, EAX);
+  __ shrl(EDX, Immediate(6));
+  __ xorl(EAX, EDX);
+
+  __ incl(EDI);
+  __ jmp(&loop, Assembler::kNearJump);
+
+  __ Bind(&done);
+  // Finalize:
+  // hash_ += hash_ << 3;
+  // hash_ ^= hash_ >> 11;
+  // hash_ += hash_ << 15;
+  __ movl(EDX, EAX);
+  __ shll(EDX, Immediate(3));
+  __ addl(EAX, EDX);
+  __ movl(EDX, EAX);
+  __ shrl(EDX, Immediate(11));
+  __ xorl(EAX, EDX);
+  __ movl(EDX, EAX);
+  __ shll(EDX, Immediate(15));
+  __ addl(EAX, EDX);
+  // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
+  __ andl(EAX,
+      Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1)));
+
+  // return hash_ == 0 ? 1 : hash_;
+  __ cmpl(EAX, Immediate(0));
+  __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump);
+  __ incl(EAX);
+  __ Bind(&set_hash_code);
+  __ SmiTag(EAX);
+  __ movl(FieldAddress(EBX, String::hash_offset()), EAX);
+  __ ret();
+  return true;
+}
+
 #undef __
 }  // namespace dart
 
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 70540a6..08a298c 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -374,7 +374,7 @@
 }
 
 
-bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
+bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
   return false;
 }
 
@@ -383,6 +383,11 @@
   return false;
 }
 
+
+bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+  return false;
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 694c384..b72beb0 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -1358,7 +1358,7 @@
 
 
 // TODO(srdjan): Implement for two and four byte strings as well.
-bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
+bool Intrinsifier::String_codeUnitAt(Assembler* assembler) {
   Label fall_through;
   __ movq(RCX, Address(RSP, + 1 * kWordSize));  // Index.
   __ movq(RAX, Address(RSP, + 2 * kWordSize));  // String.
@@ -1394,6 +1394,77 @@
   return true;
 }
 
+
+bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
+  Label compute_hash;
+  __ movq(RBX, Address(RSP, + 1 * kWordSize));  // OneByteString object.
+  __ movq(RAX, FieldAddress(RBX, String::hash_offset()));
+  __ cmpq(RAX, Immediate(0));
+  __ j(EQUAL, &compute_hash, Assembler::kNearJump);
+  __ ret();
+
+  __ Bind(&compute_hash);
+  // Hash not yet computed, use algorithm of class StringHasher.
+  __ movq(RCX, FieldAddress(RBX, String::length_offset()));
+  __ SmiUntag(RCX);
+  __ xorq(RAX, RAX);
+  __ xorq(RDI, RDI);
+  // RBX: Instance of OneByteString.
+  // RCX: String length, untagged integer.
+  // RDI: Loop counter, untagged integer.
+  // RAX: Hash code, untagged integer.
+  Label loop, done, set_hash_code;
+  __ Bind(&loop);
+  __ cmpq(RDI, RCX);
+  __ j(EQUAL, &done, Assembler::kNearJump);
+  // Add to hash code: (hash_ is uint32)
+  // hash_ += ch;
+  // hash_ += hash_ << 10;
+  // hash_ ^= hash_ >> 6;
+  // Get one characters (ch).
+  __ movzxb(RDX, FieldAddress(RBX, RDI, TIMES_1, OneByteString::data_offset()));
+  // RDX: ch and temporary.
+  __ addl(RAX, RDX);
+  __ movq(RDX, RAX);
+  __ shll(RDX, Immediate(10));
+  __ addl(RAX, RDX);
+  __ movq(RDX, RAX);
+  __ shrl(RDX, Immediate(6));
+  __ xorl(RAX, RDX);
+
+  __ incq(RDI);
+  __ jmp(&loop, Assembler::kNearJump);
+
+  __ Bind(&done);
+  // Finalize:
+  // hash_ += hash_ << 3;
+  // hash_ ^= hash_ >> 11;
+  // hash_ += hash_ << 15;
+  __ movq(RDX, RAX);
+  __ shll(RDX, Immediate(3));
+  __ addl(RAX, RDX);
+  __ movq(RDX, RAX);
+  __ shrl(RDX, Immediate(11));
+  __ xorl(RAX, RDX);
+  __ movq(RDX, RAX);
+  __ shll(RDX, Immediate(15));
+  __ addl(RAX, RDX);
+  // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
+  __ andl(RAX,
+      Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1)));
+
+  // return hash_ == 0 ? 1 : hash_;
+  __ cmpq(RAX, Immediate(0));
+  __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump);
+  __ incq(RAX);
+  __ Bind(&set_hash_code);
+  __ SmiTag(RAX);
+  __ movq(FieldAddress(RBX, String::hash_offset()), RAX);
+  __ ret();
+  return true;
+}
+
+
 #undef __
 
 }  // namespace dart
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 06ca69e..31e909b 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -191,8 +191,8 @@
   const Array& callback_args = Array::Handle(Array::New(1));
   callback_args.SetAt(0, exception);
   const Object& result =
-      Object::Handle(DartEntry::InvokeStatic(Function::Cast(function),
-                                             callback_args));
+      Object::Handle(DartEntry::InvokeFunction(Function::Cast(function),
+                                               callback_args));
   if (result.IsError()) {
     const Error& err = Error::Cast(result);
     OS::PrintErr("failed calling unhandled exception callback: %s\n",
@@ -388,6 +388,13 @@
 
 
 void Isolate::SetStackLimitFromCurrentTOS(uword stack_top_value) {
+#ifdef USING_SIMULATOR
+  // Ignore passed-in native stack top and use Simulator stack top.
+  Simulator* sim = Simulator::Current();  // May allocate a simulator.
+  ASSERT(simulator() == sim);  // This isolate's simulator is the current one.
+  stack_top_value = sim->StackTop();
+  // The overflow area is accounted for by the simulator.
+#endif
   SetStackLimit(stack_top_value - GetSpecifiedStackSize());
 }
 
@@ -627,4 +634,61 @@
   }
 }
 
+
+char* Isolate::GetStatus(const char* request) {
+  char* p = const_cast<char*>(request);
+  const char* service_type = "/isolate/";
+  ASSERT(strncmp(p, service_type, strlen(service_type)) == 0);
+  p += strlen(service_type);
+
+  // Extract isolate handle.
+  int64_t addr;
+  OS::StringToInt64(p, &addr);
+  Isolate* isolate = reinterpret_cast<Isolate*>(addr);
+  Heap* heap = isolate->heap();
+
+  char buffer[256];
+  int64_t port = isolate->main_port();
+  int64_t start_time = (isolate->start_time() / 1000L);
+#if defined(TARGET_ARCH_X64)
+  const char* format = "{\n"
+      "  \"name\": \"%s\",\n"
+      "  \"port\": %ld,\n"
+      "  \"starttime\": %ld,\n"
+      "  \"stacklimit\": %ld,\n"
+      "  \"newspace\": {\n"
+      "    \"used\": %ld,\n"
+      "    \"capacity\": %ld\n"
+      "  },\n"
+      "  \"oldspace\": {\n"
+      "    \"used\": %ld,\n"
+      "    \"capacity\": %ld\n"
+      "  }\n"
+      "}";
+#else
+  const char* format = "{\n"
+      "  \"name\": \"%s\",\n"
+      "  \"port\": %lld,\n"
+      "  \"starttime\": %lld,\n"
+      "  \"stacklimit\": %d,\n"
+      "  \"newspace\": {\n"
+      "    \"used\": %d,\n"
+      "    \"capacity\": %d\n"
+      "  },\n"
+      "  \"oldspace\": {\n"
+      "    \"used\": %d,\n"
+      "    \"capacity\": %d\n"
+      "  }\n"
+      "}";
+#endif
+  int n = OS::SNPrint(buffer, 256, format, isolate->name(), port, start_time,
+                      isolate->saved_stack_limit(),
+                      heap->Used(Heap::kNew) / KB,
+                      heap->Capacity(Heap::kNew) / KB,
+                      heap->Used(Heap::kOld) / KB,
+                      heap->Capacity(Heap::kOld) / KB);
+  ASSERT(n < 256);
+  return strdup(buffer);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index b8f03b5..2e6735f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -344,6 +344,8 @@
     return list;
   }
 
+  static char* GetStatus(const char* request);
+
  private:
   Isolate();
 
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index f8b7f6c..6a8dda8 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -366,15 +366,15 @@
     }
   }
 
-  bool ContainsRegister(Register reg) {
+  bool ContainsRegister(Register reg) const {
     return (cpu_registers_ & (1 << reg)) != 0;
   }
 
-  bool ContainsFpuRegister(FpuRegister fpu_reg) {
+  bool ContainsFpuRegister(FpuRegister fpu_reg) const {
     return (fpu_registers_ & (1 << fpu_reg)) != 0;
   }
 
-  intptr_t fpu_regs_count() {
+  intptr_t fpu_regs_count() const {
     intptr_t count = 0;
     for (intptr_t reg_idx = 0; reg_idx < kNumberOfFpuRegisters; reg_idx++) {
       if (ContainsFpuRegister(static_cast<FpuRegister>(reg_idx))) {
@@ -384,6 +384,9 @@
     return count;
   }
 
+  intptr_t cpu_registers() const { return cpu_registers_; }
+  intptr_t fpu_registers() const { return fpu_registers_; }
+
  private:
   intptr_t cpu_registers_;
   intptr_t fpu_registers_;
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index de192a2..1027e3f 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -7,6 +7,7 @@
 
 #include "platform/assert.h"
 #include "vm/globals.h"
+#include "vm/simulator.h"
 #include "vm/stub_code.h"
 
 namespace dart {
@@ -21,7 +22,13 @@
 
 #if defined(TESTING) || defined(DEBUG)
 
-#if defined(TARGET_OS_WINDOWS)
+#if defined(USING_SIMULATOR)
+#define CHECK_STACK_ALIGNMENT {                                                \
+  uword current_sp = Simulator::Current()->get_register(SPREG);                \
+  ASSERT((OS::ActivationFrameAlignment() == 0) ||                              \
+         (Utils::IsAligned(current_sp, OS::ActivationFrameAlignment())));      \
+}
+#elif defined(TARGET_OS_WINDOWS)
 // The compiler may dynamically align the stack on Windows, so do not check.
 #define CHECK_STACK_ALIGNMENT { }
 #else
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b2dba5a..5bceca2 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -125,7 +125,7 @@
 // (Library, class name, method name)
 #define INVISIBLE_LIST(V)                                                      \
   V(CoreLibrary, Object, _noSuchMethod)                                        \
-  V(CoreLibrary, List, _throwArgumentError)                                    \
+  V(CoreLibrary, _ObjectArray, _ObjectArray.)                                  \
   V(CoreLibrary, AssertionErrorImplementation, _throwNew)                      \
   V(CoreLibrary, TypeErrorImplementation, _throwNew)                           \
   V(CoreLibrary, FallThroughErrorImplementation, _throwNew)                    \
@@ -133,6 +133,7 @@
   V(CoreLibrary, NoSuchMethodError, _throwNew)                                 \
   V(CoreLibrary, int, _throwFormatException)                                   \
   V(CoreLibrary, int, _parse)                                                  \
+  V(CoreLibrary, StackTrace, _setupFullStackTrace)                             \
 
 
 static void MarkFunctionAsInvisible(const Library& lib,
@@ -140,7 +141,7 @@
                                     const char* function_name) {
   ASSERT(!lib.IsNull());
   const Class& cls = Class::Handle(
-      lib.LookupClass(String::Handle(String::New(class_name))));
+      lib.LookupClassAllowPrivate(String::Handle(String::New(class_name))));
   ASSERT(!cls.IsNull());
   const Function& function =
       Function::Handle(
@@ -631,15 +632,30 @@
   lib.AddClass(cls);
 }
 
-#define INIT_LIBRARY(name, raw_script, raw_lib)                                \
-  script ^= raw_script;                                                        \
-  Library::Init##name##Library(isolate);                                       \
-  lib ^= raw_lib;                                                              \
-  ASSERT(!lib.IsNull());                                                       \
+
+#define LOAD_LIBRARY(name, raw_name)                                           \
+  url = Symbols::Dart##name().raw();                                           \
+  lib = Library::LookupLibrary(url);                                           \
+  if (lib.IsNull()) {                                                          \
+    lib = Library::NewLibraryHelper(url, true);                                \
+    lib.Register();                                                            \
+  }                                                                            \
+  isolate->object_store()->set_##raw_name##_library(lib);                      \
+
+#define INIT_LIBRARY(name, raw_name, has_patch)                                \
+  LOAD_LIBRARY(name, raw_name)                                                 \
+  script = Bootstrap::Load##name##Script(false);                               \
   error = Bootstrap::Compile(lib, script);                                     \
   if (!error.IsNull()) {                                                       \
     return error.raw();                                                        \
   }                                                                            \
+  if (has_patch) {                                                             \
+    script = Bootstrap::Load##name##Script(true);                              \
+    error = lib.Patch(script);                                                 \
+    if (!error.IsNull()) {                                                     \
+      return error.raw();                                                      \
+    }                                                                          \
+  }                                                                            \
 
 
 RawError* Object::Init(Isolate* isolate) {
@@ -649,6 +665,10 @@
   Class& cls = Class::Handle();
   Type& type = Type::Handle();
   Array& array = Array::Handle();
+  String& url = String::Handle();
+  Library& lib = Library::Handle();
+  Script& script = Script::Handle();
+  Error& error = Error::Handle();
 
   // All RawArray fields will be initialized to an empty array, therefore
   // initialize array class first.
@@ -698,8 +718,10 @@
       GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
   object_store->set_libraries(libraries);
 
-  // Basic infrastructure has been setup, initialize the class dictionary.
+  // Pre-register the core library.
   Library::InitCoreLibrary(isolate);
+
+  // Basic infrastructure has been setup, initialize the class dictionary.
   Library& core_lib = Library::Handle(Library::CoreLibrary());
   ASSERT(!core_lib.IsNull());
 
@@ -726,7 +748,7 @@
   type ^= Type::New(Object::Handle(cls.raw()),
                     TypeArguments::Handle(),
                     Scanner::kDummyTokenIndex);
-  type.set_is_finalized_instantiated();
+  type.SetIsFinalized();
   type ^= type.Canonicalize();
   object_store->set_array_type(type);
 
@@ -761,7 +783,7 @@
 
   cls = Class::New<Stacktrace>();
   object_store->set_stacktrace_class(cls);
-  RegisterClass(cls, Symbols::Stacktrace(), core_lib);
+  RegisterClass(cls, Symbols::StackTrace(), core_lib);
   pending_classes.Add(cls, Heap::kOld);
   // Super type set below, after Object is allocated.
 
@@ -771,7 +793,7 @@
   pending_classes.Add(cls, Heap::kOld);
 
   // Initialize the base interfaces used by the core VM classes.
-  Script& script = Script::Handle(Bootstrap::LoadCoreScript(false));
+  script = Bootstrap::LoadCoreScript(false);
 
   // Allocate and initialize the pre-allocated classes in the core library.
   cls = Class::New<Instance>(kInstanceCid);
@@ -821,8 +843,25 @@
   object_store->set_weak_property_class(cls);
   RegisterPrivateClass(cls, Symbols::_WeakProperty(), core_lib);
 
-  Library::InitScalarlistLibrary(isolate);
+  // Setup some default native field classes which can be extended for
+  // specifying native fields in dart classes.
+  Library::InitNativeWrappersLibrary(isolate);
+  ASSERT(isolate->object_store()->native_wrappers_library() != Library::null());
+
+  // Pre-register the scalarlist library so the native class implementations
+  // can be hooked up before compiling it.
+  LOAD_LIBRARY(Scalarlist, scalarlist);
+
   Library& scalarlist_lib = Library::Handle(Library::ScalarlistLibrary());
+  ASSERT(!scalarlist_lib.IsNull());
+
+  cls = Class::New<Float32x4>();
+  object_store->set_float32x4_class(cls);
+  RegisterPrivateClass(cls, Symbols::_Float32x4(), scalarlist_lib);
+
+  cls = Class::New<Uint32x4>();
+  object_store->set_uint32x4_class(cls);
+  RegisterPrivateClass(cls, Symbols::_Uint32x4(), scalarlist_lib);
 
   cls = Class::New<Int8Array>();
   object_store->set_int8_array_class(cls);
@@ -860,6 +899,10 @@
   object_store->set_uint64_array_class(cls);
   RegisterPrivateClass(cls, Symbols::_Uint64Array(), scalarlist_lib);
 
+  cls = Class::New<Float32x4Array>();
+  object_store->set_float32x4_array_class(cls);
+  RegisterPrivateClass(cls, Symbols::_Float32x4Array(), scalarlist_lib);
+
   cls = Class::New<Float32Array>();
   object_store->set_float32_array_class(cls);
   RegisterPrivateClass(cls, Symbols::_Float32Array(), scalarlist_lib);
@@ -906,6 +949,11 @@
   object_store->set_external_uint64_array_class(cls);
   RegisterPrivateClass(cls, Symbols::_ExternalUint64Array(), scalarlist_lib);
 
+  cls = Class::New<ExternalFloat32x4Array>();
+  object_store->set_external_float32x4_array_class(cls);
+  RegisterPrivateClass(cls, Symbols::_ExternalFloat32x4Array(),
+                       scalarlist_lib);
+
   cls = Class::New<ExternalFloat32Array>();
   object_store->set_external_float32_array_class(cls);
   RegisterPrivateClass(cls, Symbols::_ExternalFloat32Array(), scalarlist_lib);
@@ -993,120 +1041,22 @@
   type = Type::NewNonParameterizedType(cls);
   object_store->set_dynamic_type(type);
 
-  // Setup some default native field classes which can be extended for
-  // specifying native fields in dart classes.
-  Library::InitNativeWrappersLibrary(isolate);
-  ASSERT(isolate->object_store()->native_wrappers_library() != Library::null());
-
   // Finish the initialization by compiling the bootstrap scripts containing the
   // base interfaces and the implementation of the internal classes.
-  Error& error = Error::Handle();
-  error = Bootstrap::Compile(core_lib, script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  Script& patch_script = Script::Handle(Bootstrap::LoadCoreScript(true));
-  error = core_lib.Patch(patch_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  Library::InitASyncLibrary(isolate);
-  const Script& async_script =
-      Script::Handle(Bootstrap::LoadASyncScript(false));
-  const Library& async_lib = Library::Handle(Library::ASyncLibrary());
-  ASSERT(!async_lib.IsNull());
-  error = Bootstrap::Compile(async_lib, async_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  patch_script = Bootstrap::LoadASyncScript(true);
-  error = async_lib.Patch(patch_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  const Script& collection_script =
-      Script::Handle(Bootstrap::LoadCollectionScript(false));
-  const Library& collection_lib =
-      Library::Handle(Library::CollectionLibrary());
-  ASSERT(!collection_lib.IsNull());
-  error = Bootstrap::Compile(collection_lib, collection_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  const Script& collection_dev_script =
-      Script::Handle(Bootstrap::LoadCollectionDevScript(false));
-  const Library& collection_dev_lib =
-      Library::Handle(Library::CollectionDevLibrary());
-  ASSERT(!collection_dev_lib.IsNull());
-  error = Bootstrap::Compile(collection_dev_lib, collection_dev_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  const Script& math_script = Script::Handle(Bootstrap::LoadMathScript(false));
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  ASSERT(!math_lib.IsNull());
-  error = Bootstrap::Compile(math_lib, math_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  patch_script = Bootstrap::LoadMathScript(true);
-  error = math_lib.Patch(patch_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  const Script& isolate_script = Script::Handle(
-      Bootstrap::LoadIsolateScript(false));
-  Library::InitIsolateLibrary(isolate);
-  const Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
-  ASSERT(!isolate_lib.IsNull());
-  error = Bootstrap::Compile(isolate_lib, isolate_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  patch_script = Bootstrap::LoadIsolateScript(true);
-  error = isolate_lib.Patch(patch_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  const Script& mirrors_script = Script::Handle(
-      Bootstrap::LoadMirrorsScript(false));
-  Library::InitMirrorsLibrary(isolate);
-  const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary());
-  ASSERT(!mirrors_lib.IsNull());
-  error = Bootstrap::Compile(mirrors_lib, mirrors_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  patch_script = Bootstrap::LoadMirrorsScript(true);
-  error = mirrors_lib.Patch(patch_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  const Script& scalarlist_script = Script::Handle(
-      Bootstrap::LoadScalarlistScript(false));
-  ASSERT(!scalarlist_lib.IsNull());
-  error = Bootstrap::Compile(scalarlist_lib, scalarlist_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  patch_script = Bootstrap::LoadScalarlistScript(true);
-  error = scalarlist_lib.Patch(patch_script);
-  if (!error.IsNull()) {
-    return error.raw();
-  }
-  Library& lib = Library::Handle();
-  INIT_LIBRARY(Crypto,
-               Bootstrap::LoadCryptoScript(false),
-               Library::CryptoLibrary());
-  INIT_LIBRARY(Json,
-               Bootstrap::LoadJsonScript(false),
-               Library::JsonLibrary());
-  INIT_LIBRARY(Utf,
-               Bootstrap::LoadUtfScript(false),
-               Library::UtfLibrary());
-  INIT_LIBRARY(Uri,
-               Bootstrap::LoadUriScript(false),
-               Library::UriLibrary());
+  INIT_LIBRARY(Core, core, true);
+
+  INIT_LIBRARY(Async, async, true);
+  INIT_LIBRARY(Collection, collection, false);
+  INIT_LIBRARY(CollectionDev, collection_dev, false);
+  INIT_LIBRARY(Crypto, crypto, false);
+  INIT_LIBRARY(Isolate, isolate, true);
+  INIT_LIBRARY(Json, json, true);
+  INIT_LIBRARY(Math, math, true);
+  INIT_LIBRARY(Mirrors, mirrors, true);
+  INIT_LIBRARY(Scalarlist, scalarlist, true);
+  INIT_LIBRARY(Utf, utf, false);
+  INIT_LIBRARY(Uri, uri, false);
+
   Bootstrap::SetupNativeResolver();
 
   // Remove the Object superclass cycle by setting the super type to null (not
@@ -1151,6 +1101,12 @@
   cls = Class::New<GrowableObjectArray>();
   object_store->set_growable_object_array_class(cls);
 
+  cls = Class::New<Float32x4>();
+  object_store->set_float32x4_class(cls);
+
+  cls = Class::New<Uint32x4>();
+  object_store->set_uint32x4_class(cls);
+
   cls = Class::New<Int8Array>();
   object_store->set_int8_array_class(cls);
 
@@ -1178,6 +1134,9 @@
   cls = Class::New<Uint64Array>();
   object_store->set_uint64_array_class(cls);
 
+  cls = Class::New<Float32x4Array>();
+  object_store->set_float32x4_array_class(cls);
+
   cls = Class::New<Float32Array>();
   object_store->set_float32_array_class(cls);
 
@@ -1211,6 +1170,9 @@
   cls = Class::New<ExternalUint64Array>();
   object_store->set_external_uint64_array_class(cls);
 
+  cls = Class::New<ExternalFloat32x4Array>();
+  object_store->set_external_float32x4_array_class(cls);
+
   cls = Class::New<ExternalFloat32Array>();
   object_store->set_external_float32_array_class(cls);
 
@@ -1413,6 +1375,10 @@
     case kImmutableArrayCid:
     case kGrowableObjectArrayCid:
       return Symbols::List().raw();
+    case kFloat32x4Cid:
+      return Symbols::Float32x4().raw();
+    case kUint32x4Cid:
+      return Symbols::Uint32x4().raw();
     case kInt8ArrayCid:
     case kExternalInt8ArrayCid:
       return Symbols::Int8List().raw();
@@ -1440,6 +1406,9 @@
     case kUint64ArrayCid:
     case kExternalUint64ArrayCid:
       return Symbols::Uint64List().raw();
+    case kFloat32x4ArrayCid:
+    case kExternalFloat32x4ArrayCid:
+      return Symbols::Float32x4List().raw();
     case kFloat32ArrayCid:
     case kExternalFloat32ArrayCid:
       return Symbols::Float32List().raw();
@@ -6340,37 +6309,12 @@
 }
 
 
-void Library::InitASyncLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartAsync();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  isolate->object_store()->set_async_library(lib);
-}
-
-
 void Library::InitCoreLibrary(Isolate* isolate) {
   const String& core_lib_url = Symbols::DartCore();
   const Library& core_lib =
       Library::Handle(Library::NewLibraryHelper(core_lib_url, false));
   core_lib.Register();
   isolate->object_store()->set_core_library(core_lib);
-  Library::InitMathLibrary(isolate);
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  const Namespace& math_ns = Namespace::Handle(
-      Namespace::New(math_lib, Array::Handle(), Array::Handle()));
-  Library::InitCollectionDevLibrary(isolate);
-  const Library& collection_dev_lib =
-      Library::Handle(Library::CollectionDevLibrary());
-  const Namespace& collection_dev_ns = Namespace::Handle(
-      Namespace::New(collection_dev_lib, Array::Handle(), Array::Handle()));
-  Library::InitCollectionLibrary(isolate);
-  const Library& collection_lib =
-      Library::Handle(Library::CollectionLibrary());
-  const Namespace& collection_ns = Namespace::Handle(
-      Namespace::New(collection_lib, Array::Handle(), Array::Handle()));
-  core_lib.AddImport(math_ns);
-  core_lib.AddImport(collection_ns);
-  core_lib.AddImport(collection_dev_ns);
   isolate->object_store()->set_root_library(Library::Handle());
 
   // Hook up predefined classes without setting their library pointers. These
@@ -6381,92 +6325,6 @@
 }
 
 
-void Library::InitCollectionLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartCollection();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  const Namespace& math_ns = Namespace::Handle(
-      Namespace::New(math_lib, Array::Handle(), Array::Handle()));
-  const Library& collection_dev_lib =
-      Library::Handle(Library::CollectionDevLibrary());
-  const Namespace& collection_dev_ns = Namespace::Handle(
-      Namespace::New(collection_dev_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(math_ns);
-  lib.AddImport(collection_dev_ns);
-  isolate->object_store()->set_collection_library(lib);
-}
-
-
-void Library::InitCollectionDevLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartCollectionDev();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  isolate->object_store()->set_collection_dev_library(lib);
-}
-
-
-void Library::InitCryptoLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartCrypto();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  const Namespace& math_ns = Namespace::Handle(
-      Namespace::New(math_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(math_ns);
-  isolate->object_store()->set_crypto_library(lib);
-}
-
-
-void Library::InitIsolateLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartIsolate();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  const Library& async_lib = Library::Handle(Library::ASyncLibrary());
-  const Namespace& async_ns = Namespace::Handle(
-      Namespace::New(async_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(async_ns);
-  isolate->object_store()->set_isolate_library(lib);
-}
-
-
-void Library::InitJsonLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartJson();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  isolate->object_store()->set_json_library(lib);
-}
-
-
-void Library::InitMathLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartMath();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  isolate->object_store()->set_math_library(lib);
-}
-
-
-void Library::InitMirrorsLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartMirrors();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  const Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
-  const Namespace& isolate_ns = Namespace::Handle(
-      Namespace::New(isolate_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(isolate_ns);
-  const Library& async_lib = Library::Handle(Library::ASyncLibrary());
-  const Namespace& async_ns = Namespace::Handle(
-      Namespace::New(async_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(async_ns);
-  const Library& wrappers_lib =
-      Library::Handle(Library::NativeWrappersLibrary());
-  const Namespace& wrappers_ns = Namespace::Handle(
-      Namespace::New(wrappers_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(wrappers_ns);
-  isolate->object_store()->set_mirrors_library(lib);
-}
-
-
 void Library::InitNativeWrappersLibrary(Isolate* isolate) {
   static const int kNumNativeWrappersClasses = 4;
   ASSERT(kNumNativeWrappersClasses > 0 && kNumNativeWrappersClasses < 10);
@@ -6492,47 +6350,6 @@
 }
 
 
-void Library::InitScalarlistLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartScalarlist();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  const Library& collection_lib =
-      Library::Handle(Library::CollectionLibrary());
-  const Namespace& collection_ns = Namespace::Handle(
-      Namespace::New(collection_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(collection_ns);
-  isolate->object_store()->set_scalarlist_library(lib);
-}
-
-
-void Library::InitUriLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartUri();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  const Namespace& math_ns = Namespace::Handle(
-      Namespace::New(math_lib, Array::Handle(), Array::Handle()));
-  const Library& utf_lib = Library::Handle(Library::UtfLibrary());
-  const Namespace& utf_ns = Namespace::Handle(
-      Namespace::New(utf_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(math_ns);
-  lib.AddImport(utf_ns);
-  isolate->object_store()->set_uri_library(lib);
-}
-
-
-void Library::InitUtfLibrary(Isolate* isolate) {
-  const String& url = Symbols::DartUtf();
-  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
-  lib.Register();
-  const Library& async_lib = Library::Handle(Library::ASyncLibrary());
-  const Namespace& async_ns = Namespace::Handle(
-      Namespace::New(async_lib, Array::Handle(), Array::Handle()));
-  lib.AddImport(async_ns);
-  isolate->object_store()->set_utf_library(lib);
-}
-
-
 RawLibrary* Library::LookupLibrary(const String &url) {
   Isolate* isolate = Isolate::Current();
   Library& lib = Library::Handle(isolate, Library::null());
@@ -6626,7 +6443,7 @@
 }
 
 
-RawLibrary* Library::ASyncLibrary() {
+RawLibrary* Library::AsyncLibrary() {
   return Isolate::Current()->object_store()->async_library();
 }
 
@@ -7263,8 +7080,38 @@
 
 
 const char* LocalVarDescriptors::ToCString() const {
-  UNIMPLEMENTED();
-  return "LocalVarDescriptors";
+  intptr_t len = 1;  // Trailing '\0'.
+  const char* kFormat =
+      "%2"Pd" kind=%d scope=0x%04x begin=%"Pd" end=%"Pd" name=%s\n";
+  for (intptr_t i = 0; i < Length(); i++) {
+    String& var_name = String::Handle(GetName(i));
+    RawLocalVarDescriptors::VarInfo info;
+    GetInfo(i, &info);
+    len += OS::SNPrint(NULL, 0, kFormat,
+                       i,
+                       info.kind,
+                       info.scope_id,
+                       info.begin_pos,
+                       info.end_pos,
+                       var_name.ToCString());
+  }
+  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
+  intptr_t num_chars = 0;
+  for (intptr_t i = 0; i < Length(); i++) {
+    String& var_name = String::Handle(GetName(i));
+    RawLocalVarDescriptors::VarInfo info;
+    GetInfo(i, &info);
+    num_chars += OS::SNPrint((buffer + num_chars),
+                             (len - num_chars),
+                             kFormat,
+                             i,
+                             info.kind,
+                             info.scope_id,
+                             info.begin_pos,
+                             info.end_pos,
+                             var_name.ToCString());
+  }
+  return buffer;
 }
 
 
@@ -8912,7 +8759,7 @@
   }
   const Type& type = Type::Handle(
       Type::New(cls, type_arguments, Scanner::kDummyTokenIndex));
-  type.set_is_finalized_instantiated();
+  type.SetIsFinalized();
   return type.raw();
 }
 
@@ -9475,21 +9322,19 @@
   type ^= Type::New(Object::Handle(type_class.raw()),
                     no_type_arguments,
                     Scanner::kDummyTokenIndex);
-  type.set_is_finalized_instantiated();
+  type.SetIsFinalized();
   type ^= type.Canonicalize();
   return type.raw();
 }
 
 
-void Type::set_is_finalized_instantiated() const {
+void Type::SetIsFinalized() const {
   ASSERT(!IsFinalized());
-  set_type_state(RawType::kFinalizedInstantiated);
-}
-
-
-void Type::set_is_finalized_uninstantiated() const {
-  ASSERT(!IsFinalized());
-  set_type_state(RawType::kFinalizedUninstantiated);
+  if (IsInstantiated()) {
+    set_type_state(RawType::kFinalizedInstantiated);
+  } else {
+    set_type_state(RawType::kFinalizedUninstantiated);
+  }
 }
 
 
@@ -9603,7 +9448,7 @@
       Type::New(cls, type_arguments, token_pos()));
   ASSERT(type_arguments.IsNull() ||
          (type_arguments.Length() == cls.NumTypeArguments()));
-  instantiated_type.set_is_finalized_instantiated();
+  instantiated_type.SetIsFinalized();
   return instantiated_type.raw();
 }
 
@@ -10655,6 +10500,7 @@
 }
 
 
+// Synchronize with implementation in compiler (intrinsifier).
 class StringHasher : ValueObject {
  public:
   StringHasher() : hash_(0) {}
@@ -10683,9 +10529,15 @@
   ASSERT(len >= 0);
   ASSERT((begin_index + len) <= str.Length());
   StringHasher hasher;
-  CodePointIterator it(str, begin_index, len);
-  while (it.Next()) {
-    hasher.Add(it.Current());
+  if (str.IsOneByteString()) {
+    for (intptr_t i = 0; i < len; i++) {
+      hasher.Add(*OneByteString::CharAddr(str, i + begin_index));
+    }
+  } else {
+    CodePointIterator it(str, begin_index, len);
+    while (it.Next()) {
+      hasher.Add(it.Current());
+    }
   }
   return hasher.Finalize(String::kHashBits);
 }
@@ -10727,13 +10579,13 @@
   ASSERT(RawObject::IsStringClassId(class_id));
   NoGCScope no_gc;
   if (class_id == kOneByteStringCid) {
-      return *OneByteString::CharAddr(*this, index);
+    return *OneByteString::CharAddr(*this, index);
   }
   if (class_id == kTwoByteStringCid) {
-      return *TwoByteString::CharAddr(*this, index);
+    return *TwoByteString::CharAddr(*this, index);
   }
   if (class_id == kExternalOneByteStringCid) {
-      return *ExternalOneByteString::CharAddr(*this, index);
+    return *ExternalOneByteString::CharAddr(*this, index);
   }
   ASSERT(class_id == kExternalTwoByteStringCid);
   return *ExternalTwoByteString::CharAddr(*this, index);
@@ -11206,7 +11058,30 @@
 
 
 const char* String::ToCString() const {
-  intptr_t len = Utf8::Length(*this);
+  if (IsOneByteString()) {
+    // Quick conversion if OneByteString contains only ASCII characters.
+    intptr_t len = Length();
+    if (len == 0) {
+      return "";
+    }
+    Zone* zone = Isolate::Current()->current_zone();
+    uint8_t* result = zone->Alloc<uint8_t>(len + 1);
+    NoGCScope no_gc;
+    const uint8_t* original_str = OneByteString::CharAddr(*this, 0);
+    for (intptr_t i = 0; i < len; i++) {
+      if (original_str[i] <= Utf8::kMaxOneByteChar) {
+        result[i] = original_str[i];
+      } else {
+        len = -1;
+        break;
+      }
+    }
+    if (len > 0) {
+      result[len] = 0;
+      return reinterpret_cast<const char*>(result);
+    }
+  }
+  const intptr_t len = Utf8::Length(*this);
   Zone* zone = Isolate::Current()->current_zone();
   uint8_t* result = zone->Alloc<uint8_t>(len + 1);
   ToUTF8(result, len);
@@ -11508,17 +11383,16 @@
     // This should be caught before we reach here.
     FATAL1("Fatal error in OneByteString::New: invalid len %"Pd"\n", len);
   }
-  String& result = String::Handle();
   {
     RawObject* raw = Object::Allocate(OneByteString::kClassId,
                                       OneByteString::InstanceSize(len),
                                       space);
     NoGCScope no_gc;
-    result ^= raw;
-    result.SetLength(len);
-    result.SetHash(0);
+    RawOneByteString* result = reinterpret_cast<RawOneByteString*>(raw);
+    result->ptr()->length_ = Smi::New(len);
+    result->ptr()->hash_ = 0;
+    return result;
   }
-  return OneByteString::raw(result);
 }
 
 
@@ -12149,6 +12023,206 @@
 }
 
 
+RawFloat32x4* Float32x4::New(float v0, float v1, float v2, float v3,
+                                       Heap::Space space) {
+  ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
+         Class::null());
+  Float32x4& result = Float32x4::Handle();
+  {
+    RawObject* raw = Object::Allocate(Float32x4::kClassId,
+                                      Float32x4::InstanceSize(),
+                                      space);
+    NoGCScope no_gc;
+    result ^= raw;
+  }
+  result.set_x(v0);
+  result.set_y(v1);
+  result.set_z(v2);
+  result.set_w(v3);
+  return result.raw();
+}
+
+
+RawFloat32x4* Float32x4::New(simd_value_t value, Heap::Space space) {
+ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
+         Class::null());
+  Float32x4& result = Float32x4::Handle();
+  {
+    RawObject* raw = Object::Allocate(Float32x4::kClassId,
+                                      Float32x4::InstanceSize(),
+                                      space);
+    NoGCScope no_gc;
+    result ^= raw;
+  }
+  result.set_value(value);
+  return result.raw();
+}
+
+
+simd_value_t Float32x4::value() const {
+  return simd_value_safe_load(&raw_ptr()->value_[0]);
+}
+
+
+void Float32x4::set_value(simd_value_t value) const {
+  simd_value_safe_store(&raw_ptr()->value_[0], value);
+}
+
+
+void Float32x4::set_x(float value) const {
+  raw_ptr()->value_[0] = value;
+}
+
+
+void Float32x4::set_y(float value) const {
+  raw_ptr()->value_[1] = value;
+}
+
+
+void Float32x4::set_z(float value) const {
+  raw_ptr()->value_[2] = value;
+}
+
+
+void Float32x4::set_w(float value) const {
+  raw_ptr()->value_[3] = value;
+}
+
+
+float Float32x4::x() const {
+  return raw_ptr()->value_[0];
+}
+
+
+float Float32x4::y() const {
+  return raw_ptr()->value_[1];
+}
+
+
+float Float32x4::z() const {
+  return raw_ptr()->value_[2];
+}
+
+
+float Float32x4::w() const {
+  return raw_ptr()->value_[3];
+}
+
+
+const char* Float32x4::ToCString() const {
+  const char* kFormat = "[%f, %f, %f, %f]";
+  float _x = x();
+  float _y = y();
+  float _z = z();
+  float _w = w();
+  // Calculate the size of the string.
+  intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y, _z, _w) + 1;
+  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  OS::SNPrint(chars, len, kFormat, _x, _y, _z, _w);
+  return chars;
+}
+
+
+RawUint32x4* Uint32x4::New(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3,
+                           Heap::Space space) {
+  ASSERT(Isolate::Current()->object_store()->uint32x4_class() !=
+         Class::null());
+  Uint32x4& result = Uint32x4::Handle();
+  {
+    RawObject* raw = Object::Allocate(Uint32x4::kClassId,
+                                      Uint32x4::InstanceSize(),
+                                      space);
+    NoGCScope no_gc;
+    result ^= raw;
+  }
+  result.set_x(v0);
+  result.set_y(v1);
+  result.set_z(v2);
+  result.set_w(v3);
+  return result.raw();
+}
+
+
+RawUint32x4* Uint32x4::New(simd_value_t value, Heap::Space space) {
+  ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
+         Class::null());
+  Uint32x4& result = Uint32x4::Handle();
+  {
+    RawObject* raw = Object::Allocate(Uint32x4::kClassId,
+                                      Uint32x4::InstanceSize(),
+                                      space);
+    NoGCScope no_gc;
+    result ^= raw;
+  }
+  result.set_value(value);
+  return result.raw();
+}
+
+
+void Uint32x4::set_x(uint32_t value) const {
+  raw_ptr()->value_[0] = value;
+}
+
+
+void Uint32x4::set_y(uint32_t value) const {
+  raw_ptr()->value_[1] = value;
+}
+
+
+void Uint32x4::set_z(uint32_t value) const {
+  raw_ptr()->value_[2] = value;
+}
+
+
+void Uint32x4::set_w(uint32_t value) const {
+  raw_ptr()->value_[3] = value;
+}
+
+
+uint32_t Uint32x4::x() const {
+  return raw_ptr()->value_[0];
+}
+
+
+uint32_t Uint32x4::y() const {
+  return raw_ptr()->value_[1];
+}
+
+
+uint32_t Uint32x4::z() const {
+  return raw_ptr()->value_[2];
+}
+
+
+uint32_t Uint32x4::w() const {
+  return raw_ptr()->value_[3];
+}
+
+
+simd_value_t Uint32x4::value() const {
+  return simd_value_safe_load(&raw_ptr()->value_[0]);
+}
+
+
+void Uint32x4::set_value(simd_value_t value) const {
+  simd_value_safe_store(&raw_ptr()->value_[0], value);
+}
+
+
+const char* Uint32x4::ToCString() const {
+  const char* kFormat = "[%08x, %08x, %08x, %08x]";
+  uint32_t _x = x();
+  uint32_t _y = y();
+  uint32_t _z = z();
+  uint32_t _w = w();
+  // Calculate the size of the string.
+  intptr_t len = OS::SNPrint(NULL, 0, kFormat, _x, _y, _z, _w) + 1;
+  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  OS::SNPrint(chars, len, kFormat, _x, _y, _z, _w);
+  return chars;
+}
+
+
 void ByteArray::Copy(void* dst,
                      const ByteArray& src,
                      intptr_t src_offset,
@@ -12481,6 +12555,30 @@
 }
 
 
+RawFloat32x4Array* Float32x4Array::New(intptr_t len,
+                                                 Heap::Space space) {
+  ASSERT(Isolate::Current()->object_store()->float32x4_array_class() !=
+         Class::null());
+  return NewImpl<Float32x4Array, RawFloat32x4Array>(kClassId, len,
+                                                              space);
+}
+
+
+RawFloat32x4Array* Float32x4Array::New(const simd_value_t* data,
+                                                 intptr_t len,
+                                                 Heap::Space space) {
+  ASSERT(Isolate::Current()->object_store()->float32_array_class() !=
+         Class::null());
+  return NewImpl<Float32x4Array, RawFloat32x4Array>(kClassId, data,
+                                                              len, space);
+}
+
+
+const char* Float32x4Array::ToCString() const {
+  return "_Float32x4Array";
+}
+
+
 RawFloat32Array* Float32Array::New(intptr_t len, Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->float32_array_class() !=
          Class::null());
@@ -12661,6 +12759,24 @@
 }
 
 
+RawExternalFloat32x4Array* ExternalFloat32x4Array::New(
+    simd_value_t* data,
+    intptr_t len,
+    Heap::Space space) {
+  RawClass* cls =
+     Isolate::Current()->object_store()->external_float32x4_array_class();
+  ASSERT(cls != Class::null());
+  return NewExternalImpl<ExternalFloat32x4Array,
+                         RawExternalFloat32x4Array>(kClassId, data, len,
+                                                         space);
+}
+
+
+const char* ExternalFloat32x4Array::ToCString() const {
+  return "_ExternalFloat32x4Array";
+}
+
+
 RawExternalFloat32Array* ExternalFloat32Array::New(float* data,
                                                    intptr_t len,
                                                    Heap::Space space) {
@@ -12742,18 +12858,39 @@
 }
 
 
+void Stacktrace::SetFunctionAtFrame(intptr_t frame_index,
+                                    const Function& func) const {
+  const Array& function_array = Array::Handle(raw_ptr()->function_array_);
+  function_array.SetAt(frame_index, func);
+}
+
+
 RawCode* Stacktrace::CodeAtFrame(intptr_t frame_index) const {
   const Array& code_array = Array::Handle(raw_ptr()->code_array_);
   return reinterpret_cast<RawCode*>(code_array.At(frame_index));
 }
 
 
+void Stacktrace::SetCodeAtFrame(intptr_t frame_index,
+                                const Code& code) const {
+  const Array& code_array = Array::Handle(raw_ptr()->code_array_);
+  code_array.SetAt(frame_index, code);
+}
+
+
 RawSmi* Stacktrace::PcOffsetAtFrame(intptr_t frame_index) const {
   const Array& pc_offset_array = Array::Handle(raw_ptr()->pc_offset_array_);
   return reinterpret_cast<RawSmi*>(pc_offset_array.At(frame_index));
 }
 
 
+void Stacktrace::SetPcOffsetAtFrame(intptr_t frame_index,
+                                    const Smi& pc_offset) const {
+  const Array& pc_offset_array = Array::Handle(raw_ptr()->pc_offset_array_);
+  pc_offset_array.SetAt(frame_index, pc_offset);
+}
+
+
 void Stacktrace::set_function_array(const Array& function_array) const {
   StorePointer(&raw_ptr()->function_array_, function_array.raw());
 }
@@ -12769,9 +12906,24 @@
 }
 
 
-RawStacktrace* Stacktrace::New(const GrowableObjectArray& func_list,
-                               const GrowableObjectArray& code_list,
-                               const GrowableObjectArray& pc_offset_list,
+void Stacktrace::set_catch_func_array(const Array& function_array) const {
+  StorePointer(&raw_ptr()->catch_func_array_, function_array.raw());
+}
+
+
+void Stacktrace::set_catch_code_array(const Array& code_array) const {
+  StorePointer(&raw_ptr()->catch_code_array_, code_array.raw());
+}
+
+
+void Stacktrace::set_catch_pc_offset_array(const Array& pc_offset_array) const {
+  StorePointer(&raw_ptr()->catch_pc_offset_array_, pc_offset_array.raw());
+}
+
+
+RawStacktrace* Stacktrace::New(const Array& func_array,
+                               const Array& code_array,
+                               const Array& pc_offset_array,
                                Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->stacktrace_class() !=
          Class::null());
@@ -12783,21 +12935,19 @@
     NoGCScope no_gc;
     result ^= raw;
   }
-  // Create arrays for the function, code and pc_offset triplet for each frame.
-  const Array& function_array = Array::Handle(Array::MakeArray(func_list));
-  const Array& code_array = Array::Handle(Array::MakeArray(code_list));
-  const Array& pc_offset_array =
-      Array::Handle(Array::MakeArray(pc_offset_list));
-  result.set_function_array(function_array);
+  result.set_function_array(func_array);
   result.set_code_array(code_array);
   result.set_pc_offset_array(pc_offset_array);
+  result.SetCatchStacktrace(Object::empty_array(),
+                            Object::empty_array(),
+                            Object::empty_array());
   return result.raw();
 }
 
 
-void Stacktrace::Append(const GrowableObjectArray& func_list,
-                        const GrowableObjectArray& code_list,
-                        const GrowableObjectArray& pc_offset_list) const {
+void Stacktrace::Append(const Array& func_list,
+                        const Array& code_list,
+                        const Array& pc_offset_list) const {
   intptr_t old_length = Length();
   intptr_t new_length = old_length + pc_offset_list.Length();
   ASSERT(pc_offset_list.Length() == func_list.Length());
@@ -12828,7 +12978,42 @@
 }
 
 
+void Stacktrace::SetCatchStacktrace(const Array& func_array,
+                                    const Array& code_array,
+                                    const Array& pc_offset_array) const {
+  StorePointer(&raw_ptr()->catch_func_array_, func_array.raw());
+  StorePointer(&raw_ptr()->catch_code_array_, code_array.raw());
+  StorePointer(&raw_ptr()->catch_pc_offset_array_, pc_offset_array.raw());
+}
+
+
+RawString* Stacktrace::FullStacktrace() const {
+  const Array& func_array = Array::Handle(raw_ptr()->catch_func_array_);
+  if (!func_array.IsNull() && (func_array.Length() > 0)) {
+    const Array& code_array = Array::Handle(raw_ptr()->catch_code_array_);
+    const Array& pc_offset_array =
+        Array::Handle(raw_ptr()->catch_pc_offset_array_);
+    const Stacktrace& catch_trace = Stacktrace::Handle(
+        Stacktrace::New(func_array, code_array, pc_offset_array));
+    intptr_t idx = Length();
+    const String& trace =
+        String::Handle(String::New(catch_trace.ToCStringInternal(idx)));
+    const String& throw_trace =
+        String::Handle(String::New(ToCStringInternal(0)));
+    return String::Concat(throw_trace, trace);
+  }
+  return String::New(ToCStringInternal(0));
+}
+
+
 const char* Stacktrace::ToCString() const {
+  const String& trace = String::Handle(FullStacktrace());
+  return trace.ToCString();
+}
+
+
+const char* Stacktrace::ToCStringInternal(intptr_t frame_index) const {
+  Isolate* isolate = Isolate::Current();
   Function& function = Function::Handle();
   Code& code = Code::Handle();
   Script& script = Script::Handle();
@@ -12840,8 +13025,21 @@
   intptr_t total_len = 0;
   const char* kFormat = "#%-6d %s (%s:%d:%d)\n";
   GrowableArray<char*> frame_strings;
+  char* chars;
   for (intptr_t i = 0; i < Length(); i++) {
     function = FunctionAtFrame(i);
+    if (function.IsNull()) {
+      // Check if null function object indicates a stack trace overflow.
+      if ((i < (Length() - 1)) &&
+          (FunctionAtFrame(i + 1) != Function::null())) {
+        const char* kTruncated = "...\n...\n";
+        intptr_t truncated_len = strlen(kTruncated) + 1;
+        chars = isolate->current_zone()->Alloc<char>(truncated_len);
+        OS::SNPrint(chars, truncated_len, "%s", kTruncated);
+        frame_strings.Add(chars);
+      }
+      continue;
+    }
     code = CodeAtFrame(i);
     uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i));
     intptr_t token_pos = code.GetTokenIndexOfPC(pc);
@@ -12854,22 +13052,22 @@
       script.GetTokenLocation(token_pos, &line, &column);
     }
     intptr_t len = OS::SNPrint(NULL, 0, kFormat,
-                               i,
+                               (frame_index + i),
                                function_name.ToCString(),
                                url.ToCString(),
                                line, column);
     total_len += len;
-    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
+    chars = isolate->current_zone()->Alloc<char>(len + 1);
     OS::SNPrint(chars, (len + 1), kFormat,
-                i,
+                (frame_index + i),
                 function_name.ToCString(),
                 url.ToCString(),
                 line, column);
     frame_strings.Add(chars);
   }
 
-  // Now concatentate the frame descriptions into a single C string.
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(total_len + 1);
+  // Now concatenate the frame descriptions into a single C string.
+  chars = isolate->current_zone()->Alloc<char>(total_len + 1);
   intptr_t index = 0;
   for (intptr_t i = 0; i < frame_strings.length(); i++) {
     index += OS::SNPrint((chars + index),
@@ -12877,6 +13075,7 @@
                          "%s",
                          frame_strings[i]);
   }
+  chars[total_len] = '\0';
   return chars;
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index a0ba8ae..e2ed725 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2113,21 +2113,10 @@
   static RawLibrary* GetLibrary(intptr_t index);
   static bool IsKeyUsed(intptr_t key);
 
-  static void InitASyncLibrary(Isolate* isolate);
   static void InitCoreLibrary(Isolate* isolate);
-  static void InitCollectionLibrary(Isolate* isolate);
-  static void InitCollectionDevLibrary(Isolate* isolate);
-  static void InitCryptoLibrary(Isolate* isolate);
-  static void InitIsolateLibrary(Isolate* isolate);
-  static void InitJsonLibrary(Isolate* isolate);
-  static void InitMathLibrary(Isolate* isolate);
-  static void InitMirrorsLibrary(Isolate* isolate);
   static void InitNativeWrappersLibrary(Isolate* isolate);
-  static void InitScalarlistLibrary(Isolate* isolate);
-  static void InitUriLibrary(Isolate* isolate);
-  static void InitUtfLibrary(Isolate* isolate);
 
-  static RawLibrary* ASyncLibrary();
+  static RawLibrary* AsyncLibrary();
   static RawLibrary* CoreLibrary();
   static RawLibrary* CollectionLibrary();
   static RawLibrary* CollectionDevLibrary();
@@ -2165,6 +2154,8 @@
   RawObject* LookupEntry(const String& name, intptr_t *index) const;
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Library, Object);
+
+  friend class Object;
   friend class Class;
   friend class Debugger;
   friend class DictionaryIterator;
@@ -2236,6 +2227,9 @@
   intptr_t size() const { return raw_ptr()->size_; }  // Excludes HeaderSize().
   RawCode* code() const { return raw_ptr()->code_; }
   RawArray* object_pool() const { return raw_ptr()->object_pool_; }
+  static intptr_t object_pool_offset() {
+    return OFFSET_OF(RawInstructions, object_pool_);
+  }
 
   uword EntryPoint() const {
     return reinterpret_cast<uword>(raw_ptr()) + HeaderSize();
@@ -3512,8 +3506,7 @@
     (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) ||
     (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated);
   }
-  void set_is_finalized_instantiated() const;
-  void set_is_finalized_uninstantiated() const;
+  void SetIsFinalized() const;
   virtual bool IsBeingFinalized() const {
     return raw_ptr()->type_state_ == RawType::kBeingFinalized;
   }
@@ -4770,6 +4763,72 @@
 };
 
 
+class Float32x4 : public Instance {
+ public:
+  static RawFloat32x4* New(float value0, float value1, float value2,
+                                float value3, Heap::Space space = Heap::kNew);
+  static RawFloat32x4* New(simd_value_t value, Heap::Space space = Heap::kNew);
+
+  float x() const;
+  float y() const;
+  float z() const;
+  float w() const;
+
+  void set_x(float x) const;
+  void set_y(float y) const;
+  void set_z(float z) const;
+  void set_w(float w) const;
+
+  simd_value_t value() const;
+  void set_value(simd_value_t value) const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawFloat32x4));
+  }
+
+  static intptr_t value_offset() {
+    return OFFSET_OF(RawFloat32x4, value_);
+  }
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(Float32x4, Instance);
+  friend class Class;
+};
+
+
+class Uint32x4 : public Instance {
+ public:
+  static RawUint32x4* New(uint32_t value0, uint32_t value1, uint32_t value2,
+                             uint32_t value3, Heap::Space space = Heap::kNew);
+  static RawUint32x4* New(simd_value_t value, Heap::Space space = Heap::kNew);
+
+  uint32_t x() const;
+  uint32_t y() const;
+  uint32_t z() const;
+  uint32_t w() const;
+
+  void set_x(uint32_t x) const;
+  void set_y(uint32_t y) const;
+  void set_z(uint32_t z) const;
+  void set_w(uint32_t w) const;
+
+  simd_value_t value() const;
+  void set_value(simd_value_t value) const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawUint32x4));
+  }
+
+  static intptr_t value_offset() {
+    return OFFSET_OF(RawUint32x4, value_);
+  }
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(Uint32x4, Instance);
+  friend class Class;
+};
+
+
 class ByteArray : public Instance {
  public:
   intptr_t Length() const {
@@ -5310,6 +5369,61 @@
 };
 
 
+class Float32x4Array : public ByteArray {
+ public:
+  intptr_t ByteLength() const {
+    return Length() * kBytesPerElement;
+  }
+
+  simd_value_t At(intptr_t index) const {
+    ASSERT((index >= 0) && (index < Length()));
+    simd_value_t* load_ptr = &raw_ptr()->data_[index];
+    return simd_value_safe_load(load_ptr);
+  }
+
+  void SetAt(intptr_t index, simd_value_t value) const {
+    ASSERT((index >= 0) && (index < Length()));
+    simd_value_t* store_ptr = &raw_ptr()->data_[index];
+    simd_value_safe_store(store_ptr, value);
+  }
+
+  static const intptr_t kBytesPerElement = 16;
+  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
+
+  static intptr_t data_offset() {
+    return OFFSET_OF(RawFloat32x4Array, data_);
+  }
+
+  static intptr_t InstanceSize() {
+    ASSERT(sizeof(RawFloat32x4Array) ==
+           OFFSET_OF(RawFloat32x4Array, data_));
+    return 0;
+  }
+
+  static intptr_t InstanceSize(intptr_t len) {
+    ASSERT(0 <= len && len <= kMaxElements);
+    return RoundedAllocationSize(
+        sizeof(RawFloat32x4Array) + (len * kBytesPerElement));
+  }
+
+  static RawFloat32x4Array* New(intptr_t len,
+                                     Heap::Space space = Heap::kNew);
+  static RawFloat32x4Array* New(const simd_value_t* data,
+                                     intptr_t len,
+                                     Heap::Space space = Heap::kNew);
+
+ private:
+  uint8_t* ByteAddr(intptr_t byte_offset) const {
+    ASSERT((byte_offset >= 0) && (byte_offset < ByteLength()));
+    return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
+  }
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(Float32x4Array, ByteArray);
+  friend class ByteArray;
+  friend class Class;
+};
+
+
 class Float32Array : public ByteArray {
  public:
   intptr_t ByteLength() const {
@@ -5909,6 +6023,68 @@
 };
 
 
+class ExternalFloat32x4Array : public ByteArray {
+ public:
+  intptr_t ByteLength() const {
+    return Length() * kBytesPerElement;
+  }
+
+  simd_value_t At(intptr_t index) const {
+    ASSERT((index >= 0) && (index < Length()));
+    simd_value_t* load_ptr = &raw_ptr()->data_[index];
+    return simd_value_safe_load(load_ptr);
+  }
+
+  void SetAt(intptr_t index, simd_value_t value) const {
+    ASSERT((index >= 0) && (index < Length()));
+    simd_value_t* store_ptr = &raw_ptr()->data_[index];
+    simd_value_safe_store(store_ptr, value);
+  }
+
+
+  simd_value_t* GetData() const {
+    return raw_ptr()->data_;
+  }
+
+  void* GetPeer() const {
+    return raw_ptr()->peer_;
+  }
+
+  static const intptr_t kBytesPerElement = 16;
+
+  // Since external arrays may be serialized to non-external ones,
+  // enforce the same maximum element count.
+  static const intptr_t kMaxElements = Float32x4Array::kMaxElements;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawExternalFloat32x4Array));
+  }
+
+  static RawExternalFloat32x4Array* New(simd_value_t* data,
+                                             intptr_t len,
+                                             Heap::Space space = Heap::kNew);
+
+ private:
+  uint8_t* ByteAddr(intptr_t byte_offset) const {
+    ASSERT((byte_offset >= 0) && (byte_offset < ByteLength()));
+    uint8_t* data = reinterpret_cast<uint8_t*>(raw_ptr()->data_);
+    return data + byte_offset;
+  }
+
+  void SetData(simd_value_t* data) const {
+    raw_ptr()->data_ = data;
+  }
+
+  void SetPeer(void* peer) const {
+    raw_ptr()->peer_ = peer;
+  }
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32x4Array, ByteArray);
+  friend class ByteArray;
+  friend class Class;
+};
+
+
 class ExternalFloat32Array : public ByteArray {
  public:
   intptr_t ByteLength() const {
@@ -6112,28 +6288,44 @@
 // Internal stacktrace object used in exceptions for printing stack traces.
 class Stacktrace : public Instance {
  public:
+  static const int kPreallocatedStackdepth = 10;
+
   intptr_t Length() const;
+
   RawFunction* FunctionAtFrame(intptr_t frame_index) const;
+  void SetFunctionAtFrame(intptr_t frame_index, const Function& func) const;
+
   RawCode* CodeAtFrame(intptr_t frame_index) const;
+  void SetCodeAtFrame(intptr_t frame_index, const Code& code) const;
+
   RawSmi* PcOffsetAtFrame(intptr_t frame_index) const;
-  void Append(const GrowableObjectArray& func_list,
-              const GrowableObjectArray& code_list,
-              const GrowableObjectArray& pc_offset_list) const;
+  void SetPcOffsetAtFrame(intptr_t frame_index, const Smi& pc_offset) const;
+  void SetCatchStacktrace(const Array& func_array,
+                          const Array& code_array,
+                          const Array& pc_offset_array) const;
+
+  void Append(const Array& func_list,
+              const Array& code_list,
+              const Array& pc_offset_list) const;
 
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawStacktrace));
   }
-  static RawStacktrace* New(const GrowableObjectArray& func_list,
-                            const GrowableObjectArray& code_list,
-                            const GrowableObjectArray& pc_offset_list,
+  static RawStacktrace* New(const Array& func_array,
+                            const Array& code_array,
+                            const Array& pc_offset_array,
                             Heap::Space space = Heap::kNew);
 
-  const char* ToCStringInternal(bool verbose) const;
+  RawString* FullStacktrace() const;
+  const char* ToCStringInternal(intptr_t frame_index) const;
 
  private:
   void set_function_array(const Array& function_array) const;
   void set_code_array(const Array& code_array) const;
   void set_pc_offset_array(const Array& pc_offset_array) const;
+  void set_catch_func_array(const Array& function_array) const;
+  void set_catch_code_array(const Array& code_array) const;
+  void set_catch_pc_offset_array(const Array& pc_offset_array) const;
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Stacktrace, Instance);
   friend class Class;
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 5343c42..31b9ccc 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -87,6 +87,7 @@
     empty_context_(Context::null()),
     stack_overflow_(Instance::null()),
     out_of_memory_(Instance::null()),
+    preallocated_stack_trace_(Stacktrace::null()),
     keyword_symbols_(Array::null()),
     receive_port_create_function_(Function::null()),
     lookup_receive_port_function_(Function::null()),
@@ -114,12 +115,14 @@
 bool ObjectStore::PreallocateObjects() {
   Isolate* isolate = Isolate::Current();
   ASSERT(isolate != NULL && isolate->object_store() == this);
-  if (this->stack_overflow() != Instance::null() &&
-      this->out_of_memory() != Instance::null()) {
+  if (this->stack_overflow() != Instance::null()) {
+    ASSERT(this->out_of_memory() != Instance::null());
+    ASSERT(this->preallocated_stack_trace() != Stacktrace::null());
     return true;
   }
   ASSERT(this->stack_overflow() == Instance::null());
   ASSERT(this->out_of_memory() == Instance::null());
+  ASSERT(this->preallocated_stack_trace() == Stacktrace::null());
   // TODO(regis): Reenable this code for arm and mips when possible.
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
   Object& result = Object::Handle();
@@ -136,6 +139,17 @@
     return false;
   }
   set_out_of_memory(Instance::Cast(result));
+  const Array& func_array = Array::Handle(
+      isolate,
+      Array::New(Stacktrace::kPreallocatedStackdepth, Heap::kOld));
+  const Array& code_array = Array::Handle(
+      isolate,
+      Array::New(Stacktrace::kPreallocatedStackdepth, Heap::kOld));
+  const Array& pc_offset_array = Array::Handle(
+      isolate,
+      Array::New(Stacktrace::kPreallocatedStackdepth, Heap::kOld));
+  result = Stacktrace::New(func_array, code_array, pc_offset_array);
+  set_preallocated_stack_trace(Stacktrace::Cast(result));
 #endif
   return true;
 }
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 8bc26cf..1811803 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -164,6 +164,20 @@
     return OFFSET_OF(ObjectStore, growable_object_array_class_);
   }
 
+  RawClass* float32x4_class() const {
+    return float32x4_class_;
+  }
+  void set_float32x4_class(const Class& value) {
+    float32x4_class_ = value.raw();
+  }
+
+  RawClass* uint32x4_class() const {
+    return uint32x4_class_;
+  }
+  void set_uint32x4_class(const Class& value) {
+    uint32x4_class_ = value.raw();
+  }
+
   RawClass* int8_array_class() const {
     return int8_array_class_;
   }
@@ -227,6 +241,13 @@
     uint64_array_class_ = value.raw();
   }
 
+  RawClass* float32x4_array_class() const {
+    return float32x4_array_class_;
+  }
+  void set_float32x4_array_class(const Class& value) {
+    float32x4_array_class_ = value.raw();
+  }
+
   RawClass* float32_array_class() const {
     return float32_array_class_;
   }
@@ -304,6 +325,13 @@
     external_uint64_array_class_ = value.raw();
   }
 
+  RawClass* external_float32x4_array_class() const {
+    return external_float32x4_array_class_;
+  }
+  void set_external_float32x4_array_class(const Class& value) {
+    external_float32x4_array_class_ = value.raw();
+  }
+
   RawClass* external_float32_array_class() const {
     return external_float32_array_class_;
   }
@@ -497,6 +525,13 @@
     out_of_memory_ = value.raw();
   }
 
+  RawStacktrace* preallocated_stack_trace() const {
+    return preallocated_stack_trace_;
+  }
+  void set_preallocated_stack_trace(const Stacktrace& value) {
+    preallocated_stack_trace_ = value.raw();
+  }
+
   RawArray* keyword_symbols() const { return keyword_symbols_; }
   void set_keyword_symbols(const Array& value) {
     keyword_symbols_ = value.raw();
@@ -568,6 +603,8 @@
   RawType* array_type_;
   RawClass* immutable_array_class_;
   RawClass* growable_object_array_class_;
+  RawClass* float32x4_class_;
+  RawClass* uint32x4_class_;
   RawClass* int8_array_class_;
   RawClass* uint8_array_class_;
   RawClass* uint8_clamped_array_class_;
@@ -577,6 +614,7 @@
   RawClass* uint32_array_class_;
   RawClass* int64_array_class_;
   RawClass* uint64_array_class_;
+  RawClass* float32x4_array_class_;
   RawClass* float32_array_class_;
   RawClass* float64_array_class_;
   RawClass* external_int8_array_class_;
@@ -588,6 +626,7 @@
   RawClass* external_uint32_array_class_;
   RawClass* external_int64_array_class_;
   RawClass* external_uint64_array_class_;
+  RawClass* external_float32x4_array_class_;
   RawClass* external_float32_array_class_;
   RawClass* external_float64_array_class_;
   RawClass* stacktrace_class_;
@@ -618,6 +657,7 @@
   RawContext* empty_context_;
   RawInstance* stack_overflow_;
   RawInstance* out_of_memory_;
+  RawStacktrace* preallocated_stack_trace_;
   RawArray* keyword_symbols_;
   RawFunction* receive_port_create_function_;
   RawFunction* lookup_receive_port_function_;
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index a9dcfd9..ab50b27 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -32,9 +32,95 @@
     "Generate symbols of generated dart functions for debugging with GDB");
 DEFINE_FLAG(bool, generate_perf_events_symbols, false,
     "Generate events symbols for profiling with perf");
+DEFINE_FLAG(bool, ll_prof, false,
+    "Generate compiled code log file for processing with ll_prof.py.");
 DEFINE_FLAG(charp, generate_pprof_symbols, NULL,
     "Writes pprof events symbols to the provided file");
 
+class LowLevelProfileCodeObserver : public CodeObserver {
+ public:
+  LowLevelProfileCodeObserver() {
+    Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+    if (file_open == NULL) {
+      return;
+    }
+    const char* filename = "v8.log.ll";
+    log_file_ = (*file_open)(filename);
+#if defined(TARGET_ARCH_IA32)
+    const char arch[] = "ia32";
+#elif defined(TARGET_ARCH_X64)
+    const char arch[] = "x64";
+#elif defined(TARGET_ARCH_ARM)
+    const char arch[] = "arm";
+#elif defined(TARGET_ARCH_MIPS)
+    const char arch[] = "mips";
+#else
+    const char arch[] = "unknown";
+#endif
+    LowLevelLogWriteBytes(arch, sizeof(arch));
+  }
+
+  ~LowLevelProfileCodeObserver() {
+    Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+    if (file_close == NULL) {
+      return;
+    }
+    ASSERT(log_file_ != NULL);
+    (*file_close)(log_file_);
+  }
+
+  virtual bool IsActive() const {
+    return FLAG_ll_prof;
+  }
+
+  struct LowLevelCodeCreateStruct {
+    static const char kTag = 'C';
+
+    int32_t name_size;
+    uword code_address;
+    int32_t code_size;
+  };
+
+  template <typename T>
+  void LowLevelLogWriteStruct(const T& s) {
+    char tag = T::kTag;
+    LowLevelLogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag));
+    LowLevelLogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s));
+  }
+
+  void LowLevelLogWriteBytes(const char* bytes, int size) {
+    Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+    ASSERT(file_write != NULL);
+    (file_write)(bytes, size, log_file_);
+  }
+
+  virtual void Notify(const char* name,
+                      uword base,
+                      uword prologue_offset,
+                      uword size,
+                      bool optimized) {
+    const char* marker = optimized ? "*" : "";
+    char* name_buffer =
+        Isolate::Current()->current_zone()->PrintToString("%s%s", marker, name);
+    intptr_t len = strlen(name_buffer);
+
+    LowLevelCodeCreateStruct event;
+    event.name_size = len;
+    event.code_address = base;
+    event.code_size = size;
+
+    LowLevelLogWriteStruct(event);
+    LowLevelLogWriteBytes(name_buffer, len);
+    LowLevelLogWriteBytes(reinterpret_cast<char*>(base), size);
+  }
+
+ private:
+  void* log_file_;
+
+  DISALLOW_COPY_AND_ASSIGN(LowLevelProfileCodeObserver);
+};
+
+
 class PerfCodeObserver : public CodeObserver {
  public:
   PerfCodeObserver() {
@@ -378,6 +464,9 @@
 
 
 void OS::RegisterCodeObservers() {
+  if (FLAG_ll_prof) {
+    CodeObservers::Register(new LowLevelProfileCodeObserver);
+  }
   if (FLAG_generate_perf_events_symbols) {
     CodeObservers::Register(new PerfCodeObserver);
   }
diff --git a/runtime/vm/os_test.cc b/runtime/vm/os_test.cc
index a64fc82..ff577b4 100644
--- a/runtime/vm/os_test.cc
+++ b/runtime/vm/os_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -15,7 +15,7 @@
   int64_t sleep_time = 702;
   OS::Sleep(sleep_time);
   int64_t delta = OS::GetCurrentTimeMillis() - start_time;
-  const int kAcceptableSleepWakeupJitter = 100;  // Measured in milliseconds.
+  const int kAcceptableSleepWakeupJitter = 200;  // Measured in milliseconds.
   EXPECT_GE(delta, sleep_time - kAcceptableSleepWakeupJitter);
   EXPECT_LE(delta, sleep_time + kAcceptableSleepWakeupJitter);
 }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 4740688..47c8b1e 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -3415,6 +3415,13 @@
   library_.AddClass(mixin_application);
   set_current_class(mixin_application);
   ParseTypeParameters(mixin_application);
+
+  // TODO(hausner): Handle mixin application aliases with generics.
+  if (mixin_application.NumTypeParameters() > 0) {
+    ErrorMsg(classname_pos,
+             "type parameters on mixin applications not yet supported");
+  }
+
   ExpectToken(Token::kASSIGN);
 
   if (CurrentToken() == Token::kABSTRACT) {
@@ -3438,8 +3445,15 @@
     ErrorMsg("mixin application 'with Type' expected");
   }
 
-  Type& mixin_application_type = Type::Handle(ParseMixins(mixin_super_type));
-  // The result of ParseMixins() is a chain of super classes that is the
+  const Type& mixin_application_type =
+      Type::Handle(ParseMixins(mixin_super_type));
+  // TODO(hausner): Implement generic mixin support.
+  if (mixin_application_type.arguments() != AbstractTypeArguments::null()) {
+    ErrorMsg(mixin_application_type.token_pos(),
+             "mixin class with type arguments not yet supported");
+  }
+
+  // The result of ParseMixins() is a chain of super types that is the
   // result of the mixin composition 'S with M1, M2, ...'. The mixin
   // application classes are anonymous (i.e. not registered in the current
   // library). We steal the super type and mixin type from the bottom of
@@ -3838,7 +3852,7 @@
   // TODO(hausner): Remove this restriction.
   if (super_type.arguments() != AbstractTypeArguments::null()) {
     ErrorMsg(super_type.token_pos(),
-             "super class of mixin may not have type arguments");
+             "super class in mixin application may not have type arguments");
   }
 
   AbstractType& mixin_type = AbstractType::Handle();
@@ -3848,7 +3862,6 @@
   Type& mixin_application_type = Type::Handle();
   Type& mixin_super_type = Type::Handle(super_type.raw());
   Array& mixin_application_interfaces = Array::Handle();
-  const TypeArguments& no_type_arguments = TypeArguments::Handle();
   do {
     ConsumeToken();
     const intptr_t mixin_pos = TokenPos();
@@ -3858,22 +3871,14 @@
                "mixin type '%s' may not be a type parameter",
                String::Handle(mixin_type.UserVisibleName()).ToCString());
     }
-    // TODO(hausner): Remove this check once we handle mixins with type
-    // arguments.
-    mixin_type_arguments = mixin_type.arguments();
-    if (!mixin_type_arguments.IsNull()) {
-      ErrorMsg(mixin_pos,
-               "mixin type '%s' may not have type arguments",
-               String::Handle(mixin_type.UserVisibleName()).ToCString());
-    }
 
     // The name of the mixin application class is a combination of
     // the superclass and mixin class.
     String& mixin_app_name = String::Handle();
-    mixin_app_name = mixin_super_type.Name();
+    mixin_app_name = mixin_super_type.ClassName();
     mixin_app_name = String::Concat(mixin_app_name, Symbols::Ampersand());
     mixin_app_name = String::Concat(mixin_app_name,
-                                     String::Handle(mixin_type.Name()));
+                                     String::Handle(mixin_type.ClassName()));
     mixin_app_name = Symbols::New(mixin_app_name);
 
     mixin_application = Class::New(mixin_app_name, script_, mixin_pos);
@@ -3887,10 +3892,17 @@
     mixin_application_interfaces.SetAt(0, mixin_type);
     mixin_application.set_interfaces(mixin_application_interfaces);
 
-    // TODO(hausner): Need to support type arguments.
+    // For the type arguments of the mixin application type, we need
+    // a copy of the type arguments to the mixin type. The simplest way
+    // to get the copy is to rewind the parser, parse the mixin type
+    // again and steal its type arguments.
+    SetPosition(mixin_pos);
+    mixin_type = ParseType(ClassFinalizer::kTryResolve);
+    mixin_type_arguments = mixin_type.arguments();
+
     mixin_application_type = Type::New(mixin_application,
-                                       no_type_arguments,
-                                       Scanner::kDummyTokenIndex);
+                                       mixin_type_arguments,
+                                       mixin_pos);
     mixin_super_type = mixin_application_type.raw();
   } while (CurrentToken() == Token::kCOMMA);
   return mixin_application_type.raw();
@@ -4252,23 +4264,36 @@
 }
 
 
-Dart_Handle Parser::CallLibraryTagHandler(Dart_LibraryTag tag,
+RawObject* Parser::CallLibraryTagHandler(Dart_LibraryTag tag,
                                           intptr_t token_pos,
                                           const String& url) {
   Isolate* isolate = Isolate::Current();
   Dart_LibraryTagHandler handler = isolate->library_tag_handler();
   if (handler == NULL) {
+    if (url.StartsWith(Symbols::DartScheme())) {
+      if (tag == kCanonicalizeUrl) {
+        return url.raw();
+      }
+      return Object::null();
+    }
     ErrorMsg(token_pos, "no library handler registered");
   }
   Dart_Handle result = handler(tag,
                                Api::NewHandle(isolate, library_.raw()),
                                Api::NewHandle(isolate, url.raw()));
   if (Dart_IsError(result)) {
+    // In case of an error we append an explanatory error message to the
+    // error obtained from the library tag handler.
     Error& prev_error = Error::Handle();
     prev_error ^= Api::UnwrapHandle(result);
     AppendErrorMsg(prev_error, token_pos, "library handler failed");
   }
-  return result;
+  if (tag == kCanonicalizeUrl) {
+    if (!Dart_IsString(result)) {
+      ErrorMsg(token_pos, "library handler failed URI canonicalization");
+    }
+  }
+  return Api::UnwrapHandle(result);
 }
 
 
@@ -4303,10 +4328,8 @@
     }
     ExpectToken(Token::kRPAREN);
     ExpectToken(Token::kSEMICOLON);
-    Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl,
-                                               import_pos,
-                                               url);
-    const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
+    const String& canon_url = String::CheckedHandle(
+        CallLibraryTagHandler(kCanonicalizeUrl, import_pos, url));
     // Lookup the library URL.
     Library& library = Library::Handle(Library::LookupLibrary(canon_url));
     if (library.IsNull()) {
@@ -4352,10 +4375,8 @@
     ConsumeToken();
     ExpectToken(Token::kRPAREN);
     ExpectToken(Token::kSEMICOLON);
-    Dart_Handle handle = CallLibraryTagHandler(kCanonicalizeUrl,
-                                               source_pos,
-                                               url);
-    const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
+    const String& canon_url = String::CheckedHandle(
+        CallLibraryTagHandler(kCanonicalizeUrl, source_pos, url));
     CallLibraryTagHandler(kSourceTag, source_pos, canon_url);
   }
 }
@@ -4442,9 +4463,8 @@
   ExpectSemicolon();
 
   // Canonicalize library URL.
-  Dart_Handle handle =
-      CallLibraryTagHandler(kCanonicalizeUrl, import_pos, url);
-  const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
+  const String& canon_url = String::CheckedHandle(
+      CallLibraryTagHandler(kCanonicalizeUrl, import_pos, url));
   // Lookup the library URL.
   Library& library = Library::Handle(Library::LookupLibrary(canon_url));
   if (library.IsNull()) {
@@ -4496,9 +4516,8 @@
   const String& url = *CurrentLiteral();
   ConsumeToken();
   ExpectSemicolon();
-  Dart_Handle handle =
-      CallLibraryTagHandler(kCanonicalizeUrl, source_pos, url);
-  const String& canon_url = String::CheckedHandle(Api::UnwrapHandle(handle));
+  const String& canon_url = String::CheckedHandle(
+      CallLibraryTagHandler(kCanonicalizeUrl, source_pos, url));
   CallLibraryTagHandler(kSourceTag, source_pos, canon_url);
 }
 
@@ -4531,8 +4550,6 @@
     return;
   }
 
-  const bool is_script = (script_.kind() == RawScript::kScriptTag);
-  const bool is_library = (script_.kind() == RawScript::kLibraryTag);
   ASSERT(script_.kind() != RawScript::kSourceTag);
 
   // We may read metadata tokens that are part of the toplevel
@@ -4542,17 +4559,15 @@
   intptr_t metadata_pos = TokenPos();
   SkipMetadata();
   if (CurrentToken() == Token::kLIBRARY) {
+    if (is_patch_source()) {
+      ErrorMsg("patch cannot override library name");
+    }
     ParseLibraryName();
     metadata_pos = TokenPos();
     SkipMetadata();
-  } else if (is_library) {
-    ErrorMsg("library name definition expected");
   }
   while ((CurrentToken() == Token::kIMPORT) ||
       (CurrentToken() == Token::kEXPORT)) {
-    if (is_script && (CurrentToken() == Token::kEXPORT)) {
-      ErrorMsg("export not allowed in scripts");
-    }
     ParseLibraryImportExport();
     metadata_pos = TokenPos();
     SkipMetadata();
@@ -4617,7 +4632,7 @@
       Class::New(Symbols::TopLevel(), script_, TokenPos()));
   toplevel_class.set_library(library_);
 
-  if (is_library_source()) {
+  if (is_library_source() || is_patch_source()) {
     ParseLibraryDefinition();
   } else if (is_part_source()) {
     ParsePartHeader();
@@ -5082,7 +5097,7 @@
         Type::Handle(Type::Function()).type_class());
     function_type = Type::New(
         unknown_signature_class, TypeArguments::Handle(), ident_pos);
-    function_type.set_is_finalized_instantiated();  // No finalization needed.
+    function_type.SetIsFinalized();  // No finalization needed.
 
     // Add the function variable to the scope before parsing the function in
     // order to allow self reference from inside the function.
@@ -6278,11 +6293,18 @@
       // A stack trace variable is specified in this block, so generate code
       // to load the stack trace object (:stacktrace_var) into the stack trace
       // variable specified in this block.
+      ArgumentListNode* no_args = new ArgumentListNode(catch_pos);
       LocalVariable* trace = LookupLocalScope(*stack_trace_param.var);
       ASSERT(catch_trace_var != NULL);
       current_block_->statements->Add(
           new StoreLocalNode(catch_pos, trace,
                              new LoadLocalNode(catch_pos, catch_trace_var)));
+      current_block_->statements->Add(
+          new InstanceCallNode(
+              catch_pos,
+              new LoadLocalNode(catch_pos, trace),
+              PrivateCoreLibName(Symbols::_setupFullStackTrace()),
+              no_args));
     }
 
     ParseStatementSequence();  // Parse the catch handler code.
@@ -8185,7 +8207,7 @@
       ASSERT(!func.IsNull());
       ASSERT(func.kind() == RawFunction::kConstImplicitGetter);
       Object& const_value = Object::Handle(
-          DartEntry::InvokeStatic(func, Object::empty_array()));
+          DartEntry::InvokeFunction(func, Object::empty_array()));
       if (const_value.IsError()) {
         const Error& error = Error::Cast(const_value);
         if (error.IsUnhandledException()) {
@@ -8248,9 +8270,9 @@
       Array::Handle(ArgumentsDescriptor::New(num_arguments,
                                              arguments->names()));
   const Object& result =
-      Object::Handle(DartEntry::InvokeStatic(constructor,
-                                             arg_values,
-                                             arg_descriptor));
+      Object::Handle(DartEntry::InvokeFunction(constructor,
+                                               arg_values,
+                                               arg_descriptor));
   if (result.IsError()) {
       if (result.IsUnhandledException()) {
         return result.raw();
@@ -9459,7 +9481,7 @@
 
   // Call interpolation function.
   String& concatenated = String::ZoneHandle();
-  concatenated ^= DartEntry::InvokeStatic(func, interpolate_arg);
+  concatenated ^= DartEntry::InvokeFunction(func, interpolate_arg);
   if (concatenated.IsUnhandledException()) {
     ErrorMsg("Exception thrown in Parser::Interpolate");
   }
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index ba83c47..5dd2aa6 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -336,9 +336,9 @@
   void ParseTopLevelAccessor(TopLevel* top_level);
 
   // Support for parsing libraries.
-  Dart_Handle CallLibraryTagHandler(Dart_LibraryTag tag,
-                                    intptr_t token_pos,
-                                    const String& url);
+  RawObject* CallLibraryTagHandler(Dart_LibraryTag tag,
+                                   intptr_t token_pos,
+                                   const String& url);
   void ParseIdentList(GrowableObjectArray* names);
   void ParseLibraryDefinition();
   void ParseLibraryName();
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index ecf2a79..0e47312 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -182,6 +182,13 @@
         instance_size = Uint64Array::InstanceSize(byte_array_length);
         break;
       }
+      case kFloat32x4ArrayCid: {
+        const RawFloat32x4Array* raw_byte_array =
+            reinterpret_cast<const RawFloat32x4Array*>(this);
+        intptr_t byte_array_length = Smi::Value(raw_byte_array->ptr()->length_);
+        instance_size = Float32x4Array::InstanceSize(byte_array_length);
+        break;
+      }
       case kFloat32ArrayCid: {
         const RawFloat32Array* raw_byte_array =
             reinterpret_cast<const RawFloat32Array*>(this);
@@ -761,6 +768,22 @@
 }
 
 
+intptr_t RawFloat32x4::VisitFloat32x4Pointers(
+    RawFloat32x4* raw_obj,
+    ObjectPointerVisitor* visitor) {
+    ASSERT(raw_obj->IsHeapObject());
+    return Float32x4::InstanceSize();
+}
+
+
+intptr_t RawUint32x4::VisitUint32x4Pointers(
+    RawUint32x4* raw_obj,
+    ObjectPointerVisitor* visitor) {
+    ASSERT(raw_obj->IsHeapObject());
+    return Uint32x4::InstanceSize();
+}
+
+
 intptr_t RawByteArray::VisitByteArrayPointers(RawByteArray* raw_obj,
                                               ObjectPointerVisitor* visitor) {
   // ByteArray is an abstract class.
@@ -859,6 +882,15 @@
 }
 
 
+intptr_t RawFloat32x4Array::VisitFloat32x4ArrayPointers(
+    RawFloat32x4Array *raw_obj, ObjectPointerVisitor* visitor) {
+  // Make sure that we got here with the tagged pointer as this.
+  ASSERT(raw_obj->IsHeapObject());
+  intptr_t length = Smi::Value(raw_obj->ptr()->length_);
+  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+  return Float32x4Array::InstanceSize(length);
+}
+
 intptr_t RawFloat32Array::VisitFloat32ArrayPointers(
     RawFloat32Array *raw_obj, ObjectPointerVisitor* visitor) {
   // Make sure that we got here with the tagged pointer as this.
@@ -960,6 +992,16 @@
 }
 
 
+intptr_t
+    RawExternalFloat32x4Array::VisitExternalFloat32x4ArrayPointers(
+    RawExternalFloat32x4Array* raw_obj, ObjectPointerVisitor* visitor) {
+  // Make sure that we got here with the tagged pointer as this.
+  ASSERT(raw_obj->IsHeapObject());
+  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+  return ExternalFloat32x4Array::InstanceSize();
+}
+
+
 intptr_t RawExternalFloat32Array::VisitExternalFloat32ArrayPointers(
     RawExternalFloat32Array* raw_obj, ObjectPointerVisitor* visitor) {
   // Make sure that we got here with the tagged pointer as this.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 2889ff9..6d829fe 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -71,6 +71,7 @@
       V(Uint32Array)                                                           \
       V(Int64Array)                                                            \
       V(Uint64Array)                                                           \
+      V(Float32x4Array)                                                        \
       V(Float32Array)                                                          \
       V(Float64Array)                                                          \
       V(ExternalInt8Array)                                                     \
@@ -82,12 +83,16 @@
       V(ExternalUint32Array)                                                   \
       V(ExternalInt64Array)                                                    \
       V(ExternalUint64Array)                                                   \
+      V(ExternalFloat32x4Array)                                                \
       V(ExternalFloat32Array)                                                  \
       V(ExternalFloat64Array)                                                  \
     V(Stacktrace)                                                              \
     V(JSRegExp)                                                                \
     V(WeakProperty)                                                            \
     V(DartFunction)                                                            \
+    V(Float32x4)                                                               \
+    V(Uint32x4)                                                                \
+
 
 #define CLASS_LIST_STRINGS(V)                                                  \
   V(String)                                                                    \
@@ -1301,6 +1306,24 @@
 };
 
 
+class RawFloat32x4 : public RawInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(Float32x4);
+
+  float value_[4];
+
+  friend class SnapshotReader;
+};
+
+
+class RawUint32x4 : public RawInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(Uint32x4);
+
+  uint32_t value_[4];
+
+  friend class SnapshotReader;
+};
+
+
 // Define an aliases for intptr_t.
 #if defined(ARCH_IS_32_BIT)
 #define RawIntPtrArray RawInt32Array
@@ -1401,6 +1424,13 @@
 };
 
 
+class RawFloat32x4Array : public RawByteArray {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(Float32x4Array);
+
+  // Variable length data follows here.
+  simd_value_t data_[0];
+};
+
 class RawFloat32Array : public RawByteArray {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Float32Array);
 
@@ -1490,6 +1520,14 @@
 };
 
 
+class RawExternalFloat32x4Array : public RawByteArray {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32x4Array);
+
+  simd_value_t* data_;
+  void* peer_;
+};
+
+
 class RawExternalFloat32Array : public RawByteArray {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32Array);
 
@@ -1524,8 +1562,11 @@
   RawArray* function_array_;  // Function for each frame in the stack trace.
   RawArray* code_array_;  // Code object for each frame in the stack trace.
   RawArray* pc_offset_array_;  // Offset of PC for each frame.
+  RawArray* catch_func_array_;  // Func for each frame in catch stack trace.
+  RawArray* catch_code_array_;  // Code for each frame in catch stack trace.
+  RawArray* catch_pc_offset_array_;  // Offset of PC for each catch stack frame.
   RawObject** to() {
-    return reinterpret_cast<RawObject**>(&ptr()->pc_offset_array_);
+    return reinterpret_cast<RawObject**>(&ptr()->catch_pc_offset_array_);
   }
 };
 
@@ -1670,20 +1711,22 @@
          kUint32ArrayCid == kByteArrayCid + 7 &&
          kInt64ArrayCid == kByteArrayCid + 8 &&
          kUint64ArrayCid == kByteArrayCid + 9 &&
-         kFloat32ArrayCid == kByteArrayCid + 10 &&
-         kFloat64ArrayCid == kByteArrayCid + 11 &&
-         kExternalInt8ArrayCid == kByteArrayCid + 12 &&
-         kExternalUint8ArrayCid == kByteArrayCid + 13 &&
-         kExternalUint8ClampedArrayCid == kByteArrayCid + 14 &&
-         kExternalInt16ArrayCid == kByteArrayCid + 15 &&
-         kExternalUint16ArrayCid == kByteArrayCid + 16 &&
-         kExternalInt32ArrayCid == kByteArrayCid + 17 &&
-         kExternalUint32ArrayCid == kByteArrayCid + 18 &&
-         kExternalInt64ArrayCid == kByteArrayCid + 19 &&
-         kExternalUint64ArrayCid == kByteArrayCid + 20 &&
-         kExternalFloat32ArrayCid == kByteArrayCid + 21 &&
-         kExternalFloat64ArrayCid == kByteArrayCid + 22 &&
-         kStacktraceCid == kByteArrayCid + 23);
+         kFloat32x4ArrayCid == kByteArrayCid + 10 &&
+         kFloat32ArrayCid == kByteArrayCid + 11 &&
+         kFloat64ArrayCid == kByteArrayCid + 12 &&
+         kExternalInt8ArrayCid == kByteArrayCid + 13 &&
+         kExternalUint8ArrayCid == kByteArrayCid + 14 &&
+         kExternalUint8ClampedArrayCid == kByteArrayCid + 15 &&
+         kExternalInt16ArrayCid == kByteArrayCid + 16 &&
+         kExternalUint16ArrayCid == kByteArrayCid + 17 &&
+         kExternalInt32ArrayCid == kByteArrayCid + 18 &&
+         kExternalUint32ArrayCid == kByteArrayCid + 19 &&
+         kExternalInt64ArrayCid == kByteArrayCid + 20 &&
+         kExternalUint64ArrayCid == kByteArrayCid + 21 &&
+         kExternalFloat32x4ArrayCid == kByteArrayCid + 22 &&
+         kExternalFloat32ArrayCid == kByteArrayCid + 23 &&
+         kExternalFloat64ArrayCid == kByteArrayCid + 24 &&
+         kStacktraceCid == kByteArrayCid + 25);
   return (index >= kByteArrayCid && index <= kExternalFloat64ArrayCid);
 }
 
@@ -1697,9 +1740,10 @@
          kExternalUint32ArrayCid == kExternalInt8ArrayCid + 6 &&
          kExternalInt64ArrayCid == kExternalInt8ArrayCid + 7 &&
          kExternalUint64ArrayCid == kExternalInt8ArrayCid + 8 &&
-         kExternalFloat32ArrayCid == kExternalInt8ArrayCid + 9 &&
-         kExternalFloat64ArrayCid == kExternalInt8ArrayCid + 10 &&
-         kStacktraceCid == kExternalInt8ArrayCid + 11);
+         kExternalFloat32x4ArrayCid == kExternalInt8ArrayCid + 9 &&
+         kExternalFloat32ArrayCid == kExternalInt8ArrayCid + 10 &&
+         kExternalFloat64ArrayCid == kExternalInt8ArrayCid + 11 &&
+         kStacktraceCid == kExternalInt8ArrayCid + 12);
   return (index >= kExternalInt8ArrayCid && index <= kExternalFloat64ArrayCid);
 }
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 2b4011d..99370a2 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -2045,6 +2045,98 @@
 }
 
 
+RawFloat32x4* Float32x4::ReadFrom(SnapshotReader* reader,
+                                            intptr_t object_id,
+                                            intptr_t tags,
+                                            Snapshot::Kind kind) {
+  ASSERT(reader != NULL);
+  // Read the values.
+  float value0 = reader->Read<float>();
+  float value1 = reader->Read<float>();
+  float value2 = reader->Read<float>();
+  float value3 = reader->Read<float>();
+
+  // Create a Float32x4 object.
+  Float32x4& simd = Float32x4::ZoneHandle(reader->isolate(),
+                                          Float32x4::null());
+  if (kind == Snapshot::kFull) {
+    simd = reader->NewFloat32x4(value0, value1, value2, value3);
+  } else {
+    simd = Float32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
+  }
+  reader->AddBackRef(object_id, &simd, kIsDeserialized);
+  // Set the object tags.
+  simd.set_tags(tags);
+  return simd.raw();
+}
+
+
+void RawFloat32x4::WriteTo(SnapshotWriter* writer,
+                                intptr_t object_id,
+                                Snapshot::Kind kind) {
+  ASSERT(writer != NULL);
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+
+  // Write out the class and tags information.
+  writer->WriteIndexedObject(kFloat32x4Cid);
+  writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+  // Write out the float values.
+  writer->Write<float>(ptr()->value_[0]);
+  writer->Write<float>(ptr()->value_[1]);
+  writer->Write<float>(ptr()->value_[2]);
+  writer->Write<float>(ptr()->value_[3]);
+}
+
+
+RawUint32x4* Uint32x4::ReadFrom(SnapshotReader* reader,
+                                      intptr_t object_id,
+                                      intptr_t tags,
+                                      Snapshot::Kind kind) {
+  ASSERT(reader != NULL);
+  // Read the values.
+  uint32_t value0 = reader->Read<uint32_t>();
+  uint32_t value1 = reader->Read<uint32_t>();
+  uint32_t value2 = reader->Read<uint32_t>();
+  uint32_t value3 = reader->Read<uint32_t>();
+
+  // Create a Float32x4 object.
+  Uint32x4& simd = Uint32x4::ZoneHandle(reader->isolate(), Uint32x4::null());
+
+  if (kind == Snapshot::kFull) {
+    simd = reader->NewUint32x4(value0, value1, value2, value3);
+  } else {
+    simd = Uint32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
+  }
+  reader->AddBackRef(object_id, &simd, kIsDeserialized);
+  // Set the object tags.
+  simd.set_tags(tags);
+  return simd.raw();
+}
+
+
+void RawUint32x4::WriteTo(SnapshotWriter* writer,
+                             intptr_t object_id,
+                             Snapshot::Kind kind) {
+  ASSERT(writer != NULL);
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+
+  // Write out the class and tags information.
+  writer->WriteIndexedObject(kUint32x4Cid);
+  writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+  // Write out the mask values.
+  writer->Write<uint32_t>(ptr()->value_[0]);
+  writer->Write<uint32_t>(ptr()->value_[1]);
+  writer->Write<uint32_t>(ptr()->value_[2]);
+  writer->Write<uint32_t>(ptr()->value_[3]);
+}
+
+
 RawByteArray* ByteArray::ReadFrom(SnapshotReader* reader,
                                   intptr_t object_id,
                                   intptr_t tags,
@@ -2106,6 +2198,32 @@
 BYTEARRAY_TYPE_LIST(BYTEARRAY_READ_FROM)
 #undef BYTEARRAY_READ_FROM
 
+RawFloat32x4Array* Float32x4Array::ReadFrom(SnapshotReader* reader,
+                                                      intptr_t object_id,
+                                                      intptr_t tags,
+                                                      Snapshot::Kind kind) {
+  ASSERT(reader != NULL);
+
+  intptr_t len = reader->ReadSmiValue();
+  Float32x4Array& result = Float32x4Array::ZoneHandle(
+      reader->isolate(), Float32x4Array::New(len, HEAP_SPACE(kind)));
+  reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+  // Set the object tags.
+  result.set_tags(tags);
+
+  // Setup the array elements.
+  float v[4];
+  for (intptr_t i = 0; i < len; ++i) {
+    v[0] = reader->Read<float>();
+    v[1] = reader->Read<float>();
+    v[2] = reader->Read<float>();
+    v[3] = reader->Read<float>();
+    result.SetAt(i, simd_value_safe_load(&v[0]));
+  }
+  return result.raw();
+}
+
 
 #define EXTERNALARRAY_READ_FROM(name, lname, type)                             \
 RawExternal##name##Array* External##name##Array::ReadFrom(                     \
@@ -2126,8 +2244,8 @@
   return obj.raw();                                                            \
 }                                                                              \
 
-
 BYTEARRAY_TYPE_LIST(EXTERNALARRAY_READ_FROM)
+EXTERNALARRAY_READ_FROM(Float32x4, Float32x4, simd_value_t)
 #undef EXTERNALARRAY_READ_FROM
 
 
@@ -2183,6 +2301,28 @@
 BYTEARRAY_TYPE_LIST(BYTEARRAY_WRITE_TO)
 #undef BYTEARRAY_WRITE_TO
 
+void RawFloat32x4Array::WriteTo(SnapshotWriter* writer, intptr_t object_id,
+                                     Snapshot::Kind kind) {
+  ASSERT(writer != NULL);
+  RawSmi* length = ptr()->length_;
+  float* data = reinterpret_cast<float*>(&ptr()->data_[0]);
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+
+  // Write out the class and tags information.
+  writer->WriteIndexedObject(kFloat32x4ArrayCid);
+  writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+  // Write out the length field.
+  writer->Write<RawObject*>(length);
+
+  // Write out the array elements as floats.
+  intptr_t len = Smi::Value(length)*4;
+  for (intptr_t i = 0; i < len; i++) {
+    writer->Write(data[i]);
+  }
+}
 
 #define EXTERNALARRAY_WRITE_TO(name, lname, type)                              \
 void RawExternal##name##Array::WriteTo(SnapshotWriter* writer,                 \
@@ -2200,6 +2340,30 @@
 
 BYTEARRAY_TYPE_LIST(EXTERNALARRAY_WRITE_TO)
 #undef BYTEARRAY_WRITE_TO
+void RawExternalFloat32x4Array::WriteTo(SnapshotWriter* writer,
+                                             intptr_t object_id,
+                                             Snapshot::Kind kind) {
+  ASSERT(writer != NULL);
+  RawSmi* length = ptr()->length_;
+  float* data = reinterpret_cast<float*>(&ptr()->data_[0]);
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+
+  // Write out the class and tags information.
+  writer->WriteIndexedObject(kExternalFloat32x4ArrayCid);
+  writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+  // Write out the length field.
+  writer->Write<RawObject*>(length);
+
+  // Write out the array elements as floats.
+  intptr_t len = Smi::Value(length)*4;
+  for (intptr_t i = 0; i < len; i++) {
+    writer->Write(data[i]);
+  }
+}
+
 #undef BYTEARRAY_TYPE_LIST
 
 
@@ -2223,7 +2387,32 @@
                                     intptr_t object_id,
                                     intptr_t tags,
                                     Snapshot::Kind kind) {
-  UNIMPLEMENTED();
+  if (kind == Snapshot::kFull) {
+    Stacktrace& result = Stacktrace::ZoneHandle(reader->isolate(),
+                                                reader->NewStacktrace());
+    reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+    // There are no non object pointer fields.
+
+    // Read all the object pointer fields.
+    Array& array = Array::Handle(reader->isolate());
+    array ^= reader->ReadObjectRef();
+    result.set_function_array(array);
+    array ^= reader->ReadObjectRef();
+    result.set_code_array(array);
+    array ^= reader->ReadObjectRef();
+    result.set_pc_offset_array(array);
+
+    array ^= reader->ReadObjectRef();
+    result.set_catch_func_array(array);
+    array ^= reader->ReadObjectRef();
+    result.set_catch_code_array(array);
+    array ^= reader->ReadObjectRef();
+    result.set_catch_pc_offset_array(array);
+
+    return result.raw();
+  }
+  UNREACHABLE();  // Stacktraces are not sent in a snapshot.
   return Stacktrace::null();
 }
 
@@ -2231,7 +2420,26 @@
 void RawStacktrace::WriteTo(SnapshotWriter* writer,
                             intptr_t object_id,
                             Snapshot::Kind kind) {
-  UNIMPLEMENTED();
+  if (kind == Snapshot::kFull) {
+    ASSERT(writer != NULL);
+    ASSERT(this == Isolate::Current()->object_store()->
+           preallocated_stack_trace());
+
+    // Write out the serialization header value for this object.
+    writer->WriteInlinedObjectHeader(object_id);
+
+    // Write out the class and tags information.
+    writer->WriteIndexedObject(kStacktraceCid);
+    writer->WriteIntptrValue(writer->GetObjectTags(this));
+
+    // There are no non object pointer fields.
+
+    // Write out all the object pointer fields.
+    SnapshotWriterVisitor visitor(writer);
+    visitor.VisitPointers(from(), to());
+  } else {
+    UNREACHABLE();  // Stacktraces are not supported for other snapshot forms.
+  }
 }
 
 
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
index 6e97d71..8b5499b 100644
--- a/runtime/vm/resolver_test.cc
+++ b/runtime/vm/resolver_test.cc
@@ -113,7 +113,7 @@
     const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
     args.SetAt(1, arg1);
     const Smi& retval = Smi::Handle(
-        reinterpret_cast<RawSmi*>(DartEntry::InvokeStatic(function, args)));
+        reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
     EXPECT_EQ(kTestValue, retval.Value());
   }
 
@@ -188,7 +188,7 @@
     const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
     args.SetAt(2, arg1);
     const Smi& retval = Smi::Handle(
-        reinterpret_cast<RawSmi*>(DartEntry::InvokeDynamic(function, args)));
+        reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
     EXPECT_EQ(kTestValue, retval.Value());
   }
 
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index e7119b8..77e6b54 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -7,10 +7,36 @@
 
 #include "vm/runtime_entry.h"
 
+#include "vm/assembler.h"
+#include "vm/simulator.h"
+#include "vm/stub_code.h"
+
 namespace dart {
 
+#define __ assembler->
+
+
+// Generate code to call into the stub which will call the runtime
+// function. Input for the stub is as follows:
+//   SP : points to the arguments and return value array.
+//   R5 : address of the runtime function to call.
+//   R4 : number of arguments to the call.
 void RuntimeEntry::Call(Assembler* assembler) const {
-  UNIMPLEMENTED();
+  // Compute the effective address. When running under the simulator,
+  // this is a redirection address that forces the simulator to call
+  // into the runtime system.
+  uword entry = GetEntryPoint();
+#if defined(USING_SIMULATOR)
+  entry = Simulator::RedirectExternalReference(entry, argument_count());
+#endif
+  if (is_leaf()) {
+    ExternalLabel label(name(), entry);
+    __ BranchLink(&label);
+  } else {
+    __ LoadImmediate(R5, entry);
+    __ LoadImmediate(R4, argument_count());
+    __ BranchLink(&StubCode::CallToRuntimeLabel());
+  }
 }
 
 }  // namespace dart
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 952ab88..5d14e41 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -135,14 +135,14 @@
 }
 
 
-static Register LookupCoreRegisterByName(const char* name) {
+static Register LookupCpuRegisterByName(const char* name) {
   static const char* kNames[] = {
       "r0",  "r1",  "r2",  "r3",
       "r4",  "r5",  "r6",  "r7",
       "r8",  "r9",  "r10", "r11",
       "r12", "r13", "r14", "r15",
       "pc",  "lr",  "sp",  "ip",
-      "fp",  "sl"
+      "fp",  "pp",  "ctx"
   };
   static const Register kRegisters[] = {
       R0,  R1,  R2,  R3,
@@ -150,7 +150,7 @@
       R8,  R9,  R10, R11,
       R12, R13, R14, R15,
       PC,  LR,  SP,  IP,
-      FP,  R10
+      FP,  R10, R9
   };
   ASSERT(ARRAY_SIZE(kNames) == ARRAY_SIZE(kRegisters));
   for (unsigned i = 0; i < ARRAY_SIZE(kNames); i++) {
@@ -183,7 +183,7 @@
 
 
 bool SimulatorDebugger::GetValue(char* desc, uint32_t* value) {
-  Register reg = LookupCoreRegisterByName(desc);
+  Register reg = LookupCpuRegisterByName(desc);
   if (reg != kNoRegister) {
     if (reg == PC) {
       *value = sim_->get_pc();
@@ -195,6 +195,9 @@
   if ((desc[0] == '*')) {
     uint32_t addr;
     if (GetValue(desc + 1, &addr)) {
+      if (Simulator::IsIllegalAddress(addr)) {
+        return false;
+      }
       *value = *(reinterpret_cast<uint32_t*>(addr));
       return true;
     }
@@ -216,6 +219,9 @@
   if ((desc[0] == '*')) {
     uint32_t addr;
     if (GetValue(desc + 1, &addr)) {
+      if (Simulator::IsIllegalAddress(addr)) {
+        return false;
+      }
       *value = *(reinterpret_cast<float*>(addr));
       return true;
     }
@@ -233,6 +239,9 @@
   if ((desc[0] == '*')) {
     uint32_t addr;
     if (GetValue(desc + 1, &addr)) {
+      if (Simulator::IsIllegalAddress(addr)) {
+        return false;
+      }
       *value = *(reinterpret_cast<double*>(addr));
       return true;
     }
@@ -671,11 +680,11 @@
     return reinterpret_cast<uword>(&svc_instruction_);
   }
 
-  void* external_function() const { return external_function_; }
+  uword external_function() const { return external_function_; }
 
   uint32_t argument_count() const { return argument_count_; }
 
-  static Redirection* Get(void* external_function, uint32_t argument_count) {
+  static Redirection* Get(uword external_function, uint32_t argument_count) {
     Redirection* current;
     for (current = list_; current != NULL; current = current->next_) {
       if (current->external_function_ == external_function) return current;
@@ -693,7 +702,7 @@
  private:
   static const int32_t kRedirectSvcInstruction =
     ((AL << kConditionShift) | (0xf << 24) | kRedirectionSvcCode);
-  Redirection(void* external_function, uint32_t argument_count)
+  Redirection(uword external_function, uint32_t argument_count)
       : external_function_(external_function),
         argument_count_(argument_count),
         svc_instruction_(kRedirectSvcInstruction),
@@ -701,7 +710,7 @@
     list_ = this;
   }
 
-  void* external_function_;
+  uword external_function_;
   const uint32_t argument_count_;
   uint32_t svc_instruction_;
   Redirection* next_;
@@ -712,7 +721,7 @@
 Redirection* Redirection::list_ = NULL;
 
 
-uword Simulator::RedirectExternalReference(void* function,
+uword Simulator::RedirectExternalReference(uword function,
                                            uint32_t argument_count) {
   Redirection* redirection = Redirection::Get(function, argument_count);
   return redirection->address_of_svc_instruction();
@@ -956,10 +965,10 @@
 
 // Returns the top of the stack area to enable checking for stack pointer
 // validity.
-uintptr_t Simulator::StackTop() const {
+uword Simulator::StackTop() const {
   // To be safe in potential stack underflows we leave some buffer above and
   // set the stack top.
-  return reinterpret_cast<uintptr_t>(stack_) +
+  return reinterpret_cast<uword>(stack_) +
       (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
 }
 
@@ -1316,8 +1325,7 @@
 
         int32_t saved_lr = get_register(LR);
         Redirection* redirection = Redirection::FromSvcInstruction(instr);
-        intptr_t external =
-            reinterpret_cast<intptr_t>(redirection->external_function());
+        uword external = redirection->external_function();
         SimulatorRuntimeCall target =
             reinterpret_cast<SimulatorRuntimeCall>(external);
         if (FLAG_trace_sim) {
@@ -1391,21 +1399,28 @@
     if (instr->IsMiscellaneous()) {
       switch (instr->Bits(4, 3)) {
         case 1: {
-          ASSERT(instr->Bits(21, 2) == 0x3);
-          // Format(instr, "clz'cond 'rd, 'rm");
-          Register rm = instr->RmField();
-          Register rd = instr->RdField();
-          int32_t rm_val = get_register(rm);
-          int32_t rd_val = 0;
-          if (rm_val != 0) {
-            while (rm_val > 0) {
-              rd_val++;
-              rm_val <<= 1;
+          if (instr->Bits(21, 2) == 0x3) {
+            // Format(instr, "clz'cond 'rd, 'rm");
+            Register rm = instr->RmField();
+            Register rd = instr->RdField();
+            int32_t rm_val = get_register(rm);
+            int32_t rd_val = 0;
+            if (rm_val != 0) {
+              while (rm_val > 0) {
+                rd_val++;
+                rm_val <<= 1;
+              }
+            } else {
+              rd_val = 32;
             }
+            set_register(rd, rd_val);
           } else {
-            rd_val = 32;
+            ASSERT(instr->Bits(21, 2) == 0x1);
+            // Format(instr, "bx'cond 'rm");
+            Register rm = instr->RmField();
+            int32_t rm_val = get_register(rm);
+            set_pc(rm_val);
           }
-          set_register(rd, rd_val);
           break;
         }
         case 3: {
@@ -1420,7 +1435,7 @@
         }
         case 7: {
           if (instr->Bits(21, 2) == 0x1) {
-            // Format(instr, "bkpt #'imm12_4");
+            // Format(instr, "bkpt'cond #'imm12_4");
             SimulatorDebugger dbg(this);
             set_pc(get_pc() + Instr::kInstrSize);
             char buffer[32];
@@ -2144,6 +2159,57 @@
         }
       }
     }
+  } else if (instr->IsVFPMultipleLoadStore()) {
+    Register rn = instr->RnField();
+    int32_t addr = get_register(rn);
+    int32_t imm_val = instr->Bits(0, 8);
+    if (instr->Bit(23) == 0) {
+      addr -= (imm_val << 2);
+    }
+    if (instr->HasW()) {
+      if (instr->Bit(23) == 1) {
+        set_register(rn, addr + (imm_val << 2));
+      } else {
+        set_register(rn, addr);  // already subtracted from addr
+      }
+    }
+    if (IsIllegalAddress(addr)) {
+      HandleIllegalAccess(addr, instr);
+    } else {
+      if (instr->Bit(8) == 0) {
+        int32_t regs_cnt = imm_val;
+        int32_t start = instr->Bit(22) | (instr->Bits(12, 4) << 1);
+        for (int i = start; i < start + regs_cnt; i++) {
+          SRegister sd = static_cast<SRegister>(i);
+          if (instr->Bit(20) == 1) {
+            // Format(instr, "vldms'cond'pu 'rn'w, 'slist");
+            set_sregister(sd, bit_cast<float, int32_t>(ReadW(addr, instr)));
+          } else {
+            // Format(instr, "vstms'cond'pu 'rn'w, 'slist");
+            WriteW(addr, bit_cast<int32_t, float>(get_sregister(sd)), instr);
+          }
+          addr += 4;
+        }
+      } else {
+        int32_t regs_cnt = imm_val >> 1;
+        int32_t start = (instr->Bit(22) << 4) | instr->Bits(12, 4);
+        for (int i = start; i < start + regs_cnt; i++) {
+          DRegister dd = static_cast<DRegister>(i);
+          if (instr->Bit(20) == 1) {
+            // Format(instr, "vldmd'cond'pu 'rn'w, 'dlist");
+            int64_t dd_val = Utils::LowHighTo64Bits(ReadW(addr, instr),
+                                                    ReadW(addr + 4, instr));
+            set_dregister(dd, bit_cast<double, int64_t>(dd_val));
+          } else {
+            // Format(instr, "vstmd'cond'pu 'rn'w, 'dlist");
+            int64_t dd_val = bit_cast<int64_t, double>(get_dregister(dd));
+            WriteW(addr, Utils::Low32Bits(dd_val), instr);
+            WriteW(addr + 4, Utils::High32Bits(dd_val), instr);
+          }
+          addr += 8;
+        }
+      }
+    }
   } else {
     UNIMPLEMENTED();
   }
@@ -2673,7 +2739,7 @@
   int32_t r11_val = get_register(R11);
 
   // Setup the callee-saved registers with a known value. To be able to check
-  // that they are preserved properly across JS execution.
+  // that they are preserved properly across dart execution.
   int32_t callee_saved_value = icount_;
   set_register(R4, callee_saved_value);
   set_register(R5, callee_saved_value);
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index 7b4a377..2b4589c 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -27,7 +27,7 @@
 
 class Simulator {
  public:
-  static const size_t kSimulatorStackUnderflowSize = 64;
+  static const uword kSimulatorStackUnderflowSize = 64;
 
   Simulator();
   ~Simulator();
@@ -52,9 +52,8 @@
   void set_dregister(DRegister reg, double value);
   double get_dregister(DRegister reg) const;
 
-  // Accessor to the internal simulator stack area.
-  uintptr_t StackTop() const;
-  uintptr_t StackLimit() const;
+  // Accessor to the internal simulator stack top.
+  uword StackTop() const;
 
   // Executes ARM instructions until the PC reaches end_sim_pc.
   void Execute();
@@ -79,7 +78,7 @@
                                uword new_value);
 
   // Runtime call support.
-  static uword RedirectExternalReference(void* function,
+  static uword RedirectExternalReference(uword function,
                                          uint32_t argument_count);
 
   void Longjmp(int32_t pc, int32_t sp, int32_t fp, const Instance& object);
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 56d73eb..39f92ce 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -17,7 +17,15 @@
 namespace dart {
 
 Simulator::Simulator() {
-  UNIMPLEMENTED();
+  // Setup simulator support first. Some of this information is needed to
+  // setup the architecture state.
+  // We allocate the stack here, the size is computed as the sum of
+  // the size specified by the user and the buffer space needed for
+  // handling stack overflow exceptions. To be safe in potential
+  // stack underflows we also add some underflow buffer space.
+  stack_ = new char[(Isolate::GetSpecifiedStackSize() +
+                     Isolate::kStackSizeBuffer +
+                     kSimulatorStackUnderflowSize)];
 }
 
 
@@ -40,6 +48,31 @@
 }
 
 
+// Sets the register in the architecture state. It will also deal with updating
+// Simulator internal state for special registers such as PC.
+void Simulator::set_register(Register reg, int32_t value) {
+  UNIMPLEMENTED();
+}
+
+
+// Get the register from the architecture state. This function does handle
+// the special case of accessing the PC register.
+int32_t Simulator::get_register(Register reg) const {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Returns the top of the stack area to enable checking for stack pointer
+// validity.
+uword Simulator::StackTop() const {
+  // To be safe in potential stack underflows we leave some buffer above and
+  // set the stack top.
+  return reinterpret_cast<uword>(stack_) +
+      (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer);
+}
+
+
 void Simulator::InitOnce() {
 }
 
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index b852ebb..cd8df77 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -16,10 +16,14 @@
 #error Do not include simulator_mips.h directly; use simulator.h.
 #endif
 
+#include "vm/constants_mips.h"
+
 namespace dart {
 
 class Simulator {
  public:
+  static const uword kSimulatorStackUnderflowSize = 64;
+
   Simulator();
   ~Simulator();
 
@@ -27,6 +31,13 @@
   // current isolate
   static Simulator* Current();
 
+  // Accessors for register state.
+  void set_register(Register reg, int32_t value);
+  int32_t get_register(Register reg) const;
+
+  // Accessor to the internal simulator stack top.
+  uword StackTop() const;
+
   // Call on program start.
   static void InitOnce();
 
@@ -39,6 +50,9 @@
                int32_t parameter2,
                int32_t parameter3,
                int32_t parameter4);
+
+ private:
+  char* stack_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 70941d9..b729606 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -578,6 +578,36 @@
 }
 
 
+RawFloat32x4* SnapshotReader::NewFloat32x4(float v0, float v1, float v2,
+                                           float v3) {
+  ASSERT(kind_ == Snapshot::kFull);
+  ASSERT(isolate()->no_gc_scope_depth() != 0);
+  cls_ = object_store()->float32x4_class();
+  RawFloat32x4* obj = reinterpret_cast<RawFloat32x4*>(
+      AllocateUninitialized(cls_, Float32x4::InstanceSize()));
+  obj->ptr()->value_[0] = v0;
+  obj->ptr()->value_[1] = v1;
+  obj->ptr()->value_[2] = v2;
+  obj->ptr()->value_[3] = v3;
+  return obj;
+}
+
+
+RawUint32x4* SnapshotReader::NewUint32x4(uint32_t v0, uint32_t v1, uint32_t v2,
+                                         uint32_t v3) {
+  ASSERT(kind_ == Snapshot::kFull);
+  ASSERT(isolate()->no_gc_scope_depth() != 0);
+  cls_ = object_store()->uint32x4_class();
+  RawUint32x4* obj = reinterpret_cast<RawUint32x4*>(
+      AllocateUninitialized(cls_, Uint32x4::InstanceSize()));
+  obj->ptr()->value_[0] = v0;
+  obj->ptr()->value_[1] = v1;
+  obj->ptr()->value_[2] = v2;
+  obj->ptr()->value_[3] = v3;
+  return obj;
+}
+
+
 RawApiError* SnapshotReader::NewApiError() {
   ALLOC_NEW_OBJECT(ApiError, Object::api_error_class());
 }
@@ -601,6 +631,11 @@
 }
 
 
+RawStacktrace* SnapshotReader::NewStacktrace() {
+  ALLOC_NEW_OBJECT(Stacktrace, object_store()->stacktrace_class());
+}
+
+
 RawClass* SnapshotReader::LookupInternalClass(intptr_t class_header) {
   // If the header is an object Id, lookup singleton VM classes or classes
   // stored in the object store.
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 616235d..be21112 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -42,6 +42,8 @@
 class RawRedirectionData;
 class RawFunction;
 class RawGrowableObjectArray;
+class RawFloat32x4;
+class RawUint32x4;
 class RawImmutableArray;
 class RawLanguageError;
 class RawLibrary;
@@ -54,6 +56,7 @@
 class RawPatchClass;
 class RawScript;
 class RawSmi;
+class RawStacktrace;
 class RawTokenStream;
 class RawType;
 class RawTypeParameter;
@@ -263,9 +266,12 @@
   RawScript* NewScript();
   RawLiteralToken* NewLiteralToken();
   RawGrowableObjectArray* NewGrowableObjectArray();
+  RawFloat32x4* NewFloat32x4(float v0, float v1, float v2, float v3);
+  RawUint32x4* NewUint32x4(uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3);
   RawApiError* NewApiError();
   RawLanguageError* NewLanguageError();
   RawObject* NewInteger(int64_t value);
+  RawStacktrace* NewStacktrace();
 
  private:
   class BackRefNode : public ZoneAllocated {
@@ -340,6 +346,7 @@
   friend class LiteralToken;
   friend class PatchClass;
   friend class Script;
+  friend class Stacktrace;
   friend class TokenStream;
   friend class Type;
   friend class TypeArguments;
diff --git a/runtime/vm/snapshot_test.dart b/runtime/vm/snapshot_test.dart
index b42d771..9742c38 100644
--- a/runtime/vm/snapshot_test.dart
+++ b/runtime/vm/snapshot_test.dart
@@ -104,8 +104,8 @@
 class Towers {
   List<TowersDisk> piles;
   int movesDone;
-  Towers(int disks) 
-      : piles = new List<TowersDisk>.fixedLength(3), movesDone = 0 {
+  Towers(int disks)
+      : piles = new List<TowersDisk>(3), movesDone = 0 {
     build(0, disks);
   }
 
@@ -178,7 +178,7 @@
 
   static int sieve(int size) {
     int primeCount = 0;
-    List<bool> flags = new List<bool>.fixedLength(size + 1);
+    List<bool> flags = new List<bool>(size + 1);
     for (int i = 1; i < size; i++) flags[i] = true;
     for (int i = 2; i < size; i++) {
       if (flags[i]) {
@@ -236,7 +236,7 @@
 
   int permute(int size) {
     permuteCount = 0;
-    List<int> list = new List<int>.fixedLength(size);
+    List<int> list = new List<int>(size);
     for (int i = 1; i < size; i++) list[i] = i - 1;
     doPermute(size - 1, list);
     return permuteCount;
@@ -299,10 +299,10 @@
   }
 
   static void queens() {
-    List<bool> a = new List<bool>.fixedLength(9);
-    List<bool> b = new List<bool>.fixedLength(17);
-    List<bool> c = new List<bool>.fixedLength(15);
-    List<int> x = new List<int>.fixedLength(9);
+    List<bool> a = new List<bool>(9);
+    List<bool> b = new List<bool>(17);
+    List<bool> c = new List<bool>(15);
+    List<int> x = new List<int>(9);
     b[1] = false;
     for (int i = -7; i <= 16; i++) {
       if ((i >= 1) && (i <= 8)) a[i] = true;
@@ -408,7 +408,7 @@
 
   SortData(int length) {
     Random r = new Random();
-    list = new List<int>.fixedLength(length);
+    list = new List<int>(length);
     for (int i = 0; i < length; i++) list[i] = r.random();
 
     int min, max;
@@ -829,7 +829,7 @@
     text += text;
     CharAtBenchmark.test(text, ITERATE3);
     NumberBenchmark.test(text, ITERATE3);
-    CharCodeAtBenchmark.test(text, ITERATE3);
+    CodeUnitAtBenchmark.test(text, ITERATE3);
     IndexOfBenchmark.test(text, ITERATE3);
     LastIndexOfBenchmark.test(text, ITERATE3);
     SliceBenchmark.test(text, ITERATE4);
@@ -918,17 +918,17 @@
 }
 
 
-class CharCodeAtBenchmark {
-  CharCodeAtBenchmark() {}
+class CodeUnitAtBenchmark {
+  CodeUnitAtBenchmark() {}
 
   static String test(String input, var iterations) {
     var str;
     for (var j = 0; j < iterations; j++) {
-      str = input.charCodeAt(0);
-      str = input.charCodeAt(input.length - 1);
-      str = input.charCodeAt(150); //set it to 15000
-      str = input.charCodeAt(100); //set it to 10000
-      str = input.charCodeAt(50); //set it to 5000
+      str = input.codeUnitAt(0);
+      str = input.codeUnitAt(input.length - 1);
+      str = input.codeUnitAt(150); //set it to 15000
+      str = input.codeUnitAt(100); //set it to 10000
+      str = input.codeUnitAt(50); //set it to 5000
     }
     return str;
   }
@@ -1319,7 +1319,7 @@
     List local_list1 = ["Hello", "World", "Hello", 0xffffffffff];
     List local_list2 = [null, local_list1, local_list1 ];
     List local_list3 = [local_list2, 2.0, true, false, 0xffffffffff];
-    List sendObject = new List.fixedLength(5);
+    List sendObject = new List(5);
     sendObject[0] = local_list1;
     sendObject[1] = sendObject;
     sendObject[2] = local_list2;
@@ -1443,7 +1443,7 @@
 
   MandelbrotState() {
     _result = new List<List<int>>(N);
-    _lineProcessedBy = new List<LineProcessorClient>.fixedLength(N);
+    _lineProcessedBy = new List<LineProcessorClient>(N);
     _sent = 0;
     _missing = N;
     _validated = new Completer<bool>();
@@ -1523,7 +1523,7 @@
 List<int> processLine(int y) {
   double inverseN = 2.0 / N;
   double Civ = y * inverseN - 1.0;
-  List<int> result = new List<int>.fixedLength(N);
+  List<int> result = new List<int>(N);
   for (int x = 0; x < N; x++) {
     double Crv = x * inverseN - 1.5;
 
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index ca20583..f0fdd3e 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -20,7 +20,8 @@
 
 bool StackFrame::IsStubFrame() const {
   ASSERT(!(IsEntryFrame() || IsExitFrame()));
-  uword saved_pc = *(reinterpret_cast<uword*>(fp() - kWordSize));
+  uword saved_pc =
+      *(reinterpret_cast<uword*>(fp() + EntrypointMarkerOffsetFromFp()));
   return (saved_pc == 0);
 }
 
@@ -138,7 +139,8 @@
   // a GC as we are handling raw object references here. It is possible
   // that the code is called while a GC is in progress, that is ok.
   NoGCScope no_gc;
-  uword saved_pc = *(reinterpret_cast<uword*>(fp() - kWordSize));
+  uword saved_pc =
+      *(reinterpret_cast<uword*>(fp() + EntrypointMarkerOffsetFromFp()));
   if (saved_pc != 0) {
     uword entry_point =
         (saved_pc - AssemblerMacros::kOffsetOfSavedPCfromEntrypoint);
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 483f212..5e5290d 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -34,7 +34,7 @@
 
   void SetEntrypointMarker(uword value) {
     ASSERT(!(IsStubFrame() || IsEntryFrame() || IsExitFrame()));
-    *reinterpret_cast<uword*>(fp_ - kWordSize) = value;
+    *reinterpret_cast<uword*>(fp_ + EntrypointMarkerOffsetFromFp()) = value;
   }
 
   // Visit objects in the frame.
@@ -73,6 +73,7 @@
 
   // Target specific implementations for locating pc and caller fp/sp values.
   static intptr_t PcAddressOffsetFromSp();
+  static intptr_t EntrypointMarkerOffsetFromFp();
   uword GetCallerSp() const;
   uword GetCallerFp() const;
 
diff --git a/runtime/vm/stack_frame_arm.cc b/runtime/vm/stack_frame_arm.cc
index 8d4ee28..e3ea537 100644
--- a/runtime/vm/stack_frame_arm.cc
+++ b/runtime/vm/stack_frame_arm.cc
@@ -5,47 +5,63 @@
 #include "vm/globals.h"
 #if defined(TARGET_ARCH_ARM)
 
+#include "vm/instructions.h"
+#include "vm/isolate.h"
 #include "vm/stack_frame.h"
 
 namespace dart {
 
+// The constant kExitLinkOffsetInEntryFrame must be kept in sync with the
+// code in the InvokeDartCode stub.
+static const int kSavedContextOffsetInEntryFrame = -10 * kWordSize;
+static const int kExitLinkOffsetInEntryFrame = -9 * kWordSize;
+static const int kPcAddressOffsetFromSp = -2 * kWordSize;
+static const int kEntrypointMarkerOffsetFromFp = 2 * kWordSize;
+static const int kSpOffsetFromPreviousFp = 3 * kWordSize;
+
+
 intptr_t StackFrame::PcAddressOffsetFromSp() {
-  UNIMPLEMENTED();
-  return 0;
+  return kPcAddressOffsetFromSp;
 }
 
 
-uword StackFrame::GetCallerFp() const {
-  UNIMPLEMENTED();
-  return 0;
+intptr_t StackFrame::EntrypointMarkerOffsetFromFp() {
+  return kEntrypointMarkerOffsetFromFp;
 }
 
 
 uword StackFrame::GetCallerSp() const {
-  UNIMPLEMENTED();
-  return 0;
+  return fp() + kSpOffsetFromPreviousFp;
+}
+
+
+uword StackFrame::GetCallerFp() const {
+  return *(reinterpret_cast<uword*>(fp()));
 }
 
 
 intptr_t EntryFrame::ExitLinkOffset() const {
-  UNIMPLEMENTED();
-  return 0;
+  return kExitLinkOffsetInEntryFrame;
 }
 
 
 intptr_t EntryFrame::SavedContextOffset() const {
-  UNIMPLEMENTED();
-  return 0;
+  return kSavedContextOffsetInEntryFrame;
 }
 
 
 void StackFrameIterator::SetupLastExitFrameData() {
-  UNIMPLEMENTED();
+  Isolate* current = Isolate::Current();
+  uword exit_marker = current->top_exit_frame_info();
+  frames_.fp_ = exit_marker;
 }
 
 
 void StackFrameIterator::SetupNextExitFrameData() {
-  UNIMPLEMENTED();
+  uword exit_address = entry_.fp() + kExitLinkOffsetInEntryFrame;
+  uword exit_marker = *reinterpret_cast<uword*>(exit_address);
+  frames_.fp_ = exit_marker;
+  frames_.sp_ = 0;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/stack_frame_ia32.cc b/runtime/vm/stack_frame_ia32.cc
index b3f554e..ae4de47 100644
--- a/runtime/vm/stack_frame_ia32.cc
+++ b/runtime/vm/stack_frame_ia32.cc
@@ -16,6 +16,7 @@
 static const int kSavedContextOffsetInEntryFrame = -5 * kWordSize;
 static const int kExitLinkOffsetInEntryFrame = -4 * kWordSize;
 static const int kPcAddressOffsetFromSp = -1 * kWordSize;
+static const int kEntrypointMarkerOffsetFromFp = -1 * kWordSize;
 static const int kSpOffsetFromPreviousFp = 2 * kWordSize;
 
 
@@ -24,6 +25,11 @@
 }
 
 
+intptr_t StackFrame::EntrypointMarkerOffsetFromFp() {
+  return kEntrypointMarkerOffsetFromFp;
+}
+
+
 uword StackFrame::GetCallerSp() const {
   return fp() + kSpOffsetFromPreviousFp;
 }
diff --git a/runtime/vm/stack_frame_mips.cc b/runtime/vm/stack_frame_mips.cc
index eb79f18..b15de57 100644
--- a/runtime/vm/stack_frame_mips.cc
+++ b/runtime/vm/stack_frame_mips.cc
@@ -15,6 +15,12 @@
 }
 
 
+intptr_t StackFrame::EntrypointMarkerOffsetFromFp() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
 uword StackFrame::GetCallerFp() const {
   UNIMPLEMENTED();
   return 0;
diff --git a/runtime/vm/stack_frame_x64.cc b/runtime/vm/stack_frame_x64.cc
index d0ae422..64ff644 100644
--- a/runtime/vm/stack_frame_x64.cc
+++ b/runtime/vm/stack_frame_x64.cc
@@ -16,6 +16,7 @@
 static const int kSavedContextOffsetInEntryFrame = -9 * kWordSize;
 static const int kExitLinkOffsetInEntryFrame = -8 * kWordSize;
 static const int kPcAddressOffsetFromSp = -1 * kWordSize;
+static const int kEntrypointMarkerOffsetFromFp = -1 * kWordSize;
 static const int kSpOffsetFromPreviousFp = 2 * kWordSize;
 
 
@@ -24,6 +25,11 @@
 }
 
 
+intptr_t StackFrame::EntrypointMarkerOffsetFromFp() {
+  return kEntrypointMarkerOffsetFromFp;
+}
+
+
 uword StackFrame::GetCallerSp() const {
   return fp() + kSpOffsetFromPreviousFp;
 }
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 50c189b..32ea56f 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -5,14 +5,127 @@
 #include "vm/globals.h"
 #if defined(TARGET_ARCH_ARM)
 
+#include "vm/assembler.h"
+#include "vm/assembler_macros.h"
+#include "vm/code_generator.h"
+#include "vm/dart_entry.h"
+#include "vm/instructions.h"
+#include "vm/stack_frame.h"
 #include "vm/stub_code.h"
 
 #define __ assembler->
 
 namespace dart {
 
+// Input parameters:
+//   LR : return address.
+//   SP : address of last argument in argument array.
+//   SP + 4*R4 - 4 : address of first argument in argument array.
+//   SP + 4*R4 : address of return value.
+//   R5 : address of the runtime function to call.
+//   R4 : number of arguments to the call.
 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
-  __ Unimplemented("CallToRuntime stub");
+  const intptr_t isolate_offset = NativeArguments::isolate_offset();
+  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = NativeArguments::argv_offset();
+  const intptr_t retval_offset = NativeArguments::retval_offset();
+  __ EnterFrame((1 << FP) | (1 << LR), 0);
+
+  // Load current Isolate pointer from Context structure into R0.
+  __ ldr(R0, FieldAddress(CTX, Context::isolate_offset()));
+
+  // Save exit frame information to enable stack walking as we are about
+  // to transition to Dart VM C++ code.
+  {
+    // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+    // restriction on the offset.
+    const intptr_t offset = Isolate::top_exit_frame_info_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(IP, R0, offset12_hi);
+    __ str(SP, Address(IP, offset12_lo));
+  }
+
+  // Save current Context pointer into Isolate structure.
+  {
+    // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+    // restriction on the offset.
+    const intptr_t offset = Isolate::top_context_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(IP, R0, offset12_hi);
+    __ str(CTX, Address(IP, offset12_lo));
+  }
+
+  // Cache Isolate pointer into CTX while executing runtime code.
+  __ mov(CTX, ShifterOperand(R0));
+
+  // Reserve space for arguments and align frame before entering C++ world.
+  // NativeArguments are passed in registers.
+  ASSERT(sizeof(NativeArguments) == 4 * kWordSize);
+  __ ReserveAlignedFrameSpace(0);
+
+  // Pass NativeArguments structure by value and call runtime.
+  // Registers R0, R1, R2, and R3 are used.
+
+  ASSERT(isolate_offset == 0 * kWordSize);
+  __ mov(R0, ShifterOperand(CTX));  // Set isolate in NativeArgs.
+
+  // There are no runtime calls to closures, so we do not need to set the tag
+  // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
+  ASSERT(argc_tag_offset == 1 * kWordSize);
+  __ mov(R1, ShifterOperand(R4));  // Set argc in NativeArguments.
+
+  ASSERT(argv_offset == 2 * kWordSize);
+  __ add(R2, FP, ShifterOperand(R4, LSL, 2));  // Compute argv.
+  __ AddImmediate(R2, kWordSize);  // Set argv in NativeArguments.
+
+  ASSERT(retval_offset == 3 * kWordSize);
+  __ add(R3, R2, ShifterOperand(kWordSize));  // Retval is next to 1st argument.
+
+  // Call runtime or redirection via simulator.
+  __ blx(R5);
+
+  // Reset exit frame information in Isolate structure.
+  __ LoadImmediate(R2, 0);
+  {
+    // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+    // restriction on the offset.
+    const intptr_t offset = Isolate::top_exit_frame_info_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(IP, CTX, offset12_hi);
+    __ str(R2, Address(IP, offset12_lo));
+  }
+
+  // Load Context pointer from Isolate structure into R2.
+  {
+    // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+    // restriction on the offset.
+    const intptr_t offset = Isolate::top_context_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(IP, CTX, offset12_hi);
+    __ ldr(R2, Address(IP, offset12_lo));
+  }
+
+  // Reset Context pointer in Isolate structure.
+  __ LoadImmediate(R3, reinterpret_cast<intptr_t>(Object::null()));
+  {
+    // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+    // restriction on the offset.
+    const intptr_t offset = Isolate::top_context_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(IP, CTX, offset12_hi);
+    __ str(R3, Address(IP, offset12_lo));
+  }
+
+  // Cache Context pointer into CTX while executing Dart code.
+  __ mov(CTX, ShifterOperand(R2));
+
+  __ LeaveFrame((1 << FP) | (1 << LR));
+  __ Ret();
 }
 
 
@@ -26,8 +139,22 @@
 }
 
 
+// Input parameters:
+//   R4: arguments descriptor array.
 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
-  __ Unimplemented("CallStaticFunction stub");
+  AssemblerMacros::EnterStubFrame(assembler);
+  // Setup space on stack for return value and preserve arguments descriptor.
+  __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+  __ PushList((1 << R0) | (1 << R4));
+  __ CallRuntime(kPatchStaticCallRuntimeEntry);
+  // Get Code object result and restore arguments descriptor array.
+  __ PopList((1 << R0) | (1 << R4));
+  // Remove the stub frame as we are about to jump to the dart function.
+  AssemblerMacros::LeaveStubFrame(assembler);
+
+  __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
+  __ AddImmediate(R0, R0, Instructions::HeaderSize() - kHeapObjectTag);
+  __ bx(R0);
 }
 
 
@@ -66,8 +193,134 @@
 }
 
 
+// Called when invoking Dart code from C++ (VM code).
+// Input parameters:
+//   LR : points to return address.
+//   R0 : entrypoint of the Dart function to call.
+//   R1 : arguments descriptor array.
+//   R2 : arguments array.
+//   R3 : new context containing the current isolate pointer.
 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
-  __ Unimplemented("InvokeDartCode stub");
+  // Save frame pointer coming in.
+  AssemblerMacros::EnterStubFrame(assembler);
+
+  // Save new context and C++ ABI callee-saved registers.
+  const intptr_t kNewContextOffset =
+      -(1 + kAbiPreservedCpuRegCount) * kWordSize;
+  __ PushList((1 << R3) | kAbiPreservedCpuRegs);
+
+  // The new Context structure contains a pointer to the current Isolate
+  // structure. Cache the Context pointer in the CTX register so that it is
+  // available in generated code and calls to Isolate::Current() need not be
+  // done. The assumption is that this register will never be clobbered by
+  // compiled or runtime stub code.
+
+  // Cache the new Context pointer into CTX while executing Dart code.
+  __ ldr(CTX, Address(R3, VMHandles::kOffsetOfRawPtrInHandle));
+
+  // Load Isolate pointer from Context structure into temporary register R8.
+  __ ldr(R8, FieldAddress(CTX, Context::isolate_offset()));
+
+  // Save the top exit frame info. Use R5 as a temporary register.
+  // StackFrameIterator reads the top exit frame info saved in this frame.
+  {
+    // TODO(regis): Add assembler macro for {Load,Store}BasedOffset with no
+    // restriction on the offset.
+    const intptr_t offset = Isolate::top_exit_frame_info_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(R7, R8, offset12_hi);
+    __ ldr(R5, Address(R7, offset12_lo));
+    __ LoadImmediate(R6, 0);
+    __ str(R6, Address(R7, offset12_lo));
+  }
+
+  // Save the old Context pointer. Use R4 as a temporary register.
+  // Note that VisitObjectPointers will find this saved Context pointer during
+  // GC marking, since it traverses any information between SP and
+  // FP - kExitLinkOffsetInEntryFrame.
+  // EntryFrame::SavedContext reads the context saved in this frame.
+  {
+    const intptr_t offset = Isolate::top_context_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(R7, R8, offset12_hi);
+    __ ldr(R4, Address(R7, offset12_lo));
+  }
+
+  // The constants kSavedContextOffsetInEntryFrame and
+  // kExitLinkOffsetInEntryFrame must be kept in sync with the code below.
+  __ PushList((1 << R4) | (1 << R5));
+
+  // The stack pointer is restore after the call to this location.
+  const intptr_t kSavedContextOffsetInEntryFrame = -10 * kWordSize;
+
+  // Load arguments descriptor array into R4, which is passed to Dart code.
+  __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle));
+
+  // Load number of arguments into R5.
+  __ ldr(R5, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+  __ SmiUntag(R5);
+
+  // Compute address of 'arguments array' data area into R2.
+  __ ldr(R2, Address(R2, VMHandles::kOffsetOfRawPtrInHandle));
+  __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag);
+
+  // Set up arguments for the Dart call.
+  Label push_arguments;
+  Label done_push_arguments;
+  __ CompareImmediate(R5, 0);  // check if there are arguments.
+  __ b(&done_push_arguments, EQ);
+  __ LoadImmediate(R1, 0);
+  __ Bind(&push_arguments);
+  __ ldr(R3, Address(R2));
+  __ Push(R3);
+  __ AddImmediate(R2, kWordSize);
+  __ AddImmediate(R1, 1);
+  __ cmp(R1, ShifterOperand(R5));
+  __ b(&push_arguments, LT);
+  __ Bind(&done_push_arguments);
+
+  // Call the Dart code entrypoint.
+  __ blx(R0);  // R4 is the arguments descriptor array.
+
+  // Read the saved new Context pointer.
+  __ ldr(CTX, Address(FP, kNewContextOffset));
+  __ ldr(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle));
+
+  // Get rid of arguments pushed on the stack.
+  __ AddImmediate(SP, FP, kSavedContextOffsetInEntryFrame);
+
+  // Load Isolate pointer from Context structure into CTX. Drop Context.
+  __ ldr(CTX, FieldAddress(CTX, Context::isolate_offset()));
+
+  // Restore the saved Context pointer into the Isolate structure.
+  // Uses R4 as a temporary register for this.
+  // Restore the saved top exit frame info back into the Isolate structure.
+  // Uses R5 as a temporary register for this.
+  __ PopList((1 << R4) | (1 << R5));
+  {
+    const intptr_t offset = Isolate::top_context_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(R7, CTX, offset12_hi);
+    __ str(R4, Address(R7, offset12_lo));
+  }
+  {
+    const intptr_t offset = Isolate::top_exit_frame_info_offset();
+    const int32_t offset12_hi = offset & ~kOffset12Mask;  // signed
+    const uint32_t offset12_lo = offset & kOffset12Mask;  // unsigned
+    __ AddImmediate(R7, CTX, offset12_hi);
+    __ str(R5, Address(R7, offset12_lo));
+  }
+
+  // Restore C++ ABI callee-saved registers.
+  __ PopList((1 << R3) | kAbiPreservedCpuRegs);  // Ignore restored R3.
+
+  // Restore the frame pointer.
+  AssemblerMacros::LeaveStubFrame(assembler);
+
+  __ Ret();
 }
 
 
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index a1893b1..67a15c9 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -55,7 +55,7 @@
       *CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
   const Function& function = RegisterFakeFunction(kName, code);
   Smi& result = Smi::Handle();
-  result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
   EXPECT_EQ((value1 - value2), result.Value());
 }
 
@@ -80,7 +80,7 @@
       *CreateFunction("Test_CallLeafRuntimeStubCode"), &_assembler_));
   const Function& function = RegisterFakeFunction(kName, code);
   Smi& result = Smi::Handle();
-  result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
   EXPECT_EQ((value1 + value2), result.Value());
 }
 
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 387a52d..f844588 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -679,28 +679,25 @@
   AssemblerMacros::EnterStubFrame(assembler);
 
   __ pushl(raw_null);  // Setup space on stack for result from error reporting.
-  __ pushl(EDI);  // Non-closure object.
   __ pushl(EDX);  // Arguments descriptor.
   // Load smi-tagged arguments array length, including the non-closure.
   __ movl(EDX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  // See stack layout below explaining "wordSize * 6" offset.
-  PushArgumentsArray(assembler, (kWordSize * 6));
+  // See stack layout below explaining "wordSize * 5" offset.
+  PushArgumentsArray(assembler, (kWordSize * 5));
 
   // Stack:
   // TOS + 0: Argument array.
   // TOS + 1: Arguments descriptor array.
-  // TOS + 2: Non-closure object.
-  // TOS + 3: Place for result from the call.
-  // TOS + 4: PC marker => RawInstruction object.
-  // TOS + 5: Saved EBP of previous frame. <== EBP
-  // TOS + 6: Dart code return address
-  // TOS + 7: Last argument of caller.
+  // TOS + 2: Place for result from the call.
+  // TOS + 3: PC marker => RawInstruction object.
+  // TOS + 4: Saved EBP of previous frame. <== EBP
+  // TOS + 5: Dart code return address
+  // TOS + 6: Last argument of caller.
   // ....
   __ CallRuntime(kInvokeNonClosureRuntimeEntry);
   // Remove arguments.
   __ popl(EAX);
   __ popl(EAX);
-  __ popl(EAX);
   __ popl(EAX);  // Get result into EAX.
 
   // Remove the stub frame as we are about to return.
diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc
index 222fd0f..6e43487 100644
--- a/runtime/vm/stub_code_ia32_test.cc
+++ b/runtime/vm/stub_code_ia32_test.cc
@@ -71,7 +71,7 @@
       *CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
   const Function& function = RegisterFakeFunction(kName, code);
   Smi& result = Smi::Handle();
-  result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
   EXPECT_EQ((value1 - value2), result.Value());
 }
 
@@ -106,7 +106,7 @@
       *CreateFunction("Test_CallLeafRuntimeStubCode"), &_assembler_));
   const Function& function = RegisterFakeFunction(kName, code);
   Smi& result = Smi::Handle();
-  result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
   EXPECT_EQ((value1 + value2), result.Value());
 }
 
diff --git a/runtime/vm/stub_code_mips_test.cc b/runtime/vm/stub_code_mips_test.cc
index 7181fda..df573cb 100644
--- a/runtime/vm/stub_code_mips_test.cc
+++ b/runtime/vm/stub_code_mips_test.cc
@@ -55,7 +55,7 @@
       *CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
   const Function& function = RegisterFakeFunction(kName, code);
   Smi& result = Smi::Handle();
-  result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
   EXPECT_EQ((value1 - value2), result.Value());
 }
 
@@ -80,7 +80,7 @@
       *CreateFunction("Test_CallLeafRuntimeStubCode"), &_assembler_));
   const Function& function = RegisterFakeFunction(kName, code);
   Smi& result = Smi::Handle();
-  result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
   EXPECT_EQ((value1 + value2), result.Value());
 }
 
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index de2b1de..703a058 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -668,28 +668,25 @@
   AssemblerMacros::EnterStubFrame(assembler);
 
   __ pushq(raw_null);  // Setup space on stack for result from call.
-  __ pushq(R13);  // Non-closure object.
   __ pushq(R10);  // Arguments descriptor.
   // Load smi-tagged arguments array length, including the non-closure.
   __ movq(R10, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  // See stack layout below explaining "wordSize * 6" offset.
-  PushArgumentsArray(assembler, (kWordSize * 6));
+  // See stack layout below explaining "wordSize * 5" offset.
+  PushArgumentsArray(assembler, (kWordSize * 5));
 
   // Stack:
   // TOS + 0: Argument array.
   // TOS + 1: Arguments descriptor array.
-  // TOS + 2: Non-closure object.
-  // TOS + 3: Place for result from the call.
-  // TOS + 4: PC marker => RawInstruction object.
-  // TOS + 5: Saved RBP of previous frame. <== RBP
-  // TOS + 6: Dart code return address
-  // TOS + 7: Last argument of caller.
+  // TOS + 2: Place for result from the call.
+  // TOS + 3: PC marker => RawInstruction object.
+  // TOS + 4: Saved RBP of previous frame. <== RBP
+  // TOS + 5: Dart code return address
+  // TOS + 6: Last argument of caller.
   // ....
   __ CallRuntime(kInvokeNonClosureRuntimeEntry);
   // Remove arguments.
   __ popq(RAX);
   __ popq(RAX);
-  __ popq(RAX);
   __ popq(RAX);  // Get result into RAX.
 
   // Remove the stub frame as we are about to return.
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index 20a7d7a..b73a0b4 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -71,7 +71,7 @@
       *CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
   const Function& function = RegisterFakeFunction(kName, code);
   Smi& result = Smi::Handle();
-  result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
   EXPECT_EQ((value1 - value2), result.Value());
 }
 
@@ -104,7 +104,7 @@
       *CreateFunction("Test_CallLeafRuntimeStubCode"), &_assembler_));
   const Function& function = RegisterFakeFunction(kName, code);
   Smi& result = Smi::Handle();
-  result ^= DartEntry::InvokeStatic(function, Object::empty_array());
+  result ^= DartEntry::InvokeFunction(function, Object::empty_array());
   EXPECT_EQ((value1 + value2), result.Value());
 }
 
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index ee82911..afac4a3 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -44,7 +44,6 @@
   V(List, "List")                                                              \
   V(ListLiteralFactory, "List._fromLiteral")                                   \
   V(ListFactory, "List.")                                                      \
-  V(ListFixedLengthFactory, "List.fixedLength")                                \
   V(Map, "Map")                                                                \
   V(MapLiteralFactory, "Map._fromLiteral")                                     \
   V(ImmutableMap, "ImmutableMap")                                              \
@@ -111,17 +110,24 @@
   V(_Double, "_Double")                                                        \
   V(Bool, "bool")                                                              \
   V(ObjectArray, "_ObjectArray")                                               \
+  V(ObjectArrayDot, "_ObjectArray.")                                           \
   V(GrowableObjectArray, "_GrowableObjectArray")                               \
+  V(GrowableObjectArrayDot, "_GrowableObjectArray.")                           \
+  V(GrowableObjectArrayWithData, "_GrowableObjectArray.withData")              \
   V(ImmutableArray, "_ImmutableArray")                                         \
   V(OneByteString, "_OneByteString")                                           \
   V(TwoByteString, "_TwoByteString")                                           \
   V(ExternalOneByteString, "_ExternalOneByteString")                           \
   V(ExternalTwoByteString, "_ExternalTwoByteString")                           \
-  V(Stacktrace, "Stacktrace")                                                  \
+  V(StackTrace, "StackTrace")                                                  \
   V(JSSyntaxRegExp, "_JSSyntaxRegExp")                                         \
   V(Object, "Object")                                                          \
   V(Int, "int")                                                                \
   V(Double, "double")                                                          \
+  V(_Float32x4, "_Float32x4")                                                  \
+  V(_Uint32x4, "_Uint32x4")                                                    \
+  V(Float32x4, "Float32x4")                                                    \
+  V(Uint32x4, "Uint32x4")                                                      \
   V(Int8List, "Int8List")                                                      \
   V(Uint8List, "Uint8List")                                                    \
   V(Uint8ClampedList, "Uint8ClampedList")                                      \
@@ -131,6 +137,7 @@
   V(Uint32List, "Uint32List")                                                  \
   V(Int64List, "Int64List")                                                    \
   V(Uint64List, "Uint64List")                                                  \
+  V(Float32x4List, "Float32x4List")                                            \
   V(Float32List, "Float32List")                                                \
   V(Float64List, "Float64List")                                                \
   V(_Int8Array, "_Int8Array")                                                  \
@@ -142,6 +149,7 @@
   V(_Uint32Array, "_Uint32Array")                                              \
   V(_Int64Array, "_Int64Array")                                                \
   V(_Uint64Array, "_Uint64Array")                                              \
+  V(_Float32x4Array, "_Float32x4Array")                                        \
   V(_Float32Array, "_Float32Array")                                            \
   V(_Float64Array, "_Float64Array")                                            \
   V(_ExternalInt8Array, "_ExternalInt8Array")                                  \
@@ -153,6 +161,7 @@
   V(_ExternalUint32Array, "_ExternalUint32Array")                              \
   V(_ExternalInt64Array, "_ExternalInt64Array")                                \
   V(_ExternalUint64Array, "_ExternalUint64Array")                              \
+  V(_ExternalFloat32x4Array, "_ExternalFloat32x4Array")                        \
   V(_ExternalFloat32Array, "_ExternalFloat32Array")                            \
   V(_ExternalFloat64Array, "_ExternalFloat64Array")                            \
   V(_WeakProperty, "_WeakProperty")                                            \
@@ -174,9 +183,9 @@
   V(OutOfMemoryError, "OutOfMemoryError")                                      \
   V(InternalError, "InternalError")                                            \
   V(NullThrownError, "NullThrownError")                                        \
-  V(IllegalJSRegExpException, "IllegalJSRegExpException")                      \
   V(IsolateSpawnException, "IsolateSpawnException")                            \
   V(IsolateUnhandledException, "IsolateUnhandledException")                    \
+  V(_setupFullStackTrace, "_setupFullStackTrace")                              \
   V(BooleanExpression, "boolean expression")                                   \
   V(Malformed, "malformed")                                                    \
   V(InstanceOf, "InstanceOf")                                                  \
diff --git a/runtime/vm/unicode.h b/runtime/vm/unicode.h
index 993ee9e..3a9b862 100644
--- a/runtime/vm/unicode.h
+++ b/runtime/vm/unicode.h
@@ -79,12 +79,12 @@
                                    int32_t* dst,
                                    intptr_t len);
 
- private:
   static const int32_t kMaxOneByteChar   = 0x7F;
   static const int32_t kMaxTwoByteChar   = 0x7FF;
   static const int32_t kMaxThreeByteChar = 0xFFFF;
   static const int32_t kMaxFourByteChar  = Utf::kMaxCodePoint;
 
+ private:
   static bool IsTrailByte(uint8_t code_unit) {
     return (code_unit & 0xC0) == 0x80;
   }
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 26547cc..308b8ba 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -84,7 +84,7 @@
   }                                                                            \
   static void CodeGenTestRun##name(const Function& function) {                 \
     Object& result = Object::Handle();                                         \
-    result = DartEntry::InvokeStatic(function, Object::empty_array());         \
+    result = DartEntry::InvokeFunction(function, Object::empty_array());       \
     EXPECT(!result.IsError());                                                 \
     Instance& actual = Instance::Handle();                                     \
     actual ^= result.raw();                                                    \
@@ -122,7 +122,7 @@
   }                                                                            \
   static void CodeGenTestRun##name1(const Function& function) {                \
     Object& result = Object::Handle();                                         \
-    result = DartEntry::InvokeStatic(function, Object::empty_array());         \
+    result = DartEntry::InvokeFunction(function, Object::empty_array());       \
     EXPECT(!result.IsError());                                                 \
     Instance& actual = Instance::Handle();                                     \
     actual ^= result.raw();                                                    \
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index ca69ca5..1c1b10f 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -19,6 +19,7 @@
     'isolate_cc_file': '<(SHARED_INTERMEDIATE_DIR)/isolate_gen.cc',
     'isolate_patch_cc_file': '<(SHARED_INTERMEDIATE_DIR)/isolate_patch_gen.cc',
     'json_cc_file': '<(SHARED_INTERMEDIATE_DIR)/json_gen.cc',
+    'json_patch_cc_file': '<(SHARED_INTERMEDIATE_DIR)/json_patch_gen.cc',
     'scalarlist_cc_file': '<(SHARED_INTERMEDIATE_DIR)/scalarlist_gen.cc',
     'scalarlist_patch_cc_file': '<(SHARED_INTERMEDIATE_DIR)/scalarlist_patch_gen.cc',
     'uri_cc_file': '<(SHARED_INTERMEDIATE_DIR)/uri_gen.cc',
@@ -101,6 +102,7 @@
         'generate_isolate_cc_file',
         'generate_isolate_patch_cc_file',
         'generate_json_cc_file',
+        'generate_json_patch_cc_file',
         'generate_mirrors_cc_file',
         'generate_mirrors_patch_cc_file',
         'generate_scalarlist_cc_file',
@@ -131,6 +133,7 @@
         '<(isolate_cc_file)',
         '<(isolate_patch_cc_file)',
         '<(json_cc_file)',
+        '<(json_patch_cc_file)',
         '<(mirrors_cc_file)',
         '<(mirrors_patch_cc_file)',
         '<(scalarlist_cc_file)',
@@ -848,6 +851,44 @@
       ]
     },
     {
+      'target_name': 'generate_json_patch_cc_file',
+      'type': 'none',
+      'includes': [
+        # Load the shared json library sources.
+        '../lib/json_sources.gypi',
+      ],
+      'sources/': [
+        # Exclude all .[cc|h] files.
+        # This is only here for reference. Excludes happen after
+        # variable expansion, so the script has to do its own
+        # exclude processing of the sources being passed.
+        ['exclude', '\\.cc|h$'],
+      ],
+      'actions': [
+        {
+          'action_name': 'generate_json_patch_cc',
+          'inputs': [
+            '../tools/create_string_literal.py',
+            '<(builtin_in_cc_file)',
+            '<@(_sources)',
+          ],
+          'outputs': [
+            '<(json_patch_cc_file)',
+          ],
+          'action': [
+            'python',
+            'tools/create_string_literal.py',
+            '--output', '<(json_patch_cc_file)',
+            '--input_cc', '<(builtin_in_cc_file)',
+            '--include', 'vm/bootstrap.h',
+            '--var_name', 'dart::Bootstrap::json_patch_',
+            '<@(_sources)',
+          ],
+          'message': 'Generating ''<(json_patch_cc_file)'' file.'
+        },
+      ]
+    },
+    {
       'target_name': 'generate_scalarlist_cc_file',
       'type': 'none',
       'variables': {
diff --git a/sdk/lib/collection/arrays.dart b/sdk/lib/_collection_dev/arrays.dart
similarity index 98%
rename from sdk/lib/collection/arrays.dart
rename to sdk/lib/_collection_dev/arrays.dart
index eab2240..f3a7caf 100644
--- a/sdk/lib/collection/arrays.dart
+++ b/sdk/lib/_collection_dev/arrays.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of dart.collection;
+part of dart._collection.dev;
 
 // TODO(ngeoffray): Rename to Lists.
 class Arrays {
diff --git a/sdk/lib/_collection_dev/collection_dev.dart b/sdk/lib/_collection_dev/collection_dev.dart
index 839fd1c..dabbe2b 100644
--- a/sdk/lib/_collection_dev/collection_dev.dart
+++ b/sdk/lib/_collection_dev/collection_dev.dart
@@ -4,6 +4,7 @@
 
 library dart._collection.dev;
 
+part 'arrays.dart';
 part 'iterable.dart';
 part 'list.dart';
 part 'sort.dart';
diff --git a/sdk/lib/_collection_dev/collection_dev_sources.gypi b/sdk/lib/_collection_dev/collection_dev_sources.gypi
index 819f237..4f941b6 100644
--- a/sdk/lib/_collection_dev/collection_dev_sources.gypi
+++ b/sdk/lib/_collection_dev/collection_dev_sources.gypi
@@ -5,6 +5,9 @@
 # This file contains all sources for the dart:collection-dev library.
 {
   'sources': [
+    'collection_dev.dart',
+    # The above file needs to be first as it lists the parts below.
+    'arrays.dart',
     'iterable.dart',
     'list.dart',
     'sort.dart',
diff --git a/sdk/lib/_collection_dev/iterable.dart b/sdk/lib/_collection_dev/iterable.dart
index bf6c85e..daad6af 100644
--- a/sdk/lib/_collection_dev/iterable.dart
+++ b/sdk/lib/_collection_dev/iterable.dart
@@ -14,6 +14,8 @@
   int get length;
   E elementAt(int i);
 
+  const ListIterable();
+
   Iterator<E> get iterator => new ListIterator<E>(this);
 
   void forEach(void action(E element)) {
@@ -26,7 +28,7 @@
     }
   }
 
-  bool get isEmpty => length != 0;
+  bool get isEmpty => length == 0;
 
   E get first {
     if (length == 0) throw new StateError("No elements");
@@ -217,8 +219,13 @@
 
   Iterable<E> takeWhile(bool test(E element)) => super.takeWhile(test);
 
-  List<E> toList() {
-    List<E> result = new List(length);
+  List<E> toList({ bool growable: true }) {
+    List<E> result;
+    if (growable) {
+      result = new List<E>()..length = length;
+    } else {
+      result = new List<E>(length);
+    }
     for (int i = 0; i < length; i++) {
       result[i] = elementAt(i);
     }
@@ -674,7 +681,7 @@
 
   Iterable<E> takeWhile(bool test(E element)) => this;
 
-  List toList() => <E>[];
+  List toList({ bool growable: true }) => growable ? <E>[] : new List<E>(0);
 
   Set toSet() => new Set<E>();
 }
@@ -687,6 +694,6 @@
 }
 
 /** An [Iterator] that can move in both directions. */
-abstract class BiDirectionalIterator<T> implements Iterator<T> {
+abstract class BidirectionalIterator<T> implements Iterator<T> {
   bool movePrevious();
 }
diff --git a/sdk/lib/_collection_dev/list.dart b/sdk/lib/_collection_dev/list.dart
index fe698ec..9685fda 100644
--- a/sdk/lib/_collection_dev/list.dart
+++ b/sdk/lib/_collection_dev/list.dart
@@ -10,104 +10,49 @@
  * Implements all read-only operations, except [:operator[]:] and [:length:],
  * in terms of those two operations.
  */
-abstract class ListBase<E> extends Collection<E> implements List<E> {
-  Iterator<E> get iterator => new ListIterator(this);
+abstract class ListBase<E> extends ListIterable<E> implements List<E> {
+  // List interface.
+  int get length;
+  E operator[](int index);
 
-  void forEach(f(E element)) {
-    for (int i = 0; i < this.length; i++) f(this[i]);
-  }
+  // Collection interface.
+  // Implement in a fully mutable specialized class if necessary.
+  // The fixed-length and unmodifiable lists throw on all members
+  // of the collection interface.
 
-  bool contains(E value) {
-    for (int i = 0; i < length; i++) {
-      if (this[i] == value) return true;
-    }
-    return false;
-  }
-
-  reduce(initialValue, combine(previousValue, E element)) {
-    var value = initialValue;
-    for (int i = 0; i < this.length; i++) {
-      value = combine(value, this[i]);
-    }
-    return value;
-  }
-
-  bool every(bool f(E element)) {
-    for (int i = 0; i < this.length; i++) {
-      if (!f(this[i])) return false;
-    }
-    return true;
-  }
-
-  bool any(bool f(E element)) {
-    for (int i = 0; i < this.length; i++) {
-      if (f(this[i])) return true;
-    }
-    return false;
-  }
-
-  bool get isEmpty {
-    return this.length == 0;
-  }
-
+  // Iterable interface.
   E elementAt(int index) {
     return this[index];
   }
 
-  int indexOf(E value, [int start = 0]) {
-    for (int i = start; i < length; i++) {
-      if (this[i] == value) return i;
-    }
-    return -1;
-  }
-
-  int lastIndexOf(E value, [int start]) {
-    if (start == null) start = length - 1;
-    for (int i = start; i >= 0; i--) {
-      if (this[i] == value) return i;
-    }
-    return -1;
-  }
-
-  E get first {
-    if (length > 0) return this[0];
-    throw new StateError("No elements");
-  }
-
-  E get last {
-    if (length > 0) return this[length - 1];
-    throw new StateError("No elements");
-  }
-
-  E get single {
-    if (length == 1) return this[0];
-    if (length == 0) throw new StateError("No elements");
-    throw new StateError("More than one element");
+  Map<int, E> asMap() {
+    return new ListMapView(this);
   }
 
   List<E> getRange(int start, int length) {
-    List<E> result = <E>[];
+    if (start < 0 || start > this.length) {
+      throw new RangeError.range(start, 0, this.length);
+    }
+    if (length < 0 || start + length > this.length) {
+      throw new RangeError.range(length, 0, this.length - start);
+    }
+    List<E> result = new List<E>(length);
     for (int i = 0; i < length; i++) {
-      result.add(this[start + i]);
+      result[i] = this[start + i];
     }
     return result;
   }
 
-  Iterable map(f(E element)) {
-    return new MappedIterable(this, f);
+  int indexOf(E element, [int start = 0]) {
+    return Arrays.indexOf(this, element, start, this.length);
   }
 
-  Iterable<E> take(int n) {
-    return new SubListIterable(this, 0, n);
-  }
-
-  Iterable<E> skip(int n) {
-    return new SubListIterable(this, n, null);
+  int lastIndexOf(E element, [int start = null]) {
+    if (start == null) start = length - 1;
+    return Arrays.lastIndexOf(this, element, start);
   }
 
   Iterable<E> get reversed => new ReversedListIterable(this);
-
-  String toString() => ToString.collectionToString(this);
 }
 
 /**
@@ -170,6 +115,11 @@
         "Cannot remove from a fixed-length list");
   }
 
+  void retainMatching(bool test(E element)) {
+    throw new UnsupportedError(
+        "Cannot remove from a fixed-length list");
+  }
+
   void clear() {
     throw new UnsupportedError(
         "Cannot clear a fixed-length list");
@@ -246,6 +196,11 @@
         "Cannot remove from an unmodifiable list");
   }
 
+  void retainMatching(bool test(E element)) {
+    throw new UnsupportedError(
+        "Cannot remove from an unmodifiable list");
+  }
+
   void sort([Comparator<E> compare]) {
     throw new UnsupportedError(
         "Cannot modify an unmodifiable list");
@@ -301,3 +256,70 @@
 
   E elementAt(int index) => _source.elementAt(_source.length - 1 - index);
 }
+
+/**
+ * An [Iterable] of the UTF-16 code units of a [String] in index order.
+ */
+class CodeUnits extends UnmodifiableListBase<int> {
+  /** The string that this is the code units of. */
+  String _string;
+
+  CodeUnits(this._string);
+
+  int get length => _string.length;
+  int operator[](int i) => _string.codeUnitAt(i);
+}
+
+class _ListIndicesIterable extends ListIterable<int> {
+  List _backedList;
+
+  _ListIndicesIterable(this._backedList);
+
+  int get length => _backedList.length;
+  int elementAt(int index) {
+    if (index < 0 || index >= length) throw new RangeError(index);
+    return index;
+  }
+}
+
+class ListMapView<E> implements Map<int, E> {
+  List<E> _values;
+
+  ListMapView(this._values);
+
+  E operator[] (int key) => containsKey(key) ? _values[key] : null;
+  int get length => _values.length;
+
+  Iterable<E> get values => new SubListIterable<E>(_values, 0, null);
+  Iterable<int> get keys => new _ListIndicesIterable(_values);
+
+  bool get isEmpty => _values.isEmpty;
+  bool containsValue(E value) => _values.contains(value);
+  bool containsKey(int key) => key is int && key >= 0 && key < length;
+
+  void forEach(void f(int key, E value)) {
+    int length = _values.length;
+    for (int i = 0; i < length; i++) {
+      f(i, _values[i]);
+      if (length != _values.length) {
+        throw new ConcurrentModificationError(_values);
+      }
+    }
+  }
+
+  void operator[]= (int key, E value) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+
+  E putIfAbsent(int key, E ifAbsent()) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+
+  E remove(int key) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+
+  void clear() {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 4ed1564..6df2cc6 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -12,8 +12,10 @@
 import "util/util.dart";
 import "elements/modelx.dart" show ElementX, FunctionElementX, ClassElementX;
 
-abstract class ClosureNamer {
-  SourceString getClosureVariableName(SourceString name, int id);
+class ClosureNamer {
+  SourceString getClosureVariableName(SourceString name, int id) {
+    return new SourceString("${name.slowToString()}_$id");    
+  }
 }
 
 
@@ -190,6 +192,20 @@
         this.parametersWithSentinel = new Map<Element, Element>();
 
   bool isClosure() => closureElement != null;
+
+  bool captures(Element element) => freeVariableMapping.containsKey(element);
+
+  bool mutates(Element element) {
+    Element copy = freeVariableMapping[element];
+    return copy != null && !copy.isMember();
+  }
+
+  void forEachCapturedVariable(void f(Element element)) {
+    freeVariableMapping.forEach((variable, _) {
+      if (variable is BoxElement) return;
+      f(variable);
+    });
+  }
 }
 
 class ClosureTranslator extends Visitor {
@@ -431,11 +447,10 @@
     }
     if (outermostElement.isMember() &&
         compiler.world.needsRti(outermostElement.getEnclosingClass())) {
-      if (outermostElement.isInstanceMember()
-          || outermostElement.isGenerativeConstructor()) {
-        if (hasTypeVariable(type)) useLocal(closureData.thisElement);
-      } else if (outermostElement.isFactoryConstructor()) {
+      if (outermostElement.isConstructor()) {
         analyzeTypeVariables(type);
+      } else if (outermostElement.isInstanceMember()) {
+        if (hasTypeVariable(type)) useLocal(closureData.thisElement);
       }
     }
 
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index ec15da18..bdda72e 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -98,12 +98,19 @@
           [ConstantSystem constantSystem = DART_CONSTANT_SYSTEM])
       : this.constantSystem = constantSystem;
 
+  void initializeHelperClasses() {}
+
   void enqueueAllTopLevelFunctions(LibraryElement lib, Enqueuer world) {
     lib.forEachExport((Element e) {
       if (e.isFunction()) world.addToWorkList(e);
     });
   }
 
+  // TODO(karlklose): get rid of this and add a factory constructor to [List]
+  // that creates an instance of JSArray to make the dependency visible in from
+  // the source code.
+  void addBackendRtiDependencies(World world);
+
   void enqueueHelpers(ResolutionEnqueuer world);
   void codegen(CodegenWorkItem work);
 
@@ -368,6 +375,7 @@
       closureNamer = jsBackend.namer;
       backend = jsBackend;
     } else {
+      closureNamer = new closureMapping.ClosureNamer();
       backend = new dart_backend.DartBackend(this, strips);
     }
 
@@ -566,6 +574,7 @@
     }
 
     types = new Types(this, dynamicClass);
+    backend.initializeHelperClasses();
   }
 
   void scanBuiltinLibraries() {
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index 0f0a029..c76c45f 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -151,12 +151,6 @@
     return passThrough('--categories=${categories.join(",")}');
   }
 
-  // TODO(8522): Remove this method once option is restored.
-  complainAboutDisallowUnsafeEval(String argument) {
-    fail('Error: $argument is currently not supported, '
-         'see http://dartbug.com/8522');
-  }
-
   handleShortOptions(String argument) {
     var shortOptions = argument.substring(1).split("");
     for (var shortOption in shortOptions) {
@@ -202,8 +196,7 @@
                       (_) => passThrough('--enable-concrete-type-inference')),
     new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
     new OptionHandler('--package-root=.+|-p.+', setPackageRoot),
-    new OptionHandler('--disallow-unsafe-eval',
-                      complainAboutDisallowUnsafeEval),
+    new OptionHandler('--disallow-unsafe-eval', passThrough),
     new OptionHandler('--analyze-all', passThrough),
     new OptionHandler('--analyze-only', setAnalyzeOnly),
     new OptionHandler('--disable-native-live-type-analysis', passThrough),
@@ -413,6 +406,10 @@
   --minify
     Generate minified output.
 
+  --disallow-unsafe-eval
+    Disable dynamic generation of code in the generated output. This is
+    necessary to satisfy CSP restrictions (see http://www.w3.org/TR/CSP/).
+
   --suppress-warnings
     Do not display any warnings.
 
@@ -442,18 +439,6 @@
     Disable the optimization that removes unused native types from dart:html
     and related libraries.
 
-'''
-/* TODO(8522): Restore this comment once option is restored.
-'''
-  --disallow-unsafe-eval
-    Disable dynamic generation of code in the generated output. This is
-    necessary to satisfy CSP restrictions (see http://www.w3.org/TR/CSP/).
-    This flag is not continuously tested. Please report breakages and we
-    will fix them as soon as possible.
-
-'''
-*/
-'''
   --reject-deprecated-language-features
     Reject deprecated language features.  Without this option, the
     compiler will accept language features that are no longer valid
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index d400708..91cff3e 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -217,6 +217,8 @@
         stripAsserts = strips.indexOf('asserts') != -1,
         super(compiler);
 
+  void addBackendRtiDependencies(World world) {}
+
   void enqueueHelpers(ResolutionEnqueuer world) {
     // Right now resolver doesn't always resolve interfaces needed
     // for literals, so force them. TODO(antonm): fix in the resolver.
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
index 669aa02..693afa0 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -448,8 +448,7 @@
   static bool isDynamicType(TypeAnnotation typeAnnotation) {
     if (!isPlainTypeName(typeAnnotation)) return false;
     String name = typeAnnotation.typeName.asIdentifier().source.slowToString();
-    // TODO(aprelev@gmail.com): Removed deprecated Dynamic keyword support.
-    return name == 'Dynamic' || name == 'dynamic';
+    return name == 'dynamic';
   }
 
   visitTypeAnnotation(TypeAnnotation node) {
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 00bcbd2..42b33e9 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1479,12 +1479,10 @@
    */
   Element lookupSuperMemberInLibrary(SourceString memberName,
                                      LibraryElement library) {
-    bool includeInjectedMembers = isPatch;
     bool isPrivate = memberName.isPrivate();
     for (ClassElement s = superclass; s != null; s = s.superclass) {
       // Private members from a different library are not visible.
       if (isPrivate && !identical(library, s.getLibrary())) continue;
-      s = includeInjectedMembers ? s.implementation : s;
       Element e = s.lookupLocalMember(memberName);
       if (e == null) continue;
       // Static members are not inherited.
@@ -1499,11 +1497,9 @@
 
   Element lookupSuperInterfaceMember(SourceString memberName,
                                      LibraryElement fromLibrary) {
-    bool includeInjectedMembers = isPatch;
     bool isPrivate = memberName.isPrivate();
     for (InterfaceType t in interfaces) {
       ClassElement cls = t.element;
-      cls = includeInjectedMembers ? cls.implementation : cls;
       Element e = cls.lookupLocalMember(memberName);
       if (e == null) continue;
       // Private members from a different library are not visible.
@@ -1526,14 +1522,36 @@
    * origin and the patch class are returned.
    */
   Element lookupSelector(Selector selector) {
-    SourceString memberName = selector.name;
+    SourceString name = selector.name;
+    bool isPrivate = name.isPrivate();
     LibraryElement library = selector.library;
-    Element localMember = lookupLocalMember(memberName);
-    if (localMember != null &&
-        (!memberName.isPrivate() || getLibrary() == library)) {
-      return localMember;
+    for (ClassElement current = this;
+         current != null;
+         current = current.superclass) {
+      Element member = current.lookupLocalMember(name);
+      if (member == null) continue;
+      // Private members from a different library are not visible.
+      if (isPrivate && !identical(library, member.getLibrary())) continue;
+      // Static members are not inherited.
+      if (member.modifiers.isStatic() && !identical(this, current)) continue;
+      // If we find an abstract field we have to make sure that it has
+      // the getter or setter part we're actually looking
+      // for. Otherwise, we continue up the superclass chain.
+      if (member.isAbstractField()) {
+        AbstractFieldElement field = member;
+        FunctionElement getter = field.getter;
+        FunctionElement setter = field.setter;
+        if (selector.isSetter()) {
+          if (setter != null) return setter;
+        } else {
+          assert(selector.isGetter() || selector.isCall());
+          if (getter != null) return getter;
+        }
+      } else {
+        return member;
+      }
     }
-    return lookupSuperMemberInLibrary(memberName, library);
+    return null;
   }
 
   /**
@@ -1953,19 +1971,17 @@
  *
  * For example, consider:
  *
- * [:
- * class Data {
- *   const Data();
- * }
+ *     class Data {
+ *       const Data();
+ *     }
  *
- * const data = const Data();
+ *     const data = const Data();
  *
- * @data
- * class Foo {}
+ *     @data
+ *     class Foo {}
  *
- * @data @data
- * class Bar {}
- * :]
+ *     @data @data
+ *     class Bar {}
  *
  * In this example, there are three instances of [MetadataAnnotation]
  * and they correspond each to a location in the source code where
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index e22fb11..615ffe8 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -86,6 +86,11 @@
   // the work list'?
   bool addElementToWorkList(Element element, [TreeElements elements]);
 
+  void registerInstantiatedType(InterfaceType type) {
+    universe.instantiatedTypes.add(type);
+    registerInstantiatedClass(type.element);
+  }
+
   void registerInstantiatedClass(ClassElement cls) {
     if (universe.instantiatedClasses.contains(cls)) return;
     if (!cls.isAbstract(compiler)) {
@@ -317,7 +322,7 @@
            || selector.isOperator()
            || selector.isIndex()
            || selector.isIndexSet());
-    if (element.isFunction()) {
+    if (element.isFunction() || element.isGetter()) {
       addToWorkList(element);
     } else if (element.isAbstractField()) {
       AbstractFieldElement field = element;
@@ -351,6 +356,11 @@
   }
 
   void registerIsCheck(DartType type) {
+    // Even in checked mode, type annotations for return type and argument
+    // types do not imply type checks, so there should never be a check
+    // against the type variable of a typedef.
+    assert(type.kind != TypeKind.TYPE_VARIABLE ||
+           !type.element.enclosingElement.isTypedef());
     universe.isChecks.add(type);
     compiler.backend.registerIsCheck(type, this);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js/nodes.dart b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
index ccf91b9..fe89432 100644
--- a/sdk/lib/_internal/compiler/implementation/js/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/js/nodes.dart
@@ -1081,8 +1081,7 @@
   String message;
 
   String toString() {
-    var codes =
-        new List.fixedLength(parser.lastPosition, fill: charCodes.$SPACE);
+    var codes = new List.filled(parser.lastPosition, charCodes.$SPACE);
     var spaces = new String.fromCharCodes(codes);
     return "Error in MiniJsParser:\n${parser.src}\n$spaces^\n$spaces$message\n";
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index a66ab80..50433d4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -42,8 +42,8 @@
   final List<HType> types;
 
   OptionalParameterTypes(int optionalArgumentsCount)
-      : names = new List<SourceString>.fixedLength(optionalArgumentsCount),
-        types = new List<HType>.fixedLength(optionalArgumentsCount);
+      : names = new List<SourceString>(optionalArgumentsCount),
+        types = new List<HType>(optionalArgumentsCount);
 
   int get length => names.length;
   SourceString name(int index) => names[index];
@@ -69,10 +69,10 @@
   final List<SourceString> namedArguments;
 
   HTypeList(int length)
-      : types = new List<HType>.fixedLength(length),
+      : types = new List<HType>(length),
         namedArguments = null;
   HTypeList.withNamedArguments(int length, this.namedArguments)
-      : types = new List<HType>.fixedLength(length);
+      : types = new List<HType>(length);
   const HTypeList.withAllUnknown()
       : types = null,
         namedArguments = null;
@@ -90,6 +90,7 @@
     HTypeList result = new HTypeList(node.inputs.length - 1);
     for (int i = 0; i < result.types.length; i++) {
       result.types[i] = node.inputs[i + 1].instructionType;
+      assert(!result.types[i].isConflicting());
     }
     return result;
   }
@@ -115,6 +116,7 @@
 
     for (int i = 0; i < result.types.length; i++) {
       result.types[i] = node.inputs[i + startInvokeIndex].instructionType;
+      assert(!result.types[i].isConflicting());
     }
     return result;
   }
@@ -276,6 +278,7 @@
                          Element field,
                          HType type) {
     assert(field.isField());
+    assert(!type.isConflicting());
     HType before = optimisticFieldType(field);
 
     HType oldType = typeMap[field];
@@ -639,7 +642,6 @@
   ClassElement jsFunctionClass;
   ClassElement jsNullClass;
   ClassElement jsBoolClass;
-  ClassElement objectInterceptorClass;
   Element jsArrayLength;
   Element jsStringLength;
   Element jsArrayRemoveLast;
@@ -648,6 +650,7 @@
   Element jsStringConcat;
   Element jsStringToString;
   Element getInterceptorMethod;
+  Element interceptedNames;
   Element fixedLengthListConstructor;
   bool seenAnyClass = false;
 
@@ -702,11 +705,9 @@
   final Map<String, Collection<ClassElement>> specializedGetInterceptors;
 
   /**
-   * Set of classes whose instances are intercepted. Implemented as a
-   * [LinkedHashMap] to preserve the insertion order.
-   * TODO(ngeoffray): No need to preserve order anymore.
+   * Set of classes whose methods are intercepted.
    */
-  final Map<ClassElement, ClassElement> interceptedClasses;
+  final Set<ClassElement> interceptedClasses;
 
   /**
    * Set of selectors that are used from within loops. Used by the
@@ -732,11 +733,10 @@
         rti = new RuntimeTypeInformation(compiler),
         specializedGetInterceptors =
             new Map<String, Collection<ClassElement>>(),
-        interceptedClasses = new LinkedHashMap<ClassElement, ClassElement>(),
+        interceptedClasses = new Set<ClassElement>(),
         super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
     emitter = disableEval
-        // TODO(8522): Restore --disallow-unsafe-eval.
-        ? null // new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
+        ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap)
         : new CodeEmitterTask(compiler, namer, generateSourceMap);
     builder = new SsaBuilderTask(this);
     optimizer = new SsaOptimizerTask(this);
@@ -753,7 +753,7 @@
 
   bool isInterceptorClass(Element element) {
     if (element == null) return false;
-    return interceptedClasses.containsKey(element);
+    return interceptedClasses.contains(element);
   }
 
   void addInterceptedSelector(Selector selector) {
@@ -761,7 +761,7 @@
   }
 
   String registerOneShotInterceptor(Selector selector) {
-    Set<ClassElement> classes = getInterceptedClassesOn(selector);
+    Set<ClassElement> classes = getInterceptedClassesOn(selector.name);
     String name = namer.getOneShotInterceptorName(selector, classes);
     if (!oneShotInterceptors.containsKey(name)) {
       registerSpecializedGetInterceptor(classes);
@@ -770,50 +770,43 @@
     return name;
   }
 
-  final Map<Selector, Set<ClassElement>> interceptedClassesCache =
-      new Map<Selector, Set<ClassElement>>();
-  final Map<Selector, Set<ClassElement>> interceptedClassesNonNullCache =
-      new Map<Selector, Set<ClassElement>>();
-
-  /**
-   * Returns a set of interceptor classes that contain a member whose
-   * signature matches the given [selector]. Returns [:null:] if there
-   * is no class.
-   */
-  Set<ClassElement> getInterceptedClassesOn(Selector selector,
-                                            {bool canBeNull: true}) {
-    Set<Element> intercepted = interceptedElements[selector.name];
-    if (intercepted == null) return null;
-    // Pick the right cache and query it.
-    Map<Selector, Set<ClassElement>> cache = canBeNull
-        ? interceptedClassesCache
-        : interceptedClassesNonNullCache;
-    if (cache.containsKey(selector)) return cache[selector];
-    // Populate the cache by running through all the elements and
-    // determine if the given selector applies to them.
-    Set<ClassElement> result = new Set<ClassElement>();
-    for (Element element in intercepted) {
-      ClassElement enclosing = element.getEnclosingClass();
-      // We have to treat null as a bottom type, so we use the untyped
-      // applies method for those elements that are implemented on the
-      // null class.
-      bool applies = (enclosing == jsNullClass)
-          ? canBeNull && selector.appliesUntyped(element, compiler)
-          : selector.applies(element, compiler);
-      if (applies) result.add(enclosing);
-    }
-    if (result.isEmpty) result = null;
-    cache[selector] = result;
-    assert(cache.containsKey(selector));
-    return result;
+  bool isInterceptedMethod(Element element) {
+    return element.isInstanceMember()
+        && interceptedElements[element.name] != null;
   }
 
-  void initializeInterceptorElements() {
-    objectInterceptorClass =
-        compiler.findInterceptor(const SourceString('ObjectInterceptor'));
+  bool isInterceptedName(SourceString name) {
+    return interceptedElements[name] != null;
+  }
+
+  final Map<SourceString, Set<ClassElement>> interceptedClassesCache =
+      new Map<SourceString, Set<ClassElement>>();
+
+  /**
+   * Returns a set of interceptor classes that contain a member named
+   * [name]. Returns [:null:] if there is no class.
+   */
+  Set<ClassElement> getInterceptedClassesOn(SourceString name) {
+    Set<Element> intercepted = interceptedElements[name];
+    if (intercepted == null) return null;
+    return interceptedClassesCache.putIfAbsent(name, () {
+      // Populate the cache by running through all the elements and
+      // determine if the given selector applies to them.
+      Set<ClassElement> result = new Set<ClassElement>();
+      for (Element element in intercepted) {
+        result.add(element.getEnclosingClass());
+      }
+      return result;
+    });
+  }
+
+  void initializeHelperClasses() {
     getInterceptorMethod =
         compiler.findInterceptor(const SourceString('getInterceptor'));
+    interceptedNames =
+        compiler.findInterceptor(const SourceString('interceptedNames'));
     List<ClassElement> classes = [
+      compiler.objectClass,
       jsStringClass = compiler.findInterceptor(const SourceString('JSString')),
       jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')),
       // The int class must be before the double class, because the
@@ -845,7 +838,7 @@
         jsStringClass, const SourceString('toString'));
 
     for (ClassElement cls in classes) {
-      if (cls != null) interceptedClasses[cls] = null;
+      if (cls != null) interceptedClasses.add(cls);
     }
   }
 
@@ -863,23 +856,11 @@
   }
 
   void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
-    compiler.enqueuer.codegen.registerInstantiatedClass(objectInterceptorClass);
     String name = namer.getInterceptorName(getInterceptorMethod, classes);
     if (classes.contains(compiler.objectClass)) {
       // We can't use a specialized [getInterceptorMethod], so we make
       // sure we emit the one with all checks.
-      specializedGetInterceptors.putIfAbsent(name, () {
-        // It is important to take the order provided by the map,
-        // because we want the int type check to happen before the
-        // double type check: the double type check covers the int
-        // type check. Also we don't need to do a number type check
-        // because that is covered by the double type check.
-        List<ClassElement> keys = <ClassElement>[];
-        interceptedClasses.forEach((ClassElement cls, _) {
-          if (cls != jsNumberClass) keys.add(cls);
-        });
-        return keys;
-      });
+      specializedGetInterceptors[name] = interceptedClasses;
     } else {
       specializedGetInterceptors[name] = classes;
     }
@@ -890,14 +871,14 @@
     // make sure all [noSuchMethod] methods know they might take a
     // [JsInvocationMirror] as parameter.
     HTypeList types = new HTypeList(1);
-    types[0] = new HBoundedType.exact(
-        compiler.jsInvocationMirrorClass.computeType(compiler));
+    types[0] = new HType.nonNullExact(
+        compiler.jsInvocationMirrorClass.computeType(compiler),
+        compiler);
     argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod());
   }
 
   void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {
     if (!seenAnyClass) {
-      initializeInterceptorElements();
       initializeNoSuchMethod();
       seenAnyClass = true;
     }
@@ -967,6 +948,12 @@
     return new JavaScriptItemCompilationContext();
   }
 
+  void addBackendRtiDependencies(World world) {
+    if (jsArrayClass != null) {
+      world.registerRtiDependency(jsArrayClass, compiler.listClass);
+    }
+  }
+
   void enqueueHelpers(ResolutionEnqueuer world) {
     jsIndexingBehaviorInterface =
         compiler.findHelper(const SourceString('JavaScriptIndexingBehavior'));
@@ -1008,6 +995,14 @@
     enqueueInResolution(getTraceFromException());
   }
 
+  void registerSetRuntimeType() {
+    enqueueInResolution(getSetRuntimeTypeInfo());
+  }
+
+  void registerGetRuntimeTypeArgument() {
+    enqueueInResolution(getGetRuntimeTypeArgument());
+  }
+
   void registerRuntimeType() {
     enqueueInResolution(getSetRuntimeTypeInfo());
     enqueueInResolution(getGetRuntimeTypeInfo());
@@ -1016,11 +1011,13 @@
   }
 
   void registerIsCheck(DartType type, Enqueuer world) {
-    if (!type.isRaw) {
+    bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
+    if (!type.isRaw || isTypeVariable) {
       enqueueInResolution(getSetRuntimeTypeInfo());
       enqueueInResolution(getGetRuntimeTypeInfo());
       enqueueInResolution(getGetRuntimeTypeArgument());
       enqueueInResolution(getCheckArguments());
+      if (isTypeVariable) enqueueInResolution(getGetObjectIsSubtype());
       world.registerInstantiatedClass(compiler.listClass);
     }
     // [registerIsCheck] is also called for checked mode checks, so we
@@ -1469,6 +1466,10 @@
     return compiler.findHelper(const SourceString('checkArguments'));
   }
 
+  Element getGetObjectIsSubtype() {
+    return compiler.findHelper(const SourceString('objectIsSubtype'));
+  }
+
   Element getThrowNoSuchMethod() {
     return compiler.findHelper(const SourceString('throwNoSuchMethod'));
   }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 64a6aa6..227f850 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -59,17 +59,22 @@
   final Namer namer;
   ConstantEmitter constantEmitter;
   NativeEmitter nativeEmitter;
-  CodeBuffer boundClosureBuffer;
   CodeBuffer mainBuffer;
   final CodeBuffer deferredBuffer = new CodeBuffer();
   /** Shorter access to [isolatePropertiesName]. Both here in the code, as
       well as in the generated code. */
   String isolateProperties;
   String classesCollector;
-  Set<ClassElement> neededClasses;
+  final Set<ClassElement> neededClasses = new Set<ClassElement>();
+  final List<ClassElement> regularClasses = <ClassElement>[];
+  final List<ClassElement> deferredClasses = <ClassElement>[];
+  final List<ClassElement> nativeClasses = <ClassElement>[];
+
   // TODO(ngeoffray): remove this field.
   Set<ClassElement> instantiatedClasses;
 
+  final List<jsAst.Expression> boundClosures = <jsAst.Expression>[];
+
   JavaScriptBackend get backend => compiler.backend;
 
   String get _ => compiler.enableMinification ? "" : " ";
@@ -107,9 +112,20 @@
 
   final bool generateSourceMap;
 
+  Iterable<ClassElement> cachedClassesUsingTypeVariableTests;
+
+  Iterable<ClassElement> get classesUsingTypeVariableTests {
+    if (cachedClassesUsingTypeVariableTests == null) {
+      cachedClassesUsingTypeVariableTests = compiler.codegenWorld.isChecks
+          .where((DartType t) => t is TypeVariableType)
+          .map((TypeVariableType v) => v.element.getEnclosingClass())
+          .toList();
+    }
+    return cachedClassesUsingTypeVariableTests;
+  }
+
   CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap)
-      : boundClosureBuffer = new CodeBuffer(),
-        mainBuffer = new CodeBuffer(),
+      : mainBuffer = new CodeBuffer(),
         this.namer = namer,
         boundClosureCache = new Map<int, String>(),
         interceptorClosureCache = new Map<int, String>(),
@@ -123,7 +139,10 @@
   }
 
   void computeRequiredTypeChecks() {
-    assert(checkedClasses == null);
+    assert(checkedClasses == null && checkedTypedefs == null);
+
+    compiler.codegenWorld.addImplicitChecks(classesUsingTypeVariableTests);
+
     checkedClasses = new Set<ClassElement>();
     checkedTypedefs = new Set<TypedefElement>();
     compiler.codegenWorld.isChecks.forEach((DartType t) {
@@ -231,7 +250,7 @@
         fun);
   }
 
-  jsAst.Fun get defineClassFunction {
+  List get defineClassFunction {
     // First the class name, then the field names in an array and the members
     // (inside an Object literal).
     // The caller can also pass in the constructor as a function if needed.
@@ -247,11 +266,11 @@
     // });
 
     // function(cls, fields, prototype) {
-    return js.fun(['cls', 'fields', 'prototype'], [
+    var defineClass = js.fun(['cls', 'fields', 'prototype'], [
       js['var constructor'],
 
-      // if (typeof fields == 'function') {
-      js.if_(js["typeof fields == 'function'"], [
+      // if (typeof fields == "function") {
+      js.if_(js['typeof fields == "function"'], [
         js['constructor = fields']
       ], /* else */ [
         js['var str = "function " + cls + "("'],
@@ -279,6 +298,13 @@
       // return constructor;
       js.return_('constructor')
     ]);
+    // Declare a function called "generateAccessor".  This is used in
+    // defineClassFunction (it's a local declaration in init()).
+    return [
+        generateAccessorFunction,
+        js['$generateAccessorHolder = generateAccessor'],
+        new jsAst.FunctionDeclaration(
+            new jsAst.VariableDeclaration('defineClass'), defineClass) ];
   }
 
   /** Needs defineClass to be defined. */
@@ -295,11 +321,11 @@
 
     return [
       js['var $supportsProtoName = false'],
-      js["var tmp = (defineClass('c', ['f?'], {})).prototype"],
+      js['var tmp = (defineClass("c", ["f?"], {})).prototype'],
 
       js.if_(js['tmp.__proto__'], [
         js['tmp.__proto__ = {}'],
-        js.if_(js[r"typeof tmp.get$f != 'undefined'"],
+        js.if_(js[r'typeof tmp.get$f != "undefined"'],
                js['$supportsProtoName = true'])
 
       ])
@@ -341,13 +367,13 @@
            * Super;field1,field2 from the null-string property on the
            * descriptor.
            */
-          // var fields = desc[''], supr;
-          js["var fields = desc[''], supr"],
+          // var fields = desc[""], supr;
+          js['var fields = desc[""], supr'],
 
-          js.if_(js["typeof fields == 'string'"], [
+          js.if_(js['typeof fields == "string"'], [
             js['var s = fields.split(";")'],
             js['supr = s[0]'],
-            js["fields = s[1] == '' ? [] : s[1].split(',')"],
+            js['fields = s[1] == "" ? [] : s[1].split(",")'],
           ], /* else */ [
             js['supr = desc.super']
           ]),
@@ -462,7 +488,7 @@
     List copyFinishClasses = [];
     if (needsDefineClass) {
       copyFinishClasses.add(
-          // newIsolate.$finishClasses = oldIsolate.\$finishClasses;
+          // newIsolate.$finishClasses = oldIsolate.$finishClasses;
           js['newIsolate'][finishClassesProperty].assign(
               js['oldIsolate'][finishClassesProperty]));
     }
@@ -569,17 +595,7 @@
 
   List buildDefineClassAndFinishClassFunctionsIfNecessary() {
     if (!needsDefineClass) return [];
-    return [
-      // Declare a function called "generateAccessor".  This is used in
-      // defineClassFunction (it's a local declaration in init()).
-      generateAccessorFunction,
-
-      js['$generateAccessorHolder = generateAccessor'],
-
-      // function defineClass ...
-      new jsAst.FunctionDeclaration(
-          new jsAst.VariableDeclaration('defineClass'), defineClassFunction)
-    ]
+    return defineClassFunction
     ..addAll(buildProtoSupportCheck())
     ..addAll([
       js[finishClassesName].assign(finishClassesFunction)
@@ -637,12 +653,11 @@
     if (alreadyGenerated.contains(invocationName)) return;
     alreadyGenerated.add(invocationName);
 
-    bool isInterceptorClass =
-        backend.isInterceptorClass(member.getEnclosingClass());
+    bool isInterceptedMethod = backend.isInterceptedMethod(member);
 
-    // If the method is in an interceptor class, we need to also pass
+    // If the method is intercepted, we need to also pass
     // the actual receiver.
-    int extraArgumentCount = isInterceptorClass ? 1 : 0;
+    int extraArgumentCount = isInterceptedMethod ? 1 : 0;
     // Use '$receiver' to avoid clashes with other parameter names. Using
     // '$receiver' works because [:namer.safeName:] used for getting parameter
     // names never returns a name beginning with a single '$'.
@@ -650,15 +665,14 @@
 
     // The parameters that this stub takes.
     List<jsAst.Parameter> parametersBuffer =
-        new List<jsAst.Parameter>.fixedLength(
-            selector.argumentCount + extraArgumentCount);
+        new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
     // The arguments that will be passed to the real method.
     List<jsAst.Expression> argumentsBuffer =
-        new List<jsAst.Expression>.fixedLength(
+        new List<jsAst.Expression>(
             parameters.parameterCount + extraArgumentCount);
 
     int count = 0;
-    if (isInterceptorClass) {
+    if (isInterceptedMethod) {
       count++;
       parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
       argumentsBuffer[0] = js[receiverArgumentName];
@@ -898,11 +912,6 @@
   void emitInstanceMembers(ClassElement classElement,
                            ClassBuilder builder) {
     assert(invariant(classElement, classElement.isDeclaration));
-    if (classElement == backend.objectInterceptorClass) {
-      emitInterceptorMethods(builder);
-      // The ObjectInterceptor does not have any instance methods.
-      return;
-    }
 
     void visitMember(ClassElement enclosing, Element member) {
       assert(invariant(classElement, member.isDeclaration));
@@ -933,7 +942,10 @@
 
     void generateIsTest(Element other) {
       jsAst.Expression code;
-      if (compiler.objectClass == other) return;
+      if (other == compiler.objectClass && other != classElement) {
+        // Avoid emitting [:$isObject:] on all classes but [Object].
+        return;
+      }
       if (nativeEmitter.requiresNativeIsCheck(other)) {
         code = js.fun([], [js.return_(true)]);
       } else {
@@ -977,13 +989,10 @@
       }
     }
 
-    if (backend.isInterceptorClass(classElement)) {
-      // The operator== method in [:Object:] does not take the same
-      // number of arguments as an intercepted method, therefore we
-      // explicitely add one to all interceptor classes. Note that we
-      // would not have do do that if all intercepted methods had
-      // a calling convention where the receiver is the first
-      // parameter.
+    if (backend.isInterceptorClass(classElement)
+        && classElement != compiler.objectClass) {
+      // We optimize the operator== on interceptor classes to
+      // just do a JavaScript double or triple equals.
       String name = backend.namer.publicInstanceMethodNameByArity(
           const SourceString('=='), 1);
       Function kind = (classElement == backend.jsNullClass)
@@ -994,13 +1003,16 @@
     }
   }
 
-  void emitRuntimeClassesAndTests(CodeBuffer buffer) {
+  void emitRuntimeTypeSupport(CodeBuffer buffer) {
     RuntimeTypeInformation rti = backend.rti;
     TypeChecks typeChecks = rti.getRequiredChecks();
 
+    /// Classes that are not instantiated and native classes need a holder
+    /// object for their checks, because there will be no class defined for
+    /// them.
     bool needsHolder(ClassElement cls) {
       return !neededClasses.contains(cls) || cls.isNative() ||
-          rti.isJsNative(cls);
+        rti.isJsNative(cls);
     }
 
     /**
@@ -1013,7 +1025,7 @@
       if (!needsHolder(cls)) return;
       String holder = namer.isolateAccess(cls);
       String name = namer.getName(cls);
-      buffer.add("$holder$_=$_{builtin\$cls:$_'$name'");
+      buffer.add('$holder$_=$_{builtin\$cls:$_"$name"');
       buffer.add('}$N');
     }
 
@@ -1108,10 +1120,15 @@
             ? member.fixedBackendName()
             : (isMixinNativeField ? member.name.slowToString() : accessorName);
         bool needsCheckedSetter = false;
-        if (needsSetter && compiler.enableTypeAssertions
-            && canGenerateCheckedSetter(member)) {
-          needsCheckedSetter = true;
-          needsSetter = false;
+        if (needsSetter) {
+          if (compiler.enableTypeAssertions
+              && canGenerateCheckedSetter(member)) {
+            needsCheckedSetter = true;
+            needsSetter = false;
+          } else if (backend.isInterceptedMethod(member)) {
+            // The [addField] will take care of generating the setter.
+            needsSetter = false;
+          }
         }
         // Getters and setters with suffixes will be generated dynamically.
         addField(member,
@@ -1149,6 +1166,7 @@
 
   void generateGetter(Element member, String fieldName, String accessorName,
                       ClassBuilder builder) {
+    assert(!backend.isInterceptorClass(member));
     String getterName = namer.getterNameFromAccessorName(accessorName);
     builder.addProperty(getterName,
         js.fun([], js.return_(js['this'][fieldName])));
@@ -1156,9 +1174,13 @@
 
   void generateSetter(Element member, String fieldName, String accessorName,
                       ClassBuilder builder) {
+    assert(!backend.isInterceptorClass(member));
     String setterName = namer.setterNameFromAccessorName(accessorName);
+    List<String> args = backend.isInterceptedMethod(member)
+        ? ['receiver', 'v']
+        : ['v'];
     builder.addProperty(setterName,
-        js.fun(['v'], js['this'][fieldName].assign('v')));
+        js.fun(args, js['this'][fieldName].assign('v')));
   }
 
   bool canGenerateCheckedSetter(Element member) {
@@ -1189,8 +1211,11 @@
     }
 
     String setterName = namer.setterNameFromAccessorName(accessorName);
+    List<String> args = backend.isInterceptedMethod(member)
+        ? ['receiver', 'v']
+        : ['v'];
     builder.addProperty(setterName,
-        js.fun(['v'], js['this'][fieldName].assign(js[helperName](arguments))));
+        js.fun(args, js['this'][fieldName].assign(js[helperName](arguments))));
   }
 
   void emitClassConstructor(ClassElement classElement, ClassBuilder builder) {
@@ -1204,7 +1229,7 @@
   void emitClassFields(ClassElement classElement,
                        ClassBuilder builder,
                        { String superClass: "",
-                         bool classIsNative: false}) {
+                         bool classIsNative: false }) {
     bool isFirstField = true;
     StringBuffer buffer = new StringBuffer();
     if (!classIsNative) {
@@ -1275,6 +1300,13 @@
           assert(!needsSetter);
           generateCheckedSetter(member, name, accessorName, builder);
         }
+        if (backend.isInterceptedMethod(member)
+            && instanceFieldNeedsSetter(member)) {
+          // The caller of this method sets [needsSetter] as false
+          // when the setter is intercepted.
+          assert(!needsSetter);
+          generateSetter(member, name, accessorName, builder);
+        }
         if (!getterAndSetterCanBeImplementedByFieldSpec) {
           if (needsGetter) {
             generateGetter(member, name, accessorName, builder);
@@ -1294,10 +1326,7 @@
    */
   void generateClass(ClassElement classElement, CodeBuffer buffer) {
     assert(invariant(classElement, classElement.isDeclaration));
-    if (classElement.isNative()) {
-      nativeEmitter.generateNativeClass(classElement);
-      return;
-    }
+    assert(invariant(classElement, !classElement.isNative()));
 
     needsDefineClass = true;
     String className = namer.getName(classElement);
@@ -1344,38 +1373,6 @@
     return _selectorRank(selector1) - _selectorRank(selector2);
   }
 
-  void emitInterceptorMethods(ClassBuilder builder) {
-    // Emit forwarders for the ObjectInterceptor class. We need to
-    // emit all possible sends on intercepted methods. Because of
-    // typed selectors we have to avoid generating the same forwarder
-    // multiple times.
-    Set<String> alreadyGenerated = new Set<String>();
-    for (Selector selector in
-         backend.usedInterceptors.toList()..sort(_compareSelectorNames)) {
-      String name = backend.namer.invocationName(selector);
-      if (alreadyGenerated.contains(name)) continue;
-      alreadyGenerated.add(name);
-
-      List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
-      List<jsAst.Expression> arguments = <jsAst.Expression>[];
-      parameters.add(new jsAst.Parameter('receiver'));
-
-      if (selector.isSetter()) {
-        parameters.add(new jsAst.Parameter('value'));
-        arguments.add(js['value']);
-      } else {
-        for (int i = 0; i < selector.argumentCount; i++) {
-          String argName = 'a$i';
-          parameters.add(new jsAst.Parameter(argName));
-          arguments.add(js[argName]);
-        }
-      }
-      jsAst.Fun function =
-          js.fun(parameters, js.return_(js['receiver'][name](arguments)));
-      builder.addProperty(name, function);
-    }
-  }
-
   Iterable<Element> getTypedefChecksOn(DartType type) {
     bool isSubtype(TypedefElement typedef) {
       FunctionType typedefType =
@@ -1423,6 +1420,11 @@
         emitted.add(superclass);
       }
       for (DartType supertype in cls.allSupertypes) {
+        ClassElement superclass = supertype.element;
+        if (classesUsingTypeVariableTests.contains(superclass)) {
+          emitSubstitution(superclass, emitNull: true);
+          emitted.add(superclass);
+        }
         for (ClassElement check in checkedClasses) {
           if (supertype.element == check && !emitted.contains(check)) {
             // Generate substitution.  If no substitution is necessary, emit
@@ -1537,8 +1539,9 @@
     }
 
     // Add unneeded interceptors to the [unneededClasses] set.
-    for (ClassElement interceptor in backend.interceptedClasses.keys) {
-      if (!needed.contains(interceptor)) {
+    for (ClassElement interceptor in backend.interceptedClasses) {
+      if (!needed.contains(interceptor)
+          && interceptor != compiler.objectClass) {
         unneededClasses.add(interceptor);
       }
     }
@@ -1546,40 +1549,7 @@
     return (ClassElement cls) => !unneededClasses.contains(cls);
   }
 
-  void emitClasses(CodeBuffer buffer) {
-    // Compute the required type checks to know which classes need a
-    // 'is$' method.
-    computeRequiredTypeChecks();
-    List<ClassElement> sortedClasses =
-        new List<ClassElement>.from(neededClasses);
-    sortedClasses.sort((ClassElement class1, ClassElement class2) {
-      // We sort by the ids of the classes. There is no guarantee that these
-      // ids are meaningful (or even deterministic), but in the current
-      // implementation they are increasing within a source file.
-      return class1.id - class2.id;
-    });
-
-    // If we need noSuchMethod support, we run through all needed
-    // classes to figure out if we need the support on any native
-    // class. If so, we let the native emitter deal with it.
-    if (compiler.enabledNoSuchMethod) {
-      SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD;
-      Selector noSuchMethodSelector = new Selector.noSuchMethod();
-      for (ClassElement element in sortedClasses) {
-        if (!element.isNative()) continue;
-        Element member = element.lookupLocalMember(noSuchMethodName);
-        if (member == null) continue;
-        if (noSuchMethodSelector.applies(member, compiler)) {
-          nativeEmitter.handleNoSuchMethod = true;
-          break;
-        }
-      }
-    }
-
-    for (ClassElement element in sortedClasses) {
-      generateClass(element, bufferForElement(element, buffer));
-    }
-
+  void emitClosureClassIfNeeded(CodeBuffer buffer) {
     // The closure class could have become necessary because of the generation
     // of stubs.
     ClassElement closureClass = compiler.closureClass;
@@ -1595,7 +1565,7 @@
                  '${_}null)$N');
 
       // Reset the map.
-      buffer.add("$classesCollector$_=$_{}$N");
+      buffer.add("$classesCollector$_=${_}null$N$n");
     }
   }
 
@@ -1721,9 +1691,9 @@
 
     Map<int, String> cache;
     String extraArg = null;
-    // Methods on interceptor classes take an extra parameter, which is the
-    // actual receiver of the call.
-    bool inInterceptor = backend.isInterceptorClass(member.getEnclosingClass());
+    // Intercepted methods take an extra parameter, which is the
+    // receiver of the call.
+    bool inInterceptor = backend.isInterceptedMethod(member);
     if (inInterceptor) {
       cache = interceptorClosureCache;
       extraArg = 'receiver';
@@ -1802,11 +1772,9 @@
         boundClosureBuilder.addProperty(operator, new jsAst.LiteralBool(true));
       });
 
-      jsAst.Expression init =
+      boundClosures.add(
           js[classesCollector][mangledName].assign(
-              boundClosureBuilder.toObjectInitializer());
-      boundClosureBuffer.add(jsAst.prettyPrint(init, compiler));
-      boundClosureBuffer.add("$N");
+              boundClosureBuilder.toObjectInitializer()));
 
       closureClass = namer.isolateAccess(closureClassElement);
 
@@ -1846,10 +1814,9 @@
                              DefineStubFunction defineStub) {
     assert(invariant(member, member.isDeclaration));
     LibraryElement memberLibrary = member.getLibrary();
-    // If the class is an interceptor class, the stub gets the
+    // If the method is intercepted, the stub gets the
     // receiver explicitely and we need to pass it to the getter call.
-    bool isInterceptorClass =
-        backend.isInterceptorClass(member.getEnclosingClass());
+    bool isInterceptedMethod = backend.isInterceptedMethod(member);
 
     const String receiverArgumentName = r'$receiver';
 
@@ -1857,7 +1824,7 @@
       if (member.isGetter()) {
         String getterName = namer.getterName(member);
         return js['this'][getterName](
-            isInterceptorClass
+            isInterceptedMethod
                 ? <jsAst.Expression>[js[receiverArgumentName]]
                 : <jsAst.Expression>[]);
       } else {
@@ -1885,7 +1852,7 @@
 
         List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
         List<jsAst.Expression> arguments = <jsAst.Expression>[];
-        if (isInterceptorClass) {
+        if (isInterceptedMethod) {
           parameters.add(new jsAst.Parameter(receiverArgumentName));
         }
 
@@ -1909,6 +1876,8 @@
     Iterable<VariableElement> staticNonFinalFields =
         handler.getStaticNonFinalFieldsForEmission();
     for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
+      // [:interceptedNames:] is handled in [emitInterceptedNames].
+      if (element == backend.interceptedNames) continue;
       compiler.withCurrentElement(element, () {
         Constant initialValue = handler.getInitialValueFor(element);
         jsAst.Expression init =
@@ -1957,7 +1926,7 @@
     return null;
   }
 
-  void emitCompileTimeConstants(CodeBuffer buffer) {
+  void emitCompileTimeConstants(CodeBuffer eagerBuffer) {
     ConstantHandler handler = compiler.constantHandler;
     List<Constant> constants = handler.getConstantsForEmission();
     bool addedMakeConstantList = false;
@@ -1974,8 +1943,10 @@
       if (name == null) continue;
       if (!addedMakeConstantList && constant.isList()) {
         addedMakeConstantList = true;
-        emitMakeConstantList(buffer);
+        emitMakeConstantList(eagerBuffer);
       }
+      CodeBuffer buffer =
+          bufferForElement(constant.computeType(compiler).element, eagerBuffer);
       jsAst.Expression init = js[isolateProperties][name].assign(
           constantInitializerExpression(constant));
       buffer.add(jsAst.prettyPrint(init, compiler));
@@ -2047,14 +2018,19 @@
       String createInvocationMirror = namer.getName(
           compiler.createInvocationMirrorElement);
 
+      assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
       jsAst.Expression expression = js['this.$noSuchMethodName'](
-          js[namer.CURRENT_ISOLATE][createInvocationMirror]([
-              js.string(methodName),
-              js.string(internalName),
-              type,
-              new jsAst.ArrayInitializer.from(
-                  parameters.map((param) => js[param.name]).toList()),
-              new jsAst.ArrayInitializer.from(argNames)]));
+          [js['this'],
+           js[namer.CURRENT_ISOLATE][createInvocationMirror]([
+               js.string(methodName),
+               js.string(internalName),
+               type,
+               new jsAst.ArrayInitializer.from(
+                   parameters.map((param) => js[param.name]).toList()),
+               new jsAst.ArrayInitializer.from(argNames)])]);
+      parameters = backend.isInterceptedName(selector.name)
+          ? ([new jsAst.Parameter('\$receiver')]..addAll(parameters))
+          : parameters;
       return js.fun(parameters, js.return_(expression));
     }
 
@@ -2068,36 +2044,22 @@
         // class has a member that matches the current name and
         // selector (grabbed from the scope).
         bool hasMatchingMember(ClassElement holder) {
-          Element element = holder.lookupMember(selector.name);
-          if (element == null) return false;
-
-          // TODO(kasperl): Consider folding this logic into the
-          // Selector.applies() method.
-          if (element is AbstractFieldElement) {
-            AbstractFieldElement field = element;
-            if (selector.isGetter()) {
-              return field.getter != null;
-            } else if (selector.isSetter()) {
-              return field.setter != null;
-            } else {
-              return false;
-            }
-          } else if (element is VariableElement) {
-            if (selector.isSetter() && element.modifiers.isFinalOrConst()) {
-              return false;
-            }
-          }
-          return selector.applies(element, compiler);
+          Element element = holder.lookupSelector(selector);
+          return (element != null)
+              ? selector.applies(element, compiler)
+              : false;
         }
 
         // If the selector is typed, we check to see if that type may
         // have a user-defined noSuchMethod implementation. If not, we
         // skip the selector altogether.
+
+        // TODO(kasperl): This shouldn't depend on the internals of
+        // the type mask. Move more of this code to the type mask.
         ClassElement receiverClass = objectClass;
-        if (selector is TypedSelector) {
-          TypedSelector typedSelector = selector;
-          DartType receiverType = typedSelector.receiverType;
-          receiverClass = receiverType.element;
+        TypeMask mask = selector.mask;
+        if (mask != null) {
+          receiverClass = mask.base.element;
         }
 
         // If the receiver class is guaranteed to have a member that
@@ -2187,10 +2149,10 @@
     }
     addComment('BEGIN invoke [main].', buffer);
     buffer.add("""
-if (typeof document !== 'undefined' && document.readyState !== 'complete') {
-  document.addEventListener('readystatechange', function () {
-    if (document.readyState == 'complete') {
-      if (typeof dartMainRunner === 'function') {
+if (typeof document !== "undefined" && document.readyState !== "complete") {
+  document.addEventListener("readystatechange", function () {
+    if (document.readyState == "complete") {
+      if (typeof dartMainRunner === "function") {
         dartMainRunner(function() { ${mainCall}; });
       } else {
         ${mainCall};
@@ -2198,7 +2160,7 @@
     }
   }, false);
 } else {
-  if (typeof dartMainRunner === 'function') {
+  if (typeof dartMainRunner === "function") {
     dartMainRunner(function() { ${mainCall}; });
   } else {
     ${mainCall};
@@ -2209,7 +2171,6 @@
   }
 
   void emitGetInterceptorMethod(CodeBuffer buffer,
-                                String objectName,
                                 String key,
                                 Collection<ClassElement> classes) {
     jsAst.Statement buildReturnInterceptor(ClassElement cls) {
@@ -2261,10 +2222,11 @@
       else if (cls == backend.jsNullClass) hasNull = true;
       else if (cls == backend.jsNumberClass) hasNumber = true;
       else if (cls == backend.jsStringClass) hasString = true;
-      else throw 'Internal error: $cls';
+      else {
+        assert(cls == compiler.objectClass);
+      }
     }
     if (hasDouble) {
-      assert(!hasNumber);
       hasNumber = true;
     }
     if (hasInt) hasNumber = true;
@@ -2317,7 +2279,7 @@
     if (hasArray) {
       block.statements.add(buildInterceptorCheck(backend.jsArrayClass));
     }
-    block.statements.add(js.return_(js[objectName]['prototype']));
+    block.statements.add(js.return_(receiver));
 
     buffer.add(jsAst.prettyPrint(
         js[isolateProperties][key].assign(js.fun(['receiver'], block)),
@@ -2329,22 +2291,27 @@
    * Emit all versions of the [:getInterceptor:] method.
    */
   void emitGetInterceptorMethods(CodeBuffer buffer) {
-    // If no class needs to be intercepted, just return.
-    if (backend.objectInterceptorClass == null) return;
-    String objectName = namer.isolateAccess(backend.objectInterceptorClass);
     var specializedGetInterceptors = backend.specializedGetInterceptors;
     for (String name in specializedGetInterceptors.keys.toList()..sort()) {
       Collection<ClassElement> classes = specializedGetInterceptors[name];
-      emitGetInterceptorMethod(buffer, objectName, name, classes);
+      emitGetInterceptorMethod(buffer, name, classes);
     }
   }
 
+  /**
+   * Compute all the classes that must be emitted.
+   */
   void computeNeededClasses() {
     instantiatedClasses =
         compiler.codegenWorld.instantiatedClasses.where(computeClassFilter())
             .toSet();
-    neededClasses = new Set<ClassElement>.from(instantiatedClasses);
-    for (ClassElement element in instantiatedClasses) {
+
+    // The set of classes that must be emitted are based on instantiated
+    // classes.
+    neededClasses.addAll(instantiatedClasses);
+
+    // Then add all superclasses of these classes.
+    for (ClassElement element in neededClasses.toList() /* copy */) {
       for (ClassElement superclass = element.superclass;
           superclass != null;
           superclass = superclass.superclass) {
@@ -2352,6 +2319,43 @@
         neededClasses.add(superclass);
       }
     }
+
+    // Finally, sort the classes.
+    List<ClassElement> sortedClasses = neededClasses.toList();
+    sortedClasses.sort((ClassElement class1, ClassElement class2) {
+      // We sort by the ids of the classes. There is no guarantee that these
+      // ids are meaningful (or even deterministic), but in the current
+      // implementation they are increasing within a source file.
+      return class1.id - class2.id;
+    });
+
+    // If we need noSuchMethod support, we run through all needed
+    // classes to figure out if we need the support on any native
+    // class. If so, we let the native emitter deal with it.
+    if (compiler.enabledNoSuchMethod) {
+      SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD;
+      Selector noSuchMethodSelector = new Selector.noSuchMethod();
+      for (ClassElement element in sortedClasses) {
+        if (!element.isNative()) continue;
+        Element member = element.lookupLocalMember(noSuchMethodName);
+        if (member == null) continue;
+        if (noSuchMethodSelector.applies(member, compiler)) {
+          nativeEmitter.handleNoSuchMethod = true;
+          break;
+        }
+      }
+    }
+
+    for (ClassElement element in sortedClasses) {
+      if (element.isNative()) {
+        // For now, native classes cannot be deferred.
+        nativeClasses.add(element);
+      } else if (isDeferred(element)) {
+        deferredClasses.add(element);
+      } else {
+        regularClasses.add(element);
+      }
+    }
   }
 
   int _compareSelectors(Selector selector1, Selector selector2) {
@@ -2386,7 +2390,7 @@
       return isNumber(variable).binary('&&',
           js['Math']['floor'](receiver).equals(receiver));
     }
-    
+
     jsAst.Expression tripleShiftZero(jsAst.Expression receiver) {
       return receiver.binary('>>>', js.toExpression(0));
     }
@@ -2516,7 +2520,7 @@
     for (String name in names) {
       Selector selector = backend.oneShotInterceptors[name];
       Set<ClassElement> classes =
-          backend.getInterceptedClassesOn(selector);
+          backend.getInterceptedClassesOn(selector.name);
       String getInterceptorName =
           namer.getInterceptorName(backend.getInterceptorMethod, classes);
 
@@ -2558,6 +2562,32 @@
     }
   }
 
+  /**
+   * If [:invokeOn:] has been compiled, emit all the possible selector names
+   * that are intercepted into the [:interceptedNames:] top-level
+   * variable. The implementation of [:invokeOn:] will use it to
+   * determine whether it should call the method with an extra
+   * parameter.
+   */
+  void emitInterceptedNames(CodeBuffer buffer) {
+    if (!compiler.enabledInvokeOn) return;
+    String name = backend.namer.getName(backend.interceptedNames);
+    jsAst.PropertyAccess property = js[isolateProperties][name];
+
+    int index = 0;
+    List<jsAst.ArrayElement> elements = backend.usedInterceptors.map(
+      (Selector selector) {
+        jsAst.Literal str = js.string(namer.invocationName(selector));
+        return new jsAst.ArrayElement(index++, str);
+      }).toList();
+    jsAst.ArrayInitializer array = new jsAst.ArrayInitializer(
+        backend.usedInterceptors.length,
+        elements);
+
+    buffer.add(jsAst.prettyPrint(property.assign(array), compiler));
+    buffer.add(N);
+  }
+
   void emitInitFunction(CodeBuffer buffer) {
     jsAst.Fun fun = js.fun([], [
       js['$isolateProperties = {}'],
@@ -2575,32 +2605,91 @@
     measure(() {
       computeNeededClasses();
 
+      // Compute the required type checks to know which classes need a
+      // 'is$' method.
+      computeRequiredTypeChecks();
+
       mainBuffer.add(GENERATED_BY);
       addComment(HOOKS_API_USAGE, mainBuffer);
       mainBuffer.add('function ${namer.isolateName}()$_{}\n');
       mainBuffer.add('init()$N$n');
-      // Shorten the code by using "$$" as temporary.
-      classesCollector = r"$$";
-      mainBuffer.add('var $classesCollector$_=$_{}$N');
       // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
       isolateProperties = namer.CURRENT_ISOLATE;
       mainBuffer.add(
           'var $isolateProperties$_=$_$isolatePropertiesName$N');
-      emitClasses(mainBuffer);
-      mainBuffer.add(boundClosureBuffer);
-      // Clear the buffer, so that we can reuse it for the native classes.
-      boundClosureBuffer.clear();
+
+      if (!regularClasses.isEmpty ||
+          !deferredClasses.isEmpty ||
+          !nativeClasses.isEmpty) {
+        // Shorten the code by using "$$" as temporary.
+        classesCollector = r"$$";
+        mainBuffer.add('var $classesCollector$_=$_{}$N$n');
+      }
+
+      // Emit native classes on [nativeBuffer].  As a side-effect,
+      // this will produce "bound closures" in [boundClosures].  The
+      // bound closures are JS AST nodes that add properties to $$
+      // [classesCollector].  The bound closures are not emitted until
+      // we have emitted all other classes (native or not).
+      final CodeBuffer nativeBuffer = new CodeBuffer();
+      if (!nativeClasses.isEmpty) {
+        addComment('Native classes', nativeBuffer);
+        for (ClassElement element in nativeClasses) {
+          nativeEmitter.generateNativeClass(element);
+        }
+        nativeEmitter.assembleCode(nativeBuffer);
+      }
+
+      // Might also create boundClosures.
+      if (!regularClasses.isEmpty) {
+        addComment('Classes', mainBuffer);
+        for (ClassElement element in regularClasses) {
+          generateClass(element, mainBuffer);
+        }
+      }
+
+      // Might also create boundClosures.
+      if (!deferredClasses.isEmpty) {
+        emitDeferredPreambleWhenEmpty(deferredBuffer);
+        deferredBuffer.add('\$\$$_=$_{}$N');
+
+        for (ClassElement element in deferredClasses) {
+          generateClass(element, deferredBuffer);
+        }
+
+        deferredBuffer.add('$finishClassesName(\$\$,'
+                           '$_${namer.CURRENT_ISOLATE},'
+                           '$_$isolatePropertiesName)$N');
+        // Reset the map.
+        deferredBuffer.add("\$\$$_=${_}null$N$n");
+      }
+
+      emitClosureClassIfNeeded(mainBuffer);
+
+      // Now that we have emitted all classes, we know all the bound
+      // closures that will be needed.
+      for (jsAst.Node node in boundClosures) {
+        // TODO(ahe): Some of these can be deferred.
+        mainBuffer.add(jsAst.prettyPrint(node, compiler));
+        mainBuffer.add("$N$n");
+      }
+
+      emitFinishClassesInvocationIfNecessary(mainBuffer);
+
+      // After this assignment we will produce invalid JavaScript code if we use
+      // the classesCollector variable.
+      classesCollector = 'classesCollector should not be used from now on';
+
       emitStaticFunctions(mainBuffer);
       emitStaticFunctionGetters(mainBuffer);
-      // We need to finish the classes before we construct compile time
-      // constants.
-      emitFinishClassesInvocationIfNecessary(mainBuffer);
-      emitRuntimeClassesAndTests(mainBuffer);
+
+      emitRuntimeTypeSupport(mainBuffer);
       emitCompileTimeConstants(mainBuffer);
       // Static field initializations require the classes and compile-time
       // constants to be set up.
       emitStaticNonFinalFieldInitializations(mainBuffer);
       emitOneShotInterceptors(mainBuffer);
+      emitInterceptedNames(mainBuffer);
       emitGetInterceptorMethods(mainBuffer);
       emitLazilyInitializedStaticFields(mainBuffer);
 
@@ -2608,19 +2697,13 @@
       // The following code should not use the short-hand for the
       // initialStatics.
       mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N');
-      if (!boundClosureBuffer.isEmpty) {
-        mainBuffer.add(boundClosureBuffer);
-        emitFinishClassesInvocationIfNecessary(mainBuffer);
-      }
-      // After this assignment we will produce invalid JavaScript code if we use
-      // the classesCollector variable.
-      classesCollector = 'classesCollector should not be used from now on';
 
       emitFinishIsolateConstructorInvocation(mainBuffer);
       mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_='
                      '${_}new ${namer.isolateName}()$N');
 
-      nativeEmitter.assembleCode(mainBuffer);
+      mainBuffer.add(nativeBuffer);
+
       emitMain(mainBuffer);
       emitInitFunction(mainBuffer);
       compiler.assembledCode = mainBuffer.getText();
@@ -2641,13 +2724,7 @@
   void emitDeferredCode(CodeBuffer buffer) {
     if (buffer.isEmpty) return;
 
-    if (needsDefineClass) {
-      buffer.add('$finishClassesName(\$\$,'
-                 '$_${namer.CURRENT_ISOLATE},'
-                 '$_$isolatePropertiesName)$N');
-      // Reset the map.
-      buffer.add("\$\$$_=$_{}$N");
-    }
+    buffer.add(n);
 
     buffer.add('${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N');
 
@@ -2660,9 +2737,9 @@
 
   void emitDeferredPreambleWhenEmpty(CodeBuffer buffer) {
     if (!buffer.isEmpty) return;
-    final classesCollector = r"$$";
 
-    buffer.add('$classesCollector$_=$_{}$N');
+    buffer.add(GENERATED_BY);
+
     buffer.add('var old${namer.CURRENT_ISOLATE}$_='
                '$_${namer.CURRENT_ISOLATE}$N');
 
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
index 06d5d01..52a237c 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter_no_eval.dart
@@ -10,85 +10,12 @@
                         bool generateSourceMap)
       : super(compiler, namer, generateSourceMap);
 
-  String get generateGetterSetterFunction {
-    return """
-function() {
-  throw 'Internal Error: no dynamic generation of getters and setters allowed';
-}""";
-  }
+  bool get getterAndSetterCanBeImplementedByFieldSpec => false;
 
-  String get defineClassFunction {
-    return """
-function(cls, constructor, prototype) {
-  constructor.prototype = prototype;
-  constructor.builtin\$cls = cls;
-  return constructor;
-}""";
-  }
-
-  String get protoSupportCheck {
-    // We don't modify the prototypes in CSP mode. Therefore we can have an
-    // easier prototype-check.
-    return 'var $supportsProtoName = !!{}.__proto__;\n';
-  }
-
-  String get finishIsolateConstructorFunction {
-    // We replace the old Isolate function with a new one that initializes
-    // all its field with the initial (and often final) value of all globals.
-    //
-    // We also copy over old values like the prototype, and the
-    // isolateProperties themselves.
-    return """
-function(oldIsolate) {
-  var isolateProperties = oldIsolate.${namer.isolatePropertiesName};
-  function Isolate() {
-    for (var staticName in isolateProperties) {
-      if (Object.prototype.hasOwnProperty.call(isolateProperties, staticName)) {
-        this[staticName] = isolateProperties[staticName];
-      }
+  void emitSuper(String superName, ClassBuilder builder) {
+    if (superName != '') {
+      builder.addProperty('super', js.string(superName));
     }
-    // Use the newly created object as prototype. In Chrome this creates a
-    // hidden class for the object and makes sure it is fast to access.
-    function ForceEfficientMap() {}
-    ForceEfficientMap.prototype = this;
-    new ForceEfficientMap;
-  }
-  Isolate.prototype = oldIsolate.prototype;
-  Isolate.prototype.constructor = Isolate;
-  Isolate.${namer.isolatePropertiesName} = isolateProperties;
-  return Isolate;
-}""";
-  }
-
-  String get lazyInitializerFunction {
-    return """
-function(prototype, staticName, fieldName, getterName, lazyValue, getter) {
-$lazyInitializerLogic
-}""";
-  }
-
-  js.Expression buildLazyInitializedGetter(VariableElement element) {
-    String isolate = namer.CURRENT_ISOLATE;
-    return js.fun([],
-        js.block1(
-            js.return_(
-                js.fieldAccess(js.use(isolate), namer.getName(element)))));
-  }
-
-  js.Expression buildConstructor(String mangledName, List<String> fieldNames) {
-    return new js.NamedFunction(
-        new js.VariableDeclaration(mangledName),
-        new js.Fun(
-            fieldNames
-                .map((fieldName) => new js.Parameter(fieldName))
-                .toList(),
-            new js.Block(
-                fieldNames.map((fieldName) =>
-                    new js.ExpressionStatement(
-                        new js.Assignment(
-                            new js.This().dot(fieldName),
-                            new js.VariableUse(fieldName))))
-                    .toList())));
   }
 
   void emitBoundClosureClassHeader(String mangledName,
@@ -96,7 +23,16 @@
                                    List<String> fieldNames,
                                    ClassBuilder builder) {
     builder.addProperty('', buildConstructor(mangledName, fieldNames));
-    builder.addProperty('super', js.string(superName));
+    emitSuper(superName, builder);
+  }
+
+
+  void emitClassFields(ClassElement classElement,
+                       ClassBuilder builder,
+                       { String superClass: "",
+                         bool classIsNative: false }) {
+    // Class fields are dynamically generated so they have to be
+    // emitted using getters and setters instead.
   }
 
   void emitClassConstructor(ClassElement classElement, ClassBuilder builder) {
@@ -118,21 +54,80 @@
       fields.add(name);
     });
     String constructorName = namer.safeName(classElement.name.slowToString());
-
     builder.addProperty('', buildConstructor(constructorName, fields));
   }
 
-  void emitSuper(String superName, ClassBuilder builder) {
-    if (superName != '') {
-      builder.addProperty('super', js.string(superName));
-    }
+  List get defineClassFunction {
+    return [new jsAst.FunctionDeclaration(
+        new jsAst.VariableDeclaration('defineClass'),
+        js.fun(['cls', 'constructor', 'prototype'],
+               [js[r'constructor.prototype = prototype'],
+                js[r'constructor.builtin$cls = cls'],
+                js.return_('constructor')]))];
   }
 
-  void emitClassFields(ClassElement classElement,
-                       ClassBuilder builder,
-                       { String superClass: "",
-                         bool classIsNative: false}) {
+  List buildProtoSupportCheck() {
+    // We don't modify the prototypes in CSP mode. Therefore we can have an
+    // easier prototype-check.
+    return [js['var $supportsProtoName = !(!({}.__proto__))']];
   }
 
-  bool get getterAndSetterCanBeImplementedByFieldSpec => false;
+  jsAst.Expression buildConstructor(String mangledName,
+                                    List<String> fieldNames) {
+    return new jsAst.NamedFunction(
+        new jsAst.VariableDeclaration(mangledName),
+        js.fun(fieldNames, fieldNames.map(
+            (name) => js['this.$name = $name']).toList()));
+  }
+
+  jsAst.FunctionDeclaration get generateAccessorFunction {
+    String message =
+        'Internal error: no dynamic generation of accessors allowed.';
+    return new jsAst.FunctionDeclaration(
+        new jsAst.VariableDeclaration('generateAccessor'),
+        js.fun([], new jsAst.Throw(js.string(message))));
+  }
+
+  jsAst.Expression buildLazyInitializedGetter(VariableElement element) {
+    String isolate = namer.CURRENT_ISOLATE;
+    String name = namer.getName(element);
+    return js.fun([], js.return_(js['$isolate.$name']));
+  }
+
+  jsAst.Fun get lazyInitializerFunction {
+    // function(prototype, staticName, fieldName,
+    //          getterName, lazyValue, getter) {
+    var parameters = <String>['prototype', 'staticName', 'fieldName',
+                              'getterName', 'lazyValue', 'getter'];
+    return js.fun(parameters, addLazyInitializerLogic());
+  }
+
+  jsAst.Fun get finishIsolateConstructorFunction {
+    // We replace the old Isolate function with a new one that initializes
+    // all its fields with the initial (and often final) value of all globals.
+    //
+    // We also copy over old values like the prototype, and the
+    // isolateProperties themselves.
+    return js.fun('oldIsolate', [
+      js['var isolateProperties = oldIsolate.${namer.isolatePropertiesName}'],
+      new jsAst.FunctionDeclaration(
+        new jsAst.VariableDeclaration('Isolate'),
+          js.fun([], [
+            js['var hasOwnProperty = Object.prototype.hasOwnProperty'],
+            js.forIn('staticName', 'isolateProperties',
+              js.if_(js['hasOwnProperty.call(isolateProperties, staticName)'],
+                js['this[staticName] = isolateProperties[staticName]'])),
+            // Use the newly created object as prototype. In Chrome,
+            // this creates a hidden class for the object and makes
+            // sure it is fast to access.
+            new jsAst.FunctionDeclaration(
+              new jsAst.VariableDeclaration('ForceEfficientMap'),
+              js.fun([], [])),
+            js['ForceEfficientMap.prototype = this'],
+            js['new ForceEfficientMap()']])),
+      js['Isolate.prototype = oldIsolate.prototype'],
+      js['Isolate.prototype.constructor = Isolate'],
+      js['Isolate.${namer.isolatePropertiesName} = isolateProperties'],
+      js.return_('Isolate')]);
+  }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
index 8a2f2b8..77ed6f4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -21,6 +21,7 @@
 import '../source_map_builder.dart';
 import '../ssa/ssa.dart' hide js; // TODO(ahe): VM bug, see above.
 import '../tree/tree.dart';
+import '../types/types.dart';
 import '../universe/universe.dart' hide js; // TODO(ahe): VM bug, see above.
 import '../util/characters.dart';
 import '../util/util.dart';
@@ -29,8 +30,7 @@
 part 'constant_emitter.dart';
 part 'constant_system_javascript.dart';
 part 'emitter.dart';
-// TODO(8522): Restore --disallow-unsafe-eval.
-// part 'emitter_no_eval.dart';
+part 'emitter_no_eval.dart';
 part 'minify_namer.dart';
 part 'namer.dart';
 part 'native_emitter.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
index 547a3e4..e19a442 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/minify_namer.dart
@@ -94,7 +94,7 @@
         suggestedInstanceNames,
         usedInstanceNames,
         const <String>[
-            r'$add', r'add$1', r'box_0', r'charCodeAt$1', r'constructor',
+            r'$add', r'add$1', r'box_0', r'codeUnitAt$1', r'constructor',
             r'current', r'$defineNativeClass', r'$eq', r'$ne',
             r'getPrototypeOf', r'hasOwnProperty', r'$index', r'$indexSet',
             r'$isJavaScriptIndexingBehavior', r'$isolateProperties',
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index 6500fc3..8e389bf 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -290,7 +290,7 @@
       getDirectSubclasses(cls).forEach(visit);
       classes.add(cls);
     }
-    classesWithDynamicDispatch.forEach(visit);
+    Elements.sortedByPosition(classesWithDynamicDispatch).forEach(visit);
 
     List<ClassElement> preorderDispatchClasses = classes.where(
         (cls) => !getDirectSubclasses(cls).isEmpty &&
@@ -484,7 +484,9 @@
     emitIsChecks();
 
     jsAst.Expression makeCallOnThis(String functionName) {
-      return js.fun([], js.return_(js['$functionName(this)']));
+      // Because we know the function is intercepted, we need an extra
+      // parameter.
+      return js.fun(['_'], js.return_(js['$functionName(this)']));
     }
 
     // In order to have the toString method on every native class,
@@ -501,7 +503,9 @@
     // Same as above, but for operator==.
     String equalsName = backend.namer.publicInstanceMethodNameByArity(
         const SourceString('=='), 1);
-    addProperty(equalsName, js.fun(['a'],
+    // Because we know the function is intercepted, we need an extra
+    // parameter.
+    addProperty(equalsName, js.fun(['_', 'a'],
         js.return_(js['this === a'])));
 
     // If the native emitter has been asked to take care of the
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
index bfad207..e893075 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -62,6 +62,16 @@
         }
       }
     }
+
+    // TODO(karlklose): remove this temporary fix: we need to add the classes
+    // used in substitutions to addArguments.
+    allArguments.addAll([compiler.intClass,
+                         compiler.boolClass,
+                         compiler.numClass,
+                         compiler.doubleClass,
+                         compiler.stringClass,
+                         compiler.listClass]);
+
     return cachedRequiredChecks = requiredChecks;
   }
 
@@ -294,4 +304,14 @@
   }
 
   Iterator<ClassElement> get iterator => map.keys.iterator;
+
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    for (ClassElement holder in this) {
+      for (ClassElement check in [holder]) {
+        sb.add('${holder.name.slowToString()}.${check.name.slowToString()}, ');
+      }
+    }
+    return '[$sb]';
+  }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart
index cd63a24..ade4c99 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/async_patch.dart
@@ -7,34 +7,15 @@
 import 'dart:_isolate_helper' show IsolateNatives, TimerImpl;
 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
 
-typedef void _TimerCallback0();
-typedef void _TimerCallback1(Timer timer);
-
 patch class Timer {
-  patch factory Timer(var duration, var callback) {
-    // TODO(floitsch): remove these checks when we remove the deprecated
-    // millisecond argument and the 1-argument callback. Also remove the
-    // int-test below.
-    if (callback is! _TimerCallback0 && callback is! _TimerCallback1) {
-      throw new ArgumentError(callback);
-    }
-    int milliseconds = duration is int ? duration : duration.inMilliseconds;
+  patch factory Timer(Duration duration, void callback()) {
+    int milliseconds = duration.inMilliseconds;
     if (milliseconds < 0) milliseconds = 0;
-    Timer timer;
-    _TimerCallback0 zeroArgumentCallback =
-        callback is _TimerCallback0 ? callback : () => callback(timer);
-    timer = new TimerImpl(milliseconds, zeroArgumentCallback);
-    return timer;
+    return new TimerImpl(milliseconds, callback);
   }
 
-  /**
-   * Creates a new repeating timer. The [callback] is invoked every
-   * [milliseconds] millisecond until cancelled.
-   */
-  patch factory Timer.repeating(var duration, void callback(Timer timer)) {
-    // TODO(floitsch): remove this check when we remove the deprecated
-    // millisecond argument.
-    int milliseconds = duration is int ? duration : duration.inMilliseconds;
+  patch factory Timer.repeating(Duration duration, void callback(Timer timer)) {
+    int milliseconds = duration.inMilliseconds;
     if (milliseconds < 0) milliseconds = 0;
     return new TimerImpl.repeating(milliseconds, callback);
   }
@@ -78,7 +59,7 @@
     JS('', '#.addEventListener("load", #, false)', script, onLoad);
     JS('', 'document.body.appendChild(#)', script);
   } else if (JS('String', 'typeof load') == 'function') {
-    new Timer(0, (_) {
+    Timer.run(() {
       JS('void', 'load(#)', uri);
       completer.complete(true);
     });
diff --git a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
index fad1d02..1da20f6 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/core_patch.dart
@@ -11,8 +11,7 @@
                               JSSyntaxRegExp,
                               Primitives,
                               TypeImpl,
-                              stringJoinUnchecked,
-                              JsStringBuffer;
+                              stringJoinUnchecked;
 
 patch void print(var object) {
   Primitives.printString(object.toString());
@@ -166,16 +165,17 @@
 
 // Patch for List implementation.
 patch class List<E> {
-  patch factory List([int length = 0]) {
-    // Explicit type test is necessary to protect Primitives.newGrowableList in
+  patch factory List([int length]) {
+    if (!?length) return Primitives.newGrowableList(0);
+    // Explicit type test is necessary to protect Primitives.newFixedList in
     // unchecked mode.
     if ((length is !int) || (length < 0)) {
       throw new ArgumentError("Length must be a positive integer: $length.");
     }
-    return Primitives.newGrowableList(length);
+    return Primitives.newFixedList(length);
   }
 
-  patch factory List.fixedLength(int length, {E fill: null}) {
+  patch factory List.filled(int length, E fill) {
     // Explicit type test is necessary to protect Primitives.newFixedList in
     // unchecked mode.
     if ((length is !int) || (length < 0)) {
@@ -287,3 +287,13 @@
   }
 }
 
+patch class StackTrace {
+  patch String get fullStackTrace {
+    throw new UnsupportedError('fullStackTrace');
+  }
+
+  patch String get stackTrace {
+    throw new UnsupportedError('stackTrace');
+  }
+}
+
diff --git a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
index 6a32f17..5676e1d 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/interceptors.dart
@@ -16,7 +16,6 @@
                               checkNum,
                               checkString,
                               getRuntimeTypeString,
-                              listInsertRange,
                               regExpGetNative,
                               stringContainsUnchecked,
                               stringLastIndexOfUnchecked,
@@ -31,14 +30,6 @@
 part 'js_string.dart';
 
 /**
- * The interceptor class for all non-primitive objects. All its
- * members are synthethized by the compiler's emitter.
- */
-class ObjectInterceptor {
-  const ObjectInterceptor();
-}
-
-/**
  * Get the interceptor for [object]. Called by the compiler when it needs
  * to emit a call to an intercepted method, that is a method that is
  * defined in an interceptor class.
@@ -50,6 +41,13 @@
 }
 
 /**
+ * If [InvocationMirror.invokeOn] is being used, this variable
+ * contains a JavaScript array with the names of methods that are
+ * intercepted.
+ */
+var interceptedNames;
+
+/**
  * The interceptor class for tear-off static methods. Unlike
  * tear-off instance methods, tear-off static methods are just the JS
  * function, and methods inherited from Object must therefore be
diff --git a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
index 00ed800..ed10807 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/io_patch.dart
@@ -54,31 +54,31 @@
 }
 
 patch class _File {
-  patch static _exists(String name) {
+  patch static _exists(String path) {
     throw new UnsupportedError("File._exists");
   }
-  patch static _create(String name) {
+  patch static _create(String path) {
     throw new UnsupportedError("File._create");
   }
-  patch static _delete(String name) {
+  patch static _delete(String path) {
     throw new UnsupportedError("File._delete");
   }
-  patch static _directory(String name) {
+  patch static _directory(String path) {
     throw new UnsupportedError("File._directory");
   }
-  patch static _lengthFromName(String name) {
-    throw new UnsupportedError("File._lengthFromName");
+  patch static _lengthFromPath(String path) {
+    throw new UnsupportedError("File._lengthFromPath");
   }
-  patch static _lastModified(String name) {
+  patch static _lastModified(String path) {
     throw new UnsupportedError("File._lastModified");
   }
-  patch static _open(String name, int mode) {
+  patch static _open(String path, int mode) {
     throw new UnsupportedError("File._open");
   }
   patch static int _openStdio(int fd) {
     throw new UnsupportedError("File._openStdio");
   }
-  patch static _fullPath(String name) {
+  patch static _fullPath(String path) {
     throw new UnsupportedError("File._fullPath");
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart b/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
index 1c1e492..9b73f40 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_array.dart
@@ -69,7 +69,7 @@
     return IterableMixinWorkaround.expand(this, f);
   }
 
-  void addAll(Collection<E> collection) {
+  void addAll(Iterable<E> collection) {
     for (E e in collection) {
       this.add(e);
     }
@@ -155,7 +155,31 @@
   }
 
   void insertRange(int start, int length, [E initialValue]) {
-    return listInsertRange(this, start, length, initialValue);
+    checkGrowable(this, 'insertRange');
+    if (length == 0) {
+      return;
+    }
+    if (length is !int) throw new ArgumentError(length);
+    if (length < 0) throw new ArgumentError(length);
+    if (start is !int) throw new ArgumentError(start);
+
+    var receiver = this;
+    var receiverLength = receiver.length;
+    if (start < 0 || start > receiverLength) {
+      throw new RangeError.value(start);
+    }
+    receiver.length = receiverLength + length;
+    Arrays.copy(receiver,
+                start,
+                receiver,
+                start + length,
+                receiverLength - start);
+    if (initialValue != null) {
+      for (int i = start; i < start + length; i++) {
+        receiver[i] = initialValue;
+      }
+    }
+    receiver.length = receiverLength + length;
   }
 
   E get first {
@@ -205,21 +229,7 @@
 
   void setRange(int start, int length, List<E> from, [int startFrom = 0]) {
     checkMutable(this, 'set range');
-    if (length == 0) return;
-    checkNull(start); // TODO(ahe): This is not specified but co19 tests it.
-    checkNull(length); // TODO(ahe): This is not specified but co19 tests it.
-    checkNull(from); // TODO(ahe): This is not specified but co19 tests it.
-    checkNull(startFrom); // TODO(ahe): This is not specified but co19 tests it.
-    if (start is !int) throw new ArgumentError(start);
-    if (length is !int) throw new ArgumentError(length);
-    if (startFrom is !int) throw new ArgumentError(startFrom);
-    if (length < 0) throw new ArgumentError(length);
-    if (start < 0) throw new RangeError.value(start);
-    if (start + length > this.length) {
-      throw new RangeError.value(start + length);
-    }
-
-    Arrays.copy(from, startFrom, this, start, length);
+    IterableMixinWorkaround.setRangeList(this, start, length, from, startFrom);
   }
 
   bool any(bool f(E element)) => IterableMixinWorkaround.any(this, f);
@@ -234,13 +244,11 @@
   }
 
   int indexOf(E element, [int start = 0]) {
-    if (start is !int) throw new ArgumentError(start);
-    return Arrays.indexOf(this, element, start, length);
+    return IterableMixinWorkaround.indexOfList(this, element, start);
   }
 
   int lastIndexOf(E element, [int start]) {
-    if (start == null) start = this.length - 1;
-    return Arrays.lastIndexOf(this, element, start);
+    return IterableMixinWorkaround.lastIndexOfList(this, element, start);
   }
 
   bool contains(E other) {
@@ -254,7 +262,8 @@
 
   String toString() => Collections.collectionToString(this);
 
-  List<E> toList() => new List<E>.from(this);
+  List<E> toList({ bool growable: true }) =>
+      new List<E>.from(this, growable: growable);
 
   Set<E> toSet() => new Set<E>.from(this);
 
@@ -288,4 +297,8 @@
     if (index >= length || index < 0) throw new RangeError.value(index);
     JS('void', r'#[#] = #', this, index, value);
   }
+
+  Map<int, E> asMap() {
+    return IterableMixinWorkaround.asMapList(this);
+  }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
index 19f6ce8..f9a3af7 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_helper.dart
@@ -15,7 +15,8 @@
                                    JS_HAS_EQUALS,
                                    RAW_DART_FUNCTION_REF,
                                    UNINTERCEPTED;
-import 'dart:_interceptors' show getInterceptor;
+import 'dart:_interceptors' show getInterceptor,
+                                 interceptedNames;
 
 part 'constant_map.dart';
 part 'native_helper.dart';
@@ -23,7 +24,7 @@
 part 'string_helper.dart';
 
 bool isJsArray(var value) {
-  return value != null && JS('bool', r'#.constructor === Array', value);
+  return value != null && JS('bool', r'(#.constructor === Array)', value);
 }
 
 checkMutable(list, reason) {
@@ -98,13 +99,16 @@
     return map;
   }
 
-  static final _objectInterceptor = getInterceptor(new Object());
   invokeOn(Object object) {
     var interceptor = getInterceptor(object);
     var receiver = object;
     var name = _internalName;
     var arguments = _arguments;
-    if (identical(interceptor, _objectInterceptor)) {
+    // TODO(ngeoffray): If this functionality ever become performance
+    // critical, we might want to dynamically change [interceptedNames]
+    // to be a JavaScript object with intercepted names as property
+    // instead of a JavaScript array.
+    if (JS('int', '#.indexOf(#)', interceptedNames, name) == -1) {
       if (!isJsArray(arguments)) arguments = new List.from(arguments);
     } else {
       arguments = [object]..addAll(arguments);
@@ -157,7 +161,7 @@
     // This is somewhat nasty, but we don't want to drag in a bunch of
     // dependencies to handle a situation that cannot happen. So we
     // avoid using Dart [:throw:] and Dart [toString].
-    JS('void', "throw 'Unable to print message: ' + String(#)", string);
+    JS('void', 'throw "Unable to print message: " + String(#)', string);
   }
 
   static void _throwFormatException(String string) {
@@ -210,19 +214,19 @@
           if (radix <= 10) {
             // Allow all digits less than the radix. For example 0, 1, 2 for
             // radix 3.
-            // "0".charCodeAt(0) + radix - 1;
+            // "0".codeUnitAt(0) + radix - 1;
             maxCharCode = 0x30 + radix - 1;
           } else {
             // Characters are located after the digits in ASCII. Therefore we
             // only check for the character code. The regexp above made already
             // sure that the string does not contain anything but digits or
             // characters.
-            // "0".charCodeAt(0) + radix - 1;
+            // "0".codeUnitAt(0) + radix - 1;
             maxCharCode = 0x61 + radix - 10 - 1;
           }
           String digitsPart = match[digitsIndex].toLowerCase();
           for (int i = 0; i < digitsPart.length; i++) {
-            if (digitsPart.charCodeAt(i) > maxCharCode) {
+            if (digitsPart.codeUnitAt(i) > maxCharCode) {
               return handleError(source);
             }
           }
@@ -255,7 +259,7 @@
     return result;
   }
 
-  /** [: r"$".charCodeAt(0) :] */
+  /** [: r"$".codeUnitAt(0) :] */
   static const int DOLLAR_CHAR_VALUE = 36;
 
   static String objectTypeName(Object object) {
@@ -270,7 +274,7 @@
     }
     // TODO(kasperl): If the namer gave us a fresh global name, we may
     // want to remove the numeric suffix that makes it unique too.
-    if (identical(name.charCodeAt(0), DOLLAR_CHAR_VALUE)) name = name.substring(1);
+    if (identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) name = name.substring(1);
     return name;
   }
 
@@ -557,32 +561,6 @@
   throw new RangeError.value(index);
 }
 
-listInsertRange(receiver, start, length, initialValue) {
-  if (length == 0) {
-    return;
-  }
-  if (length is !int) throw new ArgumentError(length);
-  if (length < 0) throw new ArgumentError(length);
-  if (start is !int) throw new ArgumentError(start);
-
-  var receiverLength = JS('num', r'#.length', receiver);
-  if (start < 0 || start > receiverLength) {
-    throw new RangeError.value(start);
-  }
-  receiver.length = receiverLength + length;
-  Arrays.copy(receiver,
-              start,
-              receiver,
-              start + length,
-              receiverLength - start);
-  if (initialValue != null) {
-    for (int i = start; i < start + length; i++) {
-      receiver[i] = initialValue;
-    }
-  }
-  receiver.length = receiverLength + length;
-}
-
 stringLastIndexOfUnchecked(receiver, element, start)
   => JS('int', r'#.lastIndexOf(#, #)', receiver, element, start);
 
@@ -807,6 +785,7 @@
     if (message is String) {
       if (message == 'null has no properties' ||
           message == "'null' is not an object" ||
+          message == "'undefined' is not an object" ||
           message.endsWith('is null') ||
           message.endsWith('is undefined') ||
           message.endsWith('is null or undefined') ||
@@ -845,7 +824,7 @@
 
   // Check for the Firefox specific stack overflow signal.
   if (JS('bool',
-         r"typeof InternalError == 'function' && # instanceof InternalError",
+         r'typeof InternalError == "function" && # instanceof InternalError',
          ex)) {
     if (message is String && message == 'too much recursion') {
       return new StackOverflowError();
@@ -914,23 +893,20 @@
   if (closure == null) return null;
   var function = JS('var', r'#.$identity', closure);
   if (JS('bool', r'!!#', function)) return function;
-  // By fetching the current isolate before creating the JavaScript
-  // function, we prevent the compiler from inlining its use in
-  // the JavaScript function below (the compiler generates code for
-  // fetching the isolate before creating the JavaScript function).
-  // If it was inlined, the JavaScript function would not get the
-  // current isolate, but the one that is active when the callback
-  // executes.
-  var currentIsolate = JS_CURRENT_ISOLATE();
 
   // We use $0 and $1 to not clash with variable names used by the
   // compiler and/or minifier.
-  function = JS("var",
-                r"""function($0, $1) { return #(#, #, #, $0, $1); }""",
-                DART_CLOSURE_TO_JS(invokeClosure),
+  function = JS('var',
+                r'(function ($2, $3) {'
+                    r' return function($0, $1) { '
+                        r'return $3(#, $2, #, $0, $1) }})(#, #)',
                 closure,
+                arity,
+                // Capture the current isolate now.  Remember that "#"
+                // in JS is simply textual substitution of compiled
+                // expressions.
                 JS_CURRENT_ISOLATE(),
-                arity);
+                DART_CLOSURE_TO_JS(invokeClosure));
 
   JS('void', r'#.$identity = #', closure, function);
   return function;
@@ -1494,7 +1470,7 @@
   return "$className<${joinArguments(typeInfo, 0)}>";
 }
 
-bool isJsFunction(var o) => JS('bool', r"typeof # == 'function'", o);
+bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
 
 Object invoke(function, arguments) {
   return JS('var', r'#.apply(null, #)', function, arguments);
@@ -1538,23 +1514,57 @@
   return true;
 }
 
-getArguments(var type) => JS('var', r'#.slice(1)', type);
+getArguments(var type) {
+  return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
+}
 
 getField(var object, var name) => JS('var', r'#[#]', object, name);
 
 /**
+ * Tests whether the Dart object [o] is a subtype of the runtime type
+ * representation [t], which is a type representation as described in the
+ * comment on [isSubtype].
+ */
+bool objectIsSubtype(Object o, var t) {
+  if (JS('bool', '# == null', o) || JS('bool', '# == null', t)) return true;
+  // Get the runtime type information from the object here, because we may
+  // overwrite o with the interceptor below.
+  var rti = getRuntimeTypeInfo(o);
+  // Check for native objects and use the interceptor instead of the object.
+  o = getInterceptor(o);
+  // We can use the object as its own type representation because we install
+  // the subtype flags and the substitution on the prototype, so they are
+  // properties of the object in JS.
+  var type;
+  if (JS('bool', '# != null', rti)) {
+    // If the type has type variables (that is, [:rti != null:]), make a copy of
+    // the type arguments and insert [o] in the first position to create a
+    // compound type representation.
+    type = JS('List', '#.slice()', rti);
+    JS('', '#.splice(0, 0, #)', type, o);
+  } else {
+    // Use the object as representation of the raw type.
+    type = o;
+  }
+  return isSubtype(type, t);
+}
+
+
+/**
  * Check whether the type represented by [s] is a subtype of the type
  * represented by [t].
  *
  * Type representations can be:
  *  1) a JavaScript constructor for a class C: the represented type is the raw
  *     type C.
- *  2) a JavaScript object: this represents a class for which there is no
+ *  2) a Dart object: this is the interceptor instance for a native type.
+ *  3) a JavaScript object: this represents a class for which there is no
  *     JavaScript constructor, because it is only used in type arguments or it
  *     is native. The represented type is the raw type of this class.
- *  3) a JavaScript array: the first entry is of type 1 or 2 and identifies the
- *     class of the type and the rest of the array are the type arguments.
- *  4) [:null:]: the dynamic type.
+ *  4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
+ *     subtyping flags and the substitution of the type and the rest of the
+ *     array are the type arguments.
+ *  5) [:null:]: the dynamic type.
  */
 bool isSubtype(var s, var t) {
   // If either type is dynamic, [s] is a subtype of [t].
@@ -1568,15 +1578,20 @@
   // Check for a subtyping flag.
   var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
   if (getField(typeOfS, test) == null) return false;
-  // The class of [s] is a subclass of the class of [t]. If either of the types
-  // is raw, [s] is a subtype of [t].
-  if (!isJsArray(s) || !isJsArray(t)) return true;
   // Get the necessary substitution of the type arguments, if there is one.
   var substitution;
   if (JS('bool', '# !== #', typeOfT, typeOfS)) {
     var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
     substitution = getField(typeOfS, field);
   }
+  // The class of [s] is a subclass of the class of [t].  If [s] has no type
+  // arguments and no substitution, it is used as raw type.  If [t] has no
+  // type arguments, it used as a raw type.  In both cases, [s] is a subtype
+  // of [t].
+  if ((!isJsArray(s) && JS('bool', '# == null', substitution)) ||
+      !isJsArray(t)) {
+    return true;
+  }
   // Recursively check the type arguments.
   return checkArguments(substitution, getArguments(s), getArguments(t));
 }
diff --git a/sdk/lib/_internal/compiler/implementation/lib/js_string.dart b/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
index 6d81f32..c271e16 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/js_string.dart
@@ -13,8 +13,6 @@
 class JSString implements String {
   const JSString();
 
-  int charCodeAt(index) => codeUnitAt(index);
-
   int codeUnitAt(int index) {
     if (index is !num) throw new ArgumentError(index);
     if (index < 0) throw new RangeError.value(index);
@@ -71,10 +69,6 @@
     }
   }
 
-  List<String> splitChars() {
-    return JS('=List', r'#.split("")', this);
-  }
-
   bool startsWith(String other) {
     checkString(other);
     int otherLength = other.length;
@@ -141,15 +135,7 @@
     return JS('String', r'#.trim()', this);
   }
 
-  List<int> get charCodes  {
-    List<int> result = new List<int>.fixedLength(length);
-    for (int i = 0; i < length; i++) {
-      result[i] = JS('int', '#.charCodeAt(#)', this, i);
-    }
-    return result;
-  }
-
-  Iterable<int> get codeUnits => new CodeUnits(this);
+  List<int> get codeUnits => new CodeUnits(this);
 
   Runes get runes => new Runes(this);
 
diff --git a/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart
new file mode 100644
index 0000000..01cce1a
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart
@@ -0,0 +1,91 @@
+// 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.
+
+// Patch file for dart:json library.
+
+import 'dart:_foreign_helper' show JS;
+
+/**
+ * Parses [json] and builds the corresponding parsed JSON value.
+ *
+ * Parsed JSON values are of the types [num], [String], [bool], [Null],
+ * [List]s of parsed JSON values or [Map]s from [String] to parsed
+ * JSON values.
+ *
+ * The optional [reviver] function, if provided, is called once for each object
+ * or list property parsed. The arguments are the property name ([String]) or
+ * list index ([int]), and the value is the parsed value.  The return value of
+ * the reviver will be used as the value of that property instead of the parsed
+ * value.  The top level value is passed to the reviver with the empty string as
+ * a key.
+ *
+ * Throws [FormatException] if the input is not valid JSON text.
+ */
+patch parse(String json, [reviver(var key, var value)]) {
+  if (json is! String) throw new ArgumentError(json);
+
+  var parsed;
+  try {
+    parsed = JS('=Object|=List|Null|bool|num|String', 'JSON.parse(#)', json);
+  } catch (e) {
+    throw new FormatException(JS('String', 'String(#)', e));
+  }
+
+  return _convertJsonToDart(parsed, reviver);
+}
+
+/**
+ * Walks the raw JavaScript value [json], replacing JavaScript Objects with
+ * Maps. [json] is expected to be freshly allocated so elements can be replaced
+ * in-place.
+ */
+_convertJsonToDart(json, reviver(key, value)) {
+
+  var revive = reviver == null ? (key, value) => value : reviver;
+
+  walk(e) {
+    // JavaScript null, string, number, bool are in the correct representation.
+    if (JS('bool', '# == null', e) || JS('bool', 'typeof # != "object"', e)) {
+      return e;
+    }
+
+    // This test is needed to avoid identifing '{"__proto__":[]}' as an Array.
+    // TODO(sra): Replace this test with cheaper '#.constructor === Array' when
+    // bug 621 below is fixed.
+    if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) {
+      var list = JS('=List', '#', e);  // Teach compiler the type is known.
+      // In-place update of the elements since JS Array is a Dart List.
+      for (int i = 0; i < list.length; i++) {
+        // Use JS indexing to avoid range checks.  We know this is the only
+        // reference to the list, but the compiler will likely never be able to
+        // tell that this instance of the list cannot have its length changed by
+        // the reviver even though it later will be passed to the reviver at the
+        // outer level.
+        var item = JS('', '#[#]', list, i);
+        JS('', '#[#]=#', list, i, revive(i, walk(item)));
+      }
+      return list;
+    }
+
+    // Otherwise it is a plain Object, so copy to a Map.
+    var keys = JS('=List', 'Object.keys(#)', e);
+    Map map = {};
+    for (int i = 0; i < keys.length; i++) {
+      String key = keys[i];
+      map[key] = revive(key, walk(JS('', '#[#]', e, key)));
+    }
+    // V8 has a bug with properties named "__proto__"
+    // https://code.google.com/p/v8/issues/detail?id=621
+    var proto = JS('', '#.__proto__', e);
+    // __proto__ can be undefined on IE9.
+    if (JS('bool',
+           'typeof # !== "undefined" && # !== Object.prototype',
+           proto, proto)) {
+      map['__proto__'] = revive('__proto__', walk(proto));
+    }
+    return map;
+  }
+
+  return revive('', walk(json));
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
index b62b0b5..bdd5d23 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/regexp_helper.dart
@@ -4,71 +4,73 @@
 
 part of _js_helper;
 
-List regExpExec(JSSyntaxRegExp regExp, String str) {
-  var nativeRegExp = regExpGetNative(regExp);
-  var result = JS('=List', r'#.exec(#)', nativeRegExp, str);
-  if (JS('bool', r'# == null', result)) return null;
-  return result;
-}
-
-bool regExpTest(JSSyntaxRegExp regExp, String str) {
-  var nativeRegExp = regExpGetNative(regExp);
-  return JS('bool', r'#.test(#)', nativeRegExp, str);
-}
-
-regExpGetNative(JSSyntaxRegExp regExp) {
-  var r = JS('var', r'#._re', regExp);
-  if (r == null) {
-    r = JS('var', r'#._re = #', regExp, regExpMakeNative(regExp));
-  }
-  return r;
-}
-
-regExpAttachGlobalNative(JSSyntaxRegExp regExp) {
-  JS('void', r'#._re = #', regExp, regExpMakeNative(regExp, global: true));
-}
-
-regExpMakeNative(JSSyntaxRegExp regExp, {bool global: false}) {
-  String pattern = regExp.pattern;
-  bool isMultiLine = regExp.isMultiLine;
-  bool isCaseSensitive = regExp.isCaseSensitive;
-  checkString(pattern);
-  StringBuffer sb = new StringBuffer();
-  if (isMultiLine) sb.add('m');
-  if (!isCaseSensitive) sb.add('i');
-  if (global) sb.add('g');
-  try {
-    return JS('var', r'new RegExp(#, #)', pattern, sb.toString());
-  } catch (e) {
-    throw new IllegalJSRegExpException(pattern,
-                                       JS('String', r'String(#)', e));
-  }
-}
-
-int regExpMatchStart(m) => JS('int', r'#.index', m);
+// Helper method used by internal libraries.
+regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;
 
 class JSSyntaxRegExp implements RegExp {
   final String _pattern;
   final bool _isMultiLine;
   final bool _isCaseSensitive;
+  var _nativeRegExp;
 
-  const JSSyntaxRegExp(String pattern,
-                       {bool multiLine: false,
-                        bool caseSensitive: true})
-      : _pattern = pattern,
-        _isMultiLine = multiLine,
-        _isCaseSensitive = caseSensitive;
+  JSSyntaxRegExp._internal(String pattern,
+                           bool multiLine,
+                           bool caseSensitive,
+                           bool global)
+      : _nativeRegExp = makeNative(pattern, multiLine, caseSensitive, global),
+        this._pattern = pattern,
+        this._isMultiLine = multiLine,
+        this._isCaseSensitive = caseSensitive;
+
+  JSSyntaxRegExp(String pattern,
+                 {bool multiLine: false,
+                  bool caseSensitive: true})
+      : this._internal(pattern, multiLine, caseSensitive, false);
+
+  JSSyntaxRegExp._globalVersionOf(JSSyntaxRegExp other)
+      : this._internal(other.pattern,
+                       other.isMultiLine,
+                       other.isCaseSensitive,
+                       true);
+
+  static makeNative(
+      String pattern, bool multiLine, bool caseSensitive, bool global) {
+    checkString(pattern);
+    String m = multiLine ? 'm' : '';
+    String i = caseSensitive ? '' : 'i';
+    String g = global ? 'g' : '';
+    // We're using the JavaScript's try catch instead of the Dart one
+    // to avoid dragging in Dart runtime support just because of using
+    // RegExp.
+    var regexp = JS('',
+        '(function() {'
+         'try {'
+          'return new RegExp(#, # + # + #);'
+         '} catch (e) {'
+           'return e;'
+         '}'
+        '})()', pattern, m, i, g);
+    if (JS('bool', '# instanceof RegExp', regexp)) return regexp;
+    // The returned value is the JavaScript exception. Turn it into a
+    // Dart exception.
+    String errorMessage = JS('String', r'String(#)', regexp);
+    throw new FormatException(
+        "Illegal RegExp pattern: $pattern, $errorMessage");
+  }
 
   Match firstMatch(String str) {
-    List<String> m = regExpExec(this, checkString(str));
+    List<String> m =
+        JS('=List|Null', r'#.exec(#)', _nativeRegExp, checkString(str));
     if (m == null) return null;
-    var matchStart = regExpMatchStart(m);
+    var matchStart = JS('int', r'#.index', m);
     // m.lastIndex only works with flag 'g'.
     var matchEnd = matchStart + m[0].length;
     return new _MatchImplementation(pattern, str, matchStart, matchEnd, m);
   }
 
-  bool hasMatch(String str) => regExpTest(this, checkString(str));
+  bool hasMatch(String str) {
+    return JS('bool', r'#.test(#)', _nativeRegExp, checkString(str));
+  }
 
   String stringMatch(String str) {
     var match = firstMatch(str);
@@ -83,17 +85,6 @@
   String get pattern => _pattern;
   bool get isMultiLine => _isMultiLine;
   bool get isCaseSensitive => _isCaseSensitive;
-
-  static JSSyntaxRegExp _globalVersionOf(JSSyntaxRegExp other) {
-    JSSyntaxRegExp re =
-        new JSSyntaxRegExp(other.pattern,
-                           multiLine: other.isMultiLine,
-                           caseSensitive: other.isCaseSensitive);
-    regExpAttachGlobalNative(re);
-    return re;
-  }
-
-  _getNative() => regExpGetNative(this);
 }
 
 class _MatchImplementation implements Match {
@@ -138,7 +129,7 @@
   Match _current;
 
   _AllMatchesIterator(JSSyntaxRegExp re, String this._str)
-    : _re = JSSyntaxRegExp._globalVersionOf(re);
+    : _re = new JSSyntaxRegExp._globalVersionOf(re);
 
   Match get current => _current;
 
diff --git a/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart
index 326b892..4106c98 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/scalarlist_patch.dart
@@ -128,3 +128,33 @@
     throw new UnsupportedError('Float64List.view');
   }
 }
+
+patch class Float32x4 {
+  patch factory Float32x4(double x, double y, double z, double w) {
+    throw new UnsupportedError('Float32x4');
+  }
+  patch factory Float32x4.zero() {
+    throw new UnsupportedError('Float32x4.zero');
+  }
+}
+
+patch class Uint32x4 {
+  patch factory Uint32x4(int x, int y, int z, int w) {
+    throw new UnsupportedError('Uint32x4');
+  }
+  patch factory Uint32x4.bool(bool x, bool y, bool z, bool w) {
+    throw new UnsupportedError('Uint32x4.bool');
+  }
+}
+
+
+patch class Float32x4List {
+  patch factory Float32x4List(int length) {
+    throw new UnsupportedError('Float32x4List');
+  }
+
+  patch factory Float32x4List.view(ByteArray array,
+                                   [int start = 0, int length]) {
+    throw new UnsupportedError('Float32x4List.view');
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
index 9749028..aa13997 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/string_helper.dart
@@ -73,12 +73,10 @@
   // The JavaScript String.replace method recognizes replacement
   // patterns in the replacement string. Dart does not have that
   // behavior.
-  to = JS('String', r"#.replace('$', '$$$$')", to);
+  to = JS('String', r'#.replace("$", "$$$$")', to);
   return JS('String', r'#.replace(#, #)', receiver, replacer, to);
 }
 
-final RegExp quoteRegExp = const JSSyntaxRegExp(r'[-[\]{}()*+?.,\\^$|#\s]');
-
 stringReplaceAllUnchecked(receiver, from, to) {
   checkString(to);
   if (from is String) {
@@ -96,15 +94,14 @@
         return result.toString();
       }
     } else {
-      var quoter = regExpMakeNative(quoteRegExp, global: true);
+      var quoter = JS('', "new RegExp(#, 'g')", r'[-[\]{}()*+?.,\\^$|#\s]');
       var quoted = JS('String', r'#.replace(#, "\\$&")', from, quoter);
-      RegExp replaceRegExp = new JSSyntaxRegExp(quoted);
-      var replacer = regExpMakeNative(replaceRegExp, global: true);
+      var replacer = JS('', "new RegExp(#, 'g')", quoted);
       return stringReplaceJS(receiver, replacer, to);
     }
   } else if (from is JSSyntaxRegExp) {
-    var re = regExpMakeNative(from, global: true);
-    return stringReplaceJS(receiver, re, to);
+    var re = new JSSyntaxRegExp._globalVersionOf(from);
+    return stringReplaceJS(receiver, re._nativeRegExp, to);
   } else {
     checkNull(from);
     // TODO(floitsch): implement generic String.replace (with patterns).
@@ -145,10 +142,10 @@
   while (i < length) {
     buffer.add(onMatch(new StringMatch(i, receiver, "")));
     // Special case to avoid splitting a surrogate pair.
-    int code = receiver.charCodeAt(i);
+    int code = receiver.codeUnitAt(i);
     if ((code & ~0x3FF) == 0xD800 && length > i + 1) {
       // Leading surrogate;
-      code = receiver.charCodeAt(i + 1);
+      code = receiver.codeUnitAt(i + 1);
       if ((code & ~0x3FF) == 0xDC00) {
         // Matching trailing surrogate.
         buffer.add(onNonMatch(receiver.substring(i, i + 2)));
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index 13a15f8..d18c2e1 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -251,10 +251,10 @@
       : cwd = getCurrentDirectory(),
         provider = new SourceFileProvider() {
     var handler = new FormattingDiagnosticHandler(provider);
-    var libraryUri = cwd.resolve(libraryRoot.toString());
+    var libraryUri = cwd.resolve('${libraryRoot}/');
     var packageUri;
     if (packageRoot != null) {
-      packageUri = cwd.resolve(packageRoot.toString());
+      packageUri = cwd.resolve('${packageRoot}/');
     } else {
       packageUri = libraryUri;
     }
@@ -271,10 +271,10 @@
                      [Path packageRoot, List<String> opts = const <String>[]])
       : cwd = getCurrentDirectory(),
         provider = new SourceFileProvider() {
-    var libraryUri = cwd.resolve(libraryRoot.toString());
+    var libraryUri = cwd.resolve('${libraryRoot}/');
     var packageUri;
     if (packageRoot != null) {
-      packageUri = cwd.resolve(packageRoot.toString());
+      packageUri = cwd.resolve('${packageRoot}/');
     } else {
       packageUri = libraryUri;
     }
@@ -688,8 +688,8 @@
     var columnNumber = 0;
     while (0 <= index && index < sourceText.length) {
       columnNumber++;
-      var charCode = sourceText.charCodeAt(index);
-      if (charCode == $CR || charCode == $LF) {
+      var codeUnit = sourceText.codeUnitAt(index);
+      if (codeUnit == $CR || codeUnit == $LF) {
         break;
       }
       index--;
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 54055cd..1ff6f48 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -7,6 +7,11 @@
 abstract class TreeElements {
   Element operator[](Node node);
   Selector getSelector(Send send);
+  Selector getGetterSelectorInComplexSendSet(SendSet node);
+  Selector getOperatorSelectorInComplexSendSet(SendSet node);
+  Selector getIteratorSelector(ForIn node);
+  Selector getMoveNextSelector(ForIn node);
+  Selector getCurrentSelector(ForIn node);
   DartType getType(Node node);
   bool isParameterChecked(Element element);
   Set<Node> get superUses;
@@ -14,7 +19,8 @@
 
 class TreeElementMapping implements TreeElements {
   final Element currentElement;
-  final Map<Node, Selector> selectors = new LinkedHashMap<Node, Selector>();
+  final Map<Spannable, Selector> selectors =
+      new LinkedHashMap<Spannable, Selector>();
   final Map<Node, DartType> types = new LinkedHashMap<Node, DartType>();
   final Set<Element> checkedParameters = new Set<Element>();
   final Set<Node> superUses = new Set<Node>();
@@ -61,7 +67,53 @@
     selectors[node] = selector;
   }
 
-  Selector getSelector(Node node) => selectors[node];
+  Selector getSelector(Node node) {
+    return selectors[node];
+  }
+
+  void setGetterSelectorInComplexSendSet(SendSet node, Selector selector) {
+    selectors[node.selector] = selector;
+  }
+
+  Selector getGetterSelectorInComplexSendSet(SendSet node) {
+    return selectors[node.selector];
+  }
+
+  void setOperatorSelectorInComplexSendSet(SendSet node, Selector selector) {
+    selectors[node.assignmentOperator] = selector;
+  }
+
+  Selector getOperatorSelectorInComplexSendSet(SendSet node) {
+    return selectors[node.assignmentOperator];
+  }
+
+  // The following methods set selectors on the "for in" node. Since
+  // we're using three selectors, we need to use children of the node,
+  // and we arbitrarily choose which ones.
+
+  Selector setIteratorSelector(ForIn node, Selector selector) {
+    selectors[node] = selector;
+  }
+
+  Selector getIteratorSelector(ForIn node) {
+    return selectors[node];
+  }
+
+  Selector setMoveNextSelector(ForIn node, Selector selector) {
+    selectors[node.forToken] = selector;
+  }
+
+  Selector getMoveNextSelector(ForIn node) {
+    return selectors[node.forToken];
+  }
+
+  Selector setCurrentSelector(ForIn node, Selector selector) {
+    selectors[node.inToken] = selector;
+  }
+
+  Selector getCurrentSelector(ForIn node) {
+    return selectors[node.inToken];
+  }
 
   bool isParameterChecked(Element element) {
     return checkedParameters.contains(element);
@@ -1585,7 +1637,12 @@
       this.statementScope = new StatementScope(),
       typeResolver = new TypeResolver(compiler),
       scope = element.buildScope(),
-      inCheckContext = compiler.enableTypeAssertions,
+      // The type annotations on a typedef do not imply type checks.
+      // TODO(karlklose): clean this up (dartbug.com/8870).
+      inCheckContext = compiler.enableTypeAssertions &&
+          !element.isTypedef() &&
+          (element.enclosingElement == null ||
+           !element.enclosingElement.isTypedef()),
       inCatchBlock = false,
       super(compiler);
 
@@ -1866,9 +1923,6 @@
     FunctionElement function = new FunctionElementX.node(
         name, node, ElementKind.FUNCTION, Modifiers.EMPTY,
         enclosingElement);
-    // [function] and its enclosing method share the same
-    // [TreeElementMapping].
-    compiler.enqueuer.resolution.resolvedElements[function] = mapping;
     Scope oldScope = scope; // The scope is modified by [setupFunction].
     setupFunction(node, function);
     defineElement(node, function, doAddToScope: node.name != null);
@@ -1955,6 +2009,13 @@
       // [target] may be null which means invoking noSuchMethod on
       // super.
       if (target == null) {
+        target = warnAndCreateErroneousElement(
+            node, name, MessageKind.NO_SUCH_SUPER_MEMBER,
+            {'className': currentClass, 'memberName': name});
+        // We still need to register the invocation, because we might
+        // call [:super.noSuchMethod:] that does a
+        // [:InvocationMirror.invokeOn:].
+        world.registerDynamicInvocation(selector.name, selector);
         compiler.backend.registerSuperNoSuchMethod();
       }
     } else if (Elements.isUnresolved(resolvedReceiver)) {
@@ -2216,24 +2277,29 @@
         setter = field.setter;
         getter = field.getter;
         if (setter == null && !inInstanceContext) {
-          setter =
-              warnAndCreateErroneousElement(node.selector, field.name,
-                                            MessageKind.CANNOT_RESOLVE_SETTER);
+          setter = warnAndCreateErroneousElement(
+              node.selector, field.name, MessageKind.CANNOT_RESOLVE_SETTER);
           compiler.backend.registerThrowNoSuchMethod();
         }
         if (isComplex && getter == null && !inInstanceContext) {
-          getter =
-              warnAndCreateErroneousElement(node.selector, field.name,
-                                            MessageKind.CANNOT_RESOLVE_GETTER);
+          getter = warnAndCreateErroneousElement(
+              node.selector, field.name, MessageKind.CANNOT_RESOLVE_GETTER);
           compiler.backend.registerThrowNoSuchMethod();
         }
       } else if (target.impliesType()) {
         compiler.backend.registerThrowNoSuchMethod();
       } else if (target.modifiers.isFinal() || target.modifiers.isConst()) {
-        setter =
-            warnAndCreateErroneousElement(node.selector, target.name,
-                                          MessageKind.CANNOT_RESOLVE_SETTER);
+        setter = warnAndCreateErroneousElement(
+            node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER);
         compiler.backend.registerThrowNoSuchMethod();
+      } else if (isComplex && target.name == const SourceString('[]=')) {
+        getter = target.getEnclosingClass().lookupMember(
+            const SourceString('[]'));
+        if (getter == null) {
+          getter = warnAndCreateErroneousElement(
+              node, setter.name, MessageKind.CANNOT_RESOLVE_INDEX);
+          compiler.backend.registerThrowNoSuchMethod();
+        }
       }
     }
 
@@ -2245,34 +2311,29 @@
 
     Selector selector = mapping.getSelector(node);
     if (isComplex) {
+      Selector getterSelector;
       if (selector.isSetter()) {
-        // TODO(kasperl): We're registering the getter selector for
-        // compound assignments on the AST selector node. In the code
-        // generator, we then fetch it from there when generating the
-        // getter for a SendSet node.
-        Selector getterSelector = new Selector.getterFrom(selector);
-        registerSend(getterSelector, getter);
-        mapping.setSelector(node.selector, getterSelector);
-        useElement(node.selector, getter);
+        getterSelector = new Selector.getterFrom(selector);
       } else {
-        // TODO(kasperl): If [getter] is resolved, it will actually
-        // refer to the []= operator which isn't the one we want to
-        // register here. We should consider using some notion of
-        // abstract indexable element that we can resolve to so we can
-        // distinguish the two.
         assert(selector.isIndexSet());
-        registerSend(new Selector.index(), null);
+        getterSelector = new Selector.index();
       }
+      registerSend(getterSelector, getter);
+      mapping.setGetterSelectorInComplexSendSet(node, getterSelector);
+      useElement(node.selector, getter);
 
       // Make sure we include the + and - operators if we are using
       // the ++ and -- ones.  Also, if op= form is used, include op itself.
       void registerBinaryOperator(SourceString name) {
         Selector binop = new Selector.binaryOperator(name);
         world.registerDynamicInvocation(binop.name, binop);
+        mapping.setOperatorSelectorInComplexSendSet(node, binop);
       }
-      if (identical(source, '++')) registerBinaryOperator(const SourceString('+'));
-      if (identical(source, '--')) registerBinaryOperator(const SourceString('-'));
-      if (source.endsWith('=')) {
+      if (identical(source, '++')) {
+        registerBinaryOperator(const SourceString('+'));
+      } else if (identical(source, '--')) {
+        registerBinaryOperator(const SourceString('-'));
+      } else if (source.endsWith('=')) {
         registerBinaryOperator(Elements.mapToUserOperator(operatorName));
       }
     }
@@ -2448,7 +2509,7 @@
     ClassElement cls = constructor.getEnclosingClass();
     // [cls] might be the implementation element and only declaration elements
     // may be registered.
-    world.registerInstantiatedClass(cls.declaration);
+    world.registerInstantiatedType(mapping.getType(node));
     if (cls.isAbstract(compiler)) {
       compiler.backend.registerAbstractClassInstantiation();
     }
@@ -2518,9 +2579,7 @@
           analyzeTypeArgument(type, argument);
         });
       }
-      // TODO(ngeoffray): Also handle cases like:
-      // 1) a is T
-      // 2) T a (in checked mode).
+      // TODO(ngeoffray): Also handle T a (in checked mode).
     }
     return type;
   }
@@ -2631,18 +2690,23 @@
     world.registerDynamicInvocation(name, selector);
   }
 
-  registerImplicitFieldGet(SourceString name) {
-    Selector selector = new Selector.getter(name, null);
-    world.registerDynamicGetter(name, selector);
-  }
-
   visitForIn(ForIn node) {
-    for (final name in const [
-        const SourceString('iterator'),
-        const SourceString('current')]) {
-      registerImplicitFieldGet(name);
-    }
-    registerImplicitInvocation(const SourceString('moveNext'), 0);
+    LibraryElement library = enclosingElement.getLibrary();
+    Selector iteratorSelector =
+        new Selector.getter(const SourceString('iterator'), library);
+    world.registerDynamicGetter(iteratorSelector.name, iteratorSelector);
+    mapping.setIteratorSelector(node, iteratorSelector);
+
+    Selector currentSelector =
+        new Selector.getter(const SourceString('current'), library);
+    world.registerDynamicGetter(currentSelector.name, currentSelector);
+    mapping.setCurrentSelector(node, currentSelector);
+
+    Selector moveNextSelector =
+        new Selector.call(const SourceString('moveNext'), library, 0);
+    world.registerDynamicInvocation(moveNextSelector.name, moveNextSelector);
+    mapping.setMoveNextSelector(node, moveNextSelector);
+
     visit(node.expression);
     Scope blockScope = new BlockScope(scope);
     Node declaration = node.declaredIdentifier;
@@ -2968,7 +3032,7 @@
         DartType supertype = resolveSupertype(element, superMixin.superclass);
         Link<Node> link = superMixin.mixins.nodes;
         while (!link.isEmpty) {
-          supertype = applyMixin(supertype, visit(link.head));
+          supertype = applyMixin(supertype, resolveType(link.head));
           link = link.tail;
         }
         element.supertype = supertype;
@@ -3013,10 +3077,10 @@
     DartType supertype = resolveSupertype(element, node.superclass);
     Link<Node> link = node.mixins.nodes;
     while (!link.tail.isEmpty) {
-      supertype = applyMixin(supertype, visit(link.head));
+      supertype = applyMixin(supertype, resolveType(link.head));
       link = link.tail;
     }
-    doApplyMixinTo(element, supertype, visit(link.head));
+    doApplyMixinTo(element, supertype, resolveType(link.head));
     return element.computeType(compiler);
   }
 
@@ -3093,6 +3157,10 @@
     return visit(node.typeName);
   }
 
+  DartType resolveType(TypeAnnotation node) {
+    return typeResolver.resolveTypeAnnotation(node, scope, element);
+  }
+
   // TODO(johnniwinther): Remove when default class is no longer supported.
   DartType visitIdentifier(Identifier node) {
     Element element = scope.lookup(node.source);
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart b/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart
index 4d79898..c9372bf 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/byte_strings.dart
@@ -75,7 +75,7 @@
 
 
   static AsciiString fromString(String string) {
-    List<int> bytes = string.charCodes;
+    List<int> bytes = string.codeUnits;
     return AsciiString.of(bytes, 0, bytes.length);
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart b/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
index 6f47f73..aa85287 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/keyword.dart
@@ -68,9 +68,6 @@
       const Keyword("show", isPseudo: true),
       const Keyword("source", isPseudo: true) ];
 
-  // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support.
-  static const DYNAMIC_DEPRECATED = const Keyword("Dynamic", isBuiltIn: true);
-
   final String syntax;
   final bool isPseudo;
   final bool isBuiltIn;
@@ -136,7 +133,7 @@
   static KeywordState get KEYWORD_STATE {
     if (_KEYWORD_STATE == null) {
       List<String> strings =
-          new List<String>.fixedLength(Keyword.values.length);
+          new List<String>(Keyword.values.length);
       for (int i = 0; i < Keyword.values.length; i++) {
         strings[i] = Keyword.values[i].syntax;
       }
@@ -148,7 +145,7 @@
 
   static KeywordState computeKeywordStateTable(int start, List<String> strings,
                                                int offset, int length) {
-    List<KeywordState> result = new List<KeywordState>.fixedLength(26);
+    List<KeywordState> result = new List<KeywordState>(26);
     assert(length != 0);
     int chunk = 0;
     int chunkStart = -1;
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
index 8955b00..c2469c3 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
@@ -404,10 +404,8 @@
     if (identical(kind, KEYWORD_TOKEN)) {
       Keyword keyword = token.value;
       String value = keyword.stringValue;
-      // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support.
       return keyword.isPseudo
           || (identical(value, 'dynamic'))
-          || (identical(value, 'Dynamic'))
           || (identical(value, 'void'));
     }
     return false;
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
index 123b650..75b9cb5 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/scanner.dart
@@ -660,46 +660,17 @@
   int tokenizeIdentifier(int next, int start, bool allowDollar) {
     bool isAscii = true;
 
-    // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support.
-    bool isDynamicBuiltIn = false;
-
-    if (identical(next, $D)) {
-      next = advance();
-      if (identical(next, $y)) {
-        next = advance();
-        if (identical(next, $n)) {
-          next = advance();
-          if (identical(next, $a)) {
-            next = advance();
-            if (identical(next, $m)) {
-              next = advance();
-              if (identical(next, $i)) {
-                next = advance();
-                if (identical(next, $c)) {
-                  isDynamicBuiltIn = true;
-                  next = advance();
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-
     while (true) {
       if (($a <= next && next <= $z) ||
           ($A <= next && next <= $Z) ||
           ($0 <= next && next <= $9) ||
           identical(next, $_) ||
           (identical(next, $$) && allowDollar)) {
-        isDynamicBuiltIn = false;
         next = advance();
       } else if ((next < 128) || (identical(next, $NBSP))) {
         // Identifier ends here.
         if (start == byteOffset) {
           return error(const SourceString("expected identifier"));
-        } else if (isDynamicBuiltIn) {
-          appendKeywordToken(Keyword.DYNAMIC_DEPRECATED);
         } else if (isAscii) {
           appendByteStringToken(IDENTIFIER_INFO, asciiString(start, 0));
         } else {
@@ -707,7 +678,6 @@
         }
         return next;
       } else {
-        isDynamicBuiltIn = false;
         int nonAsciiStart = byteOffset;
         do {
           next = nextByte();
diff --git a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
index c100694..fc4e9b2 100644
--- a/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_file_provider.dart
@@ -19,7 +19,7 @@
 String readAll(String filename) {
   var file = (new File(filename)).openSync(FileMode.READ);
   var length = file.lengthSync();
-  var buffer = new List<int>.fixedLength(length);
+  var buffer = new List<int>(length);
   var bytes = file.readListSync(buffer, 0, length);
   file.closeSync();
   return new String.fromCharCodes(new Utf8Decoder(buffer).decodeRest());
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 0c387a8..252afbd 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -11,10 +11,8 @@
  */
 class InterceptedElement extends ElementX {
   final HType ssaType;
-  InterceptedElement(this.ssaType, Element enclosing)
-      : super(const SourceString('receiver'),
-              ElementKind.PARAMETER,
-              enclosing);
+  InterceptedElement(this.ssaType, SourceString name, Element enclosing)
+      : super(name, ElementKind.PARAMETER, enclosing);
 
   DartType computeType(Compiler compiler) => ssaType.computeType(compiler);
 }
@@ -185,39 +183,38 @@
     // See if any variable in the top-scope of the function is captured. If yes
     // we need to create a box-object.
     ClosureScope scopeData = closureData.capturingScopes[node];
-    if (scopeData != null) {
-      HInstruction box;
-      // The scope has captured variables.
-      if (element != null && element.isGenerativeConstructorBody()) {
-        // The box is passed as a parameter to a generative
-        // constructor body.
-        box = builder.addParameter(scopeData.boxElement);
-      } else {
-        box = createBox();
-      }
-      // Add the box to the known locals.
-      directLocals[scopeData.boxElement] = box;
-      // Make sure that accesses to the boxed locals go into the box. We also
-      // need to make sure that parameters are copied into the box if necessary.
-      scopeData.capturedVariableMapping.forEach((Element from, Element to) {
-        // The [from] can only be a parameter for function-scopes and not
-        // loop scopes.
-        if (from.isParameter() && !element.isGenerativeConstructorBody()) {
-          // Now that the redirection is set up, the update to the local will
-          // write the parameter value into the box.
-          // Store the captured parameter in the box. Get the current value
-          // before we put the redirection in place.
-          // We don't need to update the local for a generative
-          // constructor body, because it receives a box that already
-          // contains the updates as the last parameter.
-          HInstruction instruction = readLocal(from);
-          redirectElement(from, to);
-          updateLocal(from, instruction);
-        } else {
-          redirectElement(from, to);
-        }
-      });
+    if (scopeData == null) return;
+    HInstruction box;
+    // The scope has captured variables.
+    if (element != null && element.isGenerativeConstructorBody()) {
+      // The box is passed as a parameter to a generative
+      // constructor body.
+      box = builder.addParameter(scopeData.boxElement);
+    } else {
+      box = createBox();
     }
+    // Add the box to the known locals.
+    directLocals[scopeData.boxElement] = box;
+    // Make sure that accesses to the boxed locals go into the box. We also
+    // need to make sure that parameters are copied into the box if necessary.
+    scopeData.capturedVariableMapping.forEach((Element from, Element to) {
+      // The [from] can only be a parameter for function-scopes and not
+      // loop scopes.
+      if (from.isParameter() && !element.isGenerativeConstructorBody()) {
+        // Now that the redirection is set up, the update to the local will
+        // write the parameter value into the box.
+        // Store the captured parameter in the box. Get the current value
+        // before we put the redirection in place.
+        // We don't need to update the local for a generative
+        // constructor body, because it receives a box that already
+        // contains the updates as the last parameter.
+        HInstruction instruction = readLocal(from);
+        redirectElement(from, to);
+        updateLocal(from, instruction);
+      } else {
+        redirectElement(from, to);
+      }
+    });
   }
 
   /**
@@ -325,10 +322,12 @@
     }
 
     // If this method is an intercepted method, add the extra
-    // parameter to it, that is the actual receiver.
+    // parameter to it, that is the actual receiver for intercepted
+    // classes, or the same as [:this:] for non-intercepted classes.
     ClassElement cls = element.getEnclosingClass();
-    if (builder.backend.isInterceptorClass(cls)) {
+    if (builder.backend.isInterceptedMethod(element)) {
       HType type = HType.UNKNOWN;
+      SourceString name = const SourceString('receiver');
       if (cls == builder.backend.jsArrayClass) {
         type = HType.READABLE_ARRAY;
       } else if (cls == builder.backend.jsStringClass) {
@@ -343,12 +342,21 @@
         type = HType.NULL;
       } else if (cls == builder.backend.jsBoolClass) {
         type = HType.BOOLEAN;
+      } else if (cls == builder.backend.jsFunctionClass) {
+        type = HType.UNKNOWN;
+      } else if (cls != compiler.objectClass) {
+        JavaScriptBackend backend = compiler.backend;
+        assert(!backend.isInterceptorClass(cls));
+        name = const SourceString('_');
       }
-      Element parameter = new InterceptedElement(type, element);
+      Element parameter = new InterceptedElement(type, name, element);
       HParameterValue value = new HParameterValue(parameter);
       builder.graph.entry.addAfter(
           directLocals[closureData.thisElement], value);
-      directLocals[closureData.thisElement] = value;
+      if (builder.backend.isInterceptorClass(cls.declaration)) {
+        // Only use the extra parameter in intercepted classes.
+        directLocals[closureData.thisElement] = value;
+      }
       value.instructionType = type;
     }
   }
@@ -895,6 +903,18 @@
     // check at the beginning of the method. This is to avoid having
     // call sites do the null check.
     if (name == const SourceString('==')) {
+      if (functionElement.getEnclosingClass() == compiler.objectClass) {
+        // We special case [Object.operator==] because we know the
+        // receiver is not null and therefore can just do an identity
+        // check on [:this:]. The interceptor classes have their own
+        // synthesized [:operator==:] method.
+        HInstruction parameter = parameters.values.first;
+        HIdentity identity = new HIdentity(graph.thisInstruction, parameter);
+        add(identity);
+        HReturn ret = new HReturn(identity);
+        close(ret).addSuccessor(graph.exit);
+        return closeFunction();
+      }
       handleIf(
           function,
           () {
@@ -1124,6 +1144,7 @@
   }
 
   inlinedFrom(Element element, f()) {
+    assert(element is FunctionElement || element is VariableElement);
     return compiler.withCurrentElement(element, () {
       sourceElementStack.add(element);
       var result = f();
@@ -1143,7 +1164,8 @@
                              Link<Node> arguments,
                              List<FunctionElement> constructors,
                              Map<Element, HInstruction> fieldValues,
-                             FunctionElement inlinedFromElement) {
+                             FunctionElement inlinedFromElement,
+                             Node callNode) {
     compiler.withCurrentElement(constructor, () {
       assert(invariant(constructor, constructor.isImplementation));
       constructors.addLast(constructor);
@@ -1163,10 +1185,34 @@
             element: constructor);
       }
 
-      sourceElementStack.add(constructor.enclosingElement);
-      buildFieldInitializers(constructor.enclosingElement.implementation,
-                             fieldValues);
-      sourceElementStack.removeLast();
+      ClassElement superclass = constructor.getEnclosingClass();
+      if (compiler.world.needsRti(superclass)) {
+        // If [superclass] needs RTI, we have to give a value to its
+        // type parameters. Those values are in the [supertype]
+        // declaration of [subclass].
+        ClassElement subclass = inlinedFromElement.getEnclosingClass();
+        DartType supertype = subclass.supertype;
+        Link<DartType> typeVariables = superclass.typeVariables;
+        supertype.typeArguments.forEach((DartType argument) {
+          localsHandler.updateLocal(typeVariables.head.element,
+              analyzeTypeArgument(argument, callNode));
+          typeVariables = typeVariables.tail;
+        });
+        // If the supertype is a raw type, we need to set to null the
+        // type variables.
+        assert(typeVariables.isEmpty
+               || superclass.typeVariables == typeVariables);
+        while (!typeVariables.isEmpty) {
+          localsHandler.updateLocal(typeVariables.head.element,
+              graph.addConstantNull(constantSystem));
+          typeVariables = typeVariables.tail;
+        }
+      }
+
+      inlinedFrom(constructor, () {
+        buildFieldInitializers(constructor.enclosingElement.implementation,
+                               fieldValues);
+      });
 
       int index = 0;
       FunctionSignature params = constructor.computeSignature(compiler);
@@ -1245,16 +1291,16 @@
           Selector selector = elements.getSelector(call);
           Link<Node> arguments = call.arguments;
           inlineSuperOrRedirect(target, selector, arguments, constructors,
-                                fieldValues, constructor);
+                                fieldValues, constructor, call);
           foundSuperOrRedirect = true;
         } else {
           // A field initializer.
           SendSet init = link.head;
           Link<Node> arguments = init.arguments;
           assert(!arguments.isEmpty && arguments.tail.isEmpty);
-          sourceElementStack.add(constructor);
-          visit(arguments.head);
-          sourceElementStack.removeLast();
+          inlinedFrom(constructor, () {
+            visit(arguments.head);
+          });
           fieldValues[elements[init]] = pop();
         }
       }
@@ -1280,7 +1326,8 @@
                               const Link<Node>(),
                               constructors,
                               fieldValues,
-                              constructor);
+                              constructor,
+                              functionNode);
       }
     }
   }
@@ -1296,21 +1343,27 @@
     assert(invariant(classElement, classElement.isImplementation));
     classElement.forEachInstanceField(
         (ClassElement enclosingClass, Element member) {
-          TreeElements definitions = compiler.analyzeElement(member);
-          Node node = member.parseNode(compiler);
-          SendSet assignment = node.asSendSet();
-          HInstruction value;
-          if (assignment == null) {
-            value = graph.addConstantNull(constantSystem);
-          } else {
-            Node right = assignment.arguments.head;
-            TreeElements savedElements = elements;
-            elements = definitions;
-            right.accept(this);
-            elements = savedElements;
-            value = pop();
-          }
-          fieldValues[member] = value;
+          compiler.withCurrentElement(member, () {
+            TreeElements definitions = compiler.analyzeElement(member);
+            Node node = member.parseNode(compiler);
+            SendSet assignment = node.asSendSet();
+            HInstruction value;
+            if (assignment == null) {
+              value = graph.addConstantNull(constantSystem);
+            } else {
+              Node right = assignment.arguments.head;
+              TreeElements savedElements = elements;
+              elements = definitions;
+              // In case the field initializer uses closures, run the
+              // closure to class mapper.
+              compiler.closureToClassMapper.computeClosureToClassMapping(
+                  member, node, elements);
+              right.accept(this);
+              elements = savedElements;
+              value = pop();
+            }
+            fieldValues[member] = value;
+          });
         },
         includeBackendMembers: true,
         includeSuperMembers: false);
@@ -1375,19 +1428,19 @@
         includeSuperMembers: true);
 
     InterfaceType type = classElement.computeType(compiler);
-    HType ssaType = new HBoundedType.exact(type);
+    HType ssaType = new HType.nonNullExact(type, compiler);
     HForeignNew newObject = new HForeignNew(classElement,
                                             ssaType,
                                             constructorArguments);
     add(newObject);
 
     // Create the runtime type information, if needed.
-    List<HInstruction> inputs = <HInstruction>[];
     if (compiler.world.needsRti(classElement)) {
+      List<HInstruction> rtiInputs = <HInstruction>[];
       classElement.typeVariables.forEach((TypeVariableType typeVariable) {
-        inputs.add(localsHandler.directLocals[typeVariable.element]);
+        rtiInputs.add(localsHandler.readLocal(typeVariable.element));
       });
-      callSetRuntimeTypeInfo(classElement, inputs, newObject);
+      callSetRuntimeTypeInfo(classElement, rtiInputs, newObject);
     }
 
     // Generate calls to the constructor bodies.
@@ -1398,23 +1451,22 @@
       if (body == null) continue;
       List bodyCallInputs = <HInstruction>[];
       bodyCallInputs.add(newObject);
-      FunctionSignature functionSignature = body.computeSignature(compiler);
-      functionSignature.orderedForEachParameter((parameter) {
-        if (!localsHandler.isBoxed(parameter)) {
-          // The parameter will be a field in the box passed as the
-          // last parameter. So no need to pass it.
-          bodyCallInputs.add(localsHandler.readLocal(parameter));
-        }
-      });
-
-      // If parameters are checked, we pass the already computed
-      // boolean to the constructor body.
       TreeElements elements =
           compiler.enqueuer.resolution.getCachedElements(constructor);
       Node node = constructor.parseNode(compiler);
       ClosureClassMap parameterClosureData =
           compiler.closureToClassMapper.getMappingForNestedFunction(node);
+
+
+      FunctionSignature functionSignature = body.computeSignature(compiler);
       functionSignature.orderedForEachParameter((parameter) {
+        // if [parameter] is boxed, it will be a field in the box passed as the
+        // last parameter. So no need to direclty pass it.
+        if (!localsHandler.isBoxed(parameter)) {
+          bodyCallInputs.add(localsHandler.readLocal(parameter));
+        }
+        // If [parameter] is checked, we pass the already computed
+        // boolean to the constructor body.
         if (elements.isParameterChecked(parameter)) {
           Element fieldCheck =
               parameterClosureData.parametersWithSentinel[parameter];
@@ -1422,7 +1474,16 @@
         }
       });
 
-      // If there are locals that escape (ie used in closures), we
+      ClassElement currentClass = constructor.getEnclosingClass();
+      if (compiler.world.needsRti(currentClass)) {
+        // If [currentClass] needs RTI, we add the type variables as
+        // parameters of the generative constructor body.
+        currentClass.typeVariables.forEach((DartType argument) {
+          bodyCallInputs.add(localsHandler.readLocal(argument.element));
+        });
+      }
+
+      // If there are locals that escape (ie mutated in closures), we
       // pass the box to the constructor.
       ClosureScope scopeData = parameterClosureData.capturingScopes[node];
       if (scopeData != null) {
@@ -1553,7 +1614,8 @@
     // Add the type parameters of the class as parameters of this
     // method.
     var enclosing = element.enclosingElement;
-    if (element.isConstructor() && compiler.world.needsRti(enclosing)) {
+    if ((element.isConstructor() || element.isGenerativeConstructorBody())
+        && compiler.world.needsRti(enclosing)) {
       enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
         HParameterValue param = addParameter(typeVariable.element);
         localsHandler.directLocals[typeVariable.element] = param;
@@ -2164,8 +2226,9 @@
       }
     });
 
-    HType type = new HBoundedType.exact(
-        compiler.functionClass.computeType(compiler));
+    HType type = new HType.nonNullExact(
+        compiler.functionClass.computeType(compiler),
+        compiler);
     push(new HForeignNew(closureClassElement, type, capturedVariables));
   }
 
@@ -2243,74 +2306,12 @@
     pushWithPosition(result, node);
   }
 
-  void visitBinary(
-      HInstruction left, Operator op, HInstruction right, Send send) {
-    Selector selector = null;
-    // TODO(ngeoffray): The resolver creates these selectors already
-    // but does not put them on the [send] instruction.
+  void visitBinary(HInstruction left,
+                   Operator op,
+                   HInstruction right,
+                   Selector selector,
+                   Send send) {
     switch (op.source.stringValue) {
-      case "+":
-      case "+=":
-      case "++":
-        selector = new Selector.binaryOperator(const SourceString('+'));
-        break;
-      case "-":
-      case "-=":
-      case "--":
-        selector = new Selector.binaryOperator(const SourceString('-'));
-        break;
-      case "*":
-      case "*=":
-        selector = new Selector.binaryOperator(const SourceString('*'));
-        break;
-      case "/":
-      case "/=":
-        selector = new Selector.binaryOperator(const SourceString('/'));
-        break;
-      case "~/":
-      case "~/=":
-        selector = new Selector.binaryOperator(const SourceString('~/'));
-        break;
-      case "%":
-      case "%=":
-        selector = new Selector.binaryOperator(const SourceString('%'));
-        break;
-      case "<<":
-      case "<<=":
-        selector = new Selector.binaryOperator(const SourceString('<<'));
-        break;
-      case ">>":
-      case ">>=":
-        selector = new Selector.binaryOperator(const SourceString('>>'));
-        break;
-      case "|":
-      case "|=":
-        selector = new Selector.binaryOperator(const SourceString('|'));
-        break;
-      case "&":
-      case "&=":
-        selector = new Selector.binaryOperator(const SourceString('&'));
-        break;
-      case "^":
-      case "^=":
-        selector = new Selector.binaryOperator(const SourceString('^'));
-        break;
-      case "==":
-      case "!=":
-        selector = new Selector.binaryOperator(const SourceString('=='));
-        break;
-      case "<":
-        selector = new Selector.binaryOperator(const SourceString('<'));
-        break;
-      case "<=":
-        selector = new Selector.binaryOperator(const SourceString('<='));
-        break;
-      case ">":
-        selector = new Selector.binaryOperator(const SourceString('>'));
-        break;
-      case ">=":
-        selector = new Selector.binaryOperator(const SourceString('>='));
-        break;
       case "===":
         pushWithPosition(new HIdentity(left, right), op);
         return;
@@ -2319,9 +2320,6 @@
         add(eq);
         pushWithPosition(new HNot(eq), op);
         return;
-      default:
-        compiler.internalError("Unexpected operator $op", node: op);
-        break;
     }
 
     pushWithPosition(
@@ -2350,25 +2348,17 @@
   }
 
   /**
-   * Returns a set of interceptor classes that contain a member whose
-   * signature matches the given [selector].
+   * Returns a set of interceptor classes that contain the given
+   * [selector].
    */
-  Set<ClassElement> getInterceptedClassesOn(Selector selector) {
-    return backend.getInterceptedClassesOn(selector);
-  }
-
   void generateInstanceGetterWithCompiledReceiver(Send send,
+                                                  Selector selector,
                                                   HInstruction receiver) {
     assert(Elements.isInstanceSend(send, elements));
-    // TODO(kasperl): This is a convoluted way of checking if we're
-    // generating code for a compound assignment. If we are, we need
-    // to get the selector from the mapping for the AST selector node.
-    Selector selector = (send.asSendSet() == null)
-        ? elements.getSelector(send)
-        : elements.getSelector(send.selector);
     assert(selector.isGetter());
     SourceString getterName = selector.name;
-    Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
+    Set<ClassElement> interceptedClasses =
+        backend.getInterceptedClassesOn(getterName);
 
     bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
     HInstruction instruction;
@@ -2418,7 +2408,8 @@
       }
     } else if (Elements.isInstanceSend(send, elements)) {
       HInstruction receiver = generateInstanceSendReceiver(send);
-      generateInstanceGetterWithCompiledReceiver(send, receiver);
+      generateInstanceGetterWithCompiledReceiver(
+          send, elements.getSelector(send), receiver);
     } else if (Elements.isStaticOrTopLevelFunction(element)) {
       // TODO(5346): Try to avoid the need for calling [declaration] before
       // creating an [HStatic].
@@ -2443,7 +2434,8 @@
     assert(selector.isSetter());
     SourceString setterName = selector.name;
     bool hasSetter = compiler.world.hasAnyUserDefinedSetter(selector);
-    Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
+    Set<ClassElement> interceptedClasses =
+        backend.getInterceptedClassesOn(setterName);
     if (interceptedClasses != null) {
       // If we're using an interceptor class, emit a call to the
       // getInterceptor method and then the actual dynamic call on the
@@ -2587,14 +2579,10 @@
   // TODO(karlklose): change construction of the representations to be GVN'able
   // (dartbug.com/7182).
   List<HInstruction> buildTypeArgumentRepresentations(DartType type) {
-    HInstruction createForeignArray(String code, inputs) {
-      return createForeign(code, HType.READABLE_ARRAY, inputs);
-    }
-
     // Compute the representation of the type arguments, including access
     // to the runtime type information for type variables as instructions.
     HInstruction representations;
-    if (type.element.isTypeVariable()) {
+    if (type.kind == TypeKind.TYPE_VARIABLE) {
       return <HInstruction>[addTypeVariableReference(type)];
     } else {
       assert(type.element.isClass());
@@ -2606,7 +2594,8 @@
           HInstruction runtimeType = addTypeVariableReference(variable);
           inputs.add(runtimeType);
         });
-        HInstruction representation = createForeignArray(template, inputs);
+        HInstruction representation =
+            createForeign(template, HType.READABLE_ARRAY, inputs);
         add(representation);
         arguments.add(representation);
       }
@@ -2647,16 +2636,23 @@
         }
         return;
       }
-      if (type.element.isTypeVariable()) {
-        // TODO(karlklose): remove this check when the backend can deal with
-        // checks of the form [:o is T:] where [:T:] is a type variable.
-        stack.add(graph.addConstantBool(true, constantSystem));
-        return;
-      }
 
       HInstruction instruction;
-      if (type.element.isTypeVariable() ||
-          RuntimeTypeInformation.hasTypeArguments(type)) {
+      if (type.kind == TypeKind.TYPE_VARIABLE) {
+        List<HInstruction> representations =
+            buildTypeArgumentRepresentations(type);
+        assert(representations.length == 1);
+        HInstruction runtimeType = addTypeVariableReference(type);
+        Element helper = backend.getGetObjectIsSubtype();
+        HInstruction helperCall = new HStatic(helper);
+        add(helperCall);
+        List<HInstruction> inputs = <HInstruction>[helperCall, expression,
+                                                   runtimeType];
+        instruction = new HInvokeStatic(inputs, HType.BOOLEAN);
+        add(instruction);
+        compiler.enqueuer.codegen.registerIsCheck(type);
+
+      } else if (RuntimeTypeInformation.hasTypeArguments(type)) {
 
         void argumentsCheck() {
           HInstruction typeInfo = getRuntimeTypeInfo(expression);
@@ -2685,7 +2681,8 @@
         void classCheck() { push(new HIs(type, <HInstruction>[expression])); }
 
         SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node);
-        branchBuilder.handleLogicalAndOr(classCheck, argumentsCheck, isAnd: true);
+        branchBuilder.handleLogicalAndOr(classCheck, argumentsCheck,
+                                         isAnd: true);
         instruction = pop();
       } else {
         instruction = new HIs(type, <HInstruction>[expression]);
@@ -2711,7 +2708,7 @@
       visit(node.argumentsNode);
       var right = pop();
       var left = pop();
-      visitBinary(left, op, right, node);
+      visitBinary(left, op, right, elements.getSelector(node), node);
     }
   }
 
@@ -3100,10 +3097,11 @@
                       argumentNamesInstruction,
                       HType.UNKNOWN);
 
-    var inputs = <HInstruction>[
-        target,
-        self,
-        pop()];
+    var inputs = <HInstruction>[target, self];
+    if (backend.isInterceptedMethod(element)) {
+      inputs.add(self);
+    }
+    inputs.add(pop());
     push(new HInvokeSuper(inputs));
   }
 
@@ -3118,13 +3116,18 @@
   visitSuperSend(Send node) {
     Selector selector = elements.getSelector(node);
     Element element = elements[node];
-    if (element == null) return generateSuperNoSuchMethodSend(node);
+    if (Elements.isUnresolved(element)) {
+      return generateSuperNoSuchMethodSend(node);
+    }
     // TODO(5346): Try to avoid the need for calling [declaration] before
     // creating an [HStatic].
     HInstruction target = new HStatic(element.declaration);
     HInstruction context = localsHandler.readThis();
     add(target);
     var inputs = <HInstruction>[target, context];
+    if (backend.isInterceptedMethod(element)) {
+      inputs.add(context);
+    }
     if (node.isPropertyAccess) {
       push(new HInvokeSuper(inputs));
     } else if (element.isFunction() || element.isGenerativeConstructor()) {
@@ -3158,11 +3161,10 @@
       member = closureClass.methodElement;
       member = member.getOutermostEnclosingMemberOrTopLevel();
     }
-    if (member.isFactoryConstructor()) {
+    if (member.isConstructor() || member.isGenerativeConstructorBody()) {
       // The type variable is stored in a parameter of the method.
       return localsHandler.readLocal(type.element);
-    } else if (member.isInstanceMember() ||
-               member.isGenerativeConstructor()) {
+    } else if (member.isInstanceMember()) {
       // The type variable is stored on the object.  Generate code to extract
       // the type arguments from the object, substitute them as an instance
       // of the type we are testing against (if necessary), and extract the
@@ -3268,7 +3270,7 @@
         }
       } else if (element.isGenerativeConstructor()) {
         ClassElement cls = element.getEnclosingClass();
-        return new HBoundedType.exact(cls.thisType);
+        return new HType.nonNullExact(cls.thisType, compiler);
       } else {
         return HType.UNKNOWN;
       }
@@ -3564,7 +3566,8 @@
                                           Selector selector,
                                           HInstruction receiver,
                                           List<HInstruction> arguments) {
-    Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
+    Set<ClassElement> interceptedClasses =
+        backend.getInterceptedClassesOn(selector.name);
     List<HInstruction> inputs = <HInstruction>[];
     bool isIntercepted = interceptedClasses != null;
     if (isIntercepted) {
@@ -3625,12 +3628,16 @@
         }
 
         HInvokeDynamicMethod left = buildInvokeDynamic(
-            node, new Selector.index(), receiver, [index]);
+            node,
+            elements.getGetterSelectorInComplexSendSet(node),
+            receiver,
+            <HInstruction>[index]);
         add(left);
-        visitBinary(left, op, value, node);
+        visitBinary(left, op, value,
+                    elements.getOperatorSelectorInComplexSendSet(node), node);
         value = pop();
         HInvokeDynamicMethod assign = buildInvokeDynamic(
-            node, new Selector.indexSet(), receiver, [index, value]);
+            node, elements.getSelector(node), receiver, [index, value]);
         add(assign);
         if (isPrefix) {
           stack.add(value);
@@ -3657,7 +3664,8 @@
       HInstruction receiver = null;
       if (Elements.isInstanceSend(node, elements)) {
         receiver = generateInstanceSendReceiver(node);
-        generateInstanceGetterWithCompiledReceiver(node, receiver);
+        generateInstanceGetterWithCompiledReceiver(
+            node, elements.getGetterSelectorInComplexSendSet(node), receiver);
       } else {
         generateGetter(node, elements[node.selector]);
       }
@@ -3669,7 +3677,8 @@
       } else {
         right = graph.addConstantInt(1, constantSystem);
       }
-      visitBinary(left, op, right, node);
+      visitBinary(left, op, right,
+                  elements.getOperatorSelectorInComplexSendSet(node), node);
       HInstruction operation = pop();
       assert(operation != null);
       if (Elements.isInstanceSend(node, elements)) {
@@ -3915,10 +3924,9 @@
     // The iterator is shared between initializer, condition and body.
     HInstruction iterator;
     void buildInitializer() {
-      SourceString iteratorName = const SourceString("iterator");
-      Selector selector =
-          new Selector.getter(iteratorName, currentElement.getLibrary());
-      Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
+      Selector selector = elements.getIteratorSelector(node);
+      Set<ClassElement> interceptedClasses =
+          backend.getInterceptedClassesOn(selector.name);
       visit(node.expression);
       HInstruction receiver = pop();
       bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
@@ -3937,15 +3945,12 @@
       add(iterator);
     }
     HInstruction buildCondition() {
-      SourceString name = const SourceString('moveNext');
-      Selector selector = new Selector.call(
-          name, currentElement.getLibrary(), 0);
+      Selector selector = elements.getMoveNextSelector(node);
       push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator]));
       return popBoolified();
     }
     void buildBody() {
-      SourceString name = const SourceString('current');
-      Selector call = new Selector.getter(name, currentElement.getLibrary());
+      Selector call = elements.getCurrentSelector(node);
       bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call);
       push(new HInvokeDynamicGetter(call, null, iterator, !hasGetter));
 
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 527ce59..f2fe22c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1625,7 +1625,7 @@
     if (target != null) {
       // If we know we're calling a specific method, register that
       // method only.
-      assert(selector.typeKind != TypedSelectorKind.UNKNOWN);
+      assert(selector.mask != null);
       world.registerDynamicInvocationOf(target, selector);
     } else {
       SourceString name = node.selector.name;
@@ -2365,8 +2365,7 @@
       checkType(input, type);
       push(new js.Binary('&&', nullTest, pop()));
       attachLocationToLast(node);
-    } else if (input.instructionType.canBePrimitive()
-               || input.instructionType.canBeNull()) {
+    } else if (input.canBePrimitive(compiler) || input.canBeNull()) {
       checkObject(input, '===');
       js.Expression objectTest = pop();
       checkType(input, type);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index b6714b8..d7acb32 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -168,7 +168,11 @@
     if (constant.isFunction()) return HType.UNKNOWN;
     if (constant.isSentinel()) return HType.UNKNOWN;
     ObjectConstant objectConstant = constant;
-    return new HBoundedType.exact(objectConstant.type);
+    // TODO(kasperl): This seems a bit fishy, but we do not have the
+    // compiler at hand so we cannot use the usual HType factory
+    // methods. At some point this should go away.
+    TypeMask mask = new TypeMask.nonNullExact(objectConstant.type);
+    return new HBoundedType(mask);
   }
 
   HConstant addConstant(Constant constant) {
@@ -881,8 +885,9 @@
   bool isTypeUnknown() => instructionType.isUnknown();
   bool isIndexablePrimitive() => instructionType.isIndexablePrimitive();
   bool isPrimitive() => instructionType.isPrimitive();
-  bool canBePrimitive() => instructionType.canBePrimitive();
   bool canBeNull() => instructionType.canBeNull();
+  bool canBePrimitive(Compiler compiler) =>
+      instructionType.canBePrimitive(compiler);
 
   /**
    * Type of the unstruction.
@@ -1213,6 +1218,12 @@
   bool isJsStatement() => isEnabled;
   bool canThrow() => isEnabled;
 
+  // A [HTypeGuard] cannot be moved anywhere in the graph, otherwise
+  // instructions that have side effects could end up before the guard
+  // in the otpimized version, and after the guard in a bailout
+  // version.
+  bool isPure() => false;
+
   accept(HVisitor visitor) => visitor.visitTypeGuard(this);
   int typeCode() => HInstruction.TYPE_GUARD_TYPECODE;
   bool typeEquals(other) => other is HTypeGuard;
@@ -1305,6 +1316,9 @@
   toString() => 'invoke dynamic: $selector';
   HInstruction get receiver => inputs[0];
 
+  /**
+   * Returns whether this call is on an intercepted method.
+   */
   bool get isInterceptorCall {
     // We know it's a selector call if it follows the interceptor
     // calling convention, which adds the actual receiver as a
@@ -1312,6 +1326,18 @@
     return inputs.length - 2 == selector.argumentCount;
   }
 
+  /**
+   * Returns whether this call is on an interceptor object.
+   */
+  bool get isCallOnInterceptor {
+    // When the optimizers know this call does not need an
+    // interceptor, they udpate the receiver of the call to be the
+    // actual receiver.
+    // TODO(ngeoffray): This is very fragile and we should inspect the
+    // receiver instead.
+    return isInterceptorCall && inputs[0] != inputs[1];
+  }
+
   int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
   bool typeEquals(other) => other is HInvokeDynamic;
   bool dataEquals(HInvokeDynamic other) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index ced53a5..7a41583 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -138,8 +138,16 @@
 
         // If we can replace [instruction] with [replacement], then
         // [replacement]'s type can be narrowed.
-        replacement.instructionType = replacement.instructionType.intersection(
+        HType newType = replacement.instructionType.intersection(
             instruction.instructionType, compiler);
+        if (!newType.isConflicting()) {
+          // [HType.intersection] may give up when doing the
+          // intersection of two types is too complicated, and return
+          // [HType.CONFLICTING]. We do not want instructions to have
+          // [HType.CONFLICTING], so we only update the type if the
+          // intersection did not give up.
+          replacement.instructionType = newType;
+        }
 
         // If the replacement instruction does not know its
         // source element, use the source element of the
@@ -309,27 +317,6 @@
       }
     }
 
-    // Check if this call does not need to be intercepted.
-    HType type = input.instructionType;
-    // TODO(kasperl): Get rid of this refinement once the receiver
-    // specialization phase takes care of it.
-    Selector refined = type.refine(selector, compiler);
-    Set<ClassElement> classes = backend.getInterceptedClassesOn(
-        refined, canBeNull: type.canBeNull());
-    if (classes == null) {
-      if (selector.isGetter()) {
-        // Change the call to a regular invoke dynamic call.
-        return new HInvokeDynamicGetter(selector, null, input, false);
-      } else if (selector.isSetter()) {
-        return new HInvokeDynamicSetter(
-            selector, null, input, node.inputs[2], false);
-      } else {
-        // Change the call to a regular invoke dynamic call.
-        return new HInvokeDynamicMethod(
-            selector, node.inputs.getRange(1, node.inputs.length - 1));
-      }
-    }
-
     // If the intercepted call is through a constant interceptor, we
     // know which element to call.
     if (node is !HOneShotInterceptor
@@ -337,7 +324,10 @@
         && selector.isCall()) {
       DartType type = interceptor.instructionType.computeType(compiler);
       ClassElement cls = type.element;
-      node.element = cls.lookupSelector(selector);
+      Element target = cls.lookupSelector(selector);
+      if (target != null && selector.applies(target, compiler)) {
+        node.element = target;
+      }
     }
     return node;
   }
@@ -347,7 +337,7 @@
     if (backend.fixedLengthListConstructor == null) {
       backend.fixedLengthListConstructor =
         compiler.listClass.lookupConstructor(
-            new Selector.callConstructor(const SourceString("fixedLength"),
+            new Selector.callConstructor(const SourceString(""),
                                          compiler.listClass.getLibrary()));
     }
     // TODO(ngeoffray): checking if the second input is an integer
@@ -355,6 +345,7 @@
     // other optimizations to reason on a fixed length constructor
     // that we know takes an int.
     return element == backend.fixedLengthListConstructor
+        && node.inputs.length == 2
         && node.inputs[1].isInteger();
   }
 
@@ -366,7 +357,7 @@
   }
 
   HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
-    if (node.isInterceptorCall) return handleInterceptorCall(node);
+    if (node.isCallOnInterceptor) return handleInterceptorCall(node);
     HType receiverType = node.receiver.instructionType;
     Selector selector = receiverType.refine(node.selector, compiler);
     Element element = compiler.world.locateSingleElement(selector);
@@ -589,7 +580,7 @@
     if (node.element == backend.jsArrayLength) {
       if (node.receiver is HInvokeStatic) {
         // Try to recognize the length getter with input
-        // [:new List.fixedLength(int):].
+        // [:new List(int):].
         HInvokeStatic call = node.receiver;
         if (isFixedSizeListConstructor(call)) {
           return call.inputs[1];
@@ -600,7 +591,7 @@
   }
 
   HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
-    if (node.isInterceptorCall) return handleInterceptorCall(node);
+    if (node.isCallOnInterceptor) return handleInterceptorCall(node);
 
     Element field =
         findConcreteFieldForDynamicAccess(node.receiver, node.selector);
@@ -616,6 +607,14 @@
     HFieldGet result = new HFieldGet(
         field, node.inputs[0], isAssignable: !isFinalOrConst);
 
+    // Some native fields are views of data that may be changed by operations.
+    // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2).
+    // TODO(sra): Refine the effect classification so that native effects are
+    // distinct from ordinary Dart effects.
+    if (field.isNative()) {
+      result.setDependsOnSomething();
+    }
+
     if (field.getEnclosingClass().isNative()) {
       result.instructionType =
           new HType.subtype(field.computeType(compiler), compiler);
@@ -636,12 +635,15 @@
   }
 
   HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
-    if (node.isInterceptorCall) return handleInterceptorCall(node);
+    if (node.isCallOnInterceptor) return handleInterceptorCall(node);
 
     Element field =
         findConcreteFieldForDynamicAccess(node.receiver, node.selector);
     if (field == null || !field.isAssignable()) return node;
-    HInstruction value = node.inputs[1];
+    // Use [:node.inputs.last:] in case the call follows the
+    // interceptor calling convention, but is not a call on an
+    // interceptor.
+    HInstruction value = node.inputs.last;
     if (compiler.enableTypeAssertions) {
       HInstruction other = value.convertType(
           compiler,
@@ -670,9 +672,20 @@
 
   HInstruction visitInterceptor(HInterceptor node) {
     if (node.isConstant()) return node;
+    // If the intercepted object does not need to be intercepted, just
+    // return the object (the [:getInterceptor:] method would have
+    // returned the object).
+    HType type = node.receiver.instructionType;
+    if (!type.canBePrimitive(compiler)) {
+      if (!(type.canBeNull()
+            && node.interceptedClasses.contains(compiler.objectClass))) {
+        return node.receiver;
+      }
+    }
     HInstruction constant = tryComputeConstantInterceptor(
         node.inputs[0], node.interceptedClasses);
     if (constant == null) return node;
+
     return constant;
   }
 
@@ -1080,8 +1093,8 @@
     // loop changes flags list to zero so we can use bitwise or when
     // propagating loop changes upwards.
     final int length = graph.blocks.length;
-    blockChangesFlags = new List<int>.fixedLength(length);
-    loopChangesFlags = new List<int>.fixedLength(length);
+    blockChangesFlags = new List<int>(length);
+    loopChangesFlags = new List<int>(length);
     for (int i = 0; i < length; i++) loopChangesFlags[i] = 0;
 
     // Run through all the basic blocks in the graph and fill in the
@@ -1156,7 +1169,7 @@
   List<ValueSet> values;
 
   void visitGraph(HGraph graph) {
-    values = new List<ValueSet>.fixedLength(graph.blocks.length);
+    values = new List<ValueSet>(graph.blocks.length);
     for (int i = 0; i < graph.blocks.length; i++) {
       values[graph.blocks[i].id] = new ValueSet();
     }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index fb62f89..fd4884c 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -176,36 +176,32 @@
   String temporaryId(HInstruction instruction) {
     String prefix;
     HType type = instruction.instructionType;
-    if (!type.isPrimitive()) {
-      prefix = 'U';
+    if (type == HType.MUTABLE_ARRAY) {
+      prefix = 'm';
+    } else if (type == HType.READABLE_ARRAY) {
+      prefix = 'a';
+    } else if (type == HType.EXTENDABLE_ARRAY) {
+      prefix = 'e';
+    } else if (type == HType.BOOLEAN) {
+      prefix = 'b';
+    } else if (type == HType.INTEGER) {
+      prefix = 'i';
+    } else if (type == HType.DOUBLE) {
+      prefix = 'd';
+    } else if (type == HType.NUMBER) {
+      prefix = 'n';
+    } else if (type == HType.STRING) {
+      prefix = 's';
+    } else if (type == HType.UNKNOWN) {
+      prefix = 'v';
+    } else if (type == HType.CONFLICTING) {
+      prefix = 'c';
+    } else if (type == HType.INDEXABLE_PRIMITIVE) {
+      prefix = 'r';
+    } else if (type == HType.NULL) {
+      prefix = 'u';
     } else {
-      if (type == HType.MUTABLE_ARRAY) {
-        prefix = 'm';
-      } else if (type == HType.READABLE_ARRAY) {
-        prefix = 'a';
-      } else if (type == HType.EXTENDABLE_ARRAY) {
-        prefix = 'e';
-      } else if (type == HType.BOOLEAN) {
-        prefix = 'b';
-      } else if (type == HType.INTEGER) {
-        prefix = 'i';
-      } else if (type == HType.DOUBLE) {
-        prefix = 'd';
-      } else if (type == HType.NUMBER) {
-        prefix = 'n';
-      } else if (type == HType.STRING) {
-        prefix = 's';
-      } else if (type == HType.UNKNOWN) {
-        prefix = 'v';
-      } else if (type == HType.CONFLICTING) {
-        prefix = 'c';
-      } else if (type == HType.INDEXABLE_PRIMITIVE) {
-        prefix = 'r';
-      } else if (type == HType.NULL) {
-        prefix = 'u';
-      } else {
-        prefix = 'x';
-      }
+      prefix = 'U';
     }
     return "$prefix${instruction.id}";
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index 8372c2b..0c0ad12 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -8,114 +8,74 @@
   const HType();
 
   /**
-   * Returns an [HType] that represents [type] and all types that have
-   * [type] as supertype.
+   * Returns an [HType] with the given type mask. The factory method
+   * takes care to track whether or not the resulting type may be a
+   * primitive type.
    */
-  factory HType.fromBoundedType(DartType type,
-                                Compiler compiler,
-                                {bool canBeNull: true,
-                                 bool isExact: false,
-                                 bool isInterfaceType: true}) {
-    Element element = type.element;
+  factory HType.fromMask(TypeMask mask, Compiler compiler) {
+    Element element = mask.base.element;
     if (element.kind == ElementKind.TYPE_VARIABLE) {
-      // TODO(ngeoffray): Replace object type with [type].
-      return new HBoundedPotentialPrimitiveType(
-          compiler.objectClass.computeType(compiler),
-          true,
-          canBeNull: canBeNull,
-          isInterfaceType: isInterfaceType);
+      // TODO(ngeoffray): Can we do better here?
+      DartType base = compiler.objectClass.computeType(compiler);
+      mask = new TypeMask.internal(base, mask.flags);
+      return new HBoundedType(mask);
     }
 
+    bool isNullable = mask.isNullable;
     JavaScriptBackend backend = compiler.backend;
     if (element == compiler.intClass || element == backend.jsIntClass) {
-      return canBeNull ? HType.INTEGER_OR_NULL : HType.INTEGER;
+      return isNullable ? HType.INTEGER_OR_NULL : HType.INTEGER;
     } else if (element == compiler.numClass
                || element == backend.jsNumberClass) {
-      return canBeNull ? HType.NUMBER_OR_NULL : HType.NUMBER;
+      return isNullable ? HType.NUMBER_OR_NULL : HType.NUMBER;
     } else if (element == compiler.doubleClass
                || element == backend.jsDoubleClass) {
-      return canBeNull ? HType.DOUBLE_OR_NULL : HType.DOUBLE;
+      return isNullable ? HType.DOUBLE_OR_NULL : HType.DOUBLE;
     } else if (element == compiler.stringClass
                || element == backend.jsStringClass) {
-      return canBeNull ? HType.STRING_OR_NULL : HType.STRING;
+      return isNullable ? HType.STRING_OR_NULL : HType.STRING;
     } else if (element == compiler.boolClass
                || element == backend.jsBoolClass) {
-      return canBeNull ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN;
+      return isNullable ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN;
     } else if (element == compiler.nullClass
                || element == backend.jsNullClass) {
       return HType.NULL;
     } else if (element == backend.jsArrayClass) {
-      return canBeNull
+      return isNullable
           ? HType.READABLE_ARRAY.union(HType.NULL, compiler)
           : HType.READABLE_ARRAY;
-    } else if (isInterfaceType) {
-      if (element == compiler.listClass
-          || Elements.isListSupertype(element, compiler)) {
-        return new HBoundedPotentialPrimitiveArray(
-            type,
-            canBeNull: canBeNull,
-            isInterfaceType: isInterfaceType);
-      } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
-        return new HBoundedPotentialPrimitiveNumberOrString(
-            type,
-            canBeNull: canBeNull,
-            isInterfaceType: isInterfaceType);
-      } else if (Elements.isStringOnlySupertype(element, compiler)) {
-        return new HBoundedPotentialPrimitiveString(
-            type,
-            canBeNull: canBeNull,
-            isInterfaceType: isInterfaceType);
-      }
     }
-    if (!isExact && (element == compiler.objectClass ||
-                     element == compiler.dynamicClass)) {
-      return new HBoundedPotentialPrimitiveType(
-          compiler.objectClass.computeType(compiler),
-          true,
-          canBeNull: canBeNull,
-          isInterfaceType: isInterfaceType);
-    }
-    return new HBoundedType(
-        type,
-        canBeNull: canBeNull,
-        isExact: isExact,
-        isInterfaceType: isInterfaceType);
+    return new HBoundedType(mask);
   }
 
-  factory HType.nonNullExactClass(DartType type, Compiler compiler) {
-    return new HType.fromBoundedType(
-        type,
-        compiler,
-        canBeNull: false,
-        isExact: true,
-        isInterfaceType: false);
+  factory HType.exact(DartType type, Compiler compiler) {
+    TypeMask mask = new TypeMask.exact(type);
+    return new HType.fromMask(mask, compiler);
   }
 
-  factory HType.nonNullSubclass(DartType type, Compiler compiler) {
-    return new HType.fromBoundedType(
-        type,
-        compiler,
-        canBeNull: false,
-        isExact: false,
-        isInterfaceType: false);
+  factory HType.subclass(DartType type, Compiler compiler) {
+    TypeMask mask = new TypeMask.subclass(type);
+    return new HType.fromMask(mask, compiler);
   }
 
   factory HType.subtype(DartType type, Compiler compiler) {
-    return new HType.fromBoundedType(
-        type,
-        compiler,
-        canBeNull: true,
-        isExact: false,
-        isInterfaceType: true);
+    TypeMask mask = new TypeMask.subtype(type);
+    return new HType.fromMask(mask, compiler);
+  }
+
+  factory HType.nonNullExact(DartType type, Compiler compiler) {
+    TypeMask mask = new TypeMask.nonNullExact(type);
+    return new HType.fromMask(mask, compiler);
+  }
+
+  factory HType.nonNullSubclass(DartType type, Compiler compiler) {
+    TypeMask mask = new TypeMask.nonNullSubclass(type);
+    return new HType.fromMask(mask, compiler);
   }
 
   factory HType.nonNullSubtype(DartType type, Compiler compiler) {
-    return new HType.fromBoundedType(
-        type,
-        compiler,
-        canBeNull: false,
-        isExact: false,
-        isInterfaceType: true);
+    TypeMask mask = new TypeMask.nonNullSubtype(type);
+    return new HType.fromMask(mask, compiler);
   }
 
   factory HType.fromBaseType(BaseType baseType, Compiler compiler) {
@@ -132,7 +92,7 @@
       return new HType.nonNullSubtype(
           compiler.mapLiteralClass.computeType(compiler), compiler);
     } else {
-      return new HType.nonNullExactClass(
+      return new HType.nonNullExact(
           cls.computeType(compiler), compiler);
     }
   }
@@ -165,7 +125,7 @@
   // like [native.SpecialType.JsObject], or [native.SpecialType.JsArray].
   factory HType.fromNativeType(type, Compiler compiler) {
     if (type == native.SpecialType.JsObject) {
-      return new HType.nonNullExactClass(
+      return new HType.nonNullExact(
           compiler.objectClass.computeType(compiler), compiler);
     } else if (type == native.SpecialType.JsArray) {
       return HType.READABLE_ARRAY;
@@ -187,6 +147,26 @@
     return ssaType;
   }
 
+  factory HType.readableArrayOrNull(Compiler compiler) {
+    return new HBoundedType(
+        READABLE_ARRAY.computeMask(compiler).nullable());
+  }
+
+  factory HType.mutableArrayOrNull(Compiler compiler) {
+    return new HBoundedType(
+        MUTABLE_ARRAY.computeMask(compiler).nullable());
+  }
+
+  factory HType.fixedArrayOrNull(Compiler compiler) {
+    return new HBoundedType(
+        FIXED_ARRAY.computeMask(compiler).nullable());
+  }
+
+  factory HType.extendableArrayOrNull(Compiler compiler) {
+    return new HBoundedType(
+        EXTENDABLE_ARRAY.computeMask(compiler).nullable());
+  }
+
   static const HType CONFLICTING = const HConflictingType();
   static const HType UNKNOWN = const HUnknownType();
   static const HType BOOLEAN = const HBooleanType();
@@ -209,53 +189,52 @@
 
   bool isConflicting() => identical(this, CONFLICTING);
   bool isUnknown() => identical(this, UNKNOWN);
+  bool isExact() => false;
   bool isNull() => false;
   bool isBoolean() => false;
   bool isNumber() => false;
   bool isInteger() => false;
   bool isDouble() => false;
   bool isString() => false;
-  bool isBooleanOrNull() => false;
-  bool isNumberOrNull() => false;
-  bool isIntegerOrNull() => false;
-  bool isDoubleOrNull() => false;
-  bool isStringOrNull() => false;
   bool isIndexablePrimitive() => false;
   bool isFixedArray() => false;
   bool isReadableArray() => false;
   bool isMutableArray() => false;
   bool isExtendableArray() => false;
   bool isPrimitive() => false;
-  bool isExact() => false;
-  bool isPrimitiveOrNull() => false;
-  bool isTop() => false;
-  bool isInterfaceType() => false;
 
-  bool canBePrimitive() => false;
+  bool isBooleanOrNull() => false;
+  bool isNumberOrNull() => false;
+  bool isIntegerOrNull() => false;
+  bool isDoubleOrNull() => false;
+  bool isStringOrNull() => false;
+  bool isPrimitiveOrNull() => false;
+
   bool canBeNull() => false;
+  bool canBePrimitive(Compiler compiler) => false;
+  bool canBePrimitiveNumber(Compiler compiler) => false;
+  bool canBePrimitiveString(Compiler compiler) => false;
+  bool canBePrimitiveArray(Compiler compiler) => false;
 
   /** A type is useful it is not unknown, not conflicting, and not null. */
   bool isUseful() => !isUnknown() && !isConflicting() && !isNull();
   /** Alias for isReadableArray. */
   bool isArray() => isReadableArray();
 
-  DartType computeType(Compiler compiler);
+  TypeMask computeMask(Compiler compiler);
 
   Selector refine(Selector selector, Compiler compiler) {
-    DartType receiverType = computeType(compiler);
-    if (receiverType != null && !receiverType.isMalformed) {
-      if (isExact()) {
-        return new TypedSelector.exact(receiverType, selector);
-      } else if (isInterfaceType()) {
-        return new TypedSelector.subtype(receiverType, selector);
-      } else {
-        return new TypedSelector.subclass(receiverType, selector);
-      }
-    } else {
-      return selector;
-    }
+    TypeMask mask = computeMask(compiler);
+    // TODO(kasperl): Should we check if the refinement really is more
+    // specialized than the starting point?
+    if (mask == null || mask.base.isMalformed) return selector;
+    return new TypedSelector(mask, selector);
   }
 
+  // TODO(kasperl): Try to get rid of these.
+  DartType computeType(Compiler compiler);
+  bool isTop(Compiler compiler) => false;
+
   /**
    * The intersection of two types is the intersection of its values. For
    * example:
@@ -293,11 +272,12 @@
   String toString() => name;
 
   DartType computeType(Compiler compiler) => null;
+  TypeMask computeMask(Compiler compiler) => null;
 }
 
 class HUnknownType extends HAnalysisType {
   const HUnknownType() : super("unknown");
-  bool canBePrimitive() => true;
+  bool canBePrimitive(Compiler compiler) => true;
   bool canBeNull() => true;
 
   HType union(HType other, Compiler compiler) => this;
@@ -306,7 +286,7 @@
 
 class HConflictingType extends HAnalysisType {
   const HConflictingType() : super("conflicting");
-  bool canBePrimitive() => true;
+  bool canBePrimitive(Compiler compiler) => true;
   bool canBeNull() => true;
 
   HType union(HType other, Compiler compiler) => other;
@@ -316,7 +296,7 @@
 abstract class HPrimitiveType extends HType {
   const HPrimitiveType();
   bool isPrimitive() => true;
-  bool canBePrimitive() => true;
+  bool canBePrimitive(Compiler compiler) => true;
   bool isPrimitiveOrNull() => true;
   bool isExact() => true;
 }
@@ -332,6 +312,10 @@
     return backend.jsNullClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.exact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.NULL;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -356,7 +340,7 @@
 
 abstract class HPrimitiveOrNullType extends HType {
   const HPrimitiveOrNullType();
-  bool canBePrimitive() => true;
+  bool canBePrimitive(Compiler compiler) => true;
   bool canBeNull() => true;
   bool isPrimitiveOrNull() => true;
 }
@@ -371,6 +355,10 @@
     return backend.jsBoolClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.exact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.BOOLEAN_OR_NULL;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -385,7 +373,7 @@
     if (other.isUnknown()) return HType.BOOLEAN_OR_NULL;
     if (other.isBoolean()) return HType.BOOLEAN;
     if (other.isBooleanOrNull()) return HType.BOOLEAN_OR_NULL;
-    if (other.isTop()) {
+    if (other.isTop(compiler)) {
       return other.canBeNull() ? this : HType.BOOLEAN;
     }
     if (other.canBeNull()) return HType.NULL;
@@ -404,6 +392,10 @@
     return backend.jsBoolClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.nonNullExact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.BOOLEAN;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -427,13 +419,16 @@
   bool isNumberOrNull() => true;
   String toString() => "number or null";
   bool isExact() => false;
-  bool isInterfaceType() => true;
 
   DartType computeType(Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
     return backend.jsNumberClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.subclass(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.NUMBER_OR_NULL;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -452,7 +447,7 @@
     if (other.isIntegerOrNull()) return HType.INTEGER_OR_NULL;
     if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
     if (other.isNumberOrNull()) return HType.NUMBER_OR_NULL;
-    if (other.isTop()) {
+    if (other.isTop(compiler)) {
       return other.canBeNull() ? this : HType.NUMBER;
     }
     if (other.canBeNull()) return HType.NULL;
@@ -466,13 +461,16 @@
   bool isNumberOrNull() => true;
   String toString() => "number";
   bool isExact() => false;
-  bool isInterfaceType() => true;
 
   DartType computeType(Compiler compiler) {
     JavaScriptBackend backend = compiler.backend;
     return backend.jsNumberClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.nonNullSubclass(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.NUMBER;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -503,6 +501,10 @@
     return backend.jsIntClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.exact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.INTEGER_OR_NULL;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -523,7 +525,7 @@
     if (other.isDoubleOrNull()) return HType.NULL;
     if (other.isNumber()) return HType.INTEGER;
     if (other.isNumberOrNull()) return HType.INTEGER_OR_NULL;
-    if (other.isTop()) {
+    if (other.isTop(compiler)) {
       return other.canBeNull() ? this : HType.INTEGER;
     }
     if (other.canBeNull()) return HType.NULL;
@@ -542,6 +544,10 @@
     return backend.jsIntClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.nonNullExact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.INTEGER;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -576,6 +582,10 @@
     return backend.jsDoubleClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.exact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.DOUBLE_OR_NULL;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -596,7 +606,7 @@
     if (other.isDoubleOrNull()) return HType.DOUBLE_OR_NULL;
     if (other.isNumber()) return HType.DOUBLE;
     if (other.isNumberOrNull()) return HType.DOUBLE_OR_NULL;
-    if (other.isTop()) {
+    if (other.isTop(compiler)) {
       return other.canBeNull() ? this : HType.DOUBLE;
     }
     if (other.canBeNull()) return HType.NULL;
@@ -615,6 +625,10 @@
     return backend.jsDoubleClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.nonNullExact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.DOUBLE;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -649,15 +663,20 @@
     return null;
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    // TODO(ngeoffray): Represent union types.
+    return null;
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.INDEXABLE_PRIMITIVE;
     if (other.isUnknown()) return HType.UNKNOWN;
     if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
-    if (other is HBoundedPotentialPrimitiveString) {
+    if (other.canBePrimitiveString(compiler)) {
       // TODO(ngeoffray): Represent union types.
       return HType.UNKNOWN;
     }
-    if (other is HBoundedPotentialPrimitiveArray) {
+    if (other.canBePrimitiveArray(compiler)) {
       // TODO(ngeoffray): Represent union types.
       return HType.UNKNOWN;
     }
@@ -668,8 +687,8 @@
     if (other.isConflicting()) return HType.CONFLICTING;
     if (other.isUnknown()) return HType.INDEXABLE_PRIMITIVE;
     if (other.isIndexablePrimitive()) return other;
-    if (other is HBoundedPotentialPrimitiveString) return HType.STRING;
-    if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY;
+    if (other.canBePrimitiveString(compiler)) return HType.STRING;
+    if (other.canBePrimitiveArray(compiler)) return HType.READABLE_ARRAY;
     return HType.CONFLICTING;
   }
 }
@@ -684,6 +703,10 @@
     return backend.jsStringClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.exact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.STRING_OR_NULL;
     if (other.isUnknown()) return HType.UNKNOWN;
@@ -694,15 +717,12 @@
       // primitive.
       return HType.UNKNOWN;
     }
-    if (other is HBoundedPotentialPrimitiveString) {
+    if (other.canBePrimitiveString(compiler)) {
       if (other.canBeNull()) {
         return other;
       } else {
-        HBoundedType boundedType = other;
-        return new HBoundedPotentialPrimitiveString(
-            boundedType.type,
-            canBeNull: true,
-            isInterfaceType: other.isInterfaceType());
+        TypeMask otherMask = other.computeMask(compiler);
+        return new HType.fromMask(otherMask.nullable(), compiler);
       }
     }
     if (other.isNull()) return HType.STRING_OR_NULL;
@@ -716,10 +736,10 @@
     if (other.isStringOrNull()) return HType.STRING_OR_NULL;
     if (other.isArray()) return HType.CONFLICTING;
     if (other.isIndexablePrimitive()) return HType.STRING;
-    if (other is HBoundedPotentialPrimitiveString) {
+    if (other.canBePrimitiveString(compiler)) {
       return other.canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
     }
-    if (other.isTop()) {
+    if (other.isTop(compiler)) {
       return other.canBeNull() ? this : HType.STRING;
     }
     if (other.canBeNull()) return HType.NULL;
@@ -738,13 +758,17 @@
     return backend.jsStringClass.computeType(compiler);
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.nonNullExact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.STRING;
     if (other.isUnknown()) return HType.UNKNOWN;
     if (other.isString()) return HType.STRING;
     if (other.isStringOrNull()) return HType.STRING_OR_NULL;
     if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
-    if (other is HBoundedPotentialPrimitiveString) return other;
+    if (other.canBePrimitiveString(compiler)) return other;
     if (other.isNull()) return HType.STRING_OR_NULL;
     return HType.UNKNOWN;
   }
@@ -756,7 +780,7 @@
     if (other.isArray()) return HType.CONFLICTING;
     if (other.isIndexablePrimitive()) return HType.STRING;
     if (other.isStringOrNull()) return HType.STRING;
-    if (other is HBoundedPotentialPrimitiveString) return HType.STRING;
+    if (other.canBePrimitiveString(compiler)) return HType.STRING;
     return HType.CONFLICTING;
   }
 }
@@ -771,19 +795,17 @@
     return backend.jsArrayClass.rawType;
   }
 
+  TypeMask computeMask(Compiler compiler) {
+    return new TypeMask.nonNullExact(computeType(compiler));
+  }
+
   HType union(HType other, Compiler compiler) {
     if (other.isConflicting()) return HType.READABLE_ARRAY;
     if (other.isUnknown()) return HType.UNKNOWN;
     if (other.isReadableArray()) return HType.READABLE_ARRAY;
     if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
-    if (other is HBoundedPotentialPrimitiveArray) return other;
-    if (other.isNull()) {
-      // TODO(ngeoffray): This should be readable array or null.
-      return new HBoundedPotentialPrimitiveArray(
-          compiler.listClass.computeType(compiler),
-          canBeNull: true,
-          isInterfaceType: true);
-    }
+    if (other.canBePrimitiveArray(compiler)) return other;
+    if (other.isNull()) return new HType.readableArrayOrNull(compiler);
     return HType.UNKNOWN;
   }
 
@@ -793,7 +815,7 @@
     if (other.isString()) return HType.CONFLICTING;
     if (other.isReadableArray()) return other;
     if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY;
-    if (other is HBoundedPotentialPrimitiveArray) return HType.READABLE_ARRAY;
+    if (other.canBePrimitiveArray(compiler)) return HType.READABLE_ARRAY;
     return HType.CONFLICTING;
   }
 }
@@ -809,14 +831,8 @@
     if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
     if (other.isReadableArray()) return HType.READABLE_ARRAY;
     if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
-    if (other is HBoundedPotentialPrimitiveArray) return other;
-    if (other.isNull()) {
-      // TODO(ngeoffray): This should be mutable array or null.
-      return new HBoundedPotentialPrimitiveArray(
-          compiler.listClass.computeType(compiler),
-          canBeNull: true,
-          isInterfaceType: true);
-    }
+    if (other.canBePrimitiveArray(compiler)) return other;
+    if (other.isNull()) return new HType.mutableArrayOrNull(compiler);
     return HType.UNKNOWN;
   }
 
@@ -826,7 +842,7 @@
     if (other.isMutableArray()) return other;
     if (other.isString()) return HType.CONFLICTING;
     if (other.isIndexablePrimitive()) return HType.MUTABLE_ARRAY;
-    if (other is HBoundedPotentialPrimitiveArray) return HType.MUTABLE_ARRAY;
+    if (other.canBePrimitiveArray(compiler)) return HType.MUTABLE_ARRAY;
     return HType.CONFLICTING;
   }
 }
@@ -843,14 +859,8 @@
     if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
     if (other.isReadableArray()) return HType.READABLE_ARRAY;
     if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
-    if (other is HBoundedPotentialPrimitiveArray) return other;
-    if (other.isNull()) {
-      // TODO(ngeoffray): This should be fixed array or null.
-      return new HBoundedPotentialPrimitiveArray(
-          compiler.listClass.computeType(compiler),
-          canBeNull: true,
-          isInterfaceType: true);
-    }
+    if (other.canBePrimitiveArray(compiler)) return other;
+    if (other.isNull()) return new HType.fixedArrayOrNull(compiler);
     return HType.UNKNOWN;
   }
 
@@ -861,7 +871,7 @@
     if (other.isExtendableArray()) return HType.CONFLICTING;
     if (other.isString()) return HType.CONFLICTING;
     if (other.isIndexablePrimitive()) return HType.FIXED_ARRAY;
-    if (other is HBoundedPotentialPrimitiveArray) return HType.FIXED_ARRAY;
+    if (other.canBePrimitiveArray(compiler)) return HType.FIXED_ARRAY;
     return HType.CONFLICTING;
   }
 }
@@ -878,14 +888,8 @@
     if (other.isMutableArray()) return HType.MUTABLE_ARRAY;
     if (other.isReadableArray()) return HType.READABLE_ARRAY;
     if (other.isIndexablePrimitive()) return HType.INDEXABLE_PRIMITIVE;
-    if (other is HBoundedPotentialPrimitiveArray) return other;
-    if (other.isNull()) {
-      // TODO(ngeoffray): This should be extendable array or null.
-      return new HBoundedPotentialPrimitiveArray(
-          compiler.listClass.computeType(compiler),
-          canBeNull: true,
-          isInterfaceType: true);
-    }
+    if (other.canBePrimitiveArray(compiler)) return other;
+    if (other.isNull()) return new HType.extendableArrayOrNull(compiler);
     return HType.UNKNOWN;
   }
 
@@ -896,61 +900,82 @@
     if (other.isString()) return HType.CONFLICTING;
     if (other.isFixedArray()) return HType.CONFLICTING;
     if (other.isIndexablePrimitive()) return HType.EXTENDABLE_ARRAY;
-    if (other is HBoundedPotentialPrimitiveArray) return HType.EXTENDABLE_ARRAY;
+    if (other.canBePrimitiveArray(compiler)) return HType.EXTENDABLE_ARRAY;
     return HType.CONFLICTING;
   }
 }
 
 class HBoundedType extends HType {
-  final DartType type;
-  final bool _canBeNull;
-  final bool _isExact;
-  final bool _isInterfaceType;
+  final TypeMask mask;
+  const HBoundedType(this.mask);
 
-  String toString() {
-    return 'BoundedType($type, canBeNull: $_canBeNull, isExact: $_isExact)';
+  bool isExact() => mask.isExact;
+  bool isTop(Compiler compiler) => mask.containsAll(compiler);
+
+  bool canBeNull() => mask.isNullable;
+
+  bool canBePrimitive(Compiler compiler) {
+    return canBePrimitiveNumber(compiler)
+        || canBePrimitiveArray(compiler)
+        || canBePrimitiveString(compiler);
   }
 
-  bool canBeNull() => _canBeNull;
-  bool isExact() => _isExact;
-  bool isInterfaceType() => _isInterfaceType;
+  bool canBePrimitiveNumber(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    DartType jsNumberType = backend.jsNumberClass.computeType(compiler);
+    return mask.contains(jsNumberType, compiler);
+  }
 
-  const HBoundedType(DartType this.type,
-                     {bool canBeNull: true,
-                      bool isExact: false,
-                      bool isInterfaceType: true})
-      : _canBeNull = canBeNull,
-        _isExact = isExact,
-        _isInterfaceType = isInterfaceType;
+  bool canBePrimitiveArray(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    DartType jsArrayType = backend.jsArrayClass.computeType(compiler);
+    return mask.contains(jsArrayType, compiler);
+  }
 
-  const HBoundedType.exact(DartType this.type)
-      : _canBeNull = false, _isExact = true, _isInterfaceType = false;
+  bool canBePrimitiveString(Compiler compiler) {
+    JavaScriptBackend backend = compiler.backend;
+    DartType jsStringType = backend.jsStringClass.computeType(compiler);
+    return mask.contains(jsStringType, compiler);
+  }
 
-  DartType computeType(Compiler compiler) => type;
+  DartType computeType(Compiler compiler) => mask.base;
+  TypeMask computeMask(Compiler compiler) => mask;
+
+  bool operator ==(HType other) {
+    if (other is !HBoundedType) return false;
+    HBoundedType bounded = other;
+    return mask == bounded.mask;
+  }
 
   HType intersection(HType other, Compiler compiler) {
     if (this == other) return this;
     if (other.isConflicting()) return HType.CONFLICTING;
+    if (isTop(compiler)) return other;
     if (other.isNull()) return canBeNull() ? HType.NULL : HType.CONFLICTING;
 
-    if (other is HBoundedType) {
-      HBoundedType temp = other;
-      DartType otherType = temp.type;
-      if (!type.isMalformed && !otherType.isMalformed) {
-        DartType intersectionType;
-        if (type == otherType || compiler.types.isSubtype(type, otherType)) {
-          intersectionType = type;
-        } else if (compiler.types.isSubtype(otherType, type)) {
-          intersectionType = otherType;
-        }
-        if (intersectionType != null) {
-          return new HType.fromBoundedType(
-              intersectionType,
-              compiler,
-              canBeNull: canBeNull() && temp.canBeNull(),
-              isExact: isExact() || other.isExact(),
-              isInterfaceType: isInterfaceType() && other.isInterfaceType());
-        }
+    if (canBePrimitiveArray(compiler)) {
+      if (other.isArray()) return other;
+      if (other.isStringOrNull()) {
+        return other.isString() ? HType.CONFLICTING : HType.NULL;
+      }
+      if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY;
+    }
+
+    if (canBePrimitiveString(compiler)) {
+      if (other.isArray()) return HType.CONFLICTING;
+      if (other.isString()) return HType.STRING;
+      if (other.isStringOrNull()) {
+        return canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
+      }
+      if (other.isIndexablePrimitive()) return HType.STRING;
+    }
+
+    TypeMask otherMask = other.computeMask(compiler);
+    if (otherMask != null) {
+      TypeMask intersection = mask.intersection(otherMask, compiler.types);
+      if (intersection != null) {
+        if (intersection == mask) return this;
+        return new HType.fromMask(intersection, compiler);
       }
     }
     if (other.isUnknown()) return this;
@@ -958,212 +983,29 @@
     return HType.CONFLICTING;
   }
 
-  bool operator ==(HType other) {
-    if (other is !HBoundedType) return false;
-    HBoundedType bounded = other;
-    return type == bounded.type
-            && canBeNull() == bounded.canBeNull()
-            && isExact() == bounded.isExact()
-            && isInterfaceType() == bounded.isInterfaceType();
-  }
-
   HType union(HType other, Compiler compiler) {
     if (this == other) return this;
+    if (isTop(compiler)) return this;
     if (other.isNull()) {
       if (canBeNull()) {
         return this;
       } else {
-        return new HBoundedType(
-            type,
-            canBeNull: true,
-            isExact: this.isExact(),
-            isInterfaceType: this.isInterfaceType());
+        return new HType.fromMask(mask.nullable(), compiler);
       }
     }
-    if (other is HBoundedType) {
-      HBoundedType temp = other;
-      if (type != temp.type) return HType.UNKNOWN;
-      return new HType.fromBoundedType(
-          type,
-          compiler,
-          canBeNull: canBeNull() || other.canBeNull(),
-          isInterfaceType: isInterfaceType() || other.isInterfaceType(),
-          isExact: isExact() && other.isExact());
 
+    TypeMask otherMask = other.computeMask(compiler);
+    if (otherMask != null) {
+      TypeMask union = mask.union(otherMask, compiler.types);
+      if (union == null) return HType.UNKNOWN;
+      if (union == mask) return this;
+      return new HType.fromMask(union, compiler);
     }
     if (other.isConflicting()) return this;
     return HType.UNKNOWN;
   }
-}
-
-class HBoundedPotentialPrimitiveType extends HBoundedType {
-  final bool _isObject;
-  const HBoundedPotentialPrimitiveType(DartType type,
-                                       this._isObject,
-                                       {bool canBeNull: true,
-                                        bool isInterfaceType: true})
-      : super(type,
-              canBeNull: canBeNull,
-              isExact: false,
-              isInterfaceType: isInterfaceType);
 
   String toString() {
-    return 'BoundedPotentialPrimitiveType($type, canBeNull: $_canBeNull)';
-  }
-
-  bool canBePrimitive() => true;
-  bool isTop() => _isObject;
-
-  HType union(HType other, Compiler compiler) {
-    if (isTop()) {
-      // The union of the top type and another type is the top type.
-      if (!canBeNull() && other.canBeNull()) {
-        return new HBoundedPotentialPrimitiveType(
-            type, true, canBeNull: canBeNull(), isInterfaceType: true);
-      } else {
-        return this;
-      }
-    } else {
-      return super.union(other, compiler);
-    }
-  }
-
-  HType intersection(HType other, Compiler compiler) {
-    if (isTop()) {
-      // The intersection of the top type and any other type is the other type.
-      // TODO(ngeoffray): Also update the canBeNull information.
-      return other;
-    } else {
-      return super.intersection(other, compiler);
-    }
-  }
-}
-
-class HBoundedPotentialPrimitiveNumberOrString
-    extends HBoundedPotentialPrimitiveType {
-  const HBoundedPotentialPrimitiveNumberOrString(DartType type,
-                                                 {bool canBeNull: true,
-                                                  bool isInterfaceType: true})
-      : super(type,
-              false,
-              canBeNull: canBeNull,
-              isInterfaceType: isInterfaceType);
-
-  HType union(HType other, Compiler compiler) {
-    if (other.isNumber()) return this;
-    if (other.isNumberOrNull()) {
-      if (canBeNull()) return this;
-      return new HBoundedPotentialPrimitiveNumberOrString(
-          type, canBeNull: true, isInterfaceType: this.isInterfaceType());
-    }
-
-    if (other.isString()) return this;
-    if (other.isStringOrNull()) {
-      if (canBeNull()) return this;
-      return new HBoundedPotentialPrimitiveNumberOrString(
-          type, canBeNull: true, isInterfaceType: this.isInterfaceType());
-    }
-
-    if (other.isNull()) {
-      if (canBeNull()) return this;
-      return new HBoundedPotentialPrimitiveNumberOrString(
-          type, canBeNull: true, isInterfaceType: this.isInterfaceType());
-    }
-
-    return super.union(other, compiler);
-  }
-
-  HType intersection(HType other, Compiler compiler) {
-    if (other.isNumber()) return other;
-    if (other.isNumberOrNull()) {
-      if (!canBeNull()) return HType.NUMBER;
-      return other;
-    }
-    if (other.isString()) return other;
-    if (other.isStringOrNull()) {
-      if (!canBeNull()) return HType.STRING;
-      return other;
-    }
-    return super.intersection(other, compiler);
-  }
-}
-
-class HBoundedPotentialPrimitiveArray extends HBoundedPotentialPrimitiveType {
-  const HBoundedPotentialPrimitiveArray(DartType type,
-                                        {bool canBeNull: true,
-                                         bool isInterfaceType: true})
-      : super(type,
-              false,
-              canBeNull: canBeNull,
-              isInterfaceType: isInterfaceType);
-
-  HType union(HType other, Compiler compiler) {
-    if (other.isString()) return HType.UNKNOWN;
-    if (other.isReadableArray()) return this;
-    // TODO(ngeoffray): implement union types.
-    if (other.isIndexablePrimitive()) return HType.UNKNOWN;
-    if (other.isNull()) {
-      if (canBeNull()) {
-        return this;
-      } else {
-        return new HBoundedPotentialPrimitiveArray(
-            type, canBeNull: true, isInterfaceType: isInterfaceType());
-      }
-    }
-    return super.union(other, compiler);
-  }
-
-  HType intersection(HType other, Compiler compiler) {
-    if (other.isConflicting()) return HType.CONFLICTING;
-    if (other.isString()) return HType.CONFLICTING;
-    if (other.isReadableArray()) return other;
-    if (other.isIndexablePrimitive()) return HType.READABLE_ARRAY;
-    return super.intersection(other, compiler);
-  }
-}
-
-class HBoundedPotentialPrimitiveString extends HBoundedPotentialPrimitiveType {
-  const HBoundedPotentialPrimitiveString(DartType type,
-                                         {bool canBeNull: true,
-                                          bool isInterfaceType: true})
-      : super(type,
-              false,
-              canBeNull: canBeNull,
-              isInterfaceType: isInterfaceType);
-
-  bool isPrimitiveOrNull() => true;
-
-  HType union(HType other, Compiler compiler) {
-    if (other.isString()) return this;
-    if (other.isStringOrNull()) {
-      if (canBeNull()) {
-        return this;
-      } else {
-        return new HBoundedPotentialPrimitiveString(
-            type, canBeNull: true, isInterfaceType: isInterfaceType());
-      }
-    }
-    if (other.isNull()) {
-      if (canBeNull()) {
-        return this;
-      } else {
-        return new HBoundedPotentialPrimitiveString(
-            type, canBeNull: true, isInterfaceType: isInterfaceType());
-      }
-    }
-    // TODO(ngeoffray): implement union types.
-    if (other.isIndexablePrimitive()) return HType.UNKNOWN;
-    return super.union(other, compiler);
-  }
-
-  HType intersection(HType other, Compiler compiler) {
-    if (other.isConflicting()) return HType.CONFLICTING;
-    if (other.isString()) return HType.STRING;
-    if (other.isStringOrNull()) {
-      return canBeNull() ? HType.STRING_OR_NULL : HType.STRING;
-    }
-    if (other.isReadableArray()) return HType.CONFLICTING;
-    if (other.isIndexablePrimitive()) return HType.STRING;
-    return super.intersection(other, compiler);
+    return 'BoundedType(mask=$mask)';
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 71a20d6..4f1f4c98 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -136,7 +136,7 @@
     DartType functionType = compiler.functionClass.computeType(compiler);
     for (Element each in compiler.world.allFunctions.filter(refined)) {
       HType inferred = (refined.isGetter() && each.isFunction())
-          ? new HType.nonNullExactClass(functionType, compiler)
+          ? new HType.nonNullExact(functionType, compiler)
           : new HType.inferredForElement(each, compiler);
       type = type.union(inferred, compiler);
       if (type.isUnknown()) break;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/value_set.dart b/sdk/lib/_internal/compiler/implementation/ssa/value_set.dart
index d565de7..b68e688 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/value_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/value_set.dart
@@ -8,7 +8,7 @@
   int size = 0;
   List<HInstruction> table;
   ValueSetNode collisions;
-  ValueSet() : table = new List<HInstruction>.fixedLength(8);
+  ValueSet() : table = new List<HInstruction>(8);
 
   bool get isEmpty => size == 0;
   int get length => size;
@@ -137,7 +137,7 @@
     // Reset the table with a bigger capacity.
     assert(capacity > table.length);
     size = 0;
-    table = new List<HInstruction>.fixedLength(capacity);
+    table = new List<HInstruction>(capacity);
     collisions = null;
     // Add the old instructions to the new table.
     copyTo(this, oldTable, oldCollisions);
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index 114e8e9..6373921 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -4,6 +4,7 @@
 
 library simple_types_inferrer;
 
+import '../closure.dart' show ClosureClassMap;
 import '../native_handler.dart' as native;
 import '../elements/elements.dart';
 import '../dart2jslib.dart';
@@ -384,6 +385,13 @@
     return result;
   }
 
+  bool isNotClosure(Element element) {
+    // If the outermost enclosing element of [element] is [element]
+    // itself, we know it cannot be a closure.
+    Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
+    return outermost.declaration == element.declaration;
+  }
+
   /**
    * Registers that [caller] calls [callee] with the given
    * [arguments].
@@ -391,6 +399,7 @@
   void registerCalledElement(Element caller,
                              Element callee,
                              ArgumentsTypes arguments) {
+    assert(isNotClosure(caller));
     if (analyzeCount.containsKey(caller)) return;
     callee = callee.implementation;
     Set<Element> callers = callersOf.putIfAbsent(
@@ -404,6 +413,7 @@
    */
   void registerGetterOnElement(Element caller,
                                Element callee) {
+    assert(isNotClosure(caller));
     if (analyzeCount.containsKey(caller)) return;
     callee = callee.implementation;
     Set<Element> callers = callersOf.putIfAbsent(
@@ -418,6 +428,7 @@
   void registerCalledSelector(Element caller,
                               Selector selector,
                               ArgumentsTypes arguments) {
+    assert(isNotClosure(caller));
     if (analyzeCount.containsKey(caller)) return;
     iterateOverElements(selector, (Element element) {
       assert(element.isImplementation);
@@ -433,6 +444,7 @@
    * through a property access.
    */
   void registerGetterOnSelector(Element caller, Selector selector) {
+    assert(isNotClosure(caller));
     if (analyzeCount.containsKey(caller)) return;
     iterateOverElements(selector, (Element element) {
       assert(element.isImplementation);
@@ -447,6 +459,7 @@
    * Registers that [caller] closurizes [function].
    */
   void registerGetFunction(Element caller, Element function) {
+    assert(isNotClosure(caller));
     assert(caller.isImplementation);
     if (analyzeCount.containsKey(caller)) return;
     // We don't register that [caller] calls [function] because we
@@ -514,6 +527,11 @@
    * [secondType].
    */
   Element computeLUB(Element firstType, Element secondType) {
+    bool isNumber(type) {
+      return type == compiler.numClass
+          || type == compiler.doubleClass
+          || type == compiler.intClass;
+    }
     assert(secondType != null);
     if (firstType == null) {
       return secondType;
@@ -524,6 +542,10 @@
     } else if (firstType == compiler.dynamicClass) {
       return firstType;
     } else if (firstType != secondType) {
+      if (isNumber(firstType) && isNumber(secondType)) {
+        // The JavaScript backend knows how to deal with numbers.
+        return compiler.numClass;
+      }
       // TODO(ngeoffray): Actually compute the least upper bound.
       return giveUpType;
     } else {
@@ -544,19 +566,114 @@
   toString() => "{ positional = $positional, named = $named }";
 }
 
+/**
+ * Placeholder for inferred types of local variables.
+ */
+class LocalsHandler {
+  final SimpleTypesInferrer inferrer;
+  final Map<Element, Element> locals;
+  final Set<Element> captured;
+  final bool inTryBlock;
+
+  LocalsHandler(this.inferrer)
+      : locals = new Map<Element, Element>(),
+        captured = new Set<Element>(),
+        inTryBlock = false;
+  LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
+      : locals = new Map<Element, Element>.from(other.locals),
+        captured = new Set<Element>.from(other.captured),
+        inTryBlock = other.inTryBlock || inTryBlock,
+        inferrer = other.inferrer;
+
+  Element use(Element local) {
+    return locals[local];
+  }
+
+  void update(Element local, Element type) {
+    assert(type != null);
+    if (captured.contains(local) || inTryBlock) {
+      // If a local is captured or is set in a try block, we compute the
+      // LUB of its assignments. We don't know if an assignment in a try block
+      // will be executed, so all assigments in a try block are
+      // potential types after we have left the try block.
+      type = inferrer.computeLUB(locals[local], type);
+      if (type == inferrer.giveUpType) type = inferrer.compiler.dynamicClass;
+    }
+    locals[local] = type;
+  }
+
+  void setCaptured(Element local) {
+    captured.add(local);
+  }
+
+  /**
+   * Merge handlers [first] and [second] into [:this:] and returns
+   * whether the merge changed one of the variables types in [first].
+   */
+  bool merge(LocalsHandler other) {
+    bool changed = false;
+    List<Element> toRemove = <Element>[];
+    // Iterating over a map and just updating its entries is OK.
+    locals.forEach((local, oldType) {
+      Element otherType = other.locals[local];
+      if (otherType == null) {
+        // If [local] is not in the other map, we know it is not a
+        // local we want to keep. For example, in an if/else, we don't
+        // want to keep variables declared in the if or in the else
+        // branch at the merge point.
+        toRemove.add(local);
+        return;
+      }
+      var type = inferrer.computeLUB(oldType, otherType);
+      if (type == inferrer.giveUpType) type = inferrer.compiler.dynamicClass;
+      if (type != oldType) changed = true;
+      locals[local] = type;
+    });
+
+    // Remove locals that will not be used anymore.
+    toRemove.forEach((Element element) {
+      locals.remove(element);
+    });
+
+    // Update the locals that are captured.
+    other.captured.forEach((Element element) {
+      if (locals.containsKey(element)) {
+        captured.add(element);
+      }
+    });
+    return changed;
+  }
+}
+
 class SimpleTypeInferrerVisitor extends ResolvedVisitor {
   final Element analyzedElement;
+  final Element outermostElement;
   final SimpleTypesInferrer inferrer;
   final Compiler compiler;
+  LocalsHandler locals;
   Element returnType;
 
-  SimpleTypeInferrerVisitor(Element element,
-                            Compiler compiler,
-                            this.inferrer)
-    : super(compiler.enqueuer.resolution.resolvedElements[element.declaration]),
-      analyzedElement = element,
-      compiler = compiler {
+  SimpleTypeInferrerVisitor.internal(TreeElements mapping,
+                                     this.analyzedElement,
+                                     this.outermostElement,
+                                     this.inferrer,
+                                     this.compiler,
+                                     this.locals)
+    : super(mapping);
+
+  factory SimpleTypeInferrerVisitor(Element element,
+                                    Compiler compiler,
+                                    SimpleTypesInferrer inferrer,
+                                    [LocalsHandler handler]) {
+    Element outermostElement =
+        element.getOutermostEnclosingMemberOrTopLevel().implementation;
+    TreeElements elements = compiler.enqueuer.resolution.resolvedElements[
+        outermostElement.declaration];
     assert(elements != null);
+    assert(outermostElement != null);
+    handler = handler != null ? handler : new LocalsHandler(inferrer);
+    return new SimpleTypeInferrerVisitor.internal(
+        elements, element, outermostElement, inferrer, compiler, handler);
   }
 
   Element run() {
@@ -567,12 +684,14 @@
       FunctionElement function = analyzedElement;
       FunctionSignature signature = function.computeSignature(compiler);
       signature.forEachParameter((element) {
+        // We don't track argument types yet, so just set the fields
+        // and parameters as dynamic.
         if (element.kind == ElementKind.FIELD_PARAMETER
             && element.modifiers.isFinal()) {
-          // We don't track argument types yet, so just set the field
-          // as dynamic.
           inferrer.recordFinalFieldType(
               analyzedElement, element.fieldElement, compiler.dynamicClass);
+        } else {
+          locals.update(element, compiler.dynamicClass);
         }
       });
       visit(node.initializers);
@@ -584,6 +703,13 @@
       // they return dynamic.
       returnType = compiler.dynamicClass;
     } else {
+      FunctionElement function = analyzedElement;
+      FunctionSignature signature = function.computeSignature(compiler);
+      signature.forEachParameter((element) {
+        // We don't track argument types yet, so just set the
+        // parameters as dynamic.
+        locals.update(element, compiler.dynamicClass);
+      });
       visit(node.body);
       if (returnType == null) {
         // No return in the body.
@@ -611,15 +737,37 @@
   }
 
   visitFunctionExpression(FunctionExpression node) {
+    // Fetch the closure data of [node] and mark all locals that are
+    // captured by [node] to be captured in the locals handler.
+    compiler.closureToClassMapper.computeClosureToClassMapping(
+        outermostElement, outermostElement.parseNode(compiler), elements);
+    ClosureClassMap nestedClosureData =
+        compiler.closureToClassMapper.getMappingForNestedFunction(node);
+
+    nestedClosureData.forEachCapturedVariable((variable) {
+      locals.setCaptured(variable);
+    });
     // We don't put the closure in the work queue of the
     // inferrer, because it will share information with its enclosing
     // method, like for example the types of local variables.
-    SimpleTypeInferrerVisitor visitor =
-        new SimpleTypeInferrerVisitor(elements[node], compiler, inferrer);
+    LocalsHandler closureLocals = new LocalsHandler.from(locals);
+    SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor(
+        elements[node], compiler, inferrer, closureLocals);
     visitor.run();
+    // Do not register the runtime type, because the analysis may be
+    // invalidated due to updates on locals.
+    // TODO(ngeoffray): Track return types of closures.
+    // The closure may have updated the type of locals.
+    locals.merge(closureLocals);
     return compiler.functionClass;
   }
 
+  visitFunctionDeclaration(FunctionDeclaration node) {
+    locals.update(elements[node], compiler.functionClass);
+    return visit(node.function);
+  }
+
+
   visitLiteralString(LiteralString node) {
     return compiler.stringClass;
   }
@@ -687,16 +835,20 @@
         return compiler.dynamicClass;
       }
     } else if (const SourceString("=") == op.source) {
-      // [: foo = 42 :]
-      visit(node.receiver);
+      // [: foo = 42 :] or [: foo.bar = 42 :].
+      if (element == null) {
+        visit(node.receiver);
+      }
       Link<Node> link = node.arguments;
       assert(!link.isEmpty && link.tail.isEmpty);
       Element type = link.head.accept(this);
 
-      if (!Elements.isUnresolved(element)
-          && element.isField()
-          && element.modifiers.isFinal()) {
-        inferrer.recordFinalFieldType(analyzedElement, element, type);
+      if (!Elements.isUnresolved(element)) {
+        if (element.isField() && element.modifiers.isFinal()) {
+          inferrer.recordFinalFieldType(outermostElement, element, type);
+        } else if (element.isVariable()) {
+          locals.update(element, type);
+        }
       }
       return type;
     } else {
@@ -724,11 +876,11 @@
     }
     Selector selector = elements.getSelector(node);
     if (node.isPropertyAccess) {
-      inferrer.registerGetterOnElement(analyzedElement, element);
+      inferrer.registerGetterOnElement(outermostElement, element);
       return inferrer.returnTypeOfElement(element);
     } else if (element.isFunction()) {
       ArgumentsTypes arguments = analyzeArguments(node.arguments);
-      inferrer.registerCalledElement(analyzedElement, element, arguments);
+      inferrer.registerCalledElement(outermostElement, element, arguments);
       return inferrer.returnTypeOfElement(element);
     } else {
       // Closure call on a getter. We don't have function types yet,
@@ -746,7 +898,7 @@
       return handleForeignSend(node);
     }
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
-    inferrer.registerCalledElement(analyzedElement, element, arguments);
+    inferrer.registerCalledElement(outermostElement, element, arguments);
     return inferrer.returnTypeOfElement(element);
   }
 
@@ -817,7 +969,11 @@
       return visitDynamicSend(node);
     } else if (const SourceString("&&") == op.source ||
                const SourceString("||") == op.source) {
-      node.visitChildren(this);
+      visit(node.receiver);
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      visit(node.arguments.head);
+      saved.merge(locals);
+      locals = saved;
       return compiler.boolClass;
     } else if (const SourceString("!") == op.source) {
       node.visitChildren(this);
@@ -853,23 +1009,28 @@
   visitGetterSend(Send node) {
     Element element = elements[node];
     if (Elements.isStaticOrTopLevelField(element)) {
-      inferrer.registerGetterOnElement(analyzedElement, element);
+      inferrer.registerGetterOnElement(outermostElement, element);
       return inferrer.returnTypeOfElement(element);
     } else if (Elements.isInstanceSend(node, elements)) {
       ClassElement receiverType;
       if (node.receiver == null) {
-        receiverType = analyzedElement.getEnclosingClass();
+        receiverType = outermostElement.getEnclosingClass();
       } else {
         receiverType = node.receiver.accept(this);
       }
       Selector selector = elements.getSelector(node);
-      inferrer.registerGetterOnSelector(analyzedElement, selector);
+      inferrer.registerGetterOnSelector(outermostElement, selector);
       return inferrer.returnTypeOfSelector(selector);
     } else if (Elements.isStaticOrTopLevelFunction(element)) {
-      inferrer.registerGetFunction(analyzedElement, element);
+      inferrer.registerGetFunction(outermostElement, element);
       return compiler.functionClass;
+    } else if (Elements.isErroneousElement(element)) {
+      return compiler.dynamicClass;
+    } else if (Elements.isLocal(element)) {
+      assert(locals.use(element) != null);
+      return locals.use(element);
     } else {
-      // TODO: Analyze variable.
+      node.visitChildren(this);
       return compiler.dynamicClass;
     }
   }
@@ -882,13 +1043,13 @@
   visitDynamicSend(Send node) {
     ClassElement receiverType;
     if (node.receiver == null) {
-      receiverType = analyzedElement.getEnclosingClass();
+      receiverType = outermostElement.getEnclosingClass();
     } else {
       receiverType = node.receiver.accept(this);
     }
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = elements.getSelector(node);
-    inferrer.registerCalledSelector(analyzedElement, selector, arguments);
+    inferrer.registerCalledSelector(outermostElement, selector, arguments);
     return inferrer.returnTypeOfSelector(selector);
   }
 
@@ -901,13 +1062,120 @@
 
   visitConditional(Conditional node) {
     node.condition.accept(this);
+    LocalsHandler saved = new LocalsHandler.from(locals);
     Element firstType = node.thenExpression.accept(this);
+    LocalsHandler thenLocals = locals;
+    locals = saved;
     Element secondType = node.elseExpression.accept(this);
+    locals.merge(thenLocals);
     Element type = inferrer.computeLUB(firstType, secondType);
     if (type == inferrer.giveUpType) type = compiler.dynamicClass;
     return type;
   }
 
+  visitVariableDefinitions(VariableDefinitions node) {
+    for (Link<Node> link = node.definitions.nodes;
+         !link.isEmpty;
+         link = link.tail) {
+      Node definition = link.head;
+      if (definition is Identifier) {
+        locals.update(elements[definition], compiler.nullClass);
+      } else {
+        assert(definition.asSendSet() != null);
+        visit(definition);
+      }
+    }
+  }
+
+  visitIf(If node) {
+    visit(node.condition);
+    LocalsHandler saved = new LocalsHandler.from(locals);
+    visit(node.thenPart);
+    LocalsHandler thenLocals = locals;
+    locals = saved;
+    visit(node.elsePart);
+    locals.merge(thenLocals);
+    return compiler.dynamicClass;
+  }
+
+  visitWhile(While node) {
+    bool changed = false;
+    do {
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      visit(node.condition);
+      visit(node.body);
+      changed = saved.merge(locals);
+      locals = saved;
+    } while (changed);
+
+    return compiler.dynamicClass;
+  }
+
+  visitDoWhile(DoWhile node) {
+    bool changed = false;
+    do {
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      visit(node.body);
+      visit(node.condition);
+      changed = saved.merge(locals);
+      locals = saved;
+    } while (changed);
+
+    return compiler.dynamicClass;
+  }
+
+  visitFor(For node) {
+    bool changed = false;
+    visit(node.initializer);
+    do {
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      visit(node.condition);
+      visit(node.body);
+      visit(node.update);
+      changed = saved.merge(locals);
+      locals = saved;
+    } while (changed);
+
+    return compiler.dynamicClass;
+  }
+
+  visitForIn(ForIn node) {
+    bool changed = false;
+    visit(node.expression);
+    Element variable;
+    if (node.declaredIdentifier.asSend() != null) {
+      variable = elements[node.declaredIdentifier];
+    } else {
+      assert(node.declaredIdentifier.asVariableDefinitions() != null);
+      VariableDefinitions variableDefinitions = node.declaredIdentifier;
+      variable = elements[variableDefinitions.definitions.nodes.head];
+    }
+    locals.update(variable, compiler.dynamicClass);
+    do {
+      LocalsHandler saved = new LocalsHandler.from(locals);
+      visit(node.body);
+      changed = saved.merge(locals);
+      locals = saved;
+    } while (changed);
+
+    return compiler.dynamicClass;
+  }
+
+  visitTryStatement(TryStatement node) {
+    LocalsHandler saved = locals;
+    locals = new LocalsHandler.from(locals, inTryBlock: true);
+    visit(node.tryBlock);
+    saved.merge(locals);
+    locals = saved;
+    for (Node catchBlock in node.catchBlocks) {
+      saved = new LocalsHandler.from(locals);
+      visit(catchBlock);
+      saved.merge(locals);
+      locals = saved;
+    }
+    visit(node.finallyBlock);
+  }
+
   internalError(String reason, {Node node}) {
     compiler.internalError(reason, node: node);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
new file mode 100644
index 0000000..5d4720d
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
@@ -0,0 +1,180 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of types;
+
+/**
+ * A type mask represents a set of concrete types, but the operations
+ * on it are not guaranteed to be precise. When computing the union of
+ * two masks you may get a mask that is too wide (like a common
+ * superclass instead of a proper union type) and when computing the
+ * intersection of two masks you may get a mask that is too narrow.
+ */
+class TypeMask {
+
+  static const int EXACT    = 0;
+  static const int SUBCLASS = 1;
+  static const int SUBTYPE  = 2;
+
+  final DartType base;
+  final int flags;
+
+  TypeMask(DartType base, int kind, bool isNullable)
+      : this.internal(base, (kind << 1) | (isNullable ? 1 : 0));
+
+  const TypeMask.exact(DartType base)
+      : this.internal(base, (EXACT << 1) | 1);
+  const TypeMask.subclass(DartType base)
+      : this.internal(base, (SUBCLASS << 1) | 1);
+  const TypeMask.subtype(DartType base)
+      : this.internal(base, (SUBTYPE << 1) | 1);
+
+  const TypeMask.nonNullExact(DartType base)
+      : this.internal(base, EXACT << 1);
+  const TypeMask.nonNullSubclass(DartType base)
+      : this.internal(base, SUBCLASS << 1);
+  const TypeMask.nonNullSubtype(DartType base)
+      : this.internal(base, SUBTYPE << 1);
+
+  const TypeMask.internal(this.base, this.flags);
+
+  bool get isNullable => (flags & 1) != 0;
+  bool get isExact => (flags >> 1) == EXACT;
+
+  // TODO(kasperl): Get rid of these. They should not be a visible
+  // part of the implementation because they make it hard to add
+  // proper union types if we ever want to.
+  bool get isSubclass => (flags >> 1) == SUBCLASS;
+  bool get isSubtype => (flags >> 1) == SUBTYPE;
+
+  /**
+   * Returns a nullable variant of [this] type mask.
+   */
+  TypeMask nullable() {
+    return isNullable ? this : new TypeMask.internal(base, flags | 1);
+  }
+
+  /**
+   * Returns whether or not this type mask contains the given type.
+   */
+  bool contains(DartType type, Compiler compiler) {
+    // TODO(kasperl): Do this error handling earlier.
+    if (base.kind != TypeKind.INTERFACE) return false;
+    assert(type.kind == TypeKind.INTERFACE);
+    // Compare the interface types.
+    ClassElement baseElement = base.element;
+    ClassElement typeElement = type.element;
+    if (isExact) {
+      return identical(baseElement, typeElement);
+    } else if (isSubclass) {
+      return typeElement.isSubclassOf(baseElement);
+    } else {
+      assert(isSubtype);
+      Set<ClassElement> subtypes = compiler.world.subtypes[baseElement];
+      return subtypes != null ? subtypes.contains(typeElement) : false;
+    }
+  }
+
+  // TODO(kasperl): Try to get rid of this method. It shouldn't really
+  // be necessary.
+  bool containsAll(Compiler compiler) {
+    // TODO(kasperl): Do this error handling earlier.
+    if (base.kind != TypeKind.INTERFACE) return false;
+    // TODO(kasperl): Should we take nullability into account here?
+    if (isExact) return false;
+    ClassElement baseElement = base.element;
+    return identical(baseElement, compiler.objectClass)
+        || identical(baseElement, compiler.dynamicClass);
+  }
+
+  // TODO(kasperl): This implementation is a bit sketchy, but it
+  // behaves the same as the old implementation on HType. The plan is
+  // to extend this and add proper testing of it.
+  TypeMask union(TypeMask other, Types types) {
+    // TODO(kasperl): Add subclass handling.
+    if (base == other.base) {
+      return unionSame(other, types);
+    } else if (types.isSubtype(other.base, base)) {
+      return unionSubtype(other, types);
+    } else if (types.isSubtype(base, other.base)) {
+      return other.unionSubtype(this, types);
+    }
+    return null;
+  }
+
+  TypeMask unionSame(TypeMask other, Types types) {
+    assert(base == other.base);
+    // The two masks share the base type, so we must chose the least
+    // constraining kind (the highest) of the two. If either one of
+    // the masks are nullable the result should be nullable too.
+    int combined = (flags > other.flags)
+        ? flags | (other.flags & 1)
+        : other.flags | (flags & 1);
+    if (flags == combined) {
+      return this;
+    } else if (other.flags == combined) {
+      return other;
+    } else {
+      return new TypeMask.internal(base, combined);
+    }
+  }
+
+  TypeMask unionSubtype(TypeMask other, Types types) {
+    assert(types.isSubtype(other.base, base));
+    // Since the other mask is a subtype of this mask, we need the
+    // resulting union to be a subtype too. If either one of the masks
+    // are nullable the result should be nullable too.
+    int combined = (SUBTYPE << 1) | ((flags | other.flags) & 1);
+    return (flags != combined)
+        ? new TypeMask.internal(base, combined)
+        : this;
+  }
+
+  // TODO(kasperl): This implementation is a bit sketchy, but it
+  // behaves the same as the old implementation on HType. The plan is
+  // to extend this and add proper testing of it.
+  TypeMask intersection(TypeMask other, Types types) {
+    int combined = (flags < other.flags)
+        ? flags & ((other.flags & 1) | ~1)
+        : other.flags & ((flags & 1) | ~1);
+    if (base == other.base) {
+      if (flags == combined) {
+        return this;
+      } else if (other.flags == combined) {
+        return other;
+      } else {
+        return new TypeMask.internal(base, combined);
+      }
+    } else if (types.isSubtype(other.base, base)) {
+      if (other.flags == combined) {
+        return other;
+      } else {
+        return new TypeMask.internal(other.base, combined);
+      }
+    } else if (types.isSubtype(base, other.base)) {
+      if (flags == combined) {
+        return this;
+      } else {
+        return new TypeMask.internal(base, combined);
+      }
+    }
+    return null;
+  }
+
+  bool operator ==(var other) {
+    if (other is !TypeMask) return false;
+    TypeMask otherMask = other;
+    return (base == otherMask.base) && (flags == otherMask.flags);
+  }
+
+  String toString() {
+    StringBuffer buffer = new StringBuffer();
+    if (isNullable) buffer.write('null|');
+    if (isExact) buffer.write('exact=');
+    if (isSubclass) buffer.write('subclass=');
+    if (isSubtype) buffer.write('subtype=');
+    buffer.write(base.element.name.slowToString());
+    return "[$buffer]";
+  }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart
index 345f0be..8b03838 100644
--- a/sdk/lib/_internal/compiler/implementation/types/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -13,8 +13,10 @@
 import '../util/util.dart';
 import '../universe/universe.dart';
 import 'simple_types_inferrer.dart' show SimpleTypesInferrer;
+import '../dart_types.dart';
 
 part 'concrete_types_inferrer.dart';
+part 'type_mask.dart';
 
 /**
  * Common super class for our type inferrers. Currently, its query methods
diff --git a/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart b/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
index 1f970f2..c8ad568 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/full_function_set.dart
@@ -9,52 +9,6 @@
 
   FunctionSetNode newNode(SourceString name)
       => new FullFunctionSetNode(name);
-
-  // TODO(kasperl): This interface is a little bit weird and mostly
-  // put here to illustrate how we can refine types. Returning a
-  // selector seems weird because we're only really interested in the
-  // receiver type information and the type kind.
-  Selector refine(Selector selector) {
-    SourceString name = selector.name;
-    FunctionSetNode node = nodes[name];
-    if (node == null) return null;
-    FullFunctionSetQuery query = node.query(selector, compiler);
-
-    // If the selector is already exact, then we cannot refine it
-    // further. If the query isn't exact, it means that the exact
-    // class didn't contain any mathing element.
-    if (selector.typeKind == TypedSelectorKind.EXACT) {
-      if (!query.isExact) return null;
-      assert(selector.receiverType.element == query.classes[0]);
-      return selector;
-    }
-
-    // If the query yields an exact class, we refine the selector.
-    if (query.isExact) {
-      ClassElement refinement = query.classes[0];
-      DartType type = refinement.computeType(compiler);
-      return new TypedSelector.exact(type, selector);
-    }
-
-    // Get the list of classes from the query. If the type information
-    // cannot be represented in the selector, we avoid refining it.
-    List<ClassElement> classes = query.classes;
-    if (classes == null || classes.length != 1) return selector;
-    if (classes.isEmpty) return null;
-
-    // We found one non-exact class, so we try to refine the selector
-    // to be of subclass kind. We take care to reuse the existing
-    // selector if matching class.
-    assert(classes.length == 1);
-    ClassElement refinement = query.classes[0];
-    if (selector.typeKind == TypedSelectorKind.SUBCLASS) {
-      ClassElement existing = selector.receiverType.element;
-      if (refinement == existing) return selector;
-      assert(refinement.isSubclassOf(existing));
-    }
-    DartType type = refinement.computeType(compiler);
-    return new TypedSelector.subclass(type, selector);
-  }
 }
 
 class FullFunctionSetNode extends FunctionSetNode {
@@ -70,8 +24,7 @@
                             Selector selector,
                             Compiler compiler) {
     List<ClassElement> classes = computeClasses(functions, compiler);
-    bool isExact = (selector.typeKind == TypedSelectorKind.EXACT)
-        || isExactClass(classes, compiler);
+    bool isExact = selector.hasExactMask || isExactClass(classes, compiler);
     return new FullFunctionSetQuery(functions, classes, isExact);
   }
 
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index 4fb6cfb..ecc1c34 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -8,6 +8,7 @@
 import '../elements/elements.dart';
 import '../dart2jslib.dart';
 import '../dart_types.dart';
+import '../types/types.dart';
 import '../tree/tree.dart';
 import '../util/util.dart';
 import '../js/js.dart' as js;
@@ -88,6 +89,41 @@
   bool hasFieldSetter(Element member, Compiler compiler) {
     return fieldSetters.contains(member);
   }
+
+  /**
+   * Compute type arguments of classes that use one of their type variables in
+   * is-checks and add the is-checks that they imply.
+   *
+   * This function must be called after all is-checks have been registered.
+   *
+   * TODO(karlklose): move these computations into a function producing an
+   * immutable datastructure.
+   */
+  void addImplicitChecks(Iterable<ClassElement> classesUsingChecks) {
+    // If there are no classes that use their variables in checks, there is
+    // nothing to do.
+    if (classesUsingChecks.isEmpty) return;
+    // Find all instantiated types that are a subtype of a class that uses
+    // one of its type arguments in an is-check and add the arguments to the
+    // set of is-checks.
+    // TODO(karlklose): replace this with code that uses a subtype lookup
+    // datastructure in the world.
+    for (DartType type in instantiatedTypes) {
+      if (type.kind != TypeKind.INTERFACE) continue;
+      InterfaceType classType = type;
+      for (ClassElement cls in classesUsingChecks) {
+        // We need the type as instance of its superclass anyway, so we just
+        // try to compute the substitution; if the result is [:null:], the
+        // classes are not related.
+        InterfaceType instance = classType.asInstanceOf(cls);
+        if (instance == null) continue;
+        Link<DartType> typeArguments = instance.typeArguments;
+        for (DartType argument in typeArguments) {
+          isChecks.add(argument);
+        }
+      }
+    }
+  }
 }
 
 class SelectorKind {
@@ -103,30 +139,6 @@
   String toString() => name;
 }
 
-class TypedSelectorKind {
-  final String name;
-  const TypedSelectorKind(this.name);
-
-  /// Unknown type: used for untyped selector.
-  static const TypedSelectorKind UNKNOWN = const TypedSelectorKind('unknown');
-
-  // Exact type: the selector knows the exact type of the receiver.
-  // For example [:new Map():].
-  static const TypedSelectorKind EXACT = const TypedSelectorKind('exact');
-
-  // Subclass type: the receiver type is in a subclass hierarchy.
-  // For example [:this:].
-  static const TypedSelectorKind SUBCLASS = const TypedSelectorKind('subclass');
-
-  // Interface type: any type that implements the receiver type.
-  // For example [(foo as Foo).bar()], or any type annotation in
-  // checked mode.
-  static const TypedSelectorKind INTERFACE =
-      const TypedSelectorKind('interface');
-
-  String toString() => name;
-}
-
 class Selector {
   final SelectorKind kind;
   final SourceString name;
@@ -136,7 +148,6 @@
   final int argumentCount;
   final List<SourceString> namedArguments;
   final List<SourceString> orderedNamedArguments;
-  TypedSelectorKind get typeKind => TypedSelectorKind.UNKNOWN;
 
   Selector(
       this.kind,
@@ -233,8 +244,9 @@
   int get hashCode => argumentCount + 1000 * namedArguments.length;
   int get namedArgumentCount => namedArguments.length;
   int get positionalArgumentCount => argumentCount - namedArgumentCount;
-  DartType get receiverType => null;
 
+  bool get hasExactMask => false;
+  TypeMask get mask => null;
   Selector get asUntyped => this;
 
   /**
@@ -268,7 +280,11 @@
     if (element.isForeign(compiler)) return true;
     if (element.isSetter()) return isSetter();
     if (element.isGetter()) return isGetter() || isCall();
-    if (element.isField()) return isGetter() || isSetter() || isCall();
+    if (element.isField()) {
+      return isSetter()
+          ? !element.modifiers.isFinalOrConst()
+          : isGetter() || isCall();
+    }
     if (isGetter()) return true;
     if (isSetter()) return false;
 
@@ -386,14 +402,12 @@
 
   bool operator ==(other) {
     if (other is !Selector) return false;
-    return identical(receiverType, other.receiverType)
-        && equalsUntyped(other);
+    return mask == other.mask && equalsUntyped(other);
   }
 
   bool equalsUntyped(Selector other) {
     return name == other.name
            && kind == other.kind
-           && typeKind == other.typeKind
            && identical(library, other.library)
            && argumentCount == other.argumentCount
            && namedArguments.length == other.namedArguments.length
@@ -427,22 +441,17 @@
     String named = '';
     String type = '';
     if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}';
-    if (receiverType != null) type = ', type=$typeKind $receiverType';
+    if (mask != null) type = ', mask=$mask';
     return 'Selector($kind, ${name.slowToString()}, '
            'arity=$argumentCount$named$type)';
   }
 }
 
 class TypedSelector extends Selector {
-  /**
-   * The type of the receiver.
-   */
-  final DartType receiverType;
-  final TypedSelectorKind typeKind;
-
   final Selector asUntyped;
+  final TypeMask mask;
 
-  TypedSelector(DartType this.receiverType, this.typeKind, Selector selector)
+  TypedSelector(this.mask, Selector selector)
       : asUntyped = selector.asUntyped,
         super(selector.kind,
               selector.name,
@@ -450,43 +459,27 @@
               selector.argumentCount,
               selector.namedArguments) {
     // Invariant: Typed selector can not be based on a malformed type.
-    assert(!identical(receiverType.kind, TypeKind.MALFORMED_TYPE));
-    assert(asUntyped.receiverType == null);
-    assert(typeKind != TypedSelectorKind.UNKNOWN);
+    assert(!identical(mask.base.kind, TypeKind.MALFORMED_TYPE));
+    assert(asUntyped.mask == null);
   }
 
-  TypedSelector.subclass(DartType receiverType, Selector selector)
-      : this(receiverType, TypedSelectorKind.SUBCLASS, selector);
+  TypedSelector.exact(DartType base, Selector selector)
+      : this(new TypeMask.exact(base), selector);
 
-  TypedSelector.exact(DartType receiverType, Selector selector)
-      : this(receiverType, TypedSelectorKind.EXACT, selector);
+  TypedSelector.subclass(DartType base, Selector selector)
+      : this(new TypeMask.subclass(base), selector);
 
-  TypedSelector.subtype(DartType receiverType, Selector selector)
-      : this(receiverType, TypedSelectorKind.INTERFACE, selector);
+  TypedSelector.subtype(DartType base, Selector selector)
+      : this(new TypeMask.subtype(base), selector);
+
+  bool get hasExactMask => mask.isExact;
 
   /**
    * Check if [element] will be the one used at runtime when being
    * invoked on an instance of [cls].
    */
   bool hasElementIn(ClassElement cls, Element element) {
-    // Use the selector for the lookup instead of [:element.name:]
-    // because the selector has the right privacy information.
-    Element resolved = cls.lookupSelector(this);
-    if (resolved == element) return true;
-    if (resolved == null) return false;
-    if (resolved.isAbstractField()) {
-      AbstractFieldElement field = resolved;
-      if (element == field.getter || element == field.setter) {
-        return true;
-      } else {
-        // We have not found a match, but another class higher in the
-        // hierarchy may define the getter or the setter.
-        ClassElement otherCls = field.getEnclosingClass().superclass;
-        if (otherCls == null) return false;
-        return hasElementIn(otherCls, element);
-      }
-    }
-    return false;
+    return cls.lookupSelector(this) == element;
   }
 
   bool appliesUnnamed(Element element, Compiler compiler) {
@@ -505,26 +498,28 @@
       return appliesUntyped(element, compiler);
     }
 
-    Element self = receiverType.element;
+    // TODO(kasperl): Can't we just avoid creating typed selectors
+    // based of function types?
+    Element self = mask.base.element;
     if (self.isTypedef()) {
       // A typedef is a function type that doesn't have any
       // user-defined members.
       return false;
     }
 
-    if (typeKind == TypedSelectorKind.EXACT) {
+    if (mask.isExact) {
       return hasElementIn(self, element) && appliesUntyped(element, compiler);
-    } else if (typeKind == TypedSelectorKind.SUBCLASS) {
+    } else if (mask.isSubclass) {
       return (hasElementIn(self, element)
               || other.isSubclassOf(self)
               || compiler.world.hasAnySubclassThatMixes(self, other))
           && appliesUntyped(element, compiler);
     } else {
-      assert(typeKind == TypedSelectorKind.INTERFACE);
+      assert(mask.isSubtype);
       if (other.implementsInterface(self)
           || other.isSubclassOf(self)
           || compiler.world.hasAnySubclassThatMixes(self, other)
-          || compiler.world.hasAnySubclassThatImplements(other, receiverType)) {
+          || compiler.world.hasAnySubclassThatImplements(other, mask.base)) {
         return appliesUntyped(element, compiler);
       }
 
@@ -534,10 +529,9 @@
       if (cls.isSubclassOf(other)) {
         // Resolve an invocation of [element.name] on [self]. If it
         // is found, this selector is a candidate.
-        return hasElementIn(self, element) && appliesUntyped(element, compiler);
+        return hasElementIn(cls, element) && appliesUntyped(element, compiler);
       }
     }
-
     return false;
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/util/link.dart b/sdk/lib/_internal/compiler/implementation/util/link.dart
index 9cc81cc..d3f93ca 100644
--- a/sdk/lib/_internal/compiler/implementation/util/link.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/link.dart
@@ -38,7 +38,7 @@
   void printOn(StringBuffer buffer, [separatedBy]) {
   }
 
-  List toList() => new List<T>.fixedLength(0);
+  List toList({ bool growable: true }) => growable ? <T>[] : new List<T>(0);
 
   bool get isEmpty => true;
 
diff --git a/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart b/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
index 2f9ea84..efd0ff9 100644
--- a/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
@@ -81,12 +81,8 @@
 
   bool get isEmpty => false;
 
-  List<T> toList() {
-    List<T> list = new List<T>();
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
-      list.addLast(link.head);
-    }
-    return list;
+  List<T> toList({ bool growable: true }) {
+    return new List<T>.from(this, growable: growable);
   }
 
   void forEach(void f(T element)) {
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 39f53b6..36c1933 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -215,6 +215,9 @@
   static const ILLEGAL_SUPER_SEND = const MessageKind(
       "#{name} cannot be called on super");
 
+  static const NO_SUCH_SUPER_MEMBER = const MessageKind(
+      "Cannot resolve #{memberName} in a superclass of #{className}");
+
   static const ADDITIONAL_TYPE_ARGUMENT = const MessageKind(
       "additional type argument");
 
@@ -338,6 +341,9 @@
   static const CANNOT_RESOLVE_SETTER = const MessageKind(
       'cannot resolve setter.');
 
+  static const CANNOT_RESOLVE_INDEX = const MessageKind(
+      'cannot resolve [] member.');
+
   static const VOID_NOT_ALLOWED = const MessageKind(
       'type void is only allowed in a return type.');
 
diff --git a/sdk/lib/_internal/compiler/implementation/world.dart b/sdk/lib/_internal/compiler/implementation/world.dart
index f3142f6..a09f629 100644
--- a/sdk/lib/_internal/compiler/implementation/world.dart
+++ b/sdk/lib/_internal/compiler/implementation/world.dart
@@ -51,7 +51,11 @@
       }
     }
 
-    compiler.resolverWorld.instantiatedClasses.forEach(addSubtypes);
+    // Use the [:seenClasses:] set to include non-instantiated
+    // classes: if the superclass of these classes require RTI, then
+    // they also need RTI, so that a constructor passes the type
+    // variables to the super constructor.
+    compiler.enqueuer.resolution.seenClasses.forEach(addSubtypes);
 
     // Find the classes that need runtime type information. Such
     // classes are:
@@ -64,6 +68,7 @@
       if (classesNeedingRti.contains(cls)) return;
       classesNeedingRti.add(cls);
 
+      // TODO(ngeoffray): This should use subclasses, not subtypes.
       Set<ClassElement> classes = subtypes[cls];
       if (classes != null) {
         classes.forEach((ClassElement sub) {
@@ -79,12 +84,31 @@
       }
     }
 
+    Set<ClassElement> classesUsingTypeVariableTests = new Set<ClassElement>();
     compiler.resolverWorld.isChecks.forEach((DartType type) {
-      if (type is InterfaceType) {
+      if (type.kind == TypeKind.TYPE_VARIABLE) {
+        TypeVariableElement variable = type.element;
+        classesUsingTypeVariableTests.add(variable.enclosingElement);
+      }
+    });
+    // Add is-checks that result from classes using type variables in checks.
+    compiler.resolverWorld.addImplicitChecks(classesUsingTypeVariableTests);
+    // Add the rti dependencies that are implicit in the way the backend
+    // generates code: when we create a new [List], we actually create
+    // a JSArray in the backend and we need to add type arguments to
+    // the calls of the list constructor whenever we determine that
+    // JSArray needs type arguments.
+    compiler.backend.addBackendRtiDependencies(this);
+    // Compute the set of all classes that need runtime type information.
+    compiler.resolverWorld.isChecks.forEach((DartType type) {
+      if (type.kind == TypeKind.INTERFACE) {
         InterfaceType itf = type;
         if (!itf.isRaw) {
           potentiallyAddForRti(itf.element);
         }
+      } else if (type.kind == TypeKind.TYPE_VARIABLE) {
+        TypeVariableElement variable = type.element;
+        potentiallyAddForRti(variable.enclosingElement);
       }
     });
   }
@@ -102,7 +126,6 @@
     return uses != null && !uses.isEmpty;
   }
 
-
   void registerRtiDependency(Element element, Element dependency) {
     // We're not dealing with typedef for now.
     if (!element.isClass() || !dependency.isClass()) return;
@@ -154,10 +177,11 @@
     if (targets.length != 1) return null;
     Element result = targets.first;
     ClassElement enclosing = result.getEnclosingClass();
-    DartType receiverType = selector.receiverType;
-    ClassElement receiverTypeElement = (receiverType == null)
+    // TODO(kasperl): Move this code to the type mask.
+    ti.TypeMask mask = selector.mask;
+    ClassElement receiverTypeElement = (mask == null)
         ? compiler.objectClass
-        : receiverType.element;
+        : mask.base.element;
     // We only return the found element if it is guaranteed to be
     // implemented on the exact receiver type. It could be found in a
     // subclass or in an inheritance-wise unrelated class in case of
@@ -167,10 +191,9 @@
 
   Iterable<ClassElement> locateNoSuchMethodHolders(Selector selector) {
     Selector noSuchMethodSelector = new Selector.noSuchMethod();
-    DartType receiverType = selector.receiverType;
-    if (receiverType != null) {
-      noSuchMethodSelector = new TypedSelector(
-          receiverType, selector.typeKind, noSuchMethodSelector);
+    ti.TypeMask mask = selector.mask;
+    if (mask != null) {
+      noSuchMethodSelector = new TypedSelector(mask, noSuchMethodSelector);
     }
     ClassElement objectClass = compiler.objectClass;
     return allFunctions
diff --git a/sdk/lib/_internal/dartdoc/dartdoc.status b/sdk/lib/_internal/dartdoc/dartdoc.status
new file mode 100644
index 0000000..8b45e64
--- /dev/null
+++ b/sdk/lib/_internal/dartdoc/dartdoc.status
@@ -0,0 +1,15 @@
+# Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+test/markdown_test: Pass
+test/dartdoc_test: Pass
+test/dartdoc_search_test: Pass, Skip
+
+# Dartdoc only runs on the VM, so just rule out all compilers.
+[ $compiler == dart2js || $compiler == dart2dart || $compiler == dartc ]
+*: Skip
+
+# Dartdoc only runs on the standalone VM, not in dartium.
+[ $runtime == drt || $runtime == dartium ]
+*: Skip
diff --git a/sdk/lib/_internal/dartdoc/lib/classify.dart b/sdk/lib/_internal/dartdoc/lib/classify.dart
index d41f12a..4b4d972 100644
--- a/sdk/lib/_internal/dartdoc/lib/classify.dart
+++ b/sdk/lib/_internal/dartdoc/lib/classify.dart
@@ -45,7 +45,7 @@
     var token = tokenizer.tokenize();
     var inString = false;
     while (token.kind != EOF_TOKEN) {
-      html.add(text.substring(whitespaceOffset, token.charOffset));
+      html.write(text.substring(whitespaceOffset, token.charOffset));
       whitespaceOffset = token.charOffset + token.slowCharCount;
 
       // Track whether or not we're in a string.
@@ -62,9 +62,9 @@
         // Add a secondary class to tokens appearing within a string so that
         // we can highlight tokens in an interpolation specially.
         var stringClass = inString ? Classification.STRING_INTERPOLATION : '';
-        html.add('<span class="$kind $stringClass">$escapedText</span>');
+        html.write('<span class="$kind $stringClass">$escapedText</span>');
       } else {
-        html.add(escapedText);
+        html.write(escapedText);
       }
 
       // Track whether or not we're in a string.
diff --git a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
index a6f0179d..e02d513 100644
--- a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
@@ -110,7 +110,7 @@
   fromDir.list(recursive: false).listen(
       (FileSystemEntity entity) {
         if (entity is File) {
-          final name = new Path(entity.name).filename;
+          final name = new Path(entity.path).filename;
           // TODO(rnystrom): Hackish. Ignore 'hidden' files like .DS_Store.
           if (name.startsWith('.')) return;
 
@@ -293,15 +293,18 @@
   static const List<String> COMPILER_OPTIONS =
       const <String>['--preserve-comments', '--categories=Client,Server'];
 
-  Dartdoc() {
-    // Patch in support for [:...:]-style code to the markdown parser.
-    // TODO(rnystrom): Markdown already has syntax for this. Phase this out?
-    md.InlineParser.syntaxes.insertRange(0, 1,
-        new md.CodeSyntax(r'\[\:((?:.|\n)*?)\:\]'));
+  /// Resolves Dart links to the correct Node.
+  md.Resolver dartdocResolver;
 
-    md.setImplicitLinkResolver((name) => resolveNameReference(name,
-            currentLibrary: _currentLibrary, currentType: _currentType,
-            currentMember: _currentMember));
+  // Add support for [:...:]-style code to the markdown parser.
+  List<md.InlineSyntax> dartdocSyntaxes =
+    [new md.CodeSyntax(r'\[:\s?((?:.|\n)*?)\s?:\]')];
+
+
+  Dartdoc() {
+    dartdocResolver = (String name) => resolveNameReference(name,
+        currentLibrary: _currentLibrary, currentType: _currentType,
+        currentMember: _currentMember);
   }
 
   /**
@@ -420,7 +423,8 @@
         version, revision);
 
     for (final lib in _sortedLibraries) {
-      var libraryElement = new LibraryElement(lib.qualifiedName, lib, lookupMdnComment)
+      var libraryElement = new LibraryElement(
+          lib, lookupMdnComment: lookupMdnComment)
           ..stripDuplicateUris(null, null);
       packageManifest.libraries.add(new Reference.fromElement(libraryElement));
       startFile("$revision/${libraryElement.id}.json");
@@ -467,7 +471,7 @@
   }
 
   void write(String s) {
-    _file.add(s);
+    _file.write(s);
   }
 
   void writeln(String s) {
@@ -821,7 +825,7 @@
     // Look for a comment for the entire library.
     final comment = getLibraryComment(library);
     if (comment != null) {
-      writeln('<div class="doc">${comment.html}</div>');
+      writeln('<div class="doc">${markdownFromComment(comment)}</div>');
     }
 
     // Document the top-level members.
@@ -1517,17 +1521,25 @@
     write(')');
   }
 
+  String markdownFromComment(DocComment comment) {
+    return md.markdownToHtml(comment.text,
+        inlineSyntaxes: dartdocSyntaxes,
+        linkResolver: dartdocResolver);
+  }
+
   void docComment(ContainerMirror host, DocComment comment) {
     if (comment != null) {
+      var html = markdownFromComment(comment);
+
       if (comment.inheritedFrom != null) {
         writeln('<div class="inherited">');
-        writeln(comment.html);
+        writeln(html);
         write('<div class="docs-inherited-from">docs inherited from ');
         annotateType(host, comment.inheritedFrom);
         write('</div>');
         writeln('</div>');
       } else {
-        writeln(comment.html);
+        writeln(html);
       }
     }
   }
@@ -1986,8 +1998,6 @@
     assert(text != null && !text.trim().isEmpty);
   }
 
-  String get html => md.markdownToHtml(text);
-
   String toString() => text;
 }
 
diff --git a/sdk/lib/_internal/dartdoc/lib/markdown.dart b/sdk/lib/_internal/dartdoc/lib/markdown.dart
index a7ea5cc..01de970 100644
--- a/sdk/lib/_internal/dartdoc/lib/markdown.dart
+++ b/sdk/lib/_internal/dartdoc/lib/markdown.dart
@@ -11,9 +11,12 @@
 part 'src/markdown/html_renderer.dart';
 part 'src/markdown/inline_parser.dart';
 
+typedef Node Resolver(String name);
+
 /// Converts the given string of markdown to HTML.
-String markdownToHtml(String markdown) {
-  final document = new Document();
+String markdownToHtml(String markdown, {inlineSyntaxes, linkResolver}) {
+  final document = new Document(inlineSyntaxes: inlineSyntaxes,
+      linkResolver: linkResolver);
 
   // Replace windows line endings with unix line endings, and split.
   final lines = markdown.replaceAll('\r\n','\n').split('\n');
@@ -29,17 +32,13 @@
              .replaceAll('>', '&gt;');
 }
 
-var _implicitLinkResolver;
-
-Node setImplicitLinkResolver(Node resolver(String text)) {
-  _implicitLinkResolver = resolver;
-}
-
 /// Maintains the context needed to parse a markdown document.
 class Document {
   final Map<String, Link> refLinks;
+  List<InlineSyntax> inlineSyntaxes;
+  Resolver linkResolver;
 
-  Document()
+  Document({this.inlineSyntaxes, this.linkResolver})
     : refLinks = <String, Link>{};
 
   parseRefLinks(List<String> lines) {
diff --git a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
index 59e14b5..d7595bd 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
@@ -30,8 +30,8 @@
   // TODO(rnystrom): Should be in corelib.
   final buffer = new StringBuffer();
   for (int i = 0; i < count; i++) {
-    buffer.add(text);
-    if ((i < count - 1) && (separator != null)) buffer.add(separator);
+    buffer.write(text);
+    if ((i < count - 1) && (separator != null)) buffer.write(separator);
   }
 
   return buffer.toString();
diff --git a/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart b/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
index 01e456e..882f6b2 100755
--- a/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart
@@ -74,7 +74,7 @@
   }
   if (classMirror.superclass != null &&
       classMirror.superclass.qualifiedName != classMirror.qualifiedName &&
-      classMirror.superclass.qualifiedName != 'dart:core.Object') {
+      classMirror.superclass.qualifiedName != 'dart.core.Object') {
     determineAllMembers(classMirror.superclass, members);
   }
 }
@@ -120,7 +120,7 @@
 
   void startObject(String name) {
     _start(name);
-    _sb.add('{');
+    _sb.write('{');
 
     _indent += 1;
     _inSet = false;
@@ -131,7 +131,7 @@
     if (_inSet) {
       _newline();
     }
-    _sb.add('}');
+    _sb.write('}');
     _inSet = true;
   }
 
@@ -139,7 +139,7 @@
     _start(name);
     _inSet = false;
 
-    _sb.add('[');
+    _sb.write('[');
     _indent += 1;
   }
 
@@ -148,49 +148,49 @@
     if (_inSet) {
       _newline();
     }
-    _sb.add(']');
+    _sb.write(']');
     _inSet = true;
   }
 
   void addString(String name, String value) {
     _start(name);
-    _sb.add('"');
+    _sb.write('"');
     _escape(_sb, value);
-    _sb.add('"');
+    _sb.write('"');
     _inSet = true;
   }
 
   void addBool(String name, bool value) {
     _start(name);
-    _sb.add(value.toString());
+    _sb.write(value.toString());
     _inSet = true;
   }
 
   void addNum(String name, num value) {
     _start(name);
-    _sb.add(value.toString());
+    _sb.write(value.toString());
     _inSet = true;
   }
 
   void _start(String name) {
     if (_inSet) {
-      _sb.add(',');
+      _sb.write(',');
     }
     // Do not print a newline at the beginning of the file.
     if (!_sb.isEmpty) {
       _newline();
     }
     if (name != null) {
-      _sb.add('"$name": ');
+      _sb.write('"$name": ');
     }
   }
 
   void _newline([int indent = 0]) {
-    _sb.add('\n');
+    _sb.write('\n');
     _indent += indent;
 
     for (var i = 0; i < _indent; ++i) {
-      _sb.add('  ');
+      _sb.write('  ');
     }
   }
 
@@ -209,45 +209,45 @@
   static void _escape(StringBuffer sb, String s) {
     final int length = s.length;
     bool needsEscape = false;
-    final charCodes = new List<int>();
+    final codeUnits = new List<int>();
     for (int i = 0; i < length; i++) {
-      int charCode = s.charCodeAt(i);
-      if (charCode < 32) {
+      int codeUnit = s.codeUnitAt(i);
+      if (codeUnit < 32) {
         needsEscape = true;
-        charCodes.add(JsonPrinter.BACKSLASH);
-        switch (charCode) {
+        codeUnits.add(JsonPrinter.BACKSLASH);
+        switch (codeUnit) {
         case JsonPrinter.BACKSPACE:
-          charCodes.add(JsonPrinter.CHAR_B);
+          codeUnits.add(JsonPrinter.CHAR_B);
           break;
         case JsonPrinter.TAB:
-          charCodes.add(JsonPrinter.CHAR_T);
+          codeUnits.add(JsonPrinter.CHAR_T);
           break;
         case JsonPrinter.NEW_LINE:
-          charCodes.add(JsonPrinter.CHAR_N);
+          codeUnits.add(JsonPrinter.CHAR_N);
           break;
         case JsonPrinter.FORM_FEED:
-          charCodes.add(JsonPrinter.CHAR_F);
+          codeUnits.add(JsonPrinter.CHAR_F);
           break;
         case JsonPrinter.CARRIAGE_RETURN:
-          charCodes.add(JsonPrinter.CHAR_R);
+          codeUnits.add(JsonPrinter.CHAR_R);
           break;
         default:
-          charCodes.add(JsonPrinter.CHAR_U);
-          charCodes.add(_hexDigit((charCode >> 12) & 0xf));
-          charCodes.add(_hexDigit((charCode >> 8) & 0xf));
-          charCodes.add(_hexDigit((charCode >> 4) & 0xf));
-          charCodes.add(_hexDigit(charCode & 0xf));
+          codeUnits.add(JsonPrinter.CHAR_U);
+          codeUnits.add(_hexDigit((codeUnit >> 12) & 0xf));
+          codeUnits.add(_hexDigit((codeUnit >> 8) & 0xf));
+          codeUnits.add(_hexDigit((codeUnit >> 4) & 0xf));
+          codeUnits.add(_hexDigit(codeUnit & 0xf));
           break;
         }
-      } else if (charCode == JsonPrinter.QUOTE ||
-          charCode == JsonPrinter.BACKSLASH) {
+      } else if (codeUnit == JsonPrinter.QUOTE ||
+          codeUnit == JsonPrinter.BACKSLASH) {
         needsEscape = true;
-        charCodes.add(JsonPrinter.BACKSLASH);
-        charCodes.add(charCode);
+        codeUnits.add(JsonPrinter.BACKSLASH);
+        codeUnits.add(codeUnit);
       } else {
-        charCodes.add(charCode);
+        codeUnits.add(codeUnit);
       }
     }
-    sb.add(needsEscape ? new String.fromCharCodes(charCodes) : s);
+    sb.write(needsEscape ? new String.fromCharCodes(codeUnits) : s);
   }
 }
diff --git a/sdk/lib/_internal/dartdoc/lib/src/markdown/html_renderer.dart b/sdk/lib/_internal/dartdoc/lib/src/markdown/html_renderer.dart
index 1695e96..5494394 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/markdown/html_renderer.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/markdown/html_renderer.dart
@@ -24,17 +24,17 @@
   }
 
   void visitText(Text text) {
-    buffer.add(text.text);
+    buffer.write(text.text);
   }
 
   bool visitElementBefore(Element element) {
     // Hackish. Separate block-level elements with newlines.
     if (!buffer.isEmpty &&
         _BLOCK_TAGS.firstMatch(element.tag) != null) {
-      buffer.add('\n');
+      buffer.write('\n');
     }
 
-    buffer.add('<${element.tag}');
+    buffer.write('<${element.tag}');
 
     // Sort the keys so that we generate stable output.
     // TODO(rnystrom): This assumes keys returns a fresh mutable
@@ -42,20 +42,20 @@
     final attributeNames = element.attributes.keys.toList();
     attributeNames.sort((a, b) => a.compareTo(b));
     for (final name in attributeNames) {
-      buffer.add(' $name="${element.attributes[name]}"');
+      buffer.write(' $name="${element.attributes[name]}"');
     }
 
     if (element.isEmpty) {
       // Empty element like <hr/>.
-      buffer.add(' />');
+      buffer.write(' />');
       return false;
     } else {
-      buffer.add('>');
+      buffer.write('>');
       return true;
     }
   }
 
   void visitElementAfter(Element element) {
-    buffer.add('</${element.tag}>');
+    buffer.write('</${element.tag}>');
   }
 }
diff --git a/sdk/lib/_internal/dartdoc/lib/src/markdown/inline_parser.dart b/sdk/lib/_internal/dartdoc/lib/src/markdown/inline_parser.dart
index af42e3e..5faebf2 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/markdown/inline_parser.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/markdown/inline_parser.dart
@@ -7,56 +7,51 @@
 /// Maintains the internal state needed to parse inline span elements in
 /// markdown.
 class InlineParser {
-  static List<InlineSyntax> get syntaxes {
-    // Lazy initialize.
-    if (_syntaxes == null) {
-      _syntaxes = <InlineSyntax>[
-        // This first regexp matches plain text to accelerate parsing.  It must
-        // be written so that it does not match any prefix of any following
-        // syntax.  Most markdown is plain text, so it is faster to match one
-        // regexp per 'word' rather than fail to match all the following regexps
-        // at each non-syntax character position.  It is much more important
-        // that the regexp is fast than complete (for example, adding grouping
-        // is likely to slow the regexp down enough to negate its benefit).
-        // Since it is purely for optimization, it can be removed for debugging.
-        new TextSyntax(r'\s*[A-Za-z0-9]+'),
+  static List<InlineSyntax>  defaultSyntaxes = <InlineSyntax>[
+    // This first regexp matches plain text to accelerate parsing.  It must
+    // be written so that it does not match any prefix of any following
+    // syntax.  Most markdown is plain text, so it is faster to match one
+    // regexp per 'word' rather than fail to match all the following regexps
+    // at each non-syntax character position.  It is much more important
+    // that the regexp is fast than complete (for example, adding grouping
+    // is likely to slow the regexp down enough to negate its benefit).
+    // Since it is purely for optimization, it can be removed for debugging.
 
-        // The real syntaxes.
+    // TODO(amouravski): this regex will glom up any custom syntaxes unless
+    // they're at the beginning.
+    new TextSyntax(r'\s*[A-Za-z0-9]+'),
 
-        new AutolinkSyntax(),
-        new LinkSyntax(),
-        // "*" surrounded by spaces is left alone.
-        new TextSyntax(r' \* '),
-        // "_" surrounded by spaces is left alone.
-        new TextSyntax(r' _ '),
-        // Leave already-encoded HTML entities alone. Ensures we don't turn
-        // "&amp;" into "&amp;amp;"
-        new TextSyntax(r'&[#a-zA-Z0-9]*;'),
-        // Encode "&".
-        new TextSyntax(r'&', sub: '&amp;'),
-        // Encode "<". (Why not encode ">" too? Gruber is toying with us.)
-        new TextSyntax(r'<', sub: '&lt;'),
-        // Parse "**strong**" tags.
-        new TagSyntax(r'\*\*', tag: 'strong'),
-        // Parse "__strong__" tags.
-        new TagSyntax(r'__', tag: 'strong'),
-        // Parse "*emphasis*" tags.
-        new TagSyntax(r'\*', tag: 'em'),
-        // Parse "_emphasis_" tags.
-        // TODO(rnystrom): Underscores in the middle of a word should not be
-        // parsed as emphasis like_in_this.
-        new TagSyntax(r'_', tag: 'em'),
-        // Parse inline code within double backticks: "``code``".
-        new CodeSyntax(r'``\s?((?:.|\n)*?)\s?``'),
-        // Parse inline code within backticks: "`code`".
-        new CodeSyntax(r'`([^`]*)`')
-      ];
-    }
+    // The real syntaxes.
 
-    return _syntaxes;
-  }
-
-  static List<InlineSyntax> _syntaxes;
+    new AutolinkSyntax(),
+    new LinkSyntax(),
+    // "*" surrounded by spaces is left alone.
+    new TextSyntax(r' \* '),
+    // "_" surrounded by spaces is left alone.
+    new TextSyntax(r' _ '),
+    // Leave already-encoded HTML entities alone. Ensures we don't turn
+    // "&amp;" into "&amp;amp;"
+    new TextSyntax(r'&[#a-zA-Z0-9]*;'),
+    // Encode "&".
+    new TextSyntax(r'&', sub: '&amp;'),
+    // Encode "<". (Why not encode ">" too? Gruber is toying with us.)
+    new TextSyntax(r'<', sub: '&lt;'),
+    // Parse "**strong**" tags.
+    new TagSyntax(r'\*\*', tag: 'strong'),
+    // Parse "__strong__" tags.
+    new TagSyntax(r'__', tag: 'strong'),
+    // Parse "*emphasis*" tags.
+    new TagSyntax(r'\*', tag: 'em'),
+    // Parse "_emphasis_" tags.
+    // TODO(rnystrom): Underscores in the middle of a word should not be
+    // parsed as emphasis like_in_this.
+    new TagSyntax(r'_', tag: 'em'),
+    // Parse inline code within double backticks: "``code``".
+    new CodeSyntax(r'``\s?((?:.|\n)*?)\s?``'),
+    // Parse inline code within backticks: "`code`".
+    new CodeSyntax(r'`([^`]*)`')
+    // We will add the LinkSyntax once we know about the specific link resolver.
+  ];
 
   /// The string of markdown being parsed.
   final String source;
@@ -64,6 +59,8 @@
   /// The markdown document this parser is parsing.
   final Document document;
 
+  List<InlineSyntax> syntaxes;
+
   /// The current read position.
   int pos = 0;
 
@@ -73,7 +70,19 @@
   final List<TagState> _stack;
 
   InlineParser(this.source, this.document)
-    : _stack = <TagState>[];
+    : _stack = <TagState>[] {
+    /// User specified syntaxes will be the first syntaxes to be evaluated.
+    if (document.inlineSyntaxes != null) {
+      syntaxes = [];
+      syntaxes.addAll(document.inlineSyntaxes);
+      syntaxes.addAll(defaultSyntaxes);
+    } else {
+      syntaxes = defaultSyntaxes;
+    }
+    // Custom link resolver goes after the generic text syntax.
+    syntaxes.insertRange(1, 1,
+        new LinkSyntax(linkResolver: document.linkResolver));
+  }
 
   List<Node> parse() {
     // Make a fake top tag to hold the results.
@@ -236,6 +245,8 @@
 
 /// Matches inline links like `[blah] [id]` and `[blah] (url)`.
 class LinkSyntax extends TagSyntax {
+  Resolver linkResolver;
+
   /// The regex for the end of a link needs to handle both reference style and
   /// inline styles as well as optional titles for inline links. To make that
   /// a bit more palatable, this breaks it into pieces.
@@ -253,7 +264,7 @@
     // 4: Contains the title, if present, for an inline link.
   }
 
-  LinkSyntax()
+  LinkSyntax({this.linkResolver})
     : super(r'\[', end: linkPattern);
 
   bool onMatchEnd(InlineParser parser, Match match, TagState state) {
@@ -263,10 +274,10 @@
     // If we didn't match refLink or inlineLink, then it means there was
     // nothing after the first square bracket, so it isn't a normal markdown
     // link at all. Instead, we allow users of the library to specify a special
-    // resolver function ([setImplicitLinkResolver]) that may choose to handle
+    // resolver function ([linkResolver]) that may choose to handle
     // this. Otherwise, it's just treated as plain text.
     if ((match[1] == null) || (match[1] == '')) {
-      if (_implicitLinkResolver == null) return false;
+      if (linkResolver == null) return false;
 
       // Only allow implicit links if the content is just text.
       // TODO(rnystrom): Do we want to relax this?
@@ -276,7 +287,7 @@
       Text link = state.children[0];
 
       // See if we have a resolver that will generate a link for us.
-      final node = _implicitLinkResolver(link.text);
+      final node = linkResolver(link.text);
       if (node == null) return false;
 
       parser.addNode(node);
diff --git a/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart b/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart
index 53da583..ea87229 100755
--- a/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart
+++ b/sdk/lib/_internal/dartdoc/lib/universe_serializer.dart
@@ -62,6 +62,8 @@
    */
   String line;
 
+  // TODO(jacobr): refactor the code so that lookupMdnComment does not need to
+  // be passed to every Element constructor.
   Element(Mirror mirror, this.kind, this.name, String id, this.comment,
       MdnComment lookupMdnComment(Mirror))
       : line = mirror.location.line.toString(),
@@ -116,33 +118,78 @@
 }
 
 /**
+ * Helper class to track what members of a library should be included.
+ */
+class LibrarySubset {
+  final LibraryMirror library;
+  Set<String> includedChildren;
+
+  LibrarySubset(this.library) : includedChildren = new Set<String>();
+}
+
+/**
  * [Element] describing a Dart library.
  */
 class LibraryElement extends Element {
-  LibraryElement(String name, LibraryMirror mirror,
-      MdnComment lookupMdnComment(Mirror))
-      : super(mirror, 'library', _libraryName(mirror), name,
-          computeComment(mirror), lookupMdnComment) {
+  /**
+   * Partial versions of LibraryElements containing classes that are extended
+   * or implemented by classes in this library.
+   */
+  List<LibraryElement> dependencies;
   
+  /**
+   * Construct a LibraryElement from a [mirror].
+   *
+   * If [includedChildren] is specified, only elements matching names in
+   * [includedChildren] are included and no dependencies are included.
+   * [lookupMdnComment] is an optional function that returns the MDN
+   * documentation for elements. [dependencies] is an optional map
+   * tracking all classes dependend on by this [ClassElement].
+   */
+  LibraryElement(LibraryMirror mirror,
+      {MdnComment lookupMdnComment(Mirror), Set<String> includedChildren})
+      : super(mirror, 'library', _libraryName(mirror), mirror.displayName,
+          computeComment(mirror), lookupMdnComment) {
+    var requiredDependencies;
+    // We don't need to track our required dependencies when generating a
+    // filtered version of this library which will be used as a dependency for
+    // another library.
+    if (includedChildren == null)
+      requiredDependencies = new Map<String, LibrarySubset>();
     mirror.functions.forEach((childName, childMirror) {
-      addChild(new MethodElement(childName, childMirror, lookupMdnComment));
+      if (includedChildren == null || includedChildren.contains(childName))
+        addChild(new MethodElement(childName, childMirror, lookupMdnComment));
     });
 
     mirror.getters.forEach((childName, childMirror) {
-      addChild(new GetterElement(childName, childMirror, lookupMdnComment));
+      if (includedChildren == null || includedChildren.contains(childName))
+        addChild(new GetterElement(childName, childMirror, lookupMdnComment));
     });
 
     mirror.variables.forEach((childName, childMirror) {
+      if (includedChildren == null || includedChildren.contains(childName))
         addChild(new VariableElement(childName, childMirror, lookupMdnComment));
     });
 
     mirror.classes.forEach((className, classMirror) {
-      if (classMirror is TypedefMirror) {
-        addChild(new TypedefElement(className, classMirror));
-      } else {
-        addChild(new ClassElement(className, classMirror, lookupMdnComment));
+      if (includedChildren == null || includedChildren.contains(className)) {
+        if (classMirror is TypedefMirror) {
+          addChild(new TypedefElement(className, classMirror));
+        } else {
+          addChild(new ClassElement(classMirror,
+              dependencies: requiredDependencies,
+              lookupMdnComment: lookupMdnComment));
+        }
       }
     });
+
+    if (requiredDependencies != null && !requiredDependencies.isEmpty) {
+      dependencies = requiredDependencies.values.map((librarySubset) =>
+          new LibraryElement(
+              librarySubset.library,
+              lookupMdnComment: lookupMdnComment,
+              includedChildren: librarySubset.includedChildren)).toList();
+    }
   }
 
   static String _libraryName(LibraryMirror mirror) {
@@ -170,6 +217,16 @@
       return mirror.uri.toString();
     }
   }
+
+  void stripDuplicateUris(String parentUri, parentLine) {
+    super.stripDuplicateUris(parentUri, parentLine);
+
+    if (dependencies != null) {
+      for (var child in dependencies) {
+        child.stripDuplicateUris(null, null);
+      }
+    }
+  }
 }
 
 /**
@@ -196,14 +253,46 @@
   List<Reference> interfaces;
   /** Whether the class implements or extends [Error] or [Exception]. */
   bool isThrowable;
-
-  ClassElement(String name, ClassMirror mirror,
-      MdnComment lookupMdnComment(Mirror))
-      : super(mirror, 'class', mirror.simpleName, name, computeComment(mirror),
+  
+  /**
+   * Constructs a [ClassElement] from a [ClassMirror].
+   *
+   * [dependencies] is an optional map updated as a side effect of running
+   * this constructor that tracks what classes from other libraries are
+   * dependencies of classes in this library.  A class is considered a
+   * dependency if it implements or extends another class.
+   * [lookupMdnComment] is an optional function that returns the MDN
+   * documentation for elements. [dependencies] is an optional map
+   * tracking all classes dependend on by this [ClassElement].
+   */
+  ClassElement(ClassMirror mirror,
+      {Map<String, LibrarySubset> dependencies,
+       MdnComment lookupMdnComment(Mirror)})
+      : super(mirror, 'class', mirror.simpleName, mirror.simpleName, computeComment(mirror),
           lookupMdnComment),
         superclass = _optionalReference(mirror.superclass),
-        isAbstract = _optionalBool(mirror.isAbstract) {
-        isThrowable = _optionalBool(_isThrowable(mirror));
+        isAbstract = _optionalBool(mirror.isAbstract),
+        isThrowable = _optionalBool(_isThrowable(mirror)){
+
+    addCrossLibraryDependencies(clazz) {
+      if (clazz == null) return;
+
+      if (mirror.library != clazz.library) {
+        var libraryStub = dependencies.putIfAbsent(clazz.library.simpleName,
+            () => new LibrarySubset(clazz.library));
+        libraryStub.includedChildren.add(clazz.simpleName);
+      }
+
+      for (var interface in clazz.superinterfaces) {
+        addCrossLibraryDependencies(interface);
+      }
+      addCrossLibraryDependencies(clazz.superclass);
+    }
+
+    if (dependencies != null) {
+      addCrossLibraryDependencies(mirror);
+    }
+
     for (var interface in mirror.superinterfaces) {
       if (this.interfaces == null) {
         this.interfaces = <Reference>[];
diff --git a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
index 817889e..18d44cc 100644
--- a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
@@ -7,10 +7,12 @@
 
 import 'dart:async';
 import 'dart:io';
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 // TODO(rnystrom): Use "package:" URL (#4968).
 import '../lib/dartdoc.dart' as dd;
-import '../lib/markdown.dart' as md;
+import '../lib/markdown.dart';
+import 'markdown_test.dart';
 
 // TODO(rnystrom): Better path to unittest.
 import '../../../../../pkg/unittest/lib/unittest.dart';
@@ -120,6 +122,80 @@
     });
   });
 
+  group('dartdoc markdown', () {
+    group('[::] blocks', () {
+
+      validateDartdocMarkdown('simple case', '''
+        before [:source:] after
+        ''', '''
+        <p>before <code>source</code> after</p>
+        ''');
+
+      validateDartdocMarkdown('unmatched [:', '''
+        before [: after
+        ''', '''
+        <p>before [: after</p>
+        ''');
+      validateDartdocMarkdown('multiple spans in one text', '''
+        a [:one:] b [:two:] c
+        ''', '''
+        <p>a <code>one</code> b <code>two</code> c</p>
+        ''');
+
+      validateDartdocMarkdown('multi-line', '''
+        before [:first
+        second:] after
+        ''', '''
+        <p>before <code>first
+        second</code> after</p>
+        ''');
+
+      validateDartdocMarkdown('contain backticks', '''
+        before [:can `contain` backticks:] after
+        ''', '''
+        <p>before <code>can `contain` backticks</code> after</p>
+        ''');
+
+      validateDartdocMarkdown('contain double backticks', '''
+        before [:can ``contain`` backticks:] after
+        ''', '''
+        <p>before <code>can ``contain`` backticks</code> after</p>
+        ''');
+
+      validateDartdocMarkdown('contain backticks with spaces', '''
+        before [: `tick` :] after
+        ''', '''
+        <p>before <code>`tick`</code> after</p>
+        ''');
+
+      validateDartdocMarkdown('multiline with spaces', '''
+        before [:in `tick`
+        another:] after
+        ''', '''
+        <p>before <code>in `tick`
+        another</code> after</p>
+        ''');
+
+      validateDartdocMarkdown('ignore markup inside code', '''
+        before [:*b* _c_:] after
+        ''', '''
+        <p>before <code>*b* _c_</code> after</p>
+        ''');
+
+      validateDartdocMarkdown('escape HTML characters', '''
+        [:<&>:]
+        ''', '''
+        <p><code>&lt;&amp;&gt;</code></p>
+        ''');
+
+      validateDartdocMarkdown('escape HTML tags', '''
+        '*' [:<em>:]
+        ''', '''
+        <p>'*' <code>&lt;em&gt;</code></p>
+        ''');
+    });
+  });
+
   group('integration tests', () {
     test('no entrypoints', () {
       expect(_runDartdoc([], exitCode: 1), completes);
@@ -138,16 +214,31 @@
               'package_test_file.dart').toNativePath()]),
         completes);
     });
-
   });
 }
 
 Future _runDartdoc(List<String> arguments, {int exitCode: 0}) {
   var dartBin = new Options().executable;
-  var dartdoc = 'bin/dartdoc.dart';
+
+  var dir = path.absolute(new Options().script);
+  while (path.basename(dir) != 'dartdoc') {
+    if (!path.absolute(dir).contains('dartdoc') || dir == path.dirname(dir)) {
+      fail('Unable to find root dartdoc directory.');
+    }
+    dir = path.dirname(dir);
+  }
+
+  var dartdoc = path.join(path.absolute(dir), 'bin/dartdoc.dart');
   arguments.insertRange(0, 1, dartdoc);
   return Process.run(dartBin, arguments)
       .then((result) {
         expect(result.exitCode, exitCode);
       });
 }
+
+validateDartdocMarkdown(String description, String markdown,
+    String html) {
+  var dartdoc = new dd.Dartdoc();
+  validate(description, markdown, html, linkResolver: dartdoc.dartdocResolver,
+      inlineSyntaxes: dartdoc.dartdocSyntaxes);
+}
diff --git a/sdk/lib/_internal/dartdoc/test/markdown_test.dart b/sdk/lib/_internal/dartdoc/test/markdown_test.dart
index bd23384..44c9431 100644
--- a/sdk/lib/_internal/dartdoc/test/markdown_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/markdown_test.dart
@@ -649,6 +649,12 @@
         second</code> after</p>
         ''');
 
+    validate('simple double backticks', '''
+        before ``source`` after
+        ''', '''
+        <p>before <code>source</code> after</p>
+        ''');
+
     validate('double backticks', '''
         before ``can `contain` backticks`` after
         ''', '''
@@ -798,6 +804,29 @@
         <p>links <a href="http://foo.com"><em>are</em></a> awesome</p>
         ''');
   });
+
+  group('Resolver', () {
+    var nyanResolver = (text) => new Text('~=[,,_${text}_,,]:3');
+    validate('simple resolver', '''
+        resolve [this] thing
+        ''', '''
+        <p>resolve ~=[,,_this_,,]:3 thing</p>
+        ''', linkResolver: nyanResolver);
+  });
+
+  group('Custom inline syntax', () {
+    List<InlineSyntax> nyanSyntax =
+      [new TextSyntax('nyan', sub: '~=[,,_,,]:3')];
+    validate('simple inline syntax', '''
+        nyan
+        ''', '''
+        <p>~=[,,_,,]:3</p>
+        ''', inlineSyntaxes: nyanSyntax);
+
+    // TODO(amouravski): need more tests here for custom syntaxes, as some
+    // things are not quite working properly. The regexps are sometime a little
+    // too greedy, I think.
+  });
 }
 
 /**
@@ -829,12 +858,13 @@
 }
 
 validate(String description, String markdown, String html,
-         {bool verbose: false}) {
+         {bool verbose: false, inlineSyntaxes, linkResolver}) {
   test(description, () {
     markdown = cleanUpLiteral(markdown);
     html = cleanUpLiteral(html);
 
-    var result = markdownToHtml(markdown);
+    var result = markdownToHtml(markdown, inlineSyntaxes: inlineSyntaxes,
+        linkResolver: linkResolver);
     var passed = compareOutput(html, result);
 
     if (!passed) {
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 8ab2e7f..b8146bb 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -66,7 +66,8 @@
       dart2jsPatchPath: "_internal/compiler/implementation/lib/isolate_patch.dart"),
 
   "json": const LibraryInfo(
-      "json/json.dart"),
+      "json/json.dart",
+      dart2jsPatchPath: "_internal/compiler/implementation/lib/json_patch.dart"),
 
   "math": const LibraryInfo(
       "math/math.dart",
diff --git a/sdk/lib/async/async_error.dart b/sdk/lib/async/async_error.dart
index 81a1e04..fa90e87 100644
--- a/sdk/lib/async/async_error.dart
+++ b/sdk/lib/async/async_error.dart
@@ -20,30 +20,29 @@
   AsyncError(this.error, [this.stackTrace]): cause = null;
   AsyncError.withCause(this.error, this.stackTrace, this.cause);
 
-  void _writeOn(StringBuffer buffer) {
-    buffer.add("'");
+  void _writeOn(StringSink buffer) {
+    buffer.write("'");
     String message;
     try {
       message = error.toString();
     } catch (e) {
       message = Error.safeToString(error);
     }
-    buffer.add(message);
-    buffer.add("'\n");
+    buffer.write(message);
+    buffer.write("'\n");
     if (stackTrace != null) {
-      buffer.add("Stack trace:\n");
-      buffer.add(stackTrace.toString());
-      buffer.add("\n");
+      buffer.write("Stack trace:\n");
+      buffer.writeln(stackTrace.toString());
     }
   }
 
   String toString() {
     StringBuffer buffer = new StringBuffer();
-    buffer.add("AsyncError: ");
+    buffer.write("AsyncError: ");
     _writeOn(buffer);
     AsyncError cause = this.cause;
     while (cause != null) {
-      buffer.add("Caused by: ");
+      buffer.write("Caused by: ");
       cause._writeOn(buffer);
       cause = cause.cause;
     }
diff --git a/sdk/lib/async/async_sources.gypi b/sdk/lib/async/async_sources.gypi
index d297cae..7fdd956 100644
--- a/sdk/lib/async/async_sources.gypi
+++ b/sdk/lib/async/async_sources.gypi
@@ -5,6 +5,8 @@
 # This file contains all sources for the dart:async library.
 {
   'sources': [
+    'async.dart',
+    # The above file needs to be first as it lists the parts below.
     'async_error.dart',
     'collection_sink.dart',
     'deferred_load.dart',
diff --git a/sdk/lib/async/deferred_load.dart b/sdk/lib/async/deferred_load.dart
index bc99a4d..35ff034 100644
--- a/sdk/lib/async/deferred_load.dart
+++ b/sdk/lib/async/deferred_load.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+part of dart.async;
+
 /**
  * Indicates that loading of [libraryName] is deferred.
  *
@@ -9,21 +11,19 @@
  *
  * Example usage:
  *
- * [:
- * @lazy
- * import 'foo.dart' as foo;
+ *     @lazy
+ *     import 'foo.dart' as foo;
  *
- * const lazy = const DeferredLibrary('com.example.foo');
+ *     const lazy = const DeferredLibrary('com.example.foo');
  *
- * void main() {
- *   foo.method(); // Throws a NoSuchMethodError, foo is not loaded yet.
- *   lazy.load().then(onFooLoaded);
- * }
+ *     void main() {
+ *       foo.method(); // Throws a NoSuchMethodError, foo is not loaded yet.
+ *       lazy.load().then(onFooLoaded);
+ *     }
  *
- * void onFooLoaded(_) {
- *   foo.method();
- * }
- * :]
+ *     void onFooLoaded(_) {
+ *       foo.method();
+ *     }
  */
 class DeferredLibrary {
   final String libraryName;
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 820ba00..96bf0cc 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -149,11 +149,8 @@
    * error.
    *
    * See [Completer]s, for futures with values that are computed asynchronously.
-   *
-   * *Deprecation note*: this method initially took an [int] as argument (the
-   * milliseconds to wait). It is now a [Duration].
    */
-  factory Future.delayed(var duration, [T computation()]) {
+  factory Future.delayed(Duration duration, [T computation()]) {
     // TODO(floitsch): no need to allocate a ThenFuture when the computation is
     // null.
     if (computation == null) computation = (() => null);
@@ -190,7 +187,8 @@
     Iterator iterator = input.iterator;
     void nextElement(_) {
       if (iterator.moveNext()) {
-        f(iterator.current).then(nextElement, onError: doneSignal._setError);
+        new Future.of(() => f(iterator.current))
+            .then(nextElement, onError: doneSignal._setError);
       } else {
         doneSignal._setValue(null);
       }
@@ -362,4 +360,9 @@
    * [AsyncError] and sent to this future's listeners.
    */
   void completeError(Object exception, [Object stackTrace]);
+
+  /**
+   * Whether the future has been completed.
+   */
+  bool get isCompleted;
 }
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 85d73af..c793d8f 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -33,6 +33,8 @@
     _FutureImpl future = this.future;
     future._setError(asyncError);
   }
+
+  bool get isCompleted => _isComplete;
 }
 
 /**
@@ -139,7 +141,7 @@
     if (remaining == 0) {
       return new Future.immediate(const []);
     }
-    values = new List.fixedLength(remaining);
+    values = new List(remaining);
     completer = new Completer<List>();
     return completer.future;
   }
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index a026484..185ce2a 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -20,8 +20,14 @@
  * or to temporarily pause events from the stream.
  *
  * When an event is fired, the listeners at that time are informed.
- * If a listener is added or removed while an event is being fired, the change
- * will only take effect after the event is completely fired.
+ * If a listener is added while an event is being fired, the change
+ * will only take effect after the event is completely fired. If a listener
+ * is canceled, it immediately stops receiving events.
+ *
+ * When the "done" event is fired, subscribers are unsubscribed before
+ * receiving the event. After the event has been sent, the stream has no
+ * subscribers. Adding new subscribers after this point is allowed, but
+ * they will just receive a new "done" event as soon as possible.
  *
  * Streams always respect "pause" requests. If necessary they need to buffer
  * their input, but often, and preferably, they can simply request their input
@@ -77,7 +83,7 @@
   }
 
   /**
-   * Whether the stream is a broadcast stream.
+   * Reports whether this stream is a broadcast stream.
    */
   bool get isBroadcast => false;
 
@@ -97,9 +103,9 @@
   }
 
   /**
-   * Add a subscription to this stream.
+   * Adds a subscription to this stream.
    *
-   * On each data event from this stream, the subscribers [onData] handler
+   * On each data event from this stream, the subscriber's [onData] handler
    * is called. If [onData] is null, nothing happens.
    *
    * On errors from this stream, the [onError] handler is given a
@@ -126,7 +132,7 @@
   }
 
   /**
-   * Create a new stream that converts each element of this stream
+   * Creates a new stream that converts each element of this stream
    * to a new value using the [convert] function.
    */
   Stream map(convert(T event)) {
@@ -134,7 +140,7 @@
   }
 
   /**
-   * Create a wrapper Stream that intercepts some errors from this stream.
+   * Creates a wrapper Stream that intercepts some errors from this stream.
    *
    * If this stream sends an error that matches [test], then it is intercepted
    * by the [handle] function.
@@ -155,7 +161,7 @@
   }
 
   /**
-   * Create a new stream from this stream that converts each element
+   * Creates a new stream from this stream that converts each element
    * into zero or more events.
    *
    * Each incoming event is converted to an [Iterable] of new events,
@@ -167,14 +173,14 @@
   }
 
   /**
-   * Bind this stream as the input of the provided [StreamConsumer].
+   * Binds this stream as the input of the provided [StreamConsumer].
    */
   Future pipe(StreamConsumer<T, dynamic> streamConsumer) {
     return streamConsumer.consume(this);
   }
 
   /**
-   * Chain this stream as the input of the provided [StreamTransformer].
+   * Chains this stream as the input of the provided [StreamTransformer].
    *
    * Returns the result of [:streamTransformer.bind:] itself.
    */
@@ -225,7 +231,7 @@
 
 
   /**
-   * Check whether [match] occurs in the elements provided by this stream.
+   * Checks whether [match] occurs in the elements provided by this stream.
    *
    * Completes the [Future] when the answer is known.
    * If this stream reports an error, the [Future] will report that error.
@@ -257,7 +263,7 @@
   }
 
   /**
-   * Check whether [test] accepts all elements provided by this stream.
+   * Checks whether [test] accepts all elements provided by this stream.
    *
    * Completes the [Future] when the answer is known.
    * If this stream reports an error, the [Future] will report that error.
@@ -289,7 +295,7 @@
   }
 
   /**
-   * Check whether [test] accepts any element provided by this stream.
+   * Checks whether [test] accepts any element provided by this stream.
    *
    * Completes the [Future] when the answer is known.
    * If this stream reports an error, the [Future] will report that error.
@@ -440,7 +446,7 @@
     return future;
   }
 
-  /** Collect the data of this stream in a [List]. */
+  /** Collects the data of this stream in a [List]. */
   Future<List<T>> toList() {
     List<T> result = <T>[];
     _FutureImpl<List<T>> future = new _FutureImpl<List<T>>();
@@ -458,7 +464,7 @@
     return future;
   }
 
-  /** Collect the data of this stream in a [Set]. */
+  /** Collects the data of this stream in a [Set]. */
   Future<Set<T>> toSet() {
     Set<T> result = new Set<T>();
     _FutureImpl<Set<T>> future = new _FutureImpl<Set<T>>();
@@ -477,7 +483,7 @@
   }
 
   /**
-   * Provide at most the first [n] values of this stream.
+   * Provides at most the first [n] values of this stream.
    *
    * Forwards the first [n] data events of this stream, and all error
    * events, to the returned stream, and ends with a done event.
@@ -521,7 +527,7 @@
   }
 
   /**
-   * Skip data events if they are equal to the previous data event.
+   * Skips data events if they are equal to the previous data event.
    *
    * The returned stream provides the same events as this stream, except
    * that it never provides two consequtive data events that are equal.
@@ -624,7 +630,7 @@
   }
 
   /**
-   * Find the first element of this stream matching [test].
+   * Finds the first element of this stream matching [test].
    *
    * Returns a future that is filled with the first element of this stream
    * that [test] returns true for.
@@ -1014,6 +1020,7 @@
                                { void onError(AsyncError error),
                                  void onDone(),
                                  bool unsubscribeOnError }) {
+    unsubscribeOnError = identical(true, unsubscribeOnError);
     return new _EventTransformStreamSubscription(_source, _transformer,
                                                  onData, onError, onDone,
                                                  unsubscribeOnError);
@@ -1077,6 +1084,7 @@
   }
 
   void _handleDone() {
+    _subscription = null;
     try {
       _transformer.handleDone(_sink);
     } catch (e, s) {
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index e5b8b45..9ea10f5 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -19,6 +19,32 @@
  * It's possible to check whether the stream is paused or not, and whether
  * it has subscribers or not, as well as getting a callback when either of
  * these change.
+ *
+ * If the stream starts or stops having listeners (first listener subscribing,
+ * last listener unsubscribing), the `onSubscriptionStateChange` callback
+ * is notified as soon as possible. If the subscription stat changes during
+ * an event firing or a callback being executed, the change will not be reported
+ * until the current event or callback has finished.
+ * If the pause state has also changed during an event or callback, only the
+ * subscription state callback is notified.
+ *
+ * If the subscriber state has not changed, but the pause state has, the
+ * `onPauseStateChange` callback is notified as soon as possible, after firing
+ * a current event or completing another callback. This happens if the stream
+ * is not paused, and a listener pauses it, or if the stream has been resumed
+ * from pause and has no pending events. If the listeners resume a paused stream
+ * while it still has queued events, the controller will still consider the
+ * stream paused until all queued events have been dispatched.
+ *
+ * Whether to invoke a callback depends only on the state before and after
+ * a stream action, for example firing an event. If the state changes multiple
+ * times during the action, and then ends up in the same state as before, no
+ * callback is performed.
+ *
+ * If listeners are added after the stream has completed (sent a "done" event),
+ * the listeners will be sent a "done" event eventually, but they won't affect
+ * the stream at all, and won't trigger callbacks. From the controller's point
+ * of view, the stream is completely inert when has completed.
  */
 class StreamController<T> implements StreamSink<T> {
   final _StreamImpl<T> stream;
@@ -63,8 +89,16 @@
    */
   StreamSink<T> get sink => new StreamSinkView<T>(this);
 
+  /**
+   * Whether the stream is closed for adding more events.
+   *
+   * If true, the "done" event might not have fired yet, but it has been
+   * scheduled, and it is too late to add more events.
+   */
+  bool get isClosed => stream._isClosed;
+
   /** Whether one or more active subscribers have requested a pause. */
-  bool get isPaused => stream._isPaused;
+  bool get isPaused => stream._isInputPaused;
 
   /** Whether there are currently any subscribers on this [Stream]. */
   bool get hasSubscribers => stream._hasSubscribers;
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 130f226..ccaa506 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -6,6 +6,7 @@
 
 // States shared by single/multi stream implementations.
 
+// Completion state of the stream.
 /// Initial and default state where the stream can receive and send events.
 const int _STREAM_OPEN = 0;
 /// The stream has received a request to complete, but hasn't done so yet.
@@ -15,17 +16,26 @@
 /// Also counts as closed. The stream must not be paused when it's completed.
 /// Always used in conjunction with [_STREAM_CLOSED].
 const int _STREAM_COMPLETE = 2;
+
 /// Bit that alternates between events, and listeners are updated to the
 /// current value when they are notified of the event.
 const int _STREAM_EVENT_ID = 4;
 const int _STREAM_EVENT_ID_SHIFT = 2;
+
+// The activity state of the stream: What is it currently doing.
 /// Bit set while firing and clear while not.
 const int _STREAM_FIRING = 8;
 /// Bit set while calling a pause-state or subscription-state change callback.
 const int _STREAM_CALLBACK = 16;
+
+// The pause state of the stream.
+/// Bit set when resuming with pending events. Cleared after all pending events
+/// have been transmitted. Means that the controller still considers the
+/// stream paused, even if the listener doesn't.
+const int _STREAM_PENDING_RESUME = 32;
 /// The count of times a stream has paused is stored in the
 /// state, shifted by this amount.
-const int _STREAM_PAUSE_COUNT_SHIFT = 5;
+const int _STREAM_PAUSE_COUNT_SHIFT = 6;
 
 // States for listeners.
 
@@ -36,9 +46,11 @@
 /// The listener is subscribed until it has been notified of the current event.
 /// This flag bit is always used in conjuction with [_LISTENER_SUBSCRIBED].
 const int _LISTENER_PENDING_UNSUBSCRIBE = 2;
+
 /// Bit that contains the last sent event's "id bit".
 const int _LISTENER_EVENT_ID = 4;
 const int _LISTENER_EVENT_ID_SHIFT = 2;
+
 /// The count of times a listener has paused is stored in the
 /// state, shifted by this amount.
 const int _LISTENER_PAUSE_COUNT_SHIFT = 3;
@@ -92,11 +104,16 @@
    */
   void _add(T value) {
     if (_isClosed) throw new StateError("Sending on closed stream");
-    if (!_canFireEvent) {
+    if (!_mayFireState) {
+      // Not the time to send events.
       _addPendingEvent(new _DelayedData<T>(value));
       return;
     }
-    _sendData(value);
+    if (_hasPendingEvent) {
+      _addPendingEvent(new _DelayedData<T>(value));
+    } else {
+      _sendData(value);
+    }
     _handlePendingEvents();
   }
 
@@ -108,11 +125,16 @@
    */
   void _signalError(AsyncError error) {
     if (_isClosed) throw new StateError("Sending on closed stream");
-    if (!_canFireEvent) {
+    if (!_mayFireState) {
+      // Not the time to send events.
       _addPendingEvent(new _DelayedError(error));
       return;
     }
-    _sendError(error);
+    if (_hasPendingEvent) {
+      _addPendingEvent(new _DelayedError(error));
+    } else {
+      _sendError(error);
+    }
     _handlePendingEvents();
   }
 
@@ -125,19 +147,29 @@
   void _close() {
     if (_isClosed) return;
     _state |= _STREAM_CLOSED;
-    if (!_canFireEvent) {
-      // You can't enqueue an event after the Done, so make it const.
+    if (!_mayFireState) {
+      // Not the time to send events.
       _addPendingEvent(const _DelayedDone());
       return;
     }
-    _sendDone();
-    assert(!_hasPendingEvent);
+    if (_hasPendingEvent) {
+      _addPendingEvent(new _DelayedDone());
+      _handlePendingEvents();
+    } else {
+      _sendDone();
+      assert(_isComplete);
+      assert(!_hasPendingEvent);
+    }
   }
 
   // -------------------------------------------------------------------
   // Internal implementation.
 
-  // State prediates.
+  // State predicates.
+
+  // Lifecycle state.
+  /** Whether the stream is in the default, open, state for events. */
+  bool get _isOpen => (_state & (_STREAM_CLOSED | _STREAM_COMPLETE)) == 0;
 
   /** Whether the stream has been closed (a done event requested). */
   bool get _isClosed => (_state & _STREAM_CLOSED) != 0;
@@ -145,25 +177,64 @@
   /** Whether the stream is completed. */
   bool get _isComplete => (_state & _STREAM_COMPLETE) != 0;
 
+  // Pause state.
+
   /** Whether one or more active subscribers have requested a pause. */
   bool get _isPaused => _state >= (1 << _STREAM_PAUSE_COUNT_SHIFT);
 
+  /** How many times the stream has been paused. */
+  int get _pauseCount => _state >> _STREAM_PAUSE_COUNT_SHIFT;
+
+  /**
+   * Whether a controller thinks the stream is paused.
+   *
+   * When this changes, a pause-state change callback is performed.
+   *
+   * It may differ from [_isPaused] if there are pending events
+   * in the queue when the listeners resume. The controller won't
+   * be informed until all queued events have been fired.
+   */
+  bool get _isInputPaused => _state >= (_STREAM_PENDING_RESUME);
+
+  /** Whether we have a pending resume scheduled. */
+  bool get _hasPendingResume => (_state & _STREAM_PENDING_RESUME) != 0;
+
+
+  // Action state. If the stream makes a call-out to external code,
+  // this state tracks it and avoids reentrancy problems.
+
+  /** Whether the stream is not currently firing or calling a callback. */
+  bool get _isInactive => (_state & (_STREAM_CALLBACK | _STREAM_FIRING)) == 0;
+
   /** Whether we are currently executing a state-chance callback. */
   bool get _isInCallback => (_state & _STREAM_CALLBACK) != 0;
 
+  /** Whether we are currently firing an event. */
+  bool get _isFiring => (_state & _STREAM_FIRING) != 0;
+
   /** Check whether the pending event queue is non-empty */
   bool get _hasPendingEvent =>
       _pendingEvents != null && !_pendingEvents.isEmpty;
 
-  /** Whether we are currently firing an event. */
-  bool get _isFiring => (_state & _STREAM_FIRING) != 0;
+  /**
+   * The bit representing the current or last event fired.
+   *
+   * This bit matches a bit on listeners that have received the corresponding
+   * event. It is toggled for each new event being fired.
+   */
+  int get _currentEventIdBit =>
+      (_state & _STREAM_EVENT_ID ) >> _STREAM_EVENT_ID_SHIFT;
+
+  /** Whether there is currently a subscriber on this [Stream]. */
+  bool get _hasSubscribers;
+
 
   /** Whether the state bits allow firing. */
   bool get _mayFireState {
-    // The state disallows firing if:
-    // - an event is currently firing
-    // - a stat-change callback is being called
-    // - the pause-count is not zero.
+    // The state allows firing unless:
+    // - it's currently firing
+    // - it's currently in a callback
+    // - it's paused
     const int mask =
         _STREAM_FIRING |
         _STREAM_CALLBACK |
@@ -171,20 +242,12 @@
     return (_state & mask) == 0;
   }
 
-  int get _currentEventIdBit =>
-      (_state & _STREAM_EVENT_ID ) >> _STREAM_EVENT_ID_SHIFT;
-
-  /** Whether there is currently a subscriber on this [Stream]. */
-  bool get _hasSubscribers;
-
-  /** Whether the stream can fire a new event. */
-  bool get _canFireEvent => _mayFireState && !_hasPendingEvent;
-
   // State modification.
 
   /** Record an increases in the number of times the listener has paused. */
   void _incrementPauseCount(_StreamListener<T> listener) {
     listener._incrementPauseCount();
+    _state &= ~_STREAM_PENDING_RESUME;
     _updatePauseCount(1);
   }
 
@@ -222,6 +285,7 @@
 
   void _startFiring() {
     assert(!_isFiring);
+    assert(!_isInCallback);
     assert(_hasSubscribers);
     assert(!_isPaused);
     // This sets the _STREAM_FIRING bit and toggles the _STREAM_EVENT_ID
@@ -231,14 +295,11 @@
     _state ^= _STREAM_FIRING | _STREAM_EVENT_ID;
   }
 
-  void _endFiring() {
+  void _endFiring(bool wasInputPaused) {
     assert(_isFiring);
     _state ^= _STREAM_FIRING;
-    if (!_hasSubscribers) {
-      _callOnSubscriptionStateChange();
-    } else if (_isPaused) {
-      _callOnPauseStateChange();
-    }
+    // Had listeners, or we wouldn't have fired.
+    _checkCallbacks(true, wasInputPaused);
   }
 
   /**
@@ -256,13 +317,20 @@
       throw new StateError("Subscription has been canceled.");
     }
     assert(!_isComplete);  // There can be no subscribers when complete.
+    bool wasInputPaused = _isInputPaused;
     bool wasPaused = _isPaused;
     _incrementPauseCount(listener);
     if (resumeSignal != null) {
       resumeSignal.whenComplete(() { this._resume(listener, true); });
     }
-    if (!wasPaused && !_isFiring) {
-      _callOnPauseStateChange();
+    if (!wasPaused && _hasPendingEvent && _pendingEvents.isScheduled) {
+      _pendingEvents.cancelSchedule();
+    }
+    if (_isInactive && !wasInputPaused) {
+      _checkCallbacks(true, false);
+      if (!_isPaused && _hasPendingEvent) {
+        _schedulePendingEvents();
+      }
     }
   }
 
@@ -273,13 +341,25 @@
     assert(_isPaused);
     _decrementPauseCount(listener);
     if (!_isPaused) {
-      if (!_isFiring) _callOnPauseStateChange();
       if (_hasPendingEvent) {
+        _state |= _STREAM_PENDING_RESUME;
+        // Controller's pause state hasn't changed.
         // If we can fire events now, fire any pending events right away.
-        if (fromEvent && !_isFiring) {
-          _handlePendingEvents();
-        } else {
-          _schedulePendingEvents();
+        if (_isInactive) {
+          if (fromEvent) {
+            _handlePendingEvents();
+          } else {
+            _schedulePendingEvents();
+          }
+        }
+      } else if (_isInactive) {
+        _checkCallbacks(true, true);
+        if (!_isPaused && _hasPendingEvent) {
+          if (fromEvent) {
+            _handlePendingEvents();
+          } else {
+            _schedulePendingEvents();
+          }
         }
       }
     }
@@ -330,27 +410,34 @@
    */
   void _forEachSubscriber(void action(_StreamSubscriptionImpl<T> subscription));
 
-  /** Calls [_onPauseStateChange] while setting callback bit. */
-  void _callOnPauseStateChange() {
-    // After calling [_close], all pauses are handled internally by the Stream.
-    if (_isClosed) return;
-    if (!_isInCallback) {
-      _state |= _STREAM_CALLBACK;
-      _onPauseStateChange();
-      _state ^= _STREAM_CALLBACK;
-    } else {
-      _onPauseStateChange();
+  /**
+   * Checks whether the subscription/pause state has changed.
+   *
+   * Calls the appropriate callback if the state has changed from the
+   * provided one. Repeats calling callbacks as long as the call changes
+   * the state.
+   */
+  void _checkCallbacks(bool hadSubscribers, bool wasPaused) {
+    assert(!_isFiring);
+    // Will be handled after the current callback.
+    if (_isInCallback) return;
+    if (_hasPendingResume && !_hasPendingEvent) {
+      _state ^= _STREAM_PENDING_RESUME;
     }
-  }
-
-  /** Calls [_onSubscriptionStateChange] while setting callback bit. */
-  void _callOnSubscriptionStateChange() {
-    if (!_isInCallback) {
-      _state |= _STREAM_CALLBACK;
-      _onSubscriptionStateChange();
-      _state ^= _STREAM_CALLBACK;
-    } else {
-      _onSubscriptionStateChange();
+    _state |= _STREAM_CALLBACK;
+    while (true) {
+      bool hasSubscribers = _hasSubscribers;
+      bool isPaused = _isInputPaused;
+      if (hadSubscribers != hasSubscribers) {
+        _onSubscriptionStateChange();
+      } else if (isPaused != wasPaused) {
+        _onPauseStateChange();
+      } else {
+        _state ^= _STREAM_CALLBACK;
+        return;
+      }
+      wasPaused = isPaused;
+      hadSubscribers = hasSubscribers;
     }
   }
 
@@ -368,20 +455,32 @@
    */
   void _onSubscriptionStateChange() {}
 
-  /** Add a pending event at the end of the pending event queue. */
+  /**
+   * Add a pending event at the end of the pending event queue.
+   *
+   * Schedules events if currently not paused and inside a callback.
+   */
   void _addPendingEvent(_DelayedEvent event) {
     if (_pendingEvents == null) _pendingEvents = new _StreamImplEvents();
     _StreamImplEvents events = _pendingEvents;
     events.add(event);
+    if (_isPaused || _isFiring) return;
+    if (_isInCallback) {
+      _schedulePendingEvents();
+      return;
+    }
   }
 
-  /** Fire any pending events until the pending event queue. */
+  /** Fire any pending events until the pending event queue is empty. */
   void _handlePendingEvents() {
+    assert(_isInactive);
+    if (!_hasPendingEvent) return;
     _PendingEvents events = _pendingEvents;
-    if (events == null) return;
-    while (!events.isEmpty && !_isPaused) {
+    do {
+      if (_isPaused) return;
+      if (events.isScheduled) events.cancelSchedule();
       events.handleNext(this);
-    }
+    } while (!events.isEmpty);
   }
 
   /**
@@ -390,6 +489,7 @@
   _sendData(T value) {
     assert(!_isPaused);
     assert(!_isComplete);
+    if (!_hasSubscribers) return;
     _forEachSubscriber((subscriber) {
       try {
         subscriber._sendData(value);
@@ -407,6 +507,7 @@
   void _sendError(AsyncError error) {
     assert(!_isPaused);
     assert(!_isComplete);
+    if (!_hasSubscribers) return;
     _forEachSubscriber((subscriber) {
       try {
         subscriber._sendError(error);
@@ -467,7 +568,7 @@
  *                               when losing the last subscriber.
  * * [_onPauseStateChange]: Called when entering or leaving paused mode.
  * * [_hasSubscribers]: Test whether there are currently any subscribers.
- * * [_isPaused]: Test whether the stream is currently paused.
+ * * [_isInputPaused]: Test whether the stream is currently paused.
  * The user should not add new events while the stream is paused, but if it
  * happens anyway, the stream will enqueue the events just as when new events
  * arrive while still firing an old event.
@@ -475,26 +576,17 @@
 class _SingleStreamImpl<T> extends _StreamImpl<T> {
   _StreamListener _subscriber = null;
 
-  // A single-stream is considered paused when it has no subscriber.
-  // Exception is when it's complete (which only matters for pause-state-change
-  // callbacks), where it's not considered paused.
-  bool get _isPaused => (!_hasSubscribers && !_isComplete) || super._isPaused;
-
-
-  bool get _canFireEvent {
-    // A single-stream is considered paused when it has no subscriber and
-    // isn't complete, so it can't fire if there is no subscriber.
-    // It won't try to fire when completed, so no need to check that.
-    return _mayFireState && !_hasPendingEvent && _hasSubscribers;
-  }
-
-
   /** Whether there is currently a subscriber on this [Stream]. */
   bool get _hasSubscribers => _subscriber != null;
 
   // -------------------------------------------------------------------
   // Internal implementation.
 
+  _SingleStreamImpl() {
+    // Start out paused.
+    _updatePauseCount(1);
+  }
+
   /**
    * Create the new subscription object.
    */
@@ -508,14 +600,19 @@
   }
 
   void _addListener(_StreamListener subscription) {
+    assert(!_isComplete);
     if (_hasSubscribers) {
       throw new StateError("Stream already has subscriber.");
     }
+    assert(_pauseCount == 1);
+    _updatePauseCount(-1);
     _subscriber = subscription;
     subscription._setSubscribed(0);
-    _callOnSubscriptionStateChange();
-    if (_hasPendingEvent) {
-      _schedulePendingEvents();
+    if (_isInactive) {
+      _checkCallbacks(false, true);
+      if (!_isPaused && _hasPendingEvent) {
+        _schedulePendingEvents();
+      }
     }
   }
 
@@ -523,9 +620,6 @@
    * Handle a cancel requested from a [_StreamSubscriptionImpl].
    *
    * This method is called from [_StreamSubscriptionImpl.cancel].
-   *
-   * If an event is currently firing, the cancel is delayed
-   * until after the subscriber has received the event.
    */
   void _cancel(_StreamListener subscriber) {
     assert(identical(subscriber._source, this));
@@ -538,21 +632,27 @@
     }
     _subscriber = null;
     // Unsubscribing a paused subscription also cancels its pauses.
-    int subscriptionPauseCount = subscriber._setUnsubscribed();
-    _updatePauseCount(-subscriptionPauseCount);
-    if (!_isFiring) {
-      _callOnSubscriptionStateChange();
+    int resumeCount = subscriber._setUnsubscribed();
+    // Keep being paused while there is no subscriber and the stream is not
+    // complete.
+    _updatePauseCount(_isComplete ? -resumeCount : -resumeCount + 1);
+    if (_isInactive) {
+      _checkCallbacks(true, resumeCount > 0);
+      if (!_isPaused && _hasPendingEvent) {
+        _schedulePendingEvents();
+      }
     }
   }
 
   void _forEachSubscriber(
       void action(_StreamListener<T> subscription)) {
     assert(!_isPaused);
+    bool wasInputPaused = _isInputPaused;
     _StreamListener subscription = _subscriber;
     assert(subscription != null);
     _startFiring();
     action(subscription);
-    _endFiring();
+    _endFiring(wasInputPaused);
   }
 }
 
@@ -638,6 +738,7 @@
       void action(_StreamListener<T> subscription)) {
     assert(!_isFiring);
     if (!_hasSubscribers) return;
+    bool wasInputPaused = _isInputPaused;
     _startFiring();
     _InternalLink cursor = this._nextLink;
     while (!identical(cursor, this)) {
@@ -652,15 +753,18 @@
         _removeListener(current);
       }
     }
-    _endFiring();
+    _endFiring(wasInputPaused);
   }
 
   void _addListener(_StreamListener listener) {
     listener._setSubscribed(_currentEventIdBit);
-    bool firstSubscriber = !_hasSubscribers;
+    bool hadSubscribers = _hasSubscribers;
     _InternalLinkList.add(this, listener);
-    if (firstSubscriber) {
-      _callOnSubscriptionStateChange();
+    if (!hadSubscribers && _isInactive) {
+      _checkCallbacks(false, false);
+      if (!_isPaused && _hasPendingEvent) {
+        _schedulePendingEvents();
+      }
     }
   }
 
@@ -681,7 +785,7 @@
     if (_isFiring) {
       if (listener._needsEvent(_currentEventIdBit)) {
         assert(listener._isSubscribed);
-        listener._setPendingUnsubscribe();
+        listener._setPendingUnsubscribe(_currentEventIdBit);
       } else {
         // The listener has been notified of the event (or don't need to,
         // if it's still pending subscription) so it's safe to remove it.
@@ -690,10 +794,14 @@
       // Pause and subscription state changes are reported when we end
       // firing.
     } else {
-      bool wasPaused = _isPaused;
+      bool wasInputPaused = _isInputPaused;
       _removeListener(listener);
-      if (wasPaused != _isPaused) _onPauseStateChange();
-      if (!_hasSubscribers) _callOnSubscriptionStateChange();
+      if (_isInactive) {
+        _checkCallbacks(true, wasInputPaused);
+        if (!_isPaused && _hasPendingEvent) {
+          _schedulePendingEvents();
+        }
+      }
     }
   }
 
@@ -705,8 +813,13 @@
    */
   void _removeListener(_StreamListener listener) {
     int pauseCount = listener._setUnsubscribed();
-    _updatePauseCount(-pauseCount);
     _InternalLinkList.remove(listener);
+    if (pauseCount > 0) {
+      _updatePauseCount(-pauseCount);
+      if (!_isPaused && _hasPendingEvent) {
+        _state |= _STREAM_PENDING_RESUME;
+      }
+    }
   }
 }
 
@@ -1031,9 +1144,13 @@
     _state = _LISTENER_SUBSCRIBED | (eventIdBit << _LISTENER_EVENT_ID_SHIFT);
   }
 
-  void _setPendingUnsubscribe() {
+  void _setPendingUnsubscribe(int currentEventIdBit) {
     assert(_isSubscribed);
-    _state |= _LISTENER_PENDING_UNSUBSCRIBE;
+    // Sets the pending unsubscribe, and ensures that the listener
+    // won't get the current event.
+    _state |= _LISTENER_PENDING_UNSUBSCRIBE | _LISTENER_EVENT_ID;
+    _state ^= (1 ^ currentEventIdBit) << _LISTENER_EVENT_ID_SHIFT;
+    assert(!_needsEvent(currentEventIdBit));
   }
 
   /**
@@ -1079,7 +1196,7 @@
 
   void schedule(_StreamImpl stream) {
     if (isScheduled) return;
-    scheduleTimer = Timer.run(() {
+    scheduleTimer = new Timer(Duration.ZERO, () {
       scheduleTimer = null;
       stream._handlePendingEvents();
     });
@@ -1115,7 +1232,7 @@
   }
 
   void handleNext(_StreamImpl stream) {
-    if (isScheduled) cancelSchedule();
+    assert(!isScheduled);
     _DelayedEvent event = firstPendingEvent;
     firstPendingEvent = event.next;
     if (firstPendingEvent == null) {
@@ -1137,7 +1254,7 @@
 
   void _delayDone() {
     assert(_timer == null && _pauseCount == 0);
-    _timer = Timer.run(() {
+    _timer = new Timer(Duration.ZERO, () {
       if (_handler != null) _handler();
     });
   }
@@ -1156,8 +1273,12 @@
     if (_isComplete) {
       throw new StateError("Subscription has been canceled.");
     }
-    if (_timer != null) _timer.cancel();
+    if (_timer != null) {
+      _timer.cancel();
+      _timer = null;
+    }
     _pauseCount++;
+    if (signal != null) signal.whenComplete(resume);
   }
 
   void resume() {
@@ -1186,7 +1307,7 @@
 }
 
 class _SingleStreamMultiplexer<T> extends _MultiStreamImpl<T> {
-  final _SingleStreamImpl<T> _source;
+  final Stream<T> _source;
   StreamSubscription<T> _subscription;
 
   _SingleStreamMultiplexer(this._source);
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index 39fe4c2..7ed5d5a 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.dart
@@ -5,12 +5,14 @@
 part of dart.async;
 
 abstract class Timer {
+  // Internal list used to group Timer.run callbacks.
+  static List _runCallbacks = [];
+
   /**
    * Creates a new timer.
    *
-   * The [callback] callback is invoked after the given [duration]
-   * (a [Duration]) has passed. A negative duration is treated similar to
-   * a duration of 0.
+   * The [callback] callback is invoked after the given [duration].
+   * A negative duration is treated similar to a duration of 0.
    *
    * If the [duration] is statically known to be 0, consider using [run].
    *
@@ -25,34 +27,45 @@
    *       var duration = milliseconds == null ? TIMEOUT : ms * milliseconds;
    *       return new Timer(duration, handleTimeout);
    *     }
-   *
-   * *Deprecation warning*: this constructor used to take an [int] (the time
-   * in milliseconds) and a callback with one argument (the timer). This has
-   * changed to a [Duration] and a callback without arguments.
    */
-  // TODO(floitsch): add types.
-  external factory Timer(var duration, Function callback);
+  external factory Timer(Duration duration, void callback());
 
   /**
    * Creates a new repeating timer.
    *
    * The [callback] is invoked repeatedly with [duration] intervals until
    * canceled. A negative duration is treated similar to a duration of 0.
-   *
-   * *Deprecation warning*: this constructor used to take an [int] (the time
-   * in milliseconds). This has changed to a [Duration].
    */
-  external factory Timer.repeating(var duration,
+  external factory Timer.repeating(Duration duration,
                                    void callback(Timer timer));
 
   /**
    * Runs the given [callback] asynchronously as soon as possible.
-   *
-   * Returns a [Timer] that can be cancelled if the callback is not necessary
-   * anymore.
    */
-  static Timer run(void callback()) {
-    return new Timer(const Duration(), callback);
+  static void run(void callback()) {
+    // Optimizing a group of Timer.run callbacks to be executed in the
+    // same Timer callback.
+    _runCallbacks.add(callback);
+    if (_runCallbacks.length == 1) {
+      new Timer(const Duration(milliseconds: 0), () {
+        List runCallbacks = _runCallbacks;
+        // Create new list to make sure we don't call newly added callbacks in
+        // this event.
+        _runCallbacks = [];
+        for (int i = 0; i < runCallbacks.length; i++) {
+          Function callback = runCallbacks[i];
+          try {
+            callback();
+          } catch (e) {
+            List newCallbacks = _runCallbacks;
+            _runCallbacks = [];
+            _runCallbacks.addAll(runCallbacks.skip(i + 1));
+            _runCallbacks.addAll(newCallbacks);
+            throw;
+          }
+        }
+      });
+    }
   }
 
   /**
diff --git a/sdk/lib/chrome/dart2js/chrome_dart2js.dart b/sdk/lib/chrome/dart2js/chrome_dart2js.dart
index 92b66c5..7c1ca62 100644
--- a/sdk/lib/chrome/dart2js/chrome_dart2js.dart
+++ b/sdk/lib/chrome/dart2js/chrome_dart2js.dart
@@ -1,3 +1,10 @@
+/// Native wrappers for the Chrome Packaged App APIs.
+///
+/// These functions allow direct access to the Packaged App APIs, allowing
+/// Chrome Packaged Apps to be written using Dart.
+///
+/// For more information on these APIs, see the
+/// [Chrome APIs Documentation](http://developer.chrome.com/extensions/api_index.html)
 library chrome;
 
 import 'dart:_foreign_helper' show JS;
@@ -13,13 +20,6 @@
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
 // Auto-generated dart:chrome library.
 
-/// Native wrappers for the Chrome Packaged App APIs.
-///
-/// These functions allow direct access to the Packaged App APIs, allowing
-/// Chrome Packaged Apps to be written using Dart.
-///
-/// For more information on these APIs, see the Chrome.* APIs Documentation:
-///   http://developer.chrome.com/extensions/api_index.html
 
 /* TODO(sashab): Add "show convertDartClosureToJS" once 'show' works. */
 
diff --git a/sdk/lib/chrome/dartium/chrome_dartium.dart b/sdk/lib/chrome/dartium/chrome_dartium.dart
index c228655..b741b3b 100644
--- a/sdk/lib/chrome/dartium/chrome_dartium.dart
+++ b/sdk/lib/chrome/dartium/chrome_dartium.dart
@@ -1,3 +1,10 @@
+/// Native wrappers for the Chrome Packaged App APIs.
+///
+/// These functions allow direct access to the Packaged App APIs, allowing
+/// Chrome Packaged Apps to be written using Dart.
+///
+/// For more information on these APIs, see the
+/// [Chrome APIs Documentation](http://developer.chrome.com/extensions/api_index.html)
 library chrome;
 
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index 88c1ada..4d37c77 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.dart
@@ -6,7 +6,6 @@
 
 import 'dart:_collection-dev';
 
-part 'arrays.dart';
 part 'collections.dart';
 part 'iterator.dart';
 part 'maps.dart';
diff --git a/sdk/lib/collection/collection_sources.gypi b/sdk/lib/collection/collection_sources.gypi
index 37d67be..4531699 100644
--- a/sdk/lib/collection/collection_sources.gypi
+++ b/sdk/lib/collection/collection_sources.gypi
@@ -5,7 +5,8 @@
 # This file contains all sources for the dart:collection library.
 {
   'sources': [
-    'arrays.dart',
+    'collection.dart',
+    # The above file needs to be first as it lists the parts below.
     'collections.dart',
     'hash_map.dart',
     'hash_set.dart',
diff --git a/sdk/lib/collection/collections.dart b/sdk/lib/collection/collections.dart
index b35a52f..09a0778 100644
--- a/sdk/lib/collection/collections.dart
+++ b/sdk/lib/collection/collections.dart
@@ -115,7 +115,7 @@
    * Removes elements matching [test] from [list].
    *
    * This is performed in two steps, to avoid exposing an inconsistent state
-   * to the [test] function. First the elements to ratain are found, and then
+   * to the [test] function. First the elements to retain are found, and then
    * the original list is updated to contain those elements.
    */
   static void removeMatchingList(List list, bool test(var element)) {
@@ -131,10 +131,10 @@
       }
     }
     if (retained.length == length) return;
+    list.length = retained.length;
     for (int i = 0; i < retained.length; i++) {
       list[i] = retained[i];
     }
-    list.length = retained.length;
   }
 
   /**
@@ -347,13 +347,46 @@
     return new SkipWhileIterable(iterable, test);
   }
 
-  static Iterable reversedList(List l) {
-    return new ReversedListIterable(l);
+  static Iterable reversedList(List list) {
+    return new ReversedListIterable(list);
   }
 
-  static void sortList(List l, int compare(a, b)) {
+  static void sortList(List list, int compare(a, b)) {
     if (compare == null) compare = Comparable.compare;
-    Sort.sort(l, compare);
+    Sort.sort(list, compare);
+  }
+
+  static int indexOfList(List list, var element, int start) {
+    return Arrays.indexOf(list, element, start, list.length);
+  }
+
+  static int lastIndexOfList(List list, var element, int start) {
+    if (start == null) start = list.length - 1;
+    return Arrays.lastIndexOf(list, element, start);
+  }
+
+  static void setRangeList(List list, int start, int length,
+                           List from, int startFrom) {
+    if (length == 0) return;
+
+    // TODO(floitsch): decide what to do with these checks. Currently copied
+    // since that was the old behavior of dart2js, and some co19 tests rely on
+    // it.
+    if (start is! int) throw new ArgumentError(start);
+    if (length is! int) throw new ArgumentError(length);
+    if (from is! List) throw new ArgumentError(from);
+    if (startFrom is! int) throw new ArgumentError(startFrom);
+    if (length < 0) throw new ArgumentError(length);
+    if (start < 0) throw new RangeError.value(start);
+    if (start + length > list.length) {
+      throw new RangeError.value(start + length);
+    }
+
+    Arrays.copy(from, startFrom, list, start, length);
+  }
+
+  static Map<int, dynamic> asMapList(List l) {
+    return new ListMapView(l);
   }
 }
 
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index 22fb38f..6908029 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -19,6 +19,8 @@
   // Iterable.
   Iterator<E> get iterator => new _HashTableKeyIterator<E>(_table);
 
+  int get length => _table._elementCount;
+
   bool get isEmpty => _table._elementCount == 0;
 
   bool contains(Object object) => _table._get(object) >= 0;
diff --git a/sdk/lib/collection/hash_table.dart b/sdk/lib/collection/hash_table.dart
index 7ab52cb..ececc47 100644
--- a/sdk/lib/collection/hash_table.dart
+++ b/sdk/lib/collection/hash_table.dart
@@ -74,7 +74,7 @@
    * Create an empty table.
    */
   List _createTable(int capacity) {
-    List table = new List.fixedLength(capacity * _entrySize);
+    List table = new List(capacity * _entrySize);
     return table;
   }
 
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index e72493a..7fc0653 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -30,6 +30,8 @@
     }
   }
 
+  int get length => _table._elementCount;
+
   bool get isEmpty => _table._elementCount == 0;
 
   bool contains(Object object) => _table._get(object) >= 0;
diff --git a/sdk/lib/collection/linked_hash_table.dart b/sdk/lib/collection/linked_hash_table.dart
index fbf6172..4b8b063 100644
--- a/sdk/lib/collection/linked_hash_table.dart
+++ b/sdk/lib/collection/linked_hash_table.dart
@@ -22,7 +22,7 @@
   int get _entrySize => 3;
 
   List _createTable(int capacity) {
-    List result = new List.fixedLength(capacity * _entrySize);
+    List result = new List(capacity * _entrySize);
     result[_HEAD_OFFSET] = _HEAD_MARKER;
     result[_HEAD_OFFSET + _NEXT_INDEX] = _HEAD_OFFSET;
     result[_HEAD_OFFSET + _PREV_INDEX] = _HEAD_OFFSET;
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 13ec536..975939a 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -350,7 +350,7 @@
       initialCapacity = _nextPowerOf2(initialCapacity);
     }
     assert(_isPowerOf2(initialCapacity));
-    _table = new List<E>.fixedLength(initialCapacity);
+    _table = new List<E>(initialCapacity);
   }
 
   /**
@@ -409,8 +409,13 @@
     return _table[(_head + index) & (_table.length - 1)];
   }
 
-  List<E> toList() {
-    List<E> list = new List<E>(length);
+  List<E> toList({ bool growable: true }) {
+    List<E> list;
+    if (growable) {
+      list = new List<E>()..length = length;
+    } else {
+      list = new List<E>(length);
+    }
     _writeToList(list);
     return list;
   }
@@ -629,7 +634,7 @@
    * Grow the table when full.
    */
   void _grow() {
-    List<E> newTable = new List<E>.fixedLength(_table.length * 2);
+    List<E> newTable = new List<E>(_table.length * 2);
     int split = _table.length - _head;
     newTable.setRange(0, split, _table, _head);
     newTable.setRange(split, _head, _table, 0);
@@ -656,7 +661,7 @@
   void _preGrow(int newElementCount) {
     assert(newElementCount >= length);
     int newCapacity = _nextPowerOf2(newElementCount);
-    List<E> newTable = new List<E>.fixedLength(newCapacity);
+    List<E> newTable = new List<E>(newCapacity);
     _tail = _writeToList(newTable);
     _table = newTable;
     _head = 0;
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 0345f8a..53707f1 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -5,40 +5,48 @@
 part of dart.collection;
 
 /**
- * A node in a splay tree. It holds the key, the value and the left
+ * A node in a splay tree. It holds the sorting key and the left
  * and right children in the tree.
  */
-class SplayTreeNode<K, V> {
+class _SplayTreeNode<K> {
   final K key;
-  V value;
-  SplayTreeNode<K, V> left;
-  SplayTreeNode<K, V> right;
+  _SplayTreeNode<K> left;
+  _SplayTreeNode<K> right;
 
-  SplayTreeNode(K this.key, V this.value);
+  _SplayTreeNode(K this.key);
 }
 
 /**
- * A splay tree is a self-balancing binary
- * search tree with the additional property that recently accessed
- * elements are quick to access again. It performs basic operations
- * such as insertion, look-up and removal in O(log(n)) amortized time.
+ * A node in a splay tree based map.
  *
- * This implementation is a Dart version of the JavaScript
- * implementation in the V8 project.
+ * A [_SplayTreeNode] that also contains a value
  */
-class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> {
+class _SplayTreeMapNode<K, V> extends _SplayTreeNode<K> {
+  V value;
+  _SplayTreeMapNode(K key, V this.value) : super(key);
+}
 
+/**
+ * A splay tree is a self-balancing binary search tree.
+ *
+ * It has the additional property that recently accessed elements
+ * are quick to access again.
+ * It performs basic operations such as insertion, look-up and
+ * removal, in O(log(n)) amortized time.
+ */
+abstract class _SplayTree<K> {
   // The root node of the splay tree. It will contain either the last
   // element inserted, or the last element looked up.
-  SplayTreeNode<K, V> _root;
+  _SplayTreeNode<K> _root;
 
   // The dummy node used when performing a splay on the tree. It is a
   // local field of the class to avoid allocating a node each time a
   // splay is performed.
-  SplayTreeNode<K, V> _dummy;
+  // TODO(lrn); Should it be a getter backed by a static instead?
+  _SplayTreeNode<K> _dummy = new _SplayTreeNode<K>(null);
 
   // Number of elements in the splay tree.
-  int _count;
+  int _count = 0;
 
   /**
    * Counter incremented whenever the keys in the map changes.
@@ -46,6 +54,7 @@
    * Used to detect concurrent modifications.
    */
   int _modificationCount = 0;
+
   /**
    * Counter incremented whenever the tree structure changes.
    *
@@ -54,9 +63,8 @@
    */
   int _splayCount = 0;
 
-  SplayTreeMap() :
-    _dummy = new SplayTreeNode<K, V>(null, null),
-    _count = 0;
+  /** Comparison used to compare keys. */
+  int _compare(K key1, K key2);
 
   /**
    * Perform the splay operation for the given key. Moves the node with
@@ -75,9 +83,9 @@
     // the L tree of the algorithm.  The left child of the dummy node
     // will hold the R tree of the algorithm.  Using a dummy node, left
     // and right will always be nodes and we avoid special cases.
-    SplayTreeNode<K, V> left = _dummy;
-    SplayTreeNode<K, V> right = _dummy;
-    SplayTreeNode<K, V> current = _root;
+    _SplayTreeNode<K> left = _dummy;
+    _SplayTreeNode<K> right = _dummy;
+    _SplayTreeNode<K> current = _root;
     int comp;
     while (true) {
       comp = current.key.compareTo(key);
@@ -86,7 +94,7 @@
         comp = current.left.key.compareTo(key);
         if (comp > 0) {
           // Rotate right.
-          SplayTreeNode<K, V> tmp = current.left;
+          _SplayTreeNode<K> tmp = current.left;
           current.left = tmp.right;
           tmp.right = current;
           current = tmp;
@@ -101,7 +109,7 @@
         comp = current.right.key.compareTo(key);
         if (comp < 0) {
           // Rotate left.
-          SplayTreeNode<K, V> tmp = current.right;
+          _SplayTreeNode<K> tmp = current.right;
           current.right = tmp.left;
           tmp.left = current;
           current = tmp;
@@ -128,26 +136,17 @@
     return comp;
   }
 
-  V operator [](K key) {
-    if (_root != null) {
-      int comp = _splay(key);
-      if (comp == 0) return _root.value;
-    }
-    return null;
-  }
-
-  V remove(K key) {
+  _SplayTreeNode _remove(K key) {
     if (_root == null) return null;
     int comp = _splay(key);
     if (comp != 0) return null;
-    V value = _root.value;
-
+    _SplayTreeNode result = _root;
     _count--;
     // assert(_count >= 0);
     if (_root.left == null) {
       _root = _root.right;
     } else {
-      SplayTreeNode<K, V> right = _root.right;
+      _SplayTreeNode<K> right = _root.right;
       _root = _root.left;
       // Splay to make sure that the new root has an empty right child.
       _splay(key);
@@ -156,24 +155,7 @@
       _root.right = right;
     }
     _modificationCount++;
-    return value;
-  }
-
-  void operator []=(K key, V value) {
-    if (_root == null) {
-      _count++;
-      _root = new SplayTreeNode(key, value);
-      _modificationCount++;
-      return;
-    }
-    // Splay on the key to move the last node on the search path for
-    // the key to the root of the tree.
-    int comp = _splay(key);
-    if (comp == 0) {
-      _root.value = value;
-      return;
-    }
-    _addNewRoot(key, value, comp);
+    return result;
   }
 
   /**
@@ -182,10 +164,14 @@
    * The [comp] value is the result of comparing the existing root's key
    * with key.
    */
-  void _addNewRoot(K key, V value, int comp) {
-    SplayTreeNode<K, V> node = new SplayTreeNode(key, value);
-    // assert(_count >= 0);
+  void _addNewRoot(_SplayTreeNode<K> node, int comp) {
     _count++;
+    _modificationCount++;
+    if (_root == null) {
+      _root = node;
+      return;
+    }
+    // assert(_count >= 0);
     if (comp < 0) {
       node.left = _root;
       node.right = _root.right;
@@ -196,20 +182,89 @@
       _root.left = null;
     }
     _root = node;
-    _modificationCount++;
   }
 
-  V putIfAbsent(K key, V ifAbsent()) {
-    if (_root == null) {
-      V value = ifAbsent();
-      if (_root != null) {
-        throw new ConcurrentModificationError(this);
-      }
-      _root = new SplayTreeNode(key, value);
-      _count++;
-      _modificationCount++;
-      return value;
+  _SplayTreeNode get _first {
+    if (_root == null) return null;
+    _SplayTreeNode<K> node = _root;
+    while (node.left != null) {
+      node = node.left;
     }
+    // Maybe implement a splay-method that can splay the minimum without
+    // performing comparisons.
+    _splay(node.key);
+    return node;
+  }
+
+  _SplayTreeNode get _last {
+    if (_root == null) return null;
+    _SplayTreeNode<K> node = _root;
+    while (node.right != null) {
+      node = node.right;
+    }
+    // Maybe implement a splay-method that can splay the minimum without
+    // performing comparisons.
+    _splay(node.key);
+    return node;
+  }
+
+  void _clear() {
+    _root = null;
+    _count = 0;
+    _modificationCount++;
+  }
+}
+
+/*
+ * A [Map] of objects that can be ordered relative to each other.
+ *
+ * The map is based on a self-balancing binary tree. It allows most operations
+ * in amortized logarithmic time.
+ *
+ * Keys of the map are compared using the `compare` function passed in
+ * the constructor. If that is omitted, the objects are assumed to be
+ * [Comparable], and are compared using their [Comparable.compareTo]
+ * method.
+ */
+class SplayTreeMap<K, V> extends _SplayTree<K> implements Map<K, V> {
+  // TODO(ngeoffray): Restore type when feature is implemented in dart2js
+  // checked mode. http://dartbug.com/7733  
+  Function /* Comparator<K> */_comparator;
+
+  SplayTreeMap([int compare(K key1, K key2)])
+      : _comparator = (compare == null) ? Comparable.compare : compare;
+
+  int _compare(K key1, K key2) => _comparator(key1, key2);
+
+  SplayTreeMap._internal();
+
+  V operator [](K key) {
+    if (_root != null) {
+      int comp = _splay(key);
+      if (comp == 0) return _root.value;
+    }
+    return null;
+  }
+
+  V remove(K key) {
+    _SplayTreeMapNode root = _remove(key);
+    if (root != null) return root.value;
+    return null;
+  }
+
+  void operator []=(K key, V value) {
+    // Splay on the key to move the last node on the search path for
+    // the key to the root of the tree.
+    int comp = _splay(key);
+    if (comp == 0) {
+      _root.value = value;
+      return;
+    }
+    _addNewRoot(new _SplayTreeMapNode(key, value), comp);
+  }
+
+
+  V putIfAbsent(K key, V ifAbsent()) {
     int comp = _splay(key);
     if (comp == 0) return _root.value;
     int modificationCount = _modificationCount;
@@ -223,7 +278,7 @@
       // Key is still not there, otherwise _modificationCount would be changed.
       assert(comp != 0);
     }
-    _addNewRoot(key, value, comp);
+    _addNewRoot(new _SplayTreeMapNode(key, value), comp);
     return value;
   }
 
@@ -234,10 +289,10 @@
   }
 
   void forEach(void f(K key, V value)) {
-    Iterator<SplayTreeNode<K, V>> nodes =
-        new _SplayTreeNodeIterator<K, V>(this);
+    Iterator<_SplayTreeNode<K>> nodes =
+        new _SplayTreeNodeIterator<K>(this);
     while (nodes.moveNext()) {
-      SplayTreeNode<K, V> node = nodes.current;
+      _SplayTreeMapNode<K, V> node = nodes.current;
       f(node.key, node.value);
     }
   }
@@ -247,8 +302,7 @@
   }
 
   void clear() {
-    _root = null;
-    _count = 0;
+    _clear();
   }
 
   bool containsKey(K key) {
@@ -257,7 +311,7 @@
 
   bool containsValue(V value) {
     bool found = false;
-    bool visit(SplayTreeNode node) {
+    bool visit(_SplayTreeNode node) {
       if (node == null) return false;
       if (node.value == value) return true;
       // TODO(lrn): Do we want to handle the case where node.value.operator==
@@ -267,9 +321,9 @@
     return visit(_root);
   }
 
-  Iterable<K> get keys => new _SplayTreeKeyIterable(this);
+  Iterable<K> get keys => new _SplayTreeKeyIterable<K>(this);
 
-  Iterable<V> get values => new _SplayTreeValueIterable(this);
+  Iterable<V> get values => new _SplayTreeValueIterable<K, V>(this);
 
   String toString() {
     return Maps.mapToString(this);
@@ -279,30 +333,16 @@
    * Get the first key in the map. Returns [null] if the map is empty.
    */
   K firstKey() {
-    if (_root == null) return null;
-    SplayTreeNode<K, V> node = _root;
-    while (node.left != null) {
-      node = node.left;
-    }
-    // Maybe implement a splay-method that can splay the minimum without
-    // performing comparisons.
-    _splay(node.key);
-    return node.key;
+    _SplayTreeNode node = _first;
+    return (node == null) ? null : node.key;
   }
 
   /**
    * Get the last key in the map. Returns [null] if the map is empty.
    */
   K lastKey() {
-    if (_root == null) return null;
-    SplayTreeNode<K, V> node = _root;
-    while (node.right != null) {
-      node = node.right;
-    }
-    // Maybe implement a splay-method that can splay the maximum without
-    // performing comparisons.
-    _splay(node.key);
-    return node.key;
+    _SplayTreeNode node = _last;
+    return (node == null) ? null : node.key;
   }
 
   /**
@@ -313,7 +353,7 @@
     if (_root == null) return null;
     int comp = _splay(key);
     if (comp < 0) return _root.key;
-    SplayTreeNode<K, V> node = _root.left;
+    _SplayTreeNode<K> node = _root.left;
     if (node == null) return null;
     while (node.right != null) {
       node = node.right;
@@ -329,7 +369,7 @@
     if (_root == null) return null;
     int comp = _splay(key);
     if (comp > 0) return _root.key;
-    SplayTreeNode<K, V> node = _root.right;
+    _SplayTreeNode<K> node = _root.right;
     if (node == null) return null;
     while (node.left != null) {
       node = node.left;
@@ -339,7 +379,7 @@
 }
 
 abstract class _SplayTreeIterator<T> implements Iterator<T> {
-  final SplayTreeMap _map;
+  final _SplayTree _tree;
   /**
    * Worklist of nodes to visit.
    *
@@ -348,33 +388,33 @@
    * and their right subtrees will visit the remainder of
    * the nodes of a full traversal.
    *
-   * Only valid as long as the original tree map isn't reordered.
+   * Only valid as long as the original tree isn't reordered.
    */
-  final List<SplayTreeNode> _workList = <SplayTreeNode>[];
+  final List<_SplayTreeNode> _workList = <_SplayTreeNode>[];
 
   /**
-   * Original modification counter of [_map].
+   * Original modification counter of [_tree].
    *
-   * Incremented on [_map] when a key is added or removed.
+   * Incremented on [_tree] when a key is added or removed.
    * If it changes, iteration is aborted.
    */
   final int _modificationCount;
 
   /**
-   * Count of splay operations on [_map] when [_workList] was built.
+   * Count of splay operations on [_tree] when [_workList] was built.
    *
-   * If the splay count on [_map] increases, [_workList] becomes invalid.
+   * If the splay count on [_tree] increases, [_workList] becomes invalid.
    */
   int _splayCount;
 
   /** Current node. */
-  SplayTreeNode _currentNode;
+  _SplayTreeNode _currentNode;
 
-  _SplayTreeIterator(SplayTreeMap map)
-      : _map = map,
-        _modificationCount = map._modificationCount,
-        _splayCount = map._splayCount {
-    _findLeftMostDescendent(map._root);
+  _SplayTreeIterator(_SplayTree tree)
+      : _tree = tree,
+        _modificationCount = tree._modificationCount,
+        _splayCount = tree._splayCount {
+    _findLeftMostDescendent(tree._root);
   }
 
   T get current {
@@ -382,7 +422,7 @@
     return _getValue(_currentNode);
   }
 
-  void _findLeftMostDescendent(SplayTreeNode node) {
+  void _findLeftMostDescendent(_SplayTreeNode node) {
     while (node != null) {
       _workList.add(node);
       node = node.left;
@@ -390,28 +430,28 @@
   }
 
   /**
-   * Called when the tree structure of the map has changed.
+   * Called when the tree structure of the tree has changed.
    *
    * This can be caused by a splay operation.
    * If the key-set changes, iteration is aborted before getting
    * here, so we know that the keys are the same as before, it's
    * only the tree that has been reordered.
    */
-  void _rebuildWorkList(SplayTreeNode currentNode) {
+  void _rebuildWorkList(_SplayTreeNode currentNode) {
     assert(!_workList.isEmpty);
     _workList.clear();
     if (currentNode == null) {
-      _findLeftMostDescendent(_map._root);
+      _findLeftMostDescendent(_tree._root);
     } else {
-      _map._splay(currentNode.key);
-      _findLeftMostDescendent(_map._root.right);
+      _tree._splay(currentNode.key);
+      _findLeftMostDescendent(_tree._root.right);
       assert(!_workList.isEmpty);
     }
   }
 
   bool moveNext() {
-    if (_modificationCount != _map._modificationCount) {
-      throw new ConcurrentModificationError(_map);
+    if (_modificationCount != _tree._modificationCount) {
+      throw new ConcurrentModificationError(_tree);
     }
     // Picks the next element in the worklist as current.
     // Updates the worklist with the left-most path of the current node's
@@ -422,7 +462,7 @@
       _currentNode = null;
       return false;
     }
-    if (_map._splayCount != _splayCount) {
+    if (_tree._splayCount != _splayCount) {
       _rebuildWorkList(_currentNode);
     }
     _currentNode = _workList.removeLast();
@@ -430,34 +470,37 @@
     return true;
   }
 
-  T _getValue(SplayTreeNode node);
+  T _getValue(_SplayTreeNode node);
 }
 
-
-class _SplayTreeKeyIterable<K, V> extends Iterable<K> {
-  SplayTreeMap<K, V> _map;
-  _SplayTreeKeyIterable(this._map);
-  Iterator<K> get iterator => new _SplayTreeKeyIterator<K, V>(_map);
+class _SplayTreeKeyIterable<K> extends Iterable<K> {
+  _SplayTree<K> _tree;
+  _SplayTreeKeyIterable(this._tree);
+  int get length => _tree._count;
+  bool get isEmpty => _tree._count == 0;
+  Iterator<K> get iterator => new _SplayTreeKeyIterator<K>(_tree);
 }
 
 class _SplayTreeValueIterable<K, V> extends Iterable<V> {
   SplayTreeMap<K, V> _map;
-  _SplayTreeValueIterable(this._map) ;
+  _SplayTreeValueIterable(this._map);
+  int get length => _map._count;
+  bool get isEmpty => _map._count == 0;
   Iterator<V> get iterator => new _SplayTreeValueIterator<K, V>(_map);
 }
 
-class _SplayTreeKeyIterator<K, V> extends _SplayTreeIterator<K> {
-  _SplayTreeKeyIterator(SplayTreeMap<K, V> map): super(map);
-  K _getValue(SplayTreeNode node) => node.key;
+class _SplayTreeKeyIterator<K> extends _SplayTreeIterator<K> {
+  _SplayTreeKeyIterator(_SplayTree<K> map): super(map);
+  K _getValue(_SplayTreeNode node) => node.key;
 }
 
 class _SplayTreeValueIterator<K, V> extends _SplayTreeIterator<V> {
   _SplayTreeValueIterator(SplayTreeMap<K, V> map): super(map);
-  V _getValue(SplayTreeNode node) => node.value;
+  V _getValue(_SplayTreeMapNode node) => node.value;
 }
 
-class _SplayTreeNodeIterator<K, V>
-    extends _SplayTreeIterator<SplayTreeNode<K, V>> {
-  _SplayTreeNodeIterator(SplayTreeMap<K, V> map): super(map);
-  SplayTreeNode<K, V> _getValue(SplayTreeNode node) => node;
+class _SplayTreeNodeIterator<K>
+    extends _SplayTreeIterator<_SplayTreeNode<K>> {
+  _SplayTreeNodeIterator(_SplayTree<K> map): super(map);
+  _SplayTreeNode<K> _getValue(_SplayTreeNode node) => node;
 }
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index 016d6c0..7163244 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.dart
@@ -32,6 +32,7 @@
 part "print.dart";
 part "regexp.dart";
 part "set.dart";
+part "stacktrace.dart";
 part "stopwatch.dart";
 part "string.dart";
 part "string_buffer.dart";
diff --git a/sdk/lib/core/corelib_sources.gypi b/sdk/lib/core/corelib_sources.gypi
index f85e349..e0e350b 100644
--- a/sdk/lib/core/corelib_sources.gypi
+++ b/sdk/lib/core/corelib_sources.gypi
@@ -4,6 +4,8 @@
 
 {
   'sources': [
+    'core.dart',
+    # The above file needs to be first as it lists the parts below.
     'bool.dart',
     'collection.dart',
     'comparable.dart',
@@ -29,6 +31,7 @@
     'print.dart',
     'regexp.dart',
     'set.dart',
+    'stacktrace.dart',
     'stopwatch.dart',
     'string.dart',
     'string_buffer.dart',
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index 9e7cdd8..a0cf1b6 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.dart
@@ -7,12 +7,23 @@
 /**
  * A [Duration] represents a time span. A duration can be negative.
  */
-class Duration implements Comparable {
+class Duration implements Comparable<Duration> {
+  static const int MICROSECONDS_PER_MILLISECOND = 1000;
   static const int MILLISECONDS_PER_SECOND = 1000;
   static const int SECONDS_PER_MINUTE = 60;
   static const int MINUTES_PER_HOUR = 60;
   static const int HOURS_PER_DAY = 24;
 
+  static const int MICROSECONDS_PER_SECOND =
+      MICROSECONDS_PER_MILLISECOND * MILLISECONDS_PER_SECOND;
+  static const int MICROSECONDS_PER_MINUTE =
+      MICROSECONDS_PER_SECOND * SECONDS_PER_MINUTE;
+  static const int MICROSECONDS_PER_HOUR =
+      MICROSECONDS_PER_MINUTE * MINUTES_PER_HOUR;
+  static const int MICROSECONDS_PER_DAY =
+      MICROSECONDS_PER_HOUR * HOURS_PER_DAY;
+
+
   static const int MILLISECONDS_PER_MINUTE =
       MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE;
   static const int MILLISECONDS_PER_HOUR =
@@ -28,9 +39,9 @@
   static const Duration ZERO = const Duration(seconds: 0);
 
   /**
-   * This [Duration] in milliseconds.
+   * This [Duration] in microseconds.
    */
-  final int inMilliseconds;
+  final int _duration;
 
   /**
    * The duration is the sum of all individual parts. This means that individual
@@ -44,18 +55,20 @@
                   int hours: 0,
                   int minutes: 0,
                   int seconds: 0,
-                  int milliseconds: 0})
-      : inMilliseconds = days * Duration.MILLISECONDS_PER_DAY +
-                         hours * Duration.MILLISECONDS_PER_HOUR +
-                         minutes * Duration.MILLISECONDS_PER_MINUTE +
-                         seconds * Duration.MILLISECONDS_PER_SECOND +
-                         milliseconds;
+                  int milliseconds: 0,
+                  int microseconds: 0})
+      : _duration = days * MICROSECONDS_PER_DAY +
+                    hours * MICROSECONDS_PER_HOUR +
+                    minutes * MICROSECONDS_PER_MINUTE +
+                    seconds * MICROSECONDS_PER_SECOND +
+                    milliseconds * MICROSECONDS_PER_MILLISECOND +
+                    microseconds;
 
   /**
    * Returns the sum of this [Duration] and [other]  as a new [Duration].
    */
   Duration operator +(Duration other) {
-    return new Duration(milliseconds: inMilliseconds + other.inMilliseconds);
+    return new Duration(microseconds: _duration + other._duration);
   }
 
   /**
@@ -63,7 +76,7 @@
    * [Duration].
    */
   Duration operator -(Duration other) {
-    return new Duration(milliseconds: inMilliseconds - other.inMilliseconds);
+    return new Duration(microseconds: _duration - other._duration);
   }
 
   /**
@@ -71,7 +84,7 @@
    * as a new [Duration].
    */
   Duration operator *(int factor) {
-    return new Duration(milliseconds: inMilliseconds * factor);
+    return new Duration(microseconds: _duration * factor);
   }
 
   /**
@@ -84,85 +97,87 @@
     // By doing the check here instead of relying on "~/" below we get the
     // exception even with dart2js.
     if (quotient == 0) throw new IntegerDivisionByZeroException();
-    return new Duration(milliseconds: inMilliseconds ~/ quotient);
+    return new Duration(microseconds: _duration ~/ quotient);
   }
 
-  bool operator <(Duration other) => this.inMilliseconds < other.inMilliseconds;
+  bool operator <(Duration other) => this._duration < other._duration;
 
-  bool operator >(Duration other) => this.inMilliseconds > other.inMilliseconds;
+  bool operator >(Duration other) => this._duration > other._duration;
 
-  bool operator <=(Duration other) =>
-      this.inMilliseconds <= other.inMilliseconds;
+  bool operator <=(Duration other) => this._duration <= other._duration;
 
-  bool operator >=(Duration other) =>
-      this.inMilliseconds >= other.inMilliseconds;
+  bool operator >=(Duration other) => this._duration >= other._duration;
 
   /**
    * This [Duration] in days. Incomplete days are discarded
    */
-  int get inDays {
-    return inMilliseconds ~/ Duration.MILLISECONDS_PER_DAY;
-  }
+  int get inDays => _duration ~/ Duration.MICROSECONDS_PER_DAY;
 
   /**
    * This [Duration] in hours. Incomplete hours are discarded.
+   *
    * The returned value can be greater than 23.
    */
-  int get inHours {
-    return inMilliseconds ~/ Duration.MILLISECONDS_PER_HOUR;
-  }
+  int get inHours => _duration ~/ Duration.MICROSECONDS_PER_HOUR;
 
   /**
    * This [Duration] in minutes. Incomplete minutes are discarded.
+   *
    * The returned value can be greater than 59.
    */
-  int get inMinutes {
-    return inMilliseconds ~/ Duration.MILLISECONDS_PER_MINUTE;
-  }
+  int get inMinutes => _duration ~/ Duration.MICROSECONDS_PER_MINUTE;
 
   /**
    * This [Duration] in seconds. Incomplete seconds are discarded.
+   *
    * The returned value can be greater than 59.
    */
-  int get inSeconds {
-    return inMilliseconds ~/ Duration.MILLISECONDS_PER_SECOND;
-  }
+  int get inSeconds => _duration ~/ Duration.MICROSECONDS_PER_SECOND;
+
+  /**
+   * This [Duration] in milliseconds. Incomplete milliseconds are discarded.
+   *
+   * The returned value can be greater than 999.
+   */
+  int get inMilliseconds => _duration ~/ Duration.MICROSECONDS_PER_MILLISECOND;
+
+  /**
+   * This [Duration] in microseconds.
+   */
+  int get inMicroseconds => _duration;
 
   bool operator ==(other) {
     if (other is !Duration) return false;
-    return inMilliseconds == other.inMilliseconds;
+    return _duration == other._duration;
   }
 
-  int get hashCode {
-    return inMilliseconds.hashCode;
-  }
+  int get hashCode => _duration.hashCode;
 
-  int compareTo(Duration other) {
-    return inMilliseconds.compareTo(other.inMilliseconds);
-  }
+  int compareTo(Duration other) => _duration.compareTo(other._duration);
 
   String toString() {
-    String threeDigits(int n) {
-      if (n >= 100) return "$n";
-      if (n > 10) return "0$n";
-      return "00$n";
+    String sixDigits(int n) {
+      if (n >= 100000) return "$n";
+      if (n >= 10000) return "0$n";
+      if (n >= 1000) return "00$n";
+      if (n >= 100) return "000$n";
+      if (n > 10) return "0000$n";
+      return "00000$n";
     }
     String twoDigits(int n) {
       if (n >= 10) return "$n";
       return "0$n";
     }
 
-    if (inMilliseconds < 0) {
+    if (inMicroseconds < 0) {
       Duration duration =
-          new Duration(milliseconds: -inMilliseconds);
+          new Duration(microseconds: -inMicroseconds);
       return "-$duration";
     }
-    String twoDigitMinutes =
-        twoDigits(inMinutes.remainder(Duration.MINUTES_PER_HOUR));
-    String twoDigitSeconds =
-        twoDigits(inSeconds.remainder(Duration.SECONDS_PER_MINUTE));
-    String threeDigitMs =
-        threeDigits(inMilliseconds.remainder(Duration.MILLISECONDS_PER_SECOND));
-    return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$threeDigitMs";
+    String twoDigitMinutes = twoDigits(inMinutes.remainder(MINUTES_PER_HOUR));
+    String twoDigitSeconds = twoDigits(inSeconds.remainder(SECONDS_PER_MINUTE));
+    String sixDigitUs =
+        sixDigits(inMicroseconds.remainder(MICROSECONDS_PER_SECOND));
+    return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$sixDigitUs";
   }
 }
diff --git a/sdk/lib/core/exceptions.dart b/sdk/lib/core/exceptions.dart
index 8ee78bc..800a652 100644
--- a/sdk/lib/core/exceptions.dart
+++ b/sdk/lib/core/exceptions.dart
@@ -53,16 +53,6 @@
   String toString() => "FormatException: $message";
 }
 
-/**
- * Deprecated. Replaced by [FormatException].
- */
-@deprecated
-class IllegalJSRegExpException extends FormatException {
-  IllegalJSRegExpException(String pattern, String errmsg)
-      : super("Illegal pattern: $pattern, $errmsg");
-}
-
-
 class IntegerDivisionByZeroException implements Exception {
   const IntegerDivisionByZeroException();
   String toString() => "IntegerDivisionByZeroException";
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 618eeb8..c6e09a1 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -156,7 +156,8 @@
     return false;
   }
 
-  List<E> toList() => new List<E>.from(this);
+  List<E> toList({ bool growable: true }) =>
+      new List<E>.from(this, growable: growable);
   Set<E> toSet() => new Set<E>.from(this);
 
   /**
@@ -430,7 +431,7 @@
 /**
  * An [Iterator] that allows moving backwards as well as forwards.
  */
-abstract class BiDirectionalIterator<T> extends Iterator<T> {
+abstract class BidirectionalIterator<T> extends Iterator<T> {
   /**
    * Move back to the previous element.
    *
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index ecb5535..560f08f 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -5,35 +5,103 @@
 part of dart.core;
 
 /**
- * A [List] is an indexable collection with a length. It can be of
- * fixed size or extendable.
+ * A [List] is an indexable collection with a length.
+ *
+ * A `List` implementation can be choose not to support all methods
+ * of the `List` interface.
+ *
+ * The most common list types are:
+ * * Fixed length list. It is an error to use operations that can change
+ *   the list's length.
+ * * Growable list. Full implementation of the interface.
+ * * Unmodifiable list. It is an error to use operations that can change
+ *   the list's length, or that can change the values of the list.
+ *   If an unmodifable list is backed by another modifiable data structure,
+ *   the values read from it may still change over time.
+ *
+ * Example:
+ *
+ *    var fixedLengthList = new List(5);
+ *    fixedLengthList.length = 0;  // throws.
+ *    fixedLengthList.add(499);  // throws
+ *    fixedLengthList[0] = 87;
+ *    var growableList = [1, 2];
+ *    growableList.length = 0;
+ *    growableList.add(499);
+ *    growableList[0] = 87;
+ *    var unmodifiableList = const [1, 2];
+ *    unmodifiableList.length = 0;  // throws.
+ *    unmodifiableList.add(499);  // throws
+ *    unmodifiableList[0] = 87;  // throws.
  */
 abstract class List<E> implements Collection<E> {
   /**
    * Creates a list of the given [length].
    *
-   * The length of the returned list is not fixed.
+   * The list is a fixed-length list if [length] is provided, and an empty
+   * growable list if [length] is omitted.
    */
-  external factory List([int length = 0]);
+  external factory List([int length]);
 
   /**
-   * Creates a fixed-sized list of the given [length] where each entry is
-   * filled with [fill].
+   * Creates a fixed-length list of the given [length] where each entry
+   * contains [fill].
    */
-  external factory List.fixedLength(int length, {E fill: null});
+  external factory List.filled(int length, E fill);
+
+  /**
+   * *Deprecated*: Use `new List(count)` instead.
+   */
+  factory List.fixedLength(int count, { E fill }) {
+    List<E> result = new List(count);
+    if (fill != null) {
+      for (int i = 0; i < count; i++) result[i] = fill;
+    }
+    return result;
+  }
 
   /**
    * Creates an list with the elements of [other]. The order in
    * the list will be the order provided by the iterator of [other].
    *
-   * The length of the returned list is not fixed.
+   * The returned list is growable if [growable] is true, otherwise it's
+   * a fixed length list.
    */
-  factory List.from(Iterable other) {
-    var list = new List<E>();
+  factory List.from(Iterable other, { bool growable: true }) {
+    List<E> list = new List<E>();
     for (E e in other) {
       list.add(e);
     }
-    return list;
+    if (growable) return list;
+    int length = list.length;
+    List<E> fixedList = new List<E>(length);
+    for (int i = 0; i < length; i++) {
+      fixedList[i] = list[i];
+    }
+    return fixedList;
+  }
+
+  /**
+   * Generate a `List` of elements.
+   *
+   * Generates a list of values, where the values are created by
+   * calling the [generator] function for each index in the range
+   * 0 .. [length] - 1.
+   *
+   * The created length's length is fixed unless [growable] is true.
+   */
+  factory List.generate(int length, E generator(int index),
+                       { bool growable: true }) {
+    List<E> result;
+    if (growable) {
+      result = <E>[]..length = length;
+    } else {
+      result = new List<E>(length);
+    }
+    for (int i = 0; i < length; i++) {
+      result[i] = generator(i);
+    }
+    return result;
   }
 
   /**
@@ -66,7 +134,10 @@
    * Adds [value] at the end of the list, extending the length by
    * one. Throws an [UnsupportedError] if the list is not
    * extendable.
+   *
+   * *Deprecated*: Use [add] instead.
    */
+  @deprecated
   void addLast(E value);
 
   /**
@@ -186,4 +257,12 @@
    * [start] is greater than the length of the list.
    */
   void insertRange(int start, int length, [E fill]);
+
+  /**
+   * Returns an unmodifiable [Map] view of `this`.
+   *
+   * It has the indices of this list as keys, and the corresponding elements
+   * as values.
+   */
+  Map<int, E> asMap();
 }
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index a85b0ff..c6db026 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.dart
@@ -94,6 +94,8 @@
   /**
    * Constructs a regular expression. The default implementation of a
    * [RegExp] sets [multiLine] to false and [caseSensitive] to true.
+   * Throws a [FormatException] if [pattern] is not a valid regular
+   * exression pattern.
    */
   external factory RegExp(String pattern, {bool multiLine: false,
                                            bool caseSensitive: true});
diff --git a/sdk/lib/core/stacktrace.dart b/sdk/lib/core/stacktrace.dart
new file mode 100644
index 0000000..a82a840
--- /dev/null
+++ b/sdk/lib/core/stacktrace.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.core;
+
+/**
+ * An interface implemented by all stack trace objects.
+ *
+ * A [StackTrace] is intended to convey information to the user about the call
+ * sequence that triggered an exception.
+ *
+ * These objects are created by the runtime, it is not possible to create
+ * them programmatically.
+ */
+abstract class StackTrace {
+  // Returns a String object that contains the full stack trace starting from
+  // the point where an exception has ocurred to the entry function which is
+  // typically 'main'.
+  // 'toString()' on a stack trace object essentially invokes this getter.
+  external String get fullStackTrace;
+
+  // Returns a String object that contains a stack trace starting from the
+  // point where an exception has ocurred to the point where the exception
+  // is caught.
+  external String get stackTrace;
+}
+
diff --git a/sdk/lib/core/stopwatch.dart b/sdk/lib/core/stopwatch.dart
index 5564801..9afc50b 100644
--- a/sdk/lib/core/stopwatch.dart
+++ b/sdk/lib/core/stopwatch.dart
@@ -20,16 +20,19 @@
    * Creates a [Stopwatch] in stopped state with a zero elapsed count.
    *
    * The following example shows how to start a [Stopwatch]
-   * right after allocation.
+   * immediately after allocation.
    *
    *     Stopwatch stopwatch = new Stopwatch()..start();
    */
   Stopwatch() : _start = null, _stop = null {}
 
   /**
-   * Starts the [Stopwatch]. The [elapsed] count is increasing monotonically.
-   * If the [Stopwatch] has been stopped, then calling start again restarts it
-   * without resetting the [elapsed] count.
+   * Starts the [Stopwatch].
+   *
+   * The [elapsed] count is increasing monotonically. If the [Stopwatch] has
+   * been stopped, then calling start again restarts it without resetting the
+   * [elapsed] count.
+   *
    * If the [Stopwatch] is currently running, then calling start does nothing.
    */
   void start() {
@@ -46,9 +49,11 @@
   }
 
   /**
-   * Stops the [Stopwatch]. The [elapsed] count stops increasing.
-   * If the [Stopwatch] is currently not running, then calling stop does
-   * nothing.
+   * Stops the [Stopwatch].
+   *
+   * The [elapsedTicks] count stops increasing after this call. If the
+   * [Stopwatch] is currently not running, then calling this method has no
+   * effect.
    */
   void stop() {
     if (!isRunning) return;
@@ -56,8 +61,9 @@
   }
 
   /**
-   * Resets the [elapsed] count to zero. This method does not stop or start
-   * the [Stopwatch].
+   * Resets the [elapsed] count to zero.
+   *
+   * This method does not stop or start the [Stopwatch].
    */
   void reset() {
     if (_start == null) return;
@@ -74,9 +80,12 @@
   /**
    * Returns the elapsed number of clock ticks since calling [start] while the
    * [Stopwatch] is running.
+   *
    * Returns the elapsed number of clock ticks between calling [start] and
    * calling [stop].
+   *
    * Returns 0 if the [Stopwatch] has never been started.
+   *
    * The elapsed number of clock ticks increases by [frequency] every second.
    */
   int get elapsedTicks {
@@ -87,6 +96,13 @@
   }
 
   /**
+   * Returns the [elapsedTicks] counter converted to a [Duration].
+   */
+  Duration get elapsed {
+    return new Duration(microseconds: elapsedMicroseconds);
+  }
+
+  /**
    * Returns the [elapsedTicks] counter converted to microseconds.
    */
   int get elapsedMicroseconds {
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index ba07bae..d780314 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -28,12 +28,6 @@
   external factory String.fromCharCodes(Iterable<int> charCodes);
 
   /**
-   * *Deprecated*. Use [String.fromCharCode] instead.
-   */
-  @deprecated
-  factory String.character(int charCode) => new String.fromCharCode(charCode);
-
-  /**
    * Allocates a new String for the specified [charCode].
    *
    * The new string contains a single code unit if the [charCode] can be
@@ -44,7 +38,7 @@
    * one half of a surrogate pair.
    */
   factory String.fromCharCode(int charCode) {
-    List<int> charCodes = new List<int>.fixedLength(1, fill: charCode);
+    List<int> charCodes = new List<int>.filled(1, charCode);
     return new String.fromCharCodes(charCodes);
   }
 
@@ -54,17 +48,19 @@
    * The returned string represents exactly one UTF-16 code unit which may be
    * half of a surrogate pair. For example the Unicode character for a
    * musical G-clef ("𝄞") with rune value 0x1D11E consists of a UTF-16 surrogate
-   * pair: `"\uDBFF\uDFFD"`. Using the index-operator on this string yields
+   * pair: `0xD834` and `0xDD1E`. Using the index-operator on this string yields
    * a String with half of a surrogate pair:
    *
-   *     var clef = "\uDBFF\uDFFD";
+   *     var clef = "\u{1D11E}";
    *     clef.length;  // => 2
    *     clef.runes.first == 0x1D11E;  // => true
    *     clef.runes.length;  // => 1
+   *     clef.codeUnitAt(0);  // => 0xD834
+   *     clef.codeUnitAt(1);  // => 0xDD1E
    *     // The following strings are halves of a UTF-16 surrogate pair and
    *     // thus invalid UTF-16 strings:
-   *     clef[0];  // => "\uDBFF"
-   *     clef[1];  // => "\uDFFD"
+   *     clef[0];  // => a string of length 1 with code-unit value 0xD834.
+   *     clef[1];  // => a string of length 1 with code-unit value 0xDD1E.
    *
    * This method is equivalent to
    * `new String.fromCharCode(this.codeUnitAt(index))`.
@@ -72,14 +68,6 @@
   String operator [](int index);
 
   /**
-   * Gets the scalar character code at the given [index].
-   *
-   * *This method is deprecated. Please use [codeUnitAt] instead.*
-   */
-  @deprecated
-  int charCodeAt(int index);
-
-  /**
    * Returns the 16-bit UTF-16 code unit at the given [index].
    */
   int codeUnitAt(int index);
@@ -219,30 +207,17 @@
    * are hence equivalent:
    *
    *     string.split("")
-   *     string.codeUnits.map((unit) => new String.character(unit))
+   *     string.codeUnits.map((unit) => new String.fromCharCode(unit))
    *
    * Unless it guaranteed that the string is in the basic multilingual plane
    * (meaning that each code unit represents a rune) it is often better to
    * map the runes instead:
    *
-   *     string.runes.map((rune) => new String.character(rune))
+   *     string.runes.map((rune) => new String.fromCharCode(rune))
    */
   List<String> split(Pattern pattern);
 
   /**
-   * Returns a list of the individual code-units converted to strings.
-   *
-   * *Deprecated*
-   * If you want to split on code-unit boundaries, use [split]. If you
-   * want to split on rune boundaries, use [runes] and map the result.
-   *
-   *     Iterable<String> characters =
-   *         string.runes.map((c) => new String.fromCharCode(c));
-   */
-  @deprecated
-  List<String> splitChars();
-
-  /**
    * Splits the string on the [pattern], then converts each part and each match.
    *
    * The pattern is used to split the string into parts and separating matches.
@@ -260,18 +235,9 @@
                        String onNonMatch(String nonMatch)});
 
   /**
-   * Returns a list of UTF-16 code units of this string.
-   *
-   * *This getter is deprecated. Use [codeUnits] instead.*
+   * Returns an unmodifiable list of the UTF-16 code units of this string.
    */
-  List<int> get charCodes;
-
-  /**
-   * Returns an iterable of the UTF-16 code units of this string.
-   */
-  // TODO(floitsch): should it return a list?
-  // TODO(floitsch): make it a bidirectional iterator.
-  Iterable<int> get codeUnits;
+  List<int> get codeUnits;
 
   /**
    * Returns an iterable of Unicode code-points of this string.
@@ -311,9 +277,9 @@
       throw new StateError("No elements.");
     }
     int length = string.length;
-    int code = string.charCodeAt(length - 1);
+    int code = string.codeUnitAt(length - 1);
     if (_isTrailSurrogate(code) && string.length > 1) {
-      int previousCode = string.charCodeAt(length - 2);
+      int previousCode = string.codeUnitAt(length - 2);
       if (_isLeadSurrogate(previousCode)) {
         return _combineSurrogatePair(previousCode, code);
       }
@@ -335,7 +301,7 @@
 }
 
 /** [Iterator] for reading Unicode code points out of a Dart string. */
-class RuneIterator implements BiDirectionalIterator<int> {
+class RuneIterator implements BidirectionalIterator<int> {
   /** String being iterated. */
   final String string;
   /** Position before the current code point. */
@@ -376,8 +342,8 @@
   /** Throw an error if the index is in the middle of a surrogate pair. */
   void _checkSplitSurrogate(int index) {
     if (index > 0 && index < string.length &&
-        _isLeadSurrogate(string.charCodeAt(index - 1)) &&
-        _isTrailSurrogate(string.charCodeAt(index))) {
+        _isLeadSurrogate(string.codeUnitAt(index - 1)) &&
+        _isTrailSurrogate(string.codeUnitAt(index))) {
       throw new ArgumentError("Index inside surrogate pair: $index");
     }
   }
@@ -455,10 +421,10 @@
       _currentCodePoint = null;
       return false;
     }
-    int codeUnit = string.charCodeAt(_position);
+    int codeUnit = string.codeUnitAt(_position);
     int nextPosition = _position + 1;
     if (_isLeadSurrogate(codeUnit) && nextPosition < string.length) {
-      int nextCodeUnit = string.charCodeAt(nextPosition);
+      int nextCodeUnit = string.codeUnitAt(nextPosition);
       if (_isTrailSurrogate(nextCodeUnit)) {
         _nextPosition = nextPosition + 1;
         _currentCodePoint = _combineSurrogatePair(codeUnit, nextCodeUnit);
@@ -477,9 +443,9 @@
       return false;
     }
     int position = _position - 1;
-    int codeUnit = string.charCodeAt(position);
+    int codeUnit = string.codeUnitAt(position);
     if (_isTrailSurrogate(codeUnit) && position > 0) {
-      int prevCodeUnit = string.charCodeAt(position - 1);
+      int prevCodeUnit = string.codeUnitAt(position - 1);
       if (_isLeadSurrogate(prevCodeUnit)) {
         _position = position - 1;
         _currentCodePoint = _combineSurrogatePair(prevCodeUnit, codeUnit);
@@ -491,16 +457,3 @@
     return true;
   }
 }
-
-/**
- * An [Iterable] of the UTF-16 code units of a [String] in index order.
- */
-class CodeUnits extends ListIterable<int> {
-  /** The string that this is the code units of. */
-  String string;
-
-  CodeUnits(this.string);
-
-  int get length => string.length;
-  int elementAt(int i) => string.codeUnitAt(i);
-}
diff --git a/sdk/lib/crypto/crypto_sources.gypi b/sdk/lib/crypto/crypto_sources.gypi
index b5a934a..de6faf9 100644
--- a/sdk/lib/crypto/crypto_sources.gypi
+++ b/sdk/lib/crypto/crypto_sources.gypi
@@ -3,12 +3,10 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file contains all sources for the dart:crypto library.
-#
-# TODO(ager): crypto_base.dart should be removed when the
-# VM can use the 'library' and 'part' directives for libraries.
-# At that point crypto.dart should be the only crypto library file.
 {
   'sources': [
+    'crypto.dart',
+    # The above file needs to be first as it lists the parts below.
     'crypto_base.dart',
     'crypto_utils.dart',
     'hash_utils.dart',
diff --git a/sdk/lib/crypto/hash_utils.dart b/sdk/lib/crypto/hash_utils.dart
index ed42140..d0b13cf 100644
--- a/sdk/lib/crypto/hash_utils.dart
+++ b/sdk/lib/crypto/hash_utils.dart
@@ -26,8 +26,8 @@
             int this._digestSizeInWords,
             bool this._bigEndianWords)
       : _pendingData = [] {
-    _currentChunk = new List.fixedLength(_chunkSizeInWords);
-    _h = new List.fixedLength(_digestSizeInWords);
+    _currentChunk = new List(_chunkSizeInWords);
+    _h = new List(_digestSizeInWords);
   }
 
   // Update the hasher with more data.
@@ -97,7 +97,7 @@
 
   // Convert a 32-bit word to four bytes.
   _wordToBytes(int word) {
-    List<int> bytes = new List.fixedLength(_BYTES_PER_WORD);
+    List<int> bytes = new List(_BYTES_PER_WORD);
     bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & _MASK_8;
     bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & _MASK_8;
     bytes[2] = (word >> (_bigEndianWords ? 8 : 16)) & _MASK_8;
diff --git a/sdk/lib/crypto/hmac.dart b/sdk/lib/crypto/hmac.dart
index 2dd3902..794746d 100644
--- a/sdk/lib/crypto/hmac.dart
+++ b/sdk/lib/crypto/hmac.dart
@@ -26,7 +26,7 @@
 
     // Zero-pad the key until its size is equal to the block size of the hash.
     if (_key.length < blockSize) {
-      var newKey = new List.fixedLength(blockSize);
+      var newKey = new List(blockSize);
       newKey.setRange(0, _key.length, _key);
       for (var i = _key.length; i < blockSize; i++) {
         newKey[i] = 0;
@@ -35,7 +35,7 @@
     }
 
     // Compute inner padding.
-    var padding = new List.fixedLength(blockSize);
+    var padding = new List(blockSize);
     for (var i = 0; i < blockSize; i++) {
       padding[i] = 0x36 ^ _key[i];
     }
diff --git a/sdk/lib/crypto/sha1.dart b/sdk/lib/crypto/sha1.dart
index af3d354..83e9217 100644
--- a/sdk/lib/crypto/sha1.dart
+++ b/sdk/lib/crypto/sha1.dart
@@ -7,7 +7,7 @@
 // The SHA1 hasher is used to compute an SHA1 message digest.
 class _SHA1 extends _HashBase implements SHA1 {
   // Construct a SHA1 hasher object.
-  _SHA1() : _w = new List.fixedLength(80), super(16, 5, true) {
+  _SHA1() : _w = new List(80), super(16, 5, true) {
     _h[0] = 0x67452301;
     _h[1] = 0xEFCDAB89;
     _h[2] = 0x98BADCFE;
diff --git a/sdk/lib/crypto/sha256.dart b/sdk/lib/crypto/sha256.dart
index 84dabf9..3df0ffd 100644
--- a/sdk/lib/crypto/sha256.dart
+++ b/sdk/lib/crypto/sha256.dart
@@ -7,7 +7,7 @@
 // The SHA256 hasher is used to compute an SHA256 message digest.
 class _SHA256 extends _HashBase implements SHA256 {
   // Construct a SHA256 hasher object.
-  _SHA256() : _w = new List.fixedLength(64), super(16, 8, true) {
+  _SHA256() : _w = new List(64), super(16, 8, true) {
     // Initial value of the hash parts. First 32 bits of the fractional parts
     // of the square roots of the first 8 prime numbers.
     _h[0] = 0x6a09e667;
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 7cf2fcc..32c8ac9 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -1,3 +1,4 @@
+/// The Dart HTML library.
 library dart.dom.html;
 
 import 'dart:async';
@@ -21,7 +22,6 @@
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
 // Auto-generated dart:html library.
 
-/// The Dart HTML library.
 
 // Not actually used, but imported since dart:html can generate these objects.
 
@@ -1478,7 +1478,7 @@
       '#.lineDashOffset || #.webkitLineDashOffset', this, this);
 
   @DomName('CanvasRenderingContext2D.lineDashOffset')
-  void set lineDashOffset(num value) => JS('void',
+  void set lineDashOffset(num value) => JS('void', 
       'typeof #.lineDashOffset != "undefined" ? #.lineDashOffset = # : '
       '#.webkitLineDashOffset = #', this, this, value, this, value);
 }
@@ -1622,7 +1622,7 @@
 
   static Console safeConsole = new Console();
 
-  bool get _isConsoleDefined => JS('bool', "typeof console != 'undefined'");
+  bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
 
   @DomName('Console.memory')
   MemoryInfo get memory => _isConsoleDefined ?
@@ -1712,6 +1712,10 @@
   @DocsEditable
   void clear(Object arg) native;
 
+  @DomName('Console.table')
+  @DocsEditable
+  void table(Object arg) native;
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -1810,8 +1814,14 @@
 
 @DocsEditable
 @DomName('Crypto')
+@SupportedBrowser(SupportedBrowser.CHROME)
+@SupportedBrowser(SupportedBrowser.SAFARI)
+@Experimental
 class Crypto native "*Crypto" {
 
+  /// Checks if this type is supported on the current platform.
+  static bool get supported => JS('bool', '!!(window.crypto && window.crypto.getRandomValues)');
+
   @DomName('Crypto.getRandomValues')
   @DocsEditable
   ArrayBufferView getRandomValues(ArrayBufferView array) native;
@@ -2377,11 +2387,14 @@
   }
 
   void setProperty(String propertyName, String value, [String priority]) {
-    JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
-    // Bug #2772, IE9 requires a poke to actually apply the value.
-    if (JS('bool', '!!#.setAttribute', this)) {
-      JS('void', '#.setAttribute(#, #)', this, propertyName, value);
-    }
+    // try/catch for IE9 which throws on unsupported values.
+    try {
+      JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
+      // Bug #2772, IE9 requires a poke to actually apply the value.
+      if (JS('bool', '!!#.setAttribute', this)) {
+        JS('void', '#.setAttribute(#, #)', this, propertyName, value);
+      }
+    } catch (e) {}
   }
 
   /**
@@ -6322,13 +6335,13 @@
   @DocsEditable
   String cookie;
 
-  WindowBase get window => _convertNativeToDart_Window(this._window);
+  WindowBase get window => _convertNativeToDart_Window(this._get_window);
   @JSName('defaultView')
   @DomName('Document.window')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _window;
+  final dynamic _get_window;
 
   @DomName('Document.documentElement')
   @DocsEditable
@@ -6842,7 +6855,7 @@
       final mutableMatches = $dom_getElementsByName(
           selectors.substring(7,selectors.length - 2));
       int len = mutableMatches.length;
-      final copyOfMatches = new List<Element>.fixedLength(len);
+      final copyOfMatches = new List<Element>(len);
       for (int i = 0; i < len; ++i) {
         copyOfMatches[i] = mutableMatches[i];
       }
@@ -6850,7 +6863,7 @@
     } else if (new RegExp("^[*a-zA-Z0-9]+\$").hasMatch(selectors)) {
       final mutableMatches = $dom_getElementsByTagName(selectors);
       int len = mutableMatches.length;
-      final copyOfMatches = new List<Element>.fixedLength(len);
+      final copyOfMatches = new List<Element>(len);
       for (int i = 0; i < len; ++i) {
         copyOfMatches[i] = mutableMatches[i];
       }
@@ -7140,7 +7153,9 @@
 
   bool any(bool f(DomMimeType element)) => IterableMixinWorkaround.any(this, f);
 
-  List<DomMimeType> toList() => new List<DomMimeType>.from(this);
+  List<DomMimeType> toList({ bool growable: true }) =>
+      new List<DomMimeType>.from(this, growable: growable);
+
   Set<DomMimeType> toSet() => new Set<DomMimeType>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -7394,7 +7409,9 @@
 
   bool any(bool f(DomPlugin element)) => IterableMixinWorkaround.any(this, f);
 
-  List<DomPlugin> toList() => new List<DomPlugin>.from(this);
+  List<DomPlugin> toList({ bool growable: true }) =>
+      new List<DomPlugin>.from(this, growable: growable);
+
   Set<DomPlugin> toSet() => new Set<DomPlugin>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -7755,7 +7772,9 @@
 
   bool any(bool f(String element)) => IterableMixinWorkaround.any(this, f);
 
-  List<String> toList() => new List<String>.from(this);
+  List<String> toList({ bool growable: true }) =>
+      new List<String>.from(this, growable: growable);
+
   Set<String> toSet() => new Set<String>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -7955,8 +7974,14 @@
     : _childElements = element.$dom_children,
       _element = element;
 
-  List<Element> toList() {
-    final output = new List<Element>.fixedLength(_childElements.length);
+  List<Element> toList({ bool growable: true }) {
+    List<Element> output;
+    if (growable) {
+      output = <Element>[];
+      output.length = _childElements.length;
+    } else {
+      output = new List<Element>(_childElements.length);
+    }
     for (int i = 0, len = _childElements.length; i < len; i++) {
       output[i] = _childElements[i];
     }
@@ -8252,7 +8277,8 @@
     return false;
   }
 
-  List<Element> toList() => new List<Element>.from(this);
+  List<Element> toList({ bool growable: true }) =>
+      new List<Element>.from(this, growable: growable);
   Set<Element> toSet() => new Set<Element>.from(this);
 
   Iterable<Element> take(int n) {
@@ -9155,6 +9181,11 @@
 
   static const int ALLOW_KEYBOARD_INPUT = 1;
 
+  @JSName('attributes')
+  @DomName('Element.attributes')
+  @DocsEditable
+  final _NamedNodeMap $dom_attributes;
+
   @JSName('childElementCount')
   @DomName('Element.childElementCount')
   @DocsEditable
@@ -10055,13 +10086,13 @@
   @DocsEditable
   final DataTransfer clipboardData;
 
-  EventTarget get currentTarget => _convertNativeToDart_EventTarget(this._currentTarget);
+  EventTarget get currentTarget => _convertNativeToDart_EventTarget(this._get_currentTarget);
   @JSName('currentTarget')
   @DomName('Event.currentTarget')
   @DocsEditable
   @Creates('Null')
   @Returns('EventTarget|=Object')
-  final dynamic _currentTarget;
+  final dynamic _get_currentTarget;
 
   @DomName('Event.defaultPrevented')
   @DocsEditable
@@ -10075,13 +10106,13 @@
   @DocsEditable
   bool returnValue;
 
-  EventTarget get target => _convertNativeToDart_EventTarget(this._target);
+  EventTarget get target => _convertNativeToDart_EventTarget(this._get_target);
   @JSName('target')
   @DomName('Event.target')
   @DocsEditable
   @Creates('Node')
   @Returns('EventTarget|=Object')
-  final dynamic _target;
+  final dynamic _get_target;
 
   @DomName('Event.timeStamp')
   @DocsEditable
@@ -10388,9 +10419,11 @@
 @DomName('File')
 class File extends Blob native "*File" {
 
+  DateTime get lastModifiedDate => _convertNativeToDart_DateTime(this._get_lastModifiedDate);
+  @JSName('lastModifiedDate')
   @DomName('File.lastModifiedDate')
   @DocsEditable
-  final Date lastModifiedDate;
+  final dynamic _get_lastModifiedDate;
 
   @DomName('File.name')
   @DocsEditable
@@ -10586,7 +10619,9 @@
 
   bool any(bool f(File element)) => IterableMixinWorkaround.any(this, f);
 
-  List<File> toList() => new List<File>.from(this);
+  List<File> toList({ bool growable: true }) =>
+      new List<File>.from(this, growable: growable);
+
   Set<File> toSet() => new Set<File>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -11096,7 +11131,7 @@
 
   @DomName('Float32Array.fromBuffer')
   @DocsEditable
-  factory Float32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Float32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createFloat32Array_fromBuffer(buffer, byteOffset, length);
 
   static const int BYTES_PER_ELEMENT = 4;
@@ -11143,7 +11178,9 @@
 
   bool any(bool f(num element)) => IterableMixinWorkaround.any(this, f);
 
-  List<num> toList() => new List<num>.from(this);
+  List<num> toList({ bool growable: true }) =>
+      new List<num>.from(this, growable: growable);
+
   Set<num> toSet() => new Set<num>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -11312,7 +11349,7 @@
 
   @DomName('Float64Array.fromBuffer')
   @DocsEditable
-  factory Float64Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Float64Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createFloat64Array_fromBuffer(buffer, byteOffset, length);
 
   static const int BYTES_PER_ELEMENT = 8;
@@ -11359,7 +11396,9 @@
 
   bool any(bool f(num element)) => IterableMixinWorkaround.any(this, f);
 
-  List<num> toList() => new List<num>.from(this);
+  List<num> toList({ bool growable: true }) =>
+      new List<num>.from(this, growable: growable);
+
   Set<num> toSet() => new Set<num>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -11516,11 +11555,11 @@
 @DomName('FocusEvent')
 class FocusEvent extends UIEvent native "*FocusEvent" {
 
-  EventTarget get relatedTarget => _convertNativeToDart_EventTarget(this._relatedTarget);
+  EventTarget get relatedTarget => _convertNativeToDart_EventTarget(this._get_relatedTarget);
   @JSName('relatedTarget')
   @DomName('FocusEvent.relatedTarget')
   @DocsEditable
-  final dynamic _relatedTarget;
+  final dynamic _get_relatedTarget;
 }
 // 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
@@ -11736,7 +11775,7 @@
   @JSName('clearWatch')
   @DomName('Geolocation.clearWatch')
   @DocsEditable
-  void $dom_clearWatch(int watchId) native;
+  void $dom_clearWatch(int watchID) native;
 
   @JSName('getCurrentPosition')
   @DomName('Geolocation.getCurrentPosition')
@@ -11904,13 +11943,13 @@
   @DocsEditable
   final int length;
 
-  dynamic get state => _convertNativeToDart_SerializedScriptValue(this._state);
+  dynamic get state => _convertNativeToDart_SerializedScriptValue(this._get_state);
   @JSName('state')
   @DomName('History.state')
   @DocsEditable
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  final dynamic _state;
+  final dynamic _get_state;
 
   @DomName('History.back')
   @DocsEditable
@@ -11994,7 +12033,9 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
+
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -12201,7 +12242,9 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
+
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -12370,17 +12413,6 @@
     document.$dom_body = value;
   }
 
-  /**
-   * Registers a custom Element subclass as an available HTML tag.
-   *
-   * Not yet implemented.
-   */
-  @Experimental
-  void register(String tagName, Type elementClass) {
-    // TODO: tagName validation
-    throw new Exception('Not yet implemented');
-  }
-
   @DomName('Document.caretRangeFromPoint')
   Range caretRangeFromPoint(int x, int y) {
     return document.$dom_caretRangeFromPoint(x, y);
@@ -13141,13 +13173,13 @@
   @DocsEditable
   factory IFrameElement() => document.$dom_createElement("iframe");
 
-  WindowBase get contentWindow => _convertNativeToDart_Window(this._contentWindow);
+  WindowBase get contentWindow => _convertNativeToDart_Window(this._get_contentWindow);
   @JSName('contentWindow')
   @DomName('HTMLIFrameElement.contentWindow')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _contentWindow;
+  final dynamic _get_contentWindow;
 
   @DomName('HTMLIFrameElement.height')
   @DocsEditable
@@ -13284,7 +13316,6 @@
     TelephoneInputElement,
     EmailInputElement,
     PasswordInputElement,
-    DateTimeInputElement,
     DateInputElement,
     MonthInputElement,
     WeekInputElement,
@@ -13487,9 +13518,18 @@
   @DocsEditable
   String value;
 
+  DateTime get valueAsDate => _convertNativeToDart_DateTime(this._get_valueAsDate);
+  @JSName('valueAsDate')
   @DomName('HTMLInputElement.valueAsDate')
   @DocsEditable
-  Date valueAsDate;
+  final dynamic _get_valueAsDate;
+
+  void set valueAsDate(DateTime value) {
+    this._set_valueAsDate = _convertDartToNative_DateTime(value);
+  }
+  void set _set_valueAsDate(/*dynamic*/ value) {
+    JS("void", "#.valueAsDate = #", this, value);
+  }
 
   @DomName('HTMLInputElement.valueAsNumber')
   @DocsEditable
@@ -13832,32 +13872,6 @@
 }
 
 /**
- * A date and time (year, month, day, hour, minute, second, fraction of a
- * second) with the time zone set to UTC.
- *
- * Use [supported] to check if this is supported on the current platform.
- */
-@SupportedBrowser(SupportedBrowser.CHROME, '25')
-@Experimental
-abstract class DateTimeInputElement implements RangeInputElementBase {
-  factory DateTimeInputElement() => new InputElement(type: 'datetime');
-
-  @DomName('HTMLInputElement.valueAsDate')
-  DateTime valueAsDate;
-
-  @DomName('HTMLInputElement.readOnly')
-  bool readOnly;
-
-  @DomName('HTMLInputElement.required')
-  bool required;
-
-  /// Returns true if this input type is supported on the current platform.
-  static bool get supported {
-    return (new InputElement(type: 'datetime')).type == 'datetime';
-  }
-}
-
-/**
  * A date (year, month, day) with no time zone.
  *
  * Use [supported] to check if this is supported on the current platform.
@@ -14173,7 +14187,7 @@
 
   @DomName('Int16Array.fromBuffer')
   @DocsEditable
-  factory Int16Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Int16Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createInt16Array_fromBuffer(buffer, byteOffset, length);
 
   static const int BYTES_PER_ELEMENT = 2;
@@ -14220,7 +14234,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -14389,7 +14405,7 @@
 
   @DomName('Int32Array.fromBuffer')
   @DocsEditable
-  factory Int32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Int32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createInt32Array_fromBuffer(buffer, byteOffset, length);
 
   static const int BYTES_PER_ELEMENT = 4;
@@ -14436,7 +14452,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -14605,7 +14623,7 @@
 
   @DomName('Int8Array.fromBuffer')
   @DocsEditable
-  factory Int8Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Int8Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createInt8Array_fromBuffer(buffer, byteOffset, length);
 
   static const int BYTES_PER_ELEMENT = 1;
@@ -14652,7 +14670,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -16263,13 +16283,13 @@
     return event;
   }
 
-  dynamic get data => convertNativeToDart_SerializedScriptValue(this._data);
+  dynamic get data => convertNativeToDart_SerializedScriptValue(this._get_data);
   @JSName('data')
   @DomName('MessageEvent.data')
   @DocsEditable
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  final dynamic _data;
+  final dynamic _get_data;
 
   @DomName('MessageEvent.lastEventId')
   @DocsEditable
@@ -16284,13 +16304,13 @@
   @Creates('=List')
   final List ports;
 
-  WindowBase get source => _convertNativeToDart_Window(this._source);
+  WindowBase get source => _convertNativeToDart_Window(this._get_source);
   @JSName('source')
   @DomName('MessageEvent.source')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _source;
+  final dynamic _get_source;
 
   @JSName('initMessageEvent')
   @DomName('MessageEvent.initMessageEvent')
@@ -16388,9 +16408,11 @@
 @DomName('Metadata')
 class Metadata native "*Metadata" {
 
+  DateTime get modificationTime => _convertNativeToDart_DateTime(this._get_modificationTime);
+  @JSName('modificationTime')
   @DomName('Metadata.modificationTime')
   @DocsEditable
-  final Date modificationTime;
+  final dynamic _get_modificationTime;
 
   @DomName('Metadata.size')
   @DocsEditable
@@ -16525,13 +16547,13 @@
   @DocsEditable
   final bool metaKey;
 
-  EventTarget get relatedTarget => _convertNativeToDart_EventTarget(this._relatedTarget);
+  EventTarget get relatedTarget => _convertNativeToDart_EventTarget(this._get_relatedTarget);
   @JSName('relatedTarget')
   @DomName('MouseEvent.relatedTarget')
   @DocsEditable
   @Creates('Node')
   @Returns('EventTarget|=Object')
-  final dynamic _relatedTarget;
+  final dynamic _get_relatedTarget;
 
   @DomName('MouseEvent.screenX')
   @DocsEditable
@@ -17074,7 +17096,13 @@
 
   void addAll(Iterable<Node> iterable) {
     if (iterable is _ChildNodeListLazy) {
-      iterable = new List.from(iterable);
+      if (iterable._this != _this) {
+        // Optimized route for copying between nodes.
+        for (var i = 0, len = iterable.length; i < len; ++i) {
+          _this.$dom_appendChild(iterable[0]);
+        }
+      }
+      return;
     }
     for (Node node in iterable) {
       _this.$dom_appendChild(node);
@@ -17161,7 +17189,8 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -17290,11 +17319,6 @@
   }
 
 
-  @JSName('attributes')
-  @DomName('Node.attributes')
-  @DocsEditable
-  final _NamedNodeMap $dom_attributes;
-
   @JSName('childNodes')
   @DomName('Node.childNodes')
   @DocsEditable
@@ -17550,7 +17574,9 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
+
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -18196,10 +18222,18 @@
 @DomName('PagePopupController')
 class PagePopupController native "*PagePopupController" {
 
+  @DomName('PagePopupController.closePopup')
+  @DocsEditable
+  void closePopup() native;
+
   @DomName('PagePopupController.formatMonth')
   @DocsEditable
   String formatMonth(int year, int zeroBaseMonth) native;
 
+  @DomName('PagePopupController.formatShortMonth')
+  @DocsEditable
+  String formatShortMonth(int year, int zeroBaseMonth) native;
+
   @DomName('PagePopupController.histogramEnumeration')
   @DocsEditable
   void histogramEnumeration(String name, int sample, int boundaryValue) native;
@@ -18208,6 +18242,10 @@
   @DocsEditable
   String localizeNumberString(String numberString) native;
 
+  @DomName('PagePopupController.setValue')
+  @DocsEditable
+  void setValue(String value) native;
+
   @DomName('PagePopupController.setValueAndClosePopup')
   @DocsEditable
   void setValueAndClosePopup(int numberValue, String stringValue) native;
@@ -18421,13 +18459,13 @@
 @SupportedBrowser(SupportedBrowser.SAFARI)
 class PopStateEvent extends Event native "*PopStateEvent" {
 
-  dynamic get state => convertNativeToDart_SerializedScriptValue(this._state);
+  dynamic get state => convertNativeToDart_SerializedScriptValue(this._get_state);
   @JSName('state')
   @DomName('PopStateEvent.state')
   @DocsEditable
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  final dynamic _state;
+  final dynamic _get_state;
 }
 // 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
@@ -19012,17 +19050,17 @@
   }
 
   /**
-   * Checks if Real Time Communication (RTC) APIs are supported and enabled on
+   * Checks if Real Time Communication (RTC) APIs are supported and enabled on 
    * the current platform.
    */
   static bool get supported {
     // Currently in Firefox some of the RTC elements are defined but throw an
-    // error unless the user has specifically enabled them in their
+    // error unless the user has specifically enabled them in their 
     // about:config. So we have to construct an element to actually test if RTC
     // is supported at at the given time.
     try {
       var c = new RtcPeerConnection({"iceServers": [ {"url":"stun:foo.com"}]});
-      return c is RtcPeerConnection;
+      return c is RtcPeerConnection; 
     } catch (_) {}
     return false;
   }
@@ -19309,9 +19347,11 @@
 @DomName('RTCStatsElement')
 class RtcStatsElement native "*RTCStatsElement" {
 
+  DateTime get timestamp => _convertNativeToDart_DateTime(this._get_timestamp);
+  @JSName('timestamp')
   @DomName('RTCStatsElement.timestamp')
   @DocsEditable
-  final Date timestamp;
+  final dynamic _get_timestamp;
 
   @DomName('RTCStatsElement.names')
   @DocsEditable
@@ -19888,7 +19928,9 @@
 
   bool any(bool f(SourceBuffer element)) => IterableMixinWorkaround.any(this, f);
 
-  List<SourceBuffer> toList() => new List<SourceBuffer>.from(this);
+  List<SourceBuffer> toList({ bool growable: true }) =>
+      new List<SourceBuffer>.from(this, growable: growable);
+
   Set<SourceBuffer> toSet() => new Set<SourceBuffer>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -20168,7 +20210,9 @@
 
   bool any(bool f(SpeechGrammar element)) => IterableMixinWorkaround.any(this, f);
 
-  List<SpeechGrammar> toList() => new List<SpeechGrammar>.from(this);
+  List<SpeechGrammar> toList({ bool growable: true }) =>
+      new List<SpeechGrammar>.from(this, growable: growable);
+
   Set<SpeechGrammar> toSet() => new Set<SpeechGrammar>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -20951,14 +20995,46 @@
   @DocsEditable
   int span;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 
+@DocsEditable
 @DomName('HTMLTableElement')
 class TableElement extends Element native "*HTMLTableElement" {
 
+  @DomName('HTMLTableElement.tBodies')
+  List<TableSectionElement> get tBodies =>
+  new _WrappedList<TableSectionElement>($dom_tBodies);
+
+  @DomName('HTMLTableElement.rows')
+  List<TableRowElement> get rows =>
+      new _WrappedList<TableRowElement>($dom_rows);
+
+  TableRowElement addRow() {
+    return insertRow(-1);
+  }
+
+  TableCaptionElement createCaption() => $dom_createCaption();
+  TableSectionElement createTBody() => $dom_createTBody();
+  TableSectionElement createTFoot() => $dom_createTFoot();
+  TableSectionElement createTHead() => $dom_createTHead();
+  TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+  TableSectionElement $dom_createTBody() {
+    if (JS('bool', '!!#.createTBody', this)) {
+      return this._createTBody();
+    }
+    var tbody = new Element.tag('tbody');
+    this.children.add(tbody);
+    return tbody;
+  }
+
+  @JSName('createTBody')
+  TableSectionElement _createTBody() native;
+
+
   @DomName('HTMLTableElement.HTMLTableElement')
   @DocsEditable
   factory TableElement() => document.$dom_createElement("table");
@@ -20971,13 +21047,15 @@
   @DocsEditable
   TableCaptionElement caption;
 
+  @JSName('rows')
   @DomName('HTMLTableElement.rows')
   @DocsEditable
-  final HtmlCollection rows;
+  final HtmlCollection $dom_rows;
 
+  @JSName('tBodies')
   @DomName('HTMLTableElement.tBodies')
   @DocsEditable
-  final HtmlCollection tBodies;
+  final HtmlCollection $dom_tBodies;
 
   @DomName('HTMLTableElement.tFoot')
   @DocsEditable
@@ -20987,17 +21065,20 @@
   @DocsEditable
   TableSectionElement tHead;
 
+  @JSName('createCaption')
   @DomName('HTMLTableElement.createCaption')
   @DocsEditable
-  Element createCaption() native;
+  Element $dom_createCaption() native;
 
+  @JSName('createTFoot')
   @DomName('HTMLTableElement.createTFoot')
   @DocsEditable
-  Element createTFoot() native;
+  Element $dom_createTFoot() native;
 
+  @JSName('createTHead')
   @DomName('HTMLTableElement.createTHead')
   @DocsEditable
-  Element createTHead() native;
+  Element $dom_createTHead() native;
 
   @DomName('HTMLTableElement.deleteCaption')
   @DocsEditable
@@ -21015,24 +21096,12 @@
   @DocsEditable
   void deleteTHead() native;
 
+  @JSName('insertRow')
   @DomName('HTMLTableElement.insertRow')
   @DocsEditable
-  Element insertRow(int index) native;
-
-
-  Element createTBody() {
-    if (JS('bool', '!!#.createTBody', this)) {
-      return this._createTBody();
-    }
-    var tbody = new Element.tag('tbody');
-    this.children.add(tbody);
-    return tbody;
-  }
-
-  @JSName('createTBody')
-  Element _createTBody() native;
+  Element $dom_insertRow(int index) native;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -21041,13 +21110,25 @@
 @DomName('HTMLTableRowElement')
 class TableRowElement extends Element native "*HTMLTableRowElement" {
 
+  @DomName('HTMLTableRowElement.cells')
+  List<TableCellElement> get cells =>
+      new _WrappedList<TableCellElement>($dom_cells);
+
+  TableCellElement addCell() {
+    return insertCell(-1);
+  }
+
+  TableCellElement insertCell(int index) => $dom_insertCell(index);
+
+
   @DomName('HTMLTableRowElement.HTMLTableRowElement')
   @DocsEditable
   factory TableRowElement() => document.$dom_createElement("tr");
 
+  @JSName('cells')
   @DomName('HTMLTableRowElement.cells')
   @DocsEditable
-  final HtmlCollection cells;
+  final HtmlCollection $dom_cells;
 
   @DomName('HTMLTableRowElement.rowIndex')
   @DocsEditable
@@ -21061,11 +21142,12 @@
   @DocsEditable
   void deleteCell(int index) native;
 
+  @JSName('insertCell')
   @DomName('HTMLTableRowElement.insertCell')
   @DocsEditable
-  Element insertCell(int index) native;
+  Element $dom_insertCell(int index) native;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -21075,16 +21157,29 @@
 class TableSectionElement extends Element native "*HTMLTableSectionElement" {
 
   @DomName('HTMLTableSectionElement.rows')
+  List<TableRowElement> get rows =>
+    new _WrappedList<TableRowElement>($dom_rows);
+
+  TableRowElement addRow() {
+    return insertRow(-1);
+  }
+
+  TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+
+  @JSName('rows')
+  @DomName('HTMLTableSectionElement.rows')
   @DocsEditable
-  final HtmlCollection rows;
+  final HtmlCollection $dom_rows;
 
   @DomName('HTMLTableSectionElement.deleteRow')
   @DocsEditable
   void deleteRow(int index) native;
 
+  @JSName('insertRow')
   @DomName('HTMLTableSectionElement.insertRow')
   @DocsEditable
-  Element insertRow(int index) native;
+  Element $dom_insertRow(int index) native;
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -21495,7 +21590,9 @@
 
   bool any(bool f(TextTrackCue element)) => IterableMixinWorkaround.any(this, f);
 
-  List<TextTrackCue> toList() => new List<TextTrackCue>.from(this);
+  List<TextTrackCue> toList({ bool growable: true }) =>
+      new List<TextTrackCue>.from(this, growable: growable);
+
   Set<TextTrackCue> toSet() => new Set<TextTrackCue>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -21700,7 +21797,9 @@
 
   bool any(bool f(TextTrack element)) => IterableMixinWorkaround.any(this, f);
 
-  List<TextTrack> toList() => new List<TextTrack>.from(this);
+  List<TextTrack> toList({ bool growable: true }) =>
+      new List<TextTrack>.from(this, growable: growable);
+
   Set<TextTrack> toSet() => new Set<TextTrack>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -21940,13 +22039,13 @@
   @DocsEditable
   final int screenY;
 
-  EventTarget get target => _convertNativeToDart_EventTarget(this._target);
+  EventTarget get target => _convertNativeToDart_EventTarget(this._get_target);
   @JSName('target')
   @DomName('Touch.target')
   @DocsEditable
   @Creates('Element|Document')
   @Returns('Element|Document')
-  final dynamic _target;
+  final dynamic _get_target;
 
   @JSName('webkitForce')
   @DomName('Touch.webkitForce')
@@ -22112,7 +22211,9 @@
 
   bool any(bool f(Touch element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Touch> toList() => new List<Touch>.from(this);
+  List<Touch> toList({ bool growable: true }) =>
+      new List<Touch>.from(this, growable: growable);
+
   Set<Touch> toSet() => new Set<Touch>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -22459,13 +22560,13 @@
   @DocsEditable
   final int pageY;
 
-  WindowBase get view => _convertNativeToDart_Window(this._view);
+  WindowBase get view => _convertNativeToDart_Window(this._get_view);
   @JSName('view')
   @DomName('UIEvent.view')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _view;
+  final dynamic _get_view;
 
   @DomName('UIEvent.which')
   @DocsEditable
@@ -22511,7 +22612,7 @@
 
   @DomName('Uint16Array.fromBuffer')
   @DocsEditable
-  factory Uint16Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Uint16Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createUint16Array_fromBuffer(buffer, byteOffset, length);
 
   static const int BYTES_PER_ELEMENT = 2;
@@ -22558,7 +22659,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -22727,7 +22830,7 @@
 
   @DomName('Uint32Array.fromBuffer')
   @DocsEditable
-  factory Uint32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Uint32Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createUint32Array_fromBuffer(buffer, byteOffset, length);
 
   static const int BYTES_PER_ELEMENT = 4;
@@ -22774,7 +22877,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -22943,7 +23048,7 @@
 
   @DomName('Uint8Array.fromBuffer')
   @DocsEditable
-  factory Uint8Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Uint8Array.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createUint8Array_fromBuffer(buffer, byteOffset, length);
 
   static const int BYTES_PER_ELEMENT = 1;
@@ -22990,7 +23095,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -23159,7 +23266,7 @@
 
   @DomName('Uint8ClampedArray.fromBuffer')
   @DocsEditable
-  factory Uint8ClampedArray.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) =>
+  factory Uint8ClampedArray.fromBuffer(ArrayBuffer buffer, [int byteOffset, int length]) => 
     _TypedArrayFactoryProvider.createUint8ClampedArray_fromBuffer(buffer, byteOffset, length);
 
   // Use implementation from Uint8Array.
@@ -23203,7 +23310,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -24573,6 +24682,8 @@
 
   @DomName('WebGLRenderingContext.getParameter')
   @DocsEditable
+  @Creates('Null|num|String|bool|=List|Float32Array|Int32Array|Uint32Array|WebGLFramebuffer|WebGLRenderbuffer|WebGLTexture')
+  @Returns('Null|num|String|bool|=List|Float32Array|Int32Array|Uint32Array|WebGLFramebuffer|WebGLRenderbuffer|WebGLTexture')
   Object getParameter(int pname) native;
 
   @DomName('WebGLRenderingContext.getProgramInfoLog')
@@ -25516,8 +25627,11 @@
    * registered under [name].
    */
   SendPortSync lookupPort(String name) {
-    var port =
-        json.parse(document.documentElement.attributes['dart-port:$name']);
+    var portStr = document.documentElement.attributes['dart-port:$name'];
+    if (portStr == null) {
+      return null;
+    }
+    var port = json.parse(portStr);
     return _deserialize(port);
   }
 
@@ -25844,13 +25958,13 @@
   @DocsEditable
   final bool offscreenBuffering;
 
-  WindowBase get opener => _convertNativeToDart_Window(this._opener);
+  WindowBase get opener => _convertNativeToDart_Window(this._get_opener);
   @JSName('opener')
   @DomName('DOMWindow.opener')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _opener;
+  final dynamic _get_opener;
 
   @DomName('DOMWindow.outerHeight')
   @DocsEditable
@@ -25872,13 +25986,13 @@
   @DocsEditable
   final int pageYOffset;
 
-  WindowBase get parent => _convertNativeToDart_Window(this._parent);
+  WindowBase get parent => _convertNativeToDart_Window(this._get_parent);
   @JSName('parent')
   @DomName('DOMWindow.parent')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _parent;
+  final dynamic _get_parent;
 
   @DomName('DOMWindow.performance')
   @DocsEditable
@@ -25923,13 +26037,13 @@
   @DocsEditable
   final BarInfo scrollbars;
 
-  WindowBase get self => _convertNativeToDart_Window(this._self);
+  WindowBase get self => _convertNativeToDart_Window(this._get_self);
   @JSName('self')
   @DomName('DOMWindow.self')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _self;
+  final dynamic _get_self;
 
   @DomName('DOMWindow.sessionStorage')
   @DocsEditable
@@ -25951,13 +26065,13 @@
   @DocsEditable
   final BarInfo toolbar;
 
-  WindowBase get top => _convertNativeToDart_Window(this._top);
+  WindowBase get top => _convertNativeToDart_Window(this._get_top);
   @JSName('top')
   @DomName('DOMWindow.top')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _top;
+  final dynamic _get_top;
 
   @JSName('webkitNotifications')
   @DomName('DOMWindow.webkitNotifications')
@@ -25975,13 +26089,13 @@
   @Experimental
   final StorageInfo storageInfo;
 
-  WindowBase get window => _convertNativeToDart_Window(this._window);
+  WindowBase get window => _convertNativeToDart_Window(this._get_window);
   @JSName('window')
   @DomName('DOMWindow.window')
   @DocsEditable
   @Creates('Window|=Object')
   @Returns('Window|=Object')
-  final dynamic _window;
+  final dynamic _get_window;
 
   @JSName('addEventListener')
   @DomName('DOMWindow.addEventListener')
@@ -26070,26 +26184,23 @@
   @DomName('DOMWindow.postMessage')
   @DocsEditable
   void postMessage(/*SerializedScriptValue*/ message, String targetOrigin, [List messagePorts]) {
-    if (?message && !?messagePorts) {
+    if (?messagePorts) {
       var message_1 = convertDartToNative_SerializedScriptValue(message);
-      _postMessage_1(message_1, targetOrigin);
+      _postMessage_1(message_1, targetOrigin, messagePorts);
       return;
     }
-    if (?message) {
-      var message_2 = convertDartToNative_SerializedScriptValue(message);
-      _postMessage_2(message_2, targetOrigin, messagePorts);
-      return;
-    }
-    throw new ArgumentError("Incorrect number or type of arguments");
+    var message_2 = convertDartToNative_SerializedScriptValue(message);
+    _postMessage_2(message_2, targetOrigin);
+    return;
   }
   @JSName('postMessage')
   @DomName('DOMWindow.postMessage')
   @DocsEditable
-  void _postMessage_1(message, targetOrigin) native;
+  void _postMessage_1(message, targetOrigin, List messagePorts) native;
   @JSName('postMessage')
   @DomName('DOMWindow.postMessage')
   @DocsEditable
-  void _postMessage_2(message, targetOrigin, List messagePorts) native;
+  void _postMessage_2(message, targetOrigin) native;
 
   @DomName('DOMWindow.print')
   @DocsEditable
@@ -26925,7 +27036,9 @@
 
   bool any(bool f(ClientRect element)) => IterableMixinWorkaround.any(this, f);
 
-  List<ClientRect> toList() => new List<ClientRect>.from(this);
+  List<ClientRect> toList({ bool growable: true }) =>
+      new List<ClientRect>.from(this, growable: growable);
+
   Set<ClientRect> toSet() => new Set<ClientRect>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -27122,7 +27235,9 @@
 
   bool any(bool f(CssRule element)) => IterableMixinWorkaround.any(this, f);
 
-  List<CssRule> toList() => new List<CssRule>.from(this);
+  List<CssRule> toList({ bool growable: true }) =>
+      new List<CssRule>.from(this, growable: growable);
+
   Set<CssRule> toSet() => new Set<CssRule>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -27319,7 +27434,9 @@
 
   bool any(bool f(CssValue element)) => IterableMixinWorkaround.any(this, f);
 
-  List<CssValue> toList() => new List<CssValue>.from(this);
+  List<CssValue> toList({ bool growable: true }) =>
+      new List<CssValue>.from(this, growable: growable);
+
   Set<CssValue> toSet() => new Set<CssValue>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -27516,7 +27633,9 @@
 
   bool any(bool f(Entry element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Entry> toList() => new List<Entry>.from(this);
+  List<Entry> toList({ bool growable: true }) =>
+      new List<Entry>.from(this, growable: growable);
+
   Set<Entry> toSet() => new Set<Entry>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -27713,7 +27832,9 @@
 
   bool any(bool f(EntrySync element)) => IterableMixinWorkaround.any(this, f);
 
-  List<EntrySync> toList() => new List<EntrySync>.from(this);
+  List<EntrySync> toList({ bool growable: true }) =>
+      new List<EntrySync>.from(this, growable: growable);
+
   Set<EntrySync> toSet() => new Set<EntrySync>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -27910,7 +28031,9 @@
 
   bool any(bool f(Gamepad element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Gamepad> toList() => new List<Gamepad>.from(this);
+  List<Gamepad> toList({ bool growable: true }) =>
+      new List<Gamepad>.from(this, growable: growable);
+
   Set<Gamepad> toSet() => new Set<Gamepad>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -28170,7 +28293,9 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
+
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -28391,7 +28516,9 @@
 
   bool any(bool f(SpeechInputResult element)) => IterableMixinWorkaround.any(this, f);
 
-  List<SpeechInputResult> toList() => new List<SpeechInputResult>.from(this);
+  List<SpeechInputResult> toList({ bool growable: true }) =>
+      new List<SpeechInputResult>.from(this, growable: growable);
+
   Set<SpeechInputResult> toSet() => new Set<SpeechInputResult>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -28588,7 +28715,9 @@
 
   bool any(bool f(SpeechRecognitionResult element)) => IterableMixinWorkaround.any(this, f);
 
-  List<SpeechRecognitionResult> toList() => new List<SpeechRecognitionResult>.from(this);
+  List<SpeechRecognitionResult> toList({ bool growable: true }) =>
+      new List<SpeechRecognitionResult>.from(this, growable: growable);
+
   Set<SpeechRecognitionResult> toSet() => new Set<SpeechRecognitionResult>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -28785,7 +28914,9 @@
 
   bool any(bool f(StyleSheet element)) => IterableMixinWorkaround.any(this, f);
 
-  List<StyleSheet> toList() => new List<StyleSheet>.from(this);
+  List<StyleSheet> toList({ bool growable: true }) =>
+      new List<StyleSheet>.from(this, growable: growable);
+
   Set<StyleSheet> toSet() => new Set<StyleSheet>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -29415,7 +29546,8 @@
   String get first => readClasses().first;
   String get last => readClasses().last;
   String get single => readClasses().single;
-  List<String> toList() => readClasses().toList();
+  List<String> toList({ bool growable: true }) =>
+      readClasses().toList(growable: growable);
   Set<String> toSet() => readClasses().toSet();
   String min([int compare(String a, String b)]) =>
       readClasses().min(compare);
@@ -29714,7 +29846,7 @@
   EventTarget _target;
 
   // The distance to shift from upper case alphabet Roman letters to lower case.
-  final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
+  final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
 
   StreamSubscription _keyUpSubscription, _keyDownSubscription,
       _keyPressSubscription;
@@ -29849,8 +29981,8 @@
       if (prevEvent._shadowCharCode == event.charCode) {
         return prevEvent.keyCode;
       }
-      if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".charCodes[0]
-          && event.charCode <= "Z".charCodes[0] && event.charCode +
+      if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".codeUnits[0]
+          && event.charCode <= "Z".codeUnits[0] && event.charCode +
           _ROMAN_ALPHABET_OFFSET == prevEvent._shadowCharCode) {
         return prevEvent.keyCode;
       }
@@ -30093,9 +30225,9 @@
 
 
 /**
- * Defines the keycode values for keys that are returned by
+ * Defines the keycode values for keys that are returned by 
  * KeyboardEvent.keyCode.
- *
+ * 
  * Important note: There is substantial divergence in how different browsers
  * handle keycodes and their variants in different locales/keyboard layouts. We
  * provide these constants to help make code processing keys more readable.
@@ -30103,7 +30235,7 @@
 abstract class KeyCode {
   // These constant names were borrowed from Closure's Keycode enumeration
   // class.
-  // http://closure-library.googlecode.com/svn/docs/closure_goog_events_keycodes.js.source.html
+  // http://closure-library.googlecode.com/svn/docs/closure_goog_events_keycodes.js.source.html  
   static const int WIN_KEY_FF_LINUX = 0;
   static const int MAC_ENTER = 3;
   static const int BACKSPACE = 8;
@@ -30298,12 +30430,12 @@
         (keyCode >= A && keyCode <= Z)) {
       return true;
     }
-
+ 
     // Safari sends zero key code for non-latin characters.
     if (_Device.isWebKit && keyCode == 0) {
       return true;
     }
-
+ 
     return (keyCode == SPACE || keyCode == QUESTION_MARK || keyCode == NUM_PLUS
         || keyCode == NUM_MINUS || keyCode == NUM_PERIOD ||
         keyCode == NUM_DIVISION || keyCode == SEMICOLON ||
@@ -31410,7 +31542,7 @@
 
   _serializeList(List list) {
     int len = list.length;
-    var result = new List.fixedLength(len);
+    var result = new List(len);
     for (int i = 0; i < len; i++) {
       result[i] = _dispatch(list[i]);
     }
@@ -31490,6 +31622,147 @@
   }
 }
 
+// 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.
+
+
+/**
+ * A list which just wraps another list, for either intercepting list calls or
+ * retyping the list (for example, from List<A> to List<B> where B extends A).
+ */
+class _WrappedList<E> implements List<E> {
+  final List _list;
+
+  _WrappedList(this._list);
+
+  // Iterable APIs
+
+  Iterator<E> get iterator => new _WrappedIterator(_list.iterator);
+
+  Iterable map(f(E element)) => _list.map(f);
+
+  Iterable<E> where(bool f(E element)) => _list.where(f);
+
+  Iterable expand(Iterable f(E element)) => _list.expand(f);
+
+  bool contains(E element) => _list.contains(element);
+
+  void forEach(void f(E element)) { _list.forEach(f); }
+
+  dynamic reduce(initialValue, combine(previousValue, E element)) =>
+      _list.reduce(initialValue, combine);
+
+  bool every(bool f(E element)) => _list.every(f);
+
+  String join([String separator]) => _list.join(separator);
+
+  bool any(bool f(E element)) => _list.any(f);
+
+  List<E> toList({ bool growable: true }) =>
+      new List.from(_list, growable: growable);
+
+  Set<E> toSet() => _list.toSet();
+
+  int get length => _list.length;
+
+  E min([int compare(E a, E b)]) => _list.min(compare);
+
+  E max([int compare(E a, E b)]) => _list.max(compare);
+
+  bool get isEmpty => _list.isEmpty;
+
+  Iterable<E> take(int n) => _list.take(n);
+
+  Iterable<E> takeWhile(bool test(E value)) => _list.takeWhile(test);
+
+  Iterable<E> skip(int n) => _list.skip(n);
+
+  Iterable<E> skipWhile(bool test(E value)) => _list.skipWhile(test);
+
+  E get first => _list.first;
+
+  E get last => _list.last;
+
+  E get single => _list.single;
+
+  E firstMatching(bool test(E value), { E orElse() }) =>
+      _list.firstMatching(test, orElse: orElse);
+
+  E lastMatching(bool test(E value), {E orElse()}) =>
+      _list.lastMatching(test, orElse: orElse);
+
+  E singleMatching(bool test(E value)) => _list.singleMatching(test);
+
+  E elementAt(int index) => _list.elementAt(index);
+
+  // Collection APIs
+
+  void add(E element) { _list.add(element); }
+
+  void addAll(Iterable<E> elements) { _list.addAll(elements); }
+
+  void remove(Object element) { _list.remove(element); }
+
+  void removeAll(Iterable elements) { _list.removeAll(elements); }
+
+  void retainAll(Iterable elements) { _list.retainAll(elements); }
+
+  void removeMatching(bool test(E element)) { _list.removeMatching(test); }
+
+  void retainMatching(bool test(E element)) { _list.retainMatching(test); }
+
+  void clear() { _list.clear(); }
+
+  // List APIs
+
+  E operator [](int index) => _list[index];
+
+  void operator []=(int index, E value) { _list[index] = value; }
+
+  void set length(int newLength) { _list.length = newLength; }
+
+  void addLast(E value) { _list.addLast(value); }
+
+  Iterable<E> get reversed => _list.reversed;
+
+  void sort([int compare(E a, E b)]) { _list.sort(compare); }
+
+  int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+
+  int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+
+  E removeAt(int index) => _list.removeAt(index);
+
+  E removeLast() => _list.removeLast();
+
+  List<E> getRange(int start, int length) => _list.getRange(start, length);
+
+  void setRange(int start, int length, List<E> from, [int startFrom]) {
+    _list.setRange(start, length, from, startFrom);
+  }
+
+  void removeRange(int start, int length) { _list.removeRange(start, length); }
+
+  void insertRange(int start, int length, [E fill]) {
+    _list.insertRange(start, length, fill);
+  }
+}
+
+/**
+ * Iterator wrapper for _WrappedList.
+ */
+class _WrappedIterator<E> implements Iterator<E> {
+  Iterator _iterator;
+
+  _WrappedIterator(this._iterator);
+
+  bool moveNext() {
+    return _iterator.moveNext();
+  }
+
+  E get current => _iterator.current;
+}
 // 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.
@@ -31553,6 +31826,15 @@
 // window as a parameter.
 
 
+DateTime _convertNativeToDart_DateTime(date) {
+  var millisSinceEpoch = JS('int', '#.getTime()', date);
+  return new DateTime.fromMillisecondsSinceEpoch(millisSinceEpoch, isUtc: true);
+}
+
+_convertDartToNative_DateTime(DateTime date) {
+  return JS('', 'new Date(#)', date.millisecondsSinceEpoch);
+}
+
 WindowBase _convertNativeToDart_Window(win) {
   return _DOMWindowCrossFrame._createSafe(win);
 }
@@ -32091,7 +32373,7 @@
   final int _length;  // Cache array length for faster access.
   int _position;
   T _current;
-
+  
   FixedSizeListIterator(List<T> array)
       : _array = array,
         _position = -1,
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 0dc02f2..870eaf7 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -1,3 +1,4 @@
+/// The Dart HTML library.
 library dart.dom.html;
 
 import 'dart:async';
@@ -2103,6 +2104,10 @@
   @DocsEditable
   void profileEnd(String title) native "Console_profileEnd_Callback";
 
+  @DomName('Console.table')
+  @DocsEditable
+  void table(Object arg) native "Console_table_Callback";
+
   @DomName('Console.time')
   @DocsEditable
   void time(String title) native "Console_time_Callback";
@@ -2241,9 +2246,15 @@
 
 @DocsEditable
 @DomName('Crypto')
+@SupportedBrowser(SupportedBrowser.CHROME)
+@SupportedBrowser(SupportedBrowser.SAFARI)
+@Experimental
 class Crypto extends NativeFieldWrapperClass1 {
   Crypto.internal();
 
+  /// Checks if this type is supported on the current platform.
+  static bool get supported => true;
+
   @DomName('Crypto.getRandomValues')
   @DocsEditable
   ArrayBufferView getRandomValues(ArrayBufferView array) native "Crypto_getRandomValues_Callback";
@@ -7528,7 +7539,7 @@
       final mutableMatches = $dom_getElementsByName(
           selectors.substring(7,selectors.length - 2));
       int len = mutableMatches.length;
-      final copyOfMatches = new List<Element>.fixedLength(len);
+      final copyOfMatches = new List<Element>(len);
       for (int i = 0; i < len; ++i) {
         copyOfMatches[i] = mutableMatches[i];
       }
@@ -7536,7 +7547,7 @@
     } else if (new RegExp("^[*a-zA-Z0-9]+\$").hasMatch(selectors)) {
       final mutableMatches = $dom_getElementsByTagName(selectors);
       int len = mutableMatches.length;
-      final copyOfMatches = new List<Element>.fixedLength(len);
+      final copyOfMatches = new List<Element>(len);
       for (int i = 0; i < len; ++i) {
         copyOfMatches[i] = mutableMatches[i];
       }
@@ -7832,7 +7843,9 @@
 
   bool any(bool f(DomMimeType element)) => IterableMixinWorkaround.any(this, f);
 
-  List<DomMimeType> toList() => new List<DomMimeType>.from(this);
+  List<DomMimeType> toList({ bool growable: true }) =>
+      new List<DomMimeType>.from(this, growable: growable);
+
   Set<DomMimeType> toSet() => new Set<DomMimeType>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -8100,7 +8113,9 @@
 
   bool any(bool f(DomPlugin element)) => IterableMixinWorkaround.any(this, f);
 
-  List<DomPlugin> toList() => new List<DomPlugin>.from(this);
+  List<DomPlugin> toList({ bool growable: true }) =>
+      new List<DomPlugin>.from(this, growable: growable);
+
   Set<DomPlugin> toSet() => new Set<DomPlugin>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -8486,7 +8501,9 @@
 
   bool any(bool f(String element)) => IterableMixinWorkaround.any(this, f);
 
-  List<String> toList() => new List<String>.from(this);
+  List<String> toList({ bool growable: true }) =>
+      new List<String>.from(this, growable: growable);
+
   Set<String> toSet() => new Set<String>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -8707,8 +8724,14 @@
     : _childElements = element.$dom_children,
       _element = element;
 
-  List<Element> toList() {
-    final output = new List<Element>.fixedLength(_childElements.length);
+  List<Element> toList({ bool growable: true }) {
+    List<Element> output;
+    if (growable) {
+      output = <Element>[];
+      output.length = _childElements.length;
+    } else {
+      output = new List<Element>(_childElements.length);
+    }
     for (int i = 0, len = _childElements.length; i < len; i++) {
       output[i] = _childElements[i];
     }
@@ -9004,7 +9027,8 @@
     return false;
   }
 
-  List<Element> toList() => new List<Element>.from(this);
+  List<Element> toList({ bool growable: true }) =>
+      new List<Element>.from(this, growable: growable);
   Set<Element> toSet() => new Set<Element>.from(this);
 
   Iterable<Element> take(int n) {
@@ -9739,6 +9763,10 @@
 
   static const int ALLOW_KEYBOARD_INPUT = 1;
 
+  @DomName('Element.attributes')
+  @DocsEditable
+  _NamedNodeMap get $dom_attributes native "Element_attributes_Getter";
+
   @DomName('Element.childElementCount')
   @DocsEditable
   int get $dom_childElementCount native "Element_childElementCount_Getter";
@@ -11098,7 +11126,7 @@
 
   @DomName('File.lastModifiedDate')
   @DocsEditable
-  Date get lastModifiedDate native "File_lastModifiedDate_Getter";
+  DateTime get lastModifiedDate native "File_lastModifiedDate_Getter";
 
   @DomName('File.name')
   @DocsEditable
@@ -11313,7 +11341,9 @@
 
   bool any(bool f(File element)) => IterableMixinWorkaround.any(this, f);
 
-  List<File> toList() => new List<File>.from(this);
+  List<File> toList({ bool growable: true }) =>
+      new List<File>.from(this, growable: growable);
+
   Set<File> toSet() => new Set<File>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -11924,7 +11954,9 @@
 
   bool any(bool f(num element)) => IterableMixinWorkaround.any(this, f);
 
-  List<num> toList() => new List<num>.from(this);
+  List<num> toList({ bool growable: true }) =>
+      new List<num>.from(this, growable: growable);
+
   Set<num> toSet() => new Set<num>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -12159,7 +12191,9 @@
 
   bool any(bool f(num element)) => IterableMixinWorkaround.any(this, f);
 
-  List<num> toList() => new List<num>.from(this);
+  List<num> toList({ bool growable: true }) =>
+      new List<num>.from(this, growable: growable);
+
   Set<num> toSet() => new Set<num>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -12590,7 +12624,7 @@
 
   @DomName('Geolocation.clearWatch')
   @DocsEditable
-  void $dom_clearWatch(int watchId) native "Geolocation_clearWatch_Callback";
+  void $dom_clearWatch(int watchID) native "Geolocation_clearWatch_Callback";
 
   @DomName('Geolocation.getCurrentPosition')
   @DocsEditable
@@ -12848,7 +12882,9 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
+
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -13057,7 +13093,9 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
+
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -13228,17 +13266,6 @@
     document.$dom_body = value;
   }
 
-  /**
-   * Registers a custom Element subclass as an available HTML tag.
-   *
-   * Not yet implemented.
-   */
-  @Experimental
-  void register(String tagName, Type elementClass) {
-    // TODO: tagName validation
-    throw new Exception('Not yet implemented');
-  }
-
   @DomName('Document.caretRangeFromPoint')
   Range caretRangeFromPoint(int x, int y) {
     return document.$dom_caretRangeFromPoint(x, y);
@@ -14261,7 +14288,6 @@
     TelephoneInputElement,
     EmailInputElement,
     PasswordInputElement,
-    DateTimeInputElement,
     DateInputElement,
     MonthInputElement,
     WeekInputElement,
@@ -14607,11 +14633,11 @@
 
   @DomName('HTMLInputElement.valueAsDate')
   @DocsEditable
-  Date get valueAsDate native "HTMLInputElement_valueAsDate_Getter";
+  DateTime get valueAsDate native "HTMLInputElement_valueAsDate_Getter";
 
   @DomName('HTMLInputElement.valueAsDate')
   @DocsEditable
-  void set valueAsDate(Date value) native "HTMLInputElement_valueAsDate_Setter";
+  void set valueAsDate(DateTime value) native "HTMLInputElement_valueAsDate_Setter";
 
   @DomName('HTMLInputElement.valueAsNumber')
   @DocsEditable
@@ -15019,32 +15045,6 @@
 }
 
 /**
- * A date and time (year, month, day, hour, minute, second, fraction of a
- * second) with the time zone set to UTC.
- *
- * Use [supported] to check if this is supported on the current platform.
- */
-@SupportedBrowser(SupportedBrowser.CHROME, '25')
-@Experimental
-abstract class DateTimeInputElement implements RangeInputElementBase {
-  factory DateTimeInputElement() => new InputElement(type: 'datetime');
-
-  @DomName('HTMLInputElement.valueAsDate')
-  DateTime valueAsDate;
-
-  @DomName('HTMLInputElement.readOnly')
-  bool readOnly;
-
-  @DomName('HTMLInputElement.required')
-  bool required;
-
-  /// Returns true if this input type is supported on the current platform.
-  static bool get supported {
-    return (new InputElement(type: 'datetime')).type == 'datetime';
-  }
-}
-
-/**
  * A date (year, month, day) with no time zone.
  *
  * Use [supported] to check if this is supported on the current platform.
@@ -15415,7 +15415,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -15650,7 +15652,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -15885,7 +15889,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -17930,7 +17936,7 @@
 
   @DomName('Metadata.modificationTime')
   @DocsEditable
-  Date get modificationTime native "Metadata_modificationTime_Getter";
+  DateTime get modificationTime native "Metadata_modificationTime_Getter";
 
   @DomName('Metadata.size')
   @DocsEditable
@@ -18586,7 +18592,13 @@
 
   void addAll(Iterable<Node> iterable) {
     if (iterable is _ChildNodeListLazy) {
-      iterable = new List.from(iterable);
+      if (iterable._this != _this) {
+        // Optimized route for copying between nodes.
+        for (var i = 0, len = iterable.length; i < len; ++i) {
+          _this.$dom_appendChild(iterable[0]);
+        }
+      }
+      return;
     }
     for (Node node in iterable) {
       _this.$dom_appendChild(node);
@@ -18673,7 +18685,8 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -18803,10 +18816,6 @@
 
   Node.internal() : super.internal();
 
-  @DomName('Node.attributes')
-  @DocsEditable
-  _NamedNodeMap get $dom_attributes native "Node_attributes_Getter";
-
   @DomName('Node.childNodes')
   @DocsEditable
   List<Node> get $dom_childNodes native "Node_childNodes_Getter";
@@ -19059,7 +19068,9 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
+
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -19830,10 +19841,18 @@
 class PagePopupController extends NativeFieldWrapperClass1 {
   PagePopupController.internal();
 
+  @DomName('PagePopupController.closePopup')
+  @DocsEditable
+  void closePopup() native "PagePopupController_closePopup_Callback";
+
   @DomName('PagePopupController.formatMonth')
   @DocsEditable
   String formatMonth(int year, int zeroBaseMonth) native "PagePopupController_formatMonth_Callback";
 
+  @DomName('PagePopupController.formatShortMonth')
+  @DocsEditable
+  String formatShortMonth(int year, int zeroBaseMonth) native "PagePopupController_formatShortMonth_Callback";
+
   @DomName('PagePopupController.histogramEnumeration')
   @DocsEditable
   void histogramEnumeration(String name, int sample, int boundaryValue) native "PagePopupController_histogramEnumeration_Callback";
@@ -19842,6 +19861,10 @@
   @DocsEditable
   String localizeNumberString(String numberString) native "PagePopupController_localizeNumberString_Callback";
 
+  @DomName('PagePopupController.setValue')
+  @DocsEditable
+  void setValue(String value) native "PagePopupController_setValue_Callback";
+
   @DomName('PagePopupController.setValueAndClosePopup')
   @DocsEditable
   void setValueAndClosePopup(int numberValue, String stringValue) native "PagePopupController_setValueAndClosePopup_Callback";
@@ -21011,7 +21034,7 @@
 
   @DomName('RTCStatsElement.timestamp')
   @DocsEditable
-  Date get timestamp native "RTCStatsElement_timestamp_Getter";
+  DateTime get timestamp native "RTCStatsElement_timestamp_Getter";
 
   @DomName('RTCStatsElement.names')
   @DocsEditable
@@ -21732,7 +21755,9 @@
 
   bool any(bool f(SourceBuffer element)) => IterableMixinWorkaround.any(this, f);
 
-  List<SourceBuffer> toList() => new List<SourceBuffer>.from(this);
+  List<SourceBuffer> toList({ bool growable: true }) =>
+      new List<SourceBuffer>.from(this, growable: growable);
+
   Set<SourceBuffer> toSet() => new Set<SourceBuffer>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -22050,7 +22075,9 @@
 
   bool any(bool f(SpeechGrammar element)) => IterableMixinWorkaround.any(this, f);
 
-  List<SpeechGrammar> toList() => new List<SpeechGrammar>.from(this);
+  List<SpeechGrammar> toList({ bool growable: true }) =>
+      new List<SpeechGrammar>.from(this, growable: growable);
+
   Set<SpeechGrammar> toSet() => new Set<SpeechGrammar>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -22964,16 +22991,34 @@
   void set span(int value) native "HTMLTableColElement_span_Setter";
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 
 @DocsEditable
 @DomName('HTMLTableElement')
 class TableElement extends _Element_Merged {
+
+  @DomName('HTMLTableElement.tBodies')
+  List<TableSectionElement> get tBodies =>
+  new _WrappedList<TableSectionElement>($dom_tBodies);
+
+  @DomName('HTMLTableElement.rows')
+  List<TableRowElement> get rows =>
+      new _WrappedList<TableRowElement>($dom_rows);
+
+  TableRowElement addRow() {
+    return insertRow(-1);
+  }
+
+  TableCaptionElement createCaption() => $dom_createCaption();
+  TableSectionElement createTBody() => $dom_createTBody();
+  TableSectionElement createTFoot() => $dom_createTFoot();
+  TableSectionElement createTHead() => $dom_createTHead();
+  TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+
   TableElement.internal() : super.internal();
 
   @DomName('HTMLTableElement.HTMLTableElement')
@@ -22998,11 +23043,11 @@
 
   @DomName('HTMLTableElement.rows')
   @DocsEditable
-  HtmlCollection get rows native "HTMLTableElement_rows_Getter";
+  HtmlCollection get $dom_rows native "HTMLTableElement_rows_Getter";
 
   @DomName('HTMLTableElement.tBodies')
   @DocsEditable
-  HtmlCollection get tBodies native "HTMLTableElement_tBodies_Getter";
+  HtmlCollection get $dom_tBodies native "HTMLTableElement_tBodies_Getter";
 
   @DomName('HTMLTableElement.tFoot')
   @DocsEditable
@@ -23022,19 +23067,19 @@
 
   @DomName('HTMLTableElement.createCaption')
   @DocsEditable
-  Element createCaption() native "HTMLTableElement_createCaption_Callback";
+  Element $dom_createCaption() native "HTMLTableElement_createCaption_Callback";
 
   @DomName('HTMLTableElement.createTBody')
   @DocsEditable
-  Element createTBody() native "HTMLTableElement_createTBody_Callback";
+  Element $dom_createTBody() native "HTMLTableElement_createTBody_Callback";
 
   @DomName('HTMLTableElement.createTFoot')
   @DocsEditable
-  Element createTFoot() native "HTMLTableElement_createTFoot_Callback";
+  Element $dom_createTFoot() native "HTMLTableElement_createTFoot_Callback";
 
   @DomName('HTMLTableElement.createTHead')
   @DocsEditable
-  Element createTHead() native "HTMLTableElement_createTHead_Callback";
+  Element $dom_createTHead() native "HTMLTableElement_createTHead_Callback";
 
   @DomName('HTMLTableElement.deleteCaption')
   @DocsEditable
@@ -23054,19 +23099,27 @@
 
   @DomName('HTMLTableElement.insertRow')
   @DocsEditable
-  Element insertRow(int index) native "HTMLTableElement_insertRow_Callback";
-
+  Element $dom_insertRow(int index) native "HTMLTableElement_insertRow_Callback";
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 
 @DocsEditable
 @DomName('HTMLTableRowElement')
 class TableRowElement extends _Element_Merged {
+
+  @DomName('HTMLTableRowElement.cells')
+  List<TableCellElement> get cells =>
+      new _WrappedList<TableCellElement>($dom_cells);
+
+  TableCellElement addCell() {
+    return insertCell(-1);
+  }
+
+  TableCellElement insertCell(int index) => $dom_insertCell(index);
+
   TableRowElement.internal() : super.internal();
 
   @DomName('HTMLTableRowElement.HTMLTableRowElement')
@@ -23075,7 +23128,7 @@
 
   @DomName('HTMLTableRowElement.cells')
   @DocsEditable
-  HtmlCollection get cells native "HTMLTableRowElement_cells_Getter";
+  HtmlCollection get $dom_cells native "HTMLTableRowElement_cells_Getter";
 
   @DomName('HTMLTableRowElement.rowIndex')
   @DocsEditable
@@ -23091,24 +23144,32 @@
 
   @DomName('HTMLTableRowElement.insertCell')
   @DocsEditable
-  Element insertCell(int index) native "HTMLTableRowElement_insertCell_Callback";
-
+  Element $dom_insertCell(int index) native "HTMLTableRowElement_insertCell_Callback";
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 
 @DocsEditable
 @DomName('HTMLTableSectionElement')
 class TableSectionElement extends _Element_Merged {
+
+  @DomName('HTMLTableSectionElement.rows')
+  List<TableRowElement> get rows =>
+    new _WrappedList<TableRowElement>($dom_rows);
+
+  TableRowElement addRow() {
+    return insertRow(-1);
+  }
+
+  TableRowElement insertRow(int index) => $dom_insertRow(index);
+
   TableSectionElement.internal() : super.internal();
 
   @DomName('HTMLTableSectionElement.rows')
   @DocsEditable
-  HtmlCollection get rows native "HTMLTableSectionElement_rows_Getter";
+  HtmlCollection get $dom_rows native "HTMLTableSectionElement_rows_Getter";
 
   @DomName('HTMLTableSectionElement.deleteRow')
   @DocsEditable
@@ -23116,8 +23177,7 @@
 
   @DomName('HTMLTableSectionElement.insertRow')
   @DocsEditable
-  Element insertRow(int index) native "HTMLTableSectionElement_insertRow_Callback";
-
+  Element $dom_insertRow(int index) native "HTMLTableSectionElement_insertRow_Callback";
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -23684,7 +23744,9 @@
 
   bool any(bool f(TextTrackCue element)) => IterableMixinWorkaround.any(this, f);
 
-  List<TextTrackCue> toList() => new List<TextTrackCue>.from(this);
+  List<TextTrackCue> toList({ bool growable: true }) =>
+      new List<TextTrackCue>.from(this, growable: growable);
+
   Set<TextTrackCue> toSet() => new Set<TextTrackCue>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -23893,7 +23955,9 @@
 
   bool any(bool f(TextTrack element)) => IterableMixinWorkaround.any(this, f);
 
-  List<TextTrack> toList() => new List<TextTrack>.from(this);
+  List<TextTrack> toList({ bool growable: true }) =>
+      new List<TextTrack>.from(this, growable: growable);
+
   Set<TextTrack> toSet() => new Set<TextTrack>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -24309,7 +24373,9 @@
 
   bool any(bool f(Touch element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Touch> toList() => new List<Touch>.from(this);
+  List<Touch> toList({ bool growable: true }) =>
+      new List<Touch>.from(this, growable: growable);
+
   Set<Touch> toSet() => new Set<Touch>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -24800,7 +24866,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -25035,7 +25103,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -25270,7 +25340,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -25503,7 +25575,9 @@
 
   bool any(bool f(int element)) => IterableMixinWorkaround.any(this, f);
 
-  List<int> toList() => new List<int>.from(this);
+  List<int> toList({ bool growable: true }) =>
+      new List<int>.from(this, growable: growable);
+
   Set<int> toSet() => new Set<int>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -27892,7 +27966,7 @@
    * frame unwinds, causing the future to complete after all processing has
    * completed for the current event, but before any subsequent events.
    */
-  void setImmediate(TimeoutHandler callback) { 
+  void setImmediate(TimeoutHandler callback) {
     _addMicrotaskCallback(callback);
   }
   /**
@@ -27900,8 +27974,11 @@
    * registered under [name].
    */
   SendPortSync lookupPort(String name) {
-    var port =
-        json.parse(document.documentElement.attributes['dart-port:$name']);
+    var portStr = document.documentElement.attributes['dart-port:$name'];
+    if (portStr == null) {
+      return null;
+    }
+    var port = json.parse(portStr);
     return _deserialize(port);
   }
 
@@ -27923,7 +28000,7 @@
    * If you need to later cancel this animation, use [requestAnimationFrame]
    * instead.
    *
-   * Note: The code that runs when the future completes should call 
+   * Note: The code that runs when the future completes should call
    * [animationFrame] again for the animation to continue.
    */
   Future<num> get animationFrame {
@@ -29185,7 +29262,9 @@
 
   bool any(bool f(ClientRect element)) => IterableMixinWorkaround.any(this, f);
 
-  List<ClientRect> toList() => new List<ClientRect>.from(this);
+  List<ClientRect> toList({ bool growable: true }) =>
+      new List<ClientRect>.from(this, growable: growable);
+
   Set<ClientRect> toSet() => new Set<ClientRect>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -29386,7 +29465,9 @@
 
   bool any(bool f(CssRule element)) => IterableMixinWorkaround.any(this, f);
 
-  List<CssRule> toList() => new List<CssRule>.from(this);
+  List<CssRule> toList({ bool growable: true }) =>
+      new List<CssRule>.from(this, growable: growable);
+
   Set<CssRule> toSet() => new Set<CssRule>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -29587,7 +29668,9 @@
 
   bool any(bool f(CssValue element)) => IterableMixinWorkaround.any(this, f);
 
-  List<CssValue> toList() => new List<CssValue>.from(this);
+  List<CssValue> toList({ bool growable: true }) =>
+      new List<CssValue>.from(this, growable: growable);
+
   Set<CssValue> toSet() => new Set<CssValue>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -29931,7 +30014,9 @@
 
   bool any(bool f(Entry element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Entry> toList() => new List<Entry>.from(this);
+  List<Entry> toList({ bool growable: true }) =>
+      new List<Entry>.from(this, growable: growable);
+
   Set<Entry> toSet() => new Set<Entry>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -30132,7 +30217,9 @@
 
   bool any(bool f(EntrySync element)) => IterableMixinWorkaround.any(this, f);
 
-  List<EntrySync> toList() => new List<EntrySync>.from(this);
+  List<EntrySync> toList({ bool growable: true }) =>
+      new List<EntrySync>.from(this, growable: growable);
+
   Set<EntrySync> toSet() => new Set<EntrySync>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -30333,7 +30420,9 @@
 
   bool any(bool f(Gamepad element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Gamepad> toList() => new List<Gamepad>.from(this);
+  List<Gamepad> toList({ bool growable: true }) =>
+      new List<Gamepad>.from(this, growable: growable);
+
   Set<Gamepad> toSet() => new Set<Gamepad>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -30625,7 +30714,9 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
+
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -30850,7 +30941,9 @@
 
   bool any(bool f(SpeechInputResult element)) => IterableMixinWorkaround.any(this, f);
 
-  List<SpeechInputResult> toList() => new List<SpeechInputResult>.from(this);
+  List<SpeechInputResult> toList({ bool growable: true }) =>
+      new List<SpeechInputResult>.from(this, growable: growable);
+
   Set<SpeechInputResult> toSet() => new Set<SpeechInputResult>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -31051,7 +31144,9 @@
 
   bool any(bool f(SpeechRecognitionResult element)) => IterableMixinWorkaround.any(this, f);
 
-  List<SpeechRecognitionResult> toList() => new List<SpeechRecognitionResult>.from(this);
+  List<SpeechRecognitionResult> toList({ bool growable: true }) =>
+      new List<SpeechRecognitionResult>.from(this, growable: growable);
+
   Set<SpeechRecognitionResult> toSet() => new Set<SpeechRecognitionResult>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -31252,7 +31347,9 @@
 
   bool any(bool f(StyleSheet element)) => IterableMixinWorkaround.any(this, f);
 
-  List<StyleSheet> toList() => new List<StyleSheet>.from(this);
+  List<StyleSheet> toList({ bool growable: true }) =>
+      new List<StyleSheet>.from(this, growable: growable);
+
   Set<StyleSheet> toSet() => new Set<StyleSheet>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -31884,7 +31981,8 @@
   String get first => readClasses().first;
   String get last => readClasses().last;
   String get single => readClasses().single;
-  List<String> toList() => readClasses().toList();
+  List<String> toList({ bool growable: true }) =>
+      readClasses().toList(growable: growable);
   Set<String> toSet() => readClasses().toSet();
   String min([int compare(String a, String b)]) =>
       readClasses().min(compare);
@@ -32147,7 +32245,7 @@
   EventTarget _target;
 
   // The distance to shift from upper case alphabet Roman letters to lower case.
-  final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
+  final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
 
   StreamSubscription _keyUpSubscription, _keyDownSubscription,
       _keyPressSubscription;
@@ -32282,8 +32380,8 @@
       if (prevEvent._shadowCharCode == event.charCode) {
         return prevEvent.keyCode;
       }
-      if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".charCodes[0]
-          && event.charCode <= "Z".charCodes[0] && event.charCode +
+      if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".codeUnits[0]
+          && event.charCode <= "Z".codeUnits[0] && event.charCode +
           _ROMAN_ALPHABET_OFFSET == prevEvent._shadowCharCode) {
         return prevEvent.keyCode;
       }
@@ -33341,6 +33439,147 @@
   timer = new _Timer(() { canceller(id); });
   return timer;
 };
+// 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.
+
+
+/**
+ * A list which just wraps another list, for either intercepting list calls or
+ * retyping the list (for example, from List<A> to List<B> where B extends A).
+ */
+class _WrappedList<E> implements List<E> {
+  final List _list;
+
+  _WrappedList(this._list);
+
+  // Iterable APIs
+
+  Iterator<E> get iterator => new _WrappedIterator(_list.iterator);
+
+  Iterable map(f(E element)) => _list.map(f);
+
+  Iterable<E> where(bool f(E element)) => _list.where(f);
+
+  Iterable expand(Iterable f(E element)) => _list.expand(f);
+
+  bool contains(E element) => _list.contains(element);
+
+  void forEach(void f(E element)) { _list.forEach(f); }
+
+  dynamic reduce(initialValue, combine(previousValue, E element)) =>
+      _list.reduce(initialValue, combine);
+
+  bool every(bool f(E element)) => _list.every(f);
+
+  String join([String separator]) => _list.join(separator);
+
+  bool any(bool f(E element)) => _list.any(f);
+
+  List<E> toList({ bool growable: true }) =>
+      new List.from(_list, growable: growable);
+
+  Set<E> toSet() => _list.toSet();
+
+  int get length => _list.length;
+
+  E min([int compare(E a, E b)]) => _list.min(compare);
+
+  E max([int compare(E a, E b)]) => _list.max(compare);
+
+  bool get isEmpty => _list.isEmpty;
+
+  Iterable<E> take(int n) => _list.take(n);
+
+  Iterable<E> takeWhile(bool test(E value)) => _list.takeWhile(test);
+
+  Iterable<E> skip(int n) => _list.skip(n);
+
+  Iterable<E> skipWhile(bool test(E value)) => _list.skipWhile(test);
+
+  E get first => _list.first;
+
+  E get last => _list.last;
+
+  E get single => _list.single;
+
+  E firstMatching(bool test(E value), { E orElse() }) =>
+      _list.firstMatching(test, orElse: orElse);
+
+  E lastMatching(bool test(E value), {E orElse()}) =>
+      _list.lastMatching(test, orElse: orElse);
+
+  E singleMatching(bool test(E value)) => _list.singleMatching(test);
+
+  E elementAt(int index) => _list.elementAt(index);
+
+  // Collection APIs
+
+  void add(E element) { _list.add(element); }
+
+  void addAll(Iterable<E> elements) { _list.addAll(elements); }
+
+  void remove(Object element) { _list.remove(element); }
+
+  void removeAll(Iterable elements) { _list.removeAll(elements); }
+
+  void retainAll(Iterable elements) { _list.retainAll(elements); }
+
+  void removeMatching(bool test(E element)) { _list.removeMatching(test); }
+
+  void retainMatching(bool test(E element)) { _list.retainMatching(test); }
+
+  void clear() { _list.clear(); }
+
+  // List APIs
+
+  E operator [](int index) => _list[index];
+
+  void operator []=(int index, E value) { _list[index] = value; }
+
+  void set length(int newLength) { _list.length = newLength; }
+
+  void addLast(E value) { _list.addLast(value); }
+
+  Iterable<E> get reversed => _list.reversed;
+
+  void sort([int compare(E a, E b)]) { _list.sort(compare); }
+
+  int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+
+  int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+
+  E removeAt(int index) => _list.removeAt(index);
+
+  E removeLast() => _list.removeLast();
+
+  List<E> getRange(int start, int length) => _list.getRange(start, length);
+
+  void setRange(int start, int length, List<E> from, [int startFrom]) {
+    _list.setRange(start, length, from, startFrom);
+  }
+
+  void removeRange(int start, int length) { _list.removeRange(start, length); }
+
+  void insertRange(int start, int length, [E fill]) {
+    _list.insertRange(start, length, fill);
+  }
+}
+
+/**
+ * Iterator wrapper for _WrappedList.
+ */
+class _WrappedIterator<E> implements Iterator<E> {
+  Iterator _iterator;
+
+  _WrappedIterator(this._iterator);
+
+  bool moveNext() {
+    return _iterator.moveNext();
+  }
+
+  E get current => _iterator.current;
+}
 // 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.
@@ -34127,7 +34366,7 @@
 
   _serializeList(List list) {
     int len = list.length;
-    var result = new List.fixedLength(len);
+    var result = new List(len);
     for (int i = 0; i < len; i++) {
       result[i] = _dispatch(list[i]);
     }
@@ -34299,10 +34538,15 @@
 
 
 class _Utils {
+  static double dateTimeToDouble(DateTime dateTime) =>
+      dateTime.millisecondsSinceEpoch.toDouble();
+  static DateTime doubleToDateTime(double dateTime) =>
+      new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
+
   static List convertToList(List list) {
     // FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it.
     final length = list.length;
-    List result = new List.fixedLength(length);
+    List result = new List(length);
     result.setRange(0, length, list);
     return result;
   }
diff --git a/sdk/lib/html/html_common/filtered_element_list.dart b/sdk/lib/html/html_common/filtered_element_list.dart
index 9337e6b..2644720 100644
--- a/sdk/lib/html/html_common/filtered_element_list.dart
+++ b/sdk/lib/html/html_common/filtered_element_list.dart
@@ -147,7 +147,8 @@
   }
   bool every(bool f(Element element)) => _filtered.every(f);
   bool any(bool f(Element element)) => _filtered.any(f);
-  List<Element> toList() => new List<Element>.from(this);
+  List<Element> toList({ bool growable: true }) =>
+      new List<Element>.from(this, growable: growable);
   Set<Element> toSet() => new Set<Element>.from(this);
   Element firstMatching(bool test(Element value), {Element orElse()}) {
     return _filtered.firstMatching(test, orElse: orElse);
@@ -204,4 +205,8 @@
   Element min([int compare(Element a, Element b)]) => _filtered.min(compare);
 
   Element max([int compare(Element a, Element b)]) => _filtered.max(compare);
+
+  Map<int, Element> asMap() {
+    return IterableMixinWorkaround.asMapList(this);
+  }
 }
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 9180c8a..9c3b377 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -131,15 +131,32 @@
 const String _idbKey = '=List|=Object|num|String';  // TODO(sra): Add DateTime.
 const _annotation_Creates_IDBKey = const Creates(_idbKey);
 const _annotation_Returns_IDBKey = const Returns(_idbKey);
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 
-@DocsEditable
 @DomName('IDBCursor')
 class Cursor native "*IDBCursor" {
+  @DomName('IDBCursor.delete')
+  Future delete() {
+   try {
+      return _completeRequest($dom_delete());
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
 
+  @DomName('IDBCursor.value')
+  Future update(value) {
+   try {
+      return _completeRequest($dom_update(value));
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  
   @DomName('IDBCursor.direction')
   @DocsEditable
   final String direction;
@@ -167,20 +184,22 @@
   @DocsEditable
   void next([Object key]) native;
 
+  @JSName('delete')
   @DomName('IDBCursor.delete')
   @DocsEditable
-  Request delete() native;
+  Request $dom_delete() native;
 
   @DomName('IDBCursor.update')
   @DocsEditable
-  Request update(/*any*/ value) {
+  Request $dom_update(/*any*/ value) {
     var value_1 = convertDartToNative_SerializedScriptValue(value);
-    return _update_1(value_1);
+    return _$dom_update_1(value_1);
   }
   @JSName('update')
   @DomName('IDBCursor.update')
   @DocsEditable
-  Request _update_1(value) native;
+  Request _$dom_update_1(value) native;
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -191,25 +210,40 @@
 @DomName('IDBCursorWithValue')
 class CursorWithValue extends Cursor native "*IDBCursorWithValue" {
 
-  dynamic get value => _convertNativeToDart_IDBAny(this._value);
+  dynamic get value => _convertNativeToDart_IDBAny(this._get_value);
   @JSName('value')
   @DomName('IDBCursorWithValue.value')
   @DocsEditable
   @annotation_Creates_SerializedScriptValue
   @annotation_Returns_SerializedScriptValue
-  final dynamic _value;
+  final dynamic _get_value;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 
+@DocsEditable
 @DomName('IDBDatabase')
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.FIREFOX, '15')
 @SupportedBrowser(SupportedBrowser.IE, '10')
 @Experimental
 class Database extends EventTarget native "*IDBDatabase" {
+  @DomName('IDBDatabase.createObjectStore')
+  @DocsEditable
+  ObjectStore createObjectStore(String name,
+      {String keyPath, bool autoIncrement}) {
+    var options = {};
+    if (keyPath != null) {
+      options['keyPath'] = keyPath;
+    }
+    if (autoIncrement != null) {
+      options['autoIncrement'] = autoIncrement;
+    }
+
+    return $dom_createObjectStore(name, options);
+  }
 
   Transaction transaction(storeName_OR_storeNames, String mode) {
     if (mode != 'readonly' && mode != 'readwrite') {
@@ -266,21 +300,21 @@
 
   @DomName('IDBDatabase.createObjectStore')
   @DocsEditable
-  ObjectStore createObjectStore(String name, [Map options]) {
+  ObjectStore $dom_createObjectStore(String name, [Map options]) {
     if (?options) {
       var options_1 = convertDartToNative_Dictionary(options);
-      return _createObjectStore_1(name, options_1);
+      return _$dom_createObjectStore_1(name, options_1);
     }
-    return _createObjectStore_2(name);
+    return _$dom_createObjectStore_2(name);
   }
   @JSName('createObjectStore')
   @DomName('IDBDatabase.createObjectStore')
   @DocsEditable
-  ObjectStore _createObjectStore_1(name, options) native;
+  ObjectStore _$dom_createObjectStore_1(name, options) native;
   @JSName('createObjectStore')
   @DomName('IDBDatabase.createObjectStore')
   @DocsEditable
-  ObjectStore _createObjectStore_2(name) native;
+  ObjectStore _$dom_createObjectStore_2(name) native;
 
   @DomName('IDBDatabase.deleteObjectStore')
   @DocsEditable
@@ -371,6 +405,27 @@
     }
   }
 
+  @DomName('IDBFactory.getDatabaseNames')
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  Future<List<String>> getDatabaseNames() {
+    try {
+      var request = $dom_webkitGetDatabaseNames();
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  /**
+   * Checks to see if getDatabaseNames is supported by the current platform.
+   */
+  bool get supportsDatabaseNames {
+    return supported && JS('bool',
+        '!!(#.getDatabaseNames || #.webkitGetDatabaseNames)', this, this);
+  }
+
 
   @DomName('IDBFactory.cmp')
   @DocsEditable
@@ -395,7 +450,10 @@
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
   @Experimental
-  Request getDatabaseNames() native;
+  @Returns('Request')
+  @Creates('Request')
+  @Creates('DomStringList')
+  Request $dom_webkitGetDatabaseNames() native;
 
 }
 
@@ -416,15 +474,105 @@
   });
   return completer.future;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 
-@DocsEditable
 @DomName('IDBIndex')
 class Index native "*IDBIndex" {
+  @DomName('IDBIndex.count')
+  Future<int> count([key_OR_range]) {
+   try {
+      var request;
+      if (key_OR_range != null) {
+        request = $dom_count(key_OR_range);
+      } else {
+        request = $dom_count();
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
 
+  @DomName('IDBIndex.get')
+  Future get(key) {
+    try {
+      var request = $dom_get(key);
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBIndex.getKey')
+  Future getKey(key) {
+    try {
+      var request = $dom_getKey(key);
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  /**
+   * Creates a stream of cursors over the records in this object store.
+   *
+   * See also:
+   *
+   * * [ObjectStore.openCursor]
+   */
+  Stream<CursorWithValue> openCursor({key, KeyRange range, String direction,
+      bool autoAdvance}) {
+    var key_OR_range = null;
+    if (key != null) {
+      if (range != null) {
+        throw new ArgumentError('Cannot specify both key and range.');
+      }
+      key_OR_range = key;
+    } else {
+      key_OR_range = range;
+    }
+    var request;
+    if (direction == null) {
+      request = $dom_openCursor(key_OR_range);
+    } else {
+      request = $dom_openCursor(key_OR_range, direction);
+    }
+    return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+  }
+
+  /**
+   * Creates a stream of cursors over the records in this object store.
+   *
+   * See also:
+   *
+   * * [ObjectStore.openCursor]
+   */
+  Stream<Cursor> openKeyCursor({key, KeyRange range, String direction,
+      bool autoAdvance}) {
+    var key_OR_range = null;
+    if (key != null) {
+      if (range != null) {
+        throw new ArgumentError('Cannot specify both key and range.');
+      }
+      key_OR_range = key;
+    } else {
+      key_OR_range = range;
+    }
+    var request;
+    if (direction == null) {
+      request = $dom_openKeyCursor(key_OR_range);
+    } else {
+      request = $dom_openKeyCursor(key_OR_range, direction);
+    }
+    return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+  }
+
+  
   @DomName('IDBIndex.keyPath')
   @DocsEditable
   final dynamic keyPath;
@@ -445,38 +593,44 @@
   @DocsEditable
   final bool unique;
 
+  @JSName('count')
   @DomName('IDBIndex.count')
   @DocsEditable
-  Request count([key_OR_range]) native;
+  Request $dom_count([key_OR_range]) native;
 
+  @JSName('get')
   @DomName('IDBIndex.get')
   @DocsEditable
   @Returns('Request')
   @Creates('Request')
   @annotation_Creates_SerializedScriptValue
-  Request get(key) native;
+  Request $dom_get(key) native;
 
+  @JSName('getKey')
   @DomName('IDBIndex.getKey')
   @DocsEditable
   @Returns('Request')
   @Creates('Request')
   @annotation_Creates_SerializedScriptValue
   @Creates('ObjectStore')
-  Request getKey(key) native;
+  Request $dom_getKey(key) native;
 
+  @JSName('openCursor')
   @DomName('IDBIndex.openCursor')
   @DocsEditable
   @Returns('Request')
   @Creates('Request')
   @Creates('Cursor')
-  Request openCursor([key_OR_range, String direction]) native;
+  Request $dom_openCursor([key_OR_range, String direction]) native;
 
+  @JSName('openKeyCursor')
   @DomName('IDBIndex.openKeyCursor')
   @DocsEditable
   @Returns('Request')
   @Creates('Request')
   @Creates('Cursor')
-  Request openKeyCursor([key_OR_range, String direction]) native;
+  Request $dom_openKeyCursor([key_OR_range, String direction]) native;
+
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -549,6 +703,54 @@
 @DomName('IDBObjectStore')
 class ObjectStore native "*IDBObjectStore" {
 
+  @DomName('IDBObjectStore.add')
+  Future add(value, [key]) {
+    try {
+      var request;
+      if (key != null) {
+        request = $dom_add(value, key);
+      } else {
+        request = $dom_add(value);
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.clear')
+  Future clear() {
+    try {
+      return _completeRequest($dom_clear());
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.delete')
+  Future delete(key_OR_keyRange){
+    try {
+      return _completeRequest($dom_delete(key_OR_keyRange));
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.count')
+  Future<int> count([key_OR_range]) {
+   try {
+      var request;
+      if (key_OR_range != null) {
+        request = $dom_count(key_OR_range);
+      } else {
+        request = $dom_count();
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
   @DomName('IDBObjectStore.put')
   Future put(value, [key]) {
     try {
@@ -619,6 +821,19 @@
     return _cursorStreamFromResult(request, autoAdvance);
   }
 
+  @DomName('IDBObjectStore.createIndex')
+  Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) {
+    var options = {};
+    if (unique != null) {
+      options['unique'] = unique;
+    }
+    if (multiEntry != null) {
+      options['multiEntry'] = multiEntry;
+    }
+
+    return $dom_createIndex(name, keyPath, options);
+  }
+
 
   @DomName('IDBObjectStore.autoIncrement')
   @DocsEditable
@@ -647,14 +862,14 @@
   @Returns('Request')
   @Creates('Request')
   @_annotation_Creates_IDBKey
-  Request add(/*any*/ value, [/*any*/ key]) {
+  Request $dom_add(/*any*/ value, [/*any*/ key]) {
     if (?key) {
       var value_1 = convertDartToNative_SerializedScriptValue(value);
       var key_2 = convertDartToNative_SerializedScriptValue(key);
-      return _add_1(value_1, key_2);
+      return _$dom_add_1(value_1, key_2);
     }
     var value_3 = convertDartToNative_SerializedScriptValue(value);
-    return _add_2(value_3);
+    return _$dom_add_2(value_3);
   }
   @JSName('add')
   @DomName('IDBObjectStore.add')
@@ -662,64 +877,67 @@
   @Returns('Request')
   @Creates('Request')
   @_annotation_Creates_IDBKey
-  Request _add_1(value, key) native;
+  Request _$dom_add_1(value, key) native;
   @JSName('add')
   @DomName('IDBObjectStore.add')
   @DocsEditable
   @Returns('Request')
   @Creates('Request')
   @_annotation_Creates_IDBKey
-  Request _add_2(value) native;
+  Request _$dom_add_2(value) native;
 
+  @JSName('clear')
   @DomName('IDBObjectStore.clear')
   @DocsEditable
-  Request clear() native;
+  Request $dom_clear() native;
 
+  @JSName('count')
   @DomName('IDBObjectStore.count')
   @DocsEditable
-  Request count([key_OR_range]) native;
+  Request $dom_count([key_OR_range]) native;
 
   @DomName('IDBObjectStore.createIndex')
   @DocsEditable
-  Index createIndex(String name, keyPath, [Map options]) {
+  Index $dom_createIndex(String name, keyPath, [Map options]) {
     if ((keyPath is List<String> || keyPath == null) && !?options) {
       List keyPath_1 = convertDartToNative_StringArray(keyPath);
-      return _createIndex_1(name, keyPath_1);
+      return _$dom_createIndex_1(name, keyPath_1);
     }
     if ((keyPath is List<String> || keyPath == null)) {
       List keyPath_2 = convertDartToNative_StringArray(keyPath);
       var options_3 = convertDartToNative_Dictionary(options);
-      return _createIndex_2(name, keyPath_2, options_3);
+      return _$dom_createIndex_2(name, keyPath_2, options_3);
     }
     if ((keyPath is String || keyPath == null) && !?options) {
-      return _createIndex_3(name, keyPath);
+      return _$dom_createIndex_3(name, keyPath);
     }
     if ((keyPath is String || keyPath == null)) {
       var options_4 = convertDartToNative_Dictionary(options);
-      return _createIndex_4(name, keyPath, options_4);
+      return _$dom_createIndex_4(name, keyPath, options_4);
     }
     throw new ArgumentError("Incorrect number or type of arguments");
   }
   @JSName('createIndex')
   @DomName('IDBObjectStore.createIndex')
   @DocsEditable
-  Index _createIndex_1(name, List keyPath) native;
+  Index _$dom_createIndex_1(name, List keyPath) native;
   @JSName('createIndex')
   @DomName('IDBObjectStore.createIndex')
   @DocsEditable
-  Index _createIndex_2(name, List keyPath, options) native;
+  Index _$dom_createIndex_2(name, List keyPath, options) native;
   @JSName('createIndex')
   @DomName('IDBObjectStore.createIndex')
   @DocsEditable
-  Index _createIndex_3(name, String keyPath) native;
+  Index _$dom_createIndex_3(name, String keyPath) native;
   @JSName('createIndex')
   @DomName('IDBObjectStore.createIndex')
   @DocsEditable
-  Index _createIndex_4(name, String keyPath, options) native;
+  Index _$dom_createIndex_4(name, String keyPath, options) native;
 
+  @JSName('delete')
   @DomName('IDBObjectStore.delete')
   @DocsEditable
-  Request delete(key_OR_keyRange) native;
+  Request $dom_delete(key_OR_keyRange) native;
 
   @DomName('IDBObjectStore.deleteIndex')
   @DocsEditable
@@ -854,12 +1072,12 @@
   @DocsEditable
   final String readyState;
 
-  dynamic get result => _convertNativeToDart_IDBAny(this._result);
+  dynamic get result => _convertNativeToDart_IDBAny(this._get_result);
   @JSName('result')
   @DomName('IDBRequest.result')
   @DocsEditable
   @Creates('Null')
-  final dynamic _result;
+  final dynamic _get_result;
 
   @DomName('IDBRequest.source')
   @DocsEditable
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 5aa80a1a..c0d888c 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -33,17 +33,32 @@
       [bool lowerOpen = false, bool upperOpen = false]) =>
       KeyRange.bound_(lower, upper, lowerOpen, upperOpen);
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
 
-
-@DocsEditable
 @DomName('IDBCursor')
 class Cursor extends NativeFieldWrapperClass1 {
-  Cursor.internal();
+  @DomName('IDBCursor.delete')
+  Future delete() {
+   try {
+      return _completeRequest($dom_delete());
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBCursor.value')
+  Future update(value) {
+   try {
+      return _completeRequest($dom_update(value));
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+    Cursor.internal();
 
   @DomName('IDBCursor.direction')
   @DocsEditable
@@ -84,11 +99,11 @@
 
   @DomName('IDBCursor.delete')
   @DocsEditable
-  Request delete() native "IDBCursor_delete_Callback";
+  Request $dom_delete() native "IDBCursor_delete_Callback";
 
   @DomName('IDBCursor.update')
   @DocsEditable
-  Request update(Object value) native "IDBCursor_update_Callback";
+  Request $dom_update(Object value) native "IDBCursor_update_Callback";
 
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -108,12 +123,10 @@
   Object get value native "IDBCursorWithValue_value_Getter";
 
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
-
 
 @DocsEditable
 @DomName('IDBDatabase')
@@ -122,6 +135,22 @@
 @SupportedBrowser(SupportedBrowser.IE, '10')
 @Experimental
 class Database extends EventTarget {
+  @DomName('IDBDatabase.createObjectStore')
+  @DocsEditable
+  ObjectStore createObjectStore(String name,
+      {String keyPath, bool autoIncrement}) {
+    var options = {};
+    if (keyPath != null) {
+      options['keyPath'] = keyPath;
+    }
+    if (autoIncrement != null) {
+      options['autoIncrement'] = autoIncrement;
+    }
+
+    return $dom_createObjectStore(name, options);
+  }
+
+
   Database.internal() : super.internal();
 
   @DomName('IDBDatabase.abortEvent')
@@ -158,7 +187,7 @@
 
   @DomName('IDBDatabase.createObjectStore')
   @DocsEditable
-  ObjectStore createObjectStore(String name, [Map options]) native "IDBDatabase_createObjectStore_Callback";
+  ObjectStore $dom_createObjectStore(String name, [Map options]) native "IDBDatabase_createObjectStore_Callback";
 
   @DomName('IDBDatabase.deleteObjectStore')
   @DocsEditable
@@ -208,7 +237,6 @@
   @DomName('IDBDatabase.onversionchange')
   @DocsEditable
   Stream<VersionChangeEvent> get onVersionChange => versionChangeEvent.forTarget(this);
-
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -271,6 +299,26 @@
     }
   }
 
+  @DomName('IDBFactory.getDatabaseNames')
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  Future<List<String>> getDatabaseNames() {
+    try {
+      var request = $dom_webkitGetDatabaseNames();
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  /**
+   * Checks to see if getDatabaseNames is supported by the current platform.
+   */
+  bool get supportsDatabaseNames {
+    return true;
+  }
+
   IdbFactory.internal();
 
   @DomName('IDBFactory.cmp')
@@ -301,7 +349,7 @@
   @SupportedBrowser(SupportedBrowser.CHROME)
   @SupportedBrowser(SupportedBrowser.SAFARI)
   @Experimental
-  Request getDatabaseNames() native "IDBFactory_webkitGetDatabaseNames_Callback";
+  Request $dom_webkitGetDatabaseNames() native "IDBFactory_webkitGetDatabaseNames_Callback";
 
 }
 
@@ -322,17 +370,105 @@
   });
   return completer.future;
 }
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// WARNING: Do not edit - generated code.
 
-
-@DocsEditable
 @DomName('IDBIndex')
 class Index extends NativeFieldWrapperClass1 {
-  Index.internal();
+  @DomName('IDBIndex.count')
+  Future<int> count([key_OR_range]) {
+   try {
+      var request;
+      if (key_OR_range != null) {
+        request = $dom_count(key_OR_range);
+      } else {
+        request = $dom_count();
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBIndex.get')
+  Future get(key) {
+    try {
+      var request = $dom_get(key);
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBIndex.getKey')
+  Future getKey(key) {
+    try {
+      var request = $dom_getKey(key);
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  /**
+   * Creates a stream of cursors over the records in this object store.
+   *
+   * See also:
+   *
+   * * [ObjectStore.openCursor]
+   */
+  Stream<CursorWithValue> openCursor({key, KeyRange range, String direction,
+      bool autoAdvance}) {
+    var key_OR_range = null;
+    if (key != null) {
+      if (range != null) {
+        throw new ArgumentError('Cannot specify both key and range.');
+      }
+      key_OR_range = key;
+    } else {
+      key_OR_range = range;
+    }
+    var request;
+    if (direction == null) {
+      request = $dom_openCursor(key_OR_range);
+    } else {
+      request = $dom_openCursor(key_OR_range, direction);
+    }
+    return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+  }
+
+  /**
+   * Creates a stream of cursors over the records in this object store.
+   *
+   * See also:
+   *
+   * * [ObjectStore.openCursor]
+   */
+  Stream<Cursor> openKeyCursor({key, KeyRange range, String direction,
+      bool autoAdvance}) {
+    var key_OR_range = null;
+    if (key != null) {
+      if (range != null) {
+        throw new ArgumentError('Cannot specify both key and range.');
+      }
+      key_OR_range = key;
+    } else {
+      key_OR_range = range;
+    }
+    var request;
+    if (direction == null) {
+      request = $dom_openKeyCursor(key_OR_range);
+    } else {
+      request = $dom_openKeyCursor(key_OR_range, direction);
+    }
+    return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+  }
+
+    Index.internal();
 
   @DomName('IDBIndex.keyPath')
   @DocsEditable
@@ -354,7 +490,7 @@
   @DocsEditable
   bool get unique native "IDBIndex_unique_Getter";
 
-  Request count([key_OR_range]) {
+  Request $dom_count([key_OR_range]) {
     if (!?key_OR_range) {
       return _count_1();
     }
@@ -379,7 +515,7 @@
   @DocsEditable
   Request _count_3(key_OR_range) native "IDBIndex__count_3_Callback";
 
-  Request get(key) {
+  Request $dom_get(key) {
     if ((key is KeyRange || key == null)) {
       return _get_1(key);
     }
@@ -397,7 +533,7 @@
   @DocsEditable
   Request _get_2(key) native "IDBIndex__get_2_Callback";
 
-  Request getKey(key) {
+  Request $dom_getKey(key) {
     if ((key is KeyRange || key == null)) {
       return _getKey_1(key);
     }
@@ -415,7 +551,7 @@
   @DocsEditable
   Request _getKey_2(key) native "IDBIndex__getKey_2_Callback";
 
-  Request openCursor([key_OR_range, String direction]) {
+  Request $dom_openCursor([key_OR_range, String direction]) {
     if (!?key_OR_range && !?direction) {
       return _openCursor_1();
     }
@@ -454,7 +590,7 @@
   @DocsEditable
   Request _openCursor_5(key_OR_range, direction) native "IDBIndex__openCursor_5_Callback";
 
-  Request openKeyCursor([key_OR_range, String direction]) {
+  Request $dom_openKeyCursor([key_OR_range, String direction]) {
     if (!?key_OR_range && !?direction) {
       return _openKeyCursor_1();
     }
@@ -602,6 +738,54 @@
 @DomName('IDBObjectStore')
 class ObjectStore extends NativeFieldWrapperClass1 {
 
+  @DomName('IDBObjectStore.add')
+  Future add(value, [key]) {
+    try {
+      var request;
+      if (key != null) {
+        request = $dom_add(value, key);
+      } else {
+        request = $dom_add(value);
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.clear')
+  Future clear() {
+    try {
+      return _completeRequest($dom_clear());
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.delete')
+  Future delete(key_OR_keyRange){
+    try {
+      return _completeRequest($dom_delete(key_OR_keyRange));
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.count')
+  Future<int> count([key_OR_range]) {
+   try {
+      var request;
+      if (key_OR_range != null) {
+        request = $dom_count(key_OR_range);
+      } else {
+        request = $dom_count();
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
   @DomName('IDBObjectStore.put')
   Future put(value, [key]) {
     try {
@@ -672,6 +856,19 @@
     return _cursorStreamFromResult(request, autoAdvance);
   }
 
+  @DomName('IDBObjectStore.createIndex')
+  Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) {
+    var options = {};
+    if (unique != null) {
+      options['unique'] = unique;
+    }
+    if (multiEntry != null) {
+      options['multiEntry'] = multiEntry;
+    }
+
+    return $dom_createIndex(name, keyPath, options);
+  }
+
   ObjectStore.internal();
 
   @DomName('IDBObjectStore.autoIncrement')
@@ -694,7 +891,7 @@
   @DocsEditable
   Transaction get transaction native "IDBObjectStore_transaction_Getter";
 
-  Request add(Object value, [Object key]) {
+  Request $dom_add(Object value, [Object key]) {
     if (?key) {
       return _add_1(value, key);
     }
@@ -711,9 +908,9 @@
 
   @DomName('IDBObjectStore.clear')
   @DocsEditable
-  Request clear() native "IDBObjectStore_clear_Callback";
+  Request $dom_clear() native "IDBObjectStore_clear_Callback";
 
-  Request count([key_OR_range]) {
+  Request $dom_count([key_OR_range]) {
     if (!?key_OR_range) {
       return _count_1();
     }
@@ -738,7 +935,7 @@
   @DocsEditable
   Request _count_3(key_OR_range) native "IDBObjectStore__count_3_Callback";
 
-  Index createIndex(String name, keyPath, [Map options]) {
+  Index $dom_createIndex(String name, keyPath, [Map options]) {
     if ((name is String || name == null) && (keyPath is List<String> || keyPath == null) && (options is Map || options == null)) {
       return _createIndex_1(name, keyPath, options);
     }
@@ -756,7 +953,7 @@
   @DocsEditable
   Index _createIndex_2(name, keyPath, options) native "IDBObjectStore__createIndex_2_Callback";
 
-  Request delete(key_OR_keyRange) {
+  Request $dom_delete(key_OR_keyRange) {
     if ((key_OR_keyRange is KeyRange || key_OR_keyRange == null)) {
       return _delete_1(key_OR_keyRange);
     }
diff --git a/sdk/lib/io/base64.dart b/sdk/lib/io/base64.dart
index f57eea6..12c1e5f8 100644
--- a/sdk/lib/io/base64.dart
+++ b/sdk/lib/io/base64.dart
@@ -68,7 +68,7 @@
     int charCount = 0;
     int value = 0;
     for (int i = 0; i < data.length; i++) {
-      int char = data.charCodeAt(i);
+      int char = data.codeUnitAt(i);
       if (65 <= char && char <= 90) {  // "A" - "Z".
         value = (value << 6) | char - 65;
         charCount++;
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 5963d83..2b519e7 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -31,7 +31,7 @@
 
   Future<bool> exists() {
     _ensureDirectoryService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = EXISTS_REQUEST;
     request[1] = _path;
     return _directoryService.call(request).then((response) {
@@ -110,7 +110,7 @@
   Future<Directory> create({recursive: false}) {
     if (recursive) return createRecursively();
     _ensureDirectoryService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = CREATE_REQUEST;
     request[1] = _path;
     return _directoryService.call(request).then((response) {
@@ -149,7 +149,7 @@
 
   Future<Directory> createTemp() {
     _ensureDirectoryService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = CREATE_TEMP_REQUEST;
     request[1] = _path;
     return _directoryService.call(request).then((response) {
@@ -179,7 +179,7 @@
 
   Future<Directory> delete({recursive: false}) {
     _ensureDirectoryService();
-    List request = new List.fixedLength(3);
+    List request = new List(3);
     request[0] = DELETE_REQUEST;
     request[1] = _path;
     request[2] = recursive;
@@ -203,7 +203,7 @@
 
   Future<Directory> rename(String newPath) {
     _ensureDirectoryService();
-    List request = new List.fixedLength(3);
+    List request = new List(3);
     request[0] = RENAME_REQUEST;
     request[1] = _path;
     request[2] = newPath;
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index ff956c8..f42555e 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -30,7 +30,7 @@
   /**
    * Create a File object.
    */
-  factory File(String name) => new _File(name);
+  factory File(String path) => new _File(path);
 
   /**
    * Create a File object from a Path object.
@@ -143,13 +143,13 @@
   RandomAccessFile openSync([FileMode mode = FileMode.READ]);
 
   /**
-   * Get the canonical full path corresponding to the file name.
+   * Get the canonical full path corresponding to the file path.
    * Returns a [:Future<String>:] that completes with the path.
    */
   Future<String> fullPath();
 
   /**
-   * Synchronously get the canonical full path corresponding to the file name.
+   * Synchronously get the canonical full path corresponding to the file path.
    */
   String fullPathSync();
 
@@ -274,9 +274,9 @@
                           Encoding encoding: Encoding.UTF_8});
 
   /**
-   * Get the name of the file.
+   * Get the path of the file.
    */
-  String get name;
+  String get path;
 }
 
 
@@ -444,9 +444,9 @@
   String toString();
 
   /**
-   * Gets the name of the file underlying this RandomAccessFile.
+   * Gets the path of the file underlying this RandomAccessFile.
    */
-  String get name;
+  String get path;
 }
 
 
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index ce60209..0ba765c 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -13,7 +13,7 @@
   final int _blockSize = 64 * 1024;
 
   // Information about the underlying file.
-  String _name;
+  String _path;
   RandomAccessFile _openedFile;
   int _position;
 
@@ -27,7 +27,7 @@
   // Block read but not yet send because stream is paused.
   List<int> _currentBlock;
 
-  _FileStream(String this._name) : _position = 0 {
+  _FileStream(String this._path) : _position = 0 {
     _setupController();
   }
 
@@ -103,8 +103,8 @@
 
   void _start() {
     Future<RandomAccessFile> openFuture;
-    if (_name != null) {
-      openFuture = new File(_name).open(FileMode.READ);
+    if (_path != null) {
+      openFuture = new File(_path).open(FileMode.READ);
     } else {
       openFuture = new Future.immediate(_File._openStdioSync(0));
     }
@@ -211,7 +211,7 @@
 const int _SET_POSITION_REQUEST = 8;
 const int _TRUNCATE_REQUEST = 9;
 const int _LENGTH_REQUEST = 10;
-const int _LENGTH_FROM_NAME_REQUEST = 11;
+const int _LENGTH_FROM_PATH_REQUEST = 11;
 const int _LAST_MODIFIED_REQUEST = 12;
 const int _FLUSH_REQUEST = 13;
 const int _READ_BYTE_REQUEST = 14;
@@ -253,9 +253,9 @@
 // Class for encapsulating the native implementation of files.
 class _File extends _FileBase implements File {
   // Constructor for file.
-  _File(String this._name) {
-    if (_name is! String) {
-      throw new ArgumentError('${Error.safeToString(_name)} '
+  _File(String this._path) {
+    if (_path is! String) {
+      throw new ArgumentError('${Error.safeToString(_path)} '
                               'is not a String');
     }
   }
@@ -265,85 +265,85 @@
 
   Future<bool> exists() {
     _ensureFileService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _EXISTS_REQUEST;
-    request[1] = _name;
+    request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot open file '$_name'");
+        throw _exceptionFromResponse(response, "Cannot open file '$_path'");
       }
       return response;
     });
   }
 
-  external static _exists(String name);
+  external static _exists(String path);
 
   bool existsSync() {
-    var result = _exists(_name);
-    throwIfError(result, "Cannot check existence of file '$_name'");
+    var result = _exists(_path);
+    throwIfError(result, "Cannot check existence of file '$_path'");
     return result;
   }
 
   Future<File> create() {
     _ensureFileService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _CREATE_REQUEST;
-    request[1] = _name;
+    request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot create file '$_name'");
+        throw _exceptionFromResponse(response, "Cannot create file '$_path'");
       }
       return this;
     });
   }
 
-  external static _create(String name);
+  external static _create(String path);
 
   void createSync() {
-    var result = _create(_name);
-    throwIfError(result, "Cannot create file '$_name'");
+    var result = _create(_path);
+    throwIfError(result, "Cannot create file '$_path'");
   }
 
   Future<File> delete() {
     _ensureFileService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _DELETE_REQUEST;
-    request[1] = _name;
+    request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot delete file '$_name'");
+        throw _exceptionFromResponse(response, "Cannot delete file '$_path'");
       }
       return this;
     });
   }
 
-  external static _delete(String name);
+  external static _delete(String path);
 
   void deleteSync() {
-    var result = _delete(_name);
-    throwIfError(result, "Cannot delete file '$_name'");
+    var result = _delete(_path);
+    throwIfError(result, "Cannot delete file '$_path'");
   }
 
   Future<Directory> directory() {
     _ensureFileService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _DIRECTORY_REQUEST;
-    request[1] = _name;
+    request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "Cannot retrieve directory for "
-                                     "file '$_name'");
+                                     "file '$_path'");
       }
       return new Directory(response);
     });
   }
 
-  external static _directory(String name);
+  external static _directory(String path);
 
   Directory directorySync() {
-    var result = _directory(name);
-    throwIfError(result, "Cannot retrieve directory for file '$_name'");
+    var result = _directory(path);
+    throwIfError(result, "Cannot retrieve directory for file '$_path'");
     return new Directory(result);
   }
 
@@ -358,66 +358,66 @@
       });
       return completer.future;
     }
-    List request = new List.fixedLength(3);
+    List request = new List(3);
     request[0] = _OPEN_REQUEST;
-    request[1] = _name;
+    request[1] = _path;
     request[2] = mode._mode;  // Direct int value for serialization.
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot open file '$_name'");
+        throw _exceptionFromResponse(response, "Cannot open file '$_path'");
       }
-      return new _RandomAccessFile(response, _name);
+      return new _RandomAccessFile(response, _path);
     });
   }
 
   Future<int> length() {
     _ensureFileService();
-    List request = new List.fixedLength(2);
-    request[0] = _LENGTH_FROM_NAME_REQUEST;
-    request[1] = _name;
+    List request = new List(2);
+    request[0] = _LENGTH_FROM_PATH_REQUEST;
+    request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "Cannot retrieve length of "
-                                     "file '$_name'");
+                                     "file '$_path'");
       }
       return response;
     });
   }
 
 
-  external static _lengthFromName(String name);
+  external static _lengthFromPath(String path);
 
   int lengthSync() {
-    var result = _lengthFromName(_name);
-    throwIfError(result, "Cannot retrieve length of file '$_name'");
+    var result = _lengthFromPath(_path);
+    throwIfError(result, "Cannot retrieve length of file '$_path'");
     return result;
   }
 
   Future<DateTime> lastModified() {
     _ensureFileService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _LAST_MODIFIED_REQUEST;
-    request[1] = _name;
+    request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "Cannot retrieve modification time "
-                                     "for file '$_name'");
+                                     "for file '$_path'");
       }
       return new DateTime.fromMillisecondsSinceEpoch(response);
     });
   }
 
-  external static _lastModified(String name);
+  external static _lastModified(String path);
 
   DateTime lastModifiedSync() {
-    var ms = _lastModified(name);
-    throwIfError(ms, "Cannot retrieve modification time for file '$_name'");
+    var ms = _lastModified(path);
+    throwIfError(ms, "Cannot retrieve modification time for file '$_path'");
     return new DateTime.fromMillisecondsSinceEpoch(ms);
   }
 
-  external static _open(String name, int mode);
+  external static _open(String path, int mode);
 
   RandomAccessFile openSync([FileMode mode = FileMode.READ]) {
     if (mode != FileMode.READ &&
@@ -426,9 +426,9 @@
       throw new FileIOException("Unknown file mode. Use FileMode.READ, "
                                 "FileMode.WRITE or FileMode.APPEND.");
     }
-    var id = _open(_name, mode._mode);
-    throwIfError(id, "Cannot open file '$_name'");
-    return new _RandomAccessFile(id, _name);
+    var id = _open(_path, mode._mode);
+    throwIfError(id, "Cannot open file '$_path'");
+    return new _RandomAccessFile(id, _path);
   }
 
   external static int _openStdio(int fd);
@@ -443,29 +443,29 @@
 
   Future<String> fullPath() {
     _ensureFileService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _FULL_PATH_REQUEST;
-    request[1] = _name;
+    request[1] = _path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "Cannot retrieve full path"
-                                     " for '$_name'");
+                                     " for '$_path'");
       }
       return response;
     });
   }
 
-  external static _fullPath(String name);
+  external static _fullPath(String path);
 
   String fullPathSync() {
-    var result = _fullPath(_name);
-    throwIfError(result, "Cannot retrieve full path for file '$_name'");
+    var result = _fullPath(_path);
+    throwIfError(result, "Cannot retrieve full path for file '$_path'");
     return result;
   }
 
   Stream<List<int>> openRead() {
-    return new _FileStream(_name);
+    return new _FileStream(_path);
   }
 
   IOSink<File> openWrite([FileMode mode = FileMode.WRITE]) {
@@ -525,9 +525,9 @@
     var list = [];
     var controller = new StreamController();
     controller.stream
-      .transform(new StringDecoder(encoding))
-      .transform(new LineTransformer())
-      .listen((line) => list.add(line));
+        .transform(new StringDecoder(encoding))
+        .transform(new LineTransformer())
+        .listen((line) => list.add(line));
     controller.add(bytes);
     controller.close();
     return list;
@@ -590,9 +590,9 @@
     writeAsBytesSync(_encodeString(contents, encoding), mode);
   }
 
-  String get name => _name;
+  String get path => _path;
 
-  String toString() => "File: '$name'";
+  String toString() => "File: '$path'";
 
   void _ensureFileService() {
     if (_fileService == null) {
@@ -606,20 +606,20 @@
     }
   }
 
-  final String _name;
+  final String _path;
 
   SendPort _fileService;
 }
 
 
 class _RandomAccessFile extends _FileBase implements RandomAccessFile {
-  _RandomAccessFile(int this._id, String this._name);
+  _RandomAccessFile(int this._id, String this._path);
 
   Future<RandomAccessFile> close() {
     Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
     if (closed) return _completeWithClosedException(completer);
     _ensureFileService();
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _CLOSE_REQUEST;
     request[1] = _id;
     // Set the id_ to 0 (NULL) to ensure the no more async requests
@@ -630,7 +630,7 @@
         _id = result;
         return this;
       } else {
-        throw new FileIOException("Cannot close file '$_name'");
+        throw new FileIOException("Cannot close file '$_path'");
       }
     });
   }
@@ -641,7 +641,7 @@
     _checkNotClosed();
     var id = _close(_id);
     if (id == -1) {
-      throw new FileIOException("Cannot close file '$_name'");
+      throw new FileIOException("Cannot close file '$_path'");
     }
     _id = id;
   }
@@ -650,13 +650,13 @@
     _ensureFileService();
     Completer<int> completer = new Completer<int>();
     if (closed) return _completeWithClosedException(completer);
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _READ_BYTE_REQUEST;
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "readByte failed for file '$_name'");
+                                     "readByte failed for file '$_path'");
       }
       return response;
     });
@@ -668,7 +668,7 @@
     _checkNotClosed();
     var result = _readByte(_id);
     if (result is OSError) {
-      throw new FileIOException("readByte failed for file '$_name'", result);
+      throw new FileIOException("readByte failed for file '$_path'", result);
     }
     return result;
   }
@@ -682,7 +682,7 @@
       // then handler.
       Timer.run(() {
         completer.completeError(new FileIOException(
-            "Invalid arguments to read for file '$_name'"));
+            "Invalid arguments to read for file '$_path'"));
       });
       return completer.future;
     };
@@ -694,7 +694,7 @@
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "read failed for file '$_name'");
+                                     "read failed for file '$_path'");
       }
       return response[1];
     });
@@ -705,7 +705,7 @@
   List<int> readSync(int bytes) {
     if (bytes is !int) {
       throw new FileIOException(
-          "Invalid arguments to readSync for file '$_name'");
+          "Invalid arguments to readSync for file '$_path'");
     }
     return _read(_id, bytes);
   }
@@ -719,19 +719,19 @@
       // then handler.
       Timer.run(() {
         completer.completeError(new FileIOException(
-            "Invalid arguments to readList for file '$_name'"));
+            "Invalid arguments to readList for file '$_path'"));
       });
       return completer.future;
     };
     if (closed) return _completeWithClosedException(completer);
-    List request = new List.fixedLength(3);
+    List request = new List(3);
     request[0] = _READ_LIST_REQUEST;
     request[1] = _id;
     request[2] = bytes;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "readList failed for file '$_name'");
+                                     "readList failed for file '$_path'");
       }
       var read = response[1];
       var data = response[2];
@@ -754,13 +754,13 @@
     _checkNotClosed();
     if (buffer is !List || offset is !int || bytes is !int) {
       throw new FileIOException(
-          "Invalid arguments to readList for file '$_name'");
+          "Invalid arguments to readList for file '$_path'");
     }
     if (bytes == 0) return 0;
     _checkReadWriteListArguments(buffer.length, offset, bytes);
     var result = _readList(_id, buffer, offset, bytes);
     if (result is OSError) {
-      throw new FileIOException("readList failed for file '$_name'",
+      throw new FileIOException("readList failed for file '$_path'",
                                 result);
     }
     return result;
@@ -775,19 +775,19 @@
       // then handler.
       Timer.run(() {
           completer.completeError(new FileIOException(
-              "Invalid argument to writeByte for file '$_name'"));
+              "Invalid argument to writeByte for file '$_path'"));
       });
       return completer.future;
     }
     if (closed) return _completeWithClosedException(completer);
-    List request = new List.fixedLength(3);
+    List request = new List(3);
     request[0] = _WRITE_BYTE_REQUEST;
     request[1] = _id;
     request[2] = value;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "writeByte failed for file '$_name'");
+                                     "writeByte failed for file '$_path'");
       }
       return this;
     });
@@ -799,11 +799,11 @@
     _checkNotClosed();
     if (value is !int) {
       throw new FileIOException(
-          "Invalid argument to writeByte for file '$_name'");
+          "Invalid argument to writeByte for file '$_path'");
     }
     var result = _writeByte(_id, value);
     if (result is OSError) {
-      throw new FileIOException("writeByte failed for file '$_name'",
+      throw new FileIOException("writeByte failed for file '$_path'",
                                 result);
     }
     return result;
@@ -818,7 +818,7 @@
       // then handler.
       Timer.run(() {
           completer.completeError(new FileIOException(
-          "Invalid arguments to writeList for file '$_name'"));
+          "Invalid arguments to writeList for file '$_path'"));
       });
       return completer.future;
     }
@@ -835,7 +835,7 @@
       return completer.future;
     }
 
-    List request = new List.fixedLength(5);
+    List request = new List(5);
     request[0] = _WRITE_LIST_REQUEST;
     request[1] = _id;
     request[2] = result.buffer;
@@ -844,7 +844,7 @@
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "writeList failed for file '$_name'");
+                                     "writeList failed for file '$_path'");
       }
       return this;
     });
@@ -856,7 +856,7 @@
     _checkNotClosed();
     if (buffer is !List || offset is !int || bytes is !int) {
       throw new FileIOException(
-          "Invalid arguments to writeList for file '$_name'");
+          "Invalid arguments to writeList for file '$_path'");
     }
     if (bytes == 0) return 0;
     _checkReadWriteListArguments(buffer.length, offset, bytes);
@@ -865,7 +865,7 @@
     var result =
       _writeList(_id, bufferAndOffset.buffer, bufferAndOffset.offset, bytes);
     if (result is OSError) {
-      throw new FileIOException("writeList failed for file '$_name'", result);
+      throw new FileIOException("writeList failed for file '$_path'", result);
     }
     return result;
   }
@@ -897,13 +897,13 @@
     _ensureFileService();
     Completer<int> completer = new Completer<int>();
     if (closed) return _completeWithClosedException(completer);
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _POSITION_REQUEST;
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "position failed for file '$_name'");
+                                     "position failed for file '$_path'");
       }
       return response;
     });
@@ -915,7 +915,7 @@
     _checkNotClosed();
     var result = _position(_id);
     if (result is OSError) {
-      throw new FileIOException("position failed for file '$_name'", result);
+      throw new FileIOException("position failed for file '$_path'", result);
     }
     return result;
   }
@@ -924,14 +924,14 @@
     _ensureFileService();
     Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
     if (closed) return _completeWithClosedException(completer);
-    List request = new List.fixedLength(3);
+    List request = new List(3);
     request[0] = _SET_POSITION_REQUEST;
     request[1] = _id;
     request[2] = position;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "setPosition failed for file '$_name'");
+                                     "setPosition failed for file '$_path'");
       }
       return this;
     });
@@ -943,7 +943,7 @@
     _checkNotClosed();
     var result = _setPosition(_id, position);
     if (result is OSError) {
-      throw new FileIOException("setPosition failed for file '$_name'", result);
+      throw new FileIOException("setPosition failed for file '$_path'", result);
     }
   }
 
@@ -951,14 +951,14 @@
     _ensureFileService();
     Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
     if (closed) return _completeWithClosedException(completer);
-    List request = new List.fixedLength(3);
+    List request = new List(3);
     request[0] = _TRUNCATE_REQUEST;
     request[1] = _id;
     request[2] = length;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "truncate failed for file '$_name'");
+                                     "truncate failed for file '$_path'");
       }
       return this;
     });
@@ -970,7 +970,7 @@
     _checkNotClosed();
     var result = _truncate(_id, length);
     if (result is OSError) {
-      throw new FileIOException("truncate failed for file '$_name'", result);
+      throw new FileIOException("truncate failed for file '$_path'", result);
     }
   }
 
@@ -978,13 +978,13 @@
     _ensureFileService();
     Completer<int> completer = new Completer<int>();
     if (closed) return _completeWithClosedException(completer);
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _LENGTH_REQUEST;
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "length failed for file '$_name'");
+                                     "length failed for file '$_path'");
       }
       return response;
     });
@@ -996,7 +996,7 @@
     _checkNotClosed();
     var result = _length(_id);
     if (result is OSError) {
-      throw new FileIOException("length failed for file '$_name'", result);
+      throw new FileIOException("length failed for file '$_path'", result);
     }
     return result;
   }
@@ -1005,13 +1005,13 @@
     _ensureFileService();
     Completer<RandomAccessFile> completer = new Completer<RandomAccessFile>();
     if (closed) return _completeWithClosedException(completer);
-    List request = new List.fixedLength(2);
+    List request = new List(2);
     request[0] = _FLUSH_REQUEST;
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
-                                     "flush failed for file '$_name'");
+                                     "flush failed for file '$_path'");
       }
       return this;
     });
@@ -1023,11 +1023,11 @@
     _checkNotClosed();
     var result = _flush(_id);
     if (result is OSError) {
-      throw new FileIOException("flush failed for file '$_name'", result);
+      throw new FileIOException("flush failed for file '$_path'", result);
     }
   }
 
-  String get name => _name;
+  String get path => _path;
 
   void _ensureFileService() {
     if (_fileService == null) {
@@ -1039,19 +1039,19 @@
 
   void _checkNotClosed() {
     if (closed) {
-      throw new FileIOException("File closed '$_name'");
+      throw new FileIOException("File closed '$_path'");
     }
   }
 
   Future _completeWithClosedException(Completer completer) {
     Timer.run(() {
       completer.completeError(
-          new FileIOException("File closed '$_name'"));
+          new FileIOException("File closed '$_path'"));
     });
     return completer.future;
   }
 
-  final String _name;
+  final String _path;
   int _id;
 
   SendPort _fileService;
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 103f2be..bbe8cd5 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -15,4 +15,5 @@
  *     if (entity is File) (entity as File).readAsStringSync();
  */
 abstract class FileSystemEntity {
+  String get path;
 }
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 9c5a6fb..feaeb0e 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -61,7 +61,7 @@
   // TODO(ajohnsen): Document with example, once the stream API is final.
   // TODO(ajohnsen): Add HttpServer.secure.
   /**
-   * Start listening for HTTP requests on the specified [host] and
+   * Starts listening for HTTP requests on the specified [address] and
    * [port]. If a [port] of 0 is specified the server will choose an
    * ephemeral port. The optional argument [backlog] can be used to
    * specify the listen backlog for the underlying OS listen
@@ -73,13 +73,13 @@
       => _HttpServer.bind(address, port, backlog);
 
   /**
-   * Start listening for HTTPS requests on the specified [host] and
+   * Starts listening for HTTPS requests on the specified [address] and
    * [port]. If a [port] of 0 is specified the server will choose an
    * ephemeral port. The optional argument [backlog] can be used to
    * specify the listen backlog for the underlying OS listen
    * setup.
    *
-   * The certificate with Distinguished Name [certificate_name] is looked
+   * The certificate with Distinguished Name [certificateName] is looked
    * up in the certificate database, and is used as the server certificate.
    * if [requestClientCertificate] is true, the server will request clients
    * to authenticate with a client certificate.
@@ -97,34 +97,34 @@
                                 requestClientCertificate);
 
   /**
-   * Attach the HTTP server to an existing [:ServerSocket:]. When the
+   * Attaches the HTTP server to an existing [ServerSocket]. When the
    * [HttpServer] is closed, the [HttpServer] will just detach itself,
-   * close current connections but not close [serverSocket].
+   * closing current connections but not closing [serverSocket].
    */
   factory HttpServer.listenOn(ServerSocket serverSocket)
       => new _HttpServer.listenOn(serverSocket);
 
   /**
-   * Stop server listening. This will make the [Stream] close with a done
-   * event.
+   * Permanently stops this [HttpServer] from listening for new connections.
+   * This closes this [Stream] of [HttpRequest]s with a done event.
    */
   void close();
 
   /**
    * Returns the port that the server is listening on. This can be
-   * used to get the actual port used when a value of 0 for [port] is
-   * specified in the [listen] call.
+   * used to get the actual port used when a value of 0 for [:port:] is
+   * specified in the [bind] or [bindSecure] call.
    */
   int get port;
 
   /**
-   * Set the timeout, in seconds, for sessions of this HTTP server. Default
-   * is 20 minutes.
+   * Sets the timeout, in seconds, for sessions of this [HttpServer].
+   * The default timeout is 20 minutes.
    */
   set sessionTimeout(int timeout);
 
   /**
-   * Returns a [:HttpConnectionsInfo:] object with an overview of the
+   * Returns an [HttpConnectionsInfo] object summarizing the number of
    * current connections handled by the server.
    */
   HttpConnectionsInfo connectionsInfo();
@@ -132,7 +132,7 @@
 
 
 /**
- * Overview information of the [:HttpServer:] socket connections.
+ * Summary statistics about an [HttpServer]s current socket connections.
  */
 class HttpConnectionsInfo {
   /**
@@ -162,60 +162,64 @@
 
 /**
  * Access to the HTTP headers for requests and responses. In some
- * situations the headers will be imutable and the mutating methods
+ * situations the headers will be immutable and the mutating methods
  * will then throw exceptions.
  *
- * For all operation on HTTP headers the header name is
+ * For all operations on HTTP headers the header name is
  * case-insensitive.
  */
 abstract class HttpHeaders {
-  static const ACCEPT = "Accept";
-  static const ACCEPT_CHARSET = "Accept-Charset";
-  static const ACCEPT_ENCODING = "Accept-Encoding";
-  static const ACCEPT_LANGUAGE = "Accept-Language";
-  static const ACCEPT_RANGES = "Accept-Ranges";
-  static const AGE = "Age";
-  static const ALLOW = "Allow";
-  static const AUTHORIZATION = "Authorization";
-  static const CACHE_CONTROL = "Cache-Control";
-  static const CONNECTION = "Connection";
-  static const CONTENT_ENCODING = "Content-Encoding";
-  static const CONTENT_LANGUAGE = "Content-Language";
-  static const CONTENT_LENGTH = "Content-Length";
-  static const CONTENT_LOCATION = "Content-Location";
-  static const CONTENT_MD5 = "Content-MD5";
-  static const CONTENT_RANGE = "Content-Range";
-  static const CONTENT_TYPE = "Content-Type";
-  static const DATE = "Date";
-  static const ETAG = "ETag";
-  static const EXPECT = "Expect";
-  static const EXPIRES = "Expires";
-  static const FROM = "From";
-  static const HOST = "Host";
-  static const IF_MATCH = "If-Match";
-  static const IF_MODIFIED_SINCE = "If-Modified-Since";
-  static const IF_NONE_MATCH = "If-None-Match";
-  static const IF_RANGE = "If-Range";
-  static const IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
-  static const LAST_MODIFIED = "Last-Modified";
-  static const LOCATION = "Location";
-  static const MAX_FORWARDS = "Max-Forwards";
-  static const PRAGMA = "Pragma";
-  static const PROXY_AUTHENTICATE = "Proxy-Authenticate";
-  static const PROXY_AUTHORIZATION = "Proxy-Authorization";
-  static const RANGE = "Range";
-  static const REFERER = "Referer";
-  static const RETRY_AFTER = "Retry-After";
-  static const SERVER = "Server";
-  static const TE = "TE";
-  static const TRAILER = "Trailer";
-  static const TRANSFER_ENCODING = "Transfer-Encoding";
-  static const UPGRADE = "Upgrade";
-  static const USER_AGENT = "User-Agent";
-  static const VARY = "Vary";
-  static const VIA = "Via";
-  static const WARNING = "Warning";
-  static const WWW_AUTHENTICATE = "WWW-Authenticate";
+  static const ACCEPT = "accept";
+  static const ACCEPT_CHARSET = "accept-charset";
+  static const ACCEPT_ENCODING = "accept-encoding";
+  static const ACCEPT_LANGUAGE = "accept-language";
+  static const ACCEPT_RANGES = "accept-ranges";
+  static const AGE = "age";
+  static const ALLOW = "allow";
+  static const AUTHORIZATION = "authorization";
+  static const CACHE_CONTROL = "cache-control";
+  static const CONNECTION = "connection";
+  static const CONTENT_ENCODING = "content-encoding";
+  static const CONTENT_LANGUAGE = "content-language";
+  static const CONTENT_LENGTH = "content-length";
+  static const CONTENT_LOCATION = "content-location";
+  static const CONTENT_MD5 = "content-md5";
+  static const CONTENT_RANGE = "content-range";
+  static const CONTENT_TYPE = "content-type";
+  static const DATE = "date";
+  static const ETAG = "etag";
+  static const EXPECT = "expect";
+  static const EXPIRES = "expires";
+  static const FROM = "from";
+  static const HOST = "host";
+  static const IF_MATCH = "if-match";
+  static const IF_MODIFIED_SINCE = "if-modified-since";
+  static const IF_NONE_MATCH = "if-none-match";
+  static const IF_RANGE = "if-range";
+  static const IF_UNMODIFIED_SINCE = "if-unmodified-since";
+  static const LAST_MODIFIED = "last-modified";
+  static const LOCATION = "location";
+  static const MAX_FORWARDS = "max-forwards";
+  static const PRAGMA = "pragma";
+  static const PROXY_AUTHENTICATE = "proxy-authenticate";
+  static const PROXY_AUTHORIZATION = "proxy-authorization";
+  static const RANGE = "range";
+  static const REFERER = "referer";
+  static const RETRY_AFTER = "retry-after";
+  static const SERVER = "server";
+  static const TE = "te";
+  static const TRAILER = "trailer";
+  static const TRANSFER_ENCODING = "transfer-encoding";
+  static const UPGRADE = "upgrade";
+  static const USER_AGENT = "user-agent";
+  static const VARY = "vary";
+  static const VIA = "via";
+  static const WARNING = "warning";
+  static const WWW_AUTHENTICATE = "www-authenticate";
+
+  // Cookie headers from RFC 6265.
+  static const COOKIE = "cookie";
+  static const SET_COOKIE = "set-cookie";
 
   static const GENERAL_HEADERS = const [CACHE_CONTROL,
                                         CONNECTION,
@@ -271,13 +275,13 @@
 
   /**
    * Returns the list of values for the header named [name]. If there
-   * is no headers with the provided name [:null:] will be returned.
+   * is no header with the provided name, [:null:] will be returned.
    */
   List<String> operator[](String name);
 
   /**
-   * Convenience method for the value for a single values header. If
-   * there is no header with the provided name [:null:] will be
+   * Convenience method for the value for a single valued header. If
+   * there is no header with the provided name, [:null:] will be
    * returned. If the header has more than one value an exception is
    * thrown.
    */
@@ -286,7 +290,7 @@
   /**
    * Adds a header value. The header named [name] will have the value
    * [value] added to its list of values. Some headers are single
-   * values and for these adding a value will replace the previous
+   * valued, and for these adding a value will replace the previous
    * value. If the value is of type DateTime a HTTP date format will be
    * applied. If the value is a [:List:] each element of the list will
    * be added separately. For all other types the default [:toString:]
@@ -308,7 +312,7 @@
   void remove(String name, Object value);
 
   /**
-   * Remove all values for the specified header name. Some headers
+   * Removes all values for the specified header name. Some headers
    * have system supplied values and for these the system supplied
    * values will still be added to the collection of values for the
    * header.
@@ -316,46 +320,46 @@
   void removeAll(String name);
 
   /**
-   * Enumerate the headers applying the function [f] to each
-   * header. The header name passed in [name] will be all lower
+   * Enumerates the headers, applying the function [f] to each
+   * header. The header name passed in [:name:] will be all lower
    * case.
    */
   void forEach(void f(String name, List<String> values));
 
   /**
-   * Disable folding for the header named [name] when sending the HTTP
+   * Disables folding for the header named [name] when sending the HTTP
    * header. By default, multiple header values are folded into a
    * single header line by separating the values with commas. The
-   * Set-Cookie header has folding disabled by default.
+   * 'set-cookie' header has folding disabled by default.
    */
   void noFolding(String name);
 
   /**
    * Gets and sets the date. The value of this property will
-   * reflect the "DateTime" header.
+   * reflect the 'date' header.
    */
   DateTime date;
 
   /**
    * Gets and sets the expiry date. The value of this property will
-   * reflect the "Expires" header.
+   * reflect the 'expires' header.
    */
   DateTime expires;
 
   /**
-   * Gets and sets the 'if-modified-since' date. The value of this property will
+   * Gets and sets the "if-modified-since" date. The value of this property will
    * reflect the "if-modified-since" header.
    */
   DateTime ifModifiedSince;
 
   /**
-   * Gets and sets the host part of the "Host" header for the
+   * Gets and sets the host part of the 'host' header for the
    * connection.
    */
   String host;
 
   /**
-   * Gets and sets the port part of the "Host" header for the
+   * Gets and sets the port part of the 'host' header for the
    * connection.
    */
   int port;
@@ -367,6 +371,16 @@
    * effect.
    */
   ContentType contentType;
+
+  /**
+   * Gets and sets the content length header value.
+   */
+  int contentLength;
+
+  /**
+   * Gets and sets the persistent connection header value.
+   */
+  bool persistentConnection;
 }
 
 
@@ -378,7 +392,7 @@
  * [HeaderValue] can be used to conveniently build and parse header
  * values on this form.
  *
- * To build an [:Accepts:] header with the value
+ * To build an [:accepts:] header with the value
  *
  *     text/plain; q=0.3, text/html
  *
@@ -436,23 +450,23 @@
 
 abstract class HttpSession implements Map {
   /**
-   * Get the id for the current session.
+   * Gets the id for the current session.
    */
   String get id;
 
   /**
-   * Destroy the session. This will terminate the session and any further
+   * Destroys the session. This will terminate the session and any further
    * connections with this id will be given a new id and session.
    */
   void destroy();
 
   /**
-   * Set a callback that will be called when the session is timed out.
+   * Sets a callback that will be called when the session is timed out.
    */
   void set onTimeout(void callback());
 
   /**
-   * Is true if the session have not been sent to the client yet.
+   * Is true if the session has not been sent to the client yet.
    */
   bool get isNew;
 }
@@ -510,8 +524,8 @@
 /**
  * Representation of a cookie. For cookies received by the server as
  * Cookie header values only [:name:] and [:value:] fields will be
- * set. When building a cookie for the Set-Cookie header in the server
- * and when receiving cookies in the client as Set-Cookie headers all
+ * set. When building a cookie for the 'set-cookie' header in the server
+ * and when receiving cookies in the client as 'set-cookie' headers all
  * fields can be used.
  */
 abstract class Cookie {
@@ -521,7 +535,7 @@
   factory Cookie([String name, String value]) => new _Cookie(name, value);
 
   /**
-   * Creates a new cookie by parsing a header value from a Set-Cookie
+   * Creates a new cookie by parsing a header value from a 'set-cookie'
    * header.
    */
   factory Cookie.fromSetCookieValue(String value) {
@@ -572,7 +586,7 @@
   /**
    * Returns the formatted string representation of the cookie. The
    * string representation can be used for for setting the Cookie or
-   * Set-Cookie headers
+   * 'set-cookie' headers
    */
   String toString();
 }
@@ -629,10 +643,10 @@
   X509Certificate get certificate;
 
   /**
-   * Get the session for the given request. If the session is
+   * Gets the session for the given request. If the session is
    * being initialized by this call, [:isNew:] will be true for the returned
    * session.
-   * See [:HttpServer.sessionTimeout:] on how to change default timeout.
+   * See [HttpServer.sessionTimeout] on how to change default timeout.
    */
   HttpSession get session;
 
@@ -643,13 +657,13 @@
   String get protocolVersion;
 
   /**
-   * Get information about the client connection. Returns [null] if the socket
-   * isn't available.
+   * Gets information about the client connection. Returns [null] if the socket
+   * is not available.
    */
   HttpConnectionInfo get connectionInfo;
 
   /**
-   * Get the [HttpResponse] object, used for sending back the response to the
+   * Gets the [HttpResponse] object, used for sending back the response to the
    * client.
    */
   HttpResponse get response;
@@ -695,12 +709,12 @@
   HttpHeaders get headers;
 
   /**
-   * Cookies to set in the client (in the Set-Cookie header).
+   * Cookies to set in the client (in the 'set-cookie' header).
    */
   List<Cookie> get cookies;
 
   /**
-   * Detach the underlying socket from the HTTP server. When the
+   * Detaches the underlying socket from the HTTP server. When the
    * socket is detached the HTTP server will no longer perform any
    * operations on it.
    *
@@ -710,8 +724,8 @@
   Future<Socket> detachSocket();
 
   /**
-   * Get information about the client connection. Returns [null] if the socket
-   * isn't available.
+   * Gets information about the client connection. Returns [null] if the socket
+   * is not available.
    */
   HttpConnectionInfo get connectionInfo;
 }
@@ -734,10 +748,10 @@
 
   /**
    * Opens a HTTP connection. The returned [HttpClientRequest] is used to
-   * fill in the content of the request before sending it. The "Host" header for
+   * fill in the content of the request before sending it. The 'host' header for
    * the request will be set to the value [host]:[port]. This can be overridden
    * through the [HttpClientRequest] interface before the request is sent.
-   * NOTE if [host] is an IP address this will still be set in the "Host"
+   * NOTE if [host] is an IP address this will still be set in the 'host'
    * header.
    */
   Future<HttpClientRequest> open(String method,
@@ -747,10 +761,10 @@
 
   /**
    * Opens a HTTP connection. The returned [HttpClientRequest] is used to
-   * fill in the content of the request before sending it. The "Host" header for
+   * fill in the content of the request before sending it. The 'hosth header for
    * the request will be set to the value [host]:[port]. This can be overridden
    * through the [HttpClientRequest] interface before the request is sent.
-   * NOTE if [host] is an IP address this will still be set in the "Host"
+   * NOTE if [host] is an IP address this will still be set in the 'host'
    * header.
    */
   Future<HttpClientRequest> openUrl(String method, Uri url);
@@ -803,23 +817,6 @@
   void addCredentials(Uri url, String realm, HttpClientCredentials credentials);
 
   /**
-   * If [sendClientCertificate] is set to true, authenticate with a client
-   * certificate when connecting with an HTTPS server that requests one.
-   * Select the certificate from the certificate database that matches
-   * the authorities listed by the HTTPS server as valid.
-   * If [clientCertificate] is set, send the certificate with that nickname
-   * instead.
-   */
-  set sendClientCertificate(bool send);
-
-  /**
-   * If [clientCertificate] is non-null and [sendClientCertificate] is true,
-   * use [clientCertificate] to select the certificate to send from the
-   * certificate database, looking it up by its nickname.
-   */
-  set clientCertificate(String nickname);
-
-  /**
    * Sets the function used to resolve the proxy server to be used for
    * opening a HTTP connection to the specified [url]. If this
    * function is not set, direct connections will always be used.
@@ -882,7 +879,7 @@
   HttpHeaders get headers;
 
   /**
-   * Cookies to present to the server (in the Cookie header).
+   * Cookies to present to the server (in the 'cookie' header).
    */
   List<Cookie> get cookies;
 
@@ -894,7 +891,7 @@
 
   /**
    * A [HttpClientResponse] future that will complete once the response is
-   * available. If an error occours before the response is available, this
+   * available. If an error occurs before the response is available, this
    * future will complete with an error.
    */
   Future<HttpClientResponse> get response;
@@ -934,7 +931,7 @@
 
   /**
    * Get information about the client connection. Returns [null] if the socket
-   * isn't available.
+   * is not available.
    */
   HttpConnectionInfo get connectionInfo;
 }
@@ -944,7 +941,6 @@
  * HTTP response for a client connection. The [HttpClientResponse] is a
  * [Stream] of the body content of the response. Listen to the body to handle
  * the data and be notified once the entire body is received.
-
  */
 abstract class HttpClientResponse implements Stream<List<int>> {
   /**
@@ -958,8 +954,8 @@
   String get reasonPhrase;
 
   /**
-   * Returns the content length of the request body. If the size of
-   * the request body is not known in advance this -1.
+   * Returns the content length of the request body. Returns -1 if the size of
+   * the request body is not known in advance.
    */
   int get contentLength;
 
@@ -970,34 +966,34 @@
 
   /**
    * Returns whether the status code is one of the normal redirect
-   * codes [:HttpStatus.MOVED_PERMANENTLY:], [:HttpStatus.FOUND:],
-   * [:HttpStatus.MOVED_TEMPORARILY:], [:HttpStatus.SEE_OTHER:] and
-   * [:HttpStatus.TEMPORARY_REDIRECT:].
+   * codes [HttpStatus.MOVED_PERMANENTLY], [HttpStatus.FOUND],
+   * [HttpStatus.MOVED_TEMPORARILY], [HttpStatus.SEE_OTHER] and
+   * [HttpStatus.TEMPORARY_REDIRECT].
    */
   bool get isRedirect;
 
   /**
    * Returns the series of redirects this connection has been through. The
-   * list will be empty if no redirects was followed. [redirects] will be
+   * list will be empty if no redirects were followed. [redirects] will be
    * updated both in the case of an automatic and a manual redirect.
    */
   List<RedirectInfo> get redirects;
 
   /**
-   * Redirect this connection to a new URL. The default value for
+   * Redirects this connection to a new URL. The default value for
    * [method] is the method for the current request. The default value
-   * for [url] is the value of the [:HttpHeaders.LOCATION:] header of
+   * for [url] is the value of the [HttpHeaders.LOCATION] header of
    * the current response. All body data must have been read from the
    * current response before calling [redirect].
    *
    * All headers added to the request will be added to the redirection
-   * request(s). However, any body send with the request will not be
-   * part of the redirection request(s).
+   * request. However, any body sent with the request will not be
+   * part of the redirection request.
    *
    * If [followLoops] is set to [true], redirect will follow the redirect,
-   * even if was already visited. Default value is [false].
+   * even if the URL was already visited. The default value is [false].
    *
-   * [redirect] will ignore [maxRedirects] and always perform the redirect.
+   * [redirect] will ignore [maxRedirects] and will always perform the redirect.
    */
   Future<HttpClientResponse> redirect([String method,
                                        Uri url,
@@ -1020,7 +1016,7 @@
   Future<Socket> detachSocket();
 
   /**
-   * Cookies set by the server (from the Set-Cookie header).
+   * Cookies set by the server (from the 'set-cookie' header).
    */
   List<Cookie> get cookies;
 
@@ -1031,8 +1027,8 @@
   X509Certificate get certificate;
 
   /**
-   * Get information about the client connection. Returns [null] if the socket
-   * isn't available.
+   * Gets information about the client connection. Returns [null] if the socket
+   * is not available.
    */
   HttpConnectionInfo get connectionInfo;
 }
@@ -1042,7 +1038,7 @@
 
 
 /**
- * Represent credentials for basic authentication.
+ * Represents credentials for basic authentication.
  */
 abstract class HttpClientBasicCredentials extends HttpClientCredentials {
   factory HttpClientBasicCredentials(String username, String password) =>
@@ -1051,7 +1047,7 @@
 
 
 /**
- * Represent credentials for digest authentication.
+ * Represents credentials for digest authentication.
  */
 abstract class HttpClientDigestCredentials extends HttpClientCredentials {
   factory HttpClientDigestCredentials(String username, String password) =>
@@ -1060,7 +1056,8 @@
 
 
 /**
- * Connection information.
+ * Information about an [HttpRequest], [HttpResponse], [HttpClientRequest], or
+ * [HttpClientResponse] connection.
  */
 abstract class HttpConnectionInfo {
   String get remoteHost;
diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
index 949ace3..9d586d4 100644
--- a/sdk/lib/io/http_headers.dart
+++ b/sdk/lib/io/http_headers.dart
@@ -50,6 +50,7 @@
       if (index != -1) {
         values.removeRange(index, 1);
       }
+      if (values.length == 0) _headers.remove(name);
     }
   }
 
@@ -69,7 +70,7 @@
   }
 
   bool get persistentConnection {
-    List<String> connection = this[HttpHeaders.CONNECTION];
+    List<String> connection = _headers[HttpHeaders.CONNECTION];
     if (protocolVersion == "1.1") {
       if (connection == null) return true;
       return !connection.any((value) => value.toLowerCase() == "close");
@@ -97,9 +98,9 @@
     _checkMutable();
     _contentLength = contentLength;
     if (_contentLength >= 0) {
-      _set("content-length", contentLength.toString());
+      _set(HttpHeaders.CONTENT_LENGTH, contentLength.toString());
     } else {
-      removeAll("content-length");
+      removeAll(HttpHeaders.CONTENT_LENGTH);
     }
   }
 
@@ -108,13 +109,14 @@
   void set chunkedTransferEncoding(bool chunkedTransferEncoding) {
     _checkMutable();
     _chunkedTransferEncoding = chunkedTransferEncoding;
-    List<String> values = _headers["transfer-encoding"];
-    if (values == null || values[values.length - 1] != "chunked") {
+    List<String> values = _headers[HttpHeaders.TRANSFER_ENCODING];
+    if ((values == null || values[values.length - 1] != "chunked") &&
+        chunkedTransferEncoding) {
       // Headers does not specify chunked encoding - add it if set.
-      if (chunkedTransferEncoding) _addValue("transfer-encoding", "chunked");
-    } else {
+        _addValue(HttpHeaders.TRANSFER_ENCODING, "chunked");
+    } else if (!chunkedTransferEncoding) {
       // Headers does specify chunked encoding - remove it if not set.
-      if (!chunkedTransferEncoding) remove("transfer-encoding", "chunked");
+      remove(HttpHeaders.TRANSFER_ENCODING, "chunked");
     }
   }
 
@@ -135,7 +137,7 @@
   }
 
   DateTime get ifModifiedSince {
-    List<String> values = _headers["if-modified-since"];
+    List<String> values = _headers[HttpHeaders.IF_MODIFIED_SINCE];
     if (values != null) {
       try {
         return _HttpUtils.parseDate(values[0]);
@@ -150,11 +152,11 @@
     _checkMutable();
     // Format "ifModifiedSince" header with date in Greenwich Mean Time (GMT).
     String formatted = _HttpUtils.formatDate(ifModifiedSince.toUtc());
-    _set("if-modified-since", formatted);
+    _set(HttpHeaders.IF_MODIFIED_SINCE, formatted);
   }
 
   DateTime get date {
-    List<String> values = _headers["date"];
+    List<String> values = _headers[HttpHeaders.DATE];
     if (values != null) {
       try {
         return _HttpUtils.parseDate(values[0]);
@@ -173,7 +175,7 @@
   }
 
   DateTime get expires {
-    List<String> values = _headers["expires"];
+    List<String> values = _headers[HttpHeaders.EXPIRES];
     if (values != null) {
       try {
         return _HttpUtils.parseDate(values[0]);
@@ -188,7 +190,7 @@
     _checkMutable();
     // Format "Expires" header with date in Greenwich Mean Time (GMT).
     String formatted = _HttpUtils.formatDate(expires.toUtc());
-    _set("expires", formatted);
+    _set(HttpHeaders.EXPIRES, formatted);
   }
 
   ContentType get contentType {
@@ -202,13 +204,13 @@
 
   void set contentType(ContentType contentType) {
     _checkMutable();
-    _set("content-type", contentType.toString());
+    _set(HttpHeaders.CONTENT_TYPE, contentType.toString());
   }
 
   void _add(String name, Object value) {
     var lowerCaseName = name.toLowerCase();
     // TODO(sgjesse): Add immutable state throw HttpException is immutable.
-    if (lowerCaseName == "content-length") {
+    if (lowerCaseName == HttpHeaders.CONTENT_LENGTH) {
       if (value is int) {
         contentLength = value;
       } else if (value is String) {
@@ -216,37 +218,37 @@
       } else {
         throw new HttpException("Unexpected type for header named $name");
       }
-    } else if (lowerCaseName == "transfer-encoding") {
+    } else if (lowerCaseName == HttpHeaders.TRANSFER_ENCODING) {
       if (value == "chunked") {
         chunkedTransferEncoding = true;
       } else {
         _addValue(lowerCaseName, value);
       }
-    } else if (lowerCaseName == "date") {
+    } else if (lowerCaseName == HttpHeaders.DATE) {
       if (value is DateTime) {
         date = value;
       } else if (value is String) {
-        _set("date", value);
+        _set(HttpHeaders.DATE, value);
       } else {
         throw new HttpException("Unexpected type for header named $name");
       }
-    } else if (lowerCaseName == "expires") {
+    } else if (lowerCaseName == HttpHeaders.EXPIRES) {
       if (value is DateTime) {
         expires = value;
       } else if (value is String) {
-        _set("expires", value);
+        _set(HttpHeaders.EXPIRES, value);
       } else {
         throw new HttpException("Unexpected type for header named $name");
       }
-    } else if (lowerCaseName == "if-modified-since") {
+    } else if (lowerCaseName == HttpHeaders.IF_MODIFIED_SINCE) {
       if (value is DateTime) {
         ifModifiedSince = value;
       } else if (value is String) {
-        _set("if-modified-since", value);
+        _set(HttpHeaders.IF_MODIFIED_SINCE, value);
       } else {
         throw new HttpException("Unexpected type for header named $name");
       }
-    } else if (lowerCaseName == "host") {
+    } else if (lowerCaseName == HttpHeaders.HOST) {
       if (value is String) {
         int pos = (value as String).indexOf(":");
         if (pos == -1) {
@@ -268,12 +270,12 @@
             }
           }
         }
-        _set("host", value);
+        _set(HttpHeaders.HOST, value);
       } else {
         throw new HttpException("Unexpected type for header named $name");
       }
-    } else if (lowerCaseName == "content-type") {
-      _set("content-type", value);
+    } else if (lowerCaseName == HttpHeaders.CONTENT_TYPE) {
+      _set(HttpHeaders.CONTENT_TYPE, value);
     } else {
         _addValue(lowerCaseName, value);
     }
@@ -310,7 +312,7 @@
   }
 
   _foldHeader(String name) {
-    if (name == "set-cookie" ||
+    if (name == HttpHeaders.SET_COOKIE ||
         (_noFoldingHeaders != null &&
          _noFoldingHeaders.indexOf(name) != -1)) {
       return false;
@@ -321,8 +323,12 @@
   void _finalize() {
     // If the content length is not known make sure chunked transfer
     // encoding is used for HTTP 1.1.
-    if (contentLength < 0 && protocolVersion == "1.1") {
-      chunkedTransferEncoding = true;
+    if (contentLength < 0) {
+      if (protocolVersion == "1.0") {
+        persistentConnection = false;
+      } else {
+        chunkedTransferEncoding = true;
+      }
     }
     // If a Transfer-Encoding header field is present the
     // Content-Length header MUST NOT be sent (RFC 2616 section 4.4).
@@ -352,7 +358,7 @@
     _headers.forEach((String name, List<String> values) {
       bool fold = _foldHeader(name);
       List<int> nameData;
-      nameData = name.charCodes;
+      nameData = name.codeUnits;
       int nameDataLen = nameData.length;
       if (nameDataLen + 2 > bufferSize - bufferPos) writeBuffer();
       buffer.setRange(bufferPos, nameDataLen, nameData);
@@ -360,7 +366,7 @@
       buffer[bufferPos++] = _CharCode.COLON;
       buffer[bufferPos++] = _CharCode.SP;
       for (int i = 0; i < values.length; i++) {
-        List<int> data = values[i].charCodes;
+        List<int> data = values[i].codeUnits;
         int dataLen = data.length;
         // Worst case here is writing the name, value and 6 additional bytes.
         if (nameDataLen + dataLen + 6 > bufferSize - bufferPos) writeBuffer();
@@ -466,7 +472,7 @@
         expect(";");
       }
     }
-    List<String> values = this["cookie"];
+    List<String> values = _headers[HttpHeaders.COOKIE];
     if (values != null) {
       values.forEach((headerValue) => parseCookieString(headerValue));
     }
@@ -659,11 +665,11 @@
   _Cookie([String this.name, String this.value]);
 
   _Cookie.fromSetCookieValue(String value) {
-    // Parse the Set-Cookie header value.
+    // Parse the 'set-cookie' header value.
     _parseSetCookieValue(value);
   }
 
-  // Parse a Set-Cookie header value according to the rules in RFC 6265.
+  // Parse a 'set-cookie' header value according to the rules in RFC 6265.
   void _parseSetCookieValue(String s) {
     int index = 0;
 
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 8bc8a98..31099cc 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -4,8 +4,7 @@
 
 part of dart.io;
 
-class _HttpIncoming
-    extends Stream<List<int>> implements StreamSink<List<int>> {
+class _HttpIncoming extends Stream<List<int>> {
   final int _transferLength;
   final Completer _dataCompleter = new Completer();
   Stream<List<int>> _stream;
@@ -54,7 +53,7 @@
   }
 }
 
-class _HttpInboundMessage extends Stream<List<int>> {
+abstract class _HttpInboundMessage extends Stream<List<int>> {
   final _HttpIncoming _incoming;
   List<Cookie> _cookies;
 
@@ -65,7 +64,7 @@
     return _cookies = headers._parseCookies();
   }
 
-  HttpHeaders get headers => _incoming.headers;
+  _HttpHeaders get headers => _incoming.headers;
   String get protocolVersion => headers.protocolVersion;
   int get contentLength => headers.contentLength;
   bool get persistentConnection => headers.persistentConnection;
@@ -82,7 +81,7 @@
 
   final _HttpConnection _httpConnection;
 
-  HttpSession _session;
+  _HttpSession _session;
 
   _HttpRequest(_HttpResponse this.response,
                _HttpIncoming _incoming,
@@ -167,10 +166,15 @@
   int get statusCode => _incoming.statusCode;
   String get reasonPhrase => _incoming.reasonPhrase;
 
+  X509Certificate get certificate {
+    var socket = _httpRequest._httpClientConnection._socket;
+    return socket.peerCertificate;
+  }
+
   List<Cookie> get cookies {
     if (_cookies != null) return _cookies;
     _cookies = new List<Cookie>();
-    List<String> values = headers["set-cookie"];
+    List<String> values = headers[HttpHeaders.SET_COOKIE];
     if (values != null) {
       values.forEach((value) {
         _cookies.add(new Cookie.fromSetCookieValue(value));
@@ -314,14 +318,21 @@
 }
 
 
-class _HttpOutboundMessage<T> extends IOSink {
+abstract class _HttpOutboundMessage<T> implements IOSink {
   // Used to mark when the body should be written. This is used for HEAD
   // requests and in error handling.
   bool _ignoreBody = false;
+  bool _headersWritten = false;
+  bool _chunked = false;
+
+  final IOSink _ioSink;
+  final _HttpOutgoing _outgoing;
+
+  final _HttpHeaders headers;
 
   _HttpOutboundMessage(String protocolVersion, _HttpOutgoing outgoing)
-      : super(outgoing),
-        _outgoing = outgoing,
+      : _outgoing = outgoing,
+        _ioSink = new IOSink(outgoing),
         headers = new _HttpHeaders(protocolVersion);
 
   int get contentLength => headers.contentLength;
@@ -330,7 +341,7 @@
   }
 
   bool get persistentConnection => headers.persistentConnection;
-  bool set persistentConnection(bool p) {
+  void set persistentConnection(bool p) {
     headers.persistentConnection = p;
   }
 
@@ -341,19 +352,33 @@
       // Transform when chunked.
       stream = stream.transform(new _ChunkedTransformer());
     }
-    return super.consume(stream).then((_) => this);
+    return _ioSink.consume(stream).then((_) => this);
   }
 
   void add(List<int> data) {
     _writeHeaders();
-    if (_ignoreBody) return;
+    if (_ignoreBody || data.length == 0) return;
     if (_chunked) {
-      _ChunkedTransformer._addChunk(data, super.add);
+      _ChunkedTransformer._addChunk(data, _ioSink.add);
     } else {
-      super.add(data);
+      _ioSink.add(data);
     }
   }
 
+  void addString(String string, [Encoding encoding = Encoding.UTF_8]) {
+    add(_encodeString(string, encoding));
+  }
+
+  Future<T> addStream(Stream<List<int>> stream) {
+    _writeHeaders();
+    if (_ignoreBody) return new Future.immediate(this);
+    if (_chunked) {
+      // Transform when chunked.
+      stream = stream.transform(new _ChunkedTransformer(writeEnd: false));
+    }
+    return _ioSink.addStream(stream).then((_) => this);
+  }
+
   void close() {
     if (!_headersWritten && !_ignoreBody && headers.chunkedTransferEncoding) {
       // If no body was written, _ignoreBody is false (it's not a HEAD
@@ -363,12 +388,14 @@
     _writeHeaders();
     if (!_ignoreBody) {
       if (_chunked) {
-        _ChunkedTransformer._addChunk([], super.add);
+        _ChunkedTransformer._addChunk([], _ioSink.add);
       }
     }
-    super.close();
+    _ioSink.close();
   }
 
+  Future<T> get done => _ioSink.done.then((_) => this);
+
   void _writeHeaders() {
     if (_headersWritten) return;
     bool _tmpIgnoreBody = _ignoreBody;
@@ -377,22 +404,16 @@
     _writeHeader();
     _ignoreBody = _tmpIgnoreBody;
     if (_ignoreBody) {
-      super.close();
+      _ioSink.close();
       return;
     }
     _chunked = headers.chunkedTransferEncoding;
-    if (!_chunked) {
+    if (headers.contentLength >= 0) {
       _outgoing.setTransferLength(headers.contentLength);
     }
   }
 
   void _writeHeader();  // TODO(ajohnsen): Better name.
-
-  final _HttpHeaders headers;
-
-  final _HttpOutgoing _outgoing;
-  bool _headersWritten = false;
-  bool _chunked = false;
 }
 
 
@@ -466,7 +487,7 @@
     // Add all the cookies set to the headers.
     if (_cookies != null) {
       _cookies.forEach((cookie) {
-        headers.add("set-cookie", cookie);
+        headers.add(HttpHeaders.SET_COOKIE, cookie);
       });
     }
 
@@ -657,7 +678,7 @@
         sb.add("=");
         sb.add(cookies[i].value);
       }
-      headers.add("cookie", sb.toString());
+      headers.add(HttpHeaders.COOKIE, sb.toString());
     }
 
     headers._finalize();
@@ -670,21 +691,19 @@
 
 
 // Transformer that transforms data to HTTP Chunked Encoding.
-class _ChunkedTransformer implements StreamTransformer<List<int>, List<int>> {
-  final StreamController<List<int>> _controller
-      = new StreamController<List<int>>();
+class _ChunkedTransformer extends StreamEventTransformer<List<int>, List<int>> {
+  final bool writeEnd;
+  _ChunkedTransformer({this.writeEnd: true});
 
-  Stream<List<int>> bind(Stream<List<int>> stream) {
-    var subscription = stream.listen(
-        (data) {
-          if (data.length == 0) return;  // Avoid close on 0-bytes payload.
-          _addChunk(data, _controller.add);
-       },
-       onDone: () {
-          _addChunk([], _controller.add);
-          _controller.close();
-       });
-    return _controller.stream;
+  void handleData(List<int> data, StreamSink<List<int>> sink) {
+    _addChunk(data, sink.add);
+  }
+
+  void handleDone(StreamSink<List<int>> sink) {
+    if (writeEnd) {
+      _addChunk([], sink.add);
+    }
+    sink.close();
   }
 
   static void _addChunk(List<int> data, void add(List<int> data)) {
@@ -738,17 +757,12 @@
 // Transformer that validates the data written.
 class _DataValidatorTransformer
     implements StreamTransformer<List<int>, List<int>> {
-  final StreamController<List<int>> _controller
-      = new StreamController<List<int>>();
+  final StreamController<List<int>> _controller =
+      new StreamController<List<int>>();
   int _bytesWritten = 0;
-  Completer _completer = new Completer();
 
   int expectedTransferLength;
 
-  _DataValidatorTransformer();
-
-  Future get validatorFuture => _completer.future;
-
   Stream<List<int>> bind(Stream<List<int>> stream) {
     var subscription;
     subscription = stream.listen(
@@ -756,45 +770,31 @@
           if (expectedTransferLength != null) {
             _bytesWritten += data.length;
             if (_bytesWritten > expectedTransferLength) {
-              _controller.close();
               subscription.cancel();
-              if (_completer != null) {
-                _completer.completeError(new HttpException(
-                    "Content size exceeds specified contentLength. "
-                    "$_bytesWritten bytes written while expected "
-                    "$expectedTransferLength."));
-                _completer = null;
-              }
+              _controller.signalError(new HttpException(
+                  "Content size exceeds specified contentLength. "
+                  "$_bytesWritten bytes written while expected "
+                  "$expectedTransferLength."));
+              _controller.close();
               return;
             }
           }
           _controller.add(data);
         },
         onError: (error) {
+          _controller.signalError(error);
           _controller.close();
-          if (_completer != null) {
-            _completer.completeError(error);
-            _completer = null;
-          }
         },
         onDone: () {
-          _controller.close();
           if (expectedTransferLength != null) {
             if (_bytesWritten < expectedTransferLength) {
-              if (_completer != null) {
-                _completer.completeError(new HttpException(
-                    "Content size below specified contentLength. "
-                    " $_bytesWritten bytes written while expected "
-                    "$expectedTransferLength."));
-                _completer = null;
-                return;
-              }
+              _controller.signalError(new HttpException(
+                  "Content size below specified contentLength. "
+                  " $_bytesWritten bytes written while expected "
+                  "$expectedTransferLength."));
             }
           }
-          if (_completer != null) {
-            _completer.complete(this);
-            _completer = null;
-          }
+          _controller.close();
         },
         unsubscribeOnError: true);
     return _controller.stream;
@@ -803,31 +803,25 @@
 
 // Extends StreamConsumer as this is an internal type, only used to pipe to.
 class _HttpOutgoing implements StreamConsumer<List<int>, dynamic> {
-  final Completer _dataCompleter = new Completer();
-  final Completer _streamCompleter = new Completer();
   final _DataValidatorTransformer _validator = new _DataValidatorTransformer();
+  Function _onStream;
+  final Completer _consumeCompleter = new Completer();
 
-  // Future that completes when all data is written.
-  Future get dataDone => _dataCompleter.future;
-
-  // Future that completes with the Stream, once the _HttpClientConnection is
-  // bound to one.
-  Future<Stream<List<int>>> get stream => _streamCompleter.future;
+  Future onStream(Future callback(Stream<List<int>> stream)) {
+    _onStream = callback;
+    return _consumeCompleter.future;
+  }
 
   void setTransferLength(int transferLength) {
     _validator.expectedTransferLength = transferLength;
   }
 
   Future consume(Stream<List<int>> stream) {
-    stream = stream.transform(_validator);
-    _streamCompleter.complete(stream);
-    _validator.validatorFuture.catchError((e) {
-      _dataCompleter.completeError(e);
-    });
-    return _validator.validatorFuture.then((v) {
-      _dataCompleter.complete();
-      return v;
-    });
+    _onStream(stream.transform(_validator))
+        .then((_) => _consumeCompleter.complete(),
+              onError: _consumeCompleter.completeError);
+    // Use .then to ensure a Future branch.
+    return _consumeCompleter.future.then((_) => this);
   }
 }
 
@@ -840,7 +834,7 @@
   final _HttpClient _httpClient;
 
   Completer<_HttpIncoming> _nextResponseCompleter;
-  Future _writeDoneFuture;
+  Future _streamFuture;
 
   _HttpClientConnection(String this.key,
                         Socket this._socket,
@@ -858,11 +852,14 @@
           _subscription.pause();
           // We assume the response is not here, until we have send the request.
           assert(_nextResponseCompleter != null);
-          _nextResponseCompleter.complete(incoming);
+          var completer = _nextResponseCompleter;
+          _nextResponseCompleter = null;
+          completer.complete(incoming);
         },
         onError: (error) {
           if (_nextResponseCompleter != null) {
             _nextResponseCompleter.completeError(error);
+            _nextResponseCompleter = null;
           }
         },
         onDone: () {
@@ -870,37 +867,66 @@
         });
   }
 
-  Future<_HttpIncoming> sendRequest(_HttpOutgoing outgoing) {
-    return outgoing.stream
-      .then((stream) {
-        // Close socket if output data is invalid.
-        outgoing.dataDone.catchError((e) {
-          close();
-        });
+  _HttpClientRequest send(Uri uri, int port, String method, bool isDirect) {
+    // Start with pausing the parser.
+    _subscription.pause();
+    var outgoing = new _HttpOutgoing();
+    // Create new request object, wrapping the outgoing connection.
+    var request = new _HttpClientRequest(outgoing,
+                                         uri,
+                                         method,
+                                         !isDirect,
+                                         _httpClient,
+                                         this);
+    request.headers.host = uri.domain;
+    request.headers.port = port;
+    if (uri.userInfo != null && !uri.userInfo.isEmpty) {
+      // If the URL contains user information use that for basic
+      // authorization
+      String auth =
+          CryptoUtils.bytesToBase64(_encodeString(uri.userInfo));
+      request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
+    } else {
+      // Look for credentials.
+      _Credentials cr = _httpClient._findCredentials(uri);
+      if (cr != null) {
+        cr.authorize(request);
+      }
+    }
+    // Start sending the request (lazy, delayed until the user provides
+    // data).
+    _httpParser.responseToMethod = method;
+    _streamFuture = outgoing.onStream((stream) {
         // Sending request, set up response completer.
         _nextResponseCompleter = new Completer();
-        _writeDoneFuture = _socket.addStream(stream);
+
+        var requestFuture = _socket.addStream(stream)
+            .catchError((e) {
+              destroy();
+              throw e;
+            });
+
         // Listen for response.
-        return _nextResponseCompleter.future
-            .whenComplete(() {
-               _nextResponseCompleter = null;
-             })
+        _nextResponseCompleter.future
             .then((incoming) {
               incoming.dataDone.then((_) {
-                if (!incoming.headers.persistentConnection) {
-                  close();
+                if (incoming.headers.persistentConnection &&
+                    request.persistentConnection) {
+                  // Be sure we have written the full request.
+                  requestFuture
+                      .then((_) {
+                        // Return connection, now we are done.
+                        _httpClient._returnConnection(this);
+                        _subscription.resume();
+                      },
+                      onError: (_) {
+                        // Already handled.
+                      });
                 } else {
-                  // Wait for the socket to be done with writing, before we
-                  // continue.
-                  _writeDoneFuture.then((_) {
-                    _subscription.resume();
-                    // Return connection, now we are done.
-                    _httpClient._returnConnection(this);
-                  });
+                  destroy();
                 }
               });
-              // TODO(ajohnsen): Can there be an error on dataDone?
-              return incoming;
+              request._onIncoming(incoming);
             })
             // If we see a state error, we failed to get the 'first' element.
             // Transform the error to a HttpParserException, for consistency.
@@ -911,32 +937,32 @@
             .catchError((error) {
               // We are done with the socket.
               destroy();
-              throw error;
+              request._onError(error);
             });
-        });
+        // Resume the parser now we have a handler.
+        _subscription.resume();
+        return requestFuture;
+    });
+    return request;
   }
 
   Future<Socket> detachSocket() {
-    return _writeDoneFuture.then((_) =>
-        new _DetachedSocket(_socket, _httpParser.detachIncoming()));
+    return _streamFuture
+        .then((_) => new _DetachedSocket(_socket, _httpParser.detachIncoming()),
+              onError: (_) {});
   }
 
   void destroy() {
-    _socket.destroy();
     _httpClient._connectionClosed(this);
+    _socket.destroy();
   }
 
   void close() {
-    var future = _writeDoneFuture;
-    if (future == null) future = new Future.immediate(null);
     _httpClient._connectionClosed(this);
-    future.then((_) {
-      _socket.close();
-      // TODO(ajohnsen): Add timeout.
-      // Delay destroy until socket is actually done writing.
-      _socket.done.then((_) => _socket.destroy(),
-                        onError: (_) => _socket.destroy());
-    });
+    _streamFuture
+          // TODO(ajohnsen): Add timeout.
+        .then((_) => _socket.destroy(),
+              onError: (_) {});
   }
 
   HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket);
@@ -1055,55 +1081,19 @@
         return new Future.immediateError(error, stackTrace);
       }
     }
-    return _getConnection(uri.domain, port, proxyConf, isSecure).then((info) {
-          // Create new internal outgoing connection.
-          var outgoing = new _HttpOutgoing();
-          // Create new request object, wrapping the outgoing connection.
-          var request = new _HttpClientRequest(outgoing,
-                                               uri,
-                                               method.toUpperCase(),
-                                               !info.proxy.isDirect,
-                                               this,
-                                               info.connection);
-          request.headers.host = uri.domain;
-          request.headers.port = port;
-          if (uri.userInfo != null && !uri.userInfo.isEmpty) {
-            // If the URL contains user information use that for basic
-            // authorization
-            String auth =
-                CryptoUtils.bytesToBase64(_encodeString(uri.userInfo));
-            request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
-          } else {
-            // Look for credentials.
-            _Credentials cr = _findCredentials(uri);
-            if (cr != null) {
-              cr.authorize(request);
-            }
-          }
-          // Start sending the request (lazy, delayed until the user provides
-          // data).
-          info.connection._httpParser.responseToMethod = method;
-          info.connection.sendRequest(outgoing)
-              .then((incoming) {
-                // The full request have been sent and a response is received
-                // containing status-code, headers and etc.
-                request._onIncoming(incoming);
-              })
-              .catchError((error) {
-                // An error occoured before the http-header was parsed. This
-                // could be either a socket-error or parser-error.
-                request._onError(error);
-              });
-          // Return the request to the user. Immediate socket errors are not
-          // handled, thus forwarded to the user.
-          return request;
+    return _getConnection(uri.domain, port, proxyConf, isSecure)
+        .then((info) {
+          return info.connection.send(uri,
+                                      port,
+                                      method.toUpperCase(),
+                                      info.proxy.isDirect);
         });
   }
 
   Future<HttpClientRequest> _openUrlFromRequest(String method,
                                                 Uri uri,
                                                 _HttpClientRequest previous) {
-    return openUrl(method, uri).then((request) {
+    return openUrl(method, uri).then((_HttpClientRequest request) {
           // Only follow redirects if initial request did.
           request.followRedirects = previous.followRedirects;
           // Allow same number of redirects.
@@ -1220,7 +1210,7 @@
   final _HttpParser _httpParser;
   StreamSubscription _subscription;
 
-  Future _writeDoneFuture;
+  Future _streamFuture;
 
   _HttpConnection(Socket this._socket, _HttpServer this._httpServer)
       : _httpParser = new _HttpParser.requestParser() {
@@ -1233,37 +1223,37 @@
           _subscription.pause();
           _state = _ACTIVE;
           var outgoing = new _HttpOutgoing();
-          _writeDoneFuture = outgoing.stream.then(_socket.addStream);
-          var response = new _HttpResponse(
-              incoming.headers.protocolVersion,
-              outgoing);
+          var response = new _HttpResponse(incoming.headers.protocolVersion,
+                                           outgoing);
           var request = new _HttpRequest(response, incoming, _httpServer, this);
+          outgoing.onStream((stream) {
+            return _streamFuture = _socket.addStream(stream)
+                .then((_) {
+                  if (_state == _DETACHED) return;
+                  if (response.persistentConnection &&
+                      request.persistentConnection &&
+                      incoming.fullBodyRead) {
+                    _state = _IDLE;
+                    // Resume the subscription for incoming requests as the
+                    // request is now processed.
+                    _subscription.resume();
+                  } else {
+                    // Close socket, keep-alive not used or body sent before
+                    // received data was handled.
+                    destroy();
+                  }
+                })
+                .catchError((e) {
+                  destroy();
+                  throw e;
+                });
+          });
           response._ignoreBody = request.method == "HEAD";
           response._httpRequest = request;
-          outgoing.dataDone.then((_) {
-            if (_state == _DETACHED) return;
-            if (response.headers.persistentConnection &&
-                incoming.fullBodyRead) {
-              // Wait for the socket to be done with writing, before we
-              // continue.
-              _writeDoneFuture.then((_) {
-                _state = _IDLE;
-                // Resume the subscription for incoming requests as the
-                // request is now processed.
-                _subscription.resume();
-              });
-            } else {
-              // Close socket, keep-alive not used or body sent before received
-              // data was handled.
-              close();
-            }
-          }).catchError((e) {
-            close();
-          });
           _httpServer._handleRequest(request);
         },
         onDone: () {
-          close();
+          destroy();
         },
         onError: (error) {
           _httpServer._handleError(error);
@@ -1278,21 +1268,6 @@
     _httpServer._connectionClosed(this);
   }
 
-  void close() {
-    if (_state == _CLOSING || _state == _DETACHED) return;
-    _state = _CLOSING;
-    var future = _writeDoneFuture;
-    if (future == null) future = new Future.immediate(null);
-    _httpServer._connectionClosed(this);
-    future.then((_) {
-      _socket.close();
-      // TODO(ajohnsen): Add timeout.
-      // Delay destroy until socket is actually done writing.
-      _socket.done.then((_) => _socket.destroy(),
-                        onError: (_) => _socket.destroy());
-    });
-  }
-
   Future<Socket> detachSocket() {
     _state = _DETACHED;
     // Remove connection from server.
@@ -1300,7 +1275,7 @@
 
     _HttpDetachedIncoming detachedIncoming = _httpParser.detachIncoming();
 
-    return _writeDoneFuture.then((_) {
+    return _streamFuture.then((_) {
       return new _DetachedSocket(_socket, detachedIncoming);
     });
   }
@@ -1517,7 +1492,7 @@
 }
 
 
-class _DetachedSocket implements Socket {
+class _DetachedSocket extends Stream<List<int>> implements Socket {
   final Stream<List<int>> _incoming;
   final Socket _socket;
 
@@ -1547,7 +1522,11 @@
 
   void destroy() => _socket.destroy();
   void add(List<int> data) => _socket.add(data);
-  Future<Socket> close() => _socket.close();
+  void close() => _socket.close();
+  Future<Socket> get done => _socket.done;
+  int get port => _socket.port;
+  String get remoteHost => _socket.remoteHost;
+  int get remotePort => _socket.remotePort;
 }
 
 
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index 7dc258e..68fbc32 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -108,12 +108,18 @@
     controller = new StreamController<List<int>>(
         onSubscriptionStateChange: onSubscriptionStateChange,
         onPauseStateChange: onPauseStateChange);
-    pause();
-    if (oldResumeCompleter != null) oldResumeCompleter.complete();
-    subscription.resume();
-    subscription.onData(controller.add);
-    subscription.onDone(controller.close);
-    subscription.onError(controller.signalError);
+    if (subscription == null) {
+      // Socket was already closed.
+      if (carryOverData != null) controller.add(carryOverData);
+      controller.close();
+    } else {
+      pause();
+      if (oldResumeCompleter != null) oldResumeCompleter.complete();
+      subscription.resume();
+      subscription.onData(controller.add);
+      subscription.onDone(controller.close);
+      subscription.onError(controller.signalError);
+    }
   }
 
   StreamSubscription<List<int>> listen(void onData(List<int> event),
@@ -209,7 +215,7 @@
   }
 
 
-  StreamSubscription<_HttpIncoming> listen(void onData(List<int> event),
+  StreamSubscription<_HttpIncoming> listen(void onData(_HttpIncoming event),
                                            {void onError(AsyncError error),
                                             void onDone(),
                                             bool unsubscribeOnError}) {
@@ -840,9 +846,9 @@
   }
 
   int _toLowerCase(int byte) {
-    final int aCode = "A".charCodeAt(0);
-    final int zCode = "Z".charCodeAt(0);
-    final int delta = "a".charCodeAt(0) - aCode;
+    final int aCode = "A".codeUnitAt(0);
+    final int zCode = "Z".codeUnitAt(0);
+    final int delta = "a".codeUnitAt(0) - aCode;
     return (aCode <= byte && byte <= zCode) ? byte + delta : byte;
   }
 
@@ -868,7 +874,7 @@
     assert(_incoming == null);
     assert(_bodyController == null);
     _bodyController = new StreamController<List<int>>(
-        onSubscriptionStateChange: _updateParsePauseState,
+        onSubscriptionStateChange: _bodySubscriptionStateChange,
         onPauseStateChange: _updateParsePauseState);
     _incoming = new _HttpIncoming(
         _headers, transferLength, _bodyController.stream);
@@ -896,6 +902,14 @@
     _paused = true;
   }
 
+  void _bodySubscriptionStateChange() {
+    if (_incoming != null && !_bodyController.hasSubscribers) {
+      _closeIncoming();
+    } else {
+      _updateParsePauseState();
+    }
+  }
+
   void _updateParsePauseState() {
     if (_bodyController != null) {
       if (_bodyController.hasSubscribers && !_bodyController.isPaused) {
diff --git a/sdk/lib/io/http_utils.dart b/sdk/lib/io/http_utils.dart
index a68f08f..8fe62ed 100644
--- a/sdk/lib/io/http_utils.dart
+++ b/sdk/lib/io/http_utils.dart
@@ -18,7 +18,7 @@
 
     // Start decoding from the first encoded character.
     List<int> bytes = new List<int>();
-    for (int i = 0; i < index; i++) bytes.add(urlEncoded.charCodeAt(i));
+    for (int i = 0; i < index; i++) bytes.add(urlEncoded.codeUnitAt(i));
     for (int i = index; i < urlEncoded.length; i++) {
       if (urlEncoded[i] == "+") {
         bytes.add(32);
@@ -28,7 +28,7 @@
         }
         int byte = 0;
         for (int j = 0; j < 2; j++) {
-          var charCode = urlEncoded.charCodeAt(i + j + 1);
+          var charCode = urlEncoded.codeUnitAt(i + j + 1);
           if (0x30 <= charCode && charCode <= 0x39) {
             byte = byte * 16 + charCode - 0x30;
           } else {
@@ -44,7 +44,7 @@
         bytes.add(byte);
         i += 2;
       } else {
-        bytes.add(urlEncoded.charCodeAt(i));
+        bytes.add(urlEncoded.codeUnitAt(i));
       }
     }
     return decodeUtf8(bytes);
@@ -229,7 +229,7 @@
     int seconds;
     if (format == formatAsctime) {
       month = expectMonth(" ");
-      if (date.charCodeAt(index) == SP) index++;
+      if (date.codeUnitAt(index) == SP) index++;
       day = expectNum(" ");
       hours = expectNum(":");
       minutes = expectNum(":");
@@ -265,7 +265,7 @@
     }
 
     bool isDelimiter(String s) {
-      int char = s.charCodeAt(0);
+      int char = s.codeUnitAt(0);
       if (char == 0x09) return true;
       if (char >= 0x20 && char <= 0x2F) return true;
       if (char >= 0x3B && char <= 0x40) return true;
@@ -275,7 +275,7 @@
     }
 
     bool isNonDelimiter(String s) {
-      int char = s.charCodeAt(0);
+      int char = s.codeUnitAt(0);
       if (char >= 0x00 && char <= 0x08) return true;
       if (char >= 0x0A && char <= 0x1F) return true;
       if (char >= 0x30 && char <= 0x39) return true;  // Digit
@@ -287,7 +287,7 @@
     }
 
     bool isDigit(String s) {
-      int char = s.charCodeAt(0);
+      int char = s.codeUnitAt(0);
       if (char > 0x2F && char < 0x3A) return true;
       return false;
     }
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index b7d2843..0ff9b24 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -38,7 +38,7 @@
 part 'http_parser.dart';
 part 'http_session.dart';
 part 'http_utils.dart';
-part 'io_stream_consumer.dart';
+part 'io_sink.dart';
 part 'mime_multipart_parser.dart';
 part 'path.dart';
 part 'path_impl.dart';
diff --git a/sdk/lib/io/io_stream_consumer.dart b/sdk/lib/io/io_sink.dart
similarity index 76%
rename from sdk/lib/io/io_stream_consumer.dart
rename to sdk/lib/io/io_sink.dart
index 51b59ab..ace6f92 100644
--- a/sdk/lib/io/io_stream_consumer.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -10,11 +10,48 @@
  * buffers the input given by [add] and [addString] and will delay a [consume]
  * or [addStream] until the buffer is flushed.
  *
- * When the [IOSink] is bound to a stream (through either [comsume]
+ * When the [IOSink] is bound to a stream (through either [consume]
  * or [addStream]) any call to the [IOSink] will throw a
  * [StateError].
  */
-class IOSink<T> implements StreamConsumer<List<int>, T> {
+abstract class IOSink<T> implements StreamConsumer<List<int>, T> {
+  factory IOSink(StreamConsumer<List<int>, T> target)
+      => new _IOSinkImpl(target);
+
+  /**
+   * Provide functionality for piping to the [IOSink].
+   */
+  Future<T> consume(Stream<List<int>> stream);
+
+  /**
+   * Like [consume], but will not close the target when done.
+   */
+  Future<T> addStream(Stream<List<int>> stream);
+
+  /**
+   * Write a list of bytes to the target.
+   */
+  void add(List<int> data);
+
+  /**
+   * Write a String to the target.
+   */
+  void addString(String string, [Encoding encoding = Encoding.UTF_8]);
+
+  /**
+   * Close the target.
+   */
+  void close();
+
+  /**
+   * Get future that will complete when all data has been written to
+   * the IOSink and it has been closed.
+   */
+  Future<T> get done;
+}
+
+
+class _IOSinkImpl<T> implements IOSink<T> {
   final StreamConsumer<List<int>, T> _target;
 
   StreamController<List<int>> _controllerInstance;
@@ -22,11 +59,8 @@
   StreamSubscription<List<int>> _bindSubscription;
   bool _paused = true;
 
-  IOSink(StreamConsumer<List<int>, T> target) : _target = target;
+  _IOSinkImpl(StreamConsumer<List<int>, T> target) : _target = target;
 
-  /**
-   * Provide functionality for piping to the [IOSink].
-   */
   Future<T> consume(Stream<List<int>> stream) {
     if (_isBound) {
       throw new StateError("IOSink is already bound to a stream");
@@ -34,9 +68,6 @@
     return _fillFromStream(stream);
   }
 
-  /**
-   * Like [consume], but will not close the target when done.
-   */
   Future<T> addStream(Stream<List<int>> stream) {
     if (_isBound) {
       throw new StateError("IOSink is already bound to a stream");
@@ -44,9 +75,6 @@
     return _fillFromStream(stream, unbind: true);
   }
 
-  /**
-   * Write a list of bytes to the target.
-   */
   void add(List<int> data) {
     if (_isBound) {
       throw new StateError("IOSink is already bound to a stream");
@@ -54,16 +82,10 @@
     _controller.add(data);
   }
 
-  /**
-   * Write a String to the target.
-   */
   void addString(String string, [Encoding encoding = Encoding.UTF_8]) {
     add(_encodeString(string, encoding));
   }
 
-  /**
-   * Close the target.
-   */
   void close() {
     if (_isBound) {
       throw new StateError("IOSink is already bound to a stream");
@@ -71,10 +93,6 @@
     _controller.close();
   }
 
-  /**
-   * Get future that will complete when all data has been written to
-   * the IOSink and it has been closed.
-   */
   Future<T> get done {
     _controller;
     return _pipeFuture.then((_) => this);
@@ -85,7 +103,7 @@
       _controllerInstance = new StreamController<List<int>>(
           onPauseStateChange: _onPauseStateChange,
           onSubscriptionStateChange: _onSubscriptionStateChange);
-      _pipeFuture = _controller.stream.pipe(_target);
+      _pipeFuture = _controller.stream.pipe(_target).then((_) => this);
     }
     return _controllerInstance;
   }
@@ -139,12 +157,22 @@
     if (unbind) {
       unbindCompleter = new Completer<T>();
     }
+    completeUnbind([error]) {
+      if (unbindCompleter == null) return;
+      var tmp = unbindCompleter;
+      unbindCompleter = null;
+      if (error == null) {
+        _bindSubscription = null;
+        tmp.complete();
+      } else {
+        tmp.completeError(error);
+      }
+    }
     _bindSubscription = stream.listen(
         _controller.add,
         onDone: () {
-          _bindSubscription = null;
           if (unbind) {
-            unbindCompleter.complete(null);
+            completeUnbind();
           } else {
             _controller.close();
           }
@@ -152,9 +180,12 @@
         onError: _controller.signalError);
     if (_paused) _pause();
     if (unbind) {
+      _pipeFuture
+          .then((_) => completeUnbind(),
+                onError: (error) => completeUnbind(error));
       return unbindCompleter.future;
     } else {
-      return _pipeFuture;
+      return _pipeFuture.then((_) => this);
     }
   }
 }
diff --git a/sdk/lib/io/iolib_sources.gypi b/sdk/lib/io/iolib_sources.gypi
index b695556..92113b4 100644
--- a/sdk/lib/io/iolib_sources.gypi
+++ b/sdk/lib/io/iolib_sources.gypi
@@ -19,7 +19,7 @@
     'http_parser.dart',
     'http_session.dart',
     'http_utils.dart',
-    'io_stream_consumer.dart',
+    'io_sink.dart',
     'mime_multipart_parser.dart',
     'path.dart',
     'path_impl.dart',
diff --git a/sdk/lib/io/mime_multipart_parser.dart b/sdk/lib/io/mime_multipart_parser.dart
index 1ae374c..51f6b7f 100644
--- a/sdk/lib/io/mime_multipart_parser.dart
+++ b/sdk/lib/io/mime_multipart_parser.dart
@@ -41,8 +41,8 @@
   // [boundary]. The boundary should be as specified in the content
   // type parameter, that is without the -- prefix.
   _MimeMultipartParser(String boundary) {
-    List<int> charCodes = boundary.charCodes;
-    _boundary = new List<int>.fixedLength(4 + charCodes.length);
+    List<int> charCodes = boundary.codeUnits;
+    _boundary = new List<int>(4 + charCodes.length);
     // Set-up the matching boundary preceding it with CRLF and two
     // dashes.
     _boundary[0] = _CharCode.CR;
@@ -293,9 +293,9 @@
   }
 
   int _toLowerCase(int byte) {
-    final int aCode = "A".charCodeAt(0);
-    final int zCode = "Z".charCodeAt(0);
-    final int delta = "a".charCodeAt(0) - aCode;
+    final int aCode = "A".codeUnitAt(0);
+    final int zCode = "Z".codeUnitAt(0);
+    final int delta = "a".codeUnitAt(0) - aCode;
     return (aCode <= byte && byte <= zCode) ? byte + delta : byte;
   }
 
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index deb3c83..e3c62e9 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -79,7 +79,7 @@
                                             [ProcessOptions options]);
 
   /**
-   * Returns an input stream of the process stdout.
+   * Returns the standard output stream of the process as a [:Stream:].
    *
    * Throws an [UnsupportedError] if the process is
    * non-interactive.
@@ -87,7 +87,7 @@
   Stream<List<int>> get stdout;
 
   /**
-   * Returns an input stream of the process stderr.
+   * Returns the standard error stream of the process as a [:Stream:].
    *
    * Throws an [UnsupportedError] if the process is
    * non-interactive.
@@ -95,7 +95,7 @@
   Stream<List<int>> get stderr;
 
   /**
-   * Returns an output stream to the process stdin.
+   * Returns the standard input stream of the process as an [IOSink].
    *
    * Throws an [UnsupportedError] if the process is
    * non-interactive.
@@ -103,8 +103,8 @@
   IOSink<Process> get stdin;
 
   /**
-   * Sets an exit handler which gets invoked when the process
-   * terminates.
+   * Returns a [:Future:] which completes with the exit code of the process
+   * when the process completes.
    *
    * Throws an [UnsupportedError] if the process is
    * non-interactive.
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 333edd1..62ecb4d 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -283,7 +283,7 @@
     })
     .catchError((error) {
       _handshakeComplete.completeError(error);
-      close();
+      _close();
     });
   }
 
@@ -341,6 +341,10 @@
   }
 
   void close() {
+    shutdown(SocketDirection.BOTH);
+  }
+
+  void _close() {
     _closedWrite = true;
     _closedRead = true;
     if (_socket != null) {
@@ -360,24 +364,25 @@
   }
 
   void shutdown(SocketDirection direction) {
-    if (direction == SocketDirection.BOTH) {
-      close();
-    } else if (direction == SocketDirection.SEND) {
+    if (direction == SocketDirection.SEND ||
+        direction == SocketDirection.BOTH) {
       _closedWrite = true;
       _writeEncryptedData();
       if (_filterWriteEmpty) {
         _socket.shutdown(SocketDirection.SEND);
         _socketClosedWrite = true;
         if (_closedRead) {
-          close();
+          _close();
         }
       }
-    } else if (direction == SocketDirection.RECEIVE) {
+    }
+    if (direction == SocketDirection.RECEIVE ||
+        direction == SocketDirection.BOTH) {
       _closedRead = true;
       _socketClosedRead = true;
       _socket.shutdown(SocketDirection.RECEIVE);
       if (_socketClosedWrite) {
-        close();
+        _close();
       }
     }
   }
@@ -386,9 +391,10 @@
 
   void set writeEventsEnabled(bool value) {
     if (value &&
+        _controller.hasSubscribers &&
         _secureFilter != null &&
         _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
-      new Timer(0, (_) => _controller.add(RawSocketEvent.WRITE));
+      Timer.run(() => _controller.add(RawSocketEvent.WRITE));
     } else {
       _writeEventsEnabled = value;
     }
@@ -398,11 +404,12 @@
 
   void set readEventsEnabled(bool value) {
     _readEventsEnabled = value;
-    if (_socketClosedRead) {
-      if (value) {
-        // We have no underlying socket to set off read events.
-        new Timer(0, (_) => _readHandler());
-      }
+    if (value &&
+        ((_secureFilter != null &&
+          _secureFilter.buffers[READ_PLAINTEXT].length > 0) ||
+         _socketClosedRead)) {
+      // We might not have no underlying socket to set off read events.
+      Timer.run(_readHandler);
     }
   }
 
@@ -431,7 +438,7 @@
 
     // Set up a read event if the filter still has data.
     if (!_filterReadEmpty) {
-      new Timer(0, (_) => _readHandler());
+      Timer.run(_readHandler);
     }
 
     if (_socketClosedRead) {  // An onClose event is pending.
@@ -445,7 +452,7 @@
       if (_filterReadEmpty) {
         // This can't be an else clause: the value of _filterReadEmpty changes.
         // This must be asynchronous, because we are in a read call.
-        new Timer(0, (_) => _closeHandler());
+        Timer.run(_closeHandler);
       }
     }
 
@@ -489,6 +496,7 @@
         _secureHandshake();
       } catch (e) { _reportError(e, "RawSecureSocket error"); }
     } else if (_status == CONNECTED &&
+               _controller.hasSubscribers &&
                _writeEventsEnabled &&
                _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
       // Reset the one-shot handler.
@@ -530,7 +538,7 @@
           }
           if (_socketClosedRead) {
             // Keep firing read events until we are paused or buffer is empty.
-            new Timer(0, (_) => _readHandler());
+            Timer.run(_readHandler);
           }
         }
       } else if (_socketClosedRead) {
@@ -541,7 +549,7 @@
 
   void _doneHandler() {
     if (_filterReadEmpty) {
-      close();
+      _close();
     }
   }
 
@@ -566,7 +574,7 @@
     } else {
       _controller.signalError(e);
     }
-    close();
+    _close();
   }
 
   void _closeHandler() {
@@ -577,7 +585,7 @@
         _closedRead = true;
         _controller.add(RawSocketEvent.READ_CLOSED);
         if (_socketClosedWrite) {
-          close();
+          _close();
         }
       }
     } else if (_status == HANDSHAKE) {
@@ -600,7 +608,7 @@
       // If we complete the future synchronously, user code will run here,
       // and modify the state of the RawSecureSocket.  For example, it
       // could close the socket, and set _filter to null.
-      new Timer(0, (_) => _handshakeComplete.complete(this));
+      Timer.run(() => _handshakeComplete.complete(this));
     }
   }
 
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index b0c04b4..aa05fdc 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -200,7 +200,7 @@
    * send a close event on the stream and will no longer react on data being
    * piped to it.
    *
-   * Call [close](inherited by [IOSink]) to only close the [Socket]
+   * Call [close](inherited from [IOSink]) to only close the [Socket]
    * for sending data.
    */
   void destroy();
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index 857b8dc..cea080a 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -45,7 +45,7 @@
         break;
       case Encoding.ASCII:
         if (replacementChar == null) {
-          replacementChar = '?'.charCodeAt(0);
+          replacementChar = '?'.codeUnitAt(0);
         } else if (replacementChar > 127) {
           throw new ArgumentError("Invalid replacement character for ASCII");
         }
@@ -53,7 +53,7 @@
         break;
       case Encoding.ISO_8859_1:
         if (replacementChar == null) {
-          replacementChar = '?'.charCodeAt(0);
+          replacementChar = '?'.codeUnitAt(0);
         } else if (replacementChar > 255) {
           throw new ArgumentError(
               "Invalid replacement character for ISO_8859_1");
@@ -153,131 +153,83 @@
 }
 
 
-class LineTransformer implements StreamTransformer<String, String> {
+class LineTransformer extends StreamEventTransformer<String, String> {
   const int _LF = 10;
   const int _CR = 13;
 
   final StringBuffer _buffer = new StringBuffer();
-
-  StreamSubscription<String> _subscription;
-  StreamController<String> _controller;
   String _carry;
 
-  Stream<String> bind(Stream<String> stream) {
-    _controller = new StreamController<String>(
-        onPauseStateChange: _pauseChanged,
-        onSubscriptionStateChange: _subscriptionChanged);
-
-    void handle(String data, bool isClosing) {
-      if (_carry != null) {
-        data = _carry.concat(data);
-        _carry = null;
-      }
-      int startPos = 0;
-      int pos = 0;
-      while (pos < data.length) {
-        int skip = 0;
-        int char = data.charCodeAt(pos);
-        if (char == _LF) {
-          skip = 1;
-        } else if (char == _CR) {
-          skip = 1;
-          if (pos + 1 < data.length) {
-            if (data.charCodeAt(pos + 1) == _LF) {
-              skip = 2;
-            }
-          } else if (!isClosing) {
-            _carry = data.substring(startPos);
-            return;
+  void _handle(String data, StreamSink<String> sink, bool isClosing) {
+    if (_carry != null) {
+      data = _carry.concat(data);
+      _carry = null;
+    }
+    int startPos = 0;
+    int pos = 0;
+    while (pos < data.length) {
+      int skip = 0;
+      int char = data.codeUnitAt(pos);
+      if (char == _LF) {
+        skip = 1;
+      } else if (char == _CR) {
+        skip = 1;
+        if (pos + 1 < data.length) {
+          if (data.codeUnitAt(pos + 1) == _LF) {
+            skip = 2;
           }
-        }
-        if (skip > 0) {
-          _buffer.add(data.substring(startPos, pos));
-          _controller.add(_buffer.toString());
-          _buffer.clear();
-          startPos = pos = pos + skip;
-        } else {
-          pos++;
+        } else if (!isClosing) {
+          _carry = data.substring(startPos);
+          return;
         }
       }
-      if (pos != startPos) {
-        // Add remaining
+      if (skip > 0) {
         _buffer.add(data.substring(startPos, pos));
-      }
-      if (isClosing && !_buffer.isEmpty) {
-        _controller.add(_buffer.toString());
+        sink.add(_buffer.toString());
         _buffer.clear();
+        startPos = pos = pos + skip;
+      } else {
+        pos++;
       }
     }
-
-    _subscription = stream.listen(
-        (data) => handle(data, false),
-        onDone: () {
-          // Handle remaining data (mainly _carry).
-          handle("", true);
-          _controller.close();
-        },
-        onError: _controller.signalError);
-    return _controller.stream;
-  }
-
-  void _pauseChanged() {
-    if (_controller.isPaused) {
-      _subscription.pause();
-    } else {
-      _subscription.resume();
+    if (pos != startPos) {
+      // Add remaining
+      _buffer.add(data.substring(startPos, pos));
+    }
+    if (isClosing && !_buffer.isEmpty) {
+      sink.add(_buffer.toString());
+      _buffer.clear();
     }
   }
 
-  void _subscriptionChanged() {
-    if (!_controller.hasSubscribers) {
-      _subscription.cancel();
-    }
+  void handleData(String data, StreamSink<String> sink) {
+    _handle(data, sink, false);
+  }
+
+  void handleDone(StreamSink<String> sink) {
+    _handle("", sink, true);
+    sink.close();
   }
 }
 
 
-class _SingleByteDecoder implements StreamTransformer<List<int>, String> {
-  StreamSubscription<List<int>> _subscription;
-  StreamController<String> _controller;
+abstract class _SingleByteDecoder
+    extends StreamEventTransformer<List<int>, String> {
   final int _replacementChar;
 
   _SingleByteDecoder(this._replacementChar);
 
-  Stream<String> bind(Stream<List<int>> stream) {
-    _controller = new StreamController<String>(
-        onPauseStateChange: _pauseChanged,
-        onSubscriptionStateChange: _subscriptionChanged);
-    _subscription = stream.listen(
-        (data) {
-          var buffer = new List<int>.fixedLength(data.length);
-          for (int i = 0; i < data.length; i++) {
-            int char = _decodeByte(data[i]);
-            if (char < 0) char = _replacementChar;
-            buffer[i] = char;
-          }
-          _controller.add(new String.fromCharCodes(buffer));
-        },
-        onDone: _controller.close,
-        onError: _controller.signalError);
-    return _controller.stream;
+  void handleData(List<int> data, StreamSink<String> sink) {
+    var buffer = new List<int>(data.length);
+    for (int i = 0; i < data.length; i++) {
+      int char = _decodeByte(data[i]);
+      if (char < 0) char = _replacementChar;
+      buffer[i] = char;
+    }
+    sink.add(new String.fromCharCodes(buffer));
   }
 
   int _decodeByte(int byte);
-
-  void _pauseChanged() {
-    if (_controller.isPaused) {
-      _subscription.pause();
-    } else {
-      _subscription.resume();
-    }
-  }
-
-  void _subscriptionChanged() {
-    if (!_controller.hasSubscribers) {
-      _subscription.cancel();
-    }
-  }
 }
 
 
@@ -299,53 +251,28 @@
 }
 
 
-class _SingleByteEncoder implements StreamTransformer<String, List<int>> {
-  StreamSubscription<String> _subscription;
-  StreamController<List<int>> _controller;
-
-  Stream<List<int>> bind(Stream<String> stream) {
-    _controller = new StreamController<List<int>>(
-        onPauseStateChange: _pauseChanged,
-        onSubscriptionStateChange: _subscriptionChanged);
-    _subscription = stream.listen(
-        (string) {
-          var bytes = _encode(string);
-          if (bytes == null) {
-            _controller.signalError(new FormatException(
-                "Invalid character for encoding"));
-            _controller.close();
-            _subscription.cancel();
-          } else {
-            _controller.add(bytes);
-          }
-        },
-        onDone: _controller.close,
-        onError: _controller.signalError);
-    return _controller.stream;
+abstract class _SingleByteEncoder
+    extends StreamEventTransformer<String, List<int>> {
+  void handleData(String data, StreamSink<List<int>> sink) {
+    var bytes = _encode(data);
+    if (bytes == null) {
+      sink.signalError(
+          new AsyncError(
+              new FormatException("Invalid character for encoding")));
+      sink.close();
+    } else {
+      sink.add(bytes);
+    }
   }
 
   List<int> _encode(String string);
-
-  void _pauseChanged() {
-    if (_controller.isPaused) {
-      _subscription.pause();
-    } else {
-      _subscription.resume();
-    }
-  }
-
-  void _subscriptionChanged() {
-    if (!_controller.hasSubscribers) {
-      _subscription.cancel();
-    }
-  }
 }
 
 
 // Utility class for encoding a string into an ASCII byte stream.
 class _AsciiEncoder extends _SingleByteEncoder {
   List<int> _encode(String string) {
-    var bytes = string.charCodes;
+    var bytes = string.codeUnits;
     for (var byte in bytes) {
       if (byte > 127) return null;
     }
@@ -357,7 +284,7 @@
 // Utility class for encoding a string into a Latin1 byte stream.
 class _Latin1Encoder extends _SingleByteEncoder {
   List<int> _encode(String string) {
-    var bytes = string.charCodes;
+    var bytes = string.codeUnits;
     for (var byte in bytes) {
       if (byte > 255) return null;
     }
@@ -379,36 +306,10 @@
 
 // Utility class for decoding Windows current code page data delivered
 // as a stream of bytes.
-class _WindowsCodePageDecoder implements StreamTransformer<List<int>, String> {
-  StreamSubscription<List<int>> _subscription;
-  StreamController<String> _controller;
-
-  Stream<String> bind(Stream<List<int>> stream) {
-    _controller = new StreamController<String>(
-        onPauseStateChange: _pauseChanged,
-        onSubscriptionStateChange: _subscriptionChanged);
-    _subscription = stream.listen(
-        (data) {
-          _controller.add(_decodeBytes(data));
-        },
-        onDone: _controller.close,
-        onError: _controller.signalError);
-    return _controller.stream;
+class _WindowsCodePageDecoder extends StreamEventTransformer<List<int>, String> {
+  void handleData(List<int> data, StreamSink<String> sink) {
+    sink.add(_decodeBytes(data));
   }
 
   external static String _decodeBytes(List<int> bytes);
-
-  void _pauseChanged() {
-    if (_controller.isPaused) {
-      _subscription.pause();
-    } else {
-      _subscription.resume();
-    }
-  }
-
-  void _subscriptionChanged() {
-    if (!_controller.hasSubscribers) {
-      _subscription.cancel();
-    }
-  }
 }
diff --git a/sdk/lib/io/websocket.dart b/sdk/lib/io/websocket.dart
index 48cf54a..65249f1 100644
--- a/sdk/lib/io/websocket.dart
+++ b/sdk/lib/io/websocket.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -24,78 +24,63 @@
 }
 
 /**
- * The [WebSocketTransformer] is implemented as a stream transformer that
- * transforms a stream of HttpRequest into a stream of WebSockets by upgrading
- * each HttpRequest from the HTTP or HTTPS server, to the WebSocket protocol.
+ * The [WebSocketTransformer] provides the ability to upgrade a
+ * [HttpRequest] to a [WebSocket] connection. It supports both
+ * upgrading a single [HttpRequest] and upgrading a stream of
+ * [HttpRequest]s.
  *
- * Example of usage:
+ * To upgrade a single [HttpRequest] use the static [upgrade] method.
+ *
+ *     HttpServer server;
+ *     server.listen((request) {
+ *       if (...) {
+ *         WebSocketTransformer.upgrade(request).then(websocket) {
+ *           ...
+ *         }
+ *       } else {
+ *         // Do normal HTTP request processing.
+ *       }
+ *     });
+ *
+ * To transform a stream of [HttpRequest] events as it implements a
+ * stream transformer that transforms a stream of HttpRequest into a
+ * stream of WebSockets by upgrading each HttpRequest from the HTTP or
+ * HTTPS server, to the WebSocket protocol.
  *
  *     server.transform(new WebSocketTransformer()).listen((webSocket) => ...);
  *
- * or
- *
- *     server
- *         .where((request) => request.uri.scheme == "ws")
- *         .transform(new WebSocketTransformer()).listen((webSocket) => ...);
- *
  * This transformer strives to implement web sockets as specified by RFC6455.
  */
 abstract class WebSocketTransformer
     implements StreamTransformer<HttpRequest, WebSocket> {
   factory WebSocketTransformer() => new _WebSocketTransformerImpl();
+
+  /**
+   * Upgrades a [HttpRequest] to a [WebSocket] connection. If the
+   * request is not a valid web socket upgrade request a HTTP response
+   * with status code 500 will be returned. Otherwise the returned
+   * future will complete with the [WebSocket] when the upgrade pocess
+   * is complete.
+   */
+  static Future<WebSocket> upgrade(HttpRequest request) {
+    return _WebSocketTransformerImpl._upgrade(request);
+  }
+
+  /**
+   * Checks whether the request is a valid WebSocket upgrade request.
+   */
+  static bool isUpgradeRequest(HttpRequest request) {
+    return _WebSocketTransformerImpl._isUpgradeRequest(request);
+  }
 }
 
 
 /**
- * Base class for the events generated by the W3C complient browser
- * API for web sockets.
+ * A client or server web socket connection. The stream exposes the
+ * messages received. A text message will be of type [:String:] and a
+ * binary message will be of type [:List<int>:].
  */
-abstract class Event { }
-
-/**
- * Event delivered when there is data on a web socket connection.
- */
-abstract class MessageEvent extends Event {
-  /**
-   * The type of [message] is either [:String:] or [:List<int>:]
-   * depending on whether it is a text or binary message. If the
-   * message is empty [message] will be [:null:]
-   * If the message is a [:List<int>:] then it will contain byte values
-   * from 0 to 255.
-   */
-  get data;
-}
-
-
-/**
- * Event delivered when a web socket connection is closed.
- */
-abstract class CloseEvent extends Event {
-  /**
-   * Returns whether the connection was closed cleanly or not.
-   */
-  bool get wasClean;
-
-  /**
-   * Returns the web socket connection close code provided by the
-   * server.
-   */
-  int get code;
-
-  /**
-   * Returns the web socket connection close reason provided by the
-   * server.
-   */
-  String get reason;
-}
-
-
-/**
- * Alternative web socket client interface. This interface is compliant
- * with the W3C browser API for web sockets specified in
- * http://dev.w3.org/html5/websockets/.
- */
-abstract class WebSocket implements Stream<Event> {
+abstract class WebSocket implements Stream {
   /**
    * Possible states of the connection.
    */
@@ -119,11 +104,6 @@
   int get readyState;
 
   /**
-   * Returns the number of bytes currently buffered for transmission.
-   */
-  int get bufferedAmount;
-
-  /**
    * The extensions property is initially the empty string. After the
    * web socket connection is established this string reflects the
    * extensions used by the server.
@@ -139,6 +119,18 @@
   String get protocol;
 
   /**
+   * The close code set when the web socket connection is closed. If
+   * there is no close code available this property will be [:null:]
+   */
+  int get closeCode;
+
+  /**
+   * The close reason set when the web socket connection is closed. If
+   * there is no close reason available this property will be [:null:]
+   */
+  String get closeReason;
+
+  /**
    * Closes the web socket connection.
    */
   void close([int code, String reason]);
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index a8d01c2..a849ae1 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -363,40 +363,42 @@
 
   Stream<WebSocket> bind(Stream<HttpRequest> stream) {
     stream.listen((request) {
-      var response = request.response;
-      if (!_isWebSocketUpgrade(request)) {
-        _controller.signalError(
-            new AsyncError(
-                new WebSocketException("Invalid WebSocket upgrade request")));
-        request.listen((_) {}, onDone: () {
-          response.statusCode = HttpStatus.BAD_REQUEST;
-          response.contentLength = 0;
-          response.close();
-        });
-        return;
-      }
-      // Send the upgrade response.
-      response.statusCode = HttpStatus.SWITCHING_PROTOCOLS;
-      response.headers.add(HttpHeaders.CONNECTION, "Upgrade");
-      response.headers.add(HttpHeaders.UPGRADE, "websocket");
-      String key = request.headers.value("Sec-WebSocket-Key");
-      SHA1 sha1 = new SHA1();
-      sha1.add("$key$_webSocketGUID".charCodes);
-      String accept = _Base64._encode(sha1.close());
-      response.headers.add("Sec-WebSocket-Accept", accept);
-      response.headers.contentLength = 0;
-      response.detachSocket()
-        .then((socket) {
-          _controller.add(new _WebSocketImpl._fromSocket(socket));
-        }, onError: (error) {
-          _controller.signalError(error);
-        });
+        _upgrade(request)
+            .then((WebSocket webSocket) => _controller.add(webSocket))
+            .catchError((error) => _controller.signalError(error));
     });
 
     return _controller.stream;
   }
 
-  bool _isWebSocketUpgrade(HttpRequest request) {
+  static Future<WebSocket> _upgrade(HttpRequest request) {
+    var response = request.response;
+    if (!_isUpgradeRequest(request)) {
+      // Send error response and drain the request.
+      request.listen((_) {}, onDone: () {
+        response.statusCode = HttpStatus.BAD_REQUEST;
+        response.contentLength = 0;
+        response.close();
+      });
+      return new Future.immediateError(
+          new WebSocketException("Invalid WebSocket upgrade request"));
+    }
+
+    // Send the upgrade response.
+    response.statusCode = HttpStatus.SWITCHING_PROTOCOLS;
+    response.headers.add(HttpHeaders.CONNECTION, "Upgrade");
+    response.headers.add(HttpHeaders.UPGRADE, "websocket");
+    String key = request.headers.value("Sec-WebSocket-Key");
+    SHA1 sha1 = new SHA1();
+    sha1.add("$key$_webSocketGUID".codeUnits);
+    String accept = _Base64._encode(sha1.close());
+    response.headers.add("Sec-WebSocket-Accept", accept);
+    response.headers.contentLength = 0;
+    return response.detachSocket()
+        .then((socket) => new _WebSocketImpl._fromSocket(socket));
+  }
+
+  static bool _isUpgradeRequest(HttpRequest request) {
     if (request.method != "GET") {
       return false;
     }
@@ -425,14 +427,17 @@
 }
 
 
-class _WebSocketImpl extends Stream<Event> implements WebSocket {
-  final StreamController<Event> _controller = new StreamController<Event>();
+class _WebSocketImpl extends Stream implements WebSocket {
+  final StreamController _controller = new StreamController();
 
   final _WebSocketProtocolProcessor _processor =
       new _WebSocketProtocolProcessor();
 
   final Socket _socket;
   int _readyState = WebSocket.CONNECTING;
+  bool _writeClosed = false;
+  int _closeCode;
+  String _closeReason;
 
   static final HttpClient _httpClient = new HttpClient();
 
@@ -447,7 +452,7 @@
 
     Random random = new Random();
     // Generate 16 random bytes.
-    List<int> nonceData = new List<int>.fixedLength(16);
+    List<int> nonceData = new List<int>(16);
     for (int i = 0; i < 16; i++) {
       nonceData[i] = random.nextInt(256);
     }
@@ -490,7 +495,7 @@
           error("Response did not contain a 'Sec-WebSocket-Accept' header");
         }
         SHA1 sha1 = new SHA1();
-        sha1.add("$nonce$_webSocketGUID".charCodes);
+        sha1.add("$nonce$_webSocketGUID".codeUnits);
         List<int> expectedAccept = sha1.close();
         List<int> receivedAccept = _Base64._decode(accept);
         if (expectedAccept.length != receivedAccept.length) {
@@ -528,9 +533,9 @@
     };
     _processor.onMessageEnd = () {
       if (type == _WebSocketMessageType.TEXT) {
-        _controller.add(new _WebSocketMessageEvent(data.toString()));
+        _controller.add(data.toString());
       } else {
-        _controller.add(new _WebSocketMessageEvent(data));
+        _controller.add(data);
       }
     };
     _processor.onClosed = (code, reason) {
@@ -545,7 +550,9 @@
         }
         _readyState = WebSocket.CLOSED;
       }
-      _controller.add(new _WebSocketCloseEvent(clean, code, reason));
+      if (_readyState == WebSocket.CLOSED) return;
+      _closeCode = code;
+      _closeReason = reason;
       _controller.close();
     };
 
@@ -553,12 +560,25 @@
         (data) => _processor.update(data, 0, data.length),
         onDone: () => _processor.closed(),
         onError: (error) => _controller.signalError(error));
+
+    _socket.done
+        .catchError((error) {
+          if (_readyState == WebSocket.CLOSED) return;
+          _readyState = WebSocket.CLOSED;
+          _closeCode = ABNORMAL_CLOSURE;
+          _controller.signalError(error);
+          _controller.close();
+          _socket.destroy();
+        })
+        .whenComplete(() {
+          _writeClosed = true;
+        });
   }
 
-  StreamSubscription<Event> listen(void onData(Event event),
-                                   {void onError(AsyncError error),
-                                    void onDone(),
-                                    bool unsubscribeOnError}) {
+  StreamSubscription listen(void onData(message),
+                            {void onError(AsyncError error),
+                             void onDone(),
+                             bool unsubscribeOnError}) {
     return _controller.stream.listen(onData,
                                      onError: onError,
                                      onDone: onDone,
@@ -566,10 +586,11 @@
   }
 
   int get readyState => _readyState;
-  int get bufferedAmount => 0;
 
   String get extensions => null;
   String get protocol => null;
+  int get closeCode => _closeCode;
+  String get closeReason => _closeReason;
 
   void close([int code, String reason]) {
     if (_readyState < WebSocket.CLOSING) _readyState = WebSocket.CLOSING;
@@ -627,10 +648,16 @@
     } else {
       opcode = _WebSocketOpcode.TEXT;
     }
-    _sendFrame(opcode, data);
+    try {
+      _sendFrame(opcode, data);
+    } catch (_) {
+      // The socket can be closed before _socket.done have a chance
+      // to complete.
+    }
   }
 
   void _sendFrame(int opcode, [List<int> data]) {
+    if (_writeClosed) return;
     bool mask = false;  // Masking not implemented for server.
     int dataLength = data == null ? 0 : data.length;
     // Determine the header size.
@@ -640,7 +667,7 @@
     } else if (dataLength > 125) {
       headerSize += 2;
     }
-    List<int> header = new List<int>.fixedLength(headerSize);
+    List<int> header = new List<int>(headerSize);
     int index = 0;
     // Set FIN and opcode.
     header[index++] = 0x80 | opcode;
@@ -665,21 +692,3 @@
     }
   }
 }
-
-
-class _WebSocketMessageEvent implements MessageEvent {
-  _WebSocketMessageEvent(this._data);
-  get data => _data;
-  var _data;
-}
-
-
-class _WebSocketCloseEvent implements CloseEvent {
-  _WebSocketCloseEvent(this._wasClean, this._code, this._reason);
-  bool get wasClean => _wasClean;
-  int get code => _code;
-  String get reason => _reason;
-  bool _wasClean;
-  int _code;
-  String _reason;
-}
diff --git a/sdk/lib/isolate/isolate_sources.gypi b/sdk/lib/isolate/isolate_sources.gypi
index 4481e93..8077ccf 100644
--- a/sdk/lib/isolate/isolate_sources.gypi
+++ b/sdk/lib/isolate/isolate_sources.gypi
@@ -4,6 +4,8 @@
 
 {
   'sources': [
+    'isolate.dart',
+    # The above file needs to be first as it lists the parts below.
     'base.dart',
     'isolate_stream.dart',
     'mangler.dart',
diff --git a/sdk/lib/isolate/mangler.dart b/sdk/lib/isolate/mangler.dart
index a0e1672..8b31d5a6 100644
--- a/sdk/lib/isolate/mangler.dart
+++ b/sdk/lib/isolate/mangler.dart
@@ -44,7 +44,7 @@
       for (int i = 0; i < data.length; i++) {
         var mangled = encode(data[i]);
         if (mangled != data[i] && !hasBeenDuplicated) {
-          result = new List.fixedLength(data.length);
+          result = new List(data.length);
           for (int j = 0; j < i; j++) {
             result[j] = data[j];
           }
diff --git a/sdk/lib/json/json_base.dart b/sdk/lib/json/json_base.dart
index 9f74d65..5432e5aa 100644
--- a/sdk/lib/json/json_base.dart
+++ b/sdk/lib/json/json_base.dart
@@ -47,7 +47,9 @@
  *
  * Throws [FormatException] if the input is not valid JSON text.
  */
-parse(String json, [reviver(var key, var value)]) {
+external parse(String json, [reviver(var key, var value)]);
+
+_parse(String json, reviver(var key, var value)) {
   BuildJsonListener listener;
   if (reviver == null) {
     listener = new BuildJsonListener();
@@ -322,7 +324,7 @@
     int position = 0;
     int length = source.length;
     while (position < length) {
-      int char = source.charCodeAt(position);
+      int char = source.codeUnitAt(position);
       switch (char) {
         case SPACE:
         case CARRIAGE_RETURN:
@@ -423,11 +425,11 @@
    * [:source[position]:] must be "t".
    */
   int parseTrue(int position) {
-    assert(source.charCodeAt(position) == CHAR_t);
+    assert(source.codeUnitAt(position) == CHAR_t);
     if (source.length < position + 4) fail(position, "Unexpected identifier");
-    if (source.charCodeAt(position + 1) != CHAR_r ||
-        source.charCodeAt(position + 2) != CHAR_u ||
-        source.charCodeAt(position + 3) != CHAR_e) {
+    if (source.codeUnitAt(position + 1) != CHAR_r ||
+        source.codeUnitAt(position + 2) != CHAR_u ||
+        source.codeUnitAt(position + 3) != CHAR_e) {
       fail(position);
     }
     listener.handleBool(true);
@@ -440,12 +442,12 @@
    * [:source[position]:] must be "f".
    */
   int parseFalse(int position) {
-    assert(source.charCodeAt(position) == CHAR_f);
+    assert(source.codeUnitAt(position) == CHAR_f);
     if (source.length < position + 5) fail(position, "Unexpected identifier");
-    if (source.charCodeAt(position + 1) != CHAR_a ||
-        source.charCodeAt(position + 2) != CHAR_l ||
-        source.charCodeAt(position + 3) != CHAR_s ||
-        source.charCodeAt(position + 4) != CHAR_e) {
+    if (source.codeUnitAt(position + 1) != CHAR_a ||
+        source.codeUnitAt(position + 2) != CHAR_l ||
+        source.codeUnitAt(position + 3) != CHAR_s ||
+        source.codeUnitAt(position + 4) != CHAR_e) {
       fail(position);
     }
     listener.handleBool(false);
@@ -457,11 +459,11 @@
    * [:source[position]:] must be "n".
    */
   int parseNull(int position) {
-    assert(source.charCodeAt(position) == CHAR_n);
+    assert(source.codeUnitAt(position) == CHAR_n);
     if (source.length < position + 4) fail(position, "Unexpected identifier");
-    if (source.charCodeAt(position + 1) != CHAR_u ||
-        source.charCodeAt(position + 2) != CHAR_l ||
-        source.charCodeAt(position + 3) != CHAR_l) {
+    if (source.codeUnitAt(position + 1) != CHAR_u ||
+        source.codeUnitAt(position + 2) != CHAR_l ||
+        source.codeUnitAt(position + 3) != CHAR_l) {
       fail(position);
     }
     listener.handleNull();
@@ -477,7 +479,7 @@
       if (position == source.length) {
         fail(start - 1, "Unterminated string");
       }
-      char = source.charCodeAt(position);
+      char = source.codeUnitAt(position);
       if (char == QUOTE) {
         listener.handleString(source.substring(start, position));
         return position + 1;
@@ -494,7 +496,7 @@
       if (position == source.length) {
         fail(start - 1, "Unterminated string");
       }
-      char = source.charCodeAt(position);
+      char = source.codeUnitAt(position);
       switch (char) {
         case CHAR_b: char = BACKSPACE; break;
         case CHAR_f: char = FORM_FEED; break;
@@ -513,7 +515,7 @@
             if (position == source.length) {
               fail(start - 1, "Unterminated string");
             }
-            char = source.charCodeAt(position);
+            char = source.codeUnitAt(position);
             char -= 0x30;
             if (char < 0) fail(hexStart, "Invalid unicode escape");
             if (char < 10) {
@@ -536,7 +538,7 @@
         chars.add(char);
         position++;
         if (position == source.length) fail(start - 1, "Unterminated string");
-        char = source.charCodeAt(position);
+        char = source.codeUnitAt(position);
         if (char == QUOTE) {
           String result = new String.fromCharCodes(chars);
           if (start < firstEscape) {
@@ -553,6 +555,14 @@
     }
   }
 
+  int _handleLiteral(start, position, isDouble) {
+    String literal = source.substring(start, position);
+    // This correctly creates -0 for doubles.
+    num value = (isDouble ? double.parse(literal) : int.parse(literal));
+    listener.handleNumber(value);
+    return position;
+  }
+
   int parseNumber(int char, int position) {
     // Format:
     //  '-'?('0'|[1-9][0-9]*)('.'[0-9]+)?([eE][+-]?[0-9]+)?
@@ -562,64 +572,57 @@
     if (char == MINUS) {
       position++;
       if (position == length) fail(position, "Missing expected digit");
-      char = source.charCodeAt(position);
+      char = source.codeUnitAt(position);
     }
     if (char < CHAR_0 || char > CHAR_9) {
       fail(position, "Missing expected digit");
     }
-    int handleLiteral(position) {
-      String literal = source.substring(start, position);
-      // This correctly creates -0 for doubles.
-      num value = (isDouble ? double.parse(literal) : int.parse(literal));
-      listener.handleNumber(value);
-      return position;
-    }
     if (char == CHAR_0) {
       position++;
-      if (position == length) return handleLiteral(position);
-      char = source.charCodeAt(position);
+      if (position == length) return _handleLiteral(start, position, false);
+      char = source.codeUnitAt(position);
       if (CHAR_0 <= char && char <= CHAR_9) {
         fail(position);
       }
     } else {
       do {
         position++;
-        if (position == length) return handleLiteral(position);
-        char = source.charCodeAt(position);
+        if (position == length) return _handleLiteral(start, position, false);
+        char = source.codeUnitAt(position);
       } while (CHAR_0 <= char && char <= CHAR_9);
     }
     if (char == DECIMALPOINT) {
       isDouble = true;
       position++;
       if (position == length) fail(position, "Missing expected digit");
-      char = source.charCodeAt(position);
+      char = source.codeUnitAt(position);
       if (char < CHAR_0 || char > CHAR_9) fail(position);
       do {
         position++;
-        if (position == length) return handleLiteral(position);
-        char = source.charCodeAt(position);
+        if (position == length) return _handleLiteral(start, position, true);
+        char = source.codeUnitAt(position);
       } while (CHAR_0 <= char && char <= CHAR_9);
     }
     if (char == CHAR_e || char == CHAR_E) {
       isDouble = true;
       position++;
       if (position == length) fail(position, "Missing expected digit");
-      char = source.charCodeAt(position);
+      char = source.codeUnitAt(position);
       if (char == PLUS || char == MINUS) {
         position++;
         if (position == length) fail(position, "Missing expected digit");
-        char = source.charCodeAt(position);
+        char = source.codeUnitAt(position);
       }
       if (char < CHAR_0 || char > CHAR_9) {
         fail(position, "Missing expected digit");
       }
       do {
         position++;
-        if (position == length) return handleLiteral(position);
-        char = source.charCodeAt(position);
+        if (position == length) return _handleLiteral(start, position, true);
+        char = source.codeUnitAt(position);
       } while (CHAR_0 <= char && char <= CHAR_9);
     }
-    return handleLiteral(position);
+    return _handleLiteral(start, position, isDouble);
   }
 
   void fail(int position, [String message]) {
@@ -668,7 +671,7 @@
     bool needsEscape = false;
     final charCodes = new List<int>();
     for (int i = 0; i < length; i++) {
-      int charCode = s.charCodeAt(i);
+      int charCode = s.codeUnitAt(i);
       if (charCode < 32) {
         needsEscape = true;
         charCodes.add(JsonParser.BACKSLASH);
diff --git a/sdk/lib/json/json_sources.gypi b/sdk/lib/json/json_sources.gypi
index f9a7160..9311d82 100644
--- a/sdk/lib/json/json_sources.gypi
+++ b/sdk/lib/json/json_sources.gypi
@@ -5,6 +5,8 @@
 # This file contains all sources for the dart:json library.
 {
   'sources': [
+    'json.dart',
+    # The above file needs to be first as it lists the parts below.
     'json_base.dart',
   ],
 }
diff --git a/sdk/lib/math/math_sources.gypi b/sdk/lib/math/math_sources.gypi
index dc854da..cbfad89 100644
--- a/sdk/lib/math/math_sources.gypi
+++ b/sdk/lib/math/math_sources.gypi
@@ -4,6 +4,8 @@
 
 {
   'sources': [
+    'math.dart',
+    # The above file needs to be first as it lists the parts below.
     'base.dart',
     'random.dart',
   ],
diff --git a/sdk/lib/mirrors/mirrors_sources.gypi b/sdk/lib/mirrors/mirrors_sources.gypi
index 5f55725..73d1620 100644
--- a/sdk/lib/mirrors/mirrors_sources.gypi
+++ b/sdk/lib/mirrors/mirrors_sources.gypi
@@ -4,6 +4,8 @@
 
 {
   'sources': [
+    'mirrors.dart',
+    # The above file needs to be first as it lists the parts below.
     'mirrors_impl.dart',
   ],
 }
diff --git a/sdk/lib/scalarlist/byte_arrays.dart b/sdk/lib/scalarlist/byte_arrays.dart
index d843259..e37efc2 100644
--- a/sdk/lib/scalarlist/byte_arrays.dart
+++ b/sdk/lib/scalarlist/byte_arrays.dart
@@ -269,6 +269,30 @@
   int setUint64(int byteOffset, int value);
 
   /**
+   * Returns the Float32x4 number represented by the 16 bytes at
+   * the specified [byteOffset] in this byte array.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 16` is greater than the length of this byte array.
+   */
+  Float32x4 getFloat32x4(int byteOffset);
+
+  /**
+   * Sets the sixteen bytes starting at the specified [byteOffset] in this
+   * byte array to the Float32x4 representation of the specified [value].
+   *
+   *
+   * Returns `byteOffset + 16`, which is the offset of the first byte in the
+   * array after the last byte that was set by this call. This return value can
+   * be passed as the [byteOffset] parameter to a subsequent `setXxx` call.
+   *
+   * Throws [RangeError] if [byteOffset] is negative, or
+   * `byteOffset + 16` is greater than the length of this byte array.
+   */
+  int setFloat32x4(int byteOffset, Float32x4 value);
+
+
+  /**
    * Returns the floating point number represented by the four bytes at
    * the specified [byteOffset] in this byte array, in IEEE 754
    * single-precision binary floating-point format (binary32).
diff --git a/sdk/lib/scalarlist/scalarlist.dart b/sdk/lib/scalarlist/scalarlist.dart
index 508b20e..9d79daa 100644
--- a/sdk/lib/scalarlist/scalarlist.dart
+++ b/sdk/lib/scalarlist/scalarlist.dart
@@ -12,7 +12,7 @@
  */
 library dart.scalarlist;
 
-// TODO(ager): Inline the contents of byte_arrays.dart here and get
-// rid of scalarlist_sources.gypi when the VM understands normal
-// library structure for builtin libraries.
+import 'dart:collection';
+
 part 'byte_arrays.dart';
+part 'simd128.dart';
\ No newline at end of file
diff --git a/sdk/lib/scalarlist/scalarlist_sources.gypi b/sdk/lib/scalarlist/scalarlist_sources.gypi
index 70a6ab8..b04d10d 100644
--- a/sdk/lib/scalarlist/scalarlist_sources.gypi
+++ b/sdk/lib/scalarlist/scalarlist_sources.gypi
@@ -4,10 +4,9 @@
 
 {
   'sources': [
-    # TODO(ager): remove byte_arrays.dart and inline the code in
-    # scalarlist.dart. The reason for not doing that at this point is
-    # that the VM does not allow normal library structure for builtin
-    # libraries.
+    'scalarlist.dart',
+    # The above file needs to be first as it lists the parts below.
     'byte_arrays.dart',
+    'simd128.dart',
   ],
 }
diff --git a/sdk/lib/scalarlist/simd128.dart b/sdk/lib/scalarlist/simd128.dart
new file mode 100644
index 0000000..96349fd
--- /dev/null
+++ b/sdk/lib/scalarlist/simd128.dart
@@ -0,0 +1,188 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.scalarlist;
+
+/**
+ * Interface of Dart Float32x4 and operations.
+ * Float32x4 stores 4 32-bit floating point values in "lanes".
+ * The lanes are "x", "y", "z", and "w" respectively.
+ */
+abstract class Float32x4 {
+  external factory Float32x4(double x, double y, double z, double w);
+  external factory Float32x4.zero();
+
+  /// Addition operator.
+  Float32x4 operator+(Float32x4 other);
+  /// Negate operator.
+  Float32x4 operator-();
+  /// Subtraction operator.
+  Float32x4 operator-(Float32x4 other);
+  /// Multiplication operator.
+  Float32x4 operator*(Float32x4 other);
+  /// Division operator.
+  Float32x4 operator/(Float32x4 other);
+
+  /// Relational less than.
+  Uint32x4 lessThan(Float32x4 other);
+  /// Relational less than or equal.
+  Uint32x4 lessThanOrEqual(Float32x4 other);
+  /// Relational greater than.
+  Uint32x4 greaterThan(Float32x4 other);
+  /// Relational greater than or equal.
+  Uint32x4 greaterThanOrEqual(Float32x4 other);
+  /// Relational equal.
+  Uint32x4 equal(Float32x4 other);
+  /// Relational not-equal.
+  Uint32x4 notEqual(Float32x4 other);
+
+  /// Returns a copy of [this] each lane being scaled by [s].
+  Float32x4 scale(double s);
+  /// Returns the absolute value of this [Simd128Float32].
+  Float32x4 abs();
+  /// Clamps [this] to be in the range [lowerLimit]-[upperLimit].
+  Float32x4 clamp(Float32x4 lowerLimit,
+                         Float32x4 upperLimit);
+
+  /// Extracted x value.
+  double get x;
+  /// Extracted y value.
+  double get y;
+  /// Extracted z value.
+  double get z;
+  /// Extracted w value.
+  double get w;
+
+  /// Returns a new [Float32x4] with [this]' x value in all four lanes.
+  Float32x4 get xxxx;
+  /// Returns a new [Float32x4] with [this]' y value in all four lanes.
+  Float32x4 get yyyy;
+  /// Returns a new [Float32x4] with [this]' z value in all four lanes.
+  Float32x4 get zzzz;
+  /// Returns a new [Float32x4] with [this]' w value in all four lanes.
+  Float32x4 get wwww;
+  // TODO(johnmccutchan): Add all 256 possible combinations.
+
+  /// Returns a new [Float32x4] copied from [this] with a new x value.
+  Float32x4 withX(double x);
+  /// Returns a new [Float32x4] copied from [this] with a new y value.
+  Float32x4 withY(double y);
+  /// Returns a new [Float32x4] copied from [this] with a new z value.
+  Float32x4 withZ(double z);
+  /// Returns a new [Float32x4] copied from [this] with a new w value.
+  Float32x4 withW(double w);
+
+  /// Returns the lane-wise minimum value in [this] or [other].
+  Float32x4 min(Float32x4 other);
+
+  /// Returns the lane-wise maximum value in [this] or [other].
+  Float32x4 max(Float32x4 other);
+
+  /// Returns the square root of [this].
+  Float32x4 sqrt();
+
+  /// Returns the reciprocal of [this].
+  Float32x4 reciprocal();
+
+  /// Returns the square root of the reciprocal of [this].
+  Float32x4 reciprocalSqrt();
+
+  /// Returns a bit-wise copy of [this] as a [Uint32x4].
+  Uint32x4 toUint32x4();
+}
+
+/**
+ * Interface of Dart Uint32x4 and operations.
+ * Uint32x4 stores 4 32-bit bit-masks in "lanes".
+ * The lanes are "x", "y", "z", and "w" respectively.
+ */
+abstract class Uint32x4 {
+  external factory Uint32x4(int x, int y, int z, int w);
+  external factory Uint32x4.bool(bool x, bool y, bool z, bool w);
+
+  /// The bit-wise or operator.
+  Uint32x4 operator|(Uint32x4 other);
+  /// The bit-wise and operator.
+  Uint32x4 operator&(Uint32x4 other);
+  /// The bit-wise xor operator.
+  Uint32x4 operator^(Uint32x4 other);
+
+  /// Extract 32-bit mask from x lane.
+  int get x;
+  /// Extract 32-bit mask from y lane.
+  int get y;
+  /// Extract 32-bit mask from z lane.
+  int get z;
+  /// Extract 32-bit mask from w lane.
+  int get w;
+
+  /// Returns a new [Uint32x4] copied from [this] with a new x value.
+  Uint32x4 withX(int x);
+  /// Returns a new [Uint32x4] copied from [this] with a new y value.
+  Uint32x4 withY(int y);
+  /// Returns a new [Uint32x4] copied from [this] with a new z value.
+  Uint32x4 withZ(int z);
+  /// Returns a new [Uint32x4] copied from [this] with a new w value.
+  Uint32x4 withW(int w);
+
+  /// Extracted x value. Returns false for 0, true for any other value.
+  bool get flagX;
+  /// Extracted y value. Returns false for 0, true for any other value.
+  bool get flagY;
+  /// Extracted z value. Returns false for 0, true for any other value.
+  bool get flagZ;
+  /// Extracted w value. Returns false for 0, true for any other value.
+  bool get flagW;
+
+  /// Returns a new [Uint32x4] copied from [this] with a new x value.
+  Uint32x4 withFlagX(bool x);
+  /// Returns a new [Uint32x4] copied from [this] with a new y value.
+  Uint32x4 withFlagY(bool y);
+  /// Returns a new [Uint32x4] copied from [this] with a new z value.
+  Uint32x4 withFlagZ(bool z);
+  /// Returns a new [Uint32x4] copied from [this] with a new w value.
+  Uint32x4 withFlagW(bool w);
+
+  /// Merge [trueValue] and [falseValue] based on [this]' bit mask:
+  /// Select bit from [trueValue] when bit in [this] is on.
+  /// Select bit from [falseValue] when bit in [this] is off.
+  Float32x4 select(Float32x4 trueValue, Float32x4 falseValue);
+
+  /// Returns a bit-wise copy of [this] as a [Float32x4].
+  Float32x4 toFloat32x4();
+}
+
+/**
+ * A fixed-length list of Float32x4 numbers that is viewable as a
+ * [ByteArray]. For long lists, this implementation will be considerably more
+ * space- and time-efficient than the default [List] implementation.
+ */
+abstract class Float32x4List implements List<Float32x4>,
+    ByteArrayViewable {
+  /**
+   * Creates a [Simd128Float32List] of the specified length (in elements),
+   * all of whose elements are initially zero.
+   */
+  external factory Float32x4List(int length);
+
+  /**
+   * Creates a [Float32x4List] _view_ of the specified region in the
+   * specified byte [array]. Changes in the [Float32x4List] will be
+   * visible in the byte array and vice versa. If the [start] index of the
+   * region is not specified, it defaults to zero (the first byte in the byte
+   * array). If the length is not specified, it defaults to null, which
+   * indicates that the view extends to the end of the byte array.
+   *
+   * Throws [ArgumentError] if the length of the specified region is not
+   * divisible by 16 (the size of a "Float32x4" in bytes), or if the
+   * [start] of the region is not divisible by 16. If, however, [array] is a
+   * view of another byte array, this constructor will throw [ArgumentError]
+   * if the implicit starting position in the "ultimately backing" byte array
+   * is not divisible by 16. In plain terms, this constructor throws
+   * [ArgumentError] if the specified region does not contain an integral
+   * number of "Float32x4s," or if it is not "Float32x4-aligned."
+   */
+  external factory Float32x4List.view(ByteArray array,
+                                      [int start = 0, int length]);
+}
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index c34dc27..0784b5a 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -3050,7 +3050,7 @@
   @DocsEditable
   final int numberOfItems;
 
-  Length operator[](int index) => JS("Length", "#[#]", this, index);
+  Length operator[](int index) => this.getItem(index);
 
   void operator[]=(int index, Length value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -3093,7 +3093,9 @@
 
   bool any(bool f(Length element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Length> toList() => new List<Length>.from(this);
+  List<Length> toList({ bool growable: true }) =>
+      new List<Length>.from(this, growable: growable);
+
   Set<Length> toSet() => new Set<Length>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -3674,7 +3676,7 @@
   @DocsEditable
   final int numberOfItems;
 
-  Number operator[](int index) => JS("Number", "#[#]", this, index);
+  Number operator[](int index) => this.getItem(index);
 
   void operator[]=(int index, Number value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -3717,7 +3719,9 @@
 
   bool any(bool f(Number element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Number> toList() => new List<Number>.from(this);
+  List<Number> toList({ bool growable: true }) =>
+      new List<Number>.from(this, growable: growable);
+
   Set<Number> toSet() => new Set<Number>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -4574,7 +4578,7 @@
   @DocsEditable
   final int numberOfItems;
 
-  PathSeg operator[](int index) => JS("PathSeg", "#[#]", this, index);
+  PathSeg operator[](int index) => this.getItem(index);
 
   void operator[]=(int index, PathSeg value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -4617,7 +4621,9 @@
 
   bool any(bool f(PathSeg element)) => IterableMixinWorkaround.any(this, f);
 
-  List<PathSeg> toList() => new List<PathSeg>.from(this);
+  List<PathSeg> toList({ bool growable: true }) =>
+      new List<PathSeg>.from(this, growable: growable);
+
   Set<PathSeg> toSet() => new Set<PathSeg>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -5458,7 +5464,7 @@
   @DocsEditable
   final int numberOfItems;
 
-  String operator[](int index) => JS("String", "#[#]", this, index);
+  String operator[](int index) => this.getItem(index);
 
   void operator[]=(int index, String value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -5501,7 +5507,9 @@
 
   bool any(bool f(String element)) => IterableMixinWorkaround.any(this, f);
 
-  List<String> toList() => new List<String>.from(this);
+  List<String> toList({ bool growable: true }) =>
+      new List<String>.from(this, growable: growable);
+
   Set<String> toSet() => new Set<String>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -6620,7 +6628,7 @@
   @DocsEditable
   final int numberOfItems;
 
-  Transform operator[](int index) => JS("Transform", "#[#]", this, index);
+  Transform operator[](int index) => this.getItem(index);
 
   void operator[]=(int index, Transform value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -6663,7 +6671,9 @@
 
   bool any(bool f(Transform element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Transform> toList() => new List<Transform>.from(this);
+  List<Transform> toList({ bool growable: true }) =>
+      new List<Transform>.from(this, growable: growable);
+
   Set<Transform> toSet() => new Set<Transform>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -7139,7 +7149,7 @@
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  ElementInstance operator[](int index) => JS("ElementInstance", "#[#]", this, index);
+  ElementInstance operator[](int index) => this.item(index);
 
   void operator[]=(int index, ElementInstance value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -7180,7 +7190,9 @@
 
   bool any(bool f(ElementInstance element)) => IterableMixinWorkaround.any(this, f);
 
-  List<ElementInstance> toList() => new List<ElementInstance>.from(this);
+  List<ElementInstance> toList({ bool growable: true }) =>
+      new List<ElementInstance>.from(this, growable: growable);
+
   Set<ElementInstance> toSet() => new Set<ElementInstance>.from(this);
 
   bool get isEmpty => this.length == 0;
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index d6b19dd..d049d13 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -3356,7 +3356,9 @@
 
   bool any(bool f(Length element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Length> toList() => new List<Length>.from(this);
+  List<Length> toList({ bool growable: true }) =>
+      new List<Length>.from(this, growable: growable);
+
   Set<Length> toSet() => new Set<Length>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -4057,7 +4059,9 @@
 
   bool any(bool f(Number element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Number> toList() => new List<Number>.from(this);
+  List<Number> toList({ bool growable: true }) =>
+      new List<Number>.from(this, growable: growable);
+
   Set<Number> toSet() => new Set<Number>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -5234,7 +5238,9 @@
 
   bool any(bool f(PathSeg element)) => IterableMixinWorkaround.any(this, f);
 
-  List<PathSeg> toList() => new List<PathSeg>.from(this);
+  List<PathSeg> toList({ bool growable: true }) =>
+      new List<PathSeg>.from(this, growable: growable);
+
   Set<PathSeg> toSet() => new Set<PathSeg>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -6216,7 +6222,9 @@
 
   bool any(bool f(String element)) => IterableMixinWorkaround.any(this, f);
 
-  List<String> toList() => new List<String>.from(this);
+  List<String> toList({ bool growable: true }) =>
+      new List<String>.from(this, growable: growable);
+
   Set<String> toSet() => new Set<String>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -7467,7 +7475,9 @@
 
   bool any(bool f(Transform element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Transform> toList() => new List<Transform>.from(this);
+  List<Transform> toList({ bool growable: true }) =>
+      new List<Transform>.from(this, growable: growable);
+
   Set<Transform> toSet() => new Set<Transform>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -8038,7 +8048,9 @@
 
   bool any(bool f(ElementInstance element)) => IterableMixinWorkaround.any(this, f);
 
-  List<ElementInstance> toList() => new List<ElementInstance>.from(this);
+  List<ElementInstance> toList({ bool growable: true }) =>
+      new List<ElementInstance>.from(this, growable: growable);
+
   Set<ElementInstance> toSet() => new Set<ElementInstance>.from(this);
 
   bool get isEmpty => this.length == 0;
diff --git a/sdk/lib/uri/encode_decode.dart b/sdk/lib/uri/encode_decode.dart
index e13d284..124c803 100644
--- a/sdk/lib/uri/encode_decode.dart
+++ b/sdk/lib/uri/encode_decode.dart
@@ -114,7 +114,7 @@
   var byteToHex = (int v) => '%${hex[v >> 4]}${hex[v & 0x0f]}';
   StringBuffer result = new StringBuffer();
   for (int i = 0; i < text.length; i++) {
-    int ch = text.charCodeAt(i);
+    int ch = text.codeUnitAt(i);
     if (ch < 128 && ((canonicalTable[ch >> 4] & (1 << (ch & 0x0f))) != 0)) {
       result.add(text[i]);
     } else if (text[i] == " ") {
@@ -123,10 +123,10 @@
       if (ch >= 0xD800 && ch < 0xDC00) {
         // Low surrogate. We expect a next char high surrogate.
         ++i;
-        int nextCh = text.length == i ? 0 : text.charCodeAt(i);
+        int nextCh = text.length == i ? 0 : text.codeUnitAt(i);
         if (nextCh >= 0xDC00 && nextCh < 0xE000) {
           // convert the pair to a U+10000 codepoint
-          ch = 0x10000 + ((ch-0xD800) << 10) + (nextCh - 0xDC00);
+          ch = 0x10000 + ((ch - 0xD800) << 10) + (nextCh - 0xDC00);
         } else {
           throw new ArgumentError('Malformed URI');
         }
@@ -143,11 +143,10 @@
  * Convert a byte (2 character hex sequence) in string [s] starting
  * at position [pos] to its ordinal value
  */
-
 int _hexCharPairToByte(String s, int pos) {
   int byte = 0;
   for (int i = 0; i < 2; i++) {
-    var charCode = s.charCodeAt(pos + i);
+    var charCode = s.codeUnitAt(pos + i);
     if (0x30 <= charCode && charCode <= 0x39) {
       byte = byte * 16 + charCode - 0x30;
     } else {
diff --git a/sdk/lib/uri/uri_sources.gypi b/sdk/lib/uri/uri_sources.gypi
index 87e234a..b777678 100644
--- a/sdk/lib/uri/uri_sources.gypi
+++ b/sdk/lib/uri/uri_sources.gypi
@@ -5,6 +5,8 @@
 # This file contains all sources for the dart:uri library.
 {
   'sources': [
+    'uri.dart',
+    # The above file needs to be first as it lists the parts below.
     'uri_base.dart',
     'helpers.dart',
     'encode_decode.dart',
diff --git a/sdk/lib/utf/utf16.dart b/sdk/lib/utf/utf16.dart
index c451b1e..9794a81 100644
--- a/sdk/lib/utf/utf16.dart
+++ b/sdk/lib/utf/utf16.dart
@@ -113,7 +113,7 @@
 List<int> encodeUtf16be(String str, [bool writeBOM = false]) {
   List<int> utf16CodeUnits = _stringToUtf16CodeUnits(str);
   List<int> encoding =
-      new List<int>.fixedLength(2 * utf16CodeUnits.length + (writeBOM ? 2 : 0));
+      new List<int>(2 * utf16CodeUnits.length + (writeBOM ? 2 : 0));
   int i = 0;
   if (writeBOM) {
     encoding[i++] = UNICODE_UTF_BOM_HI;
@@ -133,7 +133,7 @@
 List<int> encodeUtf16le(String str, [bool writeBOM = false]) {
   List<int> utf16CodeUnits = _stringToUtf16CodeUnits(str);
   List<int> encoding =
-      new List<int>.fixedLength(2 * utf16CodeUnits.length + (writeBOM ? 2 : 0));
+      new List<int>(2 * utf16CodeUnits.length + (writeBOM ? 2 : 0));
   int i = 0;
   if (writeBOM) {
     encoding[i++] = UNICODE_UTF_BOM_LO;
@@ -178,7 +178,7 @@
 }
 
 List<int> _stringToUtf16CodeUnits(String str) {
-  return _codepointsToUtf16CodeUnits(str.charCodes);
+  return _codepointsToUtf16CodeUnits(str.codeUnits);
 }
 
 typedef _ListRangeIterator _CodeUnitsProvider();
@@ -238,7 +238,7 @@
    * over-allocates the List containing results.
    */
   List<int> decodeRest() {
-    List<int> codeunits = new List<int>.fixedLength(remaining);
+    List<int> codeunits = new List<int>(remaining);
     int i = 0;
     while (moveNext()) {
       codeunits[i++] = current;
@@ -246,7 +246,7 @@
     if (i == codeunits.length) {
       return codeunits;
     } else {
-      List<int> truncCodeunits = new List<int>.fixedLength(i);
+      List<int> truncCodeunits = new List<int>(i);
       truncCodeunits.setRange(0, i, codeunits);
       return truncCodeunits;
     }
diff --git a/sdk/lib/utf/utf32.dart b/sdk/lib/utf/utf32.dart
index acf6ac3..1e43f01 100644
--- a/sdk/lib/utf/utf32.dart
+++ b/sdk/lib/utf/utf32.dart
@@ -222,7 +222,7 @@
   }
 
   List<int> decodeRest() {
-    List<int> codeunits = new List<int>.fixedLength(remaining);
+    List<int> codeunits = new List<int>(remaining);
     int i = 0;
     while (moveNext()) {
       codeunits[i++] = current;
diff --git a/sdk/lib/utf/utf8.dart b/sdk/lib/utf/utf8.dart
index 4bf216f..b44cbe4 100644
--- a/sdk/lib/utf/utf8.dart
+++ b/sdk/lib/utf/utf8.dart
@@ -86,7 +86,7 @@
     }
   }
 
-  List<int> encoded = new List<int>.fixedLength(encodedLength);
+  List<int> encoded = new List<int>(encodedLength);
   int insertAt = 0;
   for (int value in source) {
     if (value < 0 || value > UNICODE_VALID_RANGE_MAX) {
@@ -173,7 +173,7 @@
     * into a [List<int>].
     */
   List<int> decodeRest() {
-    List<int> codepoints = new List<int>.fixedLength(utf8EncodedBytesIterator.remaining);
+    List<int> codepoints = new List<int>(utf8EncodedBytesIterator.remaining);
     int i = 0;
     while (moveNext()) {
       codepoints[i++] = current;
@@ -181,7 +181,7 @@
     if (i == codepoints.length) {
       return codepoints;
     } else {
-      List<int> truncCodepoints = new List<int>.fixedLength(i);
+      List<int> truncCodepoints = new List<int>(i);
       truncCodepoints.setRange(0, i, codepoints);
       return truncCodepoints;
     }
diff --git a/sdk/lib/utf/utf_core.dart b/sdk/lib/utf/utf_core.dart
index 15ca45e..30ad2dc 100644
--- a/sdk/lib/utf/utf_core.dart
+++ b/sdk/lib/utf/utf_core.dart
@@ -9,9 +9,9 @@
  * Provide a list of Unicode codepoints for a given string.
  */
 List<int> stringToCodepoints(String str) {
-  // Note: str.charCodes gives us 16-bit code units on all Dart implementations.
+  // Note: str.codeUnits gives us 16-bit code units on all Dart implementations.
   // So we need to convert.
-  return _utf16CodeUnitsToCodepoints(str.charCodes);
+  return _utf16CodeUnitsToCodepoints(str.codeUnits);
 }
 
 /**
@@ -64,7 +64,7 @@
     }
   }
 
-  List<int> codeUnitsBuffer = new List<int>.fixedLength(encodedLength);
+  List<int> codeUnitsBuffer = new List<int>(encodedLength);
   int j = 0;
   for (int value in listRange) {
     if ((value >= 0 && value < UNICODE_UTF16_RESERVED_LO) ||
@@ -96,7 +96,7 @@
       (new _ListRange(utf16CodeUnits, offset, length)).iterator;
   Utf16CodeUnitDecoder decoder = new Utf16CodeUnitDecoder
       .fromListRangeIterator(source, replacementCodepoint);
-  List<int> codepoints = new List<int>.fixedLength(source.remaining);
+  List<int> codepoints = new List<int>(source.remaining);
   int i = 0;
   while (decoder.moveNext()) {
     codepoints[i++] = decoder.current;
@@ -104,7 +104,7 @@
   if (i == codepoints.length) {
     return codepoints;
   } else {
-    List<int> codepointTrunc = new List<int>.fixedLength(i);
+    List<int> codepointTrunc = new List<int>(i);
     codepointTrunc.setRange(0, i, codepoints);
     return codepointTrunc;
   }
diff --git a/sdk/lib/utf/utf_sources.gypi b/sdk/lib/utf/utf_sources.gypi
index 9d86ff1..b11d1f5 100644
--- a/sdk/lib/utf/utf_sources.gypi
+++ b/sdk/lib/utf/utf_sources.gypi
@@ -3,11 +3,10 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file contains all sources for the dart:utf library.
-#
-# TODO(ager): When the VM can use the #source directive for libraries.
-# At that point utf.dart should be the only utf library file.
 {
   'sources': [
+    'utf.dart',
+    # The above file needs to be first as it lists the parts below.
     'utf_core.dart',
     'utf_stream.dart',
     'utf8.dart',
diff --git a/sdk/lib/utf/utf_stream.dart b/sdk/lib/utf/utf_stream.dart
index ad69c62..71dc76d 100644
--- a/sdk/lib/utf/utf_stream.dart
+++ b/sdk/lib/utf/utf_stream.dart
@@ -14,45 +14,15 @@
   }
 }
 
-abstract class _StringDecoder implements StreamTransformer<List<int>, String> {
-  _HelperStreamController<String> _controller;
-  StreamSubscription<List<int>> _subscription;
+abstract class _StringDecoder
+    extends StreamEventTransformer<List<int>, String> {
   List<int> _carry;
   List<int> _buffer;
   int _replacementChar;
-  bool _paused = false;
 
-  _StringDecoder(int this._replacementChar) {
-    _controller = new _HelperStreamController<String>(_onPauseChanged);
-  }
+  _StringDecoder(int this._replacementChar);
 
-  void _onPauseChanged() {
-    _paused = _controller.isPaused;
-    if (_subscription == null) return;
-    if (_paused) {
-      _subscription.pause();
-    } else {
-      _subscription.resume();
-    }
-  }
-
-  Stream<String> bind(Stream<List<int>> stream) {
-    _subscription = stream.listen(
-        _onData,
-        onError: _controller.signalError,
-        onDone: () {
-          if (_carry != null) {
-            _controller.add(new String.fromCharCodes(
-                new List.fixedLength(_carry.length, fill: _replacementChar)));
-          }
-          _controller.close();
-        },
-        unsubscribeOnError: false);
-    if (_paused) _subscription.pause();
-    return _controller.stream;
-  }
-
-  void _onData(List<int> bytes) {
+  void handleData(List<int> bytes, StreamSink<String> sink) {
     _buffer = <int>[];
     List<int> carry = _carry;
     _carry = null;
@@ -94,11 +64,19 @@
     }
     if (_buffer.length > 0) {
       // Limit to 'goodChars', if lower than actual charCodes in the buffer.
-      _controller.add(new String.fromCharCodes(_buffer));
+      sink.add(new String.fromCharCodes(_buffer));
     }
     _buffer = null;
   }
 
+  void handleDone(StreamSink<String> sink) {
+    if (_carry != null) {
+      sink.add(new String.fromCharCodes(
+          new List.filled(_carry.length, _replacementChar)));
+    }
+    sink.close();
+  }
+
   int _processBytes(int getNext());
 
   void _addChar(int char) {
@@ -161,25 +139,11 @@
 }
 
 
-abstract class _StringEncoder implements StreamTransformer<String, List<int>> {
-  _HelperStreamController<List<int>> _controller;
-  StreamSubscription<String> _subscription;
+abstract class _StringEncoder
+    extends StreamEventTransformer<String, List<int>> {
 
-  void _onPauseChanged() {
-    if (_controller.isPaused) {
-      _subscription.pause();
-    } else {
-      _subscription.resume();
-    }
-  }
-  Stream<List<int>> bind(Stream<String> stream) {
-    _controller = new _HelperStreamController(_onPauseChanged);
-    _subscription = stream.listen(
-        (string) => _controller.add(_processString(string)),
-        onError: _controller.signalError,
-        onDone: _controller.close,
-        unsubscribeOnError: false);
-    return _controller.stream;
+  void handleData(String data, StreamSink<List<int>> sink) {
+    sink.add(_processString(data));
   }
 
   List<int> _processString(String string);
@@ -192,7 +156,7 @@
   List<int> _processString(String string) {
     var bytes = [];
     int pos = 0;
-    List<int> codepoints = _utf16CodeUnitsToCodepoints(string.charCodes);
+    List<int> codepoints = _utf16CodeUnitsToCodepoints(string.codeUnits);
     int length = codepoints.length;
     for (int i = 0; i < length; i++) {
       int additionalBytes;
diff --git a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
index 8559913..7b68ee5 100644
--- a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -1,3 +1,13 @@
+/**
+ * An API for storing data in the browser that can be queried with SQL.
+ *
+ * **Caution:** this specification is no longer actively maintained by the Web
+ * Applications Working Group and may be removed at any time.
+ * See [the W3C Web SQL Database specification](http://www.w3.org/TR/webdatabase/)
+ * for more information.
+ *
+ * The [dart:indexed_db] APIs is a recommended alternatives.
+ */
 library dart.dom.web_sql;
 
 import 'dart:async';
@@ -80,6 +90,18 @@
   @DocsEditable
   final String version;
 
+  /**
+   * Atomically update the database version to [newVersion], asynchronously
+   * running [callback] on the [SqlTransaction] representing this
+   * [changeVersion] transaction.
+   *
+   * If [callback] runs successfully, then [successCallback] is called.
+   * Otherwise, [errorCallback] is called.
+   *
+   * [oldVersion] should match the database's current [version] exactly.
+   *
+   * * [Database.changeVersion](http://www.w3.org/TR/webdatabase/#dom-database-changeversion) from W3C.
+   */
   @DomName('Database.changeVersion')
   @DocsEditable
   void changeVersion(String oldVersion, String newVersion, [SqlTransactionCallback callback, SqlTransactionErrorCallback errorCallback, VoidCallback successCallback]) native;
@@ -224,7 +246,7 @@
   @DocsEditable
   int get length => JS("int", "#.length", this);
 
-  Map operator[](int index) => JS("Map", "#[#]", this, index);
+  Map operator[](int index) => this.item(index);
 
   void operator[]=(int index, Map value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -265,7 +287,9 @@
 
   bool any(bool f(Map element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Map> toList() => new List<Map>.from(this);
+  List<Map> toList({ bool growable: true }) =>
+      new List<Map>.from(this, growable: growable);
+
   Set<Map> toSet() => new Set<Map>.from(this);
 
   bool get isEmpty => this.length == 0;
diff --git a/sdk/lib/web_sql/dartium/web_sql_dartium.dart b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
index c25f0ae..c6b7de5 100644
--- a/sdk/lib/web_sql/dartium/web_sql_dartium.dart
+++ b/sdk/lib/web_sql/dartium/web_sql_dartium.dart
@@ -1,3 +1,13 @@
+/**
+ * An API for storing data in the browser that can be queried with SQL.
+ *
+ * **Caution:** this specification is no longer actively maintained by the Web
+ * Applications Working Group and may be removed at any time.
+ * See [the W3C Web SQL Database specification](http://www.w3.org/TR/webdatabase/)
+ * for more information.
+ *
+ * The [dart:indexed_db] APIs is a recommended alternatives.
+ */
 library dart.dom.web_sql;
 
 import 'dart:async';
@@ -82,6 +92,18 @@
   @DocsEditable
   String get version native "Database_version_Getter";
 
+  /**
+   * Atomically update the database version to [newVersion], asynchronously
+   * running [callback] on the [SqlTransaction] representing this
+   * [changeVersion] transaction.
+   *
+   * If [callback] runs successfully, then [successCallback] is called.
+   * Otherwise, [errorCallback] is called.
+   *
+   * [oldVersion] should match the database's current [version] exactly.
+   *
+   * * [Database.changeVersion](http://www.w3.org/TR/webdatabase/#dom-database-changeversion) from W3C.
+   */
   @DomName('Database.changeVersion')
   @DocsEditable
   void changeVersion(String oldVersion, String newVersion, [SqlTransactionCallback callback, SqlTransactionErrorCallback errorCallback, VoidCallback successCallback]) native "Database_changeVersion_Callback";
@@ -287,7 +309,9 @@
 
   bool any(bool f(Map element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Map> toList() => new List<Map>.from(this);
+  List<Map> toList({ bool growable: true }) =>
+      new List<Map>.from(this, growable: growable);
+
   Set<Map> toSet() => new Set<Map>.from(this);
 
   bool get isEmpty => this.length == 0;
diff --git a/tests/co19/co19-compiler.status b/tests/co19/co19-compiler.status
index 60c8924..5038551 100644
--- a/tests/co19/co19-compiler.status
+++ b/tests/co19/co19-compiler.status
@@ -4,133 +4,111 @@
 
 [ $compiler == dartc ]
 
-# co19 issue 365 (iterator changes)
-Language/12_Statements/06_For/2_For_in_A01_t05: Fail # co19 issue 365
-LibTest/core/Set/Set.from_A01_t02: Fail # co19 issue 365
-LibTest/core/Queue/Queue.from_A01_t02: Fail # co19 issue 365
+Language/12_Statements/06_For/2_For_in_A01_t05: Fail # co19 issue 365 # co19 issue 365 (iterator changes)
+LibTest/core/Set/Set.from_A01_t02: Fail # co19 issue 365 # co19 issue 365 (iterator changes)
+LibTest/core/Queue/Queue.from_A01_t02: Fail # co19 issue 365 # co19 issue 365 (iterator changes)
 
-# co19 issue 336 (allow use same prefix for several imports)
-Language/13_Libraries_and_Scripts/1_Imports_A02_t29: Fail
+Language/13_Libraries_and_Scripts/1_Imports_A02_t29: Fail # co19 issue 336 (allow use same prefix for several imports)
 
 
-# co19 issue 337 (export in scripts is allowed in 0.13)
-Language/13_Libraries_and_Scripts/4_Scripts_A01_t21: Fail
-Language/13_Libraries_and_Scripts/4_Scripts_A01_t23: Fail
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t21: Fail # co19 issue 337 (export in scripts is allowed in 0.13)
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t23: Fail # co19 issue 337 (export in scripts is allowed in 0.13)
 
 
-# co19 issue 335 (assignment to final is warning, not error)
-Language/05_Variables/05_Variables_A07_t01: Fail
-Language/05_Variables/05_Variables_A07_t02: Fail
-Language/05_Variables/05_Variables_A07_t03: Fail
-Language/05_Variables/05_Variables_A07_t04: Fail
-Language/05_Variables/05_Variables_A07_t10: Fail
-Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t05: Fail
-Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A01_t06: Fail
+Language/05_Variables/05_Variables_A07_t01: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/05_Variables/05_Variables_A07_t02: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/05_Variables/05_Variables_A07_t03: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/05_Variables/05_Variables_A07_t04: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/05_Variables/05_Variables_A07_t10: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t05: Fail # co19 issue 335 (assignment to final is warning, not error)
+Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A01_t06: Fail # co19 issue 335 (assignment to final is warning, not error)
 
-# co19 issue 344 ('null' is constant, so can be used in 'case')
-Language/12_Statements/09_Switch_A02_t03: Fail
+Language/12_Statements/09_Switch_A02_t03: Fail # co19 issue 344 ('null' is constant, so can be used in 'case')
 
-# co19 343 (invalid unicode NFC)
-Language/15_Reference/1_Lexical_Rules_A01_t10: Fail
+Language/15_Reference/1_Lexical_Rules_A01_t10: Fail # co19 343 (invalid unicode NFC)
 
 
-# co19 issue 339 (type variable is not constant)
-Language/11_Expressions/01_Constants_A20_t03: Fail
+Language/11_Expressions/01_Constants_A20_t03: Fail # co19 issue 339 (type variable is not constant)
 
 
-# co19 issue 340 (deprecated catch syntax)
-Language/11_Expressions/08_Throw_A05_t01: Fail
-Language/12_Statements/10_Try_A03_t02: Fail
-Language/12_Statements/10_Try_A03_t03: Fail
+Language/11_Expressions/08_Throw_A05_t01: Fail # co19 issue 340 (deprecated catch syntax)
+Language/12_Statements/10_Try_A03_t02: Fail # co19 issue 340 (deprecated catch syntax)
+Language/12_Statements/10_Try_A03_t03: Fail # co19 issue 340 (deprecated catch syntax)
 
 
-# co19 issue 341 (class Type has no type parameters)
-Language/11_Expressions/31_Type_Test_A01_t02: Fail
-Language/11_Expressions/31_Type_Test_A01_t04: Fail
+Language/11_Expressions/31_Type_Test_A01_t02: Fail # co19 issue 341 (class Type has no type parameters)
+Language/11_Expressions/31_Type_Test_A01_t04: Fail # co19 issue 341 (class Type has no type parameters)
 
 
-# co19 issue 342 (class can be used anywhere, including left side of "as")
-Language/11_Expressions/32_Type_Cast_A01_t04: Fail
+Language/11_Expressions/32_Type_Cast_A01_t04: Fail # co19 issue 342 (class can be used anywhere, including left side of "as")
 
 
-# co19 issue 345 (optional parameters list cannot by empty)
-Language/14_Types/5_Function_Types_A04_t01: Fail
+Language/14_Types/5_Function_Types_A04_t01: Fail # co19 issue 345 (optional parameters list cannot by empty)
 
-# co19 issue 346 (invalid 'one ugly cascade')
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: Fail
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: Fail # co19 issue 346 (invalid 'one ugly cascade')
 
-# co19 issue 347 (duplicate class in implements clause)
-Language/08_Interfaces/5_Superinterfaces_A01_t02: Fail
+Language/08_Interfaces/5_Superinterfaces_A01_t02: Fail # co19 issue 347 (duplicate class in implements clause)
+
+Language/13_Libraries_and_Scripts/1_Imports_A02_t12: Fail, OK # co19 issue 320
+Language/13_Libraries_and_Scripts/1_Imports_A02_t15: Fail, OK # co19 issue 320
+Language/13_Libraries_and_Scripts/1_Imports_A02_t18: Fail, OK # co19 issue 320
+Language/13_Libraries_and_Scripts/1_Imports_A02_t19: Fail, OK # co19 issue 320
 
 
-# co19 issue 320
-Language/13_Libraries_and_Scripts/1_Imports_A02_t12: Fail, OK
-Language/13_Libraries_and_Scripts/1_Imports_A02_t15: Fail, OK
-Language/13_Libraries_and_Scripts/1_Imports_A02_t18: Fail, OK
-Language/13_Libraries_and_Scripts/1_Imports_A02_t19: Fail, OK
+Language/13_Libraries_and_Scripts/1_Imports_A02_t16: Fail, OK # co19 issue 298
+Language/13_Libraries_and_Scripts/1_Imports_A02_t17: Fail, OK # co19 issue 298
 
 
-# co19 issue 298
-Language/13_Libraries_and_Scripts/1_Imports_A02_t16: Fail, OK
-Language/13_Libraries_and_Scripts/1_Imports_A02_t17: Fail, OK
+LibTest/core/Expect/approxEquals_A04_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/equals_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/identical_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/isFalse_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/isNotNull_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/isNull_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/isTrue_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/listEquals_A03_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/notEquals_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/setEquals_A03_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/stringEquals_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Expect/throws_A01_t04: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Future/chain_A02_t04: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Future/chain_A02_t05: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Future/transform_A02_t03: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Future/transform_A02_t04: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/every_A04_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/filter_A04_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/forEach_A03_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/List.from_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/operator_subscript_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/operator_subscript_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/operator_subscripted_assignment_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/operator_subscripted_assignment_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/List/setRange_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Queue/addFirst_A01_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/Set/intersection_A01_t03: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/String/toLowerCase_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/String/toUpperCase_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/String/trim_A01_t02: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/StringBuffer/add_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/StringBuffer/addAll_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+LibTest/core/StringBuffer/clear_A02_t01: Fail # co19 issue 351 (use deprecated === and !==)
+
+LibTest/isolate/SendPort/send_A01_t01: Fail # co19 issue 352 (use function expression with return type and name)
+
+Language/07_Classes/6_Constructors/2_Factories_A01_t02: Fail # co19 issue 354
 
 
-# co19 issue 351 (use deprecated === and !==)
-LibTest/core/Expect/approxEquals_A04_t01: Fail
-LibTest/core/Expect/equals_A02_t01: Fail
-LibTest/core/Expect/identical_A02_t01: Fail
-LibTest/core/Expect/isFalse_A02_t01: Fail
-LibTest/core/Expect/isNotNull_A02_t01: Fail
-LibTest/core/Expect/isNull_A02_t01: Fail
-LibTest/core/Expect/isTrue_A02_t01: Fail
-LibTest/core/Expect/listEquals_A03_t01: Fail
-LibTest/core/Expect/notEquals_A02_t01: Fail
-LibTest/core/Expect/setEquals_A03_t01: Fail
-LibTest/core/Expect/stringEquals_A02_t01: Fail
-LibTest/core/Expect/throws_A01_t04: Fail
-LibTest/core/Future/chain_A02_t04: Fail
-LibTest/core/Future/chain_A02_t05: Fail
-LibTest/core/Future/transform_A02_t03: Fail
-LibTest/core/Future/transform_A02_t04: Fail
-LibTest/core/List/every_A04_t01: Fail
-LibTest/core/List/filter_A04_t01: Fail
-LibTest/core/List/forEach_A03_t01: Fail
-LibTest/core/List/List.from_A01_t01: Fail
-LibTest/core/List/operator_subscript_A01_t01: Fail
-LibTest/core/List/operator_subscript_A01_t02: Fail
-LibTest/core/List/operator_subscripted_assignment_A01_t02: Fail
-LibTest/core/List/operator_subscripted_assignment_A01_t01: Fail
-LibTest/core/List/setRange_A01_t01: Fail
-LibTest/core/Queue/addFirst_A01_t01: Fail
-LibTest/core/Set/intersection_A01_t03: Fail
-LibTest/core/String/toLowerCase_A01_t02: Fail
-LibTest/core/String/toUpperCase_A01_t02: Fail
-LibTest/core/String/trim_A01_t02: Fail
-LibTest/core/StringBuffer/add_A02_t01: Fail
-LibTest/core/StringBuffer/addAll_A02_t01: Fail
-LibTest/core/StringBuffer/clear_A02_t01: Fail
-
-# co19 issue 352 (use function expression with return type and name)
-LibTest/isolate/SendPort/send_A01_t01: Fail
-
-
-# co19 issue 354
-Language/07_Classes/6_Constructors/2_Factories_A01_t02: Fail
-
-
-# co19 issue 372 (@static-clean where type warnings are expected)
-Language/07_Classes/6_Constructors_A03_t03: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t04: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t05: Fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A01_t01: Fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A02_t01: Fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A06_t01: Fail
+Language/07_Classes/6_Constructors_A03_t03: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t04: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t05: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A01_t01: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A02_t01: Fail # co19 issue 372 (@static-clean where type warnings are expected)
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A06_t01: Fail # co19 issue 372 (@static-clean where type warnings are expected)
 
 
 
 
-# testing framework or VM issue 7388 (dies on Turkish character)
-Language/11_Expressions/30_Identifier_Reference_A01_t08: Skip
+Language/11_Expressions/30_Identifier_Reference_A01_t08: Skip # testing framework or VM issue 7388 (dies on Turkish character)
 
 
 Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t02: Fail, OK # deprecated parameter syntax
@@ -503,5 +481,17 @@
 LibTest/core/Strings/concatAll_A03_t01: Fail # Strings class has been removed. co19 issue 380
 LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
 
+LibTest/core/RegExp/RegExp_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/toString_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/IllegalJSRegExpException_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+
+LibTest/core/String/charCodeAt_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A02_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A03_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodes_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/splitChars_A01_t01: Fail # Deprecated string members removed (issue 382).
+
 [ $runtime == drt && ($compiler == none || $compiler == frog) ]
 *: Skip
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 659bf48..0445889 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -34,13 +34,12 @@
 
 Language/12_Statements/02_Expression_Statements_A01_t08: Fail # co 19 issue 370
 
-# Calling unresolved class constructor:
-Language/03_Overview/2_Privacy_A01_t19: Fail
-Language/03_Overview/2_Privacy_A01_t20: Fail
-Language/07_Classes/6_Constructors_A03_t03: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t04: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t05: Fail
-Language/11_Expressions/11_Instance_Creation/1_New_A06_t06: Fail
+Language/03_Overview/2_Privacy_A01_t19: Fail # Calling unresolved class constructor.
+Language/03_Overview/2_Privacy_A01_t20: Fail # Calling unresolved class constructor.
+Language/07_Classes/6_Constructors_A03_t03: Fail # Calling unresolved class constructor.
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t04: Fail # Calling unresolved class constructor.
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t05: Fail # Calling unresolved class constructor.
+Language/11_Expressions/11_Instance_Creation/1_New_A06_t06: Fail # Calling unresolved class constructor.
 
 Language/03_Overview/1_Scoping_A01_t39: Fail # http://dartbug.com/5519
 Language/03_Overview/1_Scoping_A01_t40: Fail # http://dartbug.com/5519
@@ -352,7 +351,6 @@
 Language/14_Types/3_Type_Declarations/1_Typedef_A07_t02: Fail, Pass # inherited from dart2js: fails in minify, self-reference typedef check not performed
 Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: Fail, Pass # inherited from dart2js: fails in minify, self-reference typedef check not performed
 Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: Fail # Inherited from dart2js
-Language/14_Types/5_Function_Types_A01_t03: Fail # Inherited from dart2js
 Language/14_Types/5_Function_Types_A06_t01: Fail # Inherited from dart2js
 Language/15_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: Fail # inherited from dart2js
 Language/15_Reference/1_Lexical_Rules_A02_t06: Fail # inherited from dart2js
@@ -436,15 +434,6 @@
 LibTest/core/Queue/forEach_A01_t04: Fail # behavior of forEach is undefined when underlying iterable changes, co19 issue 357
 
 LibTest/core/List/List_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/List_A01_t02: Fail # List constructors, co19 issue 358
-LibTest/core/List/add_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addAll_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addLast_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/clear_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/insertRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/length_A04_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeLast_A02_t01: Fail # List constructors, co19 issue 358
 
 LibTest/core/List/last_A02_t01: Fail # List.last throws a StateError, co19 issue 359
 
@@ -655,19 +644,28 @@
 LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
 LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
 
-# Doesn't expect null to be allowed in Set or Map keys (issue 377).
-LibTest/core/Map/containsKey_A01_t02: Fail
-LibTest/core/Map/operator_subscript_A01_t02: Fail
-LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail
-LibTest/core/Map/remove_A01_t02: Fail
-LibTest/core/Set/add_A01_t02: Fail
-LibTest/core/Set/addAll_A01_t02: Fail
-LibTest/core/Set/contains_A01_t02: Fail
-LibTest/core/Set/containsAll_A01_t02: Fail
-LibTest/core/Set/intersection_A03_t01: Fail
-LibTest/core/Set/isSubsetOf_A01_t02: Fail
-LibTest/core/Set/remove_A01_t02: Fail
-LibTest/core/Set/removeAll_A01_t02: Fail
+LibTest/core/RegExp/RegExp_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/toString_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/IllegalJSRegExpException_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
 
-# Doesn't expect concurrent modification error (issue 376).
-LibTest/core/Map/forEach_A01_t07: Fail
+LibTest/core/Map/containsKey_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscript_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/add_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/addAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/contains_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/containsAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/intersection_A03_t01: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/isSubsetOf_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/removeAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+
+LibTest/core/Map/forEach_A01_t07: Fail # Doesn't expect concurrent modification error (issue 376).
+
+LibTest/core/String/charCodes_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A02_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A03_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/splitChars_A01_t01: Fail # Deprecated string members removed (issue 382).
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index e311447..ccc970e 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -156,8 +156,9 @@
 LibTest/core/StringBuffer/isEmpty_A01_t01:  Fail, OK # co19 issue 355
 LibTest/core/StringBuffer/clear_A02_t01: Fail, OK # co19 issue 355
 
-# Partially implemented rediriecting constructors makes this fail.
-Language/07_Classes/6_Constructors/2_Factories_A01_t05: Fail
+Language/07_Classes/6_Constructors/2_Factories_A01_t05: Fail # Partially implemented rediriecting constructors makes this fail.
+
+Language/09_Generics/09_Generics_A04_t03: Fail # dart2js does not treat 2.0 as a double; dartbug.com/1533
 
 [ $compiler == dart2js && ($system == linux || $system == macos)]
 LibTest/math/exp_A01_t01: Fail # TODO(ahe): Please triage this failure.
@@ -244,17 +245,13 @@
 LibTest/core/int/operator_addition_A01_t01: Fail, OK # co19 issue 200
 LibTest/core/int/toDouble_A01_t01: Fail, OK # co19 issue 200
 
-# Slow tests that needs extra time to finish.
-LibTest/core/List/sort_A01_t06: Slow, Pass
+LibTest/core/List/sort_A01_t06: Slow, Pass # Slow tests that needs extra time to finish.
 
-# Tests that fail because they use the legacy try-catch syntax.
-# See co19 issue 184.
-LibTest/core/List/getRange_A03_t01: Fail, OK
-LibTest/core/List/setRange_A05_t01: Fail, OK
+LibTest/core/List/getRange_A03_t01: Fail, OK # Tests that fail because they use the legacy try-catch syntax. co19 issue 184.
+LibTest/core/List/setRange_A05_t01: Fail, OK # Tests that fail because they use the legacy try-catch syntax. co19 issue 184.
 
-# These tests need to be updated for new optional parameter syntax and semantics, co19 issue 258:
-Language/07_Classes/1_Instance_Methods_A02_t05: Fail, OK
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A13_t01: Fail, OK
+Language/07_Classes/1_Instance_Methods_A02_t05: Fail, OK # These tests need to be updated for new optional parameter syntax and semantics, co19 issue 258:
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A13_t01: Fail, OK # These tests need to be updated for new optional parameter syntax and semantics, co19 issue 258:
 
 LibTest/isolate/SendPort/send_A02_t02: Fail, OK # co19 issue 293
 LibTest/isolate/SendPort/send_A02_t03: Fail, OK # co19 issue 293
@@ -306,9 +303,7 @@
 LibTest/core/int/operator_OR_A01_t01: Fail, OK # Requires bigints.
 LibTest/core/int/operator_remainder_A01_t01: Fail, OK # Requires bigints.
 
-# The following tests use the deprecated Date interface.
-# Issue co19 - 125
-LibTest/core/Date/toString_A02_t01: Fail, OK
+LibTest/core/Date/toString_A02_t01: Fail # Argument error. Year 999999 is out of range. Needs to be specified (and then potentially reported to co19): issue 1878.
 
 LibTest/core/Match/pattern_A01_t01: Fail, OK # co19 issue 212
 LibTest/core/Match/str_A01_t01: Fail, OK # co19 issue 212
@@ -360,15 +355,6 @@
 LibTest/core/Queue/forEach_A01_t04: Fail # behavior of forEach is undefined when underlying iterable changes, co19 issue 357
 
 LibTest/core/List/List_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/List_A01_t02: Fail # List constructors, co19 issue 358
-LibTest/core/List/add_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addAll_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addLast_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/clear_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/insertRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/length_A04_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeLast_A02_t01: Fail # List constructors, co19 issue 358
 
 LibTest/core/List/last_A02_t01: Fail # List.last throws a StateError, co19 issue 359
 
@@ -572,6 +558,11 @@
 LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
 LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
 
+LibTest/core/RegExp/RegExp_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/toString_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/IllegalJSRegExpException_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+
 # Issues with co19 test suite in checked mode.
 [ $compiler == dart2js && $checked ]
 LibTest/isolate/SendPort/call_A01_t01: Fail # Future is in async library. co19 issue 367
@@ -593,8 +584,6 @@
 LibTest/core/Match/str_A01_t01: Fail, OK # Bad test, allMatches return an Iterable.
 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail, OK # This is not rejected by V8.
 LibTest/core/RegExp/Pattern_semantics/firstMatch_Term_A04_t01: Fail, OK # co19 issue 92.
-LibTest/core/RegExp/RegExp_A01_t03: Fail, OK # Expects exception from const constructor.
-LibTest/core/RegExp/RegExp_A01_t04: Fail, OK # Expects exception from const constructor.
 LibTest/core/RegExp/allMatches_A01_t01: Fail, OK #  Bad test, allMatches return an Iterable.
 LibTest/core/RegExp/firstMatch_A01_t01: Fail, OK # Bad test, use Match.regexp, not Match.pattern.
 LibTest/core/double/toRadixString_A01_t01: Fail, OK # Unimplemented test stub.
@@ -744,7 +733,6 @@
 Language/07_Classes/3_Setters_A04_t07: Fail # http://dartbug.com/5023
 
 Language/14_Types/5_Function_Types_A01_t01: Fail # http://dartbug.com/5022
-Language/14_Types/5_Function_Types_A01_t03: Fail # http://dartbug.com/5022
 
 Language/13_Libraries_and_Scripts/4_Scripts_A03_t01: Fail # http://dartbug.com/5683
 Language/13_Libraries_and_Scripts/4_Scripts_A03_t03: Fail # http://dartbug.com/5683
@@ -772,19 +760,23 @@
 Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: Fail # dartbug.com/7202
 Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: Fail # dartbug.com/7202
 
-# Doesn't expect null to be allowed in Set or Map keys (issue 377).
-LibTest/core/Map/containsKey_A01_t02: Fail
-LibTest/core/Map/operator_subscript_A01_t02: Fail
-LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail
-LibTest/core/Map/remove_A01_t02: Fail
-LibTest/core/Set/add_A01_t02: Fail
-LibTest/core/Set/addAll_A01_t02: Fail
-LibTest/core/Set/contains_A01_t02: Fail
-LibTest/core/Set/containsAll_A01_t02: Fail
-LibTest/core/Set/intersection_A03_t01: Fail
-LibTest/core/Set/isSubsetOf_A01_t02: Fail
-LibTest/core/Set/remove_A01_t02: Fail
-LibTest/core/Set/removeAll_A01_t02: Fail
+LibTest/core/Map/containsKey_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscript_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/add_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/addAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/contains_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/containsAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/intersection_A03_t01: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/isSubsetOf_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/removeAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
 
-# Doesn't expect concurrent modification error (issue 376).
-LibTest/core/Map/forEach_A01_t07: Fail
+LibTest/core/Map/forEach_A01_t07: Fail # Doesn't expect concurrent modification error (issue 376).
+
+LibTest/core/String/charCodes_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A02_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A03_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/splitChars_A01_t01: Fail # Deprecated string members removed (issue 382).
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index fb79c4e..b8ff98e 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -10,6 +10,13 @@
 Language/13_Libraries_and_Scripts/1_Imports_A02_t21: Crash # Dart issue 6060
 Language/13_Libraries_and_Scripts/1_Imports_A02_t22: Crash # Dart issue 6060
 
+Language/13_Libraries_and_Scripts/1_Imports_A04_t03: Fail # co19 issue 385
+Language/13_Libraries_and_Scripts/2_Exports_A05_t01: Fail # co19 issue 385
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t20: Fail # co19 issue 387
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t21: Fail # co19 issue 387
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t22: Fail # co19 issue 387
+Language/13_Libraries_and_Scripts/4_Scripts_A01_t23: Fail # co19 issue 387
+
 Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A01_t10: Fail # co19 issue 348
 Language/07_Classes/3_Setters_A04_t01: Fail # co19 issue 383
 Language/07_Classes/3_Setters_A04_t04: Fail # co19 issue 383
@@ -136,15 +143,6 @@
 LibTest/core/Queue/forEach_A01_t04: Fail # behavior of forEach is undefined when underlying iterable changes, co19 issue 357
 
 LibTest/core/List/List_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/List_A01_t02: Fail # List constructors, co19 issue 358
-LibTest/core/List/add_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addAll_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/addLast_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/clear_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/insertRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/length_A04_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeRange_A02_t01: Fail # List constructors, co19 issue 358
-LibTest/core/List/removeLast_A02_t01: Fail # List constructors, co19 issue 358
 
 LibTest/core/List/last_A02_t01: Fail # List.last throws a StateError, co19 issue 359
 
@@ -259,19 +257,17 @@
 LibTest/core/Date/Date.fromMillisecondsSinceEpoch_A03_t01: Fail # TODO(vm-team): Please triage this failure.
 
 [ $compiler == none && $runtime == vm ]
-# Not properly reporting exception in initializer expressions
-Language/11_Expressions/01_Constants_A16_t01: Fail
-Language/11_Expressions/01_Constants_A16_t02: Fail
+Language/11_Expressions/01_Constants_A16_t01: Fail # Not properly reporting exception in initializer expressions
+Language/11_Expressions/01_Constants_A16_t02: Fail # Not properly reporting exception in initializer expressions
 
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t03: Fail # issue 392, potentially constant expression analysis
 
 Language/11_Expressions/01_Constants_A17_t03: Crash # issue 1681 (recursion in compile-time constant expression)
 Language/11_Expressions/01_Constants_A16_t02: Crash, Pass # Should result in OOM
 
-# co19 issue 183 - must not instantiate an abstract class
 # Some of these tests are expected to fail for another reason. These are marked as Skip.
-Language/07_Classes/07_Classes_A02_t29: Skip # co19 issue 183
-Language/07_Classes/07_Classes_A02_t31: Skip # co19 issue 183
+Language/07_Classes/07_Classes_A02_t29: Skip # must not instantiate an abstract class, co19 issue 183
+Language/07_Classes/07_Classes_A02_t31: Skip # must not instantiate an abstract class, co19 issue 183
 
 # co19 175 - related to issue 4522, all need fixing, some passes because of temporary warning.
 Language/11_Expressions/07_Maps_A03_t01: Pass, Fail # co19 175
@@ -338,10 +334,8 @@
 
 [ $compiler == none && $runtime == vm ]
 
-# The following tests use the deprecated Date interface.
-# Issue co19 - 125
-LibTest/core/Date/toString_A02_t01: Fail, OK
-LibTest/core/Date/year_A01_t01: Fail, OK
+LibTest/core/Date/toString_A02_t01: Fail # Argument error. Year 999999 is out of range. Needs to be specified (and then potentially reported to co19): issue 1878.
+LibTest/core/Date/year_A01_t01: Fail # Year out of range. Needs to be specified: issue 8808. Possibly a co19 bug.
 
 LibTest/isolate/SendPort/send_A02_t02: Skip # co19 issue 293
 LibTest/isolate/SendPort/send_A02_t03: Skip # co19 issue 293
@@ -509,22 +503,31 @@
 LibTest/core/Strings/concatAll_A01_t01: Fail # Strings class has been removed. co19 issue 380
 LibTest/core/Strings/concatAll_A04_t01: Fail # Strings class has been removed. co19 issue 380
 
-# Doesn't expect null to be allowed in Set or Map keys (issue 377).
-LibTest/core/Map/containsKey_A01_t02: Fail
-LibTest/core/Map/operator_subscript_A01_t02: Fail
-LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail
-LibTest/core/Map/remove_A01_t02: Fail
-LibTest/core/Set/add_A01_t02: Fail
-LibTest/core/Set/addAll_A01_t02: Fail
-LibTest/core/Set/contains_A01_t02: Fail
-LibTest/core/Set/containsAll_A01_t02: Fail
-LibTest/core/Set/intersection_A03_t01: Fail
-LibTest/core/Set/isSubsetOf_A01_t02: Fail
-LibTest/core/Set/remove_A01_t02: Fail
-LibTest/core/Set/removeAll_A01_t02: Fail
+LibTest/core/RegExp/RegExp_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t03: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/toString_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
+LibTest/core/IllegalJSRegExpException/IllegalJSRegExpException_A01_t01: Fail # IllegalJSRegExpException has been removed. co19 issue 375.
 
-# Doesn't expect concurrent modification error (issue 376).
-LibTest/core/Map/forEach_A01_t07: Fail
+LibTest/core/Map/containsKey_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscript_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/operator_subscripted_assignment_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Map/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/add_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/addAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/contains_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/containsAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/intersection_A03_t01: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/isSubsetOf_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/remove_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+LibTest/core/Set/removeAll_A01_t02: Fail # Doesn't expect null to be allowed in Set or Map keys (issue 377).
+
+LibTest/core/Map/forEach_A01_t07: Fail # Doesn't expect concurrent modification error (issue 376).
+
+LibTest/core/String/charCodes_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A02_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A03_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/charCodeAt_A01_t01: Fail # Deprecated string members removed (issue 382).
+LibTest/core/String/splitChars_A01_t01: Fail # Deprecated string members removed (issue 382).
 
 [ $compiler == none && $runtime == vm && $unchecked ]
 LibTest/core/Future/chain_A02_t05: Fail # Future is in async library. co19 issue 367
diff --git a/tests/compiler/dart2js/deprecated_features_test.dart b/tests/compiler/dart2js/deprecated_features_test.dart
index 88dd6b7..7c8bc58 100644
--- a/tests/compiler/dart2js/deprecated_features_test.dart
+++ b/tests/compiler/dart2js/deprecated_features_test.dart
@@ -68,8 +68,7 @@
       "109<Foo>::${deprecatedMessage('conflicting constructor')}\n"
 
       "129<bar>::info: This member conflicts with a constructor.\n"
-      "200<Dynamic>::${deprecatedMessage('Dynamic')}\n"
-      "221<()>::${deprecatedMessage('getter parameters')}\n",
+      "205<()>::${deprecatedMessage('getter parameters')}\n",
       messages.toString());
 }
 
@@ -95,7 +94,6 @@
   static bar() => new Foo.bar();
   factory Fisk() {}
   factory Fisk.hest() {}
-  Dynamic fisk;
   get x() => null;
 }
 
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 686c8ff..149ccf3 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -56,24 +56,25 @@
   class Dynamic_ {}
   class LinkedHashMap {}
   S() {}
+  unwrapException(e) {}
   assertHelper(a){}
   createRuntimeType(a) {}
   throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) {}
   throwAbstractClassInstantiationError(className) {}''';
 
 const String DEFAULT_INTERCEPTORSLIB = r'''
-  class JSArray {
+  class JSArray implements List {
     var length;
     operator[](index) {}
     operator[]=(index, value) {}
     var add;
   }
-  class JSString {
+  class JSString implements String {
     var length;
     operator[](index) {}
     toString() {}
   }
-  class JSNumber {
+  class JSNumber implements num {
     // All these methods return a number to please type inferencing.
     operator-() => (this is JSInt) ? 42 : 42.0;
     operator +(other) => (this is JSInt) ? 42 : 42.0;
@@ -94,15 +95,15 @@
     operator <=(other) => true;
     operator ==(other) => true;
   }
-  class JSInt extends JSNumber {
+  class JSInt extends JSNumber implements int {
   }
-  class JSDouble extends JSNumber {
+  class JSDouble extends JSNumber implements double {
   }
   class JSNull {
   }
-  class JSBool {
+  class JSBool implements bool {
   }
-  class JSFunction {
+  class JSFunction implements Function {
   }
   class ObjectInterceptor {
   }
@@ -117,7 +118,7 @@
     static parse(s) {}
   }
   class bool {}
-  class String {}
+  class String implements Pattern {}
   class Object {
     operator ==(other) {}
     String toString() {}
@@ -130,6 +131,7 @@
     DateTime(year);
     DateTime.utc(year);
   }
+  abstract class Pattern {}
   bool identical(Object a, Object b) {}''';
 
 const String DEFAULT_ISOLATE_HELPERLIB = r'''
@@ -161,13 +163,17 @@
     // We need to set the assert method to avoid calls with a 'null'
     // target being interpreted as a call to assert.
     jsHelperLibrary = createLibrary("helper", helperSource);
-    importHelperLibrary(coreLibrary);
-    libraryLoader.importLibrary(jsHelperLibrary, coreLibrary, null);
-
-    assertMethod = jsHelperLibrary.find(buildSourceString('assert'));
     interceptorsLibrary = createLibrary("interceptors", interceptorsSource);
     isolateHelperLibrary = createLibrary("isolate_helper", isolateHelperSource);
 
+    // Set up the library imports.
+    importHelperLibrary(coreLibrary);
+    libraryLoader.importLibrary(jsHelperLibrary, coreLibrary, null);
+    libraryLoader.importLibrary(interceptorsLibrary, coreLibrary, null);
+    libraryLoader.importLibrary(isolateHelperLibrary, coreLibrary, null);
+
+    assertMethod = jsHelperLibrary.find(buildSourceString('assert'));
+
     mainApp = mockLibrary(this, "");
     initializeSpecialClasses();
     // We need to make sure the Object class is resolved. When registering a
diff --git a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
new file mode 100644
index 0000000..21c0f8d
--- /dev/null
+++ b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'compiler_helper.dart';
+
+const String TEST = """
+returnDyn1() {
+  var a;
+  ((a = 52) == true) || ((a = 'foo') == true);
+  return a;
+}
+
+returnDyn2() {
+  var a;
+  ((a = 52) == true) && ((a = 'foo') == true);
+  return a;
+}
+
+returnDyn3() {
+  var a;
+  a = a == 54 ? 'foo' : 31;
+  return a;
+}
+
+main() {
+  returnDyn1();
+  returnDyn2();
+  returnDyn3();
+}
+""";
+
+
+void main() {
+  Uri uri = new Uri.fromComponents(scheme: 'source');
+  var compiler = compilerFor(TEST, uri);
+  compiler.runCompiler(uri);
+  var typesInferrer = compiler.typesTask.typesInferrer;
+
+  checkReturn(String name, type) {
+    var element = findElement(compiler, name);
+    Expect.equals(type, typesInferrer.returnTypeOf[element]);
+  }
+
+  checkReturn('returnDyn1', compiler.dynamicClass);
+  checkReturn('returnDyn2', compiler.dynamicClass);
+  checkReturn('returnDyn3', compiler.dynamicClass);
+}
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
new file mode 100644
index 0000000..d9351e3
--- /dev/null
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -0,0 +1,94 @@
+// 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 'compiler_helper.dart';
+
+const String TEST = """
+returnInt1() {
+  var a = 42;
+  var f = () {
+    return a;
+  };
+  return a;
+}
+
+returnDyn1() {
+  var a = 42;
+  var f = () {
+    a = 'foo';
+  };
+  return a;
+}
+
+returnInt2() {
+  var a = 42;
+  var f = () {
+    a = 54;
+  };
+  return a;
+}
+
+returnDyn2() {
+  var a = 42;
+  var f = () {
+    a = 54;
+  };
+  var g = () {
+    a = 'foo';
+  };
+  return a;
+}
+
+returnInt3() {
+  var a = 42;
+  if (a == 53) {
+    var f = () {
+      a = 32;
+    };
+  }
+  return a;
+}
+
+returnDyn3() {
+  var a = 42;
+  if (a == 53) {
+    var f = () {
+      a = 'foo';
+    };
+  }
+  return a;
+}
+
+main() {
+  returnInt1();
+  returnDyn1();
+  returnInt2();
+  returnDyn2();
+  returnInt3();
+  returnDyn3();
+}
+""";
+
+
+void main() {
+  Uri uri = new Uri.fromComponents(scheme: 'source');
+  var compiler = compilerFor(TEST, uri);
+  compiler.runCompiler(uri);
+  var typesInferrer = compiler.typesTask.typesInferrer;
+
+  checkReturn(String name, type) {
+    var element = findElement(compiler, name);
+    Expect.equals(type, typesInferrer.returnTypeOf[element]);
+  }
+
+  checkReturn('returnInt1', compiler.intClass);
+  checkReturn('returnInt2', compiler.intClass);
+  checkReturn('returnInt3', compiler.intClass);
+
+  checkReturn('returnDyn1', compiler.dynamicClass);
+  checkReturn('returnDyn2', compiler.dynamicClass);
+  checkReturn('returnDyn3', compiler.dynamicClass);
+
+  print(typesInferrer.returnTypeOf);
+}
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
new file mode 100644
index 0000000..58afca9
--- /dev/null
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -0,0 +1,62 @@
+// 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 'compiler_helper.dart';
+
+const String TEST = """
+returnNum1(a) {
+  if (a) return 1;
+  else return 2.0;
+}
+
+returnNum2(a) {
+  if (a) return 1.0;
+  else return 2;
+}
+
+returnInt(a) {
+  if (a) return 1;
+  else return 2;
+}
+
+returnDouble(a) {
+  if (a) return 1.0;
+  else return 2.0;
+}
+
+returnGiveUp(a) {
+  if (a) return 1;
+  else return 'foo';
+}
+
+main() {
+  returnNum1(true);
+  returnNum2(true);
+  returnInt(true);
+  returnDouble(true);
+  returnGiveUp(true);
+}
+""";
+
+void main() {
+  Uri uri = new Uri.fromComponents(scheme: 'source');
+  var compiler = compilerFor(TEST, uri);
+  compiler.runCompiler(uri);
+  var typesInferrer = compiler.typesTask.typesInferrer;
+
+  var element = findElement(compiler, 'returnNum1');
+  Expect.equals(compiler.numClass, typesInferrer.returnTypeOf[element]);
+
+  element = findElement(compiler, 'returnNum2');
+  Expect.equals(compiler.numClass, typesInferrer.returnTypeOf[element]);
+
+  element = findElement(compiler, 'returnInt');
+  Expect.equals(compiler.intClass, typesInferrer.returnTypeOf[element]);
+
+  element = findElement(compiler, 'returnDouble');
+  Expect.equals(compiler.doubleClass, typesInferrer.returnTypeOf[element]);
+
+  element = findElement(compiler, 'returnGiveUp');
+  Expect.equals(typesInferrer.giveUpType, typesInferrer.returnTypeOf[element]);
+}
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
new file mode 100644
index 0000000..700b5f8
--- /dev/null
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -0,0 +1,153 @@
+// 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 'compiler_helper.dart';
+
+const String TEST = """
+returnInt1() {
+  var a = 42;
+  try {
+    a = 54;
+  } catch (e){
+  }
+  return a;
+}
+
+returnDyn1() {
+  var a = 42;
+  try {
+    a = 'foo';
+  } catch (e){
+  }
+  return a;
+}
+
+returnInt2() {
+  var a = 42;
+  try {
+    a = 54;
+  } catch (e){
+    a = 2;
+  }
+  return a;
+}
+
+returnDyn2() {
+  var a = 42;
+  try {
+    a = 54;
+  } catch (e){
+    a = 'foo';
+  }
+  return a;
+}
+
+returnInt3() {
+  var a = 42;
+  try {
+    a = 54;
+  } catch (e){
+    a = 'foo';
+  } finally {
+    a = 4;
+  }
+  return a;
+}
+
+returnDyn3() {
+  var a = 42;
+  try {
+    a = 54;
+  } on String catch (e) {
+    a = 2;
+  } on Object catch (e) {
+    a = 'foo';
+  }
+  return a;
+}
+
+returnInt4() {
+  var a = 42;
+  try {
+    a = 54;
+  } on String catch (e) {
+    a = 2;
+  } on Object catch (e) {
+    a = 32;
+  }
+  return a;
+}
+
+returnDyn4() {
+  var a = 42;
+  if (a == 54) {
+    try {
+      a = 'foo';
+    } catch (e) {
+    }
+  }
+  return a;
+}
+
+returnInt5() {
+  var a = 42;
+  if (a == 54) {
+    try {
+      a = 42;
+    } catch (e) {
+    }
+  }
+  return a;
+}
+
+returnDyn5() {
+  var a = 42;
+  if (a == 54) {
+    try {
+      a = 'foo';
+      print(a);
+      a = 42;
+    } catch (e) {
+    }
+  }
+  return a;
+}
+
+
+main() {
+  returnInt1();
+  returnDyn1();
+  returnInt2();
+  returnDyn2();
+  returnInt3();
+  returnDyn3();
+  returnInt4();
+  returnDyn4();
+  returnInt5();
+}
+""";
+
+
+void main() {
+  Uri uri = new Uri.fromComponents(scheme: 'source');
+  var compiler = compilerFor(TEST, uri);
+  compiler.runCompiler(uri);
+  var typesInferrer = compiler.typesTask.typesInferrer;
+
+  checkReturn(String name, type) {
+    var element = findElement(compiler, name);
+    Expect.equals(type, typesInferrer.returnTypeOf[element]);
+  }
+
+  checkReturn('returnInt1', compiler.intClass);
+  checkReturn('returnInt2', compiler.intClass);
+  checkReturn('returnInt3', compiler.intClass);
+  checkReturn('returnInt4', compiler.intClass);
+  checkReturn('returnInt5', compiler.intClass);
+
+  checkReturn('returnDyn1', compiler.dynamicClass);
+  checkReturn('returnDyn2', compiler.dynamicClass);
+  checkReturn('returnDyn3', compiler.dynamicClass);
+  checkReturn('returnDyn4', compiler.dynamicClass);
+}
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart
index 3b3ae1e..ada905c 100644
--- a/tests/compiler/dart2js/type_combination_test.dart
+++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -3,7 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "mock_compiler.dart";
+import "parser_helper.dart";
 import "../../../sdk/lib/_internal/compiler/implementation/ssa/ssa.dart";
+import "../../../sdk/lib/_internal/compiler/implementation/types/types.dart";
 
 const CONFLICTING = HType.CONFLICTING;
 const UNKNOWN = HType.UNKNOWN;
@@ -23,2022 +25,2039 @@
 const DOUBLE_OR_NULL = HType.DOUBLE_OR_NULL;
 const STRING_OR_NULL = HType.STRING_OR_NULL;
 const NULL = HType.NULL;
+
+var patternClass;
 HType nonPrimitive1;
 HType nonPrimitive2;
 HType potentialArray;
 HType potentialString;
+HType jsArrayOrNull;
 
 void testUnion(MockCompiler compiler) {
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 CONFLICTING.union(UNKNOWN, compiler));
-  Expect.equals(BOOLEAN, 
+  Expect.equals(BOOLEAN,
                 CONFLICTING.union(BOOLEAN, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 CONFLICTING.union(NUMBER, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 CONFLICTING.union(INTEGER, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 CONFLICTING.union(DOUBLE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 CONFLICTING.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 CONFLICTING.union(STRING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 CONFLICTING.union(READABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 CONFLICTING.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 CONFLICTING.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(nonPrimitive1, 
+  Expect.equals(nonPrimitive1,
                 CONFLICTING.union(nonPrimitive1, compiler));
-  Expect.equals(nonPrimitive2, 
+  Expect.equals(nonPrimitive2,
                 CONFLICTING.union(nonPrimitive2, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 CONFLICTING.union(potentialArray, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 CONFLICTING.union(potentialString, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 CONFLICTING.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 CONFLICTING.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 CONFLICTING.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 CONFLICTING.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 CONFLICTING.union(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 CONFLICTING.union(NULL, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 CONFLICTING.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(STRING_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(BOOLEAN, 
+  Expect.equals(BOOLEAN,
                 BOOLEAN.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(UNKNOWN, compiler));
-  Expect.equals(BOOLEAN, 
+  Expect.equals(BOOLEAN,
                 BOOLEAN.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(potentialString, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 BOOLEAN.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(STRING_OR_NULL, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 BOOLEAN.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 NUMBER.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(BOOLEAN, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 NUMBER.union(NUMBER, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 NUMBER.union(INTEGER, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 NUMBER.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(STRING_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(BOOLEAN, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 INTEGER.union(NUMBER, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER.union(INTEGER, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 INTEGER.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 INTEGER.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 INTEGER.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(STRING_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(BOOLEAN, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 DOUBLE.union(NUMBER, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 DOUBLE.union(INTEGER, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 DOUBLE.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 DOUBLE.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(STRING_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 INDEXABLE_PRIMITIVE.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(DOUBLE, compiler));
   Expect.equals(INDEXABLE_PRIMITIVE,
-                INDEXABLE_PRIMITIVE.union(INDEXABLE_PRIMITIVE, 
+                INDEXABLE_PRIMITIVE.union(INDEXABLE_PRIMITIVE,
                 compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 INDEXABLE_PRIMITIVE.union(STRING, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 INDEXABLE_PRIMITIVE.union(READABLE_ARRAY, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 INDEXABLE_PRIMITIVE.union(MUTABLE_ARRAY, compiler));
   Expect.equals(INDEXABLE_PRIMITIVE,
-                INDEXABLE_PRIMITIVE.union(EXTENDABLE_ARRAY, 
+                INDEXABLE_PRIMITIVE.union(EXTENDABLE_ARRAY,
                 compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(STRING_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INDEXABLE_PRIMITIVE.union(NULL, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 INDEXABLE_PRIMITIVE.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(DOUBLE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 STRING.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING.union(STRING, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 STRING.union(READABLE_ARRAY, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 STRING.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 STRING.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(potentialArray, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 STRING.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING.union(STRING_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING.union(NULL, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 STRING.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(DOUBLE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 READABLE_ARRAY.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 READABLE_ARRAY.union(STRING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.union(READABLE_ARRAY, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(nonPrimitive2, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 READABLE_ARRAY.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 READABLE_ARRAY.union(STRING_OR_NULL, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(jsArrayOrNull,
                 READABLE_ARRAY.union(NULL, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(DOUBLE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 MUTABLE_ARRAY.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 MUTABLE_ARRAY.union(STRING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 MUTABLE_ARRAY.union(READABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(nonPrimitive2, compiler));
-  Expect.equals(potentialArray,MUTABLE_ARRAY.union(potentialArray, 
+  Expect.equals(potentialArray,MUTABLE_ARRAY.union(potentialArray,
                 compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 MUTABLE_ARRAY.union(STRING_OR_NULL, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(jsArrayOrNull,
                 MUTABLE_ARRAY.union(NULL, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 EXTENDABLE_ARRAY.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(DOUBLE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 EXTENDABLE_ARRAY.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 EXTENDABLE_ARRAY.union(STRING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 EXTENDABLE_ARRAY.union(READABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 EXTENDABLE_ARRAY.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 EXTENDABLE_ARRAY.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(nonPrimitive2, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 EXTENDABLE_ARRAY.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 EXTENDABLE_ARRAY.union(STRING_OR_NULL, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(jsArrayOrNull,
                 EXTENDABLE_ARRAY.union(NULL, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 EXTENDABLE_ARRAY.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(nonPrimitive1, 
+  Expect.equals(nonPrimitive1,
                 nonPrimitive1.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(nonPrimitive1, 
+  Expect.equals(nonPrimitive1,
                 nonPrimitive1.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(STRING_OR_NULL, compiler));
   Expect.isTrue(nonPrimitive1.union(NULL, compiler) is HBoundedType);
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive1.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(nonPrimitive2, 
+  Expect.equals(nonPrimitive2,
                 nonPrimitive2.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(nonPrimitive1, compiler));
-  Expect.equals(nonPrimitive2, 
+  Expect.equals(nonPrimitive2,
                 nonPrimitive2.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(STRING_OR_NULL, compiler));
   Expect.isTrue(nonPrimitive2.union(NULL, compiler) is HBoundedType);
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 nonPrimitive2.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(STRING, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.union(READABLE_ARRAY, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(nonPrimitive2, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialArray.union(STRING_OR_NULL, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.union(NULL, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 potentialString.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 potentialString.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(potentialArray, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 potentialString.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 potentialString.union(STRING_OR_NULL, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 potentialString.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 potentialString.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 BOOLEAN_OR_NULL.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(UNKNOWN, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 BOOLEAN_OR_NULL.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(potentialString, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 BOOLEAN_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(STRING_OR_NULL, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 BOOLEAN_OR_NULL.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 BOOLEAN_OR_NULL.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(BOOLEAN, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.union(NUMBER, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.union(INTEGER, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(STRING_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NUMBER_OR_NULL.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER_OR_NULL.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(BOOLEAN, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 INTEGER_OR_NULL.union(NUMBER, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER_OR_NULL.union(INTEGER, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 INTEGER_OR_NULL.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 INTEGER_OR_NULL.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER_OR_NULL.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 INTEGER_OR_NULL.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(STRING_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER_OR_NULL.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 INTEGER_OR_NULL.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE_OR_NULL.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(BOOLEAN, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 DOUBLE_OR_NULL.union(NUMBER, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 DOUBLE_OR_NULL.union(INTEGER, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE_OR_NULL.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 DOUBLE_OR_NULL.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 DOUBLE_OR_NULL.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE_OR_NULL.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(STRING_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE_OR_NULL.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 DOUBLE_OR_NULL.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING_OR_NULL.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING_OR_NULL.union(STRING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(READABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(nonPrimitive2, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(potentialArray, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 STRING_OR_NULL.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING_OR_NULL.union(STRING_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING_OR_NULL.union(NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 STRING_OR_NULL.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NULL.union(UNKNOWN, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 NULL.union(BOOLEAN, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NULL.union(NUMBER, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 NULL.union(INTEGER, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 NULL.union(DOUBLE, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NULL.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 NULL.union(STRING, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(jsArrayOrNull,
                 NULL.union(READABLE_ARRAY, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(jsArrayOrNull,
                 NULL.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(jsArrayOrNull,
                 NULL.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NULL.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 NULL.union(nonPrimitive2, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 NULL.union(potentialArray, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 NULL.union(potentialString, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 NULL.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NULL.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 NULL.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 NULL.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 NULL.union(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.union(NULL, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(jsArrayOrNull,
                 NULL.union(FIXED_ARRAY, compiler));
 
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 FIXED_ARRAY.union(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(UNKNOWN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(BOOLEAN, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(NUMBER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(INTEGER, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(DOUBLE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 FIXED_ARRAY.union(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 FIXED_ARRAY.union(STRING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 FIXED_ARRAY.union(READABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 FIXED_ARRAY.union(MUTABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 FIXED_ARRAY.union(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(nonPrimitive1, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(nonPrimitive2, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 FIXED_ARRAY.union(potentialArray, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(potentialString, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(NUMBER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(INTEGER_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(DOUBLE_OR_NULL, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 FIXED_ARRAY.union(STRING_OR_NULL, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(jsArrayOrNull,
                 FIXED_ARRAY.union(NULL, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 FIXED_ARRAY.union(FIXED_ARRAY, compiler));
 }
 
 void testIntersection(MockCompiler compiler) {
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(CONFLICTING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(nonPrimitive2, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 CONFLICTING.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 UNKNOWN.intersection(CONFLICTING, compiler));
-  Expect.equals(UNKNOWN, 
+  Expect.equals(UNKNOWN,
                 UNKNOWN.intersection(UNKNOWN, compiler));
-  Expect.equals(BOOLEAN, 
+  Expect.equals(BOOLEAN,
                 UNKNOWN.intersection(BOOLEAN, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 UNKNOWN.intersection(NUMBER, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 UNKNOWN.intersection(INTEGER, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 UNKNOWN.intersection(DOUBLE, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 UNKNOWN.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 UNKNOWN.intersection(STRING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 UNKNOWN.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 UNKNOWN.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 UNKNOWN.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(nonPrimitive1, 
+  Expect.equals(nonPrimitive1,
                 UNKNOWN.intersection(nonPrimitive1, compiler));
-  Expect.equals(nonPrimitive2, 
+  Expect.equals(nonPrimitive2,
                 UNKNOWN.intersection(nonPrimitive2, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 UNKNOWN.intersection(potentialArray, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 UNKNOWN.intersection(potentialString, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 UNKNOWN.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 UNKNOWN.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 UNKNOWN.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 UNKNOWN.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 UNKNOWN.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 UNKNOWN.intersection(NULL, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 UNKNOWN.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(CONFLICTING, compiler));
-  Expect.equals(BOOLEAN, 
+  Expect.equals(BOOLEAN,
                 BOOLEAN.intersection(UNKNOWN, compiler));
-  Expect.equals(BOOLEAN, 
+  Expect.equals(BOOLEAN,
                 BOOLEAN.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(nonPrimitive2, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(potentialString, compiler));
-  Expect.equals(BOOLEAN, 
+  Expect.equals(BOOLEAN,
                 BOOLEAN.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(CONFLICTING, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 NUMBER.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(BOOLEAN, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 NUMBER.intersection(NUMBER, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 NUMBER.intersection(INTEGER, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 NUMBER.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(nonPrimitive2, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 NUMBER.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 NUMBER.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 NUMBER.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(CONFLICTING, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(BOOLEAN, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER.intersection(NUMBER, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(nonPrimitive2, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(CONFLICTING, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(BOOLEAN, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(INTEGER, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(nonPrimitive2, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE.intersection(FIXED_ARRAY, compiler));
-  
-  Expect.equals(CONFLICTING, 
+
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(CONFLICTING, compiler));
-  Expect.equals(INDEXABLE_PRIMITIVE, 
+  Expect.equals(INDEXABLE_PRIMITIVE,
                 INDEXABLE_PRIMITIVE.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(DOUBLE, compiler));
   Expect.equals(INDEXABLE_PRIMITIVE,
-                INDEXABLE_PRIMITIVE.intersection(INDEXABLE_PRIMITIVE, 
-                compiler));
-  Expect.equals(STRING, 
-                INDEXABLE_PRIMITIVE.intersection(STRING, compiler));
-  Expect.equals(READABLE_ARRAY,
-                INDEXABLE_PRIMITIVE.intersection(READABLE_ARRAY, 
-                compiler));
-  Expect.equals(MUTABLE_ARRAY,
-                INDEXABLE_PRIMITIVE.intersection(MUTABLE_ARRAY, 
-                compiler));
-  Expect.equals(EXTENDABLE_ARRAY,
-                INDEXABLE_PRIMITIVE.intersection(EXTENDABLE_ARRAY, 
-                compiler));
-  Expect.equals(CONFLICTING, 
-                INDEXABLE_PRIMITIVE.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
-                INDEXABLE_PRIMITIVE.intersection(nonPrimitive2, compiler));
-  Expect.equals(READABLE_ARRAY,
-                INDEXABLE_PRIMITIVE.intersection(potentialArray, 
+                INDEXABLE_PRIMITIVE.intersection(INDEXABLE_PRIMITIVE,
                 compiler));
   Expect.equals(STRING,
-                INDEXABLE_PRIMITIVE.intersection(potentialString, 
+                INDEXABLE_PRIMITIVE.intersection(STRING, compiler));
+  Expect.equals(READABLE_ARRAY,
+                INDEXABLE_PRIMITIVE.intersection(READABLE_ARRAY,
                 compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(MUTABLE_ARRAY,
+                INDEXABLE_PRIMITIVE.intersection(MUTABLE_ARRAY,
+                compiler));
+  Expect.equals(EXTENDABLE_ARRAY,
+                INDEXABLE_PRIMITIVE.intersection(EXTENDABLE_ARRAY,
+                compiler));
+  Expect.equals(CONFLICTING,
+                INDEXABLE_PRIMITIVE.intersection(nonPrimitive1, compiler));
+  Expect.equals(CONFLICTING,
+                INDEXABLE_PRIMITIVE.intersection(nonPrimitive2, compiler));
+  Expect.equals(READABLE_ARRAY,
+                INDEXABLE_PRIMITIVE.intersection(potentialArray,
+                compiler));
+  Expect.equals(STRING,
+                INDEXABLE_PRIMITIVE.intersection(potentialString,
+                compiler));
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INDEXABLE_PRIMITIVE.intersection(NULL, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 INDEXABLE_PRIMITIVE.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(CONFLICTING, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(DOUBLE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(nonPrimitive2, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(potentialArray, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(CONFLICTING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(DOUBLE, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(STRING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 READABLE_ARRAY.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 READABLE_ARRAY.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(nonPrimitive2, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 READABLE_ARRAY.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 READABLE_ARRAY.intersection(NULL, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 READABLE_ARRAY.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(CONFLICTING, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(DOUBLE, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(STRING, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 MUTABLE_ARRAY.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(nonPrimitive2, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 MUTABLE_ARRAY.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 MUTABLE_ARRAY.intersection(NULL, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 MUTABLE_ARRAY.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(CONFLICTING, compiler));
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 EXTENDABLE_ARRAY.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(DOUBLE, compiler));
   Expect.equals(EXTENDABLE_ARRAY,
-                EXTENDABLE_ARRAY.intersection(INDEXABLE_PRIMITIVE, 
+                EXTENDABLE_ARRAY.intersection(INDEXABLE_PRIMITIVE,
                 compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(STRING, compiler));
   Expect.equals(EXTENDABLE_ARRAY,
-                EXTENDABLE_ARRAY.intersection(READABLE_ARRAY, 
+                EXTENDABLE_ARRAY.intersection(READABLE_ARRAY,
                 compiler));
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 EXTENDABLE_ARRAY.intersection(MUTABLE_ARRAY, compiler));
   Expect.equals(EXTENDABLE_ARRAY,
-                EXTENDABLE_ARRAY.intersection(EXTENDABLE_ARRAY, 
+                EXTENDABLE_ARRAY.intersection(EXTENDABLE_ARRAY,
                 compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(nonPrimitive2, compiler));
   Expect.equals(EXTENDABLE_ARRAY,
-                EXTENDABLE_ARRAY.intersection(potentialArray, 
+                EXTENDABLE_ARRAY.intersection(potentialArray,
                 compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 EXTENDABLE_ARRAY.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(CONFLICTING, compiler));
-  Expect.equals(nonPrimitive1, 
+  Expect.equals(nonPrimitive1,
                 nonPrimitive1.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(nonPrimitive1, 
+  Expect.equals(nonPrimitive1,
                 nonPrimitive1.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(nonPrimitive2, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive1.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(CONFLICTING, compiler));
-  Expect.equals(nonPrimitive2, 
+  Expect.equals(nonPrimitive2,
                 nonPrimitive2.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(nonPrimitive1, compiler));
-  Expect.equals(nonPrimitive2, 
+  Expect.equals(nonPrimitive2,
                 nonPrimitive2.intersection(nonPrimitive2, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 nonPrimitive2.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialArray.intersection(CONFLICTING, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialArray.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialArray.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialArray.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialArray.intersection(DOUBLE, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 potentialArray.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialArray.intersection(STRING, compiler));
-  Expect.equals(READABLE_ARRAY, 
+  Expect.equals(READABLE_ARRAY,
                 potentialArray.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(MUTABLE_ARRAY, 
+  Expect.equals(MUTABLE_ARRAY,
                 potentialArray.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(EXTENDABLE_ARRAY, 
+  Expect.equals(EXTENDABLE_ARRAY,
                 potentialArray.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialArray.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialArray.intersection(nonPrimitive2, compiler));
-  Expect.equals(potentialArray, 
+  Expect.equals(potentialArray,
                 potentialArray.intersection(potentialArray, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialArray.intersection(potentialString, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialArray.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialArray.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialArray.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialArray.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialArray.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialArray.intersection(NULL, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 potentialArray.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(CONFLICTING, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 potentialString.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(DOUBLE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 potentialString.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 potentialString.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(nonPrimitive2, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialString.intersection(potentialArray, compiler));
-  Expect.equals(potentialString, 
+  Expect.equals(potentialString,
                 potentialString.intersection(potentialString, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialString.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialString.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialString.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialString.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 potentialString.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 potentialString.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 potentialString.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(CONFLICTING, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 BOOLEAN_OR_NULL.intersection(UNKNOWN, compiler));
-  Expect.equals(BOOLEAN, 
+  Expect.equals(BOOLEAN,
                 BOOLEAN_OR_NULL.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(nonPrimitive2, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 BOOLEAN_OR_NULL.intersection(potentialArray, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 BOOLEAN_OR_NULL.intersection(potentialString, compiler));
-  Expect.equals(BOOLEAN_OR_NULL, 
+  Expect.equals(BOOLEAN_OR_NULL,
                 BOOLEAN_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 BOOLEAN_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 BOOLEAN_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 BOOLEAN_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 BOOLEAN_OR_NULL.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 BOOLEAN_OR_NULL.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 BOOLEAN_OR_NULL.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(CONFLICTING, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(BOOLEAN, compiler));
-  Expect.equals(NUMBER, 
+  Expect.equals(NUMBER,
                 NUMBER_OR_NULL.intersection(NUMBER, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 NUMBER_OR_NULL.intersection(INTEGER, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 NUMBER_OR_NULL.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(nonPrimitive2, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NUMBER_OR_NULL.intersection(potentialArray, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NUMBER_OR_NULL.intersection(potentialString, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NUMBER_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NUMBER_OR_NULL, 
+  Expect.equals(NUMBER_OR_NULL,
                 NUMBER_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 NUMBER_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 NUMBER_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NUMBER_OR_NULL.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NUMBER_OR_NULL.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NUMBER_OR_NULL.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(CONFLICTING, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER_OR_NULL.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(BOOLEAN, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER_OR_NULL.intersection(NUMBER, compiler));
-  Expect.equals(INTEGER, 
+  Expect.equals(INTEGER,
                 INTEGER_OR_NULL.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(nonPrimitive2, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 INTEGER_OR_NULL.intersection(potentialArray, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 INTEGER_OR_NULL.intersection(potentialString, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 INTEGER_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(INTEGER_OR_NULL, 
+  Expect.equals(INTEGER_OR_NULL,
                 INTEGER_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 INTEGER_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 INTEGER_OR_NULL.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 INTEGER_OR_NULL.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 INTEGER_OR_NULL.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(CONFLICTING, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE_OR_NULL.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(BOOLEAN, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE_OR_NULL.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(INTEGER, compiler));
-  Expect.equals(DOUBLE, 
+  Expect.equals(DOUBLE,
                 DOUBLE_OR_NULL.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(nonPrimitive2, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 DOUBLE_OR_NULL.intersection(potentialArray, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 DOUBLE_OR_NULL.intersection(potentialString, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 DOUBLE_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 DOUBLE_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(DOUBLE_OR_NULL, 
+  Expect.equals(DOUBLE_OR_NULL,
                 DOUBLE_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 DOUBLE_OR_NULL.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 DOUBLE_OR_NULL.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 DOUBLE_OR_NULL.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(CONFLICTING, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING_OR_NULL.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(DOUBLE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING_OR_NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(STRING, 
+  Expect.equals(STRING,
                 STRING_OR_NULL.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(nonPrimitive2, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 STRING_OR_NULL.intersection(potentialArray, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING_OR_NULL.intersection(potentialString, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 STRING_OR_NULL.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 STRING_OR_NULL.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 STRING_OR_NULL.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 STRING_OR_NULL.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(STRING_OR_NULL, 
+  Expect.equals(STRING_OR_NULL,
                 STRING_OR_NULL.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 STRING_OR_NULL.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 STRING_OR_NULL.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(CONFLICTING, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(DOUBLE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(STRING, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(nonPrimitive2, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(potentialArray, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(potentialString, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(NULL, 
+  Expect.equals(NULL,
                 NULL.intersection(NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 NULL.intersection(FIXED_ARRAY, compiler));
 
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(CONFLICTING, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 FIXED_ARRAY.intersection(UNKNOWN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(BOOLEAN, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(NUMBER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(INTEGER, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(DOUBLE, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 FIXED_ARRAY.intersection(INDEXABLE_PRIMITIVE, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(STRING, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 FIXED_ARRAY.intersection(READABLE_ARRAY, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 FIXED_ARRAY.intersection(MUTABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(EXTENDABLE_ARRAY, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(nonPrimitive1, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(nonPrimitive2, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 FIXED_ARRAY.intersection(potentialArray, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(potentialString, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(BOOLEAN_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(NUMBER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(INTEGER_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(DOUBLE_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(STRING_OR_NULL, compiler));
-  Expect.equals(CONFLICTING, 
+  Expect.equals(CONFLICTING,
                 FIXED_ARRAY.intersection(NULL, compiler));
-  Expect.equals(FIXED_ARRAY, 
+  Expect.equals(FIXED_ARRAY,
                 FIXED_ARRAY.intersection(FIXED_ARRAY, compiler));
 }
 
 void testRegressions(MockCompiler compiler) {
-  HType nonNullPotentialString = new HBoundedPotentialPrimitiveString(
-      compiler.stringClass.computeType(compiler), canBeNull: false);
+  HType nonNullPotentialString = new HType.nonNullSubtype(
+      patternClass.computeType(compiler), compiler);
   Expect.equals(
       potentialString, STRING_OR_NULL.union(nonNullPotentialString, compiler));
 }
 
 void main() {
   MockCompiler compiler = new MockCompiler();
-  nonPrimitive1 = new HBoundedType(
-      compiler.mapClass.computeType(compiler), canBeNull: false);
-  nonPrimitive2 = new HBoundedType(
-      compiler.functionClass.computeType(compiler), canBeNull: false);
-  potentialArray = new HBoundedPotentialPrimitiveArray(
-      compiler.listClass.computeType(compiler));
-  potentialString = new HBoundedPotentialPrimitiveString(
-      compiler.stringClass.computeType(compiler));
+  compiler.interceptorsLibrary.forEachLocalMember((element) {
+    if (element.isClass()) {
+      compiler.enqueuer.resolution.registerInstantiatedClass(element);
+    }
+  });
+  compiler.world.populate();
+
+  // Grab hold of a supertype for String so we can produce potential
+  // string types.
+  patternClass = compiler.coreLibrary.find(buildSourceString('Pattern'));
+
+  nonPrimitive1 = new HType.nonNullSubtype(
+      compiler.mapClass.computeType(compiler), compiler);
+  nonPrimitive2 = new HType.nonNullSubtype(
+      compiler.functionClass.computeType(compiler), compiler);
+  potentialArray = new HType.subtype(
+      compiler.listClass.computeType(compiler), compiler);
+  potentialString = new HType.subtype(
+      patternClass.computeType(compiler), compiler);
+  jsArrayOrNull = new HType.exact(
+      compiler.backend.jsArrayClass.computeType(compiler), compiler);
+
   testUnion(compiler);
   testIntersection(compiler);
   testRegressions(compiler);
diff --git a/tests/compiler/dart2js/value_range_test.dart b/tests/compiler/dart2js/value_range_test.dart
index fdf0b6b..e1bfe73 100644
--- a/tests/compiler/dart2js/value_range_test.dart
+++ b/tests/compiler/dart2js/value_range_test.dart
@@ -40,7 +40,7 @@
 main(check) {
   // Make sure value is an int.
   var value = check ? 42 : 54;
-  var a = new List.fixedLength(value);
+  var a = new List(value);
   var sum = 0;
   for (int i = 0; i < value; i++) {
     sum += a[i];
@@ -68,7 +68,7 @@
 
 """
 main() {
-  var a = new List.fixedLength(4);
+  var a = new List(4);
   return a[0];
 }
 """,
@@ -76,7 +76,7 @@
 
 """
 main() {
-  var a = new List.fixedLength(4);
+  var a = new List(4);
   return a.removeLast();
 }
 """,
@@ -84,7 +84,7 @@
 
 """
 main(value) {
-  var a = new List.fixedLength(value);
+  var a = new List(value);
   return a[value];
 }
 """,
@@ -92,7 +92,7 @@
 
 """
 main(value) {
-  var a = new List.fixedLength(1024);
+  var a = new List(1024);
   return a[1023 & value];
 }
 """,
@@ -100,7 +100,7 @@
 
 """
 main(value) {
-  var a = new List.fixedLength(1024);
+  var a = new List(1024);
   return a[1024 & value];
 }
 """,
@@ -212,8 +212,8 @@
   class Type {}
   class Function {}
   class List {
-    List();
-    List.fixedLength(length);
+    List([int length]);
+    List.filled(int length, fill);
   }
   abstract class Map {}
   class Closure {}
diff --git a/tests/compiler/dart2js_extra/bailout_test.dart b/tests/compiler/dart2js_extra/bailout_test.dart
index 308658a..dd31071f 100644
--- a/tests/compiler/dart2js_extra/bailout_test.dart
+++ b/tests/compiler/dart2js_extra/bailout_test.dart
@@ -45,7 +45,7 @@
 String forInBailout() {
   var n = myString.length;
   var res = '';
-  for (int i in myString.charCodes) {
+  for (int i in myString.codeUnits) {
     var o = myString;
     if (false) o[1] = 2;
     res = res.concat(new String.fromCharCodes([i]));
diff --git a/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart b/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
index bf9a9dd..97b18ee 100644
--- a/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
+++ b/tests/compiler/dart2js_extra/deferred/deferred_class_library.dart
@@ -7,6 +7,8 @@
 library deferred_class_library;
 
 class MyClass {
+  const MyClass();
+
   foo(x) {
     print('MyClass.foo($x)');
     return (x - 3) ~/ 2;
diff --git a/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart b/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart
new file mode 100644
index 0000000..0cbe262
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/deferred_constant_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+@lazy import 'deferred_class_library.dart';
+
+const lazy = const DeferredLibrary('deferred_class_library');
+
+main() {
+  var x;
+  // TODO(ahe): What are the semantics of this:
+  // x = const MyClass();
+  Expect.isNull(x);
+  int counter = 0;
+  lazy.load().then((bool didLoad) {
+    Expect.isTrue(didLoad);
+    Expect.equals(1, ++counter);
+    print('deferred_class_library was loaded');
+    x = const MyClass();
+    Expect.equals(42, x.foo(87));
+  });
+  Expect.equals(0, counter);
+  Expect.isNull(x);
+  lazy.load().then((bool didLoad) {
+    Expect.isFalse(didLoad);
+    Expect.equals(2, ++counter);
+    print('deferred_class_library was loaded');
+    x = const MyClass();
+    Expect.equals(42, x.foo(87));
+  });
+  Expect.equals(0, counter);
+  Expect.isNull(x);
+  // TODO(ahe): What are the semantics of this:
+  // x = const MyClass();
+  Expect.isNull(x);
+}
diff --git a/tests/compiler/dart2js_extra/generics_factories_test.dart b/tests/compiler/dart2js_extra/generics_factories_test.dart
new file mode 100644
index 0000000..2de7501
--- /dev/null
+++ b/tests/compiler/dart2js_extra/generics_factories_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.
+
+// Test that factories are marked as needing rti.
+
+class A<T> {
+  foo(o) => o is T;
+  factory A.c() => new B<T>();
+  A();
+}
+
+class B<T> extends A<T> {}
+
+class C {}
+
+class D {}
+
+main() {
+  Expect.isTrue(new A<C>.c().foo(new C()));
+  Expect.isFalse(new A<C>.c().foo(new D()));
+}
diff --git a/tests/compiler/dart2js_extra/invalid_length_negative_test.dart b/tests/compiler/dart2js_extra/invalid_length_negative_test.dart
index e990bd0..9836653 100644
--- a/tests/compiler/dart2js_extra/invalid_length_negative_test.dart
+++ b/tests/compiler/dart2js_extra/invalid_length_negative_test.dart
@@ -3,5 +3,5 @@
 // BSD-style license that can be found in the LICENSE file.
 
 main() {
-  new List.fixedLength("foo");
+  new List("foo");
 }
diff --git a/tests/compiler/dart2js_extra/list_factory_test.dart b/tests/compiler/dart2js_extra/list_factory_test.dart
index 1d7b940..e774573 100644
--- a/tests/compiler/dart2js_extra/list_factory_test.dart
+++ b/tests/compiler/dart2js_extra/list_factory_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 main() {
-  var a = new List.fixedLength(4);
+  var a = new List(4);
   Expect.equals(4, a.length);
   a[0] = 42;
   a[1] = 43;
diff --git a/tests/compiler/dart2js_extra/string_escape_test.dart b/tests/compiler/dart2js_extra/string_escape_test.dart
index 27e3218..6094469 100644
--- a/tests/compiler/dart2js_extra/string_escape_test.dart
+++ b/tests/compiler/dart2js_extra/string_escape_test.dart
@@ -15,7 +15,7 @@
   for (String s in examples) {
     Expect.equals(6, s.length);
     for (int i = 0; i < 6; i++) {
-      Expect.equals(values[i], s.charCodeAt(i));
+      Expect.equals(values[i], s.codeUnitAt(i));
     }
   }
 
@@ -48,7 +48,7 @@
       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
   Expect.equals(256, allBytes.length);
   for (int i = 0; i < 256; i++) {
-    Expect.equals(i, allBytes.charCodeAt(i));
+    Expect.equals(i, allBytes.codeUnitAt(i));
   }
 }
 
@@ -67,7 +67,7 @@
   for (String s in examples) {
     Expect.equals(values.length, s.length);
     for (int i = 0; i < values.length; i++) {
-      Expect.equals(values[i], s.charCodeAt(i));
+      Expect.equals(values[i], s.codeUnitAt(i));
     }
   }
   // No characters above 0xffff until Leg supports that.
@@ -78,7 +78,7 @@
   var longValues = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0xffff, 0xffff, 0xffff];
   Expect.equals(longValues.length, long.length);
   for (int i = 0; i < longValues.length; i++) {
-    Expect.equals(longValues[i], long.charCodeAt(i));
+    Expect.equals(longValues[i], long.codeUnitAt(i));
   }
 }
 
@@ -93,7 +93,7 @@
 
   Expect.equals(128 - 32, asciiLiterals.length);
   for (int i = 32; i < 128; i++) {
-    int code = asciiLiterals.charCodeAt(i - 32);
+    int code = asciiLiterals.codeUnitAt(i - 32);
     if (code != 0) {
       Expect.equals(i, code);
     }
@@ -116,7 +116,7 @@
 testRawStrings() {
   String raw1 = r'\x00';
   Expect.equals(4, raw1.length);
-  Expect.equals(0x5c, raw1.charCodeAt(0));
+  Expect.equals(0x5c, raw1.codeUnitAt(0));
 }
 
 main() {
diff --git a/tests/corelib/collection_contains_test.dart b/tests/corelib/collection_contains_test.dart
index da96f5d..168855b 100644
--- a/tests/corelib/collection_contains_test.dart
+++ b/tests/corelib/collection_contains_test.dart
@@ -12,7 +12,7 @@
     }
     Expect.isFalse(list.contains(notInList), "!$list.contains($notInList)");
   }
-  List fixedList = new List.fixedLength(list.length);
+  List fixedList = new List(list.length);
   List growList = new List();
   for (int i = 0; i < list.length; i++) {
     fixedList[i] = list[i];
diff --git a/tests/corelib/collection_length_test.dart b/tests/corelib/collection_length_test.dart
new file mode 100644
index 0000000..e98cb1b
--- /dev/null
+++ b/tests/corelib/collection_length_test.dart
@@ -0,0 +1,75 @@
+// 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 map_test;
+import 'dart:collection';
+
+// Test that length/isEmpty opertions are constant time on
+// maps, strings and collections.
+
+void testString(int n) {
+  String s = "x";
+  String string = "";
+  int length = n;
+  while (true) {
+    if ((length & 1) == 1) {
+      string = string.concat(s);
+    }
+    length >>= 1;
+    if (length == 0) break;
+    s = s.concat(s);
+  }
+  testLength(string, n);
+  testLength(string.codeUnits, n);
+}
+
+void testMap(Map map, int n) {
+  for (int i = 0; i < n; i++) {
+    map[i] = i;
+  }
+  testLength(map, n);
+  testLength(map.keys, n);
+  testLength(map.values, n);
+}
+
+void testCollection(Collection collection, n) {
+  for (int i = 0; i < n; i++) {
+    collection.add(i);
+  }
+  testLength(collection, n);
+}
+
+void testList(List list, n) {
+  for (int i = 0; i < n; i++) {
+    list[i] = i;
+  }
+  testLength(list, n);
+}
+
+
+void testLength(var lengthable, int size) {
+  print(lengthable.runtimeType);  // Show what hangs the test.
+  int length = 0;
+  // If length or isEmpty is not a constant-time (or very fast) operation,
+  // this will timeout.
+  for (int i = 0; i < 100000; i++) {
+    if (!lengthable.isEmpty) length += lengthable.length;
+  }
+  if (length != size * 100000) throw "Bad length: $length / size: $size";
+}
+
+
+main() {
+  const int N = 100000;
+  testMap(new HashMap(), N);
+  testMap(new LinkedHashMap(), N);
+  testMap(new SplayTreeMap(), N);
+  testCollection(new HashSet(), N);
+  testCollection(new LinkedHashSet(), N);
+  testCollection(new ListQueue(), N);
+  testList(new List()..length = N, N);
+  testList(new List(N), N);
+  testString(N);
+  // DoubleLinkedQueue has linear length, but fast isEmpty.
+}
diff --git a/tests/corelib/collection_removes_test.dart b/tests/corelib/collection_removes_test.dart
index 738ce72..d057ed8 100644
--- a/tests/corelib/collection_removes_test.dart
+++ b/tests/corelib/collection_removes_test.dart
@@ -95,7 +95,8 @@
       testRetainAll(base.toList(), delta);
       testRetainAll(base.toList(), deltaSet);
       testRemoveMatching(base.toList(), deltaSet.contains);
-      testRetainMatching(base.toList(), (e) => !deltaSet.contains(e));
+      testRetainMatching(base.toList(),
+                         (e) => !deltaSet.contains(e));
 
       testRemoveAll(base.toSet(), delta);
       testRemoveAll(base.toSet(), deltaSet);
diff --git a/tests/corelib/collection_test.dart b/tests/corelib/collection_test.dart
index 202b4bb..64dfe2b 100644
--- a/tests/corelib/collection_test.dart
+++ b/tests/corelib/collection_test.dart
@@ -25,7 +25,7 @@
   new CollectionTest(TEST_ELEMENTS);
 
   // Fixed size list.
-  var fixedList = new List.fixedLength(TEST_ELEMENTS.length);
+  var fixedList = new List(TEST_ELEMENTS.length);
   for (int i = 0; i < TEST_ELEMENTS.length; i++) {
     fixedList[i] = TEST_ELEMENTS[i];
   }
diff --git a/tests/corelib/collection_to_string_test.dart b/tests/corelib/collection_to_string_test.dart
index 694aa0f..3f07236 100644
--- a/tests/corelib/collection_to_string_test.dart
+++ b/tests/corelib/collection_to_string_test.dart
@@ -299,7 +299,8 @@
 
 /** Returns the alphabetized characters in a string. */
 String alphagram(String s) {
-  List<int> chars = s.charCodes;
+  // Calling [toList] to convert unmodifiable list to normal list.
+  List<int> chars = s.codeUnits.toList();
   chars.sort((int a, int b) => a - b);
   return new String.fromCharCodes(chars);
 }
diff --git a/tests/corelib/core_runtime_types_test.dart b/tests/corelib/core_runtime_types_test.dart
index 728adb4..4c06009 100644
--- a/tests/corelib/core_runtime_types_test.dart
+++ b/tests/corelib/core_runtime_types_test.dart
@@ -153,7 +153,7 @@
   static testStringOperators() {
     var s = "abcdef";
     assertEquals(s, "abcdef");
-    assertEquals(s.charCodeAt(0), 97);
+    assertEquals(s.codeUnitAt(0), 97);
     assertEquals(s[0], 'a');
     assertEquals(s.length, 6);
     assertTypeError(() { s[null]; });
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 8672c1c..089101b 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -35,22 +35,21 @@
 math_test: Fail # issue 3333
 surrogate_pair_toUpper_test: Fail # Issue 6707
 
-reg_exp4_test: Fail, OK # Expects exception from const constructor.
-
 big_integer_vm_test: Fail, OK # VM specific test.
 compare_to2_test: Fail, OK    # Requires bigint support.
 string_base_vm_test: Fail, OK # VM specific test.
 
 string_replace_func_test: Skip # Bug 6554 - doesn't terminate.
 
+[ $compiler == dart2js && $checked ]
+string_codeunits_test: Fail # Issue 8904
+
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
-[ $compiler == dart2js && $runtime == safari ]
-core_runtime_types_test: Fail
-
 [ $compiler == dart2js && $runtime == ie9 ]
 date_time7_test: Fail # BUG(3304): Maybe this doesn't time out?
+json_strict_test: Fail # IE parses slightly harmless no-standard JSON.
 string_base_vm_test: Fail # BUG(3304): Maybe this doesn't time out?
 
 [ $compiler == dart2dart ]
diff --git a/tests/corelib/duration_test.dart b/tests/corelib/duration_test.dart
index 87f2da8..51d65c3 100644
--- a/tests/corelib/duration_test.dart
+++ b/tests/corelib/duration_test.dart
@@ -5,36 +5,51 @@
 main() {
   Duration d;
   d = new Duration(days: 1);
+  Expect.equals(86400000000, d.inMicroseconds);
   Expect.equals(86400000, d.inMilliseconds);
   Expect.equals(86400, d.inSeconds);
   Expect.equals(1440, d.inMinutes);
   Expect.equals(24, d.inHours);
   Expect.equals(1, d.inDays);
   d = const Duration(hours: 1);
+  Expect.equals(3600000000, d.inMicroseconds);
   Expect.equals(3600000, d.inMilliseconds);
   Expect.equals(3600, d.inSeconds);
   Expect.equals(60, d.inMinutes);
   Expect.equals(1, d.inHours);
   Expect.equals(0, d.inDays);
   d = new Duration(minutes: 1);
+  Expect.equals(60000000, d.inMicroseconds);
   Expect.equals(60000, d.inMilliseconds);
   Expect.equals(60, d.inSeconds);
   Expect.equals(1, d.inMinutes);
   Expect.equals(0, d.inHours);
   Expect.equals(0, d.inDays);
   d = const Duration(seconds: 1);
+  Expect.equals(1000000, d.inMicroseconds);
   Expect.equals(1000, d.inMilliseconds);
   Expect.equals(1, d.inSeconds);
   Expect.equals(0, d.inMinutes);
   Expect.equals(0, d.inHours);
   Expect.equals(0, d.inDays);
   d = new Duration(milliseconds: 1);
+  Expect.equals(1000, d.inMicroseconds);
   Expect.equals(1, d.inMilliseconds);
   Expect.equals(0, d.inSeconds);
   Expect.equals(0, d.inMinutes);
   Expect.equals(0, d.inHours);
   Expect.equals(0, d.inDays);
+  d = new Duration(microseconds: 1);
+  Expect.equals(1, d.inMicroseconds);
+  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inSeconds);
+  Expect.equals(0, d.inMinutes);
+  Expect.equals(0, d.inHours);
+  Expect.equals(0, d.inDays);
 
+  d = const Duration(milliseconds: 1, microseconds: 999);
+  Expect.equals(1999, d.inMicroseconds);
+  Expect.equals(1, d.inMilliseconds);
   d = const Duration(seconds: 1, milliseconds: 999);
   Expect.equals(1999, d.inMilliseconds);
   Expect.equals(1, d.inSeconds);
@@ -48,48 +63,63 @@
   Expect.equals(47, d.inHours);
   Expect.equals(1, d.inDays);
   d = const Duration(
-      days: 0, hours: 23, minutes: 59, seconds: 59, milliseconds: 999);
+      days: 0, hours: 23, minutes: 59, seconds: 59, milliseconds: 999,
+      microseconds: 999);
   Expect.equals(0, d.inDays);
 
   d = new Duration(days: -1);
+  Expect.equals(-86400000000, d.inMicroseconds);
   Expect.equals(-86400000, d.inMilliseconds);
   Expect.equals(-86400, d.inSeconds);
   Expect.equals(-1440, d.inMinutes);
   Expect.equals(-24, d.inHours);
   Expect.equals(-1, d.inDays);
   d = const Duration(hours: -1);
+  Expect.equals(-3600000000, d.inMicroseconds);
   Expect.equals(-3600000, d.inMilliseconds);
   Expect.equals(-3600, d.inSeconds);
   Expect.equals(-60, d.inMinutes);
   Expect.equals(-1, d.inHours);
   Expect.equals(0, d.inDays);
   d = new Duration(minutes: -1);
+  Expect.equals(-60000000, d.inMicroseconds);
   Expect.equals(-60000, d.inMilliseconds);
   Expect.equals(-60, d.inSeconds);
   Expect.equals(-1, d.inMinutes);
   Expect.equals(0, d.inHours);
   Expect.equals(0, d.inDays);
   d = const Duration(seconds: -1);
+  Expect.equals(-1000000, d.inMicroseconds);
   Expect.equals(-1000, d.inMilliseconds);
   Expect.equals(-1, d.inSeconds);
   Expect.equals(0, d.inMinutes);
   Expect.equals(0, d.inHours);
   Expect.equals(0, d.inDays);
   d = new Duration(milliseconds: -1);
+  Expect.equals(-1000, d.inMicroseconds);
   Expect.equals(-1, d.inMilliseconds);
   Expect.equals(0, d.inSeconds);
   Expect.equals(0, d.inMinutes);
   Expect.equals(0, d.inHours);
   Expect.equals(0, d.inDays);
+  d = new Duration(microseconds: -1);
+  Expect.equals(-1, d.inMicroseconds);
+  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inSeconds);
+  Expect.equals(0, d.inMinutes);
+  Expect.equals(0, d.inHours);
+  Expect.equals(0, d.inDays);
 
   d = const Duration(days: 1, hours: -24);
-  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inMicroseconds);
   d = new Duration(hours: 1, minutes: -60);
-  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inMicroseconds);
   d = const Duration(minutes: 1, seconds: -60);
-  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inMicroseconds);
   d = new Duration(seconds: 1, milliseconds: -1000);
-  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inMicroseconds);
+  d = new Duration(milliseconds: 1, microseconds: -1000);
+  Expect.equals(0, d.inMicroseconds);
 
   d = const Duration(hours: 25);
   Expect.equals(1, d.inDays);
@@ -97,71 +127,100 @@
   Expect.equals(1500, d.inMinutes);
   Expect.equals(90000, d.inSeconds);
   Expect.equals(90000000, d.inMilliseconds);
+  Expect.equals(90000000000, d.inMicroseconds);
   d = new Duration(minutes: 61);
   Expect.equals(0, d.inDays);
   Expect.equals(1, d.inHours);
   Expect.equals(61, d.inMinutes);
   Expect.equals(3660, d.inSeconds);
   Expect.equals(3660000, d.inMilliseconds);
+  Expect.equals(3660000000, d.inMicroseconds);
   d = const Duration(seconds: 61);
   Expect.equals(0, d.inDays);
   Expect.equals(0, d.inHours);
   Expect.equals(1, d.inMinutes);
   Expect.equals(61, d.inSeconds);
   Expect.equals(61000, d.inMilliseconds);
+  Expect.equals(61000000, d.inMicroseconds);
   d = new Duration(milliseconds: 1001);
   Expect.equals(0, d.inDays);
   Expect.equals(0, d.inHours);
   Expect.equals(0, d.inMinutes);
   Expect.equals(1, d.inSeconds);
   Expect.equals(1001, d.inMilliseconds);
+  Expect.equals(1001000, d.inMicroseconds);
+  d = new Duration(microseconds: 1001);
+  Expect.equals(0, d.inDays);
+  Expect.equals(0, d.inHours);
+  Expect.equals(0, d.inMinutes);
+  Expect.equals(0, d.inSeconds);
+  Expect.equals(1, d.inMilliseconds);
+  Expect.equals(1001, d.inMicroseconds);
 
   var d1 = const Duration(milliseconds: 1000);
   var d2 = const Duration(seconds: 1);
   Expect.identical(d1, d2);
 
+  d1 = const Duration(microseconds: 1000);
+  d2 = const Duration(milliseconds: 1);
+  Expect.identical(d1, d2);
+
   d1 = new Duration(hours: 1);
   d2 = new Duration(hours: -1);
   d = d1 + d2;
-  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inMicroseconds);
   d = d1 - d2;
-  Expect.equals(3600000 * 2, d.inMilliseconds);
+  Expect.equals(3600000000 * 2, d.inMicroseconds);
 
   d2 = new Duration(hours: 1);
   d = d1 + d2;
-  Expect.equals(3600000 * 2, d.inMilliseconds);
+  Expect.equals(3600000000 * 2, d.inMicroseconds);
   d = d1 - d2;
-  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inMicroseconds);
 
   d = d1 * 2;
-  Expect.equals(3600000 * 2, d.inMilliseconds);
+  Expect.equals(3600000000 * 2, d.inMicroseconds);
   d = d1 * -1;
-  Expect.equals(-3600000, d.inMilliseconds);
+  Expect.equals(-3600000000, d.inMicroseconds);
   d = d1 * 0;
-  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inMicroseconds);
 
   d = d1 ~/ 2;
-  Expect.equals(1800000, d.inMilliseconds);
-  d = d1 ~/ 3600001;
-  Expect.equals(0, d.inMilliseconds);
-  d = d1 ~/ -3600001;
-  Expect.equals(0, d.inMilliseconds);
-  d = d1 ~/ 3599999;
-  Expect.equals(1, d.inMilliseconds);
-  d = d1 ~/ -3599999;
-  Expect.equals(-1, d.inMilliseconds);
+  Expect.equals(1800000000, d.inMicroseconds);
+  d = d1 ~/ 3600000001;
+  Expect.equals(0, d.inMicroseconds);
+  d = d1 ~/ -3600000001;
+  Expect.equals(0, d.inMicroseconds);
+  d = d1 ~/ 3599999999;
+  Expect.equals(1, d.inMicroseconds);
+  d = d1 ~/ -3599999999;
+  Expect.equals(-1, d.inMicroseconds);
   d = d1 ~/ -1;
-  Expect.equals(-3600000, d.inMilliseconds);
+  Expect.equals(-3600000000, d.inMicroseconds);
   d = d1 * 0;
-  Expect.equals(0, d.inMilliseconds);
+  Expect.equals(0, d.inMicroseconds);
   Expect.throws(() => d1 ~/ 0,
                 (e) => e is IntegerDivisionByZeroException);
 
-  d = new Duration(milliseconds: 0);
-  Expect.isTrue(d < new Duration(milliseconds: 1));
-  Expect.isTrue(d <= new Duration(milliseconds: 1));
+  d = new Duration(microseconds: 0);
+  Expect.isTrue(d < new Duration(microseconds: 1));
+  Expect.isTrue(d <= new Duration(microseconds: 1));
   Expect.isTrue(d <= d);
-  Expect.isTrue(d > new Duration(milliseconds: -1));
-  Expect.isTrue(d >= new Duration(milliseconds: -1));
+  Expect.isTrue(d > new Duration(microseconds: -1));
+  Expect.isTrue(d >= new Duration(microseconds: -1));
   Expect.isTrue(d >= d);
+
+  d = const Duration(days: 1, hours: 3, minutes: 17, seconds: 42,
+                     milliseconds: 823, microseconds: 127);
+  Expect.equals("27:17:42.823127", d.toString());
+
+  d = const Duration(hours: 1999, minutes: 17, seconds: 42);
+  Expect.equals("1999:17:42.000000", d.toString());
+
+  d = const Duration(days: -1, hours: -3, minutes: -17, seconds: -42,
+                     milliseconds: -823, microseconds: -127);
+  Expect.equals("-27:17:42.823127", d.toString());
+
+  d = const Duration(hours: -1999, minutes: -17, seconds: -42);
+  Expect.equals("-1999:17:42.000000", d.toString());
 }
diff --git a/tests/corelib/for_in_test.dart b/tests/corelib/for_in_test.dart
index de51cc1..ea53727 100644
--- a/tests/corelib/for_in_test.dart
+++ b/tests/corelib/for_in_test.dart
@@ -79,7 +79,7 @@
 
   static void testClosure() {
     Set<int> set = getSmallSet();
-    List<Function> closures = new List.fixedLength(set.length);
+    List<Function> closures = new List(set.length);
     int index = 0;
     for (var i in set) {
       closures[index++] = () => i;
diff --git a/tests/corelib/indexed_list_access_test.dart b/tests/corelib/indexed_list_access_test.dart
index 791e961..2feab1e 100644
--- a/tests/corelib/indexed_list_access_test.dart
+++ b/tests/corelib/indexed_list_access_test.dart
@@ -6,7 +6,7 @@
 // is not int.
 
 main() {
-  checkList(new List.fixedLength(10));
+  checkList(new List(10));
   var growable = new List();
   growable.add(1);
   growable.add(1);
diff --git a/tests/corelib/is_operator_basic_types_test.dart b/tests/corelib/is_operator_basic_types_test.dart
index e0771bb..662b2a4 100644
--- a/tests/corelib/is_operator_basic_types_test.dart
+++ b/tests/corelib/is_operator_basic_types_test.dart
@@ -61,5 +61,5 @@
 
   // Try to make it even harder.
   var string = new String.fromCharCodes([new DateTime.now().year % 100 + 1]);
-  check([string.charCodes, string, null]);
+  check([string.codeUnits, string, null]);
 }
diff --git a/tests/corelib/iterable_join_test.dart b/tests/corelib/iterable_join_test.dart
index b09227f..96922a9 100644
--- a/tests/corelib/iterable_join_test.dart
+++ b/tests/corelib/iterable_join_test.dart
@@ -49,7 +49,7 @@
     testJoin("0,1,2,3,4", array.takeWhile((i) => i < 5), ",");
   }
   testArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
-  var fixedArray = new List.fixedLength(10);
+  var fixedArray = new List(10);
   for (int i = 0; i < 10; i++) {
     fixedArray[i] = i;
   }
diff --git a/tests/corelib/iterable_test.dart b/tests/corelib/iterable_test.dart
new file mode 100644
index 0000000..6b8fe13
--- /dev/null
+++ b/tests/corelib/iterable_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for dart2js where [List.addAll] was not typed
+// correctly.
+
+class MyIterable implements Iterable {
+  get iterator => [].iterator;
+}
+
+main() {
+  Expect.isTrue(([]..addAll(new MyIterable())).isEmpty);
+}
diff --git a/tests/corelib/json_test.dart b/tests/corelib/json_test.dart
index 75d22a3..5a36d99 100644
--- a/tests/corelib/json_test.dart
+++ b/tests/corelib/json_test.dart
@@ -36,8 +36,23 @@
   compare(expected, value, "value");
 }
 
+String escape(String s) {
+  var sb = new StringBuffer();
+  for (int i = 0; i < s.length; i++) {
+    int code = s.codeUnitAt(i);
+    if (code == '\\'.codeUnitAt(0)) sb.write(r'\\');
+    else if (code == '\"'.codeUnitAt(0)) sb.write(r'\"');
+    else if (code >= 32 && code < 127) sb.writeCharCode(code);
+    else {
+      String hex = '000${code.toRadixString(16)}';
+      sb.write(r'\u' '${hex.substring(hex.length - 4)}');
+    }
+  }
+  return '$sb';
+}
+
 void testThrows(json) {
-  Expect.throws(() => parse(json), badFormat);
+  Expect.throws(() => parse(json), badFormat, "json = '${escape(json)}'");
 }
 
 testNumbers() {
@@ -97,8 +112,11 @@
 
   // Integer part cannot be omitted:
   testError(integers: "");
-  // Initial zero only allowed for zero integer part.
-  testError(integers: ["00", "01"]);
+
+  // Test for "Initial zero only allowed for zero integer part" moved to
+  // json_strict_test.dart because IE's JSON.parse accepts additional initial
+  // zeros.
+
   // Only minus allowed as sign.
   testError(signs: "+");
   // Requires digits after decimal point.
@@ -107,7 +125,7 @@
   testError(exponents: ["e", "e+", "e-", "e.0"]);
 
   // No whitespace inside numbers.
-  testThrows("- 2.2e+2");
+  // Additional case "- 2.2e+2" in json_strict_test.dart.
   testThrows("-2 .2e+2");
   testThrows("-2. 2e+2");
   testThrows("-2.2 e+2");
@@ -223,21 +241,20 @@
   testJson('$v[${v}-2.2e2$v,$v{$v"key"$v:${v}true$v}$v,$v"ab"$v]$v',
            [-2.2e2, {"key": true}, "ab"]);
 
+  // IE9 accepts invalid characters at the end, so some of these tests have been
+  // moved to json_strict_test.dart.
   for (var i in invalids) {
     testThrows('${i}"s"');
-    testThrows('"s"${i}');
     testThrows('42${i}');
     testThrows('$i[]');
     testThrows('[$i]');
     testThrows('[$i"s"]');
     testThrows('["s"$i]');
-    testThrows('[]$i');
     testThrows('$i{"k":"v"}');
     testThrows('{$i"k":"v"}');
     testThrows('{"k"$i:"v"}');
     testThrows('{"k":$i"v"}');
     testThrows('{"k":"v"$i}');
-    testThrows('{"k":"v"}$i');
   }
 }
 
diff --git a/tests/corelib/linked_hash_map_test.dart b/tests/corelib/linked_hash_map_test.dart
index 4de0b3e..54eddeb 100644
--- a/tests/corelib/linked_hash_map_test.dart
+++ b/tests/corelib/linked_hash_map_test.dart
@@ -15,8 +15,8 @@
     map["d"] = 4;
     map["e"] = 5;
 
-    List<String> keys = new List<String>.fixedLength(5);
-    List<int> values = new List<int>.fixedLength(5);
+    List<String> keys = new List<String>(5);
+    List<int> values = new List<int>(5);
 
     int index;
 
diff --git a/tests/corelib/list_as_map_test.dart b/tests/corelib/list_as_map_test.dart
new file mode 100644
index 0000000..03f5540
--- /dev/null
+++ b/tests/corelib/list_as_map_test.dart
@@ -0,0 +1,96 @@
+// 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.
+
+void testListMapCorrespondence(List list, Map map) {
+  Expect.equals(list.length, map.length);
+  for (int i = 0; i < list.length; i++) {
+    Expect.equals(list[i], map[i]);
+  }
+  Expect.isNull(map[list.length]);
+  Expect.isNull(map[-1]);
+
+  Iterable keys = map.keys;
+  Iterable values = map.values;
+  Expect.isFalse(keys is List);
+  Expect.isFalse(values is List);
+  Expect.equals(list.length, keys.length);
+  Expect.equals(list.length, values.length);
+  for (int i = 0; i < list.length; i++) {
+    Expect.equals(i, keys.elementAt(i));
+    Expect.equals(list[i], values.elementAt(i));
+  }
+
+  int forEachCount = 0;
+  map.forEach((key, value) {
+    Expect.equals(forEachCount, key);
+    Expect.equals(list[key], value);
+    forEachCount++;
+  });
+
+  for (int i = 0; i < list.length; i++) {
+    Expect.isTrue(map.containsKey(i));
+    Expect.isTrue(map.containsValue(list[i]));
+  }
+  Expect.isFalse(map.containsKey(-1));
+  Expect.isFalse(map.containsKey(list.length));
+
+  Expect.equals(list.length, forEachCount);
+
+  Expect.equals(list.isEmpty, map.isEmpty);
+}
+
+void testConstAsMap(List list) {
+  Map<int, dynamic> map = list.asMap();
+
+  testListMapCorrespondence(list, map);
+
+  Expect.throws(() => map[0] = 499,
+                (e) => e is UnsupportedError);
+  Expect.throws(() => map.putIfAbsent(0, () => 499),
+                (e) => e is UnsupportedError);
+  Expect.throws(() => map.clear(),
+                (e) => e is UnsupportedError);
+}
+
+void testFixedAsMap(List list) {
+  testConstAsMap(list);
+
+  Map<int, dynamic> map = list.asMap();
+
+  if (!list.isEmpty) {
+    list[0] = 499;
+    // Check again to make sure the map is backed by the list.
+    testListMapCorrespondence(list, map);
+  }
+}
+
+void testAsMap(List list) {
+  testFixedAsMap(list);
+
+  Map<int, dynamic> map = list.asMap();
+
+  Iterable keys = map.keys;
+  Iterable values = map.values;
+
+  list.add(42);
+  // Check again to make sure the map is backed by the list and that the
+  // length is not cached.
+  testListMapCorrespondence(list, map);
+  // Also check that the keys and values iterable from the map are backed by
+  // the list.
+  Expect.equals(list.length, keys.length);
+  Expect.equals(values.length, values.length);
+}
+
+main() {
+  testConstAsMap(const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+  testAsMap([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+  List list = new List(10);
+  for (int i = 0; i < 10; i++) list[i] = i + 1;
+  testFixedAsMap(list);
+
+  testConstAsMap(const []);
+  testAsMap([]);
+  testFixedAsMap(new List(0));
+}
diff --git a/tests/corelib/list_fixed_test.dart b/tests/corelib/list_fixed_test.dart
index b6d7440..c29d8ea 100644
--- a/tests/corelib/list_fixed_test.dart
+++ b/tests/corelib/list_fixed_test.dart
@@ -5,7 +5,7 @@
 main() {
   var a;
 
-  a = new List.fixedLength(42);
+  a = new List(42);
   Expect.equals(42, a.length);
   Expect.throws(() => a.add(499), (e) => e is UnsupportedError);
   Expect.equals(42, a.length);
@@ -15,7 +15,7 @@
   Expect.throws(() => a.clear(), (e) => e is UnsupportedError);
   Expect.equals(42, a.length);
 
-  a = new List.fixedLength(42, fill: -2);
+  a = new List.filled(42, -2);
   Expect.equals(42, a.length);
   Expect.throws(() => a.add(499), (e) => e is UnsupportedError);
   Expect.equals(42, a.length);
diff --git a/tests/corelib/list_growable_test.dart b/tests/corelib/list_growable_test.dart
index 616b450..563f187 100644
--- a/tests/corelib/list_growable_test.dart
+++ b/tests/corelib/list_growable_test.dart
@@ -12,7 +12,7 @@
   Expect.equals(0, a.length);
   Expect.throws(() => a[0], (e) => e is RangeError);
 
-  a = new List(42);
+  a = new List(42).toList();
   Expect.equals(42, a.length);
   a.add(499);
   Expect.equals(43, a.length);
@@ -22,7 +22,7 @@
   Expect.equals(0, a.length);
   Expect.throws(() => a[0], (e) => e is RangeError);
 
-  a = new List<int>(42);
+  a = new List<int>(42).toList();
   Expect.equals(42, a.length);
   a.add(499);
   Expect.equals(43, a.length);
diff --git a/tests/corelib/list_index_of_test.dart b/tests/corelib/list_index_of_test.dart
index c217f41..ca8ab4c 100644
--- a/tests/corelib/list_index_of_test.dart
+++ b/tests/corelib/list_index_of_test.dart
@@ -4,7 +4,7 @@
 
 class ListIndexOfTest {
   static testMain() {
-    test(new List<int>.fixedLength(5));
+    test(new List<int>(5));
     var l = new List<int>();
     l.length = 5;
     test(l);
diff --git a/tests/corelib/list_iterators_test.dart b/tests/corelib/list_iterators_test.dart
index c20e5eb..e7ed128 100644
--- a/tests/corelib/list_iterators_test.dart
+++ b/tests/corelib/list_iterators_test.dart
@@ -18,8 +18,8 @@
   static testMain() {
     checkListIterator([]);
     checkListIterator([1, 2]);
-    checkListIterator(new List.fixedLength(0));
-    checkListIterator(new List.fixedLength(10));
+    checkListIterator(new List(0));
+    checkListIterator(new List(10));
     checkListIterator(new List());
     List g = new List();
     g.addAll([1, 2, 3]);
diff --git a/tests/corelib/list_removeat_test.dart b/tests/corelib/list_removeat_test.dart
index df7ac16..d6a9b28 100644
--- a/tests/corelib/list_removeat_test.dart
+++ b/tests/corelib/list_removeat_test.dart
@@ -42,7 +42,7 @@
   Expect.equals(3, l1.length, "length-2");
 
   // Fixed size list.
-  var l2 = new List.fixedLength(5);
+  var l2 = new List(5);
   for (var i = 0; i < 5; i++) l2[i] = i;
   Expect.throws(() { l2.removeAt(2); },
                 (e) => e is UnsupportedError,
diff --git a/tests/corelib/list_set_range_test.dart b/tests/corelib/list_set_range_test.dart
index ff91fe7..f96ede5 100644
--- a/tests/corelib/list_set_range_test.dart
+++ b/tests/corelib/list_set_range_test.dart
@@ -82,7 +82,7 @@
 }
 
 void testNonExtendableList() {
-  var list = new List<int>.fixedLength(6);
+  var list = new List<int>(6);
   Expect.listEquals([null, null, null, null, null, null], list);
   list.setRange(0, 3, [1, 2, 3, 4]);
   list.setRange(3, 3, [1, 2, 3, 4]);
diff --git a/tests/corelib/list_test.dart b/tests/corelib/list_test.dart
index 5aa5ae9..9a88a9f 100644
--- a/tests/corelib/list_test.dart
+++ b/tests/corelib/list_test.dart
@@ -49,7 +49,7 @@
   }
 
   static void testList() {
-    List list = new List.fixedLength(4);
+    List list = new List(4);
     Expect.equals(list.length, 4);
     list[0] = 4;
     expectValues(list, 4, null, null, null);
diff --git a/tests/corelib/map_test.dart b/tests/corelib/map_test.dart
index 40cfab5..d405471 100644
--- a/tests/corelib/map_test.dart
+++ b/tests/corelib/map_test.dart
@@ -5,246 +5,262 @@
 library map_test;
 import 'dart:collection';
 
-class MapTest {
-
-  static testMain() {
-    test(new HashMap());
-    test(new LinkedHashMap());
-    test(new SplayTreeMap());
-    testLinkedHashMap();
-    testMapLiteral();
-    testNullValue();
-  }
-
-  static void test(Map map) {
-    testDeletedElement(map);
-    testMap(map, 1, 2, 3, 4, 5, 6, 7, 8);
-    map.clear();
-    testMap(map, "value1", "value2", "value3", "value4", "value5",
-            "value6", "value7", "value8");
-  }
-
-  static void testLinkedHashMap() {
-    LinkedHashMap map = new LinkedHashMap();
-    Expect.equals(false, map.containsKey(1));
-    map[1] = 1;
-    map[1] = 2;
-    Expect.equals(1, map.length);
-  }
-
-  static void testMap(Map map, key1, key2, key3, key4, key5, key6, key7, key8) {
-    int value1 = 10;
-    int value2 = 20;
-    int value3 = 30;
-    int value4 = 40;
-    int value5 = 50;
-    int value6 = 60;
-    int value7 = 70;
-    int value8 = 80;
-
-    Expect.equals(0, map.length);
-
-    map[key1] = value1;
-    Expect.equals(value1, map[key1]);
-    map[key1] = value2;
-    Expect.equals(false, map.containsKey(key2));
-    Expect.equals(1, map.length);
-
-    map[key1] = value1;
-    Expect.equals(value1, map[key1]);
-    // Add enough entries to make sure the table grows.
-    map[key2] = value2;
-    Expect.equals(value2, map[key2]);
-    Expect.equals(2, map.length);
-    map[key3] = value3;
-    Expect.equals(value2, map[key2]);
-    Expect.equals(value3, map[key3]);
-    map[key4] = value4;
-    Expect.equals(value3, map[key3]);
-    Expect.equals(value4, map[key4]);
-    map[key5] = value5;
-    Expect.equals(value4, map[key4]);
-    Expect.equals(value5, map[key5]);
-    map[key6] = value6;
-    Expect.equals(value5, map[key5]);
-    Expect.equals(value6, map[key6]);
-    map[key7] = value7;
-    Expect.equals(value6, map[key6]);
-    Expect.equals(value7, map[key7]);
-    map[key8] = value8;
-    Expect.equals(value1, map[key1]);
-    Expect.equals(value2, map[key2]);
-    Expect.equals(value3, map[key3]);
-    Expect.equals(value4, map[key4]);
-    Expect.equals(value5, map[key5]);
-    Expect.equals(value6, map[key6]);
-    Expect.equals(value7, map[key7]);
-    Expect.equals(value8, map[key8]);
-    Expect.equals(8, map.length);
-
-    map.remove(key4);
-    Expect.equals(false, map.containsKey(key4));
-    Expect.equals(7, map.length);
-
-    // Test clearing the table.
-    map.clear();
-    Expect.equals(0, map.length);
-    Expect.equals(false, map.containsKey(key1));
-    Expect.equals(false, map.containsKey(key2));
-    Expect.equals(false, map.containsKey(key3));
-    Expect.equals(false, map.containsKey(key4));
-    Expect.equals(false, map.containsKey(key5));
-    Expect.equals(false, map.containsKey(key6));
-    Expect.equals(false, map.containsKey(key7));
-    Expect.equals(false, map.containsKey(key8));
-
-    // Test adding and removing again.
-    map[key1] = value1;
-    Expect.equals(value1, map[key1]);
-    Expect.equals(1, map.length);
-    map[key2] = value2;
-    Expect.equals(value2, map[key2]);
-    Expect.equals(2, map.length);
-    map[key3] = value3;
-    Expect.equals(value3, map[key3]);
-    map.remove(key3);
-    Expect.equals(2, map.length);
-    map[key4] = value4;
-    Expect.equals(value4, map[key4]);
-    map.remove(key4);
-    Expect.equals(2, map.length);
-    map[key5] = value5;
-    Expect.equals(value5, map[key5]);
-    map.remove(key5);
-    Expect.equals(2, map.length);
-    map[key6] = value6;
-    Expect.equals(value6, map[key6]);
-    map.remove(key6);
-    Expect.equals(2, map.length);
-    map[key7] = value7;
-    Expect.equals(value7, map[key7]);
-    map.remove(key7);
-    Expect.equals(2, map.length);
-    map[key8] = value8;
-    Expect.equals(value8, map[key8]);
-    map.remove(key8);
-    Expect.equals(2, map.length);
-
-    Expect.equals(true, map.containsKey(key1));
-    Expect.equals(true, map.containsValue(value1));
-
-    // Test Map.forEach.
-    Map other_map = new Map();
-    void testForEachMap(key, value) {
-      other_map[key] = value;
-    }
-    map.forEach(testForEachMap);
-    Expect.equals(true, other_map.containsKey(key1));
-    Expect.equals(true, other_map.containsKey(key2));
-    Expect.equals(true, other_map.containsValue(value1));
-    Expect.equals(true, other_map.containsValue(value2));
-    Expect.equals(2, other_map.length);
-
-    other_map.clear();
-    Expect.equals(0, other_map.length);
-
-    // Test Collection.keys.
-    void testForEachCollection(value) {
-      other_map[value] = value;
-    }
-    Iterable keys = map.keys;
-    keys.forEach(testForEachCollection);
-    Expect.equals(true, other_map.containsKey(key1));
-    Expect.equals(true, other_map.containsKey(key2));
-    Expect.equals(true, other_map.containsValue(key1));
-    Expect.equals(true, other_map.containsValue(key2));
-    Expect.equals(true, !other_map.containsKey(value1));
-    Expect.equals(true, !other_map.containsKey(value2));
-    Expect.equals(true, !other_map.containsValue(value1));
-    Expect.equals(true, !other_map.containsValue(value2));
-    Expect.equals(2, other_map.length);
-    other_map.clear();
-    Expect.equals(0, other_map.length);
-
-    // Test Collection.values.
-    Iterable values = map.values;
-    values.forEach(testForEachCollection);
-    Expect.equals(true, !other_map.containsKey(key1));
-    Expect.equals(true, !other_map.containsKey(key2));
-    Expect.equals(true, !other_map.containsValue(key1));
-    Expect.equals(true, !other_map.containsValue(key2));
-    Expect.equals(true, other_map.containsKey(value1));
-    Expect.equals(true, other_map.containsKey(value2));
-    Expect.equals(true, other_map.containsValue(value1));
-    Expect.equals(true, other_map.containsValue(value2));
-    Expect.equals(2, other_map.length);
-    other_map.clear();
-    Expect.equals(0, other_map.length);
-
-    // Test Map.putIfAbsent.
-    map.clear();
-    Expect.equals(false, map.containsKey(key1));
-    map.putIfAbsent(key1, () => 10);
-    Expect.equals(true, map.containsKey(key1));
-    Expect.equals(10, map[key1]);
-    Expect.equals(10,
-        map.putIfAbsent(key1, () => 11));
-  }
-
-  static void testDeletedElement(Map map) {
-    map.clear();
-    for (int i = 0; i < 100; i++) {
-      map[1] = 2;
-      Expect.equals(1, map.length);
-      map.remove(1);
-      Expect.equals(0, map.length);
-    }
-    Expect.equals(0, map.length);
-  }
-
-  static void testMapLiteral() {
-    Map m = {"a": 1, "b" : 2, "c": 3 };
-    Expect.equals(3, m.length);
-    int sum = 0;
-    m.forEach((a, b) {
-      sum += b;
-    });
-    Expect.equals(6, sum);
-
-    List values = m.keys.toList();
-    Expect.equals(3, values.length);
-    String first = values[0];
-    String second = values[1];
-    String third = values[2];
-    String all = "${first}${second}${third}";
-    Expect.equals(3, all.length);
-    Expect.equals(true, all.contains("a", 0));
-    Expect.equals(true, all.contains("b", 0));
-    Expect.equals(true, all.contains("c", 0));
-  }
-
-  static void testNullValue() {
-    Map m = {"a": 1, "b" : null, "c": 3 };
-
-    Expect.equals(null, m["b"]);
-    Expect.equals(true, m.containsKey("b"));
-    Expect.equals(3, m.length);
-
-    m["a"] = null;
-    m["c"] = null;
-    Expect.equals(null, m["a"]);
-    Expect.equals(true, m.containsKey("a"));
-    Expect.equals(null, m["c"]);
-    Expect.equals(true, m.containsKey("c"));
-    Expect.equals(3, m.length);
-
-    m.remove("a");
-    Expect.equals(2, m.length);
-    Expect.equals(null, m["a"]);
-    Expect.equals(false, m.containsKey("a"));
-  }
+void main() {
+  test(new HashMap());
+  test(new LinkedHashMap());
+  test(new SplayTreeMap());
+  test(new SplayTreeMap(Comparable.compare));
+  testLinkedHashMap();
+  testMapLiteral();
+  testNullValue();
+  testTypes();
 }
 
-main() {
-  MapTest.testMain();
+void test(Map map) {
+  testDeletedElement(map);
+  testMap(map, 1, 2, 3, 4, 5, 6, 7, 8);
+  map.clear();
+  testMap(map, "value1", "value2", "value3", "value4", "value5",
+          "value6", "value7", "value8");
+}
+
+void testLinkedHashMap() {
+  LinkedHashMap map = new LinkedHashMap();
+  Expect.equals(false, map.containsKey(1));
+  map[1] = 1;
+  map[1] = 2;
+  Expect.equals(1, map.length);
+}
+
+void testMap(Map map, key1, key2, key3, key4, key5, key6, key7, key8) {
+  int value1 = 10;
+  int value2 = 20;
+  int value3 = 30;
+  int value4 = 40;
+  int value5 = 50;
+  int value6 = 60;
+  int value7 = 70;
+  int value8 = 80;
+
+  Expect.equals(0, map.length);
+
+  map[key1] = value1;
+  Expect.equals(value1, map[key1]);
+  map[key1] = value2;
+  Expect.equals(false, map.containsKey(key2));
+  Expect.equals(1, map.length);
+
+  map[key1] = value1;
+  Expect.equals(value1, map[key1]);
+  // Add enough entries to make sure the table grows.
+  map[key2] = value2;
+  Expect.equals(value2, map[key2]);
+  Expect.equals(2, map.length);
+  map[key3] = value3;
+  Expect.equals(value2, map[key2]);
+  Expect.equals(value3, map[key3]);
+  map[key4] = value4;
+  Expect.equals(value3, map[key3]);
+  Expect.equals(value4, map[key4]);
+  map[key5] = value5;
+  Expect.equals(value4, map[key4]);
+  Expect.equals(value5, map[key5]);
+  map[key6] = value6;
+  Expect.equals(value5, map[key5]);
+  Expect.equals(value6, map[key6]);
+  map[key7] = value7;
+  Expect.equals(value6, map[key6]);
+  Expect.equals(value7, map[key7]);
+  map[key8] = value8;
+  Expect.equals(value1, map[key1]);
+  Expect.equals(value2, map[key2]);
+  Expect.equals(value3, map[key3]);
+  Expect.equals(value4, map[key4]);
+  Expect.equals(value5, map[key5]);
+  Expect.equals(value6, map[key6]);
+  Expect.equals(value7, map[key7]);
+  Expect.equals(value8, map[key8]);
+  Expect.equals(8, map.length);
+
+  map.remove(key4);
+  Expect.equals(false, map.containsKey(key4));
+  Expect.equals(7, map.length);
+
+  // Test clearing the table.
+  map.clear();
+  Expect.equals(0, map.length);
+  Expect.equals(false, map.containsKey(key1));
+  Expect.equals(false, map.containsKey(key2));
+  Expect.equals(false, map.containsKey(key3));
+  Expect.equals(false, map.containsKey(key4));
+  Expect.equals(false, map.containsKey(key5));
+  Expect.equals(false, map.containsKey(key6));
+  Expect.equals(false, map.containsKey(key7));
+  Expect.equals(false, map.containsKey(key8));
+
+  // Test adding and removing again.
+  map[key1] = value1;
+  Expect.equals(value1, map[key1]);
+  Expect.equals(1, map.length);
+  map[key2] = value2;
+  Expect.equals(value2, map[key2]);
+  Expect.equals(2, map.length);
+  map[key3] = value3;
+  Expect.equals(value3, map[key3]);
+  map.remove(key3);
+  Expect.equals(2, map.length);
+  map[key4] = value4;
+  Expect.equals(value4, map[key4]);
+  map.remove(key4);
+  Expect.equals(2, map.length);
+  map[key5] = value5;
+  Expect.equals(value5, map[key5]);
+  map.remove(key5);
+  Expect.equals(2, map.length);
+  map[key6] = value6;
+  Expect.equals(value6, map[key6]);
+  map.remove(key6);
+  Expect.equals(2, map.length);
+  map[key7] = value7;
+  Expect.equals(value7, map[key7]);
+  map.remove(key7);
+  Expect.equals(2, map.length);
+  map[key8] = value8;
+  Expect.equals(value8, map[key8]);
+  map.remove(key8);
+  Expect.equals(2, map.length);
+
+  Expect.equals(true, map.containsKey(key1));
+  Expect.equals(true, map.containsValue(value1));
+
+  // Test Map.forEach.
+  Map other_map = new Map();
+  void testForEachMap(key, value) {
+    other_map[key] = value;
+  }
+  map.forEach(testForEachMap);
+  Expect.equals(true, other_map.containsKey(key1));
+  Expect.equals(true, other_map.containsKey(key2));
+  Expect.equals(true, other_map.containsValue(value1));
+  Expect.equals(true, other_map.containsValue(value2));
+  Expect.equals(2, other_map.length);
+
+  other_map.clear();
+  Expect.equals(0, other_map.length);
+
+  // Test Collection.keys.
+  void testForEachCollection(value) {
+    other_map[value] = value;
+  }
+  Iterable keys = map.keys;
+  keys.forEach(testForEachCollection);
+  Expect.equals(true, other_map.containsKey(key1));
+  Expect.equals(true, other_map.containsKey(key2));
+  Expect.equals(true, other_map.containsValue(key1));
+  Expect.equals(true, other_map.containsValue(key2));
+  Expect.equals(true, !other_map.containsKey(value1));
+  Expect.equals(true, !other_map.containsKey(value2));
+  Expect.equals(true, !other_map.containsValue(value1));
+  Expect.equals(true, !other_map.containsValue(value2));
+  Expect.equals(2, other_map.length);
+  other_map.clear();
+  Expect.equals(0, other_map.length);
+
+  // Test Collection.values.
+  Iterable values = map.values;
+  values.forEach(testForEachCollection);
+  Expect.equals(true, !other_map.containsKey(key1));
+  Expect.equals(true, !other_map.containsKey(key2));
+  Expect.equals(true, !other_map.containsValue(key1));
+  Expect.equals(true, !other_map.containsValue(key2));
+  Expect.equals(true, other_map.containsKey(value1));
+  Expect.equals(true, other_map.containsKey(value2));
+  Expect.equals(true, other_map.containsValue(value1));
+  Expect.equals(true, other_map.containsValue(value2));
+  Expect.equals(2, other_map.length);
+  other_map.clear();
+  Expect.equals(0, other_map.length);
+
+  // Test Map.putIfAbsent.
+  map.clear();
+  Expect.equals(false, map.containsKey(key1));
+  map.putIfAbsent(key1, () => 10);
+  Expect.equals(true, map.containsKey(key1));
+  Expect.equals(10, map[key1]);
+  Expect.equals(10,
+      map.putIfAbsent(key1, () => 11));
+}
+
+void testDeletedElement(Map map) {
+  map.clear();
+  for (int i = 0; i < 100; i++) {
+    map[1] = 2;
+    Expect.equals(1, map.length);
+    map.remove(1);
+    Expect.equals(0, map.length);
+  }
+  Expect.equals(0, map.length);
+}
+
+void testMapLiteral() {
+  Map m = {"a": 1, "b" : 2, "c": 3 };
+  Expect.equals(3, m.length);
+  int sum = 0;
+  m.forEach((a, b) {
+    sum += b;
+  });
+  Expect.equals(6, sum);
+
+  List values = m.keys.toList();
+  Expect.equals(3, values.length);
+  String first = values[0];
+  String second = values[1];
+  String third = values[2];
+  String all = "${first}${second}${third}";
+  Expect.equals(3, all.length);
+  Expect.equals(true, all.contains("a", 0));
+  Expect.equals(true, all.contains("b", 0));
+  Expect.equals(true, all.contains("c", 0));
+}
+
+void testNullValue() {
+  Map m = {"a": 1, "b" : null, "c": 3 };
+
+  Expect.equals(null, m["b"]);
+  Expect.equals(true, m.containsKey("b"));
+  Expect.equals(3, m.length);
+
+  m["a"] = null;
+  m["c"] = null;
+  Expect.equals(null, m["a"]);
+  Expect.equals(true, m.containsKey("a"));
+  Expect.equals(null, m["c"]);
+  Expect.equals(true, m.containsKey("c"));
+  Expect.equals(3, m.length);
+
+  m.remove("a");
+  Expect.equals(2, m.length);
+  Expect.equals(null, m["a"]);
+  Expect.equals(false, m.containsKey("a"));
+}
+
+void testTypes() {
+  Map<int> map;
+  testMap(Map map) {
+    map[42] = "text";
+    map[43] = "text";
+    map[42] = "text";
+    map.remove(42);
+    map[42] = "text";
+  }
+  testMap(new HashMap<int, String>());
+  testMap(new LinkedHashMap<int, String>());
+  testMap(new SplayTreeMap<int, String>());
+  testMap(new SplayTreeMap<int, String>(Comparable.compare));
+  testMap(new SplayTreeMap<int, String>((int a, int b) => a.compareTo(b)));
+  testMap(new HashMap<num, String>());
+  testMap(new LinkedHashMap<num, String>());
+  testMap(new SplayTreeMap<num, String>());
+  testMap(new SplayTreeMap<num, String>(Comparable.compare));
+  testMap(new SplayTreeMap<num, String>((num a, num b) => a.compareTo(b)));
 }
diff --git a/tests/corelib/range_error_test.dart b/tests/corelib/range_error_test.dart
index 62be0b8..e83bd30 100644
--- a/tests/corelib/range_error_test.dart
+++ b/tests/corelib/range_error_test.dart
@@ -14,7 +14,7 @@
     testListRead(list, -1);
     testListRead(list, 1);
 
-    list = new List.fixedLength(1);
+    list = new List(1);
     testListRead(list, -1);
     testListRead(list, 1);
 
@@ -33,7 +33,7 @@
     testListWrite(list, -1);
     testListWrite(list, 1);
 
-    list = new List.fixedLength(1);
+    list = new List(1);
     testListWrite(list, -1);
     testListWrite(list, 1);
 
diff --git a/tests/corelib/set_test.dart b/tests/corelib/set_test.dart
index efe8cf1..3be91d5 100644
--- a/tests/corelib/set_test.dart
+++ b/tests/corelib/set_test.dart
@@ -2,170 +2,172 @@
 // for 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 SetTest {
+library set_test;
 
-  static testMain() {
-    Set set = new Set();
-    Expect.equals(0, set.length);
-    set.add(1);
-    Expect.equals(1, set.length);
-    Expect.equals(true, set.contains(1));
+import "dart:collection";
 
-    set.add(1);
-    Expect.equals(1, set.length);
-    Expect.equals(true, set.contains(1));
+void testMain(Set create()) {
+  Set set = create();
+  Expect.equals(0, set.length);
+  set.add(1);
+  Expect.equals(1, set.length);
+  Expect.equals(true, set.contains(1));
 
-    set.remove(1);
-    Expect.equals(0, set.length);
-    Expect.equals(false, set.contains(1));
+  set.add(1);
+  Expect.equals(1, set.length);
+  Expect.equals(true, set.contains(1));
 
-    for (int i = 0; i < 10; i++) {
-      set.add(i);
-    }
+  set.remove(1);
+  Expect.equals(0, set.length);
+  Expect.equals(false, set.contains(1));
 
-    Expect.equals(10, set.length);
-    for (int i = 0; i < 10; i++) {
-      Expect.equals(true, set.contains(i));
-    }
-
-    Expect.equals(10, set.length);
-
-    for (int i = 10; i < 20; i++) {
-      Expect.equals(false, set.contains(i));
-    }
-
-    // Test Set.forEach.
-    int sum = 0;
-    testForEach(int val) {
-      sum += (val + 1);
-    }
-
-    set.forEach(testForEach);
-    Expect.equals(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, sum);
-
-    Expect.equals(true, set.isSubsetOf(set));
-    Expect.equals(true, set.containsAll(set));
-
-    // Test Set.map.
-    testMap(int val) {
-      return val * val;
-    }
-
-    Set mapped = set.map(testMap).toSet();
-    Expect.equals(10, mapped.length);
-
-    Expect.equals(true, mapped.contains(0));
-    Expect.equals(true, mapped.contains(1));
-    Expect.equals(true, mapped.contains(4));
-    Expect.equals(true, mapped.contains(9));
-    Expect.equals(true, mapped.contains(16));
-    Expect.equals(true, mapped.contains(25));
-    Expect.equals(true, mapped.contains(36));
-    Expect.equals(true, mapped.contains(49));
-    Expect.equals(true, mapped.contains(64));
-    Expect.equals(true, mapped.contains(81));
-
-    sum = 0;
-    set.forEach(testForEach);
-    Expect.equals(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, sum);
-
-    sum = 0;
-
-    mapped.forEach(testForEach);
-    Expect.equals(1 + 2 + 5 + 10 + 17 + 26 + 37 + 50 + 65 + 82, sum);
-
-    // Test Set.filter.
-    testFilter(int val) {
-      return val.isEven;
-    }
-
-    Set filtered = set.where(testFilter).toSet();
-
-    Expect.equals(5, filtered.length);
-
-    Expect.equals(true, filtered.contains(0));
-    Expect.equals(true, filtered.contains(2));
-    Expect.equals(true, filtered.contains(4));
-    Expect.equals(true, filtered.contains(6));
-    Expect.equals(true, filtered.contains(8));
-
-    sum = 0;
-    filtered.forEach(testForEach);
-    Expect.equals(1 + 3 + 5 + 7 + 9, sum);
-
-    Expect.equals(true, set.containsAll(filtered));
-    Expect.equals(true, filtered.isSubsetOf(set));
-
-    // Test Set.every.
-    testEvery(int val) {
-      return (val < 10);
-    }
-
-    Expect.equals(true, set.every(testEvery));
-    Expect.equals(true, filtered.every(testEvery));
-
-    filtered.add(10);
-    Expect.equals(false, filtered.every(testEvery));
-
-    // Test Set.some.
-    testSome(int val) {
-      return (val == 4);
-    }
-
-    Expect.equals(true, set.any(testSome));
-    Expect.equals(true, filtered.any(testSome));
-    filtered.remove(4);
-    Expect.equals(false, filtered.any(testSome));
-
-    // Test Set.intersection.
-    Set intersection = set.intersection(filtered);
-    Expect.equals(true, set.contains(0));
-    Expect.equals(true, set.contains(2));
-    Expect.equals(true, set.contains(6));
-    Expect.equals(true, set.contains(8));
-    Expect.equals(false, intersection.contains(1));
-    Expect.equals(false, intersection.contains(3));
-    Expect.equals(false, intersection.contains(4));
-    Expect.equals(false, intersection.contains(5));
-    Expect.equals(false, intersection.contains(7));
-    Expect.equals(false, intersection.contains(9));
-    Expect.equals(false, intersection.contains(10));
-    Expect.equals(4, intersection.length);
-
-    Expect.equals(true, set.containsAll(intersection));
-    Expect.equals(true, filtered.containsAll(intersection));
-    Expect.equals(true, intersection.isSubsetOf(set));
-    Expect.equals(true, intersection.isSubsetOf(filtered));
-
-    // Test Set.addAll.
-    List list = new List.fixedLength(10);
-    for (int i = 0; i < 10; i++) {
-      list[i] = i + 10;
-    }
-    set.addAll(list);
-    Expect.equals(20, set.length);
-    for (int i = 0; i < 20; i++) {
-      Expect.equals(true, set.contains(i));
-    }
-
-    // Test Set.removeAll
-    set.removeAll(list);
-    Expect.equals(10, set.length);
-    for (int i = 0; i < 10; i++) {
-      Expect.equals(true, set.contains(i));
-    }
-    for (int i = 10; i < 20; i++) {
-      Expect.equals(false, set.contains(i));
-    }
-
-    // Test Set.clear.
-    set.clear();
-    Expect.equals(0, set.length);
-    set.add(11);
-    Expect.equals(1, set.length);
+  for (int i = 0; i < 10; i++) {
+    set.add(i);
   }
+
+  Expect.equals(10, set.length);
+  for (int i = 0; i < 10; i++) {
+    Expect.equals(true, set.contains(i));
+  }
+
+  Expect.equals(10, set.length);
+
+  for (int i = 10; i < 20; i++) {
+    Expect.equals(false, set.contains(i));
+  }
+
+  // Test Set.forEach.
+  int sum = 0;
+  testForEach(int val) {
+    sum += (val + 1);
+  }
+
+  set.forEach(testForEach);
+  Expect.equals(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, sum);
+
+  Expect.equals(true, set.isSubsetOf(set));
+  Expect.equals(true, set.containsAll(set));
+
+  // Test Set.map.
+  testMap(int val) {
+    return val * val;
+  }
+
+  Set mapped = set.map(testMap).toSet();
+  Expect.equals(10, mapped.length);
+
+  Expect.equals(true, mapped.contains(0));
+  Expect.equals(true, mapped.contains(1));
+  Expect.equals(true, mapped.contains(4));
+  Expect.equals(true, mapped.contains(9));
+  Expect.equals(true, mapped.contains(16));
+  Expect.equals(true, mapped.contains(25));
+  Expect.equals(true, mapped.contains(36));
+  Expect.equals(true, mapped.contains(49));
+  Expect.equals(true, mapped.contains(64));
+  Expect.equals(true, mapped.contains(81));
+
+  sum = 0;
+  set.forEach(testForEach);
+  Expect.equals(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1, sum);
+
+  sum = 0;
+
+  mapped.forEach(testForEach);
+  Expect.equals(1 + 2 + 5 + 10 + 17 + 26 + 37 + 50 + 65 + 82, sum);
+
+  // Test Set.filter.
+  testFilter(int val) {
+    return val.isEven;
+  }
+
+  Set filtered = set.where(testFilter).toSet();
+
+  Expect.equals(5, filtered.length);
+
+  Expect.equals(true, filtered.contains(0));
+  Expect.equals(true, filtered.contains(2));
+  Expect.equals(true, filtered.contains(4));
+  Expect.equals(true, filtered.contains(6));
+  Expect.equals(true, filtered.contains(8));
+
+  sum = 0;
+  filtered.forEach(testForEach);
+  Expect.equals(1 + 3 + 5 + 7 + 9, sum);
+
+  Expect.equals(true, set.containsAll(filtered));
+  Expect.equals(true, filtered.isSubsetOf(set));
+
+  // Test Set.every.
+  testEvery(int val) {
+    return (val < 10);
+  }
+
+  Expect.equals(true, set.every(testEvery));
+  Expect.equals(true, filtered.every(testEvery));
+
+  filtered.add(10);
+  Expect.equals(false, filtered.every(testEvery));
+
+  // Test Set.some.
+  testSome(int val) {
+    return (val == 4);
+  }
+
+  Expect.equals(true, set.any(testSome));
+  Expect.equals(true, filtered.any(testSome));
+  filtered.remove(4);
+  Expect.equals(false, filtered.any(testSome));
+
+  // Test Set.intersection.
+  Set intersection = set.intersection(filtered);
+  Expect.equals(true, set.contains(0));
+  Expect.equals(true, set.contains(2));
+  Expect.equals(true, set.contains(6));
+  Expect.equals(true, set.contains(8));
+  Expect.equals(false, intersection.contains(1));
+  Expect.equals(false, intersection.contains(3));
+  Expect.equals(false, intersection.contains(4));
+  Expect.equals(false, intersection.contains(5));
+  Expect.equals(false, intersection.contains(7));
+  Expect.equals(false, intersection.contains(9));
+  Expect.equals(false, intersection.contains(10));
+  Expect.equals(4, intersection.length);
+
+  Expect.equals(true, set.containsAll(intersection));
+  Expect.equals(true, filtered.containsAll(intersection));
+  Expect.equals(true, intersection.isSubsetOf(set));
+  Expect.equals(true, intersection.isSubsetOf(filtered));
+
+  // Test Set.addAll.
+  List list = new List.fixedLength(10);
+  for (int i = 0; i < 10; i++) {
+    list[i] = i + 10;
+  }
+  set.addAll(list);
+  Expect.equals(20, set.length);
+  for (int i = 0; i < 20; i++) {
+    Expect.equals(true, set.contains(i));
+  }
+
+  // Test Set.removeAll
+  set.removeAll(list);
+  Expect.equals(10, set.length);
+  for (int i = 0; i < 10; i++) {
+    Expect.equals(true, set.contains(i));
+  }
+  for (int i = 10; i < 20; i++) {
+    Expect.equals(false, set.contains(i));
+  }
+
+  // Test Set.clear.
+  set.clear();
+  Expect.equals(0, set.length);
+  set.add(11);
+  Expect.equals(1, set.length);
 }
 
 main() {
-  SetTest.testMain();
+  testMain(() => new Set());
+  testMain(() => new HashSet());
 }
diff --git a/tests/corelib/sort_helper.dart b/tests/corelib/sort_helper.dart
index 85d0bee..e378097 100644
--- a/tests/corelib/sort_helper.dart
+++ b/tests/corelib/sort_helper.dart
@@ -23,7 +23,7 @@
   }
 
   void testSortIntLists() {
-    List a = new List.fixedLength(40);
+    List a = new List(40);
 
     for (int i = 0; i < a.length; i++) {
       a[i] = i;
@@ -79,10 +79,10 @@
     a[33] = 1;
     testSort(a);
 
-    var a2 = new List.fixedLength(0);
+    var a2 = new List(0);
     testSort(a2);
 
-    var a3 = new List.fixedLength(1);
+    var a3 = new List(1);
     a3[0] = 1;
     testSort(a3);
 
@@ -120,7 +120,7 @@
   }
 
   void testInsertionSort(int i1, int i2, int i3, int i4) {
-    var a = new List.fixedLength(4);
+    var a = new List(4);
     a[0] = i1;
     a[1] = i2;
     a[2] = i3;
@@ -129,7 +129,7 @@
   }
 
   void testSortDoubleLists() {
-    List a = new List.fixedLength(40);
+    List a = new List(40);
     for (int i = 0; i < a.length; i++) {
       a[i] = 1.0 * i + 0.5;
     }
diff --git a/tests/corelib/stopwatch2_test.dart b/tests/corelib/stopwatch2_test.dart
new file mode 100644
index 0000000..25d1120
--- /dev/null
+++ b/tests/corelib/stopwatch2_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Dart test program for elapsed getters in stopwatch support.
+
+main() {
+  Stopwatch sw = new Stopwatch()..start();
+  while (sw.elapsedMilliseconds < 2) {
+    /* do nothing. */
+  }
+  sw.stop();
+  Expect.equals(sw.elapsedMicroseconds, sw.elapsed.inMicroseconds);
+  Expect.equals(sw.elapsedMilliseconds, sw.elapsed.inMilliseconds);
+}
diff --git a/tests/corelib/stopwatch_test.dart b/tests/corelib/stopwatch_test.dart
index 2b9c1a6..535b495 100644
--- a/tests/corelib/stopwatch_test.dart
+++ b/tests/corelib/stopwatch_test.dart
@@ -11,7 +11,7 @@
     Expect.isFalse(sw.isRunning);
     sw.start();
     Expect.isTrue(sw.isRunning);
-    for (int i = 0; i < 10000; i++) {
+    for (int i = 0; i < 1000000; i++) {
       int.parse(i.toString());
       if (sw.elapsedTicks > 0) {
         break;
diff --git a/tests/corelib/string_base_vm_test.dart b/tests/corelib/string_base_vm_test.dart
index f043f33..1acf12e 100644
--- a/tests/corelib/string_base_vm_test.dart
+++ b/tests/corelib/string_base_vm_test.dart
@@ -26,12 +26,12 @@
 
   static testCreation() {
     String s = "Hello";
-    List<int> a = new List.fixedLength(s.length);
+    List<int> a = new List(s.length);
     List<int> ga  = new List();
     bool exception_caught = false;
     for (int i = 0; i < a.length; i++) {
-      a[i] = s.charCodeAt(i);
-      ga.add(s.charCodeAt(i));
+      a[i] = s.codeUnitAt(i);
+      ga.add(s.codeUnitAt(i));
     }
     try {
       String s4 = new String.fromCharCodes([0.0]);
diff --git a/tests/corelib/string_character_test.dart b/tests/corelib/string_character_test.dart
deleted file mode 100644
index 95d272c..0000000
--- a/tests/corelib/string_character_test.dart
+++ /dev/null
@@ -1,30 +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.
-
-main() {
-  Expect.equals("A", new String.character(65));
-  Expect.equals("B", new String.character(66));
-  var gClef = new String.character(0x1D11E);
-  Expect.equals(2, gClef.length);
-  Expect.equals(0xD834, gClef.charCodeAt(0));
-  Expect.equals(0xDD1E, gClef.charCodeAt(1));
-
-  // Unmatched surrogates.
-  var unmatched = new String.character(0xD800);
-  Expect.equals(1, unmatched.length);
-  Expect.equals(0xD800, unmatched.charCodeAt(0));
-  unmatched = new String.character(0xDC00);
-  Expect.equals(1, unmatched.length);
-  Expect.equals(0xDC00, unmatched.charCodeAt(0));
-
-  Expect.throws(() => new String.character(-1),
-                (e) => e is ArgumentError);
-
-  // Invalid code point.
-  Expect.throws(() => new String.character(0x110000),
-                (e) => e is ArgumentError);
-
-  Expect.throws(() => new String.character(0x110001),
-                (e) => e is ArgumentError);
-}
diff --git a/tests/corelib/string_codeunits_test.dart b/tests/corelib/string_codeunits_test.dart
index 81625c5..ac6eb97 100644
--- a/tests/corelib/string_codeunits_test.dart
+++ b/tests/corelib/string_codeunits_test.dart
@@ -25,17 +25,48 @@
     // .map
     Expect.listEquals(expectedUnits.map((x) => x.toRadixString(16)).toList(),
                       units.map((x) => x.toRadixString(16)).toList());
+
+    if (s == "") {
+      Expect.throws(() => units.first, (e) => e is StateError);
+      Expect.throws(() => units.last, (e) => e is StateError);
+      Expect.throws(() => units[0], (e) => e is RangeError);
+      Expect.throws(() => units[0] = 499, (e) => e is UnsupportedError);
+      Expect.listEquals([], units.getRange(0, 0));
+      Expect.equals(-1, units.indexOf(42));
+      Expect.equals(-1, units.lastIndexOf(499));
+    } else {
+      Expect.equals(s.codeUnitAt(0), units.first);
+      Expect.equals(s.codeUnitAt(s.length - 1), units.last);
+      Expect.equals(s.codeUnitAt(0), units[0]);
+      Expect.throws(() { units[0] = 499; }, (e) => e is UnsupportedError);
+      List<int> sub = units.getRange(1, units.length - 1);
+      Expect.listEquals(s.substring(1, s.length).codeUnits, sub);
+      Expect.equals(-1, units.indexOf(-1));
+      Expect.equals(0, units.indexOf(units[0]));
+      Expect.equals(-1, units.lastIndexOf(-1));
+      Expect.equals(units.length - 1, units.lastIndexOf(units[units.length - 1]));
+    }
+
+    Iterable reversed = units.reversed;
+    int i = units.length - 1;
+    for (int codeUnit in reversed) {
+      Expect.equals(units[i--], codeUnit);
+    }
   }
 
+  test("");
   test("abc");
   test("\x00\u0000\u{000000}");
   test("\u{ffff}\u{10000}\u{10ffff}");
   String string = new String.fromCharCodes(
-      [0xdc00, 0xd800, 61, 0xd800, 0xdc00, 62, 0xdc00, 0xd800]);
+      [0xdc00, 0xd800, 61, 0xd9ab, 0xd9ab, 0xddef, 0xddef, 62, 0xdc00, 0xd800]);
+  test(string);
+  string = "\x00\x7f\xff\u0100\ufeff\uffef\uffff"
+           "\u{10000}\u{12345}\u{1d800}\u{1dc00}\u{1ffef}\u{1ffff}";
   test(string);
 
-  // Setting position in the middle of a surrogate pair is not allowed.
-  var r = new CodeUnits("\u{10000}");
+  // Reading each unit of a surrogate pair works.
+  var r = "\u{10000}".codeUnits;
   var it = r.iterator;
   Expect.isTrue(it.moveNext());
   Expect.equals(0xD800, it.current);
diff --git a/tests/corelib/string_from_list_test.dart b/tests/corelib/string_from_list_test.dart
index 99642a1..23c90f2 100644
--- a/tests/corelib/string_from_list_test.dart
+++ b/tests/corelib/string_from_list_test.dart
@@ -4,7 +4,7 @@
 
 class StringFromListTest {
   static testMain() {
-    Expect.equals("", new String.fromCharCodes(new List.fixedLength(0)));
+    Expect.equals("", new String.fromCharCodes(new List(0)));
     Expect.equals("", new String.fromCharCodes([]));
     Expect.equals("", new String.fromCharCodes(const []));
     Expect.equals("AB", new String.fromCharCodes([65, 66]));
diff --git a/tests/corelib/string_fromcharcode_test.dart b/tests/corelib/string_fromcharcode_test.dart
new file mode 100644
index 0000000..7f0fd20
--- /dev/null
+++ b/tests/corelib/string_fromcharcode_test.dart
@@ -0,0 +1,30 @@
+// 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.
+
+main() {
+  Expect.equals("A", new String.fromCharCode(65));
+  Expect.equals("B", new String.fromCharCode(66));
+  var gClef = new String.fromCharCode(0x1D11E);
+  Expect.equals(2, gClef.length);
+  Expect.equals(0xD834, gClef.codeUnitAt(0));
+  Expect.equals(0xDD1E, gClef.codeUnitAt(1));
+
+  // Unmatched surrogates.
+  var unmatched = new String.fromCharCode(0xD800);
+  Expect.equals(1, unmatched.length);
+  Expect.equals(0xD800, unmatched.codeUnitAt(0));
+  unmatched = new String.fromCharCode(0xDC00);
+  Expect.equals(1, unmatched.length);
+  Expect.equals(0xDC00, unmatched.codeUnitAt(0));
+
+  Expect.throws(() => new String.fromCharCode(-1),
+                (e) => e is ArgumentError);
+
+  // Invalid code point.
+  Expect.throws(() => new String.fromCharCode(0x110000),
+                (e) => e is ArgumentError);
+
+  Expect.throws(() => new String.fromCharCode(0x110001),
+                (e) => e is ArgumentError);
+}
diff --git a/tests/corelib/string_test.dart b/tests/corelib/string_test.dart
index 1518181..2dd329c 100644
--- a/tests/corelib/string_test.dart
+++ b/tests/corelib/string_test.dart
@@ -10,7 +10,7 @@
     testIllegalArgument();
     testConcat();
     testIndex();
-    testCharCodeAt();
+    testCodeUnitAt();
     testEquals();
     testEndsWith();
     testStartsWith();
@@ -19,7 +19,6 @@
     testContains();
     testReplaceAll();
     testCompareTo();
-    testToList();
     testCharCodes();
   }
 
@@ -56,10 +55,10 @@
     }
   }
 
-  static testCharCodeAt() {
+  static testCodeUnitAt() {
     String str = "string";
     for (int i = 0; i < str.length; i++) {
-      Expect.equals(true, str.charCodeAt(i) is int);
+      Expect.equals(true, str.codeUnitAt(i) is int);
     }
   }
 
@@ -271,25 +270,12 @@
     Expect.equals(-1, "".compareTo("string"));
   }
 
-  static testToList() {
-    test(str) {
-      var list = str.splitChars();
-      Expect.equals(str.length, list.length);
-      for (int i = 0; i < str.length; i++) {
-        Expect.equals(str[i], list[i]);
-      }
-    }
-    test("abc");
-    test("");
-    test(" ");
-  }
-
   static testCharCodes() {
     test(str) {
-      var list = str.charCodes;
+      var list = str.codeUnits;
       Expect.equals(str.length, list.length);
       for (int i = 0; i < str.length; i++) {
-        Expect.equals(str.charCodeAt(i), list[i]);
+        Expect.equals(str.codeUnitAt(i), list[i]);
       }
     }
     test("abc");
diff --git a/tests/corelib/strings_test.dart b/tests/corelib/strings_test.dart
index ef17663..16630f2 100644
--- a/tests/corelib/strings_test.dart
+++ b/tests/corelib/strings_test.dart
@@ -13,9 +13,9 @@
   }
   static testCreation() {
     String s = "Hello";
-    List<int> l = new List.fixedLength(s.length);
+    List<int> l = new List(s.length);
     for (int i = 0; i < l.length; i++) {
-      l[i] = s.charCodeAt(i);
+      l[i] = s.codeUnitAt(i);
     }
     String s2 = new String.fromCharCodes(l);
     Expect.equals(s, s2);
diff --git a/tests/html/canvasrenderingcontext2d_test.dart b/tests/html/canvasrenderingcontext2d_test.dart
index 6b88843..495e5e4 100644
--- a/tests/html/canvasrenderingcontext2d_test.dart
+++ b/tests/html/canvasrenderingcontext2d_test.dart
@@ -9,10 +9,10 @@
 
 // Some rounding errors in the browsers.
 checkPixel(List<int> pixel, List<int> expected) {
-  expect(pixel[0], closeTo(expected[0], 1));
-  expect(pixel[1], closeTo(expected[1], 1));
-  expect(pixel[2], closeTo(expected[2], 1));
-  expect(pixel[3], closeTo(expected[3], 1));
+  expect(pixel[0], closeTo(expected[0], 2));
+  expect(pixel[1], closeTo(expected[1], 2));
+  expect(pixel[2], closeTo(expected[2], 2));
+  expect(pixel[3], closeTo(expected[3], 2));
 }
 
 main() {
@@ -37,13 +37,13 @@
   test('setFillColorHsl hue', () {
     context.setFillColorHsl(0, 100, 50);
     context.fillRect(0, 0, canvas.width, canvas.height);
-    expect(readPixel(), [255, 0, 0, 255]);
+    checkPixel(readPixel(), [255, 0, 0, 255]);
   });
 
   test('setFillColorHsl hue 2', () {
     context.setFillColorHsl(240, 100, 50);
     context.fillRect(0, 0, canvas.width, canvas.height);
-    expect(readPixel(), [0, 0, 255, 255]);
+    checkPixel(readPixel(), [0, 0, 255, 255]);
   });
 
   test('setFillColorHsl sat', () {
@@ -83,7 +83,7 @@
   test('fillStyle', () {
     context.fillStyle = "red";
     context.fillRect(0, 0, canvas.width, canvas.height);
-    expect(readPixel(), [255, 0, 0, 255]);
+    checkPixel(readPixel(), [255, 0, 0, 255]);
   });
 
   test('strokeStyle', () {
diff --git a/tests/html/crypto_test.dart b/tests/html/crypto_test.dart
index 0e06723..57a2930 100644
--- a/tests/html/crypto_test.dart
+++ b/tests/html/crypto_test.dart
@@ -4,33 +4,45 @@
 
 library crypto_test;
 import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
 
 main() {
-  useHtmlConfiguration();
+  useHtmlIndividualConfiguration();
 
-  test('exists', () {
-    var crypto = window.crypto;
-    expect(crypto is Crypto, isTrue);
+  group('supported', () {
+    test('supported', () {
+      expect(Crypto.supported, true);
+    });
   });
 
-  test('successful call', () {
-    var crypto = window.crypto;
-    var data = new Uint8Array(100);
-    expect(data.every((e) => e == 0), isTrue);
-    crypto.getRandomValues(data);
-    // In theory this is flaky. However, in practice you will get 100 zeroes
-    // in a row from a cryptographically secure random number generator so
-    // rarely that we don't have to worry about it.
-    expect(data.any((e) => e != 0), isTrue);
-  });
+  group('functional', () {
+    if (Crypto.supported) {
+      // This will actually pass on FF since it has a Crypto API, but it is
+      // incompatible.
+      test('exists', () {
+        var crypto = window.crypto;
+        expect(crypto is Crypto, isTrue);
+      });
 
-  test('type mismatch', () {
-    var crypto = window.crypto;
-    var data = new Float32Array(100);
-    expect(() {
-      crypto.getRandomValues(data);
-    }, throws, reason: 'Only typed array views with integer types allowed');
+      test('successful call', () {
+        var crypto = window.crypto;
+        var data = new Uint8Array(100);
+        expect(data.every((e) => e == 0), isTrue);
+        crypto.getRandomValues(data);
+        // In theory this is flaky. However, in practice you will get 100 zeroes
+        // in a row from a cryptographically secure random number generator so
+        // rarely that we don't have to worry about it.
+        expect(data.any((e) => e != 0), isTrue);
+      });
+
+      test('type mismatch', () {
+        var crypto = window.crypto;
+        var data = new Float32Array(100);
+        expect(() {
+          crypto.getRandomValues(data);
+        }, throws, reason: 'Only typed array views with integer types allowed');
+      });
+    }
   });
 }
diff --git a/tests/html/cssstyledeclaration_test.dart b/tests/html/cssstyledeclaration_test.dart
index 1f86605..13a9730 100644
--- a/tests/html/cssstyledeclaration_test.dart
+++ b/tests/html/cssstyledeclaration_test.dart
@@ -91,4 +91,10 @@
       expect(style.textDecoration, equals('underline'));
     }));
   });
+
+  test('Invalid values', () {
+    var element = new DivElement();
+    // Should not throw an error.
+    element.style.background = 'some_bad_value';
+  });
 }
diff --git a/tests/html/fileapi_test.dart b/tests/html/fileapi_test.dart
index a2d23d5..079197f 100644
--- a/tests/html/fileapi_test.dart
+++ b/tests/html/fileapi_test.dart
@@ -92,6 +92,12 @@
             successCallback: expectAsync1((FileEntry e) {
               expect(e.name, equals('file4'));
               expect(e.isFile, isTrue);
+
+              e.getMetadata(expectAsync1((Metadata metadata) {
+                var changeTime = metadata.modificationTime;
+                expect(new DateTime.now().difference(changeTime).inSeconds,
+                  lessThan(60));
+              }));
             }),
             errorCallback: (e) {
               fail('Got file error: ${e.code}');
diff --git a/tests/html/html.status b/tests/html/html.status
index 1f04561..773dffa 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -13,19 +13,9 @@
 [ $runtime == ie9 || $runtime == ie10 || $runtime == safari || $runtime == ff || $runtime == chrome || $runtime == opera ]
 *layout_test: Skip
 
-[ $runtime == drt || $runtime == dartium ]
-input_element_test/supported_datetime: Fail
-
 [ $runtime == chrome ]
-element_types_test/supported_content: Pass, Fail # Issue 8700
-element_types_test/supported_shadow: Pass, Fail # Issue 8700
 input_element_test/supported_date: Pass, Fail      # Chrome stable does not support this input type.
-input_element_test/supported_datetime: Fail
-input_element_test/supported_datetime-local: Pass, Fail # Issue 8700
-input_element_test/supported_month: Pass, Fail # Issue 8700
-input_element_test/supported_week: Pass, Fail # Issue 8700
 speechrecognition_test/supported: Pass, Fail       # Chrome stable does not support it.
-shadow_dom_test/supported: Pass, Fail # Issue 8700
 speechrecognition_test/types: Pass, Fail
 touchevent_test/supported: Fail
 
@@ -38,7 +28,6 @@
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium) ]
 request_animation_frame_test: Skip   # drt hangs; requestAnimationFrame not implemented
-transferables_test: Pass, Fail # Issue 8026
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium) && $system == windows]
 websql_test: Skip # Issue 4941: stderr contains a backtrace.
@@ -53,15 +42,29 @@
 audiobuffersourcenode_test: Pass, Fail
 
 [$runtime == ie10 ]
-# TODO(efortuna, blois): Triage.
 audiobuffersourcenode_test: Fail
 audiocontext_test: Fail
-crypto_test: Fail
+dromaeo_smoke_test: Skip #TODO(efortuna): investigating.
+element_test/click: Fail                # IE does not support firing this event.
+history_test/history: Pass, Fail # issue 8183
+inner_frame_test: Skip
+isolates_test: Skip
+measurement_test: Fail, Pass
+messageevent_test: Fail
+microtask_test: Fail, Pass # Appears to be flaky
+native_gc_test: Fail, Pass # BUG(7774): Untriaged.
+serialized_script_value_test: Fail
+storage_test: Fail, Pass
+websocket_test/websocket: Fail # TODO(efortuna): Issue 7875.
+window_open_test: Skip
+xhr_cross_origin_test: Fail # TODO(efortuna): Issue 7875.
+
+# IE10 Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+crypto_test/supported: Fail
 css_test/supported_CssMatrix: Fail
 css_test/supported_DomPoint: Fail
 document_test/supports_cssCanvasContext: Fail
-dromaeo_smoke_test: Skip #TODO(efortuna): investigating.
-element_test/click: Fail                # IE does not support firing this event.
 element_types_test/supported_content: Fail
 element_types_test/supported_details: Fail
 element_types_test/supported_keygen: Fail
@@ -70,50 +73,59 @@
 element_types_test/supported_shadow: Fail
 fileapi_test/supported: Fail
 history_test/supported_HashChangeEvent: Fail
-inner_frame_test: Skip
+indexeddb_5_test/supportsDatabaseNames: Fail
 input_element_test/supported_date: Fail
-input_element_test/supported_datetime: Fail
 input_element_test/supported_datetime-local: Fail
 input_element_test/supported_month: Fail
 input_element_test/supported_time: Fail
 input_element_test/supported_week: Fail
-isolates_test: Skip
-measurement_test: Fail, Pass
-media_stream_test/supported_media: Fail
 media_stream_test/supported_MediaStreamEvent: Fail
 media_stream_test/supported_MediaStreamTrackEvent: Fail
-messageevent_test: Fail
-microtask_test: Fail, Pass # Appears to be flaky
+media_stream_test/supported_media: Fail
 mutationobserver_test/supported: Fail
-native_gc_test: Fail, Pass # BUG(7774): Untriaged.
 notifications_test/supported: Fail
 rtc_test/supported: Fail
-serialized_script_value_test: Fail
 shadow_dom_test/supported: Fail
 speechrecognition_test/supported: Fail
-storage_test: Fail, Pass
 svgelement_test/supported_altGlyph: Fail
 svgelement_test/supported_animate: Fail
-svgelement_test/supported_animateTransform: Fail
 svgelement_test/supported_animateMotion: Fail
+svgelement_test/supported_animateTransform: Fail
 svgelement_test/supported_foreignObject: Fail
 svgelement_test/supported_set: Fail
 touchevent_test/supported: Fail
 webgl_1_test/supported: Fail
 websql_test/supported: Fail
-websocket_test/websocket: Fail # TODO(efortuna): Issue 7875.
-window_open_test: Skip
-xhr_cross_origin_test: Fail # TODO(efortuna): Issue 7875.
 xhr_test/supported_HttpRequestProgressEvent: Fail
 xsltprocessor_test/supported: Fail
-history_test/history: Pass, Fail # issue 8183
-canvasrenderingcontext2d_test: Fail # issue 8678
 
 [ $runtime == ie9 ]
-crypto_test: Fail
-document_test/supports_cssCanvasContext: Fail
+audiobuffersourcenode_test: Fail
+audiocontext_test: Fail
+blob_constructor_test: Fail
+dom_constructors_test: Fail
 dromaeo_smoke_test: Skip #TODO(efortuna): investigating.
 element_test/click: Fail                # IE does not support firing this event.
+element_test/matches: Fail # IE9 does not support matches
+form_element_test: Fail # Issue 4793.
+inner_frame_test: Skip # Issue 5727 (timeout)
+isolates_test: Skip         # BUG(4016)
+localstorage_test: Fail
+messageevent_test: Fail
+microtask_test: Pass, Fail # http://dartbug.com/8300
+postmessage_structured_test: Skip   # BUG(5685): times out.
+serialized_script_value_test: Fail
+url_test: Fail              # IE9 does not support createObjectURL (it is supported in IE10)
+window_open_test: Skip      # BUG(4016)
+xhr_cross_origin_test: Fail # Issue 6016.
+
+# IE9 Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+cache_test/supported: Fail
+crypto_test/supported: Fail
+css_test/supported_CssMatrix: Fail
+css_test/supported_DomPoint: Fail
+document_test/supports_cssCanvasContext: Fail
 element_types_test/supported_content: Fail
 element_types_test/supported_datalist: Fail
 element_types_test/supported_details: Fail
@@ -123,35 +135,14 @@
 element_types_test/supported_progress: Fail
 element_types_test/supported_shadow: Fail
 element_types_test/supported_track: Fail
-form_data_test/supported: Fail
-form_element_test: Fail # Issue 4793.
-inner_frame_test: Skip # Issue 5727 (timeout)
-transition_event_test/supported: Fail
-typed_arrays_1_test/supported: Fail
-localstorage_test: Fail
-webgl_1_test/supported: Fail
-websql_test/supported: Fail
-
-microtask_test: Pass, Fail # http://dartbug.com/8300
-
-#
-# Investigate and triage the following into bug reports.
-#
-audiobuffersourcenode_test: Fail
-audiocontext_test: Fail
-blob_constructor_test: Fail
-cache_test/supported: Fail
-css_test/supported_CssMatrix: Fail
-css_test/supported_DomPoint: Fail
-dom_constructors_test: Fail
-element_test/matches: Fail # IE9 does not support matches
 fileapi_test/supported: Fail
+form_data_test/supported: Fail
 history_test/supported_HashChangeEvent: Fail
 history_test/supported_state: Fail
 indexeddb_1_test/supported: Fail
+indexeddb_5_test/supportsDatabaseNames: Fail
 input_element_test/supported_date: Fail
 input_element_test/supported_datetime-local: Fail
-input_element_test/supported_datetime: Fail
 input_element_test/supported_email: Fail
 input_element_test/supported_month: Fail
 input_element_test/supported_number: Fail
@@ -161,22 +152,19 @@
 input_element_test/supported_time: Fail
 input_element_test/supported_url: Fail
 input_element_test/supported_week: Fail
-media_stream_test/supported_media: Fail
 media_stream_test/supported_MediaStreamEvent: Fail
 media_stream_test/supported_MediaStreamTrackEvent: Fail
-messageevent_test: Fail
+media_stream_test/supported_media: Fail
 mutationobserver_test/supported: Fail
 notifications_test/supported: Fail
-postmessage_structured_test: Skip   # BUG(5685): times out.
 rtc_test/supported: Fail
-serialized_script_value_test: Fail
 shadow_dom_test/supported: Fail
 speechrecognition_test/supported: Fail
 svg_test/supported_externalResourcesRequired: Fail
 svgelement_test/supported_altGlyph: Fail
 svgelement_test/supported_animate: Fail
-svgelement_test/supported_animateTransform: Fail
 svgelement_test/supported_animateMotion: Fail
+svgelement_test/supported_animateTransform: Fail
 svgelement_test/supported_feBlend: Fail
 svgelement_test/supported_feColorMatrix: Fail
 svgelement_test/supported_feComponentTransfer: Fail
@@ -203,94 +191,106 @@
 svgelement_test/supported_foreignObject: Fail
 svgelement_test/supported_set: Fail
 touchevent_test/supported: Fail
-url_test: Fail              # IE9 does not support createObjectURL (it is supported in IE10)
+transition_event_test/supported: Fail
+typed_arrays_1_test/supported: Fail
+webgl_1_test/supported: Fail
 websocket_test/supported: Fail
-window_open_test: Skip      # BUG(4016)
-isolates_test: Skip         # BUG(4016)
+websql_test/supported: Fail
 xhr_test/supported_HttpRequestProgressEvent: Fail
 xhr_test/supported_onLoadEnd: Fail
 xhr_test/supported_onProgress: Fail
-xhr_cross_origin_test: Fail # Issue 6016.
 xsltprocessor_test/supported: Fail
 
 [ $runtime == safari ]
-element_types_test/supported_content: Fail
-element_types_test/supported_datalist: Fail
-element_types_test/supported_shadow: Fail
+audiocontext_test: Crash, Fail # Issue: 7414
+datalistelement_test: Fail # Issue: 7414
+element_test/elements: Crash, Fail # Issue: 7414
 element_types_test/supported_track: Pass, Fail
-fileapi_test/supported: Fail
-indexeddb_1_test/supported: Fail
-input_element_test/supported_date: Fail
-input_element_test/supported_datetime-local: Fail
-input_element_test/supported_datetime: Fail
 input_element_test/supported_month: Fail, Crash
 input_element_test/supported_time: Fail, Crash
 input_element_test/supported_week: Fail, Crash
-media_stream_test/supported_media: Fail
+webgl_1_test: Pass, Fail # Issue 8219
+wheelevent_test: Fail # Issue: 7414
+
+# Safari Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+element_types_test/supported_content: Fail
+element_types_test/supported_datalist: Fail
+element_types_test/supported_shadow: Fail
+fileapi_test/supported: Fail
+indexeddb_1_test/supported: Fail
+indexeddb_5_test/supportsDatabaseNames: Fail
+input_element_test/supported_date: Fail
+input_element_test/supported_datetime-local: Fail
 media_stream_test/supported_MediaStreamEvent: Fail
 media_stream_test/supported_MediaStreamTrackEvent: Fail
-notifications_test/supported: Fail # Issue: 7414
+media_stream_test/supported_media: Fail
+notifications_test/supported: Fail
 performance_api_test/supported: Fail
 rtc_test/supported: Fail
 shadow_dom_test/supported: Fail
 speechrecognition_test/supported: Fail
 touchevent_test/supported: Fail
-webgl_1_test: Pass, Fail # Issue 8219
-
-audiocontext_test: Crash, Fail # Issue: 7414
-datalistelement_test: Fail # Issue: 7414
-element_test/elements: Crash, Fail # Issue: 7414
-wheelevent_test: Fail # Issue: 7414
 
 [ $runtime == opera ]
-crypto_test: Fail
-document_test/supports_cssCanvasContext: Fail
-document_test/document: Fail # Issue: 7413
-form_data_test: Fail # Issue: 7413
-keyboard_event_test: Fail # Issue: 7413
-element_test/eventListening: Fail # Issue: 7413
-element_test/children: Fail # Issue: 7413
 audiobuffersourcenode_test: Fail
-canvas_test: Pass,Fail
 audiocontext_test: Fail
 blob_constructor_test: Fail
-canvas_using_html_test: Fail
 canvas_test: Fail
-css_test/supported_CssMatrix: Fail
-css_test/supported_DomPoint: Fail
+canvas_test: Pass,Fail
+canvas_using_html_test: Fail
 cssstyledeclaration_test: Fail
+document_test/document: Fail # Issue: 7413
 element_add_test: Fail
 element_constructor_1_test: Fail
+element_test/children: Fail # Issue: 7413
 element_test/constructors: Fail
 element_test/elements: Fail
 element_test/eventListening: Crash
+element_test/eventListening: Fail # Issue: 7413
 element_test/queryAll: Fail
 element_webkit_test: Fail
+fileapi_test: Skip # Timeout.
+form_data_test: Fail # Issue: 7413
 htmlelement_test: Fail
+inner_frame_test: Skip # Timeout.
+isolates_test: Skip # Timeout.
+js_interop_3_test: Skip # Timeout.
+js_interop_4_test: Skip # Timeout.
+keyboard_event_test: Fail # Issue: 7413
+serialized_script_value_test: Fail
+typed_arrays_arraybuffer_test: Fail
+url_test: Fail
+
+# Opera Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+crypto_test/supported: Fail
+css_test/supported_CssMatrix: Fail
+css_test/supported_DomPoint: Fail
+document_test/supports_cssCanvasContext: Fail
 indexeddb_1_test/supported: Fail
+indexeddb_5_test/supportsDatabaseNames: Fail
 mutationobserver_test/supported: Fail
 notifications_test/supported: Fail
 performance_api_test/supported: Fail
-serialized_script_value_test: Fail
 speechrecognition_test/supported: Fail
 svg_test/supported_externalResourcesRequired: Fail
 svg_test/supported_langSpace: Fail
-typed_arrays_arraybuffer_test: Fail
-url_test: Fail
-fileapi_test: Skip # Timeout.
-inner_frame_test: Skip # Timeout.
-js_interop_3_test: Skip # Timeout.
-js_interop_4_test: Skip # Timeout.
-isolates_test: Skip # Timeout.
 websql_test/supported: Fail
 
 [ $runtime == ff ]
 audiobuffersourcenode_test: Fail # FF only has Audio element.
 audiocontext_test: Fail      # FF only has Audio element
-crypto_test: Fail
+dart_object_local_storage_test: Skip  # sessionStorage NS_ERROR_DOM_NOT_SUPPORTED_ERR
+dromaeo_smoke_test: Pass, Fail # Issue: 8257
+inner_frame_test: Skip
+webgl_1_test: Pass, Fail   # Issue 8219
+
+# FireFox Feature support statuses-
+# All changes should be accompanied by platform support annotation changes.
+crypto_test/supported: Fail
 css_test/supported_CssMatrix: Fail
 css_test/supported_DomPoint: Fail
-dart_object_local_storage_test: Skip  # sessionStorage NS_ERROR_DOM_NOT_SUPPORTED_ERR
 document_test/supports_cssCanvasContext: Fail
 element_types_test/supported_content: Fail
 element_types_test/supported_details: Fail
@@ -300,16 +300,14 @@
 element_types_test/supported_shadow: Fail
 element_types_test/supported_track: Fail
 fileapi_test/supported: Fail
-# setup code fails. prepare. (DOM callback has errors) Caught [object Event]
-inner_frame_test: Skip
+indexeddb_5_test/supportsDatabaseNames: Fail
 input_element_test/supported_date: Fail
-input_element_test/supported_datetime: Fail
 input_element_test/supported_datetime-local: Fail
 input_element_test/supported_month: Fail
-input_element_test/supported_time: Fail
-input_element_test/supported_week: Fail
 input_element_test/supported_number: Fail
 input_element_test/supported_range: Fail
+input_element_test/supported_time: Fail
+input_element_test/supported_week: Fail
 media_stream_test/supported_MediaStreamEvent: Fail
 media_stream_test/supported_MediaStreamTrackEvent: Fail
 notifications_test/supported: Fail
@@ -319,11 +317,8 @@
 svg_test/supported_externalResourcesRequired: Fail
 svg_test/supported_langSpace: Fail
 touchevent_test/supported: Fail
-transferables_test: Fail   # Issue 3392.
-webgl_1_test: Pass, Fail   # Issue 8219
 websql_test/supported: Fail
 xhr_test/supported_HttpRequestProgressEvent: Fail
-dromaeo_smoke_test: Pass, Fail # Issue: 8257
 
 [ $runtime == ie9 && ($system == linux || $system == macos) ]
 *: Skip
@@ -336,9 +331,6 @@
 [ $runtime == vm ]
 *: Skip
 
-[ $compiler == dart2js ]
-transferables_test: Skip # until isInstance works in dart2js
-
 [ $compiler == dart2js && ($runtime == drt || $runtime == ff) ]
 request_animation_frame_test: Skip # Async test hangs.
 
@@ -354,3 +346,13 @@
 
 [ $compiler == dart2js && $runtime == ff ]
 inner_frame_test: Skip # Timeout
+
+[ $compiler == dart2js && $runtime == drt && $unchecked ]
+indexeddb_5_test/functional: Fail, Pass # http://dartbug.com/8851
+
+[ $compiler == dart2js && $csp && ($runtime == drt || $runtime == safari || $runtime == ff || $runtime == chrome) ]
+js_interop_1_test: Skip            # Test cannot run under CSP restrictions (times out).
+js_interop_2_test: Fail, OK        # Test cannot run under CSP restrictions.
+js_interop_3_test: Skip            # Test cannot run under CSP restrictions (times out).
+postmessage_structured_test: Skip  # Test cannot run under CSP restrictions (times out).
+shadow_dom_layout_test: Fail, OK   # Test cannot run under CSP restrictions.
diff --git a/tests/html/indexeddb_5_test.dart b/tests/html/indexeddb_5_test.dart
new file mode 100644
index 0000000..6b58ed0
--- /dev/null
+++ b/tests/html/indexeddb_5_test.dart
@@ -0,0 +1,192 @@
+library IndexedDB1Test;
+import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
+import 'dart:async';
+import 'dart:html' as html;
+import 'dart:indexed_db' as idb;
+import 'utils.dart';
+
+main() {
+  useHtmlIndividualConfiguration();
+
+  group('supportsDatabaseNames', () {
+    test('supported', () {
+      expect(html.window.indexedDB.supportsDatabaseNames, isTrue);
+    });
+  });
+
+  if (!idb.IdbFactory.supported) {
+    return;
+  }
+
+  group('functional', () {
+    var dbName = 'test_db';
+    var storeName = 'test_store';
+    var indexName = 'name_index';
+    var db;
+
+    futureTest('init', () {
+      return html.window.indexedDB.deleteDatabase(dbName).then((_) {
+        return html.window.indexedDB.open(dbName, version: 1,
+          onUpgradeNeeded: (e) {
+            var db = e.target.result;
+            var objectStore = db.createObjectStore(storeName,
+                autoIncrement: true);
+            var index = objectStore.createIndex(indexName, 'name_index',
+                unique: false);
+          });
+      }).then((database) {
+        db = database;
+      });
+    });
+
+    if (html.window.indexedDB.supportsDatabaseNames) {
+      futureTest('getDatabaseNames', () {
+        return html.window.indexedDB.getDatabaseNames().then((names) {
+          expect(names.contains(dbName), isTrue);
+        });
+      });
+    }
+
+    var value = {'name_index': 'one', 'value': 'add_value'};
+    futureTest('add/delete', () {
+      var transaction = db.transaction([storeName], 'readwrite');
+      var key;
+      return transaction.objectStore(storeName).add(value).then((addedKey) {
+        key = addedKey;
+      }).then((_) {
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readonly');
+        return transaction.objectStore(storeName).getObject(key);
+      }).then((readValue) {
+        expect(readValue['value'], value['value']);
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readwrite');
+        return transaction.objectStore(storeName).delete(key);
+      }).then((_) {
+        return transaction.completed;
+      }).then((_) {
+        var transaction = db.transaction([storeName], 'readonly');
+        return transaction.objectStore(storeName).count();
+      }).then((count) {
+        expect(count, 0);
+      });
+    });
+
+    futureTest('clear/count', () {
+      var transaction = db.transaction([storeName], 'readwrite');
+      transaction.objectStore(storeName).add(value);
+
+      return transaction.completed.then((_) {
+        transaction = db.transaction([storeName], 'readonly');
+        return transaction.objectStore(storeName).count();
+      }).then((count) {
+        expect(count, 1);
+      }).then((_) {
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readwrite');
+        transaction.objectStore(storeName).clear();
+        return transaction.completed;
+      }).then((_) {
+        var transaction = db.transaction([storeName], 'readonly');
+        return transaction.objectStore(storeName).count();
+      }).then((count) {
+        expect(count, 0);
+      });
+    });
+
+    futureTest('index', () {
+      var transaction = db.transaction([storeName], 'readwrite');
+      transaction.objectStore(storeName).add(value);
+      transaction.objectStore(storeName).add(value);
+      transaction.objectStore(storeName).add(value);
+      transaction.objectStore(storeName).add(value);
+
+      return transaction.completed.then((_) {
+        transaction = db.transaction([storeName], 'readonly');
+        var index = transaction.objectStore(storeName).index(indexName);
+        return index.count();
+      }).then((count) {
+        expect(count, 4);
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readonly');
+        var index = transaction.objectStore(storeName).index(indexName);
+        return index.openCursor(autoAdvance: true).length;
+      }).then((cursorsLength) {
+        expect(cursorsLength, 4);
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readonly');
+        var index = transaction.objectStore(storeName).index(indexName);
+        return index.openKeyCursor(autoAdvance: true).length;
+      }).then((cursorsLength) {
+        expect(cursorsLength, 4);
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readonly');
+        var index = transaction.objectStore(storeName).index(indexName);
+        return index.get('one');
+      }).then((readValue) {
+        expect(readValue['value'], value['value']);
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readwrite');
+        transaction.objectStore(storeName).clear();
+        return transaction.completed;
+      });
+    });
+
+    var deleteValue = {'name_index': 'two', 'value': 'delete_value'};
+    var updateValue = {'name_index': 'three', 'value': 'update_value'};
+    var updatedValue = {'name_index': 'three', 'value': 'updated_value'};
+    futureTest('cursor', () {
+      var transaction = db.transaction([storeName], 'readwrite');
+      transaction.objectStore(storeName).add(value);
+      transaction.objectStore(storeName).add(deleteValue);
+      transaction.objectStore(storeName).add(updateValue);
+
+      return transaction.completed.then((_) {
+        transaction = db.transaction([storeName], 'readwrite');
+        var index = transaction.objectStore(storeName).index(indexName);
+        var cursors = index.openCursor().asBroadcastStream();
+
+        cursors.listen((cursor) {
+          var value = cursor.value;
+          if (value['value'] == 'delete_value') {
+            cursor.delete().then((_) {
+              cursor.next();
+            });
+          } else if (value['value'] == 'update_value') {
+            cursor.update(updatedValue).then((_) {
+              cursor.next();
+            });
+          } else {
+            cursor.next();
+          }
+        });
+        return cursors.last;
+
+      }).then((_) {
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readonly');
+        var index = transaction.objectStore(storeName).index(indexName);
+        return index.get('three');
+      }).then((readValue) {
+        expect(readValue['value'], 'updated_value');
+        return transaction.completed;
+      }).then((_) {
+        transaction = db.transaction([storeName], 'readonly');
+        var index = transaction.objectStore(storeName).index(indexName);
+        return index.get('two');
+      }).then((readValue) {
+        expect(readValue, isNull);
+        return transaction.completed;
+      });
+    });
+  });
+}
diff --git a/tests/html/input_element_test.dart b/tests/html/input_element_test.dart
index 8f63658..fe90511 100644
--- a/tests/html/input_element_test.dart
+++ b/tests/html/input_element_test.dart
@@ -39,12 +39,6 @@
     });
   });
 
-  group('supported_datetime', () {
-    test('supported', () {
-      expect(DateTimeInputElement.supported, true);
-    });
-  });
-
   group('supported_date', () {
     test('supported', () {
       expect(DateInputElement.supported, true);
@@ -117,11 +111,6 @@
       check(new PasswordInputElement(), 'password');
     });
 
-    test('datetime', () {
-      check(new DateTimeInputElement(), 'datetime',
-          DateTimeInputElement.supported);
-    });
-
     test('date', () {
       check(new DateInputElement(), 'date', DateInputElement.supported);
     });
@@ -136,6 +125,15 @@
 
     test('time', () {
       check(new TimeInputElement(), 'time', TimeInputElement.supported);
+      if (TimeInputElement.supported) {
+        var element = new TimeInputElement();
+        var now = new DateTime.now();
+        element.valueAsDate = now;
+        expect(element.valueAsDate is DateTime, isTrue);
+
+        // Bug 8813, setting it is just going to the epoch.
+        //expect(element.valueAsDate, now);
+      }
     });
 
     test('datetime-local', () {
diff --git a/tests/html/native_gc_test.dart b/tests/html/native_gc_test.dart
index 45a89e9..8ed06bb 100644
--- a/tests/html/native_gc_test.dart
+++ b/tests/html/native_gc_test.dart
@@ -16,7 +16,7 @@
       for (int i = 0; i < M; ++i) {
         // This memory should be freed when the listener below is
         // collected.
-        List l = new List.fixedLength(N);
+        List l = new List(N);
 
         // Record the iteration number.
         l[N - 1] = i;
@@ -53,7 +53,7 @@
 }
 
 void triggerMajorGC() {
-  List list = new List.fixedLength(1000000);
+  List list = new List(1000000);
   Element div = new DivElement();
   div.onClick.listen((e) => print(list[0]));
 }
diff --git a/tests/html/table_test.dart b/tests/html/table_test.dart
index fda9fcc..5c1144f 100644
--- a/tests/html/table_test.dart
+++ b/tests/html/table_test.dart
@@ -13,31 +13,49 @@
   test('createTBody', () {
     var table = new TableElement();
     var head = table.createTHead();
-    var headerRow =  head.insertRow(-1);
-    var headerCell = headerRow.insertCell(-1);
+    expect(table.tHead, head);
+
+    var headerRow =  head.addRow();
+    var headerCell = headerRow.addCell();
     headerCell.text = 'Header Cell';
 
-    var body = table.createTBody();
-    var bodyRow =  body.insertRow(-1);
-    var bodyCell = bodyRow.insertCell(-1);
-    bodyCell.text = 'Body Cell';
+    var caption = table.createCaption();
+    expect(table.caption, caption);
 
+    var body = table.createTBody();
     expect(table.tBodies.length, 1);
     expect(table.tBodies[0], body);
 
+    var bodyRow =  body.addRow();
+    expect(body.rows.length, 1);
+    expect(body.rows[0], bodyRow);
+
+    var bodyCell = bodyRow.addCell();
+    bodyCell.text = 'Body Cell';
+    expect(bodyRow.cells.length, 1);
+    expect(bodyRow.cells[0], bodyCell);
+
     var foot = table.createTFoot();
-    var footerRow =  foot.insertRow(-1);
-    var footerCell = footerRow.insertCell(-1);
+    expect(table.tFoot, foot);
+
+    var footerRow =  foot.addRow();
+    expect(foot.rows.length, 1);
+    expect(foot.rows[0], footerRow);
+
+    var footerCell = footerRow.addCell();
     footerCell.text = 'Footer Cell';
+    expect(footerRow.cells.length, 1);
+    expect(footerRow.cells[0], footerCell);
 
     var body2 = table.createTBody();
-    var bodyRow2 =  body2.insertRow(-1);
-    var bodyCell2 = bodyRow2.insertCell(-1);
+    var bodyRow2 =  body2.addRow();
+    var bodyCell2 = bodyRow2.addCell();
     bodyCell2.text = 'Body Cell2';
 
+    expect(body2.rows.length, 1);
+
     expect(table.tBodies.length, 2);
     expect(table.tBodies[1], body2);
-
   });
 }
 
diff --git a/tests/html/transferables_test.dart b/tests/html/transferables_test.dart
index 3db9c42..a487ada 100644
--- a/tests/html/transferables_test.dart
+++ b/tests/html/transferables_test.dart
@@ -14,10 +14,21 @@
       predicate((x) => x is ArrayBuffer, 'is an ArrayBuffer');
 
   test('TransferableTest', () {
-    window.onMessage.listen(expectAsync1((messageEvent) {
-      expect(messageEvent.data, isArrayBuffer);
-    }));
+    if (!ArrayBuffer.supported) {
+      return;
+    }
+
     final buffer = (new Float32Array(3)).buffer;
-    window.postMessage(buffer, '*', [buffer]);
+    window.postMessage({
+        'id': 'transferable data',
+        'buffer': buffer
+      }, '*', [buffer]);
+
+    return window.onMessage.firstMatching(
+      (e) {
+        return e.data is Map && e.data['id'] == 'transferable data';
+      }).then((messageEvent) {
+        expect(messageEvent.data['buffer'], isArrayBuffer);
+      });
   });
 }
diff --git a/tests/html/url_test.dart b/tests/html/url_test.dart
index f332b30..fec1d44 100644
--- a/tests/html/url_test.dart
+++ b/tests/html/url_test.dart
@@ -26,7 +26,7 @@
     var arrayBuffer = new ArrayBuffer(byteString.length);
     var dataArray = new Uint8Array.fromBuffer(arrayBuffer);
     for (var i = 0; i < byteString.length; i++) {
-      dataArray[i] = byteString.charCodeAt(i);
+      dataArray[i] = byteString.codeUnitAt(i);
     }
 
     var blob = new Blob([arrayBuffer], 'image/png');
diff --git a/tests/html/websql_test.dart b/tests/html/websql_test.dart
index f98c6bb..601ab1a 100644
--- a/tests/html/websql_test.dart
+++ b/tests/html/websql_test.dart
@@ -1,9 +1,10 @@
 library WebDBTest;
-import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:async';
 import 'dart:html';
 import 'dart:web_sql';
+import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
+import 'utils.dart';
 
 void fail(message) {
   guardAsync(() {
@@ -11,81 +12,84 @@
     });
 }
 
-Future<SqlTransaction> createTransaction(SqlDatabase db) {
+Future<SqlTransaction> transaction(SqlDatabase db) {
   final completer = new Completer<SqlTransaction>();
 
   db.transaction((SqlTransaction transaction) {
     completer.complete(transaction);
+  }, (SqlError error) {
+    completer.completeError(error);
   });
 
   return completer.future;
 }
 
-createTable(tableName, columnName) => (SqlTransaction transaction) {
-  final completer = new Completer<SqlTransaction>();
+Future<SqlResultSet> createTable(SqlTransaction transaction, String tableName,
+    String columnName) {
+  final completer = new Completer<SqlResultSet>();
 
   final sql = 'CREATE TABLE $tableName ($columnName)';
   transaction.executeSql(sql, [],
     (SqlTransaction tx, SqlResultSet rs) {
-      completer.complete(transaction);
+      completer.complete(rs);
     },
     (SqlTransaction tx, SqlError error) {
-      fail(error.message);
+      completer.completeError(error);
     });
 
   return completer.future;
-};
+}
 
-insert(tableName, columnName, value) => (SqlTransaction transaction) {
-  final completer = new Completer<SqlTransaction>();
+Future<SqlResultSet> insert(SqlTransaction transaction, String tableName,
+    String columnName, value) {
+  final completer = new Completer<SqlResultSet>();
 
   final sql = 'INSERT INTO $tableName ($columnName) VALUES (?)';
   transaction.executeSql(sql, [value],
     (SqlTransaction tx, SqlResultSet rs) {
-      completer.complete(tx);
+      completer.complete(rs);
     },
     (SqlTransaction tx, SqlError error) {
-      fail(error.message);
+      completer.completeError(error);
     });
 
   return completer.future;
-};
+}
 
-queryTable(tableName, callback) => (SqlTransaction transaction) {
-  final completer = new Completer<SqlTransaction>();
+Future<SqlResultSet> queryTable(SqlTransaction transaction, String tableName) {
+  final completer = new Completer<SqlResultSet>();
 
   final sql = 'SELECT * FROM $tableName';
   transaction.executeSql(sql, [],
     (SqlTransaction tx, SqlResultSet rs) {
-      callback(rs);
-      completer.complete(tx);
+      completer.complete(rs);
     },
     (SqlTransaction tx, SqlError error) {
-      fail(error.message);
+      completer.completeError(error);
     });
 
   return completer.future;
-};
+}
 
-dropTable(tableName, [bool ignoreFailure = false]) =>
-    (SqlTransaction transaction) {
-  final completer = new Completer<SqlTransaction>();
+Future<SqlResultSet> dropTable(SqlTransaction transaction, String tableName,
+    [bool ignoreFailure = false]) {
+  final completer = new Completer<SqlResultSet>();
 
   final sql = 'DROP TABLE $tableName';
   transaction.executeSql(sql, [],
     (SqlTransaction tx, SqlResultSet rs) {
-      completer.complete(tx);
+      completer.complete(rs);
     },
     (SqlTransaction tx, SqlError error) {
       if (ignoreFailure) {
-        completer.complete(tx);
+        completer.complete(null);
       } else {
-        fail(error.message);
+        completer.completeError(error);
       }
     });
 
   return completer.future;
-};
+}
 
 main() {
   useHtmlIndividualConfiguration();
@@ -104,10 +108,10 @@
       }, expectation);
 
     });
-    test('Web Database', () {
+    futureTest('Web Database', () {
       // Skip if not supported.
       if (!SqlDatabase.supported) {
-        return;
+        return new Future.immediate(null);
       }
 
       final tableName = 'test_table';
@@ -117,22 +121,28 @@
 
       expect(db, isNotNull, reason: 'Unable to open database');
 
-      createTransaction(db)
+      var tx;
+      return transaction(db).then((transaction) {
+        tx = transaction;
+      }).then((_) {
         // Attempt to clear out any tables which may be lurking from previous
         // runs.
-        .then(dropTable(tableName, true))
-        .then(createTable(tableName, columnName))
-        .then(insert(tableName, columnName, 'Some text data'))
-        .then(queryTable(tableName, (resultSet) {
-          guardAsync(() {
-            expect(resultSet.rows.length, 1);
-            var row = resultSet.rows.item(0);
-            expect(row.containsKey(columnName), isTrue);
-            expect(row[columnName], 'Some text data');
-          });
-        }))
-        .then(dropTable(tableName))
-        .then(expectAsync1((tx) {}));
+        return dropTable(tx, tableName, true);
+      }).then((_) {
+        return createTable(tx, tableName, columnName);
+      }).then((_) {
+        return insert(tx, tableName, columnName, 'Some text data');
+      }).then((_) {
+        return queryTable(tx, tableName);
+      }).then((resultSet) {
+        expect(resultSet.rows.length, 1);
+        var row = resultSet.rows.item(0);
+        expect(row.containsKey(columnName), isTrue);
+        expect(row[columnName], 'Some text data');
+        expect(resultSet.rows[0], row);
+      }).then((_) {
+        return dropTable(tx, tableName);
+      });
     });
   });
 }
diff --git a/tests/isolate/mandel_isolate_test.dart b/tests/isolate/mandel_isolate_test.dart
index 292d6d6..abc4d83 100644
--- a/tests/isolate/mandel_isolate_test.dart
+++ b/tests/isolate/mandel_isolate_test.dart
@@ -27,7 +27,7 @@
 
   MandelbrotState() {
     _result = new List<List<int>>(N);
-    _lineProcessedBy = new List<LineProcessorClient>.fixedLength(N);
+    _lineProcessedBy = new List<LineProcessorClient>(N);
     _sent = 0;
     _missing = N;
     _validated = new Completer<bool>();
@@ -107,7 +107,7 @@
 List<int> processLine(int y) {
   double inverseN = 2.0 / N;
   double Civ = y * inverseN - 1.0;
-  List<int> result = new List<int>.fixedLength(N);
+  List<int> result = new List<int>(N);
   for (int x = 0; x < N; x++) {
     double Crv = x * inverseN - 1.5;
 
diff --git a/tests/isolate/message_test.dart b/tests/isolate/message_test.dart
index a281d81..ee00de5 100644
--- a/tests/isolate/message_test.dart
+++ b/tests/isolate/message_test.dart
@@ -100,7 +100,7 @@
     List local_list1 = ["Hello", "World", "Hello", 0xffffffffff];
     List local_list2 = [null, local_list1, local_list1 ];
     List local_list3 = [local_list2, 2.0, true, false, 0xffffffffff];
-    List sendObject = new List.fixedLength(5);
+    List sendObject = new List(5);
     sendObject[0] = local_list1;
     sendObject[1] = sendObject;
     sendObject[2] = local_list2;
diff --git a/tests/isolate/multiple_timer_test.dart b/tests/isolate/multiple_timer_test.dart
index db2248a..27e429e 100644
--- a/tests/isolate/multiple_timer_test.dart
+++ b/tests/isolate/multiple_timer_test.dart
@@ -57,7 +57,7 @@
       _message++;
     }
 
-    _order = new List<int>.fixedLength(4);
+    _order = new List<int>(4);
     _order[0] = 2;
     _order[1] = 0;
     _order[2] = 3;
diff --git a/tests/isolate/timer_cancel_test.dart b/tests/isolate/timer_cancel_test.dart
index bc4376b..a159abc 100644
--- a/tests/isolate/timer_cancel_test.dart
+++ b/tests/isolate/timer_cancel_test.dart
@@ -35,10 +35,10 @@
     repeatTimer = 0;
     new Timer.repeating(ms * 1500, expectAsync1(repeatHandler));
   });
-  
+
   test("cancel timer with same time", () {
     var t2;
-    var t1 = Timer.run(expectAsync0(() => t2.cancel()));
-    t2 = Timer.run(expectAsync0(t1.cancel, count: 0));
+    var t1 = new Timer(ms * 0, expectAsync0(() => t2.cancel()));
+    t2 = new Timer(ms * 0, expectAsync0(t1.cancel, count: 0));
   });
 }
diff --git a/tests/json/json_test.dart b/tests/json/json_test.dart
index 5ec1c83..1fe74e5 100644
--- a/tests/json/json_test.dart
+++ b/tests/json/json_test.dart
@@ -90,8 +90,8 @@
 
     // Lists.
     expect(json.stringify([]), equals('[]'));
-    expect(json.stringify(new List.fixedLength(0)), equals('[]'));
-    expect(json.stringify(new List.fixedLength(3)), equals('[null,null,null]'));
+    expect(json.stringify(new List(0)), equals('[]'));
+    expect(json.stringify(new List(3)), equals('[null,null,null]'));
     validateRoundTrip([3, -4.5, null, true, 'hi', false]);
     expect(json.stringify([[3], [], [null], ['hi', true]]),
       equals('[[3],[],[null],["hi",true]]'));
diff --git a/tests/language/arithmetic_test.dart b/tests/language/arithmetic_test.dart
index f230b3c..4ee0080 100644
--- a/tests/language/arithmetic_test.dart
+++ b/tests/language/arithmetic_test.dart
@@ -279,6 +279,8 @@
     // Double.
     Expect.equals(3.0, (2.6).round());
     Expect.equals(-3.0, (-2.6).round());
+    Expect.equals(3.0, (2.5).round());
+    Expect.equals(-3.0, (-2.5).round());
     Expect.equals(0.0, (0.0).round());
     Expect.equals(0.0, (0.1).round());
     Expect.equals(false, (0.0).round().isNegative);
diff --git a/tests/language/bailout4_test.dart b/tests/language/bailout4_test.dart
index 0bb3edf..52e9713 100644
--- a/tests/language/bailout4_test.dart
+++ b/tests/language/bailout4_test.dart
@@ -10,7 +10,7 @@
 }
 
 var a = new A();
-var b = new List.fixedLength(4);
+var b = new List(4);
 int count = 0;
 
 main() {
diff --git a/tests/language/char_escape_test.dart b/tests/language/char_escape_test.dart
index a890e4d..23c95ca 100644
--- a/tests/language/char_escape_test.dart
+++ b/tests/language/char_escape_test.dart
@@ -21,14 +21,14 @@
     Expect.equals(1, v0000.length);
     Expect.equals(1, v00000.length);
     Expect.equals(1, v000000.length);
-    Expect.equals(0, x00.charCodeAt(0));
-    Expect.equals(0, u0000.charCodeAt(0));
-    Expect.equals(0, v0.charCodeAt(0));
-    Expect.equals(0, v00.charCodeAt(0));
-    Expect.equals(0, v000.charCodeAt(0));
-    Expect.equals(0, v0000.charCodeAt(0));
-    Expect.equals(0, v00000.charCodeAt(0));
-    Expect.equals(0, v000000.charCodeAt(0));
+    Expect.equals(0, x00.codeUnitAt(0));
+    Expect.equals(0, u0000.codeUnitAt(0));
+    Expect.equals(0, v0.codeUnitAt(0));
+    Expect.equals(0, v00.codeUnitAt(0));
+    Expect.equals(0, v000.codeUnitAt(0));
+    Expect.equals(0, v0000.codeUnitAt(0));
+    Expect.equals(0, v00000.codeUnitAt(0));
+    Expect.equals(0, v000000.codeUnitAt(0));
     Expect.equals("\x00", new String.fromCharCodes([0]));
     Expect.equals("\u0000", new String.fromCharCodes([0]));
     Expect.equals("\u{0}", new String.fromCharCodes([0]));
@@ -54,14 +54,14 @@
     Expect.equals(1, v0001.length);
     Expect.equals(1, v00001.length);
     Expect.equals(1, v000001.length);
-    Expect.equals(1, x01.charCodeAt(0));
-    Expect.equals(1, u0001.charCodeAt(0));
-    Expect.equals(1, v1.charCodeAt(0));
-    Expect.equals(1, v01.charCodeAt(0));
-    Expect.equals(1, v001.charCodeAt(0));
-    Expect.equals(1, v0001.charCodeAt(0));
-    Expect.equals(1, v00001.charCodeAt(0));
-    Expect.equals(1, v000001.charCodeAt(0));
+    Expect.equals(1, x01.codeUnitAt(0));
+    Expect.equals(1, u0001.codeUnitAt(0));
+    Expect.equals(1, v1.codeUnitAt(0));
+    Expect.equals(1, v01.codeUnitAt(0));
+    Expect.equals(1, v001.codeUnitAt(0));
+    Expect.equals(1, v0001.codeUnitAt(0));
+    Expect.equals(1, v00001.codeUnitAt(0));
+    Expect.equals(1, v000001.codeUnitAt(0));
     Expect.equals("\x01", new String.fromCharCodes([1]));
     Expect.equals("\u0001", new String.fromCharCodes([1]));
     Expect.equals("\u{1}", new String.fromCharCodes([1]));
@@ -85,13 +85,13 @@
     Expect.equals(1, v0055.length);
     Expect.equals(1, v00055.length);
     Expect.equals(1, v000055.length);
-    Expect.equals(0x55, x55.charCodeAt(0));
-    Expect.equals(0x55, u0055.charCodeAt(0));
-    Expect.equals(0x55, v55.charCodeAt(0));
-    Expect.equals(0x55, v055.charCodeAt(0));
-    Expect.equals(0x55, v0055.charCodeAt(0));
-    Expect.equals(0x55, v00055.charCodeAt(0));
-    Expect.equals(0x55, v000055.charCodeAt(0));
+    Expect.equals(0x55, x55.codeUnitAt(0));
+    Expect.equals(0x55, u0055.codeUnitAt(0));
+    Expect.equals(0x55, v55.codeUnitAt(0));
+    Expect.equals(0x55, v055.codeUnitAt(0));
+    Expect.equals(0x55, v0055.codeUnitAt(0));
+    Expect.equals(0x55, v00055.codeUnitAt(0));
+    Expect.equals(0x55, v000055.codeUnitAt(0));
     Expect.equals("\x55", new String.fromCharCodes([0x55]));
     Expect.equals("\u0055", new String.fromCharCodes([0x55]));
     Expect.equals("\u{55}", new String.fromCharCodes([0x55]));
@@ -114,13 +114,13 @@
     Expect.equals(1, v007F.length);
     Expect.equals(1, v0007F.length);
     Expect.equals(1, v00007F.length);
-    Expect.equals(0x7F, x7F.charCodeAt(0));
-    Expect.equals(0x7F, u007F.charCodeAt(0));
-    Expect.equals(0x7F, v7F.charCodeAt(0));
-    Expect.equals(0x7F, v07F.charCodeAt(0));
-    Expect.equals(0x7F, v007F.charCodeAt(0));
-    Expect.equals(0x7F, v0007F.charCodeAt(0));
-    Expect.equals(0x7F, v00007F.charCodeAt(0));
+    Expect.equals(0x7F, x7F.codeUnitAt(0));
+    Expect.equals(0x7F, u007F.codeUnitAt(0));
+    Expect.equals(0x7F, v7F.codeUnitAt(0));
+    Expect.equals(0x7F, v07F.codeUnitAt(0));
+    Expect.equals(0x7F, v007F.codeUnitAt(0));
+    Expect.equals(0x7F, v0007F.codeUnitAt(0));
+    Expect.equals(0x7F, v00007F.codeUnitAt(0));
     Expect.equals("\x7F", new String.fromCharCodes([0x7F]));
     Expect.equals("\u007F", new String.fromCharCodes([0x7F]));
     Expect.equals("\u{7F}", new String.fromCharCodes([0x7F]));
@@ -143,13 +143,13 @@
     Expect.equals(1, v0080.length);
     Expect.equals(1, v00080.length);
     Expect.equals(1, v000080.length);
-    Expect.equals(0x80, x80.charCodeAt(0));
-    Expect.equals(0x80, u0080.charCodeAt(0));
-    Expect.equals(0x80, v80.charCodeAt(0));
-    Expect.equals(0x80, v080.charCodeAt(0));
-    Expect.equals(0x80, v0080.charCodeAt(0));
-    Expect.equals(0x80, v00080.charCodeAt(0));
-    Expect.equals(0x80, v000080.charCodeAt(0));
+    Expect.equals(0x80, x80.codeUnitAt(0));
+    Expect.equals(0x80, u0080.codeUnitAt(0));
+    Expect.equals(0x80, v80.codeUnitAt(0));
+    Expect.equals(0x80, v080.codeUnitAt(0));
+    Expect.equals(0x80, v0080.codeUnitAt(0));
+    Expect.equals(0x80, v00080.codeUnitAt(0));
+    Expect.equals(0x80, v000080.codeUnitAt(0));
     Expect.equals("\x80", new String.fromCharCodes([0x80]));
     Expect.equals("\u0080", new String.fromCharCodes([0x80]));
     Expect.equals("\u{80}", new String.fromCharCodes([0x80]));
@@ -172,13 +172,13 @@
     Expect.equals(1, v00AA.length);
     Expect.equals(1, v000AA.length);
     Expect.equals(1, v0000AA.length);
-    Expect.equals(0xAA, xAA.charCodeAt(0));
-    Expect.equals(0xAA, u00AA.charCodeAt(0));
-    Expect.equals(0xAA, vAA.charCodeAt(0));
-    Expect.equals(0xAA, v0AA.charCodeAt(0));
-    Expect.equals(0xAA, v00AA.charCodeAt(0));
-    Expect.equals(0xAA, v000AA.charCodeAt(0));
-    Expect.equals(0xAA, v0000AA.charCodeAt(0));
+    Expect.equals(0xAA, xAA.codeUnitAt(0));
+    Expect.equals(0xAA, u00AA.codeUnitAt(0));
+    Expect.equals(0xAA, vAA.codeUnitAt(0));
+    Expect.equals(0xAA, v0AA.codeUnitAt(0));
+    Expect.equals(0xAA, v00AA.codeUnitAt(0));
+    Expect.equals(0xAA, v000AA.codeUnitAt(0));
+    Expect.equals(0xAA, v0000AA.codeUnitAt(0));
     Expect.equals("\xAA", new String.fromCharCodes([0xAA]));
     Expect.equals("\u00AA", new String.fromCharCodes([0xAA]));
     Expect.equals("\u{AA}", new String.fromCharCodes([0xAA]));
@@ -201,13 +201,13 @@
     Expect.equals(1, v00FE.length);
     Expect.equals(1, v000FE.length);
     Expect.equals(1, v0000FE.length);
-    Expect.equals(0xFE, xFE.charCodeAt(0));
-    Expect.equals(0xFE, u00FE.charCodeAt(0));
-    Expect.equals(0xFE, vFE.charCodeAt(0));
-    Expect.equals(0xFE, v0FE.charCodeAt(0));
-    Expect.equals(0xFE, v00FE.charCodeAt(0));
-    Expect.equals(0xFE, v000FE.charCodeAt(0));
-    Expect.equals(0xFE, v0000FE.charCodeAt(0));
+    Expect.equals(0xFE, xFE.codeUnitAt(0));
+    Expect.equals(0xFE, u00FE.codeUnitAt(0));
+    Expect.equals(0xFE, vFE.codeUnitAt(0));
+    Expect.equals(0xFE, v0FE.codeUnitAt(0));
+    Expect.equals(0xFE, v00FE.codeUnitAt(0));
+    Expect.equals(0xFE, v000FE.codeUnitAt(0));
+    Expect.equals(0xFE, v0000FE.codeUnitAt(0));
     Expect.equals("\xFE", new String.fromCharCodes([0xFE]));
     Expect.equals("\u00FE", new String.fromCharCodes([0xFE]));
     Expect.equals("\u{FE}", new String.fromCharCodes([0xFE]));
@@ -230,13 +230,13 @@
     Expect.equals(1, v00FF.length);
     Expect.equals(1, v000FF.length);
     Expect.equals(1, v0000FF.length);
-    Expect.equals(0xFF, xFF.charCodeAt(0));
-    Expect.equals(0xFF, u00FF.charCodeAt(0));
-    Expect.equals(0xFF, vFF.charCodeAt(0));
-    Expect.equals(0xFF, v0FF.charCodeAt(0));
-    Expect.equals(0xFF, v00FF.charCodeAt(0));
-    Expect.equals(0xFF, v000FF.charCodeAt(0));
-    Expect.equals(0xFF, v0000FF.charCodeAt(0));
+    Expect.equals(0xFF, xFF.codeUnitAt(0));
+    Expect.equals(0xFF, u00FF.codeUnitAt(0));
+    Expect.equals(0xFF, vFF.codeUnitAt(0));
+    Expect.equals(0xFF, v0FF.codeUnitAt(0));
+    Expect.equals(0xFF, v00FF.codeUnitAt(0));
+    Expect.equals(0xFF, v000FF.codeUnitAt(0));
+    Expect.equals(0xFF, v0000FF.codeUnitAt(0));
     Expect.equals("\xFF", new String.fromCharCodes([0xFF]));
     Expect.equals("\u00FF", new String.fromCharCodes([0xFF]));
     Expect.equals("\u{FF}", new String.fromCharCodes([0xFF]));
@@ -253,10 +253,10 @@
     Expect.equals(1, v1000.length);
     Expect.equals(1, v01000.length);
     Expect.equals(1, v001000.length);
-    Expect.equals(0x1000, u1000.charCodeAt(0));
-    Expect.equals(0x1000, v1000.charCodeAt(0));
-    Expect.equals(0x1000, v01000.charCodeAt(0));
-    Expect.equals(0x1000, v001000.charCodeAt(0));
+    Expect.equals(0x1000, u1000.codeUnitAt(0));
+    Expect.equals(0x1000, v1000.codeUnitAt(0));
+    Expect.equals(0x1000, v01000.codeUnitAt(0));
+    Expect.equals(0x1000, v001000.codeUnitAt(0));
     Expect.equals("\u1000", new String.fromCharCodes([0x1000]));
     Expect.equals("\u{1000}", new String.fromCharCodes([0x1000]));
     Expect.equals("\u{01000}", new String.fromCharCodes([0x1000]));
@@ -270,10 +270,10 @@
     Expect.equals(1, v5555.length);
     Expect.equals(1, v05555.length);
     Expect.equals(1, v005555.length);
-    Expect.equals(0x5555, u5555.charCodeAt(0));
-    Expect.equals(0x5555, v5555.charCodeAt(0));
-    Expect.equals(0x5555, v05555.charCodeAt(0));
-    Expect.equals(0x5555, v005555.charCodeAt(0));
+    Expect.equals(0x5555, u5555.codeUnitAt(0));
+    Expect.equals(0x5555, v5555.codeUnitAt(0));
+    Expect.equals(0x5555, v05555.codeUnitAt(0));
+    Expect.equals(0x5555, v005555.codeUnitAt(0));
     Expect.equals("\u5555", new String.fromCharCodes([0x5555]));
     Expect.equals("\u{5555}", new String.fromCharCodes([0x5555]));
     Expect.equals("\u{05555}", new String.fromCharCodes([0x5555]));
@@ -287,10 +287,10 @@
     Expect.equals(1, v7FFF.length);
     Expect.equals(1, v07FFF.length);
     Expect.equals(1, v007FFF.length);
-    Expect.equals(0x7FFF, u7FFF.charCodeAt(0));
-    Expect.equals(0x7FFF, v7FFF.charCodeAt(0));
-    Expect.equals(0x7FFF, v07FFF.charCodeAt(0));
-    Expect.equals(0x7FFF, v007FFF.charCodeAt(0));
+    Expect.equals(0x7FFF, u7FFF.codeUnitAt(0));
+    Expect.equals(0x7FFF, v7FFF.codeUnitAt(0));
+    Expect.equals(0x7FFF, v07FFF.codeUnitAt(0));
+    Expect.equals(0x7FFF, v007FFF.codeUnitAt(0));
     Expect.equals("\u7FFF", new String.fromCharCodes([0x7FFF]));
     Expect.equals("\u{7FFF}", new String.fromCharCodes([0x7FFF]));
     Expect.equals("\u{07FFF}", new String.fromCharCodes([0x7FFF]));
@@ -304,10 +304,10 @@
     Expect.equals(1, v8000.length);
     Expect.equals(1, v08000.length);
     Expect.equals(1, v008000.length);
-    Expect.equals(0x8000, u8000.charCodeAt(0));
-    Expect.equals(0x8000, v8000.charCodeAt(0));
-    Expect.equals(0x8000, v08000.charCodeAt(0));
-    Expect.equals(0x8000, v008000.charCodeAt(0));
+    Expect.equals(0x8000, u8000.codeUnitAt(0));
+    Expect.equals(0x8000, v8000.codeUnitAt(0));
+    Expect.equals(0x8000, v08000.codeUnitAt(0));
+    Expect.equals(0x8000, v008000.codeUnitAt(0));
     Expect.equals("\u8000", new String.fromCharCodes([0x8000]));
     Expect.equals("\u{8000}", new String.fromCharCodes([0x8000]));
     Expect.equals("\u{08000}", new String.fromCharCodes([0x8000]));
@@ -321,10 +321,10 @@
     Expect.equals(1, vAAAA.length);
     Expect.equals(1, v0AAAA.length);
     Expect.equals(1, v00AAAA.length);
-    Expect.equals(0xAAAA, uAAAA.charCodeAt(0));
-    Expect.equals(0xAAAA, vAAAA.charCodeAt(0));
-    Expect.equals(0xAAAA, v0AAAA.charCodeAt(0));
-    Expect.equals(0xAAAA, v00AAAA.charCodeAt(0));
+    Expect.equals(0xAAAA, uAAAA.codeUnitAt(0));
+    Expect.equals(0xAAAA, vAAAA.codeUnitAt(0));
+    Expect.equals(0xAAAA, v0AAAA.codeUnitAt(0));
+    Expect.equals(0xAAAA, v00AAAA.codeUnitAt(0));
     Expect.equals("\uAAAA", new String.fromCharCodes([0xAAAA]));
     Expect.equals("\u{AAAA}", new String.fromCharCodes([0xAAAA]));
     Expect.equals("\u{0AAAA}", new String.fromCharCodes([0xAAAA]));
@@ -338,10 +338,10 @@
     Expect.equals(1, vFFFE.length);
     Expect.equals(1, v0FFFE.length);
     Expect.equals(1, v00FFFE.length);
-    Expect.equals(0xFFFE, uFFFE.charCodeAt(0));
-    Expect.equals(0xFFFE, vFFFE.charCodeAt(0));
-    Expect.equals(0xFFFE, v0FFFE.charCodeAt(0));
-    Expect.equals(0xFFFE, v00FFFE.charCodeAt(0));
+    Expect.equals(0xFFFE, uFFFE.codeUnitAt(0));
+    Expect.equals(0xFFFE, vFFFE.codeUnitAt(0));
+    Expect.equals(0xFFFE, v0FFFE.codeUnitAt(0));
+    Expect.equals(0xFFFE, v00FFFE.codeUnitAt(0));
     Expect.equals("\uFFFE", new String.fromCharCodes([0xFFFE]));
     Expect.equals("\u{FFFE}", new String.fromCharCodes([0xFFFE]));
     Expect.equals("\u{0FFFE}", new String.fromCharCodes([0xFFFE]));
@@ -355,10 +355,10 @@
     Expect.equals(1, vFFFF.length);
     Expect.equals(1, v0FFFF.length);
     Expect.equals(1, v00FFFF.length);
-    Expect.equals(0xFFFF, uFFFF.charCodeAt(0));
-    Expect.equals(0xFFFF, vFFFF.charCodeAt(0));
-    Expect.equals(0xFFFF, v0FFFF.charCodeAt(0));
-    Expect.equals(0xFFFF, v00FFFF.charCodeAt(0));
+    Expect.equals(0xFFFF, uFFFF.codeUnitAt(0));
+    Expect.equals(0xFFFF, vFFFF.codeUnitAt(0));
+    Expect.equals(0xFFFF, v0FFFF.codeUnitAt(0));
+    Expect.equals(0xFFFF, v00FFFF.codeUnitAt(0));
     Expect.equals("\uFFFF", new String.fromCharCodes([0xFFFF]));
     Expect.equals("\u{FFFF}", new String.fromCharCodes([0xFFFF]));
     Expect.equals("\u{0FFFF}", new String.fromCharCodes([0xFFFF]));
@@ -389,7 +389,7 @@
     var bs = "\b";
     Expect.isTrue(bs != "b");
     Expect.equals(1, bs.length);
-    Expect.equals(0x08, bs.charCodeAt(0));
+    Expect.equals(0x08, bs.codeUnitAt(0));
     Expect.equals(bs, new String.fromCharCodes([0x08]));
     Expect.equals("\x08", bs);
     Expect.equals("\u0008", bs);
@@ -403,7 +403,7 @@
     var ht = "\t";
     Expect.isTrue(ht != "t");
     Expect.equals(1, ht.length);
-    Expect.equals(0x09, ht.charCodeAt(0));
+    Expect.equals(0x09, ht.codeUnitAt(0));
     Expect.equals(ht, new String.fromCharCodes([0x09]));
     Expect.equals("\x09", ht);
     Expect.equals("\u0009", ht);
@@ -417,7 +417,7 @@
     var lf = "\n";
     Expect.isTrue(lf != "n");
     Expect.equals(1, lf.length);
-    Expect.equals(0x0A, lf.charCodeAt(0));
+    Expect.equals(0x0A, lf.codeUnitAt(0));
     Expect.equals(lf, new String.fromCharCodes([0x0A]));
     Expect.equals("\x0A", lf);
     Expect.equals("\u000A", lf);
@@ -431,7 +431,7 @@
     var vt = "\v";
     Expect.isTrue(vt != "v");
     Expect.equals(1, vt.length);
-    Expect.equals(0x0B, vt.charCodeAt(0));
+    Expect.equals(0x0B, vt.codeUnitAt(0));
     Expect.equals(vt, new String.fromCharCodes([0x0B]));
     Expect.equals("\x0B", vt);
     Expect.equals("\u000B", vt);
@@ -445,7 +445,7 @@
     var ff = "\f";
     Expect.isTrue(ff != "f");
     Expect.equals(1, ff.length);
-    Expect.equals(0x0C, ff.charCodeAt(0));
+    Expect.equals(0x0C, ff.codeUnitAt(0));
     Expect.equals(ff, new String.fromCharCodes([0x0C]));
     Expect.equals("\x0C", ff);
     Expect.equals("\u000C", ff);
@@ -459,7 +459,7 @@
     var cr = "\r";
     Expect.isTrue(cr != "r");
     Expect.equals(1, cr.length);
-    Expect.equals(0x0D, cr.charCodeAt(0));
+    Expect.equals(0x0D, cr.codeUnitAt(0));
     Expect.equals(cr, new String.fromCharCodes([0x0D]));
     Expect.equals("\x0D", cr);
     Expect.equals("\u000D", cr);
diff --git a/tests/language/closure_in_field_initializer_test.dart b/tests/language/closure_in_field_initializer_test.dart
new file mode 100644
index 0000000..88ca236
--- /dev/null
+++ b/tests/language/closure_in_field_initializer_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo {
+  var closures = {
+    'a': (x, y) => x + y
+  };
+}
+
+main() {
+  var closures = new Foo().closures;
+  Expect.equals(6, closures['a'](4, 2));
+}
diff --git a/tests/language/compound_assignment_operator_test.dart b/tests/language/compound_assignment_operator_test.dart
index 52c5289..e875af1 100644
--- a/tests/language/compound_assignment_operator_test.dart
+++ b/tests/language/compound_assignment_operator_test.dart
@@ -5,7 +5,7 @@
 
 
 class Indexed {
-  Indexed() : _f = new List.fixedLength(10), count = 0 {
+  Indexed() : _f = new List(10), count = 0 {
     _f[0] = 100;
     _f[1] = 200;
   }
diff --git a/tests/language/const_list_test.dart b/tests/language/const_list_test.dart
index 4422efb..e05f7a7 100644
--- a/tests/language/const_list_test.dart
+++ b/tests/language/const_list_test.dart
@@ -5,8 +5,8 @@
 class ConstListTest {
 
   static testMain() {
-    List fixedList = new List.fixedLength(4);
-    List fixedList2 = new List.fixedLength(4);
+    List fixedList = new List(4);
+    List fixedList2 = new List(4);
     List growableList = new List();
     List growableList2 = new List();
     for (int i = 0; i < 4; i++) {
diff --git a/tests/language/deopt_no_feedback_test.dart b/tests/language/deopt_no_feedback_test.dart
index 9cb79c1..f307e77 100644
--- a/tests/language/deopt_no_feedback_test.dart
+++ b/tests/language/deopt_no_feedback_test.dart
@@ -8,13 +8,13 @@
   test(a, i, v, flag) {
     if (flag) {
       // No type feedback in first pass
-      return a[i] = v; 
+      return a[i] = v;
     } else {
       return a[i] = i;
     }
   }
 
-  var a = new List.fixedLength(10);
+  var a = new List(10);
   for (var i = 0; i < 2000; i++) {
     var r = test(a, 3, 888, false);
     Expect.equals(3, r);
diff --git a/tests/language/execute_finally7_test.dart b/tests/language/execute_finally7_test.dart
index 6b68a0b..265e4c1 100644
--- a/tests/language/execute_finally7_test.dart
+++ b/tests/language/execute_finally7_test.dart
@@ -14,7 +14,7 @@
   static int f1(int k) {
     var b;
     try {
-      var a = new List.fixedLength(10);
+      var a = new List(10);
       int i = 0;
       while (i < 10) {
         int j = i;
diff --git a/tests/language/fannkuch_test.dart b/tests/language/fannkuch_test.dart
index a38d34d..356f20f 100644
--- a/tests/language/fannkuch_test.dart
+++ b/tests/language/fannkuch_test.dart
@@ -8,7 +8,7 @@
 
 class FannkuchTest {
   static fannkuch(n) {
-    var p = new List.fixedLength(n), q = new List.fixedLength(n), s = new List.fixedLength(n);
+    var p = new List(n), q = new List(n), s = new List(n);
     var sign = 1, maxflips = 0, sum = 0, m = n - 1;
     for (var i = 0; i < n; i++) { p[i] = i; q[i] = i; s[i] = i; }
     do {
diff --git a/tests/language/field_increment_bailout_test.dart b/tests/language/field_increment_bailout_test.dart
new file mode 100644
index 0000000..8ea2caa
--- /dev/null
+++ b/tests/language/field_increment_bailout_test.dart
@@ -0,0 +1,49 @@
+// 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.
+
+// dart2js regression test for issue 8781.
+
+class N {
+  var outgoing;
+  var incoming;
+  N(this.outgoing, this.incoming);
+}
+
+class A {
+  int offset = 0;
+  var list;
+  var node;
+
+  A(node) : node = node, list = node.outgoing;
+
+  next() {
+    // dart2js used to update [offset] twice: once in the optimized
+    // version, which would bailout to the non-optimized version
+    // because [list] is not an Array, and once in the non-optimized
+    // version.
+    var edge = list[offset++];
+    if (list == node.outgoing) {
+      list = node.incoming;
+      offset = 0;
+    } else
+      list = null;
+    return edge;
+  }
+}
+
+class L {
+  final list;
+  L(this.list);
+  // Use noSuchMethod to defeat type inferencing.
+  noSuchMethod(mirror) => mirror.invokeOn(list);
+}
+
+main () {
+  var o = new A(new N(new L([1]), new L([2])));
+
+  for (var i = 1; i <= 2; i++)
+    Expect.equals(i, o.next());
+
+  Expect.equals(null, o.list);
+}
diff --git a/tests/language/fixed_length_test.dart b/tests/language/fixed_length_test.dart
index 27be71f..0e8ab56 100644
--- a/tests/language/fixed_length_test.dart
+++ b/tests/language/fixed_length_test.dart
@@ -8,8 +8,8 @@
   Expect.equals(-1, foo());
 }
 
-int foo() {  
-  var list = new List<int>.fixedLength(1024);
+int foo() {
+  var list = new List<int>(1024);
 
   for(int i = 0; i < list.length; i++) list[i] = -i;
 
diff --git a/tests/language/full_stacktrace1_test.dart b/tests/language/full_stacktrace1_test.dart
new file mode 100644
index 0000000..37ac2bc
--- /dev/null
+++ b/tests/language/full_stacktrace1_test.dart
@@ -0,0 +1,56 @@
+void func1() {
+  throw new Exception("Test peanut gallery request for Full stacktrace");
+}
+void func2() {
+  func1();
+}
+void func3() {
+  try {
+    func2();
+  } on Object catch(e, s) {
+    print(e);
+
+    var full_trace = s.fullStackTrace;
+    Expect.isTrue(full_trace.contains("func1"));
+    Expect.isTrue(full_trace.contains("func2"));
+    Expect.isTrue(full_trace.contains("func3"));
+    Expect.isTrue(full_trace.contains("func4"));
+    Expect.isTrue(full_trace.contains("func5"));
+    Expect.isTrue(full_trace.contains("func6"));
+    Expect.isTrue(full_trace.contains("main"));
+
+    var trace = s.stackTrace;
+    Expect.isTrue(trace.contains("func1"));
+    Expect.isTrue(trace.contains("func2"));
+    Expect.isTrue(trace.contains("func3"));
+
+    Expect.isFalse(trace.contains("func4"));
+    Expect.isFalse(trace.contains("func5"));
+    Expect.isFalse(trace.contains("func6"));
+    Expect.isFalse(trace.contains("main"));
+
+    print(s);
+
+    print("Full stack trace");
+    print(full_trace);
+
+    print("Stack trace");
+    print(trace);
+  }
+}
+int func4() {
+  func3();
+  return 1;
+}
+int func5() {
+  func4();
+  return 1;
+}
+int func6() {
+  func5();
+  return 1;
+}
+main() {
+  var i = func6();
+  Expect.equals(1, i);
+}
diff --git a/tests/language/full_stacktrace2_test.dart b/tests/language/full_stacktrace2_test.dart
new file mode 100644
index 0000000..93625c9
--- /dev/null
+++ b/tests/language/full_stacktrace2_test.dart
@@ -0,0 +1,97 @@
+void func1() {
+  throw new Exception("Test peanut gallery request for Full stacktrace");
+}
+void func2() {
+  func1();
+}
+void func3() {
+  try {
+    func2();
+  } on Object catch(e, s) {
+    print(e);
+
+    var full_trace = s.fullStackTrace;
+    Expect.isTrue(full_trace.contains("func1"));
+    Expect.isTrue(full_trace.contains("func2"));
+    Expect.isTrue(full_trace.contains("func3"));
+    Expect.isTrue(full_trace.contains("func4"));
+    Expect.isTrue(full_trace.contains("func5"));
+    Expect.isTrue(full_trace.contains("func6"));
+    Expect.isTrue(full_trace.contains("func7"));
+    Expect.isTrue(full_trace.contains("main"));
+
+    var trace = s.stackTrace;
+    Expect.isTrue(trace.contains("func1"));
+    Expect.isTrue(trace.contains("func2"));
+    Expect.isTrue(trace.contains("func3"));
+
+    Expect.isFalse(trace.contains("func4"));
+    Expect.isFalse(trace.contains("func5"));
+    Expect.isFalse(trace.contains("func6"));
+    Expect.isFalse(trace.contains("func7"));
+    Expect.isFalse(trace.contains("main"));
+
+    print(s);
+
+    print("Full stack trace");
+    print(full_trace);
+
+    print("Stack trace");
+    print(trace);
+
+    throw;  // This is a rethrow.
+  }
+}
+int func4() {
+  func3();
+  return 1;
+}
+int func5() {
+  try {
+    func4();
+  } on Object catch(e, s) {
+
+    var full_trace = s.fullStackTrace;
+    print(full_trace);
+    Expect.isTrue(full_trace.contains("func1"));
+    Expect.isTrue(full_trace.contains("func2"));
+    Expect.isTrue(full_trace.contains("func3"));
+    Expect.isTrue(full_trace.contains("func4"));
+    Expect.isTrue(full_trace.contains("func5"));
+    Expect.isTrue(full_trace.contains("func6"));
+    Expect.isTrue(full_trace.contains("func7"));
+    Expect.isTrue(full_trace.contains("main"));
+
+    var trace = s.stackTrace;
+    Expect.isTrue(trace.contains("func1"));
+    Expect.isTrue(trace.contains("func2"));
+    Expect.isTrue(trace.contains("func3"));
+    Expect.isTrue(trace.contains("func4"));
+    Expect.isTrue(trace.contains("func5"));
+
+    Expect.isFalse(trace.contains("func6"));
+    Expect.isFalse(trace.contains("func7"));
+    Expect.isFalse(trace.contains("main"));
+
+    print(s);
+
+    print("Full stack trace");
+    print(full_trace);
+
+    print("Stack trace");
+    print(trace);
+  }
+  return 1;
+}
+int func6() {
+  func5();
+  return 1;
+}
+int func7() {
+  func6();
+  return 1;
+}
+main() {
+  var i = func7();
+  Expect.equals(1, i);
+}
diff --git a/tests/language/full_stacktrace3_test.dart b/tests/language/full_stacktrace3_test.dart
new file mode 100644
index 0000000..64abc93
--- /dev/null
+++ b/tests/language/full_stacktrace3_test.dart
@@ -0,0 +1,94 @@
+void func1() {
+  throw new Exception("Test peanut gallery request for Full stacktrace");
+}
+void func2() {
+  func1();
+}
+void func3() {
+  try {
+    func2();
+  } on Object catch(e, s) {
+    print(e);
+    var full_trace = s.fullStackTrace;
+    Expect.isTrue(full_trace.contains("func1"));
+    Expect.isTrue(full_trace.contains("func2"));
+    Expect.isTrue(full_trace.contains("func3"));
+    Expect.isTrue(full_trace.contains("func4"));
+    Expect.isTrue(full_trace.contains("func5"));
+    Expect.isTrue(full_trace.contains("func6"));
+    Expect.isTrue(full_trace.contains("func7"));
+    Expect.isTrue(full_trace.contains("main"));
+
+    var trace = s.stackTrace;
+    Expect.isTrue(trace.contains("func1"));
+    Expect.isTrue(trace.contains("func2"));
+    Expect.isTrue(trace.contains("func3"));
+
+    Expect.isFalse(trace.contains("func4"));
+    Expect.isFalse(trace.contains("func5"));
+    Expect.isFalse(trace.contains("func6"));
+    Expect.isFalse(trace.contains("func7"));
+    Expect.isFalse(trace.contains("main"));
+
+    print(s);
+
+    print("Full stack trace");
+    print(full_trace);
+
+    print("Stack trace");
+    print(trace);
+    throw new Exception("This is not a rethrow");
+  }
+}
+int func4() {
+  func3();
+  return 1;
+}
+int func5() {
+  try {
+    func4();
+  } on Object catch(e, s) {
+    var full_trace = s.fullStackTrace;
+    Expect.isFalse(full_trace.contains("func1"));
+    Expect.isFalse(full_trace.contains("func2"));
+    Expect.isTrue(full_trace.contains("func3"));
+    Expect.isTrue(full_trace.contains("func4"));
+    Expect.isTrue(full_trace.contains("func5"));
+    Expect.isTrue(full_trace.contains("func6"));
+    Expect.isTrue(full_trace.contains("func7"));
+    Expect.isTrue(full_trace.contains("main"));
+
+    var trace = s.stackTrace;
+    Expect.isFalse(trace.contains("func1"));
+    Expect.isFalse(trace.contains("func2"));
+
+    Expect.isTrue(trace.contains("func3"));
+    Expect.isTrue(trace.contains("func4"));
+    Expect.isTrue(trace.contains("func5"));
+
+    Expect.isFalse(trace.contains("func6"));
+    Expect.isFalse(trace.contains("func7"));
+    Expect.isFalse(trace.contains("main"));
+
+    print(s);
+
+    print("Full stack trace");
+    print(full_trace);
+
+    print("Stack trace");
+    print(trace);
+  }
+  return 1;
+}
+int func6() {
+  func5();
+  return 1;
+}
+int func7() {
+  func6();
+  return 1;
+}
+main() {
+  var i = func7();
+  Expect.equals(1, i);
+}
diff --git a/tests/language/gc_test.dart b/tests/language/gc_test.dart
index 9ae29a2..b64a4e3 100644
--- a/tests/language/gc_test.dart
+++ b/tests/language/gc_test.dart
@@ -7,12 +7,12 @@
 main() {
   var div;
   for (int i = 0; i < 200; ++i) {
-    List l = new List.fixedLength(1000000);
+    List l = new List(1000000);
     var m  = 2;
     div = (_) {
       var b = l;  // Was causing OutOfMemory.
     };
-    var lSmall = new List.fixedLength(3);
+    var lSmall = new List(3);
     // Circular reference between new and old gen objects.
     lSmall[0] = l;
     l[0] = lSmall;
diff --git a/tests/language/generic2_test.dart b/tests/language/generic2_test.dart
new file mode 100644
index 0000000..9048978
--- /dev/null
+++ b/tests/language/generic2_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test is-tests with type variables.
+
+class A<T> {
+  foo(o) => o is T;
+}
+
+class B {}
+
+class C extends A<int> {}
+
+main() {
+  Expect.isTrue(new A<Object>().foo(new B()));
+  Expect.isTrue(new A<Object>().foo(1));
+  Expect.isFalse(new A<int>().foo(new Object()));
+  Expect.isFalse(new A<int>().foo('hest'));
+  Expect.isTrue(new A<B>().foo(new B()));
+  Expect.isFalse(new A<B>().foo(new Object()));
+  Expect.isFalse(new A<B>().foo(1));
+  Expect.isTrue(new C().foo(1));
+  Expect.isFalse(new C().foo(new Object()));
+  Expect.isFalse(new C().foo('hest'));
+  Expect.isTrue(new A<List<int>>().foo(new List<int>()));
+  Expect.isFalse(new A<List<int>>().foo(new List<String>()));
+}
diff --git a/tests/language/generic_instanceof.dart b/tests/language/generic_instanceof.dart
index 5c65ec1..3f64976 100644
--- a/tests/language/generic_instanceof.dart
+++ b/tests/language/generic_instanceof.dart
@@ -37,91 +37,91 @@
     }
     {
       Foo foo = new Foo();
-      Expect.equals(true, foo.isT(new List.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<num>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isT(new List(5)));
+      Expect.equals(true, foo.isT(new List<Object>(5)));
+      Expect.equals(true, foo.isT(new List<int>(5)));
+      Expect.equals(true, foo.isT(new List<num>(5)));
+      Expect.equals(true, foo.isT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<List>();
-      Expect.equals(true, foo.isT(new List.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<num>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isT(new List(5)));
+      Expect.equals(true, foo.isT(new List<Object>(5)));
+      Expect.equals(true, foo.isT(new List<int>(5)));
+      Expect.equals(true, foo.isT(new List<num>(5)));
+      Expect.equals(true, foo.isT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<List<Object>>();
-      Expect.equals(true, foo.isT(new List.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<num>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isT(new List(5)));
+      Expect.equals(true, foo.isT(new List<Object>(5)));
+      Expect.equals(true, foo.isT(new List<int>(5)));
+      Expect.equals(true, foo.isT(new List<num>(5)));
+      Expect.equals(true, foo.isT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<List<int>>();
-      Expect.equals(true, foo.isT(new List.fixedLength(5)));
-      Expect.equals(false, foo.isT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
-      Expect.equals(false, foo.isT(new List<num>.fixedLength(5)));
-      Expect.equals(false, foo.isT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isT(new List(5)));
+      Expect.equals(false, foo.isT(new List<Object>(5)));
+      Expect.equals(true, foo.isT(new List<int>(5)));
+      Expect.equals(false, foo.isT(new List<num>(5)));
+      Expect.equals(false, foo.isT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<List<num>>();
-      Expect.equals(true, foo.isT(new List.fixedLength(5)));
-      Expect.equals(false, foo.isT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<int>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<num>.fixedLength(5)));
-      Expect.equals(false, foo.isT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isT(new List(5)));
+      Expect.equals(false, foo.isT(new List<Object>(5)));
+      Expect.equals(true, foo.isT(new List<int>(5)));
+      Expect.equals(true, foo.isT(new List<num>(5)));
+      Expect.equals(false, foo.isT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<List<String>>();
-      Expect.equals(true, foo.isT(new List.fixedLength(5)));
-      Expect.equals(false, foo.isT(new List<Object>.fixedLength(5)));
-      Expect.equals(false, foo.isT(new List<int>.fixedLength(5)));
-      Expect.equals(false, foo.isT(new List<num>.fixedLength(5)));
-      Expect.equals(true, foo.isT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isT(new List(5)));
+      Expect.equals(false, foo.isT(new List<Object>(5)));
+      Expect.equals(false, foo.isT(new List<int>(5)));
+      Expect.equals(false, foo.isT(new List<num>(5)));
+      Expect.equals(true, foo.isT(new List<String>(5)));
     }
     {
       Foo foo = new Foo();
-      Expect.equals(true, foo.isListT(new List.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<int>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<num>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isListT(new List(5)));
+      Expect.equals(true, foo.isListT(new List<Object>(5)));
+      Expect.equals(true, foo.isListT(new List<int>(5)));
+      Expect.equals(true, foo.isListT(new List<num>(5)));
+      Expect.equals(true, foo.isListT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<Object>();
-      Expect.equals(true, foo.isListT(new List.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<int>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<num>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isListT(new List(5)));
+      Expect.equals(true, foo.isListT(new List<Object>(5)));
+      Expect.equals(true, foo.isListT(new List<int>(5)));
+      Expect.equals(true, foo.isListT(new List<num>(5)));
+      Expect.equals(true, foo.isListT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<int>();
-      Expect.equals(true, foo.isListT(new List.fixedLength(5)));
-      Expect.equals(false, foo.isListT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<int>.fixedLength(5)));
-      Expect.equals(false, foo.isListT(new List<num>.fixedLength(5)));
-      Expect.equals(false, foo.isListT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isListT(new List(5)));
+      Expect.equals(false, foo.isListT(new List<Object>(5)));
+      Expect.equals(true, foo.isListT(new List<int>(5)));
+      Expect.equals(false, foo.isListT(new List<num>(5)));
+      Expect.equals(false, foo.isListT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<num>();
-      Expect.equals(true, foo.isListT(new List.fixedLength(5)));
-      Expect.equals(false, foo.isListT(new List<Object>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<int>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<num>.fixedLength(5)));
-      Expect.equals(false, foo.isListT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isListT(new List(5)));
+      Expect.equals(false, foo.isListT(new List<Object>(5)));
+      Expect.equals(true, foo.isListT(new List<int>(5)));
+      Expect.equals(true, foo.isListT(new List<num>(5)));
+      Expect.equals(false, foo.isListT(new List<String>(5)));
     }
     {
       Foo foo = new Foo<String>();
-      Expect.equals(true, foo.isListT(new List.fixedLength(5)));
-      Expect.equals(false, foo.isListT(new List<Object>.fixedLength(5)));
-      Expect.equals(false, foo.isListT(new List<int>.fixedLength(5)));
-      Expect.equals(false, foo.isListT(new List<num>.fixedLength(5)));
-      Expect.equals(true, foo.isListT(new List<String>.fixedLength(5)));
+      Expect.equals(true, foo.isListT(new List(5)));
+      Expect.equals(false, foo.isListT(new List<Object>(5)));
+      Expect.equals(false, foo.isListT(new List<int>(5)));
+      Expect.equals(false, foo.isListT(new List<num>(5)));
+      Expect.equals(true, foo.isListT(new List<String>(5)));
     }
   }
 }
diff --git a/tests/language/generic_native_test.dart b/tests/language/generic_native_test.dart
new file mode 100644
index 0000000..53e4c78
--- /dev/null
+++ b/tests/language/generic_native_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test is-tests with type variables on native subclasses.
+
+class A<T> {
+  foo(o) => o is T;
+}
+
+class B {}
+
+class C {}
+
+main() {
+  Expect.isTrue(new A<Iterable<B>>().foo(new List<B>()));
+  Expect.isFalse(new A<Iterable<C>>().foo(new List<B>()));
+
+  Expect.isTrue(new A<Collection<B>>().foo(new List<B>()));
+  Expect.isFalse(new A<Collection<C>>().foo(new List<B>()));
+
+  Expect.isTrue(new A<Pattern>().foo('hest'));
+
+  Expect.isTrue(new A<Comparable<String>>().foo('hest'));
+  Expect.isFalse(new A<Comparable<C>>().foo('hest'));
+}
diff --git a/tests/language/generics3_test.dart b/tests/language/generics3_test.dart
new file mode 100644
index 0000000..cbc2271
--- /dev/null
+++ b/tests/language/generics3_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program testing generic type allocations and generic type tests.
+// Regression test for issue 8710.
+
+class C1<T> {}
+class C2<T> {}
+class C3<T> extends C2<C1<T>> {}
+class C4<T> extends C3<T> { f() => new C5<C1<T>>(new C1<T>()); }
+class C5<T> { C5(T x); }  // Checked mode: x must be of type C1<String>.
+
+main() {
+  new C4<String>().f();
+}
diff --git a/tests/language/incr_op_test.dart b/tests/language/incr_op_test.dart
index 32730bd..be772e7 100644
--- a/tests/language/incr_op_test.dart
+++ b/tests/language/incr_op_test.dart
@@ -60,7 +60,7 @@
     Expect.equals(57, IncrOpTest.y);
     Expect.equals(56, --IncrOpTest.y);
 
-    var list = new List.fixedLength(4);
+    var list = new List(4);
     for (int i = 0; i < list.length; i++) {
       list[i] = i;
     }
diff --git a/tests/language/index_test.dart b/tests/language/index_test.dart
index 3462e4e..9e1c634 100644
--- a/tests/language/index_test.dart
+++ b/tests/language/index_test.dart
@@ -18,7 +18,7 @@
   static const ID_IDLE = 0;
 
   static testMain() {
-    var a = new List.fixedLength(10);
+    var a = new List(10);
     Expect.equals(10, a.length);
     for (int i = 0; i < a.length; i++) {
       a[i] = Helper.fibonacci(i);
diff --git a/tests/language/inst_field_initializer1_negative_test.dart b/tests/language/inst_field_initializer1_negative_test.dart
index 1c56eb0..44fcca1 100644
--- a/tests/language/inst_field_initializer1_negative_test.dart
+++ b/tests/language/inst_field_initializer1_negative_test.dart
@@ -7,7 +7,7 @@
 class A {
   A() {}
   int x = 5;
-  int arr = new List.fixedLength(x);  // Illegal access to 'this'.
+  int arr = new List(x);  // Illegal access to 'this'.
                           // Also not a compile const expression.
 }
 
diff --git a/tests/language/instance_inline_test.dart b/tests/language/instance_inline_test.dart
index e45dde2..fefdf21 100644
--- a/tests/language/instance_inline_test.dart
+++ b/tests/language/instance_inline_test.dart
@@ -15,7 +15,7 @@
   int nextByte() => charAt(++byteOffset);
 
   int charAt(index)
-      => (string.length > index) ? string.charCodeAt(index) : -1;
+      => (string.length > index) ? string.codeUnitAt(index) : -1;
 }
 
 void main() {
@@ -24,4 +24,4 @@
   Expect.equals(0x7A, scanner.nextByte()); // Expect z.
   Expect.equals(0x39, scanner.nextByte()); // Expect 9.
   Expect.equals(-1, scanner.nextByte());
-}
\ No newline at end of file
+}
diff --git a/tests/language/instanceof2_test.dart b/tests/language/instanceof2_test.dart
index 0655b86..f93c0b3 100644
--- a/tests/language/instanceof2_test.dart
+++ b/tests/language/instanceof2_test.dart
@@ -54,7 +54,7 @@
     Expect.equals(false, null is I);
 
     {
-      var a = new List.fixedLength(5);
+      var a = new List(5);
       Expect.equals(true, a is List);
       Expect.equals(true, a is List<Object>);
       Expect.equals(true, a is List<int>);
@@ -62,7 +62,7 @@
       Expect.equals(true, a is List<String>);
     }
     {
-      var a = new List<Object>.fixedLength(5);
+      var a = new List<Object>(5);
       Expect.equals(true, a is List);
       Expect.equals(true, a is List<Object>);
       Expect.equals(false, a is List<int>);
@@ -70,7 +70,7 @@
       Expect.equals(false, a is List<String>);
     }
     {
-      var a = new List<int>.fixedLength(5);
+      var a = new List<int>(5);
       Expect.equals(true, a is List);
       Expect.equals(true, a is List<Object>);
       Expect.equals(true, a is List<int>);
@@ -78,7 +78,7 @@
       Expect.equals(false, a is List<String>);
     }
     {
-      var a = new List<num>.fixedLength(5);
+      var a = new List<num>(5);
       Expect.equals(true, a is List);
       Expect.equals(true, a is List<Object>);
       Expect.equals(false, a is List<int>);
@@ -86,7 +86,7 @@
       Expect.equals(false, a is List<String>);
     }
     {
-      var a = new List<String>.fixedLength(5);
+      var a = new List<String>(5);
       Expect.equals(true, a is List);
       Expect.equals(true, a is List<Object>);
       Expect.equals(false, a is List<int>);
diff --git a/tests/language/interceptor6_test.dart b/tests/language/interceptor6_test.dart
new file mode 100644
index 0000000..35f4bd3
--- /dev/null
+++ b/tests/language/interceptor6_test.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that an intercepted call on a method that does not exist does
+// not crash the compiler.
+
+main() {
+  Expect.throws(() => 42.clamp(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/interceptor_test.dart b/tests/language/interceptor_test.dart
index e79f759..2fe247e 100644
--- a/tests/language/interceptor_test.dart
+++ b/tests/language/interceptor_test.dart
@@ -6,28 +6,28 @@
 // JavaScript primitives) in dart2js work.
 
 class A {
-  charCodeAt(a) => a;
+  codeUnitAt(a) => a;
 }
 
 main() {
   var res = [[], 1, 'foo', new A()];
-  Expect.throws(() => res[0].charCodeAt(1));
-  Expect.throws(() => (res[0].charCodeAt)(1));
+  Expect.throws(() => res[0].codeUnitAt(1));
+  Expect.throws(() => (res[0].codeUnitAt)(1));
 
-  Expect.throws(() => res[1].charCodeAt(1));
-  Expect.throws(() => (res[1].charCodeAt)(1));
+  Expect.throws(() => res[1].codeUnitAt(1));
+  Expect.throws(() => (res[1].codeUnitAt)(1));
 
-  Expect.equals(111, res[2].charCodeAt(1));
-  Expect.equals(111, (res[2].charCodeAt)(1));
-  Expect.throws(() => res[2].charCodeAt(1, 4));
-  Expect.throws(() => res[2].charCodeAt());
-  Expect.throws(() => (res[2].charCodeAt)(1, 4));
-  Expect.throws(() => (res[2].charCodeAt)());
+  Expect.equals(111, res[2].codeUnitAt(1));
+  Expect.equals(111, (res[2].codeUnitAt)(1));
+  Expect.throws(() => res[2].codeUnitAt(1, 4));
+  Expect.throws(() => res[2].codeUnitAt());
+  Expect.throws(() => (res[2].codeUnitAt)(1, 4));
+  Expect.throws(() => (res[2].codeUnitAt)());
 
-  Expect.equals(1, res[3].charCodeAt(1));
-  Expect.equals(1, (res[3].charCodeAt)(1));
-  Expect.throws(() => res[3].charCodeAt(1, 4));
-  Expect.throws(() => res[3].charCodeAt());
-  Expect.throws(() => (res[3].charCodeAt)(1, 4));
-  Expect.throws(() => (res[3].charCodeAt)());
+  Expect.equals(1, res[3].codeUnitAt(1));
+  Expect.equals(1, (res[3].codeUnitAt)(1));
+  Expect.throws(() => res[3].codeUnitAt(1, 4));
+  Expect.throws(() => res[3].codeUnitAt());
+  Expect.throws(() => (res[3].codeUnitAt)(1, 4));
+  Expect.throws(() => (res[3].codeUnitAt)());
 }
diff --git a/tests/language/invocation_mirror_invoke_on2_test.dart b/tests/language/invocation_mirror_invoke_on2_test.dart
index b8bec8a..0e4deac 100644
--- a/tests/language/invocation_mirror_invoke_on2_test.dart
+++ b/tests/language/invocation_mirror_invoke_on2_test.dart
@@ -48,7 +48,7 @@
   var string = "funky";
   var proxy = new Proxy(string);
 
-  Expect.equals(string.charCodeAt(0), proxy.charCodeAt(0));
+  Expect.equals(string.codeUnitAt(0), proxy.codeUnitAt(0));
   Expect.equals(string.length, proxy.length);
 
   Expect.throws(() => proxy.funky(), (e) => e is NoSuchMethodError);
diff --git a/tests/language/language.status b/tests/language/language.status
index 10d2a54..cf89e4a7 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -61,10 +61,11 @@
 mixin_illegal_syntax_test/none: Fail
 mixin_type_parameters_mixin_test: Fail
 mixin_type_parameters_super_test: Fail
-mixin_type_parameters_mixin_extends_test: Fail
 mixin_type_parameters_super_extends_test: Fail
 mixin_lib_extends_field_test: Fail
 
+type_variable_field_initializer_closure_test: Crash # issue 8847 
+
 [ $compiler == none && ($system == macos || $system == linux) && $arch == ia32 && $checked ]
 gc_test: Skip  # Issue 1487, flaky.
 
@@ -291,6 +292,8 @@
 # test issue 8127 (using mixin application as mixin)
 mixin_mixin_test: Fail
 
+# test issue 8801
+super_operator_index_test/04: Fail
 
 #
 # Add new dartc annotations above in alphabetical order
@@ -302,6 +305,7 @@
 
 
 [ $compiler == none && $runtime == drt ]
+type_variable_field_initializer_closure_test: Fail # issue 8847 
 final_variable_assignment_test/01: Fail
 final_variable_assignment_test/02: Fail
 final_variable_assignment_test/03: Fail
@@ -358,7 +362,6 @@
 mixin_illegal_constructor_test/none: Fail       # VM issue
 mixin_type_parameters_mixin_test: Fail          # VM issue
 mixin_type_parameters_super_test: Fail          # VM issue
-mixin_type_parameters_mixin_extends_test: Fail  # VM issue
 mixin_type_parameters_super_extends_test: Fail  # VM issue
 
 # Malformed types not handled as unresolved:
@@ -540,6 +543,8 @@
 type_error_test: Fail, OK # VM bug: http://dartbug.com/5280
 type_parameter_literal_test: Fail
 
+type_variable_field_initializer_closure_test: Crash # VM bug: issue 8847 
+
 [ $compiler == dart2dart && $minified ]
 
 # TODO(tball): Assign proper bug numbers.
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 332f08d..ccd4b5c 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -26,12 +26,21 @@
 class_literal_test/27: Fail # Class literals are expression now; delete this test.
 class_literal_test/28: Fail # Class literals are expression now; delete this test.
 class_literal_test/29: Fail # Class literals are expression now; delete this test.
+full_stacktrace1_test: Skip # Stack trace interface is not implemented yet.
+full_stacktrace2_test: Skip # Stack trace interface is not implemented yet.
+full_stacktrace3_test: Skip # Stack trace interface is not implemented yet.
+stacktrace_test: Skip # Stack trace interface is not implemented yet.
 
 # VM specific tests that should not be run by dart2js.
 *vm_test: Skip
 *vm_negative_test: Skip
 
 [ $compiler == dart2js && $checked ]
+mixin_type_parameters_super_extends_test: Fail # http://dartbug.com/8116
+mixin_type_parameters_super_test: Fail # http://dartbug.com/8116
+mixin_type_parameters_mixin_extends_test: Fail # http://dartbug.com/8116
+mixin_type_parameters_mixin_test: Fail # http://dartbug.com/8116
+
 prefix16_test: Fail # dartbug.com/7354
 default_factory2_test/01: Pass # For the wrong reasons.
 type_variable_scope_test/none: Fail
@@ -88,6 +97,7 @@
 compile_time_constant_checked3_test/06: Fail, OK
 
 [ $compiler == dart2js ]
+type_variable_field_initializer_closure_test: Fail # Issue 8848
 branch_canonicalization_test: Fail # Issue 638.
 div_with_power_of_two_test: Fail # Issue 8301.
 call_operator_test: Fail # Issue 7622.
@@ -164,7 +174,6 @@
 function_type_alias_test: Fail # cannot resolve type Fun
 function_type_parameter2_test: Fail # Internal Error: expected optional parameters
 function_type_parameter_test: Fail # Internal Error: expected optional parameters
-generic_instanceof_test: Fail # cannot resolve type T
 generic_test: Fail # cannot resolve type T
 get_set_syntax_test/00: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
 get_set_syntax_test/01: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
@@ -180,7 +189,6 @@
 get_set_syntax_test/15: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
 get_set_syntax_test/16: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
 implicit_scope_test: Fail # duplicate definition of a="bar"
-many_generic_instanceof_test: Fail # cannot resolve type T
 method_binding_test: Fail # internal error: super property read not implemented.
 method_override_test: Fail # cannot resolve type GetKeysFunctionType
 method_override2_test/00: Fail # accepts illegal override
@@ -200,13 +208,6 @@
 on_catch_malformed_type_test: Fail # Malformed types cause compile-time errors.
 
 
-# Failing tests for mixin type parameters.
-mixin_type_parameters_mixin_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_super_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_mixin_extends_test: Fail # http://dartbug.com/8116
-mixin_type_parameters_super_extends_test: Fail # http://dartbug.com/8116
-
-
 # External tests.
 external_test/01: Fail
 external_test/02: Fail
@@ -314,7 +315,6 @@
 optimization_test: Fail, OK # Expects negative results of bit-operations.
 
 expect_test: Fail, OK # JavaScript canonicalizes all strings. This test assumes that string-concatenation returns a new string.
-reg_exp3_test: Fail, OK # Expects exception from const constructor.
 
 # Partially implemented redirecting constructors makes this throw instead
 # of failing.
@@ -322,6 +322,8 @@
 
 assign_top_method_test: Fail
 
+super_operator_index2_test: Fail # Issue 8800
+super_operator_index_test/01: Fail # Issue 8800
 
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
@@ -346,8 +348,6 @@
 [ $compiler == dart2js && $runtime == safari ]
 execute_finally8_test: Fail # Issue: 7414
 execute_finally9_test: Fail # Issue: 7414
-null_access_error_test: Fail # Issue: 7414
-closure3_test: Fail # Uncaught error: Instance of 'TypeError'
 null_pointer_exception_test: Fail # Uncaught error: Instance of 'TypeError'
 string_interpolate_npe_test: Fail # Uncaught error: Instance of 'TypeError'
 arithmetic_test: Fail # Issue: 7414
diff --git a/tests/language/list_test.dart b/tests/language/list_test.dart
index a94b14b..1a9986f 100644
--- a/tests/language/list_test.dart
+++ b/tests/language/list_test.dart
@@ -5,7 +5,7 @@
 
 class ListTest {
   static void TestIterator() {
-    List<int> a = new List<int>.fixedLength(10);
+    List<int> a = new List<int>(10);
     int count = 0;
 
     // Basic iteration over ObjectList.
@@ -42,7 +42,7 @@
 
   static void testMain() {
     int len = 10;
-    List a = new List.fixedLength(len);
+    List a = new List(len);
     Expect.equals(true, a is List);
     Expect.equals(len, a.length);
     a.forEach((element) { Expect.equals(null, element); });
@@ -51,17 +51,17 @@
     Expect.throws(() => a[len], (e) => e is RangeError);
 
     Expect.throws(() {
-      List a = new List.fixedLength(4);
+      List a = new List(4);
       a.setRange(1, 1, a, null);
     });
 
     Expect.throws(() {
-      List a = new List.fixedLength(4);
+      List a = new List(4);
       a.setRange(10, 1, a, 1);
     }, (e) => e is RangeError);
 
-    a = new List.fixedLength(4);
-    List b = new List.fixedLength(4);
+    a = new List(4);
+    List b = new List(4);
     b.setRange(0, 4, a, 0);
 
     List<int> unsorted = [4, 3, 9, 12, -4, 9];
@@ -95,8 +95,8 @@
     Expect.throws(() => unsorted[2.1],
                   (e) => e is ArgumentError || e is TypeError);
 
-    Expect.throws(() => new List.fixedLength(-1));
-    Expect.throws(() => new List.fixedLength(99999999999999999999999));
+    Expect.throws(() => new List(-1));
+    Expect.throws(() => new List(99999999999999999999999));
 
     List list = new List();
     // We cannot write just 'list.removeLast' due to issue 3769.
diff --git a/tests/language/local_function_test.dart b/tests/language/local_function_test.dart
index 82f5fc2..104319f 100644
--- a/tests/language/local_function_test.dart
+++ b/tests/language/local_function_test.dart
@@ -16,8 +16,8 @@
   }
   static int h(int n) {
     k(int n) {
-      var a = new List.fixedLength(n);
-      var b = new List.fixedLength(n);
+      var a = new List(n);
+      var b = new List(n);
       int i;
       for (i = 0; i < n; i++) {
         var j = i;
@@ -36,8 +36,8 @@
   }
   static int h2(int n) {
     k(int n) {
-      var a = new List.fixedLength(n);
-      var b = new List.fixedLength(n);
+      var a = new List(n);
+      var b = new List(n);
       for (int i = 0; i < n; i++) {
         var j = i;
         a[i] = () => i;  // Captured i varies from 0 to n-1.
@@ -94,7 +94,7 @@
     f();
   }
   static testNesting(int n) {
-    var a = new List.fixedLength(n*n);
+    var a = new List(n*n);
     f0() {
       for (int i = 0; i < n; i++) {
         int vi = i;
diff --git a/tests/language/many_calls_test.dart b/tests/language/many_calls_test.dart
index a8db476..c59b90f 100644
--- a/tests/language/many_calls_test.dart
+++ b/tests/language/many_calls_test.dart
@@ -53,7 +53,7 @@
 
 class ManyCallsTest {
   static testMain() {
-    var list = new List.fixedLength(10);
+    var list = new List(10);
     for (int i = 0; i < (list.length ~/ 2) ; i++) {
       list[i] = new A();
     }
diff --git a/tests/language/null_hashcode_optimized_vm_test.dart b/tests/language/null_hashcode_optimized_vm_test.dart
new file mode 100644
index 0000000..27906ca
--- /dev/null
+++ b/tests/language/null_hashcode_optimized_vm_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test that optimized Object.hashCode works for the null receiver.
+// VMOptions=--optimization_counter_threshold=100
+
+main() {
+  for (int i = 0; i < 200; i++) {
+    foo(null);
+  }
+}
+
+foo(a) => a.hashCode;
diff --git a/tests/language/optimization_test.dart b/tests/language/optimization_test.dart
index be41f4f..c399754 100644
--- a/tests/language/optimization_test.dart
+++ b/tests/language/optimization_test.dart
@@ -63,7 +63,7 @@
   // Deoptimize because of overflow.
   var minInt = -(1 << 30);
   Expect.equals(minInt, doNeg(doNeg(minInt)));
-  
+
   for (int i = 0; i < 1000; i++) {
     Expect.equals(false, doNot(true));
     Expect.equals(true, doNot(doNot(true)));
@@ -79,7 +79,7 @@
   // Deoptimize.
   Expect.equals(-5, doNeg2(5));
 
-  var fixed = new List.fixedLength(10);
+  var fixed = new List(10);
   var growable = [1, 2, 3, 4, 5];
 
   for (int i = 0; i < 2000; i++) {
diff --git a/tests/language/optimized_constant_array_string_access_test.dart b/tests/language/optimized_constant_array_string_access_test.dart
index 2e0b1ba..391d971 100644
--- a/tests/language/optimized_constant_array_string_access_test.dart
+++ b/tests/language/optimized_constant_array_string_access_test.dart
@@ -4,10 +4,10 @@
 
 // Test optimized constant string and constant array access.
 
-int testConstantStringAndIndexCharCodeAt() {
+int testConstantStringAndIndexCodeUnitAt() {
   int test(b) {
-    if (b) return "hest".charCodeAt(400);
-    return "hest".charCodeAt(2);
+    if (b) return "hest".codeUnitAt(400);
+    return "hest".codeUnitAt(2);
   }
 
   Expect.throws(() => test(true));
@@ -43,7 +43,7 @@
 
 
 main() {
-  testConstantStringAndIndexCharCodeAt();
+  testConstantStringAndIndexCodeUnitAt();
   testConstantArrayAndIndexAt();
   testNonSmiIndex();
 }
diff --git a/tests/language/optimized_lists_test.dart b/tests/language/optimized_lists_test.dart
index cd2a596..cc3b862 100644
--- a/tests/language/optimized_lists_test.dart
+++ b/tests/language/optimized_lists_test.dart
@@ -13,7 +13,7 @@
 
 test(n) {
   var a = new List();    // Growable list.
-  var b = new List.fixedLength(10);  // Fixed size list.
+  var b = new List(10);  // Fixed size list.
   var c = const [1, 2, 3, 4];  // Constant aray.
   // In optimized mode the class checks will be eliminated since the
   // constructors above provide information about exact types.
diff --git a/tests/language/optimized_string_charcodeat_test.dart b/tests/language/optimized_string_charcodeat_test.dart
index aa2bd64..e4747f2 100644
--- a/tests/language/optimized_string_charcodeat_test.dart
+++ b/tests/language/optimized_string_charcodeat_test.dart
@@ -2,60 +2,60 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Test optimized charCodeAt and array access.
+// Test optimized CodeUnitAt and array access.
 
 String one_byte = "hest";
 String two_byte = "høns";
 
-int testOneByteCharCodeAt(String x, int j) {
+int testOneByteCodeUnitAt(String x, int j) {
   int test() {
-    return x.charCodeAt(j);
+    return x.codeUnitAt(j);
   }
   for (int i = 0; i < 10000; i++) test();
   return test();
 }
 
 
-int testTwoByteCharCodeAt(String x, int j) {
+int testTwoByteCodeUnitAt(String x, int j) {
   int test() {
-    return x.charCodeAt(j);
+    return x.codeUnitAt(j);
   }
   for (int i = 0; i < 10000; i++) test();
   return test();
 }
 
 
-int testConstantStringCharCodeAt(int j) {
+int testConstantStringCodeUnitAt(int j) {
   int test() {
-    return "høns".charCodeAt(j);
+    return "høns".codeUnitAt(j);
   }
   for (int i = 0; i < 10000; i++) test();
   return test();
 }
 
 
-int testConstantIndexCharCodeAt(String x) {
+int testConstantIndexCodeUnitAt(String x) {
   int test() {
-    return x.charCodeAt(1);
+    return x.codeUnitAt(1);
   }
   for (int i = 0; i < 10000; i++) test();
   return test();
 }
 
 
-int testOneByteCharCodeAtInLoop(var x) {
+int testOneByteCodeUnitAtInLoop(var x) {
   var result = 0;
   for (int i = 0; i < x.length; i++) {
-    result += x.charCodeAt(i);
+    result += x.codeUnitAt(i);
   }
   return result;
 }
 
 
-int testTwoByteCharCodeAtInLoop(var x) {
+int testTwoByteCodeUnitAtInLoop(var x) {
   var result = 0;
   for (int i = 0; i < x.length; i++) {
-    result += x.charCodeAt(i);
+    result += x.codeUnitAt(i);
   }
   return result;
 }
@@ -63,15 +63,15 @@
 
 main() {
   for (int j = 0; j < 10; j++) {
-    Expect.equals(101, testOneByteCharCodeAt(one_byte, 1));
-    Expect.equals(248, testTwoByteCharCodeAt(two_byte, 1));
-    Expect.equals(248, testConstantStringCharCodeAt(1));
-    Expect.equals(101, testConstantIndexCharCodeAt(one_byte));
+    Expect.equals(101, testOneByteCodeUnitAt(one_byte, 1));
+    Expect.equals(248, testTwoByteCodeUnitAt(two_byte, 1));
+    Expect.equals(248, testConstantStringCodeUnitAt(1));
+    Expect.equals(101, testConstantIndexCodeUnitAt(one_byte));
   }
   for (int j = 0; j < 2000; j++) {
-    Expect.equals(436, testOneByteCharCodeAtInLoop(one_byte));
-    Expect.equals(577, testTwoByteCharCodeAtInLoop(two_byte));
+    Expect.equals(436, testOneByteCodeUnitAtInLoop(one_byte));
+    Expect.equals(577, testTwoByteCodeUnitAtInLoop(two_byte));
   }
-  Expect.throws(() => testOneByteCharCodeAtInLoop(123));
-  Expect.throws(() => testTwoByteCharCodeAtInLoop(123));
+  Expect.throws(() => testOneByteCodeUnitAtInLoop(123));
+  Expect.throws(() => testTwoByteCodeUnitAtInLoop(123));
 }
diff --git a/tests/language/script_negative_test.dart b/tests/language/script_negative_test.dart
deleted file mode 100644
index 60c2f284..0000000
--- a/tests/language/script_negative_test.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Imported library does not start with a library tag.
-
-library ScriptNegativeTest.dart;
-import "script_negative_lib.dart";
-
-main() {
-  print("Should not reach here.");
-}
diff --git a/tests/language/stacktrace_test.dart b/tests/language/stacktrace_test.dart
new file mode 100644
index 0000000..98e644e
--- /dev/null
+++ b/tests/language/stacktrace_test.dart
@@ -0,0 +1,15 @@
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that a stack trace is properly terminated (issue 8850).
+void main() {
+  var ex = new Exception("fail");
+  try {
+    throw ex;
+  } on Exception catch(e, st) {
+    Expect.equals(ex, e);
+    Expect.isTrue(st.toString().endsWith("\n"));
+  }
+}
diff --git a/tests/language/static_inline_test.dart b/tests/language/static_inline_test.dart
index 4c5ad9a..5163b3d 100644
--- a/tests/language/static_inline_test.dart
+++ b/tests/language/static_inline_test.dart
@@ -16,7 +16,7 @@
   }
 
   static int charAt(index)
-      => (string.length > index) ? string.charCodeAt(index) : -1;
+      => (string.length > index) ? string.codeUnitAt(index) : -1;
 }
 
 void main() {
@@ -26,4 +26,4 @@
   Expect.equals(0x7A, scanner.nextByte(false)); // Expect z.
   Expect.equals(0x39, scanner.nextByte(false)); // Expect 9.
   Expect.equals(-1, scanner.nextByte(false));
-}
\ No newline at end of file
+}
diff --git a/tests/language/store_to_load_forwarding_phis_vm_test.dart b/tests/language/store_to_load_forwarding_phis_vm_test.dart
new file mode 100644
index 0000000..13654a6
--- /dev/null
+++ b/tests/language/store_to_load_forwarding_phis_vm_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Test correct handling of phis with only environment uses that were inserted
+// by store to load forwarding.
+// VMOptions=--optimization_counter_threshold=100
+
+library store_to_load_forwarding_phis_vm_test;
+
+import 'dart:async';
+
+class A {
+  var _foo;
+
+  get foo {
+    if (_foo == null) {
+      _foo = new A();
+    }
+    return _foo;
+  }
+}
+
+foo(obj) {
+  var a = obj.foo;
+  return new Future.immediate(null).then((val) { });
+}
+
+main() {
+  final obj = new A();
+  for (var i = 0; i < 200; i++) {
+    foo(obj);
+  }
+}
\ No newline at end of file
diff --git a/tests/language/string_escapes_test.dart b/tests/language/string_escapes_test.dart
index 20a7beb..6e80214 100644
--- a/tests/language/string_escapes_test.dart
+++ b/tests/language/string_escapes_test.dart
@@ -15,43 +15,43 @@
   static testDelimited() {
     String str = "Foo\u{1}Bar\u{000001}Baz\u{D7FF}Boo";
     Expect.equals(15, str.length);
-    Expect.equals(1, str.charCodeAt(3));
-    Expect.equals(1, str.charCodeAt(7));
-    Expect.equals(0xD7FF, str.charCodeAt(11));
-    Expect.equals('B'.charCodeAt(0), str.charCodeAt(12));
+    Expect.equals(1, str.codeUnitAt(3));
+    Expect.equals(1, str.codeUnitAt(7));
+    Expect.equals(0xD7FF, str.codeUnitAt(11));
+    Expect.equals('B'.codeUnitAt(0), str.codeUnitAt(12));
   }
 
   static testEscapes() {
     String str = "Foo\fBar\vBaz\bBoo";
     Expect.equals(15, str.length);
-    Expect.equals(12, str.charCodeAt(3));
-    Expect.equals('B'.charCodeAt(0), str.charCodeAt(4));
-    Expect.equals(11, str.charCodeAt(7));
-    Expect.equals('z'.charCodeAt(0), str.charCodeAt(10));
-    Expect.equals(8, str.charCodeAt(11));
-    Expect.equals('o'.charCodeAt(0), str.charCodeAt(14));
+    Expect.equals(12, str.codeUnitAt(3));
+    Expect.equals('B'.codeUnitAt(0), str.codeUnitAt(4));
+    Expect.equals(11, str.codeUnitAt(7));
+    Expect.equals('z'.codeUnitAt(0), str.codeUnitAt(10));
+    Expect.equals(8, str.codeUnitAt(11));
+    Expect.equals('o'.codeUnitAt(0), str.codeUnitAt(14));
     str = "Abc\rDef\nGhi\tJkl";
     Expect.equals(15, str.length);
-    Expect.equals(13, str.charCodeAt(3));
-    Expect.equals('D'.charCodeAt(0), str.charCodeAt(4));
-    Expect.equals(10, str.charCodeAt(7));
-    Expect.equals('G'.charCodeAt(0), str.charCodeAt(8));
-    Expect.equals(9, str.charCodeAt(11));
-    Expect.equals('J'.charCodeAt(0), str.charCodeAt(12));
+    Expect.equals(13, str.codeUnitAt(3));
+    Expect.equals('D'.codeUnitAt(0), str.codeUnitAt(4));
+    Expect.equals(10, str.codeUnitAt(7));
+    Expect.equals('G'.codeUnitAt(0), str.codeUnitAt(8));
+    Expect.equals(9, str.codeUnitAt(11));
+    Expect.equals('J'.codeUnitAt(0), str.codeUnitAt(12));
   }
 
   static testFixed2() {
     String str = "Foo\xFFBar";
     Expect.equals(7, str.length);
-    Expect.equals(255, str.charCodeAt(3));
-    Expect.equals('B'.charCodeAt(0), str.charCodeAt(4));
+    Expect.equals(255, str.codeUnitAt(3));
+    Expect.equals('B'.codeUnitAt(0), str.codeUnitAt(4));
   }
 
   static testFixed4() {
     String str = "Foo\u0001Bar";
     Expect.equals(7, str.length);
-    Expect.equals(1, str.charCodeAt(3));
-    Expect.equals('B'.charCodeAt(0), str.charCodeAt(4));
+    Expect.equals(1, str.codeUnitAt(3));
+    Expect.equals('B'.codeUnitAt(0), str.codeUnitAt(4));
   }
 
   static testLiteral() {
diff --git a/tests/language/string_test.dart b/tests/language/string_test.dart
index 52cdf71..bbeb91c 100644
--- a/tests/language/string_test.dart
+++ b/tests/language/string_test.dart
@@ -16,12 +16,12 @@
     String str = "string";
     for (int i = 0; i < str.length; i++) {
       Expect.equals(true, str[i] is String);
-      Expect.equals(true, str.charCodeAt(i) is int);
+      Expect.equals(true, str.codeUnitAt(i) is int);
     }
   }
 
   static testStringsJoin() {
-    List<String> a = new List<String>.fixedLength(2);
+    List<String> a = new List<String>(2);
     a[0] = "Hello";
     a[1] = "World";
     String s = a.join("*^*");
@@ -42,7 +42,7 @@
   static testCharCodes() {
     String s = new String.fromCharCodes(const [0x41, 0xC1, 0x424]);
     Expect.equals("A", s[0]);
-    Expect.equals(0x424, s.charCodeAt(2));
+    Expect.equals(0x424, s.codeUnitAt(2));
   }
 }
 
diff --git a/tests/language/super_operator_index2_test.dart b/tests/language/super_operator_index2_test.dart
new file mode 100644
index 0000000..47cf16d
--- /dev/null
+++ b/tests/language/super_operator_index2_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for super indexing operations.
+
+class A {
+  var map = new Map();
+  operator[]=(a, b) { map[a] = b; }
+  operator[](a) => map[a];
+}
+
+class B extends A {
+  foo() {
+    super[4] = 42;
+    Expect.equals(42, super[4]);
+    super[4] += 5;
+    Expect.equals(47, super[4]);
+  }
+}
+
+main() {
+  new B().foo();
+}
diff --git a/tests/language/super_operator_index_test.dart b/tests/language/super_operator_index_test.dart
new file mode 100644
index 0000000..36c6819
--- /dev/null
+++ b/tests/language/super_operator_index_test.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.
+
+// Test that we emit warnings for unresolved indexing operations on super.
+
+class A {
+  operator[]=(a, b) {}
+}
+
+class B extends A {
+  foo() {
+    super[4] = 42;
+    super[4] += 5; /// 01: static type warning, runtime error
+    return super[2]; /// 02: static type warning, runtime error
+  }
+}
+
+class C {
+  operator[](a) {}
+}
+
+class D extends C {
+  foo() {
+    super[4] = 42; /// 03: static type warning, runtime error
+    super[4] += 5; /// 04: static type warning, runtime error
+    return super[2];
+  }
+}
+
+class E {
+  foo() {
+    super[4] = 42; /// 05: static type warning, runtime error
+    super[4] += 5; /// 06: static type warning, runtime error
+    return super[2]; /// 07: static type warning, runtime error
+  }
+}
+
+main() {
+  new B().foo();
+  new D().foo();
+  new E().foo();
+}
diff --git a/tests/language/type_cast_vm_test.dart b/tests/language/type_cast_vm_test.dart
index fdf4cc9..22e3437 100644
--- a/tests/language/type_cast_vm_test.dart
+++ b/tests/language/type_cast_vm_test.dart
@@ -38,7 +38,7 @@
       return 0;
     }
     try {
-      var a = new List<int>.fixedLength(1) as List<int>;
+      var a = new List<int>(1) as List<int>;
       a[0] = 0;
       a[index()]++;  // Type check succeeds, but does not create side effects.
       Expect.equals(1, a[0]);
diff --git a/tests/language/type_variable_field_initializer_closure_test.dart b/tests/language/type_variable_field_initializer_closure_test.dart
new file mode 100644
index 0000000..e4da4a5
--- /dev/null
+++ b/tests/language/type_variable_field_initializer_closure_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that an inlined field closure has access to the enclosing
+// type variables.
+
+class A<T> {
+  var c = (() => new List<T>())();
+}
+
+class B<T> extends A<T> {
+}
+
+main() {
+  Expect.isTrue(new B<int>().c is List<int>);
+  Expect.isFalse(new B<String>().c is List<int>);
+}
diff --git a/tests/language/type_variable_field_initializer_test.dart b/tests/language/type_variable_field_initializer_test.dart
new file mode 100644
index 0000000..5519409
--- /dev/null
+++ b/tests/language/type_variable_field_initializer_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that an inlined field initializer has access to the enclosing
+// type variables.
+
+class A<T> {
+  var c = new List<T>();
+}
+
+class B<T> extends A<T> {
+}
+
+main() {
+  Expect.isTrue(new B<int>().c is List<int>);
+  Expect.isFalse(new B<String>().c is List<int>);
+}
diff --git a/tests/language/type_vm_test.dart b/tests/language/type_vm_test.dart
index 1b82769..7b525a1 100644
--- a/tests/language/type_vm_test.dart
+++ b/tests/language/type_vm_test.dart
@@ -34,7 +34,7 @@
       return 0;
     }
     try {
-      List<int> a = new List<int>.fixedLength(1);
+      List<int> a = new List<int>(1);
       a[0] = 0;
       a[index()]++;  // Type check succeeds, but does not create side effects.
       Expect.equals(1, a[0]);
@@ -377,7 +377,7 @@
   static int testListAssigment() {
     int result = 0;
     {
-      var a = new List.fixedLength(5);
+      var a = new List(5);
       List a0 = a;
       List<Object> ao = a;
       List<int> ai = a;
@@ -385,7 +385,7 @@
       List<String> as = a;
     }
     {
-      var a = new List<Object>.fixedLength(5);
+      var a = new List<Object>(5);
       List a0 = a;
       List<Object> ao = a;
       try {
@@ -438,7 +438,7 @@
       }
     }
     {
-      var a = new List<int>.fixedLength(5);
+      var a = new List<int>(5);
       List a0 = a;
       List<Object> ao = a;
       List<int> ai = a;
@@ -461,7 +461,7 @@
       }
     }
     {
-      var a = new List<num>.fixedLength(5);
+      var a = new List<num>(5);
       List a0 = a;
       List<Object> ao = a;
       try {
@@ -499,7 +499,7 @@
       }
     }
     {
-      var a = new List<String>.fixedLength(5);
+      var a = new List<String>(5);
       List a0 = a;
       List<Object> ao = a;
       try {
diff --git a/tests/language/typed_message_test.dart b/tests/language/typed_message_test.dart
index bda9814..4c23387 100644
--- a/tests/language/typed_message_test.dart
+++ b/tests/language/typed_message_test.dart
@@ -26,7 +26,7 @@
 
 main() {
   SendPort remote = spawnFunction(logMessages);
-  List<int> msg = new List<int>.fixedLength(5);
+  List<int> msg = new List<int>(5);
   for (int i = 0; i < 5; i++) {
     msg[i] = i;
   }
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart
index 43f083a..af4a5dd 100644
--- a/tests/lib/async/future_test.dart
+++ b/tests/lib/async/future_test.dart
@@ -53,8 +53,10 @@
 testComplete() {
   final completer = new Completer<int>();
   final future = completer.future;
+  Expect.isFalse(completer.isCompleted);
 
   completer.complete(3);
+  Expect.isTrue(completer.isCompleted);
 
   future.then((v) => Expect.equals(3, v));
 }
@@ -68,7 +70,10 @@
   int value;
   future.then((int v) { value = v; });
   Expect.isNull(value);
+
+  Expect.isFalse(completer.isCompleted);
   completer.complete(3);
+  Expect.isTrue(completer.isCompleted);
 
   Expect.equals(3, value);
 }
@@ -135,7 +140,10 @@
 
   var ex2;
   var done = future.catchError((e) { ex2 = e.error; });
+
+  Expect.isFalse(completer.isCompleted);
   completer.completeError(ex);
+  Expect.isTrue(completer.isCompleted);
 
   var port = new ReceivePort();
   done.then((_) {
@@ -153,7 +161,9 @@
   future.catchError((e) { });
   future.catchError((e) { reached = true; }, test: (e) => false)
         .catchError((e) {});
+  Expect.isFalse(completer.isCompleted);
   completer.completeError(ex);
+  Expect.isTrue(completer.isCompleted);
   Expect.isFalse(reached);
 }
 
diff --git a/tests/lib/async/futures_test.dart b/tests/lib/async/futures_test.dart
index 4e9becf..e694134 100644
--- a/tests/lib/async/futures_test.dart
+++ b/tests/lib/async/futures_test.dart
@@ -111,12 +111,13 @@
   futures.add(testWaitWithMultipleErrors());
   futures.add(testForEachEmpty());
   futures.add(testForEach());
+  futures.add(testForEachWithException());
 
   // Use a receive port for blocking the test.
   // Note that if the test fails, the program will not end.
   ReceivePort port = new ReceivePort();
   Future.wait(futures).then((List list) {
-    Expect.equals(8, list.length);
+    Expect.equals(9, list.length);
     port.close();
   });
 }
diff --git a/tests/lib/async/slow_consumer2_test.dart b/tests/lib/async/slow_consumer2_test.dart
index 0c637c0..a040256 100644
--- a/tests/lib/async/slow_consumer2_test.dart
+++ b/tests/lib/async/slow_consumer2_test.dart
@@ -75,7 +75,7 @@
       listSize -= sentCount - targetCount;
       sentCount = targetCount;
     }
-    controller.add(new List.fixedLength(listSize));
+    controller.add(new List(listSize));
     int ms = listSize * 1000 ~/ bytesPerSecond;
     Duration duration = new Duration(milliseconds: ms);
     if (!controller.isPaused) new Timer(duration, send);
diff --git a/tests/lib/async/slow_consumer3_test.dart b/tests/lib/async/slow_consumer3_test.dart
index 24386ad..7f3794b 100644
--- a/tests/lib/async/slow_consumer3_test.dart
+++ b/tests/lib/async/slow_consumer3_test.dart
@@ -53,7 +53,7 @@
   int chunks = bytesTotal ~/ chunkSize;
   return new Stream.fromIterable(new Iterable.generate(chunks, (_) {
     // This assumes one byte per entry. In practice it will be more.
-    return new List<int>.fixedLength(chunkSize);
+    return new List<int>(chunkSize);
   }));
 }
 
diff --git a/tests/lib/async/slow_consumer_test.dart b/tests/lib/async/slow_consumer_test.dart
index 2d40658..9bc05bf 100644
--- a/tests/lib/async/slow_consumer_test.dart
+++ b/tests/lib/async/slow_consumer_test.dart
@@ -77,7 +77,7 @@
       listSize -= sentCount - targetCount;
       sentCount = targetCount;
     }
-    controller.add(new List.fixedLength(listSize));
+    controller.add(new List(listSize));
     int ms = listSize * 1000 ~/ bytesPerSecond;
     Duration duration = new Duration(milliseconds: ms);
     if (!controller.isPaused) {
diff --git a/tests/lib/async/stream_controller_test.dart b/tests/lib/async/stream_controller_test.dart
index 8cfabf5..9593e96 100644
--- a/tests/lib/async/stream_controller_test.dart
+++ b/tests/lib/async/stream_controller_test.dart
@@ -392,8 +392,22 @@
   Expect.listEquals(expectedEvents.events, actualEvents.events);
 }
 
+testClosed() {
+  for (StreamController c in [new StreamController(),
+                              new StreamController.broadcast()]) {
+    Expect.isFalse(c.isClosed);
+    c.add(42);
+    Expect.isFalse(c.isClosed);
+    c.signalError("bad");
+    Expect.isFalse(c.isClosed);
+    c.close();
+    Expect.isTrue(c.isClosed);
+  }
+}
+
 main() {
   testMultiController();
   testSingleController();
   testExtraMethods();
+  testClosed();
 }
diff --git a/tests/lib/async/stream_state_helper.dart b/tests/lib/async/stream_state_helper.dart
new file mode 100644
index 0000000..86d71a1
--- /dev/null
+++ b/tests/lib/async/stream_state_helper.dart
@@ -0,0 +1,291 @@
+// 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 stream_state_helper;
+
+import "../../../pkg/unittest/lib/unittest.dart";
+import "dart:async";
+import "dart:collection";
+
+class StreamProtocolTest {
+  StreamController _controller;
+  StreamSubscription _subscription;
+  List<Event> _expectations = new List<Event>();
+  int _nextExpectationIndex = 0;
+  Function _onComplete;
+
+  StreamProtocolTest([bool broadcast = false]) {
+    if (broadcast) {
+     _controller = new StreamController.broadcast(
+          onPauseStateChange: _onPause,
+          onSubscriptionStateChange: _onSubcription);
+     // TODO(lrn): Make it work with multiple subscribers too.
+    } else {
+     _controller = new StreamController(
+          onPauseStateChange: _onPause,
+          onSubscriptionStateChange: _onSubcription);
+    }
+    _onComplete = expectAsync0((){
+      _onComplete = null;  // Being null marks the test to be complete.
+    });
+  }
+
+  // Actions on the stream and controller.
+  void add(var data) { _controller.add(data); }
+  void error(var error) { _controller.signalError(error); }
+  void close() { _controller.close(); }
+
+  void subscribe({bool unsubscribeOnError : false}) {
+    // TODO(lrn): Handle more subscriptions (e.g., a subscription-id
+    // per subscription, and an id on event _expectations).
+    if (_subscription != null) throw new StateError("Already subscribed");
+    _subscription = _controller.stream.listen(_onData,
+                                              onError: _onError,
+                                              onDone: _onDone,
+                                              unsubscribeOnError:
+                                                  unsubscribeOnError);
+  }
+
+  void pause([Future resumeSignal]) {
+    if (_subscription == null) throw new StateError("Not subscribed");
+    _subscription.pause(resumeSignal);
+  }
+
+  void resume([Future resumeSignal]) {
+    if (_subscription == null) throw new StateError("Not subscribed");
+    _subscription.resume();
+  }
+
+  void cancel() {
+    if (_subscription == null) throw new StateError("Not subscribed");
+    _subscription.cancel();
+    _subscription = null;
+  }
+
+  // Handling of stream events.
+  void _onData(var data) {
+    _withNextExpectation((Event expect) {
+      if (!expect.matchData(data)) {
+        _fail("Expected: $expect\n"
+              "Found   : [Data: $data]");
+      }
+    });
+  }
+
+  void _onError(AsyncError error) {
+    _withNextExpectation((Event expect) {
+      if (!expect.matchError(error)) {
+        _fail("Expected: $expect\n"
+              "Found   : [Data: ${error.error}]");
+      }
+    });
+  }
+
+  void _onDone() {
+    _subscription = null;
+    _withNextExpectation((Event expect) {
+      if (!expect.matchDone()) {
+        _fail("Expected: $expect\n"
+              "Found   : [Done]");
+      }
+    });
+  }
+
+  void _onPause() {
+    _withNextExpectation((Event expect) {
+      if (!expect.matchPauseChange(_controller)) {
+        _fail("Expected: $expect\n"
+              "Found   : [Paused:${_controller.isPaused}]");
+      }
+    });
+  }
+
+  void _onSubcription() {
+    _withNextExpectation((Event expect) {
+      if (!expect.matchSubscriptionChange(_controller)) {
+        _fail("Expected: $expect\n"
+              "Found: [Subscribed:${_controller.hasSubscribers}, "
+                      "Paused:${_controller.isPaused}]");
+      }
+    });
+  }
+
+  void _withNextExpectation(void action(Event expect)) {
+    if (_nextExpectationIndex == _expectations.length) {
+      action(new MismatchEvent());
+    } else {
+      Event next = _expectations[_nextExpectationIndex++];
+      action(next);
+    }
+    _checkDone();
+  }
+
+  void _checkDone() {
+    if (_nextExpectationIndex == _expectations.length) {
+      _onComplete();
+    }
+  }
+
+
+  // Adds _expectations.
+  void expectAny([void action()]) {
+    if (_onComplete == null) {
+      _fail("Adding expectation after completing");
+    }
+    _expectations.add(new LogAnyEvent(action));
+  }
+  void expectData(var data, [void action()]) {
+    if (_onComplete == null) {
+      _fail("Adding expectation after completing");
+    }
+    _expectations.add(new DataEvent(data, action));
+  }
+  void expectError(var error, [void action()]) {
+    if (_onComplete == null) {
+      _fail("Adding expectation after completing");
+    }
+    _expectations.add(new ErrorEvent(error, action));
+  }
+  void expectDone([void action()]) {
+    if (_onComplete == null) {
+      _fail("Adding expectation after completing");
+    }
+    _expectations.add(new DoneEvent(action));
+  }
+  void expectPause(bool isPaused, [void action()]) {
+    if (_onComplete == null) {
+      _fail("Adding expectation after completing");
+    }
+    _expectations.add(new PauseCallbackEvent(isPaused, action));
+  }
+  void expectSubscription(bool hasSubscribers, bool isPaused, [void action()]) {
+    if (_onComplete == null) {
+      _fail("Adding expectation after completing");
+    }
+    _expectations.add(
+          new SubscriptionCallbackEvent(hasSubscribers, isPaused, action));
+  }
+
+  void _fail(String message) {
+    if (_nextExpectationIndex == 0) {
+      throw "Unexpected event:\n$message\nNo earlier events matched.";
+    }
+    throw "Unexpected event:\n$message\nMatched so far:\n"
+          " ${_expectations.take(_nextExpectationIndex).join("\n ")}";
+  }
+}
+
+class EventCollector {
+  final Queue<Event> events = new Queue<Event>();
+
+}
+
+class Event {
+  Function _action;
+  Event(void this._action());
+
+  bool matchData(var data) {
+    if (!_testData(data)) return false;
+    if (_action != null) _action();
+    return true;
+  }
+  bool matchError(AsyncError e) {
+    if (!_testError(e)) return false;
+    if (_action != null) _action();
+    return true;
+  }
+  bool matchDone() {
+    if (!_testDone()) return false;
+    if (_action != null) _action();
+    return true;
+  }
+  bool matchPauseChange(StreamController c) {
+    if (!_testPause(c)) return false;
+    if (_action != null) _action();
+    return true;
+  }
+  bool matchSubscriptionChange(StreamController c) {
+    if (!_testSubscribe(c)) return false;
+    if (_action != null) _action();
+    return true;
+  }
+
+  bool _testData(_) => false;
+  bool _testError(_) => false;
+  bool _testDone() => false;
+  bool _testPause(_) => false;
+  bool _testSubscribe(_) => false;
+}
+
+class MismatchEvent extends Event {
+  MismatchEvent() : super(null);
+  toString() => "[No event expected]";
+}
+
+class DataEvent extends Event {
+  final data;
+  DataEvent(this.data, void action()) : super(action);
+  bool _testData(var data) => this.data == data;
+  String toString() => "[Data: $data]";
+}
+
+class ErrorEvent extends Event {
+  final error;
+  ErrorEvent(this.error, void action()) : super(action);
+  bool _testError(AsyncError error) => this.error == error.error;
+  String toString() => "[Error: $error]";
+}
+
+class DoneEvent extends Event {
+  DoneEvent(void action()) : super(action);
+  bool _testDone() => true;
+  String toString() => "[Done]";
+}
+
+class PauseCallbackEvent extends Event {
+  final bool isPaused;
+  PauseCallbackEvent(this.isPaused, void action())
+      : super(action);
+  bool _testPause(StreamController c) => isPaused == c.isPaused;
+  String toString() => "[Paused:$isPaused]";
+}
+
+class SubscriptionCallbackEvent extends Event {
+  final bool hasSubscribers;
+  final bool isPaused;
+  SubscriptionCallbackEvent(this.hasSubscribers, this.isPaused, void action())
+      : super(action);
+  bool _testSubscribe(StreamController c) {
+    return hasSubscribers == c.hasSubscribers && isPaused == c.isPaused;
+  }
+  String toString() => "[Subscribers:$hasSubscribers, Paused:$isPaused]";
+}
+
+
+class LogAnyEvent extends Event {
+  String _actual = "*Not matched yet*";
+  LogAnyEvent(void action()) : super(action);
+  bool _testData(var data) {
+    _actual = "*[Data $data]";
+    return true;
+  }
+  bool _testError(AsyncError error) {
+    _actual = "*[Error ${error.error}]";
+    return true;
+  }
+  bool _testDone() {
+    _actual = "*[Done]";
+    return true;
+  }
+  bool _testPause(StreamController c) {
+    _actual = "*[Paused:${c.isPaused}]";
+    return true;
+  }
+  bool _testSubcribe(StreamController c) {
+    _actual = "*[Subscribers:${c.hasSubscribers}, Paused:${c.isPaused}]";
+    return true;
+  }
+
+  String toString() => _actual;
+}
diff --git a/tests/lib/async/stream_state_nonzero_timer_test.dart b/tests/lib/async/stream_state_nonzero_timer_test.dart
new file mode 100644
index 0000000..d05f9fa
--- /dev/null
+++ b/tests/lib/async/stream_state_nonzero_timer_test.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.
+
+// Test the event/callback protocol of the stream implementations.
+// Uses a non-zero timer so it fails on d8.
+
+library stream_state_nonzero_timer_test;
+
+import "dart:async";
+import "../../../pkg/unittest/lib/unittest.dart";
+import "stream_state_helper.dart";
+
+const ms5 = const Duration(milliseconds: 5);
+
+main() {
+  mainTest(false);
+  mainTest(true);
+}
+
+mainTest(bool broadcast) {
+  var p = broadcast ? "BC" : "SC";
+
+  test("$p-sub-data/pause/resume/pause/resume-done", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+         t.pause();
+       })
+     ..expectPause(true, () { t.resume(); })
+     ..expectPause(false, () { t.pause(); })
+     ..expectPause(true, () { t.resume(); })
+     ..expectPause(false, () { t.close(); })
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()..add(42);
+  });
+
+  test("$p-sub-data/pause-done", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+         t.pause(new Future.delayed(ms5, () => null));
+       })
+     ..expectPause(true)
+     ..expectDone()
+     ..expectSubscription(false, false);
+     // We are calling "close" while the controller is actually paused,
+     // and it will stay paused until the pending events are sent.
+    t..subscribe()..add(42)..close();
+  });
+
+  test("$p-sub-data/pause-resume/done", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+         t.pause(new Future.delayed(ms5, () => null));
+       })
+     ..expectPause(true)
+     ..expectPause(false, () { t.close(); })
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()..add(42);
+  });
+
+  test("$p-sub-data/data+pause-data-resume-done", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+         t.add(43);
+         t.pause(new Future.delayed(ms5, () => null));
+         // Should now be paused until the future finishes.
+         // After that, the controller stays paused until the pending queue
+         // is empty.
+       })
+     ..expectPause(true)
+     ..expectData(43)
+     ..expectPause(false, () { t.close(); })
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()..add(42);
+  });
+
+  test("$p-pause-during-callback", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+       t.pause();
+     })
+     ..expectPause(true, () {
+       t.resume();
+     })
+     ..expectPause(false, () {
+       t.pause();
+       t.resume();
+       t.close();
+     })
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()
+     ..add(42);
+  });
+}
diff --git a/tests/lib/async/stream_state_test.dart b/tests/lib/async/stream_state_test.dart
new file mode 100644
index 0000000..f27697b
--- /dev/null
+++ b/tests/lib/async/stream_state_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test the event/callback protocol of the stream implementations.
+library stream_state_test;
+
+import "../../../pkg/unittest/lib/unittest.dart";
+import "stream_state_helper.dart";
+
+const ms5 = const Duration(milliseconds: 5);
+
+main() {
+  mainTest(false);
+  mainTest(true);
+}
+
+mainTest(bool broadcast) {
+  var p = broadcast ? "BC" : "SC";
+  test("$p-sub-data-done", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42)
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()..add(42)..close();
+  });
+
+  test("$p-data-done-sub", () {
+    var t = new StreamProtocolTest(broadcast);
+    if (broadcast) {
+      t..expectDone();
+    } else {
+      t..expectSubscription(true, false)
+       ..expectData(42)
+       ..expectDone()
+       ..expectSubscription(false, false);
+    }
+    t..add(42)..close()..subscribe();
+  });
+
+  test("$p-sub-data/pause+resume-done", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+         t.pause();
+         t.resume();
+         t.close();
+       })
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()..add(42);
+  });
+
+  test("$p-sub-data-unsubonerror", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42)
+     ..expectError("bad")
+     ..expectSubscription(false, !broadcast);
+    t..subscribe(unsubscribeOnError: true)
+     ..add(42)
+     ..error("bad")
+     ..add(43)
+     ..close();
+  });
+
+  test("$p-sub-data-no-unsubonerror", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42)
+     ..expectError("bad")
+     ..expectData(43)
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe(unsubscribeOnError: false)
+     ..add(42)
+     ..error("bad")
+     ..add(43)
+     ..close();
+  });
+
+  test("$p-pause-resume-during-event", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+       t.pause();
+       t.resume();
+     })
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()
+     ..add(42)
+     ..close();
+  });
+
+  test("$p-cancel-sub-during-event", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+       t.cancel();
+       t.subscribe();
+     })
+     ..expectData(43)
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()
+     ..add(42)
+     ..add(43)
+     ..close();
+  });
+
+  test("$p-cancel-sub-during-callback", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectData(42, () {
+       t.pause();
+     })
+     ..expectPause(true, () {
+       t.cancel();  // Cancels pause
+       t.subscribe();
+     })
+     ..expectPause(false)
+     ..expectData(43)
+     ..expectDone()
+     ..expectSubscription(false, false);
+    t..subscribe()
+     ..add(42)
+     ..add(43)
+     ..close();
+  });
+
+  test("$p-sub-after-done-is-done", () {
+    var t = new StreamProtocolTest(broadcast);
+    t..expectSubscription(true, false)
+     ..expectDone()
+     ..expectSubscription(false, false)
+     ..expectDone();
+    t..subscribe()
+     ..close()
+     ..subscribe();  // Subscribe after done does not cause callbacks at all.
+  });
+}
diff --git a/tests/lib/async/stream_transform_test.dart b/tests/lib/async/stream_transform_test.dart
index 436c229..abd6f53 100644
--- a/tests/lib/async/stream_transform_test.dart
+++ b/tests/lib/async/stream_transform_test.dart
@@ -10,7 +10,7 @@
 
 
 main() {
-  // Regression tests for http://dartbug.com/8311
+  // Regression tests for http://dartbug.com/8310 and 8311
 
   test("simpleDone", () {
     StreamController c = new StreamController();
@@ -45,4 +45,17 @@
     input.replay(c);
     actual.resume();
   });
+
+  test("closing after done", () {
+    var controller = new StreamController();
+    var buffer = new StringBuffer();
+    controller.stream.map((e) => e).transform(new StreamTransformer(
+        handleData: (element, sink) { sink.add(element); },
+        handleDone: (sink) { sink.close(); })
+    ).listen(expectAsync1((e) => expect(e, equals("foo"))));
+
+    controller.add("foo");
+    // Should not crash.
+    controller.close();
+  });
 }
diff --git a/tests/lib/crypto/base64_test.dart b/tests/lib/crypto/base64_test.dart
index fdf24b9..0070a50 100644
--- a/tests/lib/crypto/base64_test.dart
+++ b/tests/lib/crypto/base64_test.dart
@@ -45,11 +45,11 @@
 
 void main() {
   for (var i = 0; i < inputs.length; i++) {
-    var enc = CryptoUtils.bytesToBase64(inputs[i].charCodes);
+    var enc = CryptoUtils.bytesToBase64(inputs[i].codeUnits);
     Expect.equals(results[i], enc);
   }
-  Expect.equals(CryptoUtils.bytesToBase64(longLine.charCodes, 76),
+  Expect.equals(CryptoUtils.bytesToBase64(longLine.codeUnits, 76),
                 longLineResult);
-  Expect.equals(CryptoUtils.bytesToBase64(longLine.charCodes),
+  Expect.equals(CryptoUtils.bytesToBase64(longLine.codeUnits),
                 longLineResultNoBreak);
 }
diff --git a/tests/lib/crypto/sha1_test.dart b/tests/lib/crypto/sha1_test.dart
index b9e9069..d977230 100644
--- a/tests/lib/crypto/sha1_test.dart
+++ b/tests/lib/crypto/sha1_test.dart
@@ -11,7 +11,7 @@
 part 'sha1_short_test_vectors.dart';
 
 List<int> createTestArr(int len) {
-  var arr = new List<int>.fixedLength(len);
+  var arr = new List<int>(len);
   for (var i = 0; i < len; i++) {
     arr[i] = i;
   }
diff --git a/tests/lib/crypto/sha256_test.dart b/tests/lib/crypto/sha256_test.dart
index 62a8dc9..767812a 100644
--- a/tests/lib/crypto/sha256_test.dart
+++ b/tests/lib/crypto/sha256_test.dart
@@ -11,7 +11,7 @@
 part 'sha256_short_test_vectors.dart';
 
 List<int> createTestArr(int len) {
-  var arr = new List<int>.fixedLength(len);
+  var arr = new List<int>(len);
   for (var i = 0; i < len; i++) {
     arr[i] = i;
   }
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 73efcec..52f322a 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -17,6 +17,7 @@
 async/slow_consumer3_test: Fail # Timer interface not supported; dartbug.com/7728.
 async/slow_consumer_test: Fail # Timer interface not supported; dartbug.com/7728.
 async/stream_from_iterable_test: Fail # Timer interface not supported; dartbug.com/7728.
+async/stream_state_nonzero_timer_test: Fail # Timer interface not supported; dartbug.com/7728.
 
 [ $compiler == dart2js && $browser ]
 crypto/sha256_test: Slow, Pass
diff --git a/tests/standalone/crypto/base64_test.dart b/tests/standalone/crypto/base64_test.dart
index a20fd20..36546d4 100644
--- a/tests/standalone/crypto/base64_test.dart
+++ b/tests/standalone/crypto/base64_test.dart
@@ -24,13 +24,13 @@
       "Rpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo\r\n"
       "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm"
       "5hbCBwbGVhc3VyZS4=";
-  Expect.equals(expected, _Base64._encode(line.charCodes));
-  Expect.listEquals(line.charCodes, _Base64._decode(expected));
+  Expect.equals(expected, _Base64._encode(line.codeUnits));
+  Expect.listEquals(line.codeUnits, _Base64._decode(expected));
 
   line = "Simple string";
   expected = "U2ltcGxlIHN0cmluZw==";
-  Expect.equals(expected, _Base64._encode(line.charCodes));
-  Expect.listEquals(line.charCodes, _Base64._decode(expected));
+  Expect.equals(expected, _Base64._encode(line.codeUnits));
+  Expect.listEquals(line.codeUnits, _Base64._decode(expected));
 
   for (int i = 0; i < 256; i++) {
     List<int> x = [i];
diff --git a/tests/standalone/io/dart_std_io_pipe_test.dart b/tests/standalone/io/dart_std_io_pipe_test.dart
index a4d4f24..325e41b 100644
--- a/tests/standalone/io/dart_std_io_pipe_test.dart
+++ b/tests/standalone/io/dart_std_io_pipe_test.dart
@@ -23,7 +23,7 @@
 void checkFileContent(String fileName, String content) {
   RandomAccessFile pipeOut  = new File(fileName).openSync();
   int length = pipeOut.lengthSync();
-  List data = new List<int>.fixedLength(length);
+  List data = new List<int>(length);
   pipeOut.readListSync(data, 0, length);
   Expect.equals(content, new String.fromCharCodes(data));
   pipeOut.closeSync();
@@ -97,7 +97,7 @@
   }
 
   // Run the shell script.
-  test(shellScript.name, scriptFile.name, "0");
-  test(shellScript.name, scriptFile.name, "1");
-  test(shellScript.name, scriptFile.name, "2");
+  test(shellScript.path, scriptFile.path, "0");
+  test(shellScript.path, scriptFile.path, "1");
+  test(shellScript.path, scriptFile.path, "2");
 }
diff --git a/tests/standalone/io/directory_error_test.dart b/tests/standalone/io/directory_error_test.dart
index 950f025..6a8ebe9 100644
--- a/tests/standalone/io/directory_error_test.dart
+++ b/tests/standalone/io/directory_error_test.dart
@@ -170,7 +170,7 @@
   File f = new File("${temp.path}/file");
   var newPath = "${temp.path}/file2";
   f.createSync();
-  var d = new Directory(f.name);
+  var d = new Directory(f.path);
   Expect.throws(() => d.renameSync(newPath),
                 (e) => e is DirectoryIOException);
   var renameDone = d.rename(newPath);
diff --git a/tests/standalone/io/directory_test.dart b/tests/standalone/io/directory_test.dart
index 0d6500e..47a7b38 100644
--- a/tests/standalone/io/directory_test.dart
+++ b/tests/standalone/io/directory_test.dart
@@ -27,9 +27,9 @@
     void testSyncListing(bool recursive) {
       for (var entry in directory.listSync(recursive: recursive)) {
         if (entry is File) {
-          Expect.isTrue(entry.name.contains(directory.path));
-          Expect.isTrue(entry.name.contains('subdir'));
-          Expect.isTrue(entry.name.contains('file.txt'));
+          Expect.isTrue(entry.path.contains(directory.path));
+          Expect.isTrue(entry.path.contains('subdir'));
+          Expect.isTrue(entry.path.contains('file.txt'));
           Expect.isFalse(listedFile);
           listedFile = true;
         } else {
@@ -54,7 +54,7 @@
     directory.list(recursive: true).listen(
         (FileSystemEntity entity) {
           if (entity is File) {
-            var path = entity.name;
+            var path = entity.path;
             listedFile = true;
             Expect.isTrue(path.contains(directory.path));
             Expect.isTrue(path.contains('subdir'));
diff --git a/tests/standalone/io/echo_server_stream_test.dart b/tests/standalone/io/echo_server_stream_test.dart
index 3a59aba..b3a1868 100644
--- a/tests/standalone/io/echo_server_stream_test.dart
+++ b/tests/standalone/io/echo_server_stream_test.dart
@@ -24,7 +24,7 @@
   EchoServerGame.start()
       : _receivePort = new ReceivePort(),
         _sendPort = null,
-        _buffer = new List<int>.fixedLength(MSGSIZE),
+        _buffer = new List<int>(MSGSIZE),
         _messages = 0 {
     for (int i = 0; i < MSGSIZE; i++) {
       _buffer[i] = FIRSTCHAR + i;
@@ -65,7 +65,7 @@
                      onDone: onClosed);
       _socket.add(_buffer);
       _socket.close();
-      data = new List<int>.fixedLength(MSGSIZE);
+      data = new List<int>(MSGSIZE);
     }
 
     Socket.connect(TestingServer.HOST, _port).then((s) {
@@ -107,7 +107,7 @@
   static const int MSGSIZE = EchoServerGame.MSGSIZE;
 
   void onConnection(Socket connection) {
-    List<int> buffer = new List<int>.fixedLength(MSGSIZE);
+    List<int> buffer = new List<int>(MSGSIZE);
     int offset = 0;
 
     void dataReceived(List<int> data) {
diff --git a/tests/standalone/io/file_input_stream_test.dart b/tests/standalone/io/file_input_stream_test.dart
index 4e2e2c4..e9de0c5 100644
--- a/tests/standalone/io/file_input_stream_test.dart
+++ b/tests/standalone/io/file_input_stream_test.dart
@@ -36,7 +36,7 @@
   var keepAlive = new ReceivePort();
   String fileName = getFilename("tests/standalone/io/readuntil_test.dat");
   // File contains "Hello Dart\nwassup!\n"
-  var expected = "Hello Dart\nwassup!\n".charCodes;
+  var expected = "Hello Dart\nwassup!\n".codeUnits;
   var byteCount = 0;
   (new File(fileName)).openRead().listen(
       (d) => byteCount += d.length,
@@ -95,7 +95,6 @@
       });
 }
 
-
 void testInputStreamDelete() {
   var keepAlive = new ReceivePort();
   var temp = new Directory('').createTempSync();
diff --git a/tests/standalone/io/file_invalid_arguments_test.dart b/tests/standalone/io/file_invalid_arguments_test.dart
index 4be142a..26c9557 100644
--- a/tests/standalone/io/file_invalid_arguments_test.dart
+++ b/tests/standalone/io/file_invalid_arguments_test.dart
@@ -144,10 +144,10 @@
 main() {
   testReadInvalidArgs('asdf');
   testReadListInvalidArgs(12, 0, 1);
-  testReadListInvalidArgs(new List.fixedLength(10), '0', 1);
-  testReadListInvalidArgs(new List.fixedLength(10), 0, '1');
+  testReadListInvalidArgs(new List(10), '0', 1);
+  testReadListInvalidArgs(new List(10), 0, '1');
   testWriteByteInvalidArgs('asdf');
   testWriteListInvalidArgs(12, 0, 1);
-  testWriteListInvalidArgs(new List.fixedLength(10), '0', 1);
-  testWriteListInvalidArgs(new List.fixedLength(10), 0, '1');
+  testWriteListInvalidArgs(new List(10), '0', 1);
+  testWriteListInvalidArgs(new List(10), 0, '1');
 }
diff --git a/tests/standalone/io/file_system_links_test.dart b/tests/standalone/io/file_system_links_test.dart
index 90e9692..652bf78 100644
--- a/tests/standalone/io/file_system_links_test.dart
+++ b/tests/standalone/io/file_system_links_test.dart
@@ -66,7 +66,7 @@
   var y = '${temp.path}${Platform.pathSeparator}y';
   new File(x).createSync();
   createLink(x, y, true, () {
-    var data = "asdf".charCodes;
+    var data = "asdf".codeUnits;
     var output = new File(y).openWrite(FileMode.WRITE);
     output.add(data);
     output.close();
@@ -131,7 +131,7 @@
     var dirs = [];
     for (var entry in temp.listSync(recursive:true)) {
       if (entry is File) {
-        files.add(entry.name);
+        files.add(entry.path);
       } else {
         Expect.isTrue(entry is Directory);
         dirs.add(entry.path);
@@ -147,7 +147,7 @@
     var lister = temp.list(recursive: true).listen(
         (entity) {
           if (entity is File) {
-            files.add(entity.name);
+            files.add(entity.path);
           } else {
             Expect.isTrue(entity is Directory);
             dirs.add(entity.path);
@@ -182,7 +182,7 @@
     temp.list(recursive: true).listen(
         (entity) {
           if (entity is File) {
-            files.add(entity.name);
+            files.add(entity.path);
           } else {
             Expect.isTrue(entity is Directory);
             dirs.add(entity.path);
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
index a8daa32..6f97138 100644
--- a/tests/standalone/io/file_test.dart
+++ b/tests/standalone/io/file_test.dart
@@ -45,7 +45,7 @@
     // Read a file and check part of it's contents.
     String filename = getFilename("bin/file_test.cc");
     File file = new File(filename);
-    Expect.isTrue('$file'.contains(file.name));
+    Expect.isTrue('$file'.contains(file.path));
     var subscription;
     List<int> buffer = new List<int>();
     subscription = file.openRead().listen(
@@ -121,7 +121,7 @@
     asyncTestStarted();
 
     // Create the test data - arbitrary binary data.
-    List<int> buffer = new List<int>.fixedLength(100000);
+    List<int> buffer = new List<int>(100000);
     for (var i = 0; i < buffer.length; ++i) {
       buffer[i] = i % 256;
     }
@@ -172,7 +172,7 @@
   }
 
   static Future testPipe(File file, buffer) {
-    String outputFilename = '${file.name}_copy';
+    String outputFilename = '${file.path}_copy';
     File outputFile = new File(outputFilename);
     var input = file.openRead();
     var output = outputFile.openWrite();
@@ -201,7 +201,7 @@
     String filename = getFilename("bin/file_test.cc");
     File file = new File(filename);
     file.open(FileMode.READ).then((RandomAccessFile file) {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       file.readList(buffer, 0, 5).then((bytes_read) {
         Expect.equals(5, bytes_read);
         file.readList(buffer, 5, 5).then((bytes_read) {
@@ -225,12 +225,12 @@
   static void testReadSync() {
     // Read a file and check part of it's contents.
     String filename = getFilename("bin/file_test.cc");
-    RandomAccessFile file = (new File(filename)).openSync();
-    List<int> buffer = new List<int>.fixedLength(42);
+    RandomAccessFile raf = (new File(filename)).openSync();
+    List<int> buffer = new List<int>(42);
     int bytes_read = 0;
-    bytes_read = file.readListSync(buffer, 0, 12);
+    bytes_read = raf.readListSync(buffer, 0, 12);
     Expect.equals(12, bytes_read);
-    bytes_read = file.readListSync(buffer, 12, 30);
+    bytes_read = raf.readListSync(buffer, 12, 30);
     Expect.equals(30, bytes_read);
     Expect.equals(47, buffer[0]);  // represents '/' in the file.
     Expect.equals(47, buffer[1]);  // represents '/' in the file.
@@ -244,6 +244,17 @@
     Expect.equals(103, buffer[9]);  // represents 'g' in the file.
     Expect.equals(104, buffer[10]);  // represents 'h' in the file.
     Expect.equals(116, buffer[11]);  // represents 't' in the file.
+
+    filename = getFilename("tests/vm/data/fixed_length_file");
+    File file = new File(filename);
+    int len = file.lengthSync();
+    Expect.equals(0, file.openSync().readSync(0).length);
+    Expect.equals(1, file.openSync().readSync(1).length);
+    Expect.equals(len - 1, file.openSync().readSync(len - 1).length);
+    Expect.equals(len, file.openSync().readSync(len).length);
+    Expect.equals(len, file.openSync().readSync(len + 1).length);
+    Expect.equals(len, file.openSync().readSync(len * 2).length);
+    Expect.equals(len, file.openSync().readSync(len * 10).length);
   }
 
   // Test for file read and write functionality.
@@ -252,7 +263,7 @@
     String inFilename = getFilename("tests/vm/data/fixed_length_file");
     final File file = new File(inFilename);
     file.open(FileMode.READ).then((openedFile) {
-      List<int> buffer1 = new List<int>.fixedLength(42);
+      List<int> buffer1 = new List<int>(42);
       openedFile.readList(buffer1, 0, 42).then((bytes_read) {
         Expect.equals(42, bytes_read);
         openedFile.close().then((ignore) {
@@ -268,7 +279,7 @@
               file2.open(FileMode.WRITE).then((openedFile2) {
                 openedFile2.writeList(buffer1, 0, bytes_read).then((ignore) {
                   openedFile2.close().then((ignore) {
-                    List<int> buffer2 = new List<int>.fixedLength(bytes_read);
+                    List<int> buffer2 = new List<int>(bytes_read);
                     final File file3 = new File(outFilename);
                     file3.open(FileMode.READ).then((openedFile3) {
                       openedFile3.readList(buffer2, 0, 42).then((bytes_read) {
@@ -308,7 +319,7 @@
     File file = new File(filename);
     file.createSync();
     Expect.isTrue(new File(filename).existsSync());
-    List<int> buffer = content.charCodes;
+    List<int> buffer = content.codeUnits;
     RandomAccessFile openedFile = file.openSync(FileMode.WRITE);
     openedFile.writeListSync(buffer, 0, buffer.length);
     openedFile.closeSync();
@@ -331,7 +342,7 @@
     String filename = tempDirectory.path.concat("/outstream_write_append");
     File file = new File(filename);
     file.createSync();
-    List<int> buffer = content.charCodes;
+    List<int> buffer = content.codeUnits;
     var output = file.openWrite();
     output.add(buffer);
     output.close();
@@ -363,7 +374,7 @@
     String filename = tempDirectory.path.concat("/outstream_write_string");
     File file = new File(filename);
     file.createSync();
-    List<int> buffer = content.charCodes;
+    List<int> buffer = content.codeUnits;
     var output = file.openWrite();
     output.addString("abcdABCD");
     output.addString("abcdABCD", Encoding.UTF_8);
@@ -386,7 +397,7 @@
     // Read a file.
     String inFilename = getFilename("tests/vm/data/fixed_length_file");
     RandomAccessFile file = (new File(inFilename)).openSync();
-    List<int> buffer1 = new List<int>.fixedLength(42);
+    List<int> buffer1 = new List<int>(42);
     int bytes_read = 0;
     int bytes_written = 0;
     bytes_read = file.readListSync(buffer1, 0, 42);
@@ -405,7 +416,7 @@
     openedFile.writeListSync(buffer1, 0, bytes_read);
     openedFile.closeSync();
     // Now read the contents of the file just written.
-    List<int> buffer2 = new List<int>.fixedLength(bytes_read);
+    List<int> buffer2 = new List<int>(bytes_read);
     openedFile = (new File(outFilename)).openSync();
     bytes_read = openedFile.readListSync(buffer2, 0, 42);
     Expect.equals(42, bytes_read);
@@ -473,7 +484,7 @@
             var openedFile2 = file2.openSync();
             var length = openedFile2.lengthSync();
             Expect.equals(8, length);
-            List data = new List.fixedLength(length);
+            List data = new List(length);
             openedFile2.readListSync(data, 0, length);
             for (var i = 0; i < data.length; i++) {
               Expect.equals(i, data[i]);
@@ -577,7 +588,7 @@
     RandomAccessFile input = (new File(filename)).openSync();
     input.position().then((position) {
       Expect.equals(0, position);
-      List<int> buffer = new List<int>.fixedLength(100);
+      List<int> buffer = new List<int>(100);
       input.readList(buffer, 0, 12).then((bytes_read) {
         input.position().then((position) {
           Expect.equals(12, position);
@@ -601,7 +612,7 @@
     String filename = getFilename("tests/vm/data/fixed_length_file");
     RandomAccessFile input = (new File(filename)).openSync();
     Expect.equals(0, input.positionSync());
-    List<int> buffer = new List<int>.fixedLength(100);
+    List<int> buffer = new List<int>(100);
     input.readListSync(buffer, 0, 12);
     Expect.equals(12, input.positionSync());
     input.readListSync(buffer, 12, 6);
@@ -688,7 +699,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(100);
+      List<int> buffer = new List<int>(100);
       openedFile.readListSync(buffer, 0, 10);
     } on FileIOException catch (ex) {
       exceptionCaught = true;
@@ -699,7 +710,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(100);
+      List<int> buffer = new List<int>(100);
       openedFile.writeListSync(buffer, 0, 10);
     } on FileIOException catch (ex) {
       exceptionCaught = true;
@@ -744,7 +755,7 @@
   // Tests stream exception handling after file was closed.
   static void testCloseExceptionStream() {
     asyncTestStarted();
-    List<int> buffer = new List<int>.fixedLength(42);
+    List<int> buffer = new List<int>(42);
     File file =
         new File(tempDirectory.path.concat("/out_close_exception_stream"));
     file.createSync();
@@ -765,7 +776,7 @@
         new File(tempDirectory.path.concat("/out_buffer_out_of_bounds"));
     RandomAccessFile openedFile = file.openSync(FileMode.WRITE);
     try {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       openedFile.readListSync(buffer, 0, 12);
     } on RangeError catch (ex) {
       exceptionCaught = true;
@@ -776,7 +787,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       openedFile.readListSync(buffer, 6, 6);
     } on RangeError catch (ex) {
       exceptionCaught = true;
@@ -787,7 +798,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       openedFile.readListSync(buffer, -1, 1);
     } on RangeError catch (ex) {
       exceptionCaught = true;
@@ -798,7 +809,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       openedFile.readListSync(buffer, 0, -1);
     } on RangeError catch (ex) {
       exceptionCaught = true;
@@ -809,7 +820,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       openedFile.writeListSync(buffer, 0, 12);
     } on RangeError catch (ex) {
       exceptionCaught = true;
@@ -820,7 +831,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       openedFile.writeListSync(buffer, 6, 6);
     } on RangeError catch (ex) {
       exceptionCaught = true;
@@ -831,7 +842,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       openedFile.writeListSync(buffer, -1, 1);
     } on RangeError catch (ex) {
       exceptionCaught = true;
@@ -842,7 +853,7 @@
     Expect.equals(true, !wrongExceptionCaught);
     exceptionCaught = false;
     try {
-      List<int> buffer = new List<int>.fixedLength(10);
+      List<int> buffer = new List<int>(10);
       openedFile.writeListSync(buffer, 0, -1);
     } on RangeError catch (ex) {
       exceptionCaught = true;
@@ -940,11 +951,11 @@
       f.readAsString(Encoding.UTF_8).then((text) {
         Expect.equals(6, text.length);
         var expected = [955, 120, 46, 32, 120, 10];
-        Expect.listEquals(expected, text.charCodes);
+        Expect.listEquals(expected, text.codeUnits);
         f.readAsString(Encoding.ISO_8859_1).then((text) {
           Expect.equals(7, text.length);
           var expected = [206, 187, 120, 46, 32, 120, 10];
-          Expect.listEquals(expected, text.charCodes);
+          Expect.listEquals(expected, text.codeUnits);
           var readAsStringFuture = f.readAsString(Encoding.ASCII);
           readAsStringFuture.then((text) {
             Expect.fail("Non-ascii char should cause error");
@@ -979,15 +990,15 @@
     text = new File(name).readAsStringSync();
     Expect.equals(6, text.length);
     var expected = [955, 120, 46, 32, 120, 10];
-    Expect.listEquals(expected, text.charCodes);
+    Expect.listEquals(expected, text.codeUnits);
     text = new File(name).readAsStringSync(Encoding.ASCII);
     // Default replacement character is '?', char code 63.
     expected = [63, 63, 120, 46, 32, 120, 10];
-    Expect.listEquals(expected, text.charCodes);
+    Expect.listEquals(expected, text.codeUnits);
     text = new File(name).readAsStringSync(Encoding.ISO_8859_1);
     expected = [206, 187, 120, 46, 32, 120, 10];
     Expect.equals(7, text.length);
-    Expect.listEquals(expected, text.charCodes);
+    Expect.listEquals(expected, text.codeUnits);
   }
 
   static void testReadAsTextSyncEmptyFile() {
diff --git a/tests/standalone/io/http_10_test.dart b/tests/standalone/io/http_10_test.dart
new file mode 100644
index 0000000..a923562
--- /dev/null
+++ b/tests/standalone/io/http_10_test.dart
@@ -0,0 +1,212 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:isolate";
+import "dart:io";
+
+// Client makes a HTTP 1.0 request without connection keep alive. The
+// server sets a content length but still needs to close the
+// connection as there is no keep alive.
+void testHttp10NoKeepAlive() {
+  HttpServer.bind().then((server) {
+    server.listen(
+        (HttpRequest request) {
+          Expect.isNull(request.headers.value('content-length'));
+          Expect.equals(-1, request.contentLength);
+          var response = request.response;
+          response.contentLength = 1;
+          Expect.equals("1.0", request.protocolVersion);
+          response.done
+              .then((_) => Expect.fail("Unexpected response completion"))
+              .catchError((e) => Expect.isTrue(e.error is HttpException));
+          response.addString("Z");
+          response.addString("Z");
+          response.close();
+          Expect.throws(() => response.addString("x"),
+                        (e) => e is StateError);
+        },
+        onError: (e) => Expect.fail("Unexpected error $e"));
+
+    int count = 0;
+    makeRequest() {
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+          socket.addString("GET / HTTP/1.0\r\n\r\n");
+
+          List<int> response = [];
+          socket.listen(
+              response.addAll,
+              onDone: () {
+                count++;
+                socket.destroy();
+                String s = new String.fromCharCodes(response).toLowerCase();
+                Expect.equals("z", s[s.length - 1]);
+                Expect.isTrue(s.indexOf("\r\ncontent-length: 1\r\n") > 0);
+                Expect.equals(-1, s.indexOf("keep-alive"));
+                if (count < 10) {
+                  makeRequest();
+                } else {
+                  server.close();
+                }
+              });
+        });
+    }
+    makeRequest();
+  });
+}
+
+
+// Client makes a HTTP 1.0 request and the server does not set a
+// content length so it has to close the connection to mark the end of
+// the response.
+void testHttp10ServerClose() {
+  HttpServer.bind().then((server) {
+    server.listen(
+        (HttpRequest request) {
+          Expect.isNull(request.headers.value('content-length'));
+          Expect.equals(-1, request.contentLength);
+          var response = request.response;
+          Expect.equals("1.0", request.protocolVersion);
+          response.addString("Z");
+          response.close();
+        },
+        onError: (e) => Expect.fail("Unexpected error $e"));
+
+    int count = 0;
+    makeRequest() {
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+        socket.addString("GET / HTTP/1.0\r\n\r\n");
+        socket.addString("Connection: Keep-Alive\r\n\r\n");
+
+        List<int> response = [];
+        socket.listen(
+            response.addAll,
+            onDone: () {
+              socket.destroy();
+              count++;
+              String s = new String.fromCharCodes(response).toLowerCase();
+              print(s);
+              Expect.equals("z", s[s.length - 1]);
+              Expect.equals(-1, s.indexOf("content-length:"));
+              Expect.equals(-1, s.indexOf("keep-alive"));
+              if (count < 10) {
+                makeRequest();
+              } else {
+                server.close();
+              }
+                      },onError: (e) => print(e));
+      });
+    }
+    makeRequest();
+  });
+}
+
+
+// Client makes a HTTP 1.0 request with connection keep alive. The
+// server sets a content length so the persistent connection can be
+// used.
+void testHttp10KeepAlive() {
+  HttpServer.bind().then((server) {
+    server.listen(
+        (HttpRequest request) {
+          Expect.isNull(request.headers.value('content-length'));
+          Expect.equals(-1, request.contentLength);
+          var response = request.response;
+          response.contentLength = 1;
+          Expect.equals("1.0", request.protocolVersion);
+          response.addString("Z");
+          response.close();
+        },
+        onError: (e) => Expect.fail("Unexpected error $e"));
+
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      void sendRequest() {
+        socket.addString("GET / HTTP/1.0\r\n");
+        socket.addString("Connection: Keep-Alive\r\n\r\n");
+      }
+
+      List<int> response = [];
+      int count = 0;
+      socket.listen(
+          (d) {
+            response.addAll(d);
+            if (response[response.length - 1] == "Z".codeUnitAt(0)) {
+              String s = new String.fromCharCodes(response).toLowerCase();
+              Expect.isTrue(s.indexOf("\r\nconnection: keep-alive\r\n") > 0);
+              Expect.isTrue(s.indexOf("\r\ncontent-length: 1\r\n") > 0);
+              count++;
+              if (count < 10) {
+                response = [];
+                sendRequest();
+              } else {
+                socket.close();
+              }
+            }
+          },
+          onDone: () {
+            socket.destroy();
+            server.close();
+          });
+      sendRequest();
+    });
+  });
+}
+
+
+// Client makes a HTTP 1.0 request with connection keep alive. The
+// server does not set a content length so it cannot honor connection
+// keep alive.
+void testHttp10KeepAliveServerCloses() {
+  HttpServer.bind().then((server) {
+    server.listen(
+        (HttpRequest request) {
+          Expect.isNull(request.headers.value('content-length'));
+          Expect.equals(-1, request.contentLength);
+          var response = request.response;
+          Expect.equals("1.0", request.protocolVersion);
+          response.addString("Z");
+          response.close();
+        },
+        onError: (e) => Expect.fail("Unexpected error $e"));
+
+    int count = 0;
+    makeRequest() {
+      Socket.connect("127.0.0.1", server.port).then((socket) {
+        socket.addString("GET / HTTP/1.0\r\n");
+        socket.addString("Connection: Keep-Alive\r\n\r\n");
+
+        List<int> response = [];
+        socket.listen(
+            response.addAll,
+            onDone: () {
+              socket.destroy();
+              count++;
+              String s = new String.fromCharCodes(response).toLowerCase();
+              Expect.equals("z", s[s.length - 1]);
+              Expect.equals(-1, s.indexOf("content-length"));
+              Expect.equals(-1, s.indexOf("connection"));
+              if (count < 10) {
+                makeRequest();
+              } else {
+                server.close();
+              }
+            });
+        });
+    }
+    makeRequest();
+  });
+}
+
+
+void main() {
+  testHttp10NoKeepAlive();
+  // TODO(8871): This test fails with short socket writes.
+  //testHttp10ServerClose();
+  testHttp10KeepAlive();
+  testHttp10KeepAliveServerCloses();
+}
diff --git a/tests/standalone/io/http_auth_test.dart b/tests/standalone/io/http_auth_test.dart
index cfc692b..c6acccb 100644
--- a/tests/standalone/io/http_auth_test.dart
+++ b/tests/standalone/io/http_auth_test.dart
@@ -168,7 +168,7 @@
       String password = url.path.substring(1, 6);
       if (passwordChanged) password = "${password}1";
       Completer completer = new Completer();
-      new Timer(10, (_) {
+      new Timer(const Duration(milliseconds: 10), () {
         client.addCredentials(
             url, realm, new HttpClientBasicCredentials(username, password));
         completer.complete(true);
diff --git a/tests/standalone/io/http_client_connect_test.dart b/tests/standalone/io/http_client_connect_test.dart
index dd8a3bf..93bd7fa 100644
--- a/tests/standalone/io/http_client_connect_test.dart
+++ b/tests/standalone/io/http_client_connect_test.dart
@@ -30,7 +30,7 @@
 
 void testGetDataRequest() {
   HttpServer.bind().then((server) {
-    var data = "lalala".charCodes;
+    var data = "lalala".codeUnits;
     server.listen((request) {
       request.response.add(data);
       request.pipe(request.response);
diff --git a/tests/standalone/io/http_client_exception_test.dart b/tests/standalone/io/http_client_exception_test.dart
new file mode 100644
index 0000000..65c0a41
--- /dev/null
+++ b/tests/standalone/io/http_client_exception_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+
+import "dart:io";
+import "dart:isolate";
+import "dart:uri";
+
+void testInvalidUrl() {
+  HttpClient client = new HttpClient();
+  Expect.throws(
+      () => client.getUrl(Uri.parse('ftp://www.google.com')));
+}
+
+void testBadHostName() {
+  HttpClient client = new HttpClient();
+  ReceivePort port = new ReceivePort();
+  client.get("some.bad.host.name.7654321", 0, "/")
+    .then((request) {
+      Expect.fail("Should not open a request on bad hostname");
+    }).catchError((error) {
+      port.close();  // We expect onError to be called, due to bad host name.
+    }, test: (error) => error is! String);
+}
+
+void main() {
+  testInvalidUrl();
+  testBadHostName();
+}
diff --git a/tests/standalone/io/http_client_socket_reuse_test.dart b/tests/standalone/io/http_client_socket_reuse_test.dart
deleted file mode 100644
index 715624a8..0000000
--- a/tests/standalone/io/http_client_socket_reuse_test.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "dart:async";
-import "dart:io";
-import "dart:uri";
-import "dart:isolate";
-
-// By running tests sequentially, we cover the socket reuse code in HttpClient.
-
-void testGoogleUrls() {
-  int testsStarted = 0;
-  int testsFinished = 0;
-  bool allStarted = false;
-  HttpClient client = new HttpClient();
-
-  Future testUrl(String url) {
-    testsStarted++;
-    var requestUri = Uri.parse(url);
-    return client.getUrl(requestUri)
-        .then((HttpClientRequest request) => request.close())
-        .then((HttpClientResponse response) {
-          Expect.isTrue(response.statusCode < 500);
-          if (requestUri.path.length == 0) {
-            Expect.isTrue(response.statusCode != 404);
-          }
-          return response.reduce(null, (previous, element) => null);
-        })
-        .catchError((error) => Expect.fail("Unexpected IO error: $error"));
-  }
-
-  // TODO(3593): Use a Dart HTTP server for this test.
-  testUrl('http://www.google.dk')
-    .then((_) => testUrl('http://www.google.dk'))
-    .then((_) => testUrl('http://www.google.dk/#q=foo'))
-    .then((_) => testUrl('http://www.google.dk/#hl=da&q=foo'))
-    .then((_) { client.close(); });
-}
-
-void main() {
-  testGoogleUrls();
-}
diff --git a/tests/standalone/io/http_client_test.dart b/tests/standalone/io/http_client_test.dart
deleted file mode 100644
index c3e7db1..0000000
--- a/tests/standalone/io/http_client_test.dart
+++ /dev/null
@@ -1,75 +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.
-//
-// VMOptions=
-// VMOptions=--short_socket_read
-// VMOptions=--short_socket_write
-// VMOptions=--short_socket_read --short_socket_write
-
-import "dart:io";
-import "dart:uri";
-import "dart:isolate";
-
-void testGoogle() {
-  HttpClient client = new HttpClient();
-  client.get('www.google.com', 80, '/')
-      .then((request) => request.close())
-      .then((response) {
-        Expect.isTrue(response.statusCode < 500);
-        response.listen((data) {}, onDone: client.close);
-      })
-      .catchError((error) => Expect.fail("Unexpected IO error: $error"));
-}
-
-int testGoogleUrlCount = 0;
-void testGoogleUrl() {
-  HttpClient client = new HttpClient();
-
-  void testUrl(String url) {
-    var requestUri = Uri.parse(url);
-    client.getUrl(requestUri)
-        .then((request) => request.close())
-        .then((response) {
-          testGoogleUrlCount++;
-          Expect.isTrue(response.statusCode < 500);
-          if (requestUri.path.length == 0) {
-            Expect.isTrue(response.statusCode != 404);
-          }
-          response.listen((data) {}, onDone: () {
-            if (testGoogleUrlCount == 5) client.close();
-          });
-        })
-        .catchError((error) => Expect.fail("Unexpected IO error: $error"));
-  }
-
-  testUrl('http://www.google.com');
-  testUrl('http://www.google.com/abc');
-  testUrl('http://www.google.com/?abc');
-  testUrl('http://www.google.com/abc?abc');
-  testUrl('http://www.google.com/abc?abc#abc');
-}
-
-void testInvalidUrl() {
-  HttpClient client = new HttpClient();
-  Expect.throws(
-      () => client.getUrl(Uri.parse('ftp://www.google.com')));
-}
-
-void testBadHostName() {
-  HttpClient client = new HttpClient();
-  ReceivePort port = new ReceivePort();
-  client.get("some.bad.host.name.7654321", 0, "/")
-    .then((request) {
-      Expect.fail("Should not open a request on bad hostname");
-    }).catchError((error) {
-      port.close();  // We expect onError to be called, due to bad host name.
-    }, test: (error) => error is! String);
-}
-
-void main() {
-  testGoogle();
-  testGoogleUrl();
-  testInvalidUrl();
-  testBadHostName();
-}
diff --git a/tests/standalone/io/http_close_test.dart b/tests/standalone/io/http_close_test.dart
new file mode 100644
index 0000000..de467d5
--- /dev/null
+++ b/tests/standalone/io/http_close_test.dart
@@ -0,0 +1,160 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:scalarlist";
+
+
+void testClientAndServerCloseNoListen(int connections) {
+  HttpServer.bind().then((server) {
+    int closed = 0;
+    server.listen((request) {
+      request.response.close();
+      request.response.done.then((_) {
+        closed++;
+        if (closed == connections) {
+          Expect.equals(0, server.connectionsInfo().active);
+          Expect.equals(server.connectionsInfo().total,
+                        server.connectionsInfo().idle);
+          server.close();
+        }
+      });
+    });
+    var client = new HttpClient();
+    for (int i = 0; i < connections; i++) {
+      client.get("localhost", server.port, "/")
+          .then((request) => request.close())
+          .then((response) {
+          });
+    }
+  });
+}
+
+
+void testClientCloseServerListen(int connections) {
+  HttpServer.bind().then((server) {
+    int closed = 0;
+    void check() {
+      closed++;
+      if (closed == connections * 2) {
+        Expect.equals(0, server.connectionsInfo().active);
+        Expect.equals(server.connectionsInfo().total,
+                      server.connectionsInfo().idle);
+        server.close();
+      }
+    }
+    server.listen((request) {
+      request.listen(
+          (_) {},
+          onDone: () {
+            request.response.close();
+            request.response.done.then((_) => check());
+          });
+    });
+    var client = new HttpClient();
+    for (int i = 0; i < connections; i++) {
+      client.get("localhost", server.port, "/")
+          .then((request) => request.close())
+          .then((response) => check());
+    }
+  });
+}
+
+
+void testClientCloseDelayed(int connections) {
+  HttpServer.bind().then((server) {
+    int closed = 0;
+    void check() {
+      closed++;
+      // Wait for both server and client to see the connections as closed.
+      if (closed == connections * 2) {
+        Expect.equals(0, server.connectionsInfo().active);
+        Expect.equals(server.connectionsInfo().total,
+                      server.connectionsInfo().idle);
+        server.close();
+      }
+    }
+    server.listen((request) {
+      request.pipe(request.response)
+          .then((_) => check());
+    });
+    var client = new HttpClient();
+    for (int i = 0; i < connections; i++) {
+      var req;
+      client.post("localhost", server.port, "/")
+          .then((request) {
+            req = request;
+            request.add(new Uint8List(1024));
+            return request.response;
+          })
+          .then((response) {
+            req.close();
+            // Ensure we don't accept the response until we have send the entire
+            // request.
+            response.listen(
+                (_) {},
+                onDone: () {
+                  check();
+                });
+          });
+    }
+  });
+}
+
+
+void testClientCloseSendingResponse(int connections) {
+  HttpServer.bind().then((server) {
+    int closed = 0;
+    void check() {
+      closed++;
+      // Wait for both server and client to see the connections as closed.
+      if (closed == connections * 2) {
+        Expect.equals(0, server.connectionsInfo().active);
+        Expect.equals(server.connectionsInfo().total,
+                      server.connectionsInfo().idle);
+        server.close();
+      }
+    }
+    server.listen((request) {
+      var timer = new Timer.repeating(const Duration(milliseconds: 20), (_) {
+        request.response.add(new Uint8List(16 * 1024));
+      });
+      request.response.done
+          .catchError((_) {})
+          .whenComplete(() {
+            check();
+            timer.cancel();
+          });
+    });
+    var client = new HttpClient();
+    for (int i = 0; i < connections; i++) {
+      client.get("localhost", server.port, "/")
+          .then((request) => request.close())
+          .then((response) {
+            // Ensure we don't accept the response until we have send the entire
+            // request.
+            var subscription = response.listen((_) {});
+            new Timer(const Duration(milliseconds: 200), () {
+              subscription.cancel();
+              check();
+            });
+          });
+    }
+  });
+}
+
+
+void main() {
+  testClientAndServerCloseNoListen(10);
+  testClientCloseServerListen(10);
+  testClientCloseDelayed(10);
+  testClientCloseSendingResponse(10);
+}
+
diff --git a/tests/standalone/io/http_connection_close_test.dart b/tests/standalone/io/http_connection_close_test.dart
index e8f3609..a2a11c7 100644
--- a/tests/standalone/io/http_connection_close_test.dart
+++ b/tests/standalone/io/http_connection_close_test.dart
@@ -35,7 +35,7 @@
 
     Socket.connect("127.0.0.1", server.port)
       .then((socket) {
-        List<int> buffer = new List<int>.fixedLength(1024);
+        List<int> buffer = new List<int>(1024);
         socket.addString("GET / HTTP/1.1\r\nConnection: close\r\n\r\n");
         socket.listen(
           (data) {},
diff --git a/tests/standalone/io/http_content_length_test.dart b/tests/standalone/io/http_content_length_test.dart
index 14d4000..16a1d03 100644
--- a/tests/standalone/io/http_content_length_test.dart
+++ b/tests/standalone/io/http_content_length_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -68,6 +68,7 @@
 
 void testBody(int totalConnections, bool useHeader) {
   HttpServer.bind("127.0.0.1", 0, totalConnections).then((server) {
+    int serverCount = 0;
     server.listen(
         (HttpRequest request) {
           Expect.equals("2", request.headers.value('content-length'));
@@ -91,7 +92,10 @@
                       Expect.fail("Unexpected successful response completion");
                     })
                     .catchError((e) {
-                      Expect.isTrue(e.error is HttpException);
+                      Expect.isTrue(e.error is HttpException, "[$e]");
+                      if (++serverCount == totalConnections) {
+                        server.close();
+                      }
                     });
                 response.close();
                 Expect.throws(() => response.addString("x"),
@@ -100,7 +104,7 @@
         },
         onError: (e) => Expect.fail("Unexpected error $e"));
 
-    int count = 0;
+    int clientCount = 0;
     HttpClient client = new HttpClient();
     for (int i = 0; i < totalConnections; i++) {
       client.get("127.0.0.1", server.port, "/")
@@ -123,9 +127,8 @@
             response.listen(
                 (d) {},
                 onDone: () {
-                  if (++count == totalConnections) {
+                  if (++clientCount == totalConnections) {
                     client.close();
-                    server.close();
                   }
                 });
           });
@@ -199,35 +202,31 @@
   });
 }
 
-void testHttp10() {
-  HttpServer.bind("127.0.0.1", 0, 5).then((server) {
+void testSetContentLength() {
+  HttpServer.bind().then((server) {
     server.listen(
         (HttpRequest request) {
-          Expect.isNull(request.headers.value('content-length'));
-          Expect.equals(-1, request.contentLength);
           var response = request.response;
-          response.contentLength = 0;
-          Expect.equals("1.0", request.protocolVersion);
-          response.done
-              .then((_) => Expect.fail("Unexpected response completion"))
-              .catchError((e) => Expect.isTrue(e.error is HttpException));
-          response.addString("x");
+          Expect.isNull(response.headers.value('content-length'));
+          Expect.equals(-1, response.contentLength);
+          response.headers.set("content-length", 3);
+          Expect.equals("3", response.headers.value('content-length'));
+          Expect.equals(3, response.contentLength);
+          response.addString("xxx");
           response.close();
-          Expect.throws(() => response.addString("x"),
-                        (e) => e is StateError);
-        },
-        onError: (e) => Expect.fail("Unexpected error $e"));
+        });
 
-    Socket.connect("127.0.0.1", server.port).then((socket) {
-      socket.addString("GET / HTTP/1.0\r\n\r\n");
-      socket.close();
-      socket.listen(
-          (d) { },
-          onDone: () {
-            socket.destroy();
-            server.close();
-          });
-    });
+    var client = new HttpClient();
+    client.get("127.0.0.1", server.port, "/")
+        .then((request) => request.close())
+        .then((response) {
+          response.listen(
+              (_) { },
+              onDone: () {
+                client.close();
+                server.close();
+              });
+        });
   });
 }
 
@@ -238,5 +237,5 @@
   testBody(5, true);
   testBodyChunked(5, false);
   testBodyChunked(5, true);
-  testHttp10();
+  testSetContentLength();
 }
diff --git a/tests/standalone/io/http_date_test.dart b/tests/standalone/io/http_date_test.dart
index 5821e05..8f2ee60 100644
--- a/tests/standalone/io/http_date_test.dart
+++ b/tests/standalone/io/http_date_test.dart
@@ -5,7 +5,7 @@
 import "dart:async";
 import "dart:math";
 
-part "../../../sdk/lib/io/io_stream_consumer.dart";
+part "../../../sdk/lib/io/io_sink.dart";
 part "../../../sdk/lib/io/http.dart";
 part "../../../sdk/lib/io/http_impl.dart";
 part "../../../sdk/lib/io/http_parser.dart";
diff --git a/tests/standalone/io/http_head_test.dart b/tests/standalone/io/http_head_test.dart
index 215872c..9325ceb 100644
--- a/tests/standalone/io/http_head_test.dart
+++ b/tests/standalone/io/http_head_test.dart
@@ -13,7 +13,7 @@
           response.close();
         } else if (request.uri.path == "/test200") {
           response.contentLength = 200;
-          List<int> data = new List<int>.fixedLength(200, fill: 0);
+          List<int> data = new List<int>.filled(200, 0);
           response.add(data);
           response.close();
         } else {
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index fca7a49..19829e7 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 import 'dart:math';
 
-part "../../../sdk/lib/io/io_stream_consumer.dart";
+part "../../../sdk/lib/io/io_sink.dart";
 part "../../../sdk/lib/io/http.dart";
 part "../../../sdk/lib/io/http_headers.dart";
 part "../../../sdk/lib/io/http_impl.dart";
diff --git a/tests/standalone/io/http_keep_alive_test.dart b/tests/standalone/io/http_keep_alive_test.dart
index 70b9021..c89b4ee 100644
--- a/tests/standalone/io/http_keep_alive_test.dart
+++ b/tests/standalone/io/http_keep_alive_test.dart
@@ -26,7 +26,7 @@
     server.listen((request) {
       bool chunked = request.queryParameters["chunked"] == "true";
       int length = int.parse(request.queryParameters["length"]);
-      var buffer = new List.fixedLength(length, fill: 0);
+      var buffer = new List<int>.filled(length, 0);
       if (!chunked) request.response.contentLength = length;
       request.response.add(buffer);
       request.response.close();
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index 173fec4..ab02206 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -8,7 +8,7 @@
 import 'dart:isolate';
 import 'dart:uri';
 
-part '../../../sdk/lib/io/io_stream_consumer.dart';
+part '../../../sdk/lib/io/io_sink.dart';
 part '../../../sdk/lib/io/http.dart';
 part '../../../sdk/lib/io/http_impl.dart';
 part '../../../sdk/lib/io/http_headers.dart';
@@ -125,7 +125,7 @@
 
     // Test parsing the request three times delivering the data in
     // different chunks.
-    List<int> requestData = request.charCodes;
+    List<int> requestData = request.codeUnits;
     testWrite(requestData);
     testWrite(requestData, 10);
     testWrite(requestData, 1);
@@ -169,7 +169,7 @@
 
     // Test parsing the request three times delivering the data in
     // different chunks.
-    List<int> requestData = request.charCodes;
+    List<int> requestData = request.codeUnits;
     testWrite(requestData);
     testWrite(requestData, 10);
     testWrite(requestData, 1);
@@ -270,7 +270,7 @@
 
     // Test parsing the request three times delivering the data in
     // different chunks.
-    List<int> responseData = response.charCodes;
+    List<int> responseData = response.codeUnits;
     testWrite(responseData);
     testWrite(responseData, 10);
     testWrite(responseData, 1);
@@ -320,7 +320,7 @@
 
     // Test parsing the request three times delivering the data in
     // different chunks.
-    List<int> responseData = response.charCodes;
+    List<int> responseData = response.codeUnits;
     testWrite(responseData);
     testWrite(responseData, 10);
     testWrite(responseData, 1);
diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart
index 24a2f84..af8cdff 100644
--- a/tests/standalone/io/http_proxy_test.dart
+++ b/tests/standalone/io/http_proxy_test.dart
@@ -189,15 +189,26 @@
   setupServer(1, directRequestPaths: ["/4"], secure: true).then((secureServer) {
     HttpClient client = new HttpClient();
 
-    List<String> proxy =
-        ["PROXY localhost:${proxyServer.port}",
-         "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080",
-         "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer.port}",
-         "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;"
-             " PROXY localhost:${proxyServer.port}",
-         "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
-         "PROXY localhost:${proxyServer.port}; DIRECT"];
-
+    List<String> proxy;
+    if (Platform.operatingSystem == "windows") {
+      proxy =
+          ["PROXY localhost:${proxyServer.port}",
+           "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080",
+           "PROXY localhost:${proxyServer.port}",
+           ""
+               " PROXY localhost:${proxyServer.port}",
+           "DIRECT",
+           "PROXY localhost:${proxyServer.port}; DIRECT"];
+    } else {
+      proxy =
+          ["PROXY localhost:${proxyServer.port}",
+           "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080",
+           "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer.port}",
+           "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;"
+               " PROXY localhost:${proxyServer.port}",
+           "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
+           "PROXY localhost:${proxyServer.port}; DIRECT"];
+    }
     client.findProxy = (Uri uri) {
       // Pick the proxy configuration based on the request path.
       int index = int.parse(uri.path.substring(1));
@@ -248,13 +259,25 @@
   setupServer(2, directRequestPaths: ["/4"]).then((server) {
     HttpClient client = new HttpClient();
 
-    List<String> proxy =
-        ["PROXY localhost:${proxyServer1.port}",
-         "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080",
-         "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer1.port}",
-         "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; PROXY localhost:${proxyServer1.port}",
-         "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
-         "PROXY localhost:${proxyServer1.port}; DIRECT"];
+    List<String> proxy;
+    if (Platform.operatingSystem == "windows") {
+      proxy =
+          ["PROXY localhost:${proxyServer1.port}",
+           "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080",
+           "PROXY localhost:${proxyServer1.port}",
+           "PROXY localhost:${proxyServer1.port}",
+           "DIRECT",
+           "PROXY localhost:${proxyServer1.port}; DIRECT"];
+    } else {
+      proxy =
+          ["PROXY localhost:${proxyServer1.port}",
+           "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080",
+           "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer1.port}",
+           "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;"
+               " PROXY localhost:${proxyServer1.port}",
+           "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT",
+           "PROXY localhost:${proxyServer1.port}; DIRECT"];
+    }
 
     client.findProxy = (Uri uri) {
       // Pick the proxy configuration based on the request path.
diff --git a/tests/standalone/io/http_read_test.dart b/tests/standalone/io/http_read_test.dart
index dfef4e4..6cba2b5 100644
--- a/tests/standalone/io/http_read_test.dart
+++ b/tests/standalone/io/http_read_test.dart
@@ -174,7 +174,7 @@
               request.addString(data.substring(10, data.length));
             } else {
               request.contentLength = data.length;
-              request.add(data.charCodes);
+              request.add(data.codeUnits);
             }
             return request.close();
           })
diff --git a/tests/standalone/io/http_request_pipeling_test.dart b/tests/standalone/io/http_request_pipeling_test.dart
new file mode 100644
index 0000000..a96fa88
--- /dev/null
+++ b/tests/standalone/io/http_request_pipeling_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:io";
+import "dart:uri";
+
+void main() {
+  final int REQUEST_COUNT = 100;
+  int count = 0;
+  HttpServer.bind().then((server) {
+    server.listen((HttpRequest request) {
+      count++;
+      request.response.addString(request.uri.path);
+      request.response.close();
+      if (request.uri.path == "/done") {
+        request.response.done.then((_) {
+            Expect.equals(REQUEST_COUNT + 1, count);
+          server.close();
+        });
+      }
+    });
+    Socket.connect("127.0.0.1", server.port).then((s) {
+      s.listen((data) { });
+      for (int i = 0; i < REQUEST_COUNT; i++) {
+        s.addString("GET /$i HTTP/1.1\r\nX-Header-1: 111\r\n\r\n");
+      }
+      s.addString("GET /done HTTP/1.1\r\nConnection: close\r\n\r\n");
+      s.close();
+    });
+  });
+}
diff --git a/tests/standalone/io/http_server_early_client_close_test.dart b/tests/standalone/io/http_server_early_client_close_test.dart
index b59857e..2f75862 100644
--- a/tests/standalone/io/http_server_early_client_close_test.dart
+++ b/tests/standalone/io/http_server_early_client_close_test.dart
@@ -57,7 +57,7 @@
 
     List<int> d;
     if (data is List<int>) d = data;
-    if (data is String) d = data.charCodes;
+    if (data is String) d = data.codeUnits;
     if (d == null) Expect.fail("Invalid data");
     sendData(d, server.port);
 
@@ -116,7 +116,7 @@
     var count = 0;
     makeRequest() {
       Socket.connect("127.0.0.1", server.port).then((socket) {
-        var data = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n".charCodes;
+        var data = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n".codeUnits;
         socket.add(data);
         socket.close();
         socket.done.then((_) {
diff --git a/tests/standalone/io/http_server_response_test.dart b/tests/standalone/io/http_server_response_test.dart
index 674c901..fc94876 100644
--- a/tests/standalone/io/http_server_response_test.dart
+++ b/tests/standalone/io/http_server_response_test.dart
@@ -7,10 +7,11 @@
 // VMOptions=--short_socket_write
 // VMOptions=--short_socket_read --short_socket_write
 
+import "dart:async";
 import "dart:io";
 import "dart:scalarlist";
 
-void testServerRequest(void handler(server, request)) {
+void testServerRequest(void handler(server, request), {int bytes}) {
   HttpServer.bind().then((server) {
     server.listen((request) {
       handler(server, request);
@@ -23,11 +24,16 @@
     client.get("127.0.0.1", server.port, "/")
       .then((request) => request.close())
       .then((response) {
-        response.listen((_) {}, onDone: () {
-          client.close();
-        }, onError: (error) {
-          Expect.isTrue(error.error is HttpParserException);
-        });
+        int received = 0;
+        response.listen(
+            (data) => received += data.length,
+            onDone: () {
+              if (bytes != null) Expect.equals(received, bytes);
+              client.close();
+            },
+            onError: (error) {
+              Expect.isTrue(error.error is HttpParserException);
+            });
       })
       .catchError((error) {
          client.close();
@@ -45,6 +51,39 @@
   });
 }
 
+void testResponseAddStream() {
+  int bytes = new File(new Options().script).lengthSync();
+
+  testServerRequest((server, request) {
+    request.response.addStream(new File(new Options().script).openRead())
+        .then((response) {
+          response.close();
+          response.done.then((_) => server.close());
+        });
+  }, bytes: bytes);
+
+  testServerRequest((server, request) {
+    request.response.addStream(new File(new Options().script).openRead())
+        .then((response) {
+          request.response.addStream(new File(new Options().script).openRead())
+              .then((response) {
+                response.close();
+                response.done.then((_) => server.close());
+              });
+        });
+  }, bytes: bytes * 2);
+
+  testServerRequest((server, request) {
+    var controller = new StreamController();
+    request.response.addStream(controller.stream)
+        .then((response) {
+          response.close();
+          response.done.then((_) => server.close());
+        });
+    controller.close();
+  }, bytes: 0);
+}
+
 void testBadResponseAdd() {
   testServerRequest((server, request) {
     request.response.contentLength = 0;
@@ -95,6 +134,7 @@
 
 void main() {
   testResponseDone();
+  testResponseAddStream();
   testBadResponseAdd();
   testBadResponseClose();
 }
diff --git a/tests/standalone/io/http_shutdown_test.dart b/tests/standalone/io/http_shutdown_test.dart
index c7bcc16..8c91797 100644
--- a/tests/standalone/io/http_shutdown_test.dart
+++ b/tests/standalone/io/http_shutdown_test.dart
@@ -2,6 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
 
 import "dart:async";
 import "dart:io";
@@ -49,6 +53,7 @@
           for (int i = 0; i < outputStreamWrites; i++) {
             request.addString("Hello, world!");
           }
+          request.done.catchError((_) {});
           return request.close();
         })
         .then((HttpClientResponse response) {
@@ -146,6 +151,7 @@
               (_) { },
               onDone: () {
                 request.response.close();
+                request.response.done.catchError((e) {});
               },
               onError: (error) { });
         },
@@ -162,6 +168,7 @@
             // TODO(sgjesse): Make this test work with
             //request.response instead of request.close() return
             //return request.response;
+            request.done.catchError((e) {});
             return request.close();
           })
         .then((response) { })
diff --git a/tests/standalone/io/https_client_certificate_test.dart b/tests/standalone/io/https_client_certificate_test.dart
index 1d9b0e4..9c519eb 100644
--- a/tests/standalone/io/https_client_certificate_test.dart
+++ b/tests/standalone/io/https_client_certificate_test.dart
@@ -28,8 +28,12 @@
     HttpClient client = new HttpClient();
     client.getUrl(Uri.parse("https://$HOST_NAME:${server.port}/"))
         .then((request) => request.close())
-        .then((response) =>
-            response.reduce(<int>[], (message, data) => message..addAll(data)))
+        .then((response) {
+          Expect.equals('CN=localhost', response.certificate.subject);
+          Expect.equals('CN=myauthority', response.certificate.issuer);
+          return response.reduce(<int>[],
+                                 (message, data) => message..addAll(data));
+        })
         .then((message) {
           String received = new String.fromCharCodes(message);
           Expect.equals(received, "Hello");
diff --git a/tests/standalone/io/https_client_exception_test.dart b/tests/standalone/io/https_client_exception_test.dart
new file mode 100644
index 0000000..22c743c
--- /dev/null
+++ b/tests/standalone/io/https_client_exception_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+import "dart:isolate";
+import "dart:uri";
+
+void testBadHostName() {
+  HttpClient client = new HttpClient();
+  ReceivePort port = new ReceivePort();
+  client.getUrl(Uri.parse("https://some.bad.host.name.7654321/"))
+      .then((HttpClientRequest request) {
+        Expect.fail("Should not open a request on bad hostname");
+      })
+      .catchError((error) {
+        port.close();  // Should throw an error on bad hostname.
+      });
+}
+
+void InitializeSSL() {
+  SecureSocket.initialize();
+}
+
+void main() {
+  testBadHostName();
+  Expect.throws(InitializeSSL);
+}
diff --git a/tests/standalone/io/https_client_socket_reuse_test.dart b/tests/standalone/io/https_client_socket_reuse_test.dart
deleted file mode 100644
index 5b4244b..0000000
--- a/tests/standalone/io/https_client_socket_reuse_test.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "dart:async";
-import "dart:io";
-import "dart:uri";
-import "dart:isolate";
-
-// By running tests sequentially, we cover the socket reuse code in HttpClient.
-
-void testGoogleUrls() {
-  int testsStarted = 0;
-  int testsFinished = 0;
-  bool allStarted = false;
-  HttpClient client = new HttpClient();
-
-  Future testUrl(String url) {
-    testsStarted++;
-    var requestUri = Uri.parse(url);
-    return client.getUrl(requestUri)
-        .then((HttpClientRequest request) => request.close())
-        .then((HttpClientResponse response) {
-          Expect.isTrue(response.statusCode < 500);
-          if (requestUri.path.length == 0) {
-            Expect.isTrue(response.statusCode != 404);
-          }
-          return response.reduce(null, (previous, element) => null);
-        })
-        .catchError((error) => Expect.fail("Unexpected IO error: $error"));
-  }
-
-  // TODO(3593): Use a Dart HTTPS server for this test.
-  testUrl('https://www.google.dk')
-    .then((_) => testUrl('https://www.google.dk'))
-    .then((_) => testUrl('https://www.google.dk/#q=foo'))
-    .then((_) => testUrl('https://www.google.dk/#hl=da&q=foo'))
-    .then((_) { client.close(); });
-}
-
-void main() {
-  testGoogleUrls();
-}
diff --git a/tests/standalone/io/https_client_test.dart b/tests/standalone/io/https_client_test.dart
deleted file mode 100644
index 37b3d4f..0000000
--- a/tests/standalone/io/https_client_test.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "dart:io";
-import "dart:uri";
-import "dart:isolate";
-
-
-void testGoogleUrl() {
-  int testsStarted = 0;
-  int testsFinished = 0;
-  bool allStarted = false;
-  HttpClient client = new HttpClient();
-
-  void testUrl(String url) {
-    testsStarted++;
-    var requestUri = Uri.parse(url);
-    client.getUrl(requestUri)
-        .then((HttpClientRequest request) => request.close())
-        .then((HttpClientResponse response) {
-          Expect.isTrue(response.statusCode < 500);
-          if (requestUri.path.length == 0) {
-            Expect.isTrue(response.statusCode != 404);
-          }
-          response.listen((data) { }, onDone: () {
-            if (++testsFinished == testsStarted && allStarted) client.close();
-          });
-        })
-        .catchError((error) => Expect.fail("Unexpected IO error: $error"));
-  }
-
-  testUrl('https://www.google.dk');
-  testUrl('https://www.google.dk');
-  testUrl('https://www.google.dk/#q=foo');
-  testUrl('https://www.google.dk/#hl=da&q=foo');
-  allStarted = true;
-}
-
-void testBadHostName() {
-  HttpClient client = new HttpClient();
-  ReceivePort port = new ReceivePort();
-  client.getUrl(Uri.parse("https://some.bad.host.name.7654321/"))
-      .then((HttpClientRequest request) {
-        Expect.fail("Should not open a request on bad hostname");
-      })
-      .catchError((error) {
-        port.close();  // Should throw an error on bad hostname.
-      });
-}
-
-void InitializeSSL() {
-  SecureSocket.initialize();
-}
-
-void main() {
-  testGoogleUrl();
-  testBadHostName();
-  Expect.throws(InitializeSSL);
-}
diff --git a/tests/standalone/io/mime_multipart_parser_test.dart b/tests/standalone/io/mime_multipart_parser_test.dart
index adccecb..d9457c7 100644
--- a/tests/standalone/io/mime_multipart_parser_test.dart
+++ b/tests/standalone/io/mime_multipart_parser_test.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 import 'dart:math';
 
-part '../../../sdk/lib/io/io_stream_consumer.dart';
+part '../../../sdk/lib/io/io_sink.dart';
 part "../../../sdk/lib/io/http.dart";
 part "../../../sdk/lib/io/http_impl.dart";
 part "../../../sdk/lib/io/http_parser.dart";
@@ -47,7 +47,7 @@
       if (expectedParts[partCount] != null) {
         List<int> expectedPart;
         if (expectedParts[partCount] is String) {
-          expectedPart = expectedParts[partCount].charCodes;
+          expectedPart = expectedParts[partCount].codeUnits;
         } else {
           expectedPart = expectedParts[partCount];
         }
@@ -83,7 +83,7 @@
 
   // Test parsing the data three times delivering the data in
   // different chunks.
-  List<int> data = message.charCodes;
+  List<int> data = message.codeUnits;
   testWrite(data);
   testWrite(data, 10);
   testWrite(data, 2);
diff --git a/tests/standalone/io/process_check_arguments_test.dart b/tests/standalone/io/process_check_arguments_test.dart
index 46b1cb4..22ccde4 100644
--- a/tests/standalone/io/process_check_arguments_test.dart
+++ b/tests/standalone/io/process_check_arguments_test.dart
@@ -25,14 +25,14 @@
     scriptFile =
         new File("../tests/standalone/io/process_check_arguments_script.dart");
   }
-  test([scriptFile.name, '3', '0', 'a']);
-  test([scriptFile.name, '3', '0', 'a b']);
-  test([scriptFile.name, '3', '0', 'a\tb']);
-  test([scriptFile.name, '3', '1', 'a\tb"']);
-  test([scriptFile.name, '3', '1', 'a"\tb']);
-  test([scriptFile.name, '3', '1', 'a"\t\\\\"b"']);
-  test([scriptFile.name, '4', '0', 'a\tb', 'a']);
-  test([scriptFile.name, '4', '0', 'a\tb', 'a\t\t\t\tb']);
-  test([scriptFile.name, '4', '0', 'a\tb', 'a    b']);
+  test([scriptFile.path, '3', '0', 'a']);
+  test([scriptFile.path, '3', '0', 'a b']);
+  test([scriptFile.path, '3', '0', 'a\tb']);
+  test([scriptFile.path, '3', '1', 'a\tb"']);
+  test([scriptFile.path, '3', '1', 'a"\tb']);
+  test([scriptFile.path, '3', '1', 'a"\t\\\\"b"']);
+  test([scriptFile.path, '4', '0', 'a\tb', 'a']);
+  test([scriptFile.path, '4', '0', 'a\tb', 'a\t\t\t\tb']);
+  test([scriptFile.path, '4', '0', 'a\tb', 'a    b']);
 }
 
diff --git a/tests/standalone/io/process_non_ascii_test.dart b/tests/standalone/io/process_non_ascii_test.dart
index e7b31e3..88291be 100644
--- a/tests/standalone/io/process_non_ascii_test.dart
+++ b/tests/standalone/io/process_non_ascii_test.dart
@@ -24,7 +24,7 @@
   nonAsciiTxtFile.writeAsStringSync('æøå');
   var options = new ProcessOptions();
   options.workingDirectory = nonAsciiDir.path;
-  var script = nonAsciiFile.name;
+  var script = nonAsciiFile.path;
   Process.run(executable, [script], options).then((result) {
     Expect.equals(0, result.exitCode);
     tempDir.deleteSync(recursive: true);
diff --git a/tests/standalone/io/process_run_output_test.dart b/tests/standalone/io/process_run_output_test.dart
index 86e833a..bc5a4e3 100644
--- a/tests/standalone/io/process_run_output_test.dart
+++ b/tests/standalone/io/process_run_output_test.dart
@@ -14,7 +14,7 @@
   } else if (encoding == 'latin1') {
     Expect.equals(output, 'æøå');
   } else if (encoding == 'utf8') {
-    Expect.listEquals(output.charCodes, [955]);
+    Expect.listEquals(output.codeUnits, [955]);
   }
 }
 
@@ -57,11 +57,11 @@
         new File("../tests/standalone/io/process_std_io_script2.dart");
   }
   Expect.isTrue(scriptFile.existsSync());
-  test(scriptFile.name, 'ascii', 'stdout');
-  test(scriptFile.name, 'ascii', 'stderr');
-  test(scriptFile.name, 'latin1', 'stdout');
-  test(scriptFile.name, 'latin1', 'stderr');
-  test(scriptFile.name, 'utf8', 'stdout');
-  test(scriptFile.name, 'utf8', 'stderr');
+  test(scriptFile.path, 'ascii', 'stdout');
+  test(scriptFile.path, 'ascii', 'stderr');
+  test(scriptFile.path, 'latin1', 'stdout');
+  test(scriptFile.path, 'latin1', 'stderr');
+  test(scriptFile.path, 'utf8', 'stdout');
+  test(scriptFile.path, 'utf8', 'stderr');
 
 }
diff --git a/tests/standalone/io/process_stderr_test.dart b/tests/standalone/io/process_stderr_test.dart
index 858bb9a..b38d1a1 100644
--- a/tests/standalone/io/process_stderr_test.dart
+++ b/tests/standalone/io/process_stderr_test.dart
@@ -21,7 +21,7 @@
       Expect.equals(expectedExitCode, exitCode);
     });
 
-    List<int> data = "ABCDEFGHI\n".charCodes;
+    List<int> data = "ABCDEFGHI\n".codeUnits;
     final int dataSize = data.length;
 
     int received = 0;
@@ -64,5 +64,5 @@
     scriptFile = new File("../tests/standalone/io/process_std_io_script.dart");
   }
   Expect.isTrue(scriptFile.existsSync());
-  test(Process.start(new Options().executable, [scriptFile.name, "1"]), 0);
+  test(Process.start(new Options().executable, [scriptFile.path, "1"]), 0);
 }
diff --git a/tests/standalone/io/process_stdin_transform_unsubscribe_script.dart b/tests/standalone/io/process_stdin_transform_unsubscribe_script.dart
new file mode 100644
index 0000000..0711124
--- /dev/null
+++ b/tests/standalone/io/process_stdin_transform_unsubscribe_script.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Utility script to echo stdin to stdout or stderr or both.
+
+import "dart:io";
+
+main() {
+  var subscription;
+  subscription = stdin
+      .transform(new StringDecoder())
+      .transform(new LineTransformer())
+      .listen((String line) {
+          // Unsubscribe after the first line.
+          subscription.cancel();
+        });
+}
diff --git a/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart b/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart
new file mode 100644
index 0000000..fddc35b
--- /dev/null
+++ b/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Process test program to test process communication.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:math';
+
+import "process_test_util.dart";
+
+void test(Future<Process> future, int expectedExitCode) {
+  future.then((process) {
+    process.exitCode.then((exitCode) {
+      Expect.equals(expectedExitCode, exitCode);
+    });
+
+    process.stdout.listen((_) {});
+    process.stderr.listen((_) {});
+    process.stdin.addString("Line1\n");
+  });
+}
+
+main() {
+  var scriptName = "process_stdin_transform_unsubscribe_script.dart";
+  var scriptFile = new File("tests/standalone/io/$scriptName");
+  if (!scriptFile.existsSync()) {
+    scriptFile = new File("../tests/standalone/io/$scriptName");
+  }
+  Expect.isTrue(scriptFile.existsSync());
+  test(Process.start(new Options().executable, [scriptFile.path]), 0);
+}
diff --git a/tests/standalone/io/process_stdout_test.dart b/tests/standalone/io/process_stdout_test.dart
index 698ab57..1cba732 100644
--- a/tests/standalone/io/process_stdout_test.dart
+++ b/tests/standalone/io/process_stdout_test.dart
@@ -21,7 +21,7 @@
       Expect.equals(expectedExitCode, exitCode);
     });
 
-    List<int> data = "ABCDEFGHI\n".charCodes;
+    List<int> data = "ABCDEFGHI\n".codeUnits;
     final int dataSize = data.length;
 
     int received = 0;
@@ -64,5 +64,5 @@
     scriptFile = new File("../tests/standalone/io/process_std_io_script.dart");
   }
   Expect.isTrue(scriptFile.existsSync());
-  test(Process.start(new Options().executable, [scriptFile.name, "0"]), 0);
+  test(Process.start(new Options().executable, [scriptFile.path, "0"]), 0);
 }
diff --git a/tests/standalone/io/raw_secure_server_closing_test.dart b/tests/standalone/io/raw_secure_server_closing_test.dart
index 1f8116d4..0fa8121 100644
--- a/tests/standalone/io/raw_secure_server_closing_test.dart
+++ b/tests/standalone/io/raw_secure_server_closing_test.dart
@@ -99,7 +99,7 @@
         connection.shutdown(SocketDirection.SEND);
       });
     }
-    new Timer(500, (_) {
+    new Timer(const Duration(milliseconds: 500), () {
       subscription.resume();
       resumed = true;
       for (int i = 0; i < socketCount; i++) {
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
index 73609ae..b12b87a 100644
--- a/tests/standalone/io/raw_secure_server_socket_test.dart
+++ b/tests/standalone/io/raw_secure_server_socket_test.dart
@@ -120,7 +120,7 @@
   RawSecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
     Expect.isTrue(server.port > 0);
     var clientEndFuture = RawSecureSocket.connect(HOST_NAME, server.port);
-    new Timer(500, (_) {
+    new Timer(const Duration(milliseconds: 500), () {
       server.listen((serverEnd) {
         clientEndFuture.then((clientEnd) {
           clientEnd.shutdown(SocketDirection.SEND);
@@ -143,7 +143,7 @@
   const messageSize = 1000;
 
   List<int> createTestData() {
-    List<int> data = new List.fixedLength(messageSize);
+    List<int> data = new List<int>(messageSize);
     for (int i = 0; i < messageSize; i++) {
       data[i] = i & 0xff;
     }
@@ -162,7 +162,7 @@
     server.listen((client) {
       int bytesRead = 0;
       int bytesWritten = 0;
-      List<int> data = new List.fixedLength(messageSize);
+      List<int> data = new List<int>(messageSize);
 
       client.writeEventsEnabled = false;
       client.listen((event) {
@@ -212,7 +212,7 @@
       int bytesRead = 0;
       int bytesWritten = 0;
       List<int> dataSent = createTestData();
-      List<int> dataReceived = new List<int>.fixedLength(dataSent.length);
+      List<int> dataReceived = new List<int>(dataSent.length);
       socket.listen((event) {
         switch (event) {
           case RawSocketEvent.READ:
diff --git a/tests/standalone/io/raw_secure_socket_pause_test.dart b/tests/standalone/io/raw_secure_socket_pause_test.dart
index 23b2eff..0a79475 100644
--- a/tests/standalone/io/raw_secure_socket_pause_test.dart
+++ b/tests/standalone/io/raw_secure_socket_pause_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
@@ -11,71 +11,97 @@
 import "dart:io";
 import "dart:isolate";
 
+Future<HttpServer> startServer() {
+  return HttpServer.bindSecure(
+      "127.0.0.1",
+      0,
+      backlog: 5,
+      certificateName: 'localhost_cert').then((server) {
+    server.listen((HttpRequest request) {
+      request.listen(
+        (_) { },
+        onDone: () {
+          request.response.contentLength = 100;
+          for (int i = 0; i < 10; i++) {
+            request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+          }
+          request.response.close();
+        });
+    });
+    return server;
+  });
+}
+
+void InitializeSSL() {
+  var testPkcertDatabase =
+      new Path(new Options().script).directoryPath.append('pkcert/');
+  SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
+                          password: 'dartdart');
+}
 
 void main() {
-  List<int> message = "GET / HTTP/1.0\r\nHost: www.google.dk\r\n\r\n".charCodes;
+  List<int> message = "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n".codeUnits;
   int written = 0;
-  List<String> chunks = <String>[];
-  SecureSocket.initialize();
-  // TODO(whesse): Use a Dart HTTPS server for this test.
-  // The Dart HTTPS server works on bleeding-edge, but not on IOv2.
-  // When we use a Dart HTTPS server, allow --short_socket_write. The flag
-  // causes fragmentation of the client hello message, which doesn't seem to
-  // work with www.google.dk.
-  RawSecureSocket.connect("www.google.dk", 443).then((socket) {
-    StreamSubscription subscription;
-    bool paused = false;
-    bool readEventsTested = false;
-    bool readEventsPaused = false;
+  List<int> body = <int>[];
+  InitializeSSL();
+  startServer().then((server) {
+    RawSecureSocket.connect("localhost", server.port).then((socket) {
+      StreamSubscription subscription;
+      bool paused = false;
+      bool readEventsTested = false;
+      bool readEventsPaused = false;
 
-    void runPauseTest() {
-      subscription.pause();
-      paused = true;
-      new Timer(500, (_) {
-          paused = false;
-          subscription.resume();
-      });
-    }
-
-    void runReadEventTest() {
-      if (readEventsTested) return;
-      readEventsTested = true;
-      socket.readEventsEnabled = false;
-      readEventsPaused = true;
-      new Timer(500, (_) {
-        readEventsPaused = false;
-        socket.readEventsEnabled = true;
-      });
-    }
-
-    subscription = socket.listen((RawSocketEvent event) {
-      Expect.isFalse(paused);
-      switch (event) {
-        case RawSocketEvent.READ:
-          Expect.isFalse(readEventsPaused);
-          runReadEventTest();
-          var data = socket.read();
-          var received = new String.fromCharCodes(data);
-          chunks.add(received);
-          break;
-        case RawSocketEvent.WRITE:
-          written +=
-              socket.write(message, written, message.length - written);
-          if (written < message.length) {
-            socket.writeEventsEnabled = true;
-          } else {
-            socket.shutdown(SocketDirection.SEND);
-            runPauseTest();
-          }
-          break;
-        case RawSocketEvent.READ_CLOSED:
-          String fullPage = chunks.join();
-          Expect.isTrue(fullPage.contains('</body></html>'));
-          break;
-        default: throw "Unexpected event $event";
+      void runPauseTest() {
+        subscription.pause();
+        paused = true;
+        new Timer(const Duration(milliseconds: 500), () {
+            paused = false;
+            subscription.resume();
+        });
       }
-      }, onError: (AsyncError a) {
-        Expect.fail("onError handler of RawSecureSocket stream hit: $a");
-      });
+
+      void runReadEventTest() {
+        if (readEventsTested) return;
+        readEventsTested = true;
+        socket.readEventsEnabled = false;
+        readEventsPaused = true;
+        new Timer(const Duration(milliseconds: 500), () {
+            readEventsPaused = false;
+            socket.readEventsEnabled = true;
+        });
+      }
+
+      subscription = socket.listen(
+          (RawSocketEvent event) {
+            Expect.isFalse(paused);
+            switch (event) {
+              case RawSocketEvent.READ:
+                Expect.isFalse(readEventsPaused);
+                runReadEventTest();
+                body.addAll(socket.read());
+                break;
+              case RawSocketEvent.WRITE:
+                written +=
+                    socket.write(message, written, message.length - written);
+                if (written < message.length) {
+                  socket.writeEventsEnabled = true;
+                } else {
+                  socket.shutdown(SocketDirection.SEND);
+                  runPauseTest();
+                }
+                break;
+              case RawSocketEvent.READ_CLOSED:
+                Expect.isTrue(body.length > 100);
+                Expect.equals(72, body[0]);
+                Expect.equals(9, body[body.length - 1]);
+                server.close();
+                break;
+              default: throw "Unexpected event $event";
+            }
+          },
+          onError: (AsyncError a) {
+            Expect.fail("onError handler of RawSecureSocket stream hit: $a");
+          });
+    });
   });
 }
diff --git a/tests/standalone/io/raw_secure_socket_test.dart b/tests/standalone/io/raw_secure_socket_test.dart
index b7f7068..1a828ce 100644
--- a/tests/standalone/io/raw_secure_socket_test.dart
+++ b/tests/standalone/io/raw_secure_socket_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
@@ -11,38 +11,68 @@
 import "dart:io";
 import "dart:isolate";
 
+Future<HttpServer> startServer() {
+  return HttpServer.bindSecure(
+      "127.0.0.1",
+      0,
+      backlog: 5,
+      certificateName: 'localhost_cert').then((server) {
+    server.listen((HttpRequest request) {
+      request.listen(
+        (_) { },
+        onDone: () {
+          request.response.contentLength = 100;
+          for (int i = 0; i < 10; i++) {
+            request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+          }
+          request.response.close();
+        });
+    });
+    return server;
+  });
+}
+
+void InitializeSSL() {
+  var testPkcertDatabase =
+      new Path(new Options().script).directoryPath.append('pkcert/');
+  SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
+                          password: 'dartdart');
+}
 
 void main() {
-  List<int> message = "GET / HTTP/1.0\r\nHost: www.google.dk\r\n\r\n".charCodes;
+  List<int> message = "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n".codeUnits;
   int written = 0;
-  List<String> chunks = <String>[];
-  SecureSocket.initialize();
-  // TODO(3593): Use a Dart HTTPS server for this test.
-  RawSecureSocket.connect("www.google.dk", 443).then((socket) {
-    socket.listen((RawSocketEvent event) {
-      switch (event) {
-        case RawSocketEvent.READ:
-          var data = socket.read();
-          var received = new String.fromCharCodes(data);
-          chunks.add(received);
-          break;
-        case RawSocketEvent.WRITE:
-          written +=
-              socket.write(message, written, message.length - written);
-          if (written < message.length) {
-            socket.writeEventsEnabled = true;
-          } else {
-            socket.shutdown(SocketDirection.SEND);
-          }
-          break;
-        case RawSocketEvent.READ_CLOSED:
-          String fullPage = chunks.join();
-          Expect.isTrue(fullPage.contains('</body></html>'));
-          break;
-        default: throw "Unexpected event $event";
-      }
-    }, onError: (AsyncError a) {
-      Expect.fail("onError handler of RawSecureSocket stream hit: $a");
+  List<int> body = <int>[];
+  InitializeSSL();
+  startServer().then((server) {
+    RawSecureSocket.connect("localhost", server.port).then((socket) {
+      socket.listen(
+          (RawSocketEvent event) {
+            switch (event) {
+              case RawSocketEvent.READ:
+                body.addAll(socket.read());
+                break;
+              case RawSocketEvent.WRITE:
+                written +=
+                    socket.write(message, written, message.length - written);
+                if (written < message.length) {
+                  socket.writeEventsEnabled = true;
+                } else {
+                  socket.shutdown(SocketDirection.SEND);
+                }
+                break;
+              case RawSocketEvent.READ_CLOSED:
+                Expect.isTrue(body.length > 100, "$body\n${body.length}");
+                Expect.equals(72, body[0]);
+                Expect.equals(9, body[body.length - 1]);
+                server.close();
+                break;
+              default: throw "Unexpected event $event";
+            }
+          },
+          onError: (AsyncError a) {
+            Expect.fail("onError handler of RawSecureSocket stream hit: $a");
+          });
     });
   });
 }
diff --git a/tests/standalone/io/raw_server_socket_cancel_test.dart b/tests/standalone/io/raw_server_socket_cancel_test.dart
new file mode 100644
index 0000000..0062a6e
--- /dev/null
+++ b/tests/standalone/io/raw_server_socket_cancel_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "dart:async";
+import "dart:io";
+import "dart:isolate";
+
+void testCancelResubscribeServerSocket() {
+  const int socketCount = 10;
+  var acceptCount = 0;
+  var doneCount = 0;
+  var closeCount = 0;
+  var errorCount = 0;
+
+  ReceivePort port = new ReceivePort();
+
+  RawServerSocket.bind().then((server) {
+    Expect.isTrue(server.port > 0);
+
+    void checkDone() {
+      if (doneCount == socketCount &&
+          closeCount + errorCount == socketCount) {
+        port.close();
+      }
+    }
+
+    // Subscribe the server socket. Then cancel subscription and
+    // subscribe again.
+    var subscription;
+    subscription = server.listen((client) {
+      if (++acceptCount == socketCount / 2) {
+        subscription.cancel();
+        Timer.run(() {
+          subscription = server.listen((_) {
+            // Close on cancel, so no more events.
+            Expect.fail("Event after closed through cancel");
+          });
+        });
+      }
+      // Close the client socket.
+      client.close();
+    });
+
+    // Connect a number of sockets.
+    for (int i = 0; i < socketCount; i++) {
+      RawSocket.connect("127.0.0.1", server.port).then((socket) {
+        socket.writeEventsEnabled = false;
+        var subscription;
+        subscription = socket.listen((event) {
+          Expect.equals(RawSocketEvent.READ_CLOSED, event);
+          socket.close();
+          closeCount++;
+          checkDone();
+        },
+        onDone: () { doneCount++; checkDone(); },
+        onError: (e) { errorCount++; checkDone(); });
+      }).catchError((e) {
+        errorCount++; checkDone();
+      });
+    }
+  });
+}
+
+void main() {
+  testCancelResubscribeServerSocket();
+}
diff --git a/tests/standalone/io/raw_socket_test.dart b/tests/standalone/io/raw_socket_test.dart
index d14dc9e..01e8e71 100644
--- a/tests/standalone/io/raw_socket_test.dart
+++ b/tests/standalone/io/raw_socket_test.dart
@@ -137,7 +137,7 @@
   const messageSize = 1000;
 
   List<int> createTestData() {
-    List<int> data = new List.fixedLength(messageSize);
+    List<int> data = new List<int>(messageSize);
     for (int i = 0; i < messageSize; i++) {
       data[i] = i & 0xff;
     }
@@ -156,7 +156,7 @@
     server.listen((client) {
       int bytesRead = 0;
       int bytesWritten = 0;
-      List<int> data = new List.fixedLength(messageSize);
+      List<int> data = new List<int>(messageSize);
 
       client.writeEventsEnabled = false;
       client.listen((event) {
@@ -212,7 +212,7 @@
             if (bytesWritten < data.length) {
               socket.writeEventsEnabled = true;
             } else {
-              data = new List.fixedLength(messageSize);
+              data = new List<int>(messageSize);
             }
             break;
           case RawSocketEvent.READ_CLOSED:
@@ -263,61 +263,7 @@
   });
 }
 
-testCancelResubscribeServerSocket() {
-  const int socketCount = 10;
-  var acceptCount = 0;
-  var doneCount = 0;
-  var closeCount = 0;
-  var errorCount = 0;
-
-  ReceivePort port = new ReceivePort();
-
-  RawServerSocket.bind().then((server) {
-    Expect.isTrue(server.port > 0);
-
-    void checkDone() {
-      if (doneCount == socketCount &&
-          closeCount + errorCount == socketCount) {
-        port.close();
-      }
-    }
-
-    // Subscribe the server socket. Then cancel subscription and
-    // subscribe again.
-    var subscription;
-    subscription = server.listen((client) {
-      if (++acceptCount == socketCount / 2) {
-        subscription.cancel();
-        new Timer(0, (_) {
-          subscription = server.listen((_) {
-            // Close on cancel, so no more events.
-            Expect.fail("Event after closed through cancel");
-          });
-        });
-      }
-      // Close the client socket.
-      client.close();
-    });
-
-    // Connect a number of sockets.
-    for (int i = 0; i < socketCount; i++) {
-      RawSocket.connect("127.0.0.1", server.port).then((socket) {
-        socket.writeEventsEnabled = false;
-        var subscription;
-        subscription = socket.listen((event) {
-          Expect.equals(RawSocketEvent.READ_CLOSED, event);
-          socket.close();
-          closeCount++;
-          checkDone();
-        },
-        onDone: () { doneCount++; checkDone(); },
-        onError: (e) { errorCount++; checkDone(); });
-      });
-    }
-  });
-}
-
-testPauseSocket() {
+void testPauseSocket() {
   const messageSize = 1000;
   const loopCount = 10;
   Completer connected = new Completer();
@@ -332,7 +278,7 @@
   RawServerSocket.bind().then((server) {
     Expect.isTrue(server.port > 0);
     server.listen((client) {
-      List<int> data = new List.fixedLength(messageSize, fill: 0);
+      List<int> data = new List<int>.filled(messageSize, 0);
       writeSubscription = client.listen((event) {
         switch (event) {
           case RawSocketEvent.READ:
@@ -407,6 +353,5 @@
   testServerListenAfterConnect();
   testSimpleReadWrite();
   testPauseServerSocket();
-  testCancelResubscribeServerSocket();
   testPauseSocket();
 }
diff --git a/tests/standalone/io/raw_socket_write_destroy_test.dart b/tests/standalone/io/raw_socket_write_destroy_test.dart
index b5e558a8..d7dc0d8 100644
--- a/tests/standalone/io/raw_socket_write_destroy_test.dart
+++ b/tests/standalone/io/raw_socket_write_destroy_test.dart
@@ -18,7 +18,7 @@
     server.listen((socket) {
       socket.writeEventsEnabled = false;
 
-      var buffer = new List.fixedLength(WROTE, fill: 0);
+      var buffer = new List.filled(WROTE, 0);
       int offset = 0;
       void write() {
         int n = socket.write(buffer, offset, buffer.length - offset);
@@ -69,7 +69,7 @@
     RawSocket.connect(SERVER_ADDRESS, server.port).then((socket) {
       socket.writeEventsEnabled = false;
 
-      var buffer = new List.fixedLength(WROTE, fill: 0);
+      var buffer = new List.filled(WROTE, 0);
       int offset = 0;
       void write() {
         int n = socket.write(buffer, offset, buffer.length - offset);
@@ -93,4 +93,4 @@
 void main() {
   testWriteDestroyServer();
   testWriteDestroyClient();
-}
\ No newline at end of file
+}
diff --git a/tests/standalone/io/regress_8828_test.dart b/tests/standalone/io/regress_8828_test.dart
new file mode 100644
index 0000000..be134ac
--- /dev/null
+++ b/tests/standalone/io/regress_8828_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import 'dart:io';
+
+void main() {
+  HttpServer.bind().then((server) {
+    server.listen((request) {
+      request.response
+        ..addString("first line\n")
+        ..addString("")
+        ..addString("second line\n")
+        ..close();
+    });
+
+    HttpClient client = new HttpClient();
+    client.get("127.0.0.1", server.port, "/")
+        .then((HttpClientRequest request) {
+          return request.close();
+        })
+        .then((HttpClientResponse response) {
+            List<int> body = new List();
+          response.listen(body.addAll,
+                          onDone: () {
+                            Expect.equals("first line\nsecond line\n",
+                                          new String.fromCharCodes(body));
+                            server.close();
+                          });
+        });
+  });
+}
diff --git a/tests/standalone/io/secure_client_raw_server_test.dart b/tests/standalone/io/secure_client_raw_server_test.dart
index 331ea6c..3049b23 100644
--- a/tests/standalone/io/secure_client_raw_server_test.dart
+++ b/tests/standalone/io/secure_client_raw_server_test.dart
@@ -61,7 +61,7 @@
   Completer success = new Completer();
   List<String> chunks = <String>[];
   SecureSocket.connect(HOST_NAME, server.port).then((socket) {
-    socket.add("Hello server.".charCodes);
+    socket.add("Hello server.".codeUnits);
     socket.close();
     socket.listen(
       (List<int> data) {
diff --git a/tests/standalone/io/secure_client_server_test.dart b/tests/standalone/io/secure_client_server_test.dart
index da48e87..bd6fe43 100644
--- a/tests/standalone/io/secure_client_server_test.dart
+++ b/tests/standalone/io/secure_client_server_test.dart
@@ -32,11 +32,11 @@
 
 Future testClient(server) {
   return SecureSocket.connect(HOST_NAME, server.port).then((socket) {
-    socket.add("Hello server.".charCodes);
+    socket.add("Hello server.".codeUnits);
     socket.close();
     return socket.reduce(<int>[], (message, data) => message..addAll(data))
         .then((message) {
-          Expect.listEquals("Hello server.".charCodes, message);
+          Expect.listEquals("Hello server.".codeUnits, message);
           return server;
         });
   });
diff --git a/tests/standalone/io/secure_multiple_client_server_test.dart b/tests/standalone/io/secure_multiple_client_server_test.dart
index 52e0b56..4b7f370 100644
--- a/tests/standalone/io/secure_multiple_client_server_test.dart
+++ b/tests/standalone/io/secure_multiple_client_server_test.dart
@@ -25,7 +25,7 @@
             String received = new String.fromCharCodes(message);
             Expect.isTrue(received.contains("Hello from client "));
             String name = received.substring(received.indexOf("client ") + 7);
-            client.add("Welcome, client $name".charCodes);
+            client.add("Welcome, client $name".codeUnits);
             client.close();
           });
     });
@@ -35,11 +35,11 @@
 
 Future testClient(server, name) {
   return SecureSocket.connect(HOST_NAME, server.port).then((socket) {
-    socket.add("Hello from client $name".charCodes);
+    socket.add("Hello from client $name".codeUnits);
     socket.close();
     return socket.reduce(<int>[], (message, data) => message..addAll(data))
         .then((message) {
-          Expect.listEquals("Welcome, client $name".charCodes, message);
+          Expect.listEquals("Welcome, client $name".codeUnits, message);
           return server;
         });
   });
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
index 5d75c6c..24e72a0 100644
--- a/tests/standalone/io/secure_server_client_certificate_test.dart
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -1,125 +1,127 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import "dart:async";
 import "dart:io";
 import "dart:isolate";
 
 const SERVER_ADDRESS = "127.0.0.1";
 const HOST_NAME = "localhost";
+const CERTIFICATE = "localhost_cert";
 
-void WriteAndClose(Socket socket, String message) {
-  var data = message.charCodes;
-  int written = 0;
-  void write() {
-    written += socket.writeList(data, written, data.length - written);
-    if (written < data.length) {
-      socket.onWrite = write;
-    } else {
-      socket.close(true);
-    }
-  }
-  write();
+void testClientCertificate() {
+  ReceivePort port = new ReceivePort();
+  SecureServerSocket.bind(SERVER_ADDRESS,
+                          0,
+                          5,
+                          CERTIFICATE,
+                          requestClientCertificate: true).then((server) {
+    var clientEndFuture = SecureSocket.connect(HOST_NAME,
+                                               server.port,
+                                               sendClientCertificate: true);
+    server.listen((serverEnd) {
+      X509Certificate certificate = serverEnd.peerCertificate;
+      Expect.isNotNull(certificate);
+      Expect.equals("CN=localhost", certificate.subject);
+      Expect.equals("CN=myauthority", certificate.issuer);
+      clientEndFuture.then((clientEnd) {
+        X509Certificate certificate = clientEnd.peerCertificate;
+        Expect.isNotNull(certificate);
+        Expect.equals("CN=localhost", certificate.subject);
+        Expect.equals("CN=myauthority", certificate.issuer);
+        clientEnd.close();
+        serverEnd.close();
+        server.close();
+        port.close();
+      });
+    });
+  });
 }
 
-class SecureTestServer {
-  void onConnection(Socket connection) {
-    connection.onConnect = () {
-      numConnections++;
-      var certificate = connection.peerCertificate;
-      Expect.isTrue(certificate.subject.contains("CN="));
-    };
-    String received = "";
-    connection.onData = () {
-      received = received.concat(new String.fromCharCodes(connection.read()));
-    };
-    connection.onClosed = () {
-      Expect.isTrue(received.contains("Hello from client "));
-      String name = received.substring(received.indexOf("client ") + 7);
-      WriteAndClose(connection, "Welcome, client $name");
-    };
-  }
-
-  void errorHandlerServer(Exception e) {
-    Expect.fail("Server socket error $e");
-  }
-
-  int start() {
-    server = new SecureServerSocket(SERVER_ADDRESS,
-                                    0,
-                                    10,
-                                    "localhost_cert",
-                                    requireClientCertificate: true);
-    Expect.isNotNull(server);
-    server.onConnection = onConnection;
-    server.onError = errorHandlerServer;
-    return server.port;
-  }
-
-  void stop() {
-    server.close();
-  }
-
-  int numConnections = 0;
-  SecureServerSocket server;
+void testRequiredClientCertificate() {
+  ReceivePort port = new ReceivePort();
+  SecureServerSocket.bind(SERVER_ADDRESS,
+                          0,
+                          5,
+                          CERTIFICATE,
+                          requireClientCertificate: true).then((server) {
+    var clientEndFuture = SecureSocket.connect(HOST_NAME,
+                                               server.port,
+                                               sendClientCertificate: true);
+    server.listen((serverEnd) {
+      X509Certificate certificate = serverEnd.peerCertificate;
+      Expect.isNotNull(certificate);
+      Expect.equals("CN=localhost", certificate.subject);
+      Expect.equals("CN=myauthority", certificate.issuer);
+      clientEndFuture.then((clientEnd) {
+        X509Certificate certificate = clientEnd.peerCertificate;
+        Expect.isNotNull(certificate);
+        Expect.equals("CN=localhost", certificate.subject);
+        Expect.equals("CN=myauthority", certificate.issuer);
+        clientEnd.close();
+        serverEnd.close();
+        server.close();
+        port.close();
+      });
+    });
+  });
 }
 
-class SecureTestClient {
-  SecureTestClient(int this.port, String this.name) {
-    socket = new SecureSocket(HOST_NAME, port, sendClientCertificate: true);
-    socket.onConnect = this.onConnect;
-    socket.onData = () {
-      reply = reply.concat(new String.fromCharCodes(socket.read()));
-    };
-    socket.onClosed = done;
-    reply = "";
-  }
-
-  void onConnect() {
-    numRequests++;
-    WriteAndClose(socket, "Hello from client $name");
-  }
-
-  void done() {
-    Expect.equals("Welcome, client $name", reply);
-    numReplies++;
-    if (numReplies == CLIENT_NAMES.length) {
-      Expect.equals(numRequests, numReplies);
-      EndTest();
-    }
-  }
-
-  static int numRequests = 0;
-  static int numReplies = 0;
-
-  int port;
-  String name;
-  SecureSocket socket;
-  String reply;
+void testNoClientCertificate() {
+  ReceivePort port = new ReceivePort();
+  SecureServerSocket.bind(SERVER_ADDRESS,
+                          0,
+                          5,
+                          CERTIFICATE,
+                          requestClientCertificate: true).then((server) {
+    var clientEndFuture = SecureSocket.connect(HOST_NAME,
+                                               server.port);
+    server.listen((serverEnd) {
+      X509Certificate certificate = serverEnd.peerCertificate;
+      Expect.isNull(certificate);
+      clientEndFuture.then((clientEnd) {
+        clientEnd.close();
+        serverEnd.close();
+        server.close();
+        port.close();
+      });
+    });
+  });
 }
 
-Function EndTest;
-
-const CLIENT_NAMES = const ['able', 'baker', 'camera', 'donut', 'echo'];
+void testNoRequiredClientCertificate() {
+  ReceivePort port = new ReceivePort();
+  bool clientError = false;
+  SecureServerSocket.bind(SERVER_ADDRESS,
+                          0,
+                          5,
+                          CERTIFICATE,
+                          requireClientCertificate: true).then((server) {
+    Future clientDone = SecureSocket.connect(HOST_NAME, server.port)
+      .catchError((e) { clientError = true; });
+    server.listen((serverEnd) {
+      Expect.fail("Got a unverifiable connection");
+    },
+    onError: (e) {
+      clientDone.then((_) {
+        Expect.isTrue(clientError);
+        server.close();
+        port.close();
+      });
+    });
+  });
+}
 
 void main() {
-  ReceivePort keepAlive = new ReceivePort();
   Path scriptDir = new Path(new Options().script).directoryPath;
   Path certificateDatabase = scriptDir.append('pkcert');
   SecureSocket.initialize(database: certificateDatabase.toNativePath(),
                           password: 'dartdart',
                           useBuiltinRoots: false);
 
-  var server = new SecureTestServer();
-  int port = server.start();
-
-  EndTest = () {
-    Expect.equals(CLIENT_NAMES.length, server.numConnections);
-    server.stop();
-    keepAlive.close();
-  };
-
-  for (var x in CLIENT_NAMES) {
-    new SecureTestClient(port, x);
-  }
+  testClientCertificate();
+  testRequiredClientCertificate();
+  testNoClientCertificate();
+  testNoRequiredClientCertificate();
 }
diff --git a/tests/standalone/io/secure_server_closing_test.dart b/tests/standalone/io/secure_server_closing_test.dart
index 794c54f..fde898c 100644
--- a/tests/standalone/io/secure_server_closing_test.dart
+++ b/tests/standalone/io/secure_server_closing_test.dart
@@ -105,7 +105,7 @@
         connection.close();
       });
     }
-    new Timer(500, (_) {
+    new Timer(const Duration(milliseconds: 500), () {
       subscription.resume();
       resumed = true;
       for (int i = 0; i < socketCount; i++) {
diff --git a/tests/standalone/io/secure_server_socket_test.dart b/tests/standalone/io/secure_server_socket_test.dart
index cadabf3..c66019a 100644
--- a/tests/standalone/io/secure_server_socket_test.dart
+++ b/tests/standalone/io/secure_server_socket_test.dart
@@ -119,7 +119,7 @@
   SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
     Expect.isTrue(server.port > 0);
     var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port);
-    new Timer(500, (_) {
+    new Timer(const Duration(milliseconds: 500), () {
       server.listen((serverEnd) {
         clientEndFuture.then((clientEnd) {
           clientEnd.close();
@@ -142,7 +142,7 @@
   const messageSize = 1000;
 
   List<int> createTestData() {
-    List<int> data = new List.fixedLength(messageSize);
+    List<int> data = new List<int>(messageSize);
     for (int i = 0; i < messageSize; i++) {
       data[i] = i & 0xff;
     }
@@ -161,7 +161,7 @@
     server.listen((client) {
       int bytesRead = 0;
       int bytesWritten = 0;
-      List<int> data = new List.fixedLength(messageSize);
+      List<int> data = new List<int>(messageSize);
 
       client.listen(
         (buffer) {
@@ -183,7 +183,7 @@
       int bytesRead = 0;
       int bytesWritten = 0;
       List<int> dataSent = createTestData();
-      List<int> dataReceived = new List<int>.fixedLength(dataSent.length);
+      List<int> dataReceived = new List<int>(dataSent.length);
       socket.add(dataSent);
       socket.close();  // Can also be delayed.
       socket.listen(
diff --git a/tests/standalone/io/secure_session_resume_test.dart b/tests/standalone/io/secure_session_resume_test.dart
index b1cf5ebf..f862c64 100644
--- a/tests/standalone/io/secure_session_resume_test.dart
+++ b/tests/standalone/io/secure_session_resume_test.dart
@@ -34,7 +34,7 @@
             String received = new String.fromCharCodes(message);
             Expect.isTrue(received.contains("Hello from client "));
             String name = received.substring(received.indexOf("client ") + 7);
-            client.add("Welcome, client $name".charCodes);
+            client.add("Welcome, client $name".codeUnits);
             client.close();
           });
     });
@@ -44,11 +44,11 @@
 
 Future testClient(server, name) {
   return SecureSocket.connect(HOST_NAME, server.port).then((socket) {
-    socket.add("Hello from client $name".charCodes);
+    socket.add("Hello from client $name".codeUnits);
     socket.close();
     return socket.reduce(<int>[], (message, data) => message..addAll(data))
         .then((message) {
-          Expect.listEquals("Welcome, client $name".charCodes, message);
+          Expect.listEquals("Welcome, client $name".codeUnits, message);
           return server;
         });
   });
diff --git a/tests/standalone/io/secure_socket_bad_certificate_test.dart b/tests/standalone/io/secure_socket_bad_certificate_test.dart
index 4e8bc0e..3f2b320 100644
--- a/tests/standalone/io/secure_socket_bad_certificate_test.dart
+++ b/tests/standalone/io/secure_socket_bad_certificate_test.dart
@@ -49,7 +49,7 @@
                               onBadCertificate: badCertificateCallback)
       .then((socket) {
         Expect.isTrue(acceptCertificate);
-        socket.add("GET / HTTP/1.0\r\nHost: $host\r\n\r\n".charCodes);
+        socket.add("GET / HTTP/1.0\r\nHost: $host\r\n\r\n".codeUnits);
         socket.close();
         return socket.reduce(<int>[], (message, data)  => message..addAll(data))
             .then((message) {
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
index fec1115..abe27b1 100644
--- a/tests/standalone/io/secure_socket_test.dart
+++ b/tests/standalone/io/secure_socket_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
@@ -7,26 +7,55 @@
 // VMOptions=--short_socket_write
 // VMOptions=--short_socket_read --short_socket_write
 
-import "dart:isolate";
+import "dart:async";
 import "dart:io";
 
+Future<HttpServer> startServer() {
+  return HttpServer.bindSecure(
+      "127.0.0.1",
+      0,
+      backlog: 5,
+      certificateName: 'localhost_cert').then((server) {
+    server.listen((HttpRequest request) {
+      request.listen(
+        (_) { },
+        onDone: () {
+          request.response.contentLength = 100;
+          for (int i = 0; i < 10; i++) {
+            request.response.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
+          }
+          request.response.close();
+        });
+    });
+    return server;
+  });
+}
+
+void InitializeSSL() {
+  var testPkcertDatabase =
+      new Path(new Options().script).directoryPath.append('pkcert/');
+  SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
+                          password: 'dartdart');
+}
+
 void main() {
-  ReceivePort keepAlive = new ReceivePort();
-  SecureSocket.initialize();
-  List<String> chunks = <String>[];
-  SecureSocket.connect("www.google.dk", 443).then((socket) {
-    socket.add("GET / HTTP/1.0\r\nHost: www.google.dk\r\n\r\n".charCodes);
-    socket.close();
-    socket.listen(
-      (List<int> data) {
-        var received = new String.fromCharCodes(data);
-        chunks.add(received);
-      },
-      onDone: () {
-        String fullPage = chunks.join();
-        Expect.isTrue(fullPage.contains('</body></html>'));
-        keepAlive.close();
-      },
-      onError: (e) => Expect.fail("Unexpected error $e"));
+  InitializeSSL();
+  List<int> body = <int>[];
+  startServer().then((server) {
+    SecureSocket.connect("localhost", server.port).then((socket) {
+      socket.add("GET / HTTP/1.0\r\nHost: localhost\r\n\r\n".codeUnits);
+      socket.close();
+      socket.listen(
+        (List<int> data) {
+          body.addAll(data);
+        },
+        onDone: () {
+          Expect.isTrue(body.length > 100, "$body\n${body.length}");
+          Expect.equals(72, body[0]);
+          Expect.equals(9, body[body.length - 1]);
+          server.close();
+        },
+        onError: (e) => Expect.fail("Unexpected error $e"));
+    });
   });
 }
diff --git a/tests/standalone/io/socket_close_test.dart b/tests/standalone/io/socket_close_test.dart
index dcb90a2..4d72f3c 100644
--- a/tests/standalone/io/socket_close_test.dart
+++ b/tests/standalone/io/socket_close_test.dart
@@ -101,7 +101,7 @@
           onError: (error) => errorHandler(socket));
 
       void writeHello() {
-        socket.add("Hello".charCodes);
+        socket.add("Hello".codeUnits);
       }
 
       _iterations++;
@@ -224,7 +224,7 @@
     }
 
     void writeHello() {
-      connection.add("Hello".charCodes);
+      connection.add("Hello".codeUnits);
     }
 
     void dataHandler(bytes) {
diff --git a/tests/standalone/io/socket_exception_test.dart b/tests/standalone/io/socket_exception_test.dart
index 7624ac7..f2fec68 100644
--- a/tests/standalone/io/socket_exception_test.dart
+++ b/tests/standalone/io/socket_exception_test.dart
@@ -87,7 +87,7 @@
         Expect.isFalse(exceptionCaught);
         Expect.isFalse(wrongExceptionCaught);
         try {
-          List<int> buffer = new List<int>.fixedLength(10);
+          List<int> buffer = new List<int>(10);
           client.add(buffer);
         } on StateError catch (ex) {
           exceptionCaught = true;
@@ -121,7 +121,7 @@
       });
       Socket.connect("127.0.0.1", server.port).then((client) {
         client.listen((data) {}, onDone: server.close);
-        client.add(new List.fixedLength(1024 * 1024, fill: 0));
+        client.add(new List.filled(1024 * 1024, 0));
         client.destroy();
       });
     });
@@ -143,7 +143,7 @@
               Expect.equals(SIZE, count);
               server.close();
             });
-        client.add(new List.fixedLength(SIZE, fill: 0));
+        client.add(new List.filled(SIZE, 0));
         client.close();
         // Start piping now.
         completer.complete(null);
@@ -174,7 +174,7 @@
               Expect.isTrue(errors <= 1);
               server.close();
             });
-        client.add(new List.fixedLength(SIZE, fill: 0));
+        client.add(new List.filled(SIZE, 0));
         // Destroy other socket now.
         completer.complete(null);
         var port = new ReceivePort();
@@ -199,7 +199,7 @@
       Socket.connect("127.0.0.1", server.port).then((client) {
         const int SIZE = 1024 * 1024;
         int errors = 0;
-        client.add(new List.fixedLength(SIZE, fill: 0));
+        client.add(new List.filled(SIZE, 0));
         client.close();
         client.done.catchError((error) {
           server.close();
diff --git a/tests/standalone/io/socket_many_connections_test.dart b/tests/standalone/io/socket_many_connections_test.dart
index c313fe1..49aa34d 100644
--- a/tests/standalone/io/socket_many_connections_test.dart
+++ b/tests/standalone/io/socket_many_connections_test.dart
@@ -17,7 +17,7 @@
       : _receivePort = new ReceivePort(),
         _sendPort = null,
         _connections = 0,
-        _sockets = new List<Socket>.fixedLength(CONNECTIONS) {
+        _sockets = new List<Socket>(CONNECTIONS) {
     _sendPort = spawnFunction(startTestServer);
     initialize();
   }
diff --git a/tests/standalone/io/stdout_bad_argument_test.dart b/tests/standalone/io/stdout_bad_argument_test.dart
new file mode 100644
index 0000000..95ce44d
--- /dev/null
+++ b/tests/standalone/io/stdout_bad_argument_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+main() {
+  stdout.add("Hello\n");
+  stdout.done.catchError((e) {
+    exit(0);
+  });
+  stdin.listen(print);
+}
diff --git a/tests/standalone/io/stream_pipe_test.dart b/tests/standalone/io/stream_pipe_test.dart
index f663e81..46590fa 100644
--- a/tests/standalone/io/stream_pipe_test.dart
+++ b/tests/standalone/io/stream_pipe_test.dart
@@ -34,8 +34,8 @@
     }
   }
   if (count == null) count = length1;
-  var data1 = new List<int>.fixedLength(count);
-  var data2 = new List<int>.fixedLength(count);
+  var data1 = new List<int>(count);
+  var data2 = new List<int>(count);
   if (file1Offset != 0) file1.setPositionSync(file1Offset);
   if (file2Offset != 0) file2.setPositionSync(file2Offset);
   var read1 = file1.readListSync(data1, 0, count);
@@ -112,7 +112,7 @@
                                        dstFileName,
                                        count: srcLength));
       dst.setPositionSync(srcLength);
-      var data = new List<int>.fixedLength(1);
+      var data = new List<int>(1);
       var read2 = dst.readListSync(data, 0, 1);
       Expect.equals(32, data[0]);
       src.closeSync();
diff --git a/tests/standalone/io/string_decoder_test.dart b/tests/standalone/io/string_decoder_test.dart
index 6a81f95..4952676 100644
--- a/tests/standalone/io/string_decoder_test.dart
+++ b/tests/standalone/io/string_decoder_test.dart
@@ -15,7 +15,7 @@
   controller.add([0xfd, 0x80, 0x80, 0x80, 0x80, 0x80]);  // U+40000000
   controller.close();
 
-  var decoder = new StringDecoder(Encoding.UTF_8, '?'.charCodeAt(0));
+  var decoder = new StringDecoder(Encoding.UTF_8, '?'.codeUnitAt(0));
   var stream = controller.stream.transform(decoder);
   stream.reduce(
       new StringBuffer(),
@@ -27,14 +27,14 @@
       .then((decoded) {
         Expect.equals(7, decoded.length);
 
-        var replacementChar = '?'.charCodeAt(0);
-        Expect.equals(0xd800, decoded.charCodeAt(0));
-        Expect.equals(0xdc00, decoded.charCodeAt(1));
-        Expect.equals(0xdbff, decoded.charCodeAt(2));
-        Expect.equals(0xdfff, decoded.charCodeAt(3));
-        Expect.equals(replacementChar, decoded.charCodeAt(4));
-        Expect.equals(replacementChar, decoded.charCodeAt(5));
-        Expect.equals(replacementChar, decoded.charCodeAt(6));
+        var replacementChar = '?'.codeUnitAt(0);
+        Expect.equals(0xd800, decoded.codeUnitAt(0));
+        Expect.equals(0xdc00, decoded.codeUnitAt(1));
+        Expect.equals(0xdbff, decoded.codeUnitAt(2));
+        Expect.equals(0xdfff, decoded.codeUnitAt(3));
+        Expect.equals(replacementChar, decoded.codeUnitAt(4));
+        Expect.equals(replacementChar, decoded.codeUnitAt(5));
+        Expect.equals(replacementChar, decoded.codeUnitAt(6));
       });
 }
 
@@ -46,7 +46,7 @@
     controller.stream.transform(new StringDecoder()).listen((string) {
       Expect.equals(outputLength, string.length);
       for (var i = 0; i < outputLength; i++) {
-        Expect.equals(0xFFFD, string.charCodeAt(i));
+        Expect.equals(0xFFFD, string.codeUnitAt(i));
       }
     });
   }
diff --git a/tests/standalone/io/string_transformer_test.dart b/tests/standalone/io/string_transformer_test.dart
index 16b1b3f..2a9015e 100644
--- a/tests/standalone/io/string_transformer_test.dart
+++ b/tests/standalone/io/string_transformer_test.dart
@@ -114,7 +114,7 @@
       stringData,
       onDone: streamClosed);
 
-  controller.add("Line".charCodes);
+  controller.add("Line".codeUnits);
 }
 
 void testReadLine2() {
@@ -138,7 +138,7 @@
           Expect.equals("Line3", line);
           subStage = 0;
           stage++;
-          controller.add("ne4\n".charCodes);
+          controller.add("ne4\n".codeUnits);
         } else {
           Expect.fail("Stage 0 failed");
         }
@@ -147,7 +147,7 @@
           Expect.equals("Line4", line);
           subStage = 0;
           stage++;
-          controller.add("\n\n\r\n\r\n\r\r".charCodes);
+          controller.add("\n\n\r\n\r\n\r\r".codeUnits);
         } else {
           Expect.fail("Stage 1 failed");
         }
@@ -178,7 +178,7 @@
       Expect.equals(0, subStage);
     });
 
-  controller.add("Line1\nLine2\r\nLine3\rLi".charCodes);
+  controller.add("Line1\nLine2\r\nLine3\rLi".codeUnits);
 }
 
 class TestException implements Exception {
@@ -221,7 +221,6 @@
       Expect.fail("data not expected");
     },
     onError: (error) {
-    print(error);
       Expect.isTrue(error.error is FormatException);
     });
 
diff --git a/tests/standalone/io/url_encoding_test.dart b/tests/standalone/io/url_encoding_test.dart
index cfeefe5..788dfb1 100644
--- a/tests/standalone/io/url_encoding_test.dart
+++ b/tests/standalone/io/url_encoding_test.dart
@@ -5,7 +5,7 @@
 import "dart:async";
 import "dart:utf";
 
-part '../../../sdk/lib/io/io_stream_consumer.dart';
+part '../../../sdk/lib/io/io_sink.dart';
 part "../../../sdk/lib/io/http.dart";
 part "../../../sdk/lib/io/http_impl.dart";
 part "../../../sdk/lib/io/http_parser.dart";
diff --git a/tests/standalone/io/web_socket_no_secure_test.dart b/tests/standalone/io/web_socket_no_secure_test.dart
deleted file mode 100644
index 46e1d03..0000000
--- a/tests/standalone/io/web_socket_no_secure_test.dart
+++ /dev/null
@@ -1,281 +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.
-//
-// VMOptions=
-// VMOptions=--short_socket_read
-// VMOptions=--short_socket_write
-// VMOptions=--short_socket_read --short_socket_write
-
-// TODO(7157): Remove this test once the bug is fixed.
-// This is a copy of web_socket_test.dart with the secure connection
-// tests disabled, so it does not crash on Windows.
-import "dart:io";
-import "dart:isolate";
-import "dart:scalarlist";
-
-void testRequestResponseClientCloses(
-    int totalConnections, int closeStatus, String closeReason) {
-  HttpServer.bind().then((server) {
-
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      webSocket.listen((event) {
-        if (event is MessageEvent) {
-          webSocket.send(event.data);
-        } else if (event is CloseEvent) {
-          Expect.equals(closeStatus == null
-                        ? WebSocketStatus.NO_STATUS_RECEIVED
-                        : closeStatus, event.code);
-          Expect.equals(closeReason == null ? "" : closeReason, event.reason);
-        }
-      });
-    });
-
-    int closeCount = 0;
-    String messageText = "Hello, world!";
-    for (int i = 0; i < totalConnections; i++) {
-      int messageCount = 0;
-       WebSocket.connect("ws://127.0.0.1:${server.port}/")
-        .then((webSocket) {
-          webSocket.send(messageText);
-          webSocket.listen((event) {
-            if (event is MessageEvent) {
-              messageCount++;
-              if (messageCount < 1 ) {
-                Expect.equals(messageText, event.data);
-                webSocket.send(event.data);
-              } else {
-                webSocket.close(closeStatus, closeReason);
-              }
-            } else if (event is CloseEvent) {
-              Expect.equals(closeStatus == null
-                            ? WebSocketStatus.NO_STATUS_RECEIVED
-                            : closeStatus, event.code);
-              Expect.equals("", event.reason);
-              closeCount++;
-              if (closeCount == totalConnections) {
-                server.close();
-              }
-            }
-          });
-        });
-    }
-
-  });
-}
-
-
-void testRequestResponseServerCloses(
-    int totalConnections, int closeStatus, String closeReason) {
-  HttpServer.bind().then((server) {
-
-    int closeCount = 0;
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      String messageText = "Hello, world!";
-      int messageCount = 0;
-      webSocket.listen((event) {
-        if (event is MessageEvent) {
-          messageCount++;
-          if (messageCount < 10) {
-            Expect.equals(messageText, event.data);
-            webSocket.send(event.data);
-          } else {
-            webSocket.close(closeStatus, closeReason);
-          }
-        } else if (event is CloseEvent) {
-          Expect.equals(closeStatus == null
-                        ? WebSocketStatus.NO_STATUS_RECEIVED
-                        : closeStatus, event.code);
-          Expect.equals("", event.reason);
-          closeCount++;
-          if (closeCount == totalConnections) {
-            server.close();
-          }
-        }
-      });
-      webSocket.send(messageText);
-    });
-
-    for (int i = 0; i < totalConnections; i++) {
-      WebSocket.connect("ws://127.0.0.1:${server.port}/")
-        .then((webSocket) {
-          webSocket.listen((event) {
-            if (event is MessageEvent) {
-              webSocket.send(event.data);
-            } else if (event is CloseEvent) {
-              Expect.equals(closeStatus == null
-                            ? WebSocketStatus.NO_STATUS_RECEIVED
-                            : closeStatus, event.code);
-              Expect.equals(
-                  closeReason == null ? "" : closeReason, event.reason);
-            }
-          });
-        });
-    }
-
-  });
-}
-
-
-void testMessageLength(int messageLength) {
-  HttpServer.bind().then((server) {
-
-    Uint8List originalMessage = new Uint8List(messageLength);
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      webSocket.listen((event) {
-        if (event is MessageEvent) {
-          Expect.listEquals(originalMessage, event.data);
-          webSocket.send(event.data);
-        } else if (event is CloseEvent) {
-        }
-      });
-    });
-
-    WebSocket.connect("ws://127.0.0.1:${server.port}/")
-      .then((webSocket) {
-        webSocket.listen((event) {
-          if (event is MessageEvent) {
-            Expect.listEquals(originalMessage, event.data);
-            webSocket.close();
-          } else if (event is CloseEvent) {
-            server.close();
-          }
-        });
-        webSocket.send(originalMessage);
-      });
-
-  });
-}
-
-
-void testNoUpgrade() {
-  HttpServer.bind().then((server) {
-
-    // Create a server which always responds with NOT_FOUND.
-    server.listen((request) {
-      request.response.statusCode = HttpStatus.NOT_FOUND;
-      request.response.close();
-    });
-
-    WebSocket.connect("ws://127.0.0.1:${server.port}/").catchError((error) {
-      server.close();
-    });
-
-  });
-}
-
-
-void testUsePOST() {
-  HttpServer.bind().then((server) {
-
-    var errorPort = new ReceivePort();
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      Expect.fail("No connection expected");
-    }, onError: (e) {
-      errorPort.close();
-    });
-
-    HttpClient client = new HttpClient();
-    client.post("127.0.0.1", server.port, "/")
-      .then((request) => request.close())
-      .then((response) {
-        Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode);
-        client.close();
-        server.close();
-      });
-
-  });
-}
-
-
-class WebSocketInfo {
-  int messageCount = 0;
-}
-
-
-void testW3CInterface(
-    int totalConnections, int closeStatus, String closeReason) {
-  HttpServer.bind().then((server) {
-
-    int closeCount = 0;
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      String messageText = "Hello, world!";
-      int messageCount = 0;
-      webSocket.listen((event) {
-        if (event is MessageEvent) {
-          messageCount++;
-          if (messageCount < 10) {
-            Expect.equals(messageText, event.data);
-            webSocket.send(event.data);
-          } else {
-            webSocket.close(closeStatus, closeReason);
-          }
-        } else if (event is CloseEvent) {
-          Expect.equals(closeStatus, event.code);
-          Expect.equals("", event.reason);
-          closeCount++;
-          if (closeCount == totalConnections) {
-            server.close();
-          }
-        }
-      });
-      webSocket.send(messageText);
-    });
-
-    void webSocketConnection() {
-      bool onopenCalled = false;
-      int onmessageCalled = 0;
-      bool oncloseCalled = false;
-
-      WebSocket.connect("ws://127.0.0.1:${server.port}").then((webSocket) {
-        Expect.isFalse(onopenCalled);
-        Expect.equals(0, onmessageCalled);
-        Expect.isFalse(oncloseCalled);
-        onopenCalled = true;
-        Expect.equals(WebSocket.OPEN, webSocket.readyState);
-        webSocket.listen((event) {
-         if (event is MessageEvent) {
-            onmessageCalled++;
-            Expect.isTrue(onopenCalled);
-            Expect.isFalse(oncloseCalled);
-            Expect.equals(WebSocket.OPEN, webSocket.readyState);
-            webSocket.send(event.data);
-          } else if (event is CloseEvent) {
-            Expect.isTrue(onopenCalled);
-            Expect.equals(10, onmessageCalled);
-            Expect.isFalse(oncloseCalled);
-            oncloseCalled = true;
-            Expect.isTrue(event.wasClean);
-            Expect.equals(3002, event.code);
-            Expect.equals("Got tired", event.reason);
-            Expect.equals(WebSocket.CLOSED, webSocket.readyState);
-          }
-        });
-      });
-    }
-
-    for (int i = 0; i < totalConnections; i++) {
-      webSocketConnection();
-    }
-
-  });
-}
-
-
-main() {
-  testRequestResponseClientCloses(2, null, null);
-  testRequestResponseClientCloses(2, 3001, null);
-  testRequestResponseClientCloses(2, 3002, "Got tired");
-  testRequestResponseServerCloses(2, null, null);
-  testRequestResponseServerCloses(2, 3001, null);
-  testRequestResponseServerCloses(2, 3002, "Got tired");
-  testMessageLength(125);
-  testMessageLength(126);
-  testMessageLength(127);
-  testMessageLength(65535);
-  testMessageLength(65536);
-  testNoUpgrade();
-  testUsePOST();
-
-  testW3CInterface(2, 3002, "Got tired");
-}
diff --git a/tests/standalone/io/web_socket_protocol_processor_test.dart b/tests/standalone/io/web_socket_protocol_processor_test.dart
index 6ab0da9..9c891d6 100644
--- a/tests/standalone/io/web_socket_protocol_processor_test.dart
+++ b/tests/standalone/io/web_socket_protocol_processor_test.dart
@@ -6,7 +6,7 @@
 import "dart:async";
 
 part "../../../sdk/lib/io/http.dart";
-part "../../../sdk/lib/io/io_stream_consumer.dart";
+part "../../../sdk/lib/io/io_sink.dart";
 part "../../../sdk/lib/io/websocket.dart";
 part "../../../sdk/lib/io/websocket_impl.dart";
 
@@ -75,7 +75,7 @@
   frameSize += count;
   // No masking.
   assert(maskingKey == null);
-  List<int> frame = new List<int>.fixedLength(frameSize);
+  List<int> frame = new List<int>(frameSize);
   int frameIndex = 0;
   frame[frameIndex++] = (fin ? 0x80 : 0x00) | opcode;
   if (count < 126) {
@@ -136,7 +136,7 @@
 
   void runTest(int from, int to, int step) {
     for (int messageLength = from; messageLength < to; messageLength += step) {
-      List<int> message = new List<int>.fixedLength(messageLength);
+      List<int> message = new List<int>(messageLength);
       for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
       testMessage(FRAME_OPCODE_TEXT, message);
       testMessage(FRAME_OPCODE_BINARY, message);
@@ -202,7 +202,7 @@
 
   void runTest(int from, int to, int step) {
     for (int messageLength = from; messageLength < to; messageLength += step) {
-      List<int> message = new List<int>.fixedLength(messageLength);
+      List<int> message = new List<int>(messageLength);
       for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF;
       testMessageFragmentation(FRAME_OPCODE_TEXT, message);
       testMessageFragmentation(FRAME_OPCODE_BINARY, message);
diff --git a/tests/standalone/io/web_socket_test.dart b/tests/standalone/io/web_socket_test.dart
index baa6ddd..937467a 100644
--- a/tests/standalone/io/web_socket_test.dart
+++ b/tests/standalone/io/web_socket_test.dart
@@ -7,272 +7,366 @@
 // VMOptions=--short_socket_write
 // VMOptions=--short_socket_read --short_socket_write
 
+import "dart:async";
 import "dart:io";
 import "dart:isolate";
 import "dart:scalarlist";
+import "dart:uri";
 
-void testRequestResponseClientCloses(
-    int totalConnections, int closeStatus, String closeReason) {
-  HttpServer.bind().then((server) {
+const String CERT_NAME = 'localhost_cert';
+const String SERVER_ADDRESS = '127.0.0.1';
+const String HOST_NAME = 'localhost';
 
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      webSocket.listen((event) {
-        if (event is MessageEvent) {
-          webSocket.send(event.data);
-        } else if (event is CloseEvent) {
-          Expect.equals(closeStatus == null
-                        ? WebSocketStatus.NO_STATUS_RECEIVED
-                        : closeStatus, event.code);
-          Expect.equals(closeReason == null ? "" : closeReason, event.reason);
-        }
-      });
-    });
+/**
+ * A SecurityConfiguration lets us run the tests over HTTP or HTTPS.
+ */
+class SecurityConfiguration {
+  final bool secure;
 
-    int closeCount = 0;
-    String messageText = "Hello, world!";
-    for (int i = 0; i < totalConnections; i++) {
-      int messageCount = 0;
-       WebSocket.connect("ws://127.0.0.1:${server.port}/")
-        .then((webSocket) {
+  SecurityConfiguration({bool this.secure});
+
+  Future<HttpServer> createServer({int backlog: 0}) =>
+      secure ? HttpServer.bindSecure(SERVER_ADDRESS,
+                                     0,
+                                     backlog: backlog,
+                                     certificateName: CERT_NAME)
+             : HttpServer.bind(SERVER_ADDRESS,
+                               0,
+                               backlog);
+
+  Future<WebSocket> createClient(int port) =>
+    WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/');
+
+  void testRequestResponseClientCloses(int totalConnections,
+                                       int closeStatus,
+                                       String closeReason) {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        webSocket.listen(
+            webSocket.send,
+            onDone: () {
+              Expect.equals(closeStatus == null
+                            ? WebSocketStatus.NO_STATUS_RECEIVED
+                            : closeStatus, webSocket.closeCode);
+              Expect.equals(closeReason == null ? "" : closeReason, webSocket.closeReason);
+            });
+        });
+
+      int closeCount = 0;
+      String messageText = "Hello, world!";
+      for (int i = 0; i < totalConnections; i++) {
+        int messageCount = 0;
+        createClient(server.port).then((webSocket) {
           webSocket.send(messageText);
-          webSocket.listen((event) {
-            if (event is MessageEvent) {
+          webSocket.listen(
+              (message) {
+                messageCount++;
+                if (messageCount < 1 ) {
+                  Expect.equals(messageText, message);
+                  webSocket.send(message);
+                } else {
+                  webSocket.close(closeStatus, closeReason);
+                }
+              },
+              onDone: () {
+                Expect.equals(closeStatus == null
+                              ? WebSocketStatus.NO_STATUS_RECEIVED
+                              : closeStatus, webSocket.closeCode);
+                Expect.equals("", webSocket.closeReason);
+                closeCount++;
+                if (closeCount == totalConnections) {
+                  server.close();
+                }
+              });
+          });
+      }
+    });
+  }
+
+  void testRequestResponseServerCloses(int totalConnections,
+                                       int closeStatus,
+                                       String closeReason) {
+    createServer().then((server) {
+      int closeCount = 0;
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        String messageText = "Hello, world!";
+        int messageCount = 0;
+        webSocket.listen(
+            (message) {
               messageCount++;
-              if (messageCount < 1 ) {
-                Expect.equals(messageText, event.data);
-                webSocket.send(event.data);
+              if (messageCount < 10) {
+                Expect.equals(messageText, message);
+                webSocket.send(message);
               } else {
                 webSocket.close(closeStatus, closeReason);
               }
-            } else if (event is CloseEvent) {
+            },
+            onDone: () {
               Expect.equals(closeStatus == null
                             ? WebSocketStatus.NO_STATUS_RECEIVED
-                            : closeStatus, event.code);
-              Expect.equals("", event.reason);
+                            : closeStatus, webSocket.closeCode);
+              Expect.equals("", webSocket.closeReason);
               closeCount++;
               if (closeCount == totalConnections) {
                 server.close();
               }
-            }
-          });
-        });
-    }
-
-  });
-}
-
-
-void testRequestResponseServerCloses(
-    int totalConnections, int closeStatus, String closeReason) {
-  HttpServer.bind().then((server) {
-
-    int closeCount = 0;
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      String messageText = "Hello, world!";
-      int messageCount = 0;
-      webSocket.listen((event) {
-        if (event is MessageEvent) {
-          messageCount++;
-          if (messageCount < 10) {
-            Expect.equals(messageText, event.data);
-            webSocket.send(event.data);
-          } else {
-            webSocket.close(closeStatus, closeReason);
-          }
-        } else if (event is CloseEvent) {
-          Expect.equals(closeStatus == null
-                        ? WebSocketStatus.NO_STATUS_RECEIVED
-                        : closeStatus, event.code);
-          Expect.equals("", event.reason);
-          closeCount++;
-          if (closeCount == totalConnections) {
-            server.close();
-          }
-        }
+            });
+        webSocket.send(messageText);
       });
-      webSocket.send(messageText);
+
+      for (int i = 0; i < totalConnections; i++) {
+        createClient(server.port).then((webSocket) {
+            webSocket.listen(
+                webSocket.send,
+                onDone: () {
+                  Expect.equals(closeStatus == null
+                                ? WebSocketStatus.NO_STATUS_RECEIVED
+                                : closeStatus, event.code);
+                  Expect.equals(
+                      closeReason == null ? "" : closeReason, event.reason);
+                });
+            });
+      }
     });
-
-    for (int i = 0; i < totalConnections; i++) {
-      WebSocket.connect("ws://127.0.0.1:${server.port}/")
-        .then((webSocket) {
-          webSocket.listen((event) {
-            if (event is MessageEvent) {
-              webSocket.send(event.data);
-            } else if (event is CloseEvent) {
-              Expect.equals(closeStatus == null
-                            ? WebSocketStatus.NO_STATUS_RECEIVED
-                            : closeStatus, event.code);
-              Expect.equals(
-                  closeReason == null ? "" : closeReason, event.reason);
-            }
-          });
-        });
-    }
-
-  });
-}
+  }
 
 
-void testMessageLength(int messageLength) {
-  HttpServer.bind().then((server) {
-
-    Uint8List originalMessage = new Uint8List(messageLength);
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      webSocket.listen((event) {
-        if (event is MessageEvent) {
-          Expect.listEquals(originalMessage, event.data);
-          webSocket.send(event.data);
-        } else if (event is CloseEvent) {
-        }
+  void testMessageLength(int messageLength) {
+    createServer().then((server) {
+      Uint8List originalMessage = new Uint8List(messageLength);
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        webSocket.listen(
+            (message) {
+              Expect.listEquals(originalMessage, message);
+              webSocket.send(message);
+            });
       });
-    });
 
-    WebSocket.connect("ws://127.0.0.1:${server.port}/")
-      .then((webSocket) {
-        webSocket.listen((event) {
-          if (event is MessageEvent) {
-            Expect.listEquals(originalMessage, event.data);
-            webSocket.close();
-          } else if (event is CloseEvent) {
-            server.close();
-          }
-        });
+      createClient(server.port).then((webSocket) {
+        webSocket.listen(
+            (message) {
+              Expect.listEquals(originalMessage, message);
+              webSocket.close();
+            },
+            onDone: server.close);
         webSocket.send(originalMessage);
       });
-
-  });
-}
-
-
-void testNoUpgrade() {
-  HttpServer.bind().then((server) {
-
-    // Create a server which always responds with NOT_FOUND.
-    server.listen((request) {
-      request.response.statusCode = HttpStatus.NOT_FOUND;
-      request.response.close();
     });
+  }
 
-    WebSocket.connect("ws://127.0.0.1:${server.port}/").catchError((error) {
-      server.close();
+
+  void testDoubleCloseClient() {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        server.close();
+        webSocket.listen((_) { }, onDone: webSocket.close);
+      });
+
+      createClient(server.port).then((webSocket) {
+          webSocket.listen((_) { }, onDone: webSocket.close);
+          webSocket.close();
+        });
     });
-
-  });
-}
+  }
 
 
-void testUsePOST() {
-  HttpServer.bind().then((server) {
+  void testDoubleCloseServer() {
+    createServer().then((server) {
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        server.close();
+        webSocket.listen((_) { }, onDone: webSocket.close);
+        webSocket.close();
+      });
 
-    var errorPort = new ReceivePort();
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      Expect.fail("No connection expected");
-    }, onError: (e) {
-      errorPort.close();
+      createClient(server.port).then((webSocket) {
+          webSocket.listen((_) { }, onDone: webSocket.close);
+        });
     });
+  }
 
-    HttpClient client = new HttpClient();
-    client.post("127.0.0.1", server.port, "/")
-      .then((request) => request.close())
-      .then((response) {
-        Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode);
-        client.close();
+
+  void testNoUpgrade() {
+    createServer().then((server) {
+      // Create a server which always responds with NOT_FOUND.
+      server.listen((request) {
+        request.response.statusCode = HttpStatus.NOT_FOUND;
+        request.response.close();
+      });
+
+      createClient(server.port).catchError((error) {
         server.close();
       });
-
-  });
-}
-
-
-class WebSocketInfo {
-  int messageCount = 0;
-}
-
-
-void testW3CInterface(
-    int totalConnections, int closeStatus, String closeReason) {
-  HttpServer.bind().then((server) {
-
-    int closeCount = 0;
-    server.transform(new WebSocketTransformer()).listen((webSocket) {
-      String messageText = "Hello, world!";
-      int messageCount = 0;
-      webSocket.listen((event) {
-        if (event is MessageEvent) {
-          messageCount++;
-          if (messageCount < 10) {
-            Expect.equals(messageText, event.data);
-            webSocket.send(event.data);
-          } else {
-            webSocket.close(closeStatus, closeReason);
-          }
-        } else if (event is CloseEvent) {
-          Expect.equals(closeStatus, event.code);
-          Expect.equals("", event.reason);
-          closeCount++;
-          if (closeCount == totalConnections) {
-            server.close();
-          }
-        }
-      });
-      webSocket.send(messageText);
     });
+  }
 
-    void webSocketConnection() {
-      bool onopenCalled = false;
-      int onmessageCalled = 0;
-      bool oncloseCalled = false;
 
-      WebSocket.connect("ws://127.0.0.1:${server.port}").then((webSocket) {
-        Expect.isFalse(onopenCalled);
-        Expect.equals(0, onmessageCalled);
-        Expect.isFalse(oncloseCalled);
-        onopenCalled = true;
-        Expect.equals(WebSocket.OPEN, webSocket.readyState);
-        webSocket.listen((event) {
-         if (event is MessageEvent) {
-            onmessageCalled++;
-            Expect.isTrue(onopenCalled);
-            Expect.isFalse(oncloseCalled);
-            Expect.equals(WebSocket.OPEN, webSocket.readyState);
-            webSocket.send(event.data);
-          } else if (event is CloseEvent) {
-            Expect.isTrue(onopenCalled);
-            Expect.equals(10, onmessageCalled);
-            Expect.isFalse(oncloseCalled);
-            oncloseCalled = true;
-            Expect.isTrue(event.wasClean);
-            Expect.equals(3002, event.code);
-            Expect.equals("Got tired", event.reason);
-            Expect.equals(WebSocket.CLOSED, webSocket.readyState);
-          }
-        });
+  void testUsePOST() {
+    createServer().then((server) {
+      var errorPort = new ReceivePort();
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        Expect.fail("No connection expected");
+      }, onError: (e) {
+        errorPort.close();
       });
-    }
 
-    for (int i = 0; i < totalConnections; i++) {
-      webSocketConnection();
-    }
+      HttpClient client = new HttpClient();
+      client.postUrl(Uri.parse(
+          "${secure ? 'https:' : 'http:'}//$HOST_NAME:${server.port}/"))
+        .then((request) => request.close())
+        .then((response) {
+          Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode);
+          client.close();
+          server.close();
+        });
+    });
+  }
 
-  });
+  void testConnections(int totalConnections,
+                       int closeStatus,
+                       String closeReason) {
+    createServer().then((server) {
+      int closeCount = 0;
+      server.transform(new WebSocketTransformer()).listen((webSocket) {
+        String messageText = "Hello, world!";
+        int messageCount = 0;
+        webSocket.listen(
+            (message) {
+              messageCount++;
+              if (messageCount < 10) {
+                Expect.equals(messageText, message);
+                webSocket.send(message);
+              } else {
+                webSocket.close(closeStatus, closeReason);
+              }
+            },
+            onDone: () {
+              Expect.equals(closeStatus, webSocket.closeCode);
+              Expect.equals("", webSocket.closeReason);
+              closeCount++;
+              if (closeCount == totalConnections) {
+                server.close();
+              }
+            });
+        webSocket.send(messageText);
+      });
+
+      void webSocketConnection() {
+        bool onopenCalled = false;
+        int onmessageCalled = 0;
+        bool oncloseCalled = false;
+
+        createClient(server.port).then((webSocket) {
+          Expect.isFalse(onopenCalled);
+          Expect.equals(0, onmessageCalled);
+          Expect.isFalse(oncloseCalled);
+          onopenCalled = true;
+          Expect.equals(WebSocket.OPEN, webSocket.readyState);
+          webSocket.listen(
+              (message) {
+                onmessageCalled++;
+                Expect.isTrue(onopenCalled);
+                Expect.isFalse(oncloseCalled);
+                Expect.equals(WebSocket.OPEN, webSocket.readyState);
+                webSocket.send(message);
+              },
+              onDone: () {
+                Expect.isTrue(onopenCalled);
+                Expect.equals(10, onmessageCalled);
+                Expect.isFalse(oncloseCalled);
+                oncloseCalled = true;
+                Expect.isTrue(event.wasClean);
+                Expect.equals(3002, event.code);
+                Expect.equals("Got tired", event.reason);
+                Expect.equals(WebSocket.CLOSED, webSocket.readyState);
+              });
+        });
+      }
+
+      for (int i = 0; i < totalConnections; i++) {
+        webSocketConnection();
+      }
+    });
+  }
+
+  testIndivitualUpgrade(int connections) {
+    createServer().then((server) {
+      server.listen((request) {
+          if (WebSocketTransformer.isUpgradeRequest(request)) {
+            WebSocketTransformer.upgrade(request).then((webSocket) {
+                webSocket.listen((_) { webSocket.close(); });
+                webSocket.send("Hello");
+            });
+          } else {
+            Expect.isFalse(WebSocketTransformer.isUpgradeRequest(request));
+            request.response.statusCode = HttpStatus.OK;
+            request.response.close();
+          }
+      });
+
+      var futures = [];
+
+      var wsProtocol = '${secure ? "wss" : "ws"}';
+      var baseWsUrl = '$wsProtocol://$HOST_NAME:${server.port}/';
+      var httpProtocol = '${secure ? "https" : "http"}';
+      var baseHttpUrl = '$httpProtocol://$HOST_NAME:${server.port}/';
+      HttpClient client = new HttpClient();
+
+      for (int i = 0; i < connections; i++) {
+        var completer = new Completer();
+        futures.add(completer.future);
+        WebSocket.connect('${baseWsUrl}')
+            .then((websocket) {
+                websocket.listen((_) { websocket.close(); },
+                               onDone: completer.complete);
+            });
+
+        futures.add(client.openUrl("GET", new Uri.fromString('${baseHttpUrl}'))
+             .then((request) => request.close())
+             .then((response) {
+               response.listen((_) { });
+               Expect.equals(HttpStatus.OK, response.statusCode);
+               }));
+      }
+
+      Future.wait(futures).then((_) {
+        server.close();
+        client.close();
+      });
+    });
+  }
+
+  void runTests() {
+    testRequestResponseClientCloses(2, null, null);
+    testRequestResponseClientCloses(2, 3001, null);
+    testRequestResponseClientCloses(2, 3002, "Got tired");
+    testRequestResponseServerCloses(2, null, null);
+    testRequestResponseServerCloses(2, 3001, null);
+    testRequestResponseServerCloses(2, 3002, "Got tired");
+    testMessageLength(125);
+    testMessageLength(126);
+    testMessageLength(127);
+    testMessageLength(65535);
+    testMessageLength(65536);
+    testDoubleCloseClient();
+    testDoubleCloseServer();
+    testNoUpgrade();
+    testUsePOST();
+    testConnections(10, 3002, "Got tired");
+    testIndivitualUpgrade(5);
+  }
+}
+
+
+void initializeSSL() {
+  var testPkcertDatabase =
+      new Path(new Options().script).directoryPath.append("pkcert/");
+  SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
+                          password: "dartdart");
 }
 
 
 main() {
-  testRequestResponseClientCloses(2, null, null);
-  testRequestResponseClientCloses(2, 3001, null);
-  testRequestResponseClientCloses(2, 3002, "Got tired");
-  testRequestResponseServerCloses(2, null, null);
-  testRequestResponseServerCloses(2, 3001, null);
-  testRequestResponseServerCloses(2, 3002, "Got tired");
-  testMessageLength(125);
-  testMessageLength(126);
-  testMessageLength(127);
-  testMessageLength(65535);
-  testMessageLength(65536);
-  testNoUpgrade();
-  testUsePOST();
-
-  testW3CInterface(2, 3002, "Got tired");
+  new SecurityConfiguration(secure: false).runTests();
+  initializeSSL();
+  new SecurityConfiguration(secure: true).runTests();
 }
diff --git a/tests/standalone/io/windows_environment_test.dart b/tests/standalone/io/windows_environment_test.dart
index 1812c25..dfe5af6 100644
--- a/tests/standalone/io/windows_environment_test.dart
+++ b/tests/standalone/io/windows_environment_test.dart
@@ -20,7 +20,7 @@
   var scriptDir = new Path(options.script).directoryPath;
   var script = scriptDir.append('windows_environment_script.dart');
   Process.run('cmd',
-              ['/c', funkyFile.name, dart, script.toNativePath()]).then((p) {
+              ['/c', funkyFile.path, dart, script.toNativePath()]).then((p) {
     Expect.equals(0, p.exitCode);
     tempDir.deleteSync(recursive: true);
   });
diff --git a/tests/standalone/out_of_memory_test.dart b/tests/standalone/out_of_memory_test.dart
index 016ab2b..1fb36f9 100644
--- a/tests/standalone/out_of_memory_test.dart
+++ b/tests/standalone/out_of_memory_test.dart
@@ -6,7 +6,7 @@
   var number_of_ints = 134000000;
   var exception_thrown = false;
   try {
-    List<int> buf = new List<int>.fixedLength(number_of_ints);
+    List<int> buf = new List<int>(number_of_ints);
   } on OutOfMemoryError catch (exc) {
     exception_thrown = true;
   }
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 0bedddf..de4b7a4 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -12,30 +12,25 @@
 io/test_runner_exit_code_test: fail
 io/test_runner_test: fail
 
-[ $runtime == vm ]
-io/secure_server_client_certificate_test: fail
-
 [ $runtime == vm && ( $system == windows ) ]
-io/web_socket_test: Fail, Pass # Issue 8495.
-io/https_client_certificate_test: Pass, Timeout # Issue 8674
-io/raw_socket_test: Pass, Timeout # Issue 8675
-io/socket_test: Pass, Timeout # Issue 8676
-io/socket_exception_test: Pass, Timeout # Issue 8677
-io/https_client_test: Pass, Timeout # Issue 8674
-io/https_server_test: Pass, Timeout # Issue 8674
-io/https_client_socket_reuse_test: Pass, Timeout # Issue 8674
-io/http_client_request_test: Pass, Fail # Issue 8681
-io/http_proxy_test: Pass, Timeout # Issue 7773
+io/raw_server_socket_cancel_test: Pass, Fail, Timeout # Issue 8675
+io/raw_socket_test: Pass, Fail # Issue 8901
 
 [ $runtime == vm ]
 package/package_isolate_test: Fail # http://dartbug.com/7520.
 
+# Fails with a connection refused error on the buildbot.
+# Issue 8232.
+debugger/basic_debugger_test: Pass, Fail
+
+
 [ $runtime == vm && $checked ]
 # These tests have type errors on purpose.
 io/process_invalid_arguments_test: Fail, OK
 io/directory_invalid_arguments_test: Fail, OK
 io/file_invalid_arguments_test: Fail, OK
 io/socket_invalid_arguments_test: Fail, OK
+io/stdout_bad_argument_test: Fail, OK
 # These test have type errors on purpose and take very long to run in
 # checked mode with no benefit. Skip.
 io/file_fuzz_test: Skip
@@ -44,11 +39,6 @@
 [ $runtime == vm && $system == macos ]
 io/regress_7191_test: Pass, Timeout # http://dartbug.com/8091
 
-[ $runtime == vm ]
-# Fails with a connection refused error on the buildbot.
-# Issue 8232.
-debugger/basic_debugger_test: Pass, Fail
-
 # This test fails with "Too many open files" on the Mac OS buildbot.
 # This is expected as MacOS by default runs with a very low number
 # of allowed open files ('ulimit -n' says something like 256).
@@ -96,9 +86,6 @@
 
 io/process_exit_negative_test: Fail  # This is a compilation-time negative test.
 
-[ $compiler == frog ]
-*: Skip
-
 [ $compiler == dart2js ]
 number_identity_test: Skip # Bigints and int/double diff. not supported.
 typed_array_test: Skip # This is a VM test
diff --git a/tests/utils/recursive_import_test.dart b/tests/utils/recursive_import_test.dart
index 6654e17..62bf362 100644
--- a/tests/utils/recursive_import_test.dart
+++ b/tests/utils/recursive_import_test.dart
@@ -31,6 +31,21 @@
 class JSInvocationMirror {}  // Should be in helper.
 """;
 
+const INTERCEPTORS_LIB = """
+library interceptors;
+class JSArray {
+  get length => null;
+  removeLast() => null;
+  add(x) { }
+}
+class JSString {
+  get length => null;
+  split(x) => null;
+  concat(x) => null;
+  toString() => null;
+}
+""";
+
 const String RECURSIVE_MAIN = """
 library fisk;
 import 'recurse/fisk.dart';
@@ -56,6 +71,8 @@
         source = '';
       } else if (uri.path.endsWith('isolate_helper.dart')) {
         source = 'class _WorkerStub {}';
+      } else if (uri.path.endsWith('interceptors.dart')) {
+        source = INTERCEPTORS_LIB;
       } else {
         source = "library lib${uri.path.replaceAll('/', '.')};";
       }
diff --git a/tests/utils/utf_test.dart b/tests/utils/utf_test.dart
index 6441789..10401a3 100644
--- a/tests/utils/utf_test.dart
+++ b/tests/utils/utf_test.dart
@@ -7,8 +7,8 @@
 
 main() {
   String str = codepointsToString([0x1d537]);
-  // String.charCodes gives 16-bit code units, but stringToCodepoints gives
+  // String.codeUnits gives 16-bit code units, but stringToCodepoints gives
   // back the original code points.
-  Expect.listEquals([0xd835, 0xdd37], str.charCodes);
+  Expect.listEquals([0xd835, 0xdd37], str.codeUnits);
   Expect.listEquals([0x1d537], stringToCodepoints(str));
 }
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index 4d6e186..8119908 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -11,6 +11,9 @@
 recursive_import_test: Fail # http://dartbug.com/2264
 dart2js_test: Fail # http://dartbug.com/2264
 
+[ $compiler == dartc ]
+dart2js_test: Fail # http://dartbug.com/8802
+
 [ $compiler == dart2js && $browser ]
 *: Skip
 
diff --git a/tools/VERSION b/tools/VERSION
index 2288fc6..0419e66 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 4
-BUILD 0
+BUILD 1
 PATCH 0
diff --git a/tools/bots/bot.py b/tools/bots/bot.py
index aea443f..0d9284b 100644
--- a/tools/bots/bot.py
+++ b/tools/bots/bot.py
@@ -42,7 +42,8 @@
   """
   def __init__(self, compiler, runtime, mode, system, checked=False,
                host_checked=False, minified=False, shard_index=None,
-               total_shards=None, is_buildbot=False, test_set=None):
+               total_shards=None, is_buildbot=False, test_set=None,
+               csp=None):
     self.compiler = compiler
     self.runtime = runtime
     self.mode = mode
@@ -54,6 +55,7 @@
     self.total_shards = total_shards
     self.is_buildbot = is_buildbot
     self.test_set = test_set
+    self.csp = csp
 
   def PrintBuildInfo(self):
     shard_description = ""
@@ -214,7 +216,7 @@
     cmd.extend(flags)
     cmd.extend(targets)
 
-    print 'Running: %s' % (' '.join(cmd))
+    print 'Running: %s' % (' '.join(map(lambda arg: '"%s"' % arg, cmd)))
     RunProcess(cmd)
 
 
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index fbcaeb3..45636c7 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -22,7 +22,7 @@
 DART2JS_BUILDER = (
     r'dart2js-(linux|mac|windows)(-(jsshell))?-(debug|release)(-(checked|host-checked))?(-(host-checked))?(-(minified))?-?(\d*)-?(\d*)')
 WEB_BUILDER = (
-    r'dart2js-(ie9|ie10|ff|safari|chrome|opera)-(win7|win8|mac10\.8|mac10\.7|linux)(-(all|html))?(-(\d+)-(\d+))?')
+    r'dart2js-(ie9|ie10|ff|safari|chrome|opera)-(win7|win8|mac10\.8|mac10\.7|linux)(-(all|html))?(-(csp))?(-(\d+)-(\d+))?')
 
 
 def GetBuildInfo(builder_name, is_buildbot):
@@ -39,6 +39,7 @@
   shard_index = None
   total_shards = None
   test_set = None
+  csp = None
 
   dart2js_pattern = re.match(DART2JS_BUILDER, builder_name)
   web_pattern = re.match(WEB_BUILDER, builder_name)
@@ -49,8 +50,10 @@
     system = web_pattern.group(2)
     mode = 'release'
     test_set = web_pattern.group(4)
-    shard_index = web_pattern.group(6)
-    total_shards = web_pattern.group(7)
+    if web_pattern.group(6) == 'csp':
+      csp = True
+    shard_index = web_pattern.group(8)
+    total_shards = web_pattern.group(9)
   elif dart2js_pattern:
     compiler = 'dart2js'
     system = dart2js_pattern.group(1)
@@ -91,7 +94,7 @@
     return None
   return bot.BuildInfo(compiler, runtime, mode, system, checked, host_checked,
                        minified, shard_index, total_shards, is_buildbot,
-                       test_set)
+                       test_set, csp)
 
 
 def NeedsXterm(compiler, runtime):
@@ -146,7 +149,7 @@
       cmd.extend(flags)
     cmd.extend(targets)
 
-    print 'running %s' % (' '.join(cmd))
+    print 'Running: %s' % (' '.join(map(lambda arg: '"%s"' % arg, cmd)))
     bot.RunProcess(cmd)
 
 
@@ -294,6 +297,8 @@
 
   if build_info.minified: test_flags += ['--minified']
 
+  if build_info.csp: test_flags += ['--csp']
+
   TestCompiler(build_info.runtime, build_info.mode, build_info.system,
                list(test_flags), build_info.is_buildbot, build_info.test_set)
 
diff --git a/tools/bots/pub.py b/tools/bots/pub.py
index c5e89fb..f778cad 100755
--- a/tools/bots/pub.py
+++ b/tools/bots/pub.py
@@ -47,7 +47,7 @@
     print 'Building package-root: %s' % (' '.join(args))
     bot.RunProcess(args)
 
-  bot.RunTest('pub', build_info, ['pub', 'pkg'])
+  bot.RunTest('pub', build_info, ['pub', 'pkg', 'dartdoc'])
 
 
 if __name__ == '__main__':
diff --git a/tools/copy_dart.py b/tools/copy_dart.py
index b60ad89..9918e2e 100755
--- a/tools/copy_dart.py
+++ b/tools/copy_dart.py
@@ -14,14 +14,17 @@
 
 re_directive = re.compile(
     r'^(library|import|part|native|resource)\s+(.*);$')
+re_comment = re.compile(
+    r'^(///|/\*| \*).*$')
 
 class Library(object):
-  def __init__(self, name, imports, sources, natives, code):
+  def __init__(self, name, imports, sources, natives, code, comment):
     self.name = name
     self.imports = imports
     self.sources = sources
     self.natives = natives
     self.code = code
+    self.comment = comment
 
 def parseLibrary(library):
   """ Parses a .dart source file that is the root of a library, and returns
@@ -33,6 +36,7 @@
   sources = []
   natives = []
   inlinecode = []
+  librarycomment = []
   if exists(library):
     # TODO(sigmund): stop parsing when import/source
     for line in fileinput.input(library):
@@ -51,9 +55,14 @@
         else:
           raise Exception('unknown directive %s in %s' % (directive, line))
       else:
-        inlinecode.append(line)
+        # Check for library comment.
+        if not libraryname and re_comment.match(line):
+          librarycomment.append(line)
+        else:
+          inlinecode.append(line)
     fileinput.close()
-  return Library(libraryname, imports, sources, natives, inlinecode)
+  return Library(libraryname, imports, sources, natives, inlinecode,
+                 librarycomment)
 
 def normjoin(*args):
   return os.path.normpath(os.path.join(*args))
@@ -114,6 +123,8 @@
       # Create file containing all imports, and inlining all sources
       with open(outpath, 'w') as f:
         if library.name:
+          if library.comment:
+            f.write('%s' % (''.join(library.comment)))
           f.write("library %s;\n\n" % library.name)
         else:
           f.write("library %s;\n\n" % basename(lib))
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 4e87ffb..e24902a 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -222,7 +222,7 @@
   # Create and populate pkg/{args, intl, logging, meta, unittest, ...}
   #
 
-  for library in ['args', 'http', 'intl', 'logging', 'meta', 'oauth2', 'path',
+  for library in ['args', 'http', 'intl', 'logging', 'meta', 'oauth2', 'pathos',
                   'serialization', 'unittest', 'yaml']:
 
     copytree(join(HOME, 'pkg', library), join(PKG, library),
@@ -243,7 +243,7 @@
   copyfile(analyzer_src_jar, analyzer_dest_jar)
 
   jarsToCopy = [ join("args4j", "2.0.12", "args4j-2.0.12.jar"),
-                 join("guava", "r09", "guava-r09.jar"),
+                 join("guava", "r13", "guava-13.0.1.jar"),
                  join("json", "r2_20080312", "json.jar") ]
   for jarToCopy in jarsToCopy:
     dest_dir = join (ANALYZER_DEST, os.path.dirname(jarToCopy))
diff --git a/tools/ddbg.dart b/tools/ddbg.dart
index 7d95f79..2295ae8 100644
--- a/tools/ddbg.dart
+++ b/tools/ddbg.dart
@@ -15,7 +15,7 @@
 
 Socket vmSock;
 String vmData;
-OutputStream vmStream;
+StreamSubscription<String> streamSubscription;
 int seqNum = 0;
 int isolate_id = -1;
 
@@ -56,7 +56,7 @@
 
 
 void quitShell() {
-  vmStream.close();
+  streamSubscription.cancel();
   vmSock.close();
   stdin.close();
 }
@@ -69,7 +69,7 @@
   if (verbose) {
     print("sending: '${json.stringify(cmd)}'");
   }
-  vmStream.writeString(json.stringify(cmd));
+  vmSock.addString(json.stringify(cmd));
   return completer.future;
 }
 
@@ -528,25 +528,25 @@
 
 void debuggerMain() {
   outstandingCommands = new Map<int, Completer>();
-  vmSock = new Socket("127.0.0.1", 5858);
-  vmStream = vmSock.outputStream;
-  var stdinStream = new StringInputStream(stdin);
-  stdinStream.onLine = () {
-    processCommand(stdinStream.readLine());
-  };
-  var vmInStream = vmSock.inputStream;
-  vmInStream.onData = () {
-    String s = decodeUtf8(vmInStream.read());
-    processVmData(s);
-  };
-  vmInStream.onError = (err) {
-    print("Error in debug connection: $err");
-    quitShell();
-  };
-  vmInStream.onClosed = () {
-    print("VM debugger connection closed");
-    quitShell();
-  };
+  Socket.connect("127.0.0.1", 5858).then((s) {
+    vmSock = s;
+    Stream<String> stringStream = vmSock.transform(new StringDecoder());
+    streamSubscription = stringStream.listen(
+        (String data) {
+          processVmData(data);
+        },
+        onDone: () {
+          print("VM debugger connection closed");
+          quitShell();
+        },
+        onError: (err) {
+          print("Error in debug connection: $err");
+          quitShell();
+        });
+    stdin.transform(new StringDecoder())
+        .transform(new LineTransformer())
+        .listen((String line) => processCommand(line));
+  });
 }
 
 void main() {
@@ -555,16 +555,10 @@
   if (arguments.length > 0) {
     arguments = <String>['--debug', '--verbose_debug']..addAll(arguments);
     Process.start(options.executable, arguments).then((Process process) {
-      process.onExit = (int exitCode) {
-        print('${arguments.join(" ")} exited with $exitCode');
-      };
       process.stdin.close();
-      // Redirecting both stdout and stderr of the child process to
-      // stdout.  This should help users keep track of which errors
-      // are coming from the debugger, and which errors are coming
-      // from the process being debugged.
-      process.stderr.pipe(stdout);
-      process.stdout.pipe(stdout);
+      process.exitCode.then((int exitCode) {
+        print('${arguments.join(" ")} exited with $exitCode');
+      });
       debuggerMain();
     });
   } else {
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index 9a34601..936da3b 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -528,5 +528,25 @@
         ]
       }
     }
+  },
+  "dart.dom.web_sql": {
+    "Database": {
+      "members": {
+        "changeVersion": [
+          "/**",
+          "   * Atomically update the database version to [newVersion], asynchronously",
+          "   * running [callback] on the [SqlTransaction] representing this",
+          "   * [changeVersion] transaction.",
+          "   *",
+          "   * If [callback] runs successfully, then [successCallback] is called.",
+          "   * Otherwise, [errorCallback] is called.",
+          "   *",
+          "   * [oldVersion] should match the database's current [version] exactly.",
+          "   *",
+          "   * * [Database.changeVersion](http://www.w3.org/TR/webdatabase/#dom-database-changeversion) from W3C.",
+          "   */"
+        ]
+      }
+    }
   }
 }
\ No newline at end of file
diff --git a/tools/dom/docs/html_docs.json b/tools/dom/docs/html_docs.json
deleted file mode 100644
index 8f23289..0000000
--- a/tools/dom/docs/html_docs.json
+++ /dev/null
@@ -1,2399 +0,0 @@
-{
-"AbstractWorker.dart":
-  {
-
-  },
-"AnalyserNode.dart":
-  {
-
-  },
-"AnchorElement.dart":
-  {
-
-  },
-"Animation.dart":
-  {
-
-  },
-"AnimationEvent.dart":
-  {
-
-  },
-"AppletElement.dart":
-  {
-
-  },
-"ApplicationCache.dart":
-  {
-
-  },
-"AreaElement.dart":
-  {
-
-  },
-"ArrayBuffer.dart":
-  {
-
-  },
-"ArrayBufferView.dart":
-  {
-
-  },
-"Attr.dart":
-  {
-
-  },
-"AudioBuffer.dart":
-  {
-
-  },
-"AudioBufferCallback.dart":
-  {
-
-  },
-"AudioBufferSourceNode.dart":
-  {
-
-  },
-"AudioContext.dart":
-  {
-
-  },
-"AudioDestinationNode.dart":
-  {
-
-  },
-"AudioElement.dart":
-  {
-
-  },
-"AudioGain.dart":
-  {
-
-  },
-"AudioListener.dart":
-  {
-
-  },
-"AudioNode.dart":
-  {
-
-  },
-"AudioParam.dart":
-  {
-
-  },
-"AudioProcessingEvent.dart":
-  {
-
-  },
-"AudioSourceNode.dart":
-  {
-
-  },
-"BRElement.dart":
-  {
-
-  },
-"BarInfo.dart":
-  {
-
-  },
-"BaseElement.dart":
-  {
-
-  },
-"BaseFontElement.dart":
-  {
-
-  },
-"BatteryManager.dart":
-  {
-
-  },
-"BeforeLoadEvent.dart":
-  {
-
-  },
-"BiquadFilterNode.dart":
-  {
-
-  },
-"Blob.dart":
-  {
-
-  },
-"BodyElement.dart":
-  {
-
-  },
-"ButtonElement.dart":
-  {
-
-  },
-"CDATASection.dart":
-  {
-
-  },
-"CDataSection.dart":
-  {
-
-  },
-"CSSCharsetRule.dart":
-  {
-
-  },
-"CSSFontFaceRule.dart":
-  {
-
-  },
-"CSSImportRule.dart":
-  {
-
-  },
-"CSSKeyframeRule.dart":
-  {
-
-  },
-"CSSKeyframesRule.dart":
-  {
-
-  },
-"CSSMatrix.dart":
-  {
-
-  },
-"CSSMediaRule.dart":
-  {
-
-  },
-"CSSPageRule.dart":
-  {
-
-  },
-"CSSPrimitiveValue.dart":
-  {
-
-  },
-"CSSRule.dart":
-  {
-
-  },
-"CSSStyleDeclaration.dart":
-  {
-
-  },
-"CSSStyleRule.dart":
-  {
-
-  },
-"CSSStyleSheet.dart":
-  {
-
-  },
-"CSSTransformValue.dart":
-  {
-
-  },
-"CSSUnknownRule.dart":
-  {
-
-  },
-"CSSValue.dart":
-  {
-
-  },
-"CanvasElement.dart":
-  {
-  "  @JSName('toDataURL')":
-    [
-      "  /**",
-      "   * Returns a data URI containing a representation of the image in the ",
-      "   * format specified by type (defaults to 'image/png'). ",
-      "   * ",
-      "   * Data Uri format is as follow `data:[<MIME-type>][;charset=<encoding>][;base64],<data>`",
-      "   * ",
-      "   * Optional parameter [quality] in the range of 0.0 and 1.0 can be used when requesting [type]",
-      "   * 'image/jpeg' or 'image/webp'. If [quality] is not passed the default",
-      "   * value is used. Note: the default value varies by browser.",
-      "   * ",
-      "   * If the height or width of this canvas element is 0, then 'data:' is returned,",
-      "   * representing no data.",
-      "   * ",
-      "   * If the type requested is not 'image/png', and the returned value is ",
-      "   * 'data:image/png', then the requested type is not supported.",
-      "   * ",
-      "   * Example usage:",
-      "   * ",
-      "   *     CanvasElement canvas = new CanvasElement();",
-      "   *     var ctx = canvas.context2d",
-      "   *     ..fillStyle = \"rgb(200,0,0)\"",
-      "   *     ..fillRect(10, 10, 55, 50);",
-      "   *     var dataUrl = canvas.toDataURL(\"image/jpeg\", 0.95);",
-      "   *     // The Data Uri would look similar to",
-      "   *     // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA",
-      "   *     // AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO",
-      "   *     // 9TXL0Y4OHwAAAABJRU5ErkJggg=='",
-      "   *     //Create a new image element from the data URI.",
-      "   *     var img = new ImageElement();",
-      "   *     img.src = dataUrl;",
-      "   *     document.body.children.add(img);",
-      "   *     ",
-      "   * See also:",
-      "   * ",
-      "   * * [Data URI Scheme](http://en.wikipedia.org/wiki/Data_URI_scheme) from Wikipedia.",
-      "   * ",
-      "   * * [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/DOM/HTMLCanvasElement) from MDN.",
-      "   * ",
-      "   * * [toDataUrl](http://dev.w3.org/html5/spec/the-canvas-element.html#dom-canvas-todataurl) from W3C.",
-      "   */"
-    ],
-  "  int height;":
-    [
-      "  /// The height of this canvas element in CSS pixels."
-    ],
-  "  int width;":
-    [
-      "  /// The width of this canvas element in CSS pixels."
-    ]
-  },
-"CanvasGradient.dart":
-  {
-  "  void addColorStop(num offset, String color) native;":
-    [
-      "  /**",
-      "   * Adds a color stop to this gradient at the offset.",
-      "   *",
-      "   * The [offset] can range between 0.0 and 1.0.",
-      "   *",
-      "   * See also:",
-      "   *",
-      "   * * [Multiple Color Stops](https://developer.mozilla.org/en-US/docs/CSS/linear-gradient#Gradient_with_multiple_color_stops) from MDN.",
-      "   */"
-    ],
-  "class CanvasGradient native \"*CanvasGradient\" {":
-    [
-      "/**",
-      " * An opaque canvas object representing a gradient.",
-      " *",
-      " * Created by calling [createLinearGradient] or [createRadialGradient] on a",
-      " * [CanvasRenderingContext2D] object.",
-      " *",
-      " * Example usage:",
-      " *",
-      " *     var canvas = new CanvasElement(width: 600, height: 600);",
-      " *     var ctx = canvas.context2d;",
-      " *     ctx.clearRect(0, 0, 600, 600);",
-      " *     ctx.save();",
-      " *     // Create radial gradient.",
-      " *     CanvasGradient gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, 600);",
-      " *     gradient.addColorStop(0, '#000');",
-      " *     gradient.addColorStop(1, 'rgb(255, 255, 255)');",
-      " *     // Assign gradients to fill.",
-      " *     ctx.fillStyle = gradient;",
-      " *     // Draw a rectangle with a gradient fill.",
-      " *     ctx.fillRect(0, 0, 600, 600);",
-      " *     ctx.save();",
-      " *     document.body.children.add(canvas);",
-      " *",
-      " * See also:",
-      " *",
-      " * * [CanvasGradient](https://developer.mozilla.org/en-US/docs/DOM/CanvasGradient) from MDN.",
-      " * * [CanvasGradient](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvasgradient) from whatwg.",
-      " * * [CanvasGradient](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvasgradient) from W3C.",
-      " */"
-    ]
-  },
-"CanvasPattern.dart":
-  {
-  "class CanvasPattern native \"*CanvasPattern\" {":
-    [
-      "/**",
-      " * An opaque object representing a pattern of image, canvas, or video.",
-      " *",
-      " * Created by calling [createPattern] on a [CanvasRenderingContext2D] object.",
-      " *",
-      " * Example usage:",
-      " *",
-      " *     var canvas = new CanvasElement(width: 600, height: 600);",
-      " *     var ctx = canvas.context2d;",
-      " *     var img = new ImageElement();",
-      " *     // Image src needs to be loaded before pattern is applied.",
-      " *     img.on.load.add((event) {",
-      " *       // When the image is loaded, create a pattern",
-      " *       // from the ImageElement.",
-      " *       CanvasPattern pattern = ctx.createPattern(img, 'repeat');",
-      " *       ctx.rect(0, 0, canvas.width, canvas.height);",
-      " *       ctx.fillStyle = pattern;",
-      " *       ctx.fill();",
-      " *     });",
-      " *     img.src = \"images/foo.jpg\";",
-      " *     document.body.children.add(canvas);",
-      " *",
-      " * See also:",
-      " * * [CanvasPattern](https://developer.mozilla.org/en-US/docs/DOM/CanvasPattern) from MDN.",
-      " * * [CanvasPattern](http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvaspattern) from whatwg.",
-      " * * [CanvasPattern](http://www.w3.org/TR/2010/WD-2dcontext-20100304/#canvaspattern) from W3C.",
-      " */"
-    ]
-  },
-"CanvasRenderingContext.dart":
-  {
-  "  final CanvasElement canvas;":
-    [
-      "  /// Reference to the canvas element to which this context belongs."
-    ],
-  "class CanvasRenderingContext native \"*CanvasRenderingContext\" {":
-    [
-      "/**",
-      " * A rendering context for a canvas element.",
-      " *",
-      " * This context is extended by [CanvasRenderingContext2D] and",
-      " * [WebGLRenderingContext].",
-      " */"
-    ]
-  },
-"CanvasRenderingContext2D.dart":
-  {
-
-  },
-"ChannelMergerNode.dart":
-  {
-
-  },
-"ChannelSplitterNode.dart":
-  {
-
-  },
-"CharacterData.dart":
-  {
-
-  },
-"ClientRect.dart":
-  {
-
-  },
-"Clipboard.dart":
-  {
-
-  },
-"CloseEvent.dart":
-  {
-
-  },
-"Comment.dart":
-  {
-
-  },
-"CompositionEvent.dart":
-  {
-
-  },
-"Console.dart":
-  {
-
-  },
-"ContentElement.dart":
-  {
-
-  },
-"ConvolverNode.dart":
-  {
-
-  },
-"Coordinates.dart":
-  {
-
-  },
-"Counter.dart":
-  {
-
-  },
-"Crypto.dart":
-  {
-
-  },
-"CssCharsetRule.dart":
-  {
-
-  },
-"CssFontFaceRule.dart":
-  {
-
-  },
-"CssImportRule.dart":
-  {
-
-  },
-"CssKeyframeRule.dart":
-  {
-
-  },
-"CssKeyframesRule.dart":
-  {
-
-  },
-"CssMatrix.dart":
-  {
-
-  },
-"CssMediaRule.dart":
-  {
-
-  },
-"CssPageRule.dart":
-  {
-
-  },
-"CssPrimitiveValue.dart":
-  {
-
-  },
-"CssRule.dart":
-  {
-
-  },
-"CssStyleDeclaration.dart":
-  {
-
-  },
-"CssStyleRule.dart":
-  {
-
-  },
-"CssStyleSheet.dart":
-  {
-
-  },
-"CssTransformValue.dart":
-  {
-
-  },
-"CssUnknownRule.dart":
-  {
-
-  },
-"CssValue.dart":
-  {
-
-  },
-"CustomEvent.dart":
-  {
-
-  },
-"DListElement.dart":
-  {
-
-  },
-"DOMApplicationCache.dart":
-  {
-
-  },
-"DOMError.dart":
-  {
-
-  },
-"DOMException.dart":
-  {
-
-  },
-"DOMFileSystem.dart":
-  {
-
-  },
-"DOMFileSystemSync.dart":
-  {
-
-  },
-"DOMImplementation.dart":
-  {
-
-  },
-"DOMMimeType.dart":
-  {
-
-  },
-"DOMMimeTypeArray.dart":
-  {
-
-  },
-"DOMParser.dart":
-  {
-
-  },
-"DOMPlugin.dart":
-  {
-
-  },
-"DOMPluginArray.dart":
-  {
-
-  },
-"DOMSelection.dart":
-  {
-
-  },
-"DOMSettableTokenList.dart":
-  {
-
-  },
-"DOMStringMap.dart":
-  {
-
-  },
-"DOMTokenList.dart":
-  {
-
-  },
-"DataListElement.dart":
-  {
-
-  },
-"DataTransferItem.dart":
-  {
-
-  },
-"DataTransferItemList.dart":
-  {
-
-  },
-"DataView.dart":
-  {
-
-  },
-"Database.dart":
-  {
-
-  },
-"DatabaseCallback.dart":
-  {
-
-  },
-"DatabaseSync.dart":
-  {
-
-  },
-"DedicatedWorkerContext.dart":
-  {
-
-  },
-"DelayNode.dart":
-  {
-
-  },
-"DetailsElement.dart":
-  {
-
-  },
-"DeviceMotionEvent.dart":
-  {
-
-  },
-"DeviceOrientationEvent.dart":
-  {
-
-  },
-"DirectoryElement.dart":
-  {
-
-  },
-"DirectoryEntry.dart":
-  {
-
-  },
-"DirectoryEntrySync.dart":
-  {
-
-  },
-"DirectoryReader.dart":
-  {
-
-  },
-"DirectoryReaderSync.dart":
-  {
-
-  },
-"DivElement.dart":
-  {
-  "class DivElement extends Element native \"*HTMLDivElement\" {":
-    [
-      "/**",
-      " * Represents an HTML <div> element.",
-      " *",
-      " * The [DivElement] is a generic container for content and does not have any",
-      " * special significance. It is functionally similar to [SpanElement].",
-      " *",
-      " * The [DivElement] is a block-level element, as opposed to [SpanElement],",
-      " * which is an inline-level element.",
-      " *",
-      " * Example usage:",
-      " *",
-      " *     DivElement div = new DivElement();",
-      " *     div.text = 'Here's my new DivElem",
-      " *     document.body.elements.add(elem);",
-      " *",
-      " * See also:",
-      " *",
-      " * * [HTML <div> element](http://www.w3.org/TR/html-markup/div.html) from W3C.",
-      " * * [Block-level element](http://www.w3.org/TR/CSS2/visuren.html#block-boxes) from W3C.",
-      " * * [Inline-level element](http://www.w3.org/TR/CSS2/visuren.html#inline-boxes) from W3C.",
-      " */"
-    ]
-  },
-"Document.dart":
-  {
-  "  @JSName('body')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('caretRangeFromPoint')":
-    [
-      "  /// Use the [Range] constructor instead."
-    ],
-  "  @JSName('createElement')":
-    [
-      "  /// Deprecated: use new Element.tag(tagName) instead."
-    ],
-  "  @JSName('createTouchList')":
-    [
-      "  /// Use the [TouchList] constructor isntead."
-    ],
-  "  @JSName('elementFromPoint')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('getElementById')":
-    [
-      "  /// Deprecated: use query(\"#$elementId\") instead."
-    ],
-  "  @JSName('head')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('lastModified')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('querySelector')":
-    [
-      "  /// Deprecated: renamed to the shorter name [query]."
-    ],
-  "  @JSName('querySelectorAll')":
-    [
-      "  /// Deprecated: use query(\"#$elementId\") instead."
-    ],
-  "  @JSName('referrer')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('styleSheets')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('title')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitCancelFullScreen')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitExitFullscreen')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitExitPointerLock')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitFullscreenElement')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitFullscreenEnabled')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitHidden')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitIsFullScreen')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitPointerLockElement')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  @JSName('webkitVisibilityState')":
-    [
-      "  /// Moved to [HtmlDocument]."
-    ],
-  "  Window get window => _convertNativeToDart_Window(this._window);":
-    [
-      "  /// Returns the [Window] associated with the document."
-    ]
-  },
-"DocumentFragment.dart":
-  {
-
-  },
-"DocumentType.dart":
-  {
-
-  },
-"DomError.dart":
-  {
-
-  },
-"DomException.dart":
-  {
-
-  },
-"DomImplementation.dart":
-  {
-
-  },
-"DomMimeType.dart":
-  {
-
-  },
-"DomMimeTypeArray.dart":
-  {
-
-  },
-"DomParser.dart":
-  {
-
-  },
-"DomPlugin.dart":
-  {
-
-  },
-"DomPluginArray.dart":
-  {
-
-  },
-"DomSelection.dart":
-  {
-
-  },
-"DomSettableTokenList.dart":
-  {
-
-  },
-"DomStringList.dart":
-  {
-
-  },
-"DomStringMap.dart":
-  {
-
-  },
-"DomTokenList.dart":
-  {
-
-  },
-"DynamicsCompressorNode.dart":
-  {
-
-  },
-"EXTTextureFilterAnisotropic.dart":
-  {
-
-  },
-"Element.dart":
-  {
-
-  },
-"ElementTimeControl.dart":
-  {
-
-  },
-"ElementTraversal.dart":
-  {
-
-  },
-"EmbedElement.dart":
-  {
-
-  },
-"EntityReference.dart":
-  {
-
-  },
-"EntriesCallback.dart":
-  {
-
-  },
-"Entry.dart":
-  {
-
-  },
-"EntryCallback.dart":
-  {
-
-  },
-"EntrySync.dart":
-  {
-
-  },
-"ErrorCallback.dart":
-  {
-
-  },
-"ErrorEvent.dart":
-  {
-
-  },
-"Event.dart":
-  {
-
-  },
-"EventException.dart":
-  {
-
-  },
-"EventSource.dart":
-  {
-
-  },
-"EventTarget.dart":
-  {
-
-  },
-"ExtTextureFilterAnisotropic.dart":
-  {
-
-  },
-"FieldSetElement.dart":
-  {
-
-  },
-"File.dart":
-  {
-
-  },
-"FileCallback.dart":
-  {
-
-  },
-"FileEntry.dart":
-  {
-
-  },
-"FileEntrySync.dart":
-  {
-
-  },
-"FileError.dart":
-  {
-
-  },
-"FileException.dart":
-  {
-
-  },
-"FileList.dart":
-  {
-
-  },
-"FileReader.dart":
-  {
-
-  },
-"FileReaderSync.dart":
-  {
-
-  },
-"FileSystem.dart":
-  {
-
-  },
-"FileSystemCallback.dart":
-  {
-
-  },
-"FileSystemSync.dart":
-  {
-
-  },
-"FileWriter.dart":
-  {
-
-  },
-"FileWriterCallback.dart":
-  {
-
-  },
-"FileWriterSync.dart":
-  {
-
-  },
-"Float32Array.dart":
-  {
-
-  },
-"Float64Array.dart":
-  {
-
-  },
-"FontElement.dart":
-  {
-
-  },
-"FormData.dart":
-  {
-
-  },
-"FormElement.dart":
-  {
-
-  },
-"FrameElement.dart":
-  {
-
-  },
-"FrameSetElement.dart":
-  {
-
-  },
-"GainNode.dart":
-  {
-
-  },
-"Gamepad.dart":
-  {
-
-  },
-"Geolocation.dart":
-  {
-
-  },
-"Geoposition.dart":
-  {
-
-  },
-"HRElement.dart":
-  {
-
-  },
-"HTMLAllCollection.dart":
-  {
-
-  },
-"HTMLCollection.dart":
-  {
-
-  },
-"HTMLOptionsCollection.dart":
-  {
-
-  },
-"HashChangeEvent.dart":
-  {
-
-  },
-"HeadElement.dart":
-  {
-
-  },
-"HeadingElement.dart":
-  {
-
-  },
-"HtmlAllCollection.dart":
-  {
-
-  },
-"HtmlCollection.dart":
-  {
-
-  },
-"HtmlDocument.dart":
-  {
-
-  },
-"HtmlElement.dart":
-  {
-
-  },
-"HtmlOptionsCollection.dart":
-  {
-
-  },
-"HttpRequest.dart":
-  {
-  "  @Creates('ArrayBuffer|Blob|Document|=Object|=List|String|num')":
-    [
-      "  /**",
-      "   * The data received as a reponse from the request.",
-      "   *",
-      "   * The data could be in the",
-      "   * form of a [String], [ArrayBuffer], [Document], [Blob], or json (also a ",
-      "   * [String]). `null` indicates request failure.",
-      "   */"
-    ],
-  "  @JSName('responseXML')":
-    [
-      "  /**",
-      "   * The request response, or null on failure.",
-      "   * ",
-      "   * The response is processed as",
-      "   * `text/xml` stream, unless responseType = 'document' and the request is",
-      "   * synchronous.",
-      "   */"
-    ],
-  "  EventListenerList get abort => this['abort'];":
-    [
-      "  /**",
-      "   * Event listeners to be notified when request has been aborted,",
-      "   * generally due to calling `httpRequest.abort()`.",
-      "   */"
-    ],
-  "  EventListenerList get error => this['error'];":
-    [
-      "  /**",
-      "   * Event listeners to be notified when a request has failed, such as when a",
-      "   * cross-domain error occurred or the file wasn't found on the server.",
-      "   */"
-    ],
-  "  EventListenerList get load => this['load'];":
-    [
-      "  /**",
-      "   * Event listeners to be notified once the request has completed",
-      "   * *successfully*.",
-      "   */"
-    ],
-  "  EventListenerList get loadEnd => this['loadend'];":
-    [
-      "  /**",
-      "   * Event listeners to be notified once the request has completed (on",
-      "   * either success or failure).",
-      "   */"
-    ],
-  "  EventListenerList get loadStart => this['loadstart'];":
-    [
-      "  /**",
-      "   * Event listeners to be notified when the request starts, once",
-      "   * `httpRequest.send()` has been called.",
-      "   */"
-    ],
-  "  EventListenerList get progress => this['progress'];":
-    [
-      "  /**",
-      "   * Event listeners to be notified when data for the request ",
-      "   * is being sent or loaded.",
-      "   *",
-      "   * Progress events are fired every 50ms or for every byte transmitted,",
-      "   * whichever is less frequent.",
-      "   */"
-    ],
-  "  EventListenerList get readyStateChange => this['readystatechange'];":
-    [
-      "  /**",
-      "   * Event listeners to be notified every time the [HttpRequest]",
-      "   * object's `readyState` changes values.",
-      "   */"
-    ],
-  "  HttpRequestEvents get on =>":
-    [
-      "  /**",
-      "   * Get the set of [HttpRequestEvents] that this request can respond to.",
-      "   * Usually used when adding an EventListener, such as in",
-      "   * `document.window.on.keyDown.add((e) => print('keydown happened'))`.",
-      "   */"
-    ],
-  "  String getAllResponseHeaders() native;":
-    [
-      "  /**",
-      "   * Retrieve all the response headers from a request.",
-      "   * ",
-      "   * `null` if no headers have been received. For multipart requests,",
-      "   * `getAllResponseHeaders` will return the response headers for the current",
-      "   * part of the request.",
-      "   * ",
-      "   * See also [HTTP response headers](http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Responses)",
-      "   * for a list of common response headers.",
-      "   */"
-    ],
-  "  String getResponseHeader(String header) native;":
-    [
-      "  /**",
-      "   * Return the response header named `header`, or `null` if not found.",
-      "   * ",
-      "   * See also [HTTP response headers](http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Responses)",
-      "   * for a list of common response headers.",
-      "   */"
-    ],
-  "  String responseType;":
-    [
-      "  /**",
-      "   * [String] telling the server the desired response format. ",
-      "   *",
-      "   * Default is `String`.",
-      "   * Other options are one of 'arraybuffer', 'blob', 'document', 'json',",
-      "   * 'text'. Some newer browsers will throw `NS_ERROR_DOM_INVALID_ACCESS_ERR` if",
-      "   * `responseType` is set while performing a synchronous request.",
-      "   *",
-      "   * See also: [MDN responseType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType)",
-      "   */"
-    ],
-  "  bool withCredentials;":
-    [
-      "  /**",
-      "   * True if cross-site requests should use credentials such as cookies",
-      "   * or authorization headers; false otherwise. ",
-      "   *",
-      "   * This value is ignored for same-site requests.",
-      "   */"
-    ],
-  "  factory HttpRequest() => _HttpRequestFactoryProvider.createHttpRequest();":
-    [
-      "  /**",
-      "   * General constructor for any type of request (GET, POST, etc).",
-      "   *",
-      "   * This call is used in conjunction with [open]:",
-      "   * ",
-      "   *     var request = new HttpRequest();",
-      "   *     request.open('GET', 'http://dartlang.org')",
-      "   *     request.on.load.add((event) => print('Request complete'));",
-      "   * ",
-      "   * is the (more verbose) equivalent of",
-      "   * ",
-      "   *     var request = new HttpRequest.get('http://dartlang.org',",
-      "   *         (event) => print('Request complete'));",
-      "   */"
-    ],
-  "  final HttpRequestUpload upload;":
-    [
-      "  /**",
-      "   * [EventTarget] that can hold listeners to track the progress of the request.",
-      "   * The events fired will be members of [HttpRequestUploadEvents].",
-      "   */"
-    ],
-  "  final String responseText;":
-    [
-      "  /**",
-      "   * The response in string form or null on failure.",
-      "   */"
-    ],
-  "  final String statusText;":
-    [
-      "  /**",
-      "   * The request response string (such as \"200 OK\").",
-      "   * See also: [Http Status Codes](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes)",
-      "   */"
-    ],
-  "  final int readyState;":
-    [
-      "  /**",
-      "   * Indicator of the current state of the request:",
-      "   *",
-      "   * <table>",
-      "   *   <tr>",
-      "   *     <td>Value</td>",
-      "   *     <td>State</td>",
-      "   *     <td>Meaning</td>",
-      "   *   </tr>",
-      "   *   <tr>",
-      "   *     <td>0</td>",
-      "   *     <td>unsent</td>",
-      "   *     <td><code>open()</code> has not yet been called</td>",
-      "   *   </tr>",
-      "   *   <tr>",
-      "   *     <td>1</td>",
-      "   *     <td>opened</td>",
-      "   *     <td><code>send()</code> has not yet been called</td>",
-      "   *   </tr>",
-      "   *   <tr>",
-      "   *     <td>2</td>",
-      "   *     <td>headers received</td>",
-      "   *     <td><code>sent()</code> has been called; response headers and <code>status</code> are available</td>",
-      "   *   </tr>",
-      "   *   <tr>",
-      "   *     <td>3</td> <td>loading</td> <td><code>responseText</code> holds some data</td>",
-      "   *   </tr>",
-      "   *   <tr>",
-      "   *     <td>4</td> <td>done</td> <td>request is complete</td>",
-      "   *   </tr>",
-      "   * </table>",
-      "   */"
-    ],
-  "  final int status;":
-    [
-      "  /**",
-      "   * The http result code from the request (200, 404, etc).",
-      "   * See also: [Http Status Codes](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes)",
-      "   */"
-    ],
-  "  void abort() native;":
-    [
-      "  /**",
-      "   * Stop the current request.",
-      "   *",
-      "   * The request can only be stopped if readyState is `HEADERS_RECIEVED` or ",
-      "   * `LOADING`. If this method is not in the process of being sent, the method",
-      "   * has no effect.",
-      "   */"
-    ],
-  "  void open(String method, String url, [bool async, String user, String password]) native;":
-    [
-      "  /**",
-      "   * Specify the desired `url`, and `method` to use in making the request.",
-      "   * ",
-      "   * By default the request is done asyncronously, with no user or password",
-      "   * authentication information. If `async` is false, the request will be send",
-      "   * synchronously.",
-      "   * ",
-      "   * Calling `open` again on a currently active request is equivalent to",
-      "   * calling `abort`.",
-      "   */"
-    ],
-  "  void overrideMimeType(String override) native;":
-    [
-      "  /**",
-      "   * Specify a particular MIME type (such as `text/xml`) desired for the",
-      "   * response.",
-      "   * ",
-      "   * This value must be set before the request has been sent. See also the list",
-      "   * of [common MIME types](http://en.wikipedia.org/wiki/Internet_media_type#List_of_common_media_types)",
-      "   */"
-    ],
-  "  void send([data]) native;":
-    [
-      "  /**",
-      "   * Send the request with any given `data`.",
-      "   *",
-      "   * See also: ",
-      "   * [send() docs](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#send())",
-      "   * from MDN.",
-      "   */"
-    ],
-  "  void setRequestHeader(String header, String value) native;":
-    [
-      "  /** Sets HTTP `header` to `value`. */"
-    ],
-  "class HttpRequestEvents extends Events {":
-    [
-      "/**",
-      " * A class that supports listening for and dispatching events that can fire when",
-      " * making an HTTP request. ",
-      " *  ",
-      " * Here's an example of adding an event handler that executes once an HTTP",
-      " * request has fully loaded:",
-      " * ",
-      " *     httpRequest.on.loadEnd.add((e) => myCustomLoadEndHandler(e));",
-      " *",
-      " * Each property of this class is a read-only pointer to an [EventListenerList].",
-      " * That list holds all of the [EventListener]s that have registered for that",
-      " * particular type of event that fires from an HttpRequest.",
-      " */"
-    ]
-  },
-"HttpRequestException.dart":
-  {
-
-  },
-"HttpRequestProgressEvent.dart":
-  {
-
-  },
-"HttpRequestUpload.dart":
-  {
-
-  },
-"IDBAny.dart":
-  {
-
-  },
-"IDBCursor.dart":
-  {
-
-  },
-"IDBCursorWithValue.dart":
-  {
-
-  },
-"IDBDatabase.dart":
-  {
-
-  },
-"IDBDatabaseException.dart":
-  {
-
-  },
-"IDBFactory.dart":
-  {
-
-  },
-"IDBIndex.dart":
-  {
-
-  },
-"IDBKey.dart":
-  {
-
-  },
-"IDBKeyRange.dart":
-  {
-
-  },
-"IDBObjectStore.dart":
-  {
-
-  },
-"IDBOpenDBRequest.dart":
-  {
-
-  },
-"IDBRequest.dart":
-  {
-
-  },
-"IDBTransaction.dart":
-  {
-
-  },
-"IDBUpgradeNeededEvent.dart":
-  {
-
-  },
-"IDBVersionChangeEvent.dart":
-  {
-
-  },
-"IDBVersionChangeRequest.dart":
-  {
-
-  },
-"IFrameElement.dart":
-  {
-
-  },
-"IceCallback.dart":
-  {
-
-  },
-"IceCandidate.dart":
-  {
-
-  },
-"ImageData.dart":
-  {
-
-  },
-"ImageElement.dart":
-  {
-
-  },
-"InputElement.dart":
-  {
-
-  },
-"Int16Array.dart":
-  {
-
-  },
-"Int32Array.dart":
-  {
-
-  },
-"Int8Array.dart":
-  {
-
-  },
-"JavaScriptCallFrame.dart":
-  {
-
-  },
-"KeyboardEvent.dart":
-  {
-
-  },
-"KeygenElement.dart":
-  {
-
-  },
-"LIElement.dart":
-  {
-
-  },
-"LabelElement.dart":
-  {
-
-  },
-"LegendElement.dart":
-  {
-
-  },
-"LinkElement.dart":
-  {
-
-  },
-"LocalHistory.dart":
-  {
-
-  },
-"LocalLocation.dart":
-  {
-
-  },
-"LocalMediaStream.dart":
-  {
-
-  },
-"LocalWindow.dart":
-  {
-
-  },
-"MapElement.dart":
-  {
-
-  },
-"MarqueeElement.dart":
-  {
-
-  },
-"MediaController.dart":
-  {
-
-  },
-"MediaElement.dart":
-  {
-
-  },
-"MediaElementAudioSourceNode.dart":
-  {
-
-  },
-"MediaError.dart":
-  {
-
-  },
-"MediaKeyError.dart":
-  {
-
-  },
-"MediaKeyEvent.dart":
-  {
-
-  },
-"MediaList.dart":
-  {
-
-  },
-"MediaQueryList.dart":
-  {
-
-  },
-"MediaQueryListListener.dart":
-  {
-
-  },
-"MediaSource.dart":
-  {
-
-  },
-"MediaStream.dart":
-  {
-
-  },
-"MediaStreamAudioSourceNode.dart":
-  {
-
-  },
-"MediaStreamEvent.dart":
-  {
-
-  },
-"MediaStreamTrack.dart":
-  {
-
-  },
-"MediaStreamTrackEvent.dart":
-  {
-
-  },
-"MediaStreamTrackList.dart":
-  {
-
-  },
-"MemoryInfo.dart":
-  {
-
-  },
-"MenuElement.dart":
-  {
-  "class MenuElement extends Element native \"*HTMLMenuElement\" {":
-    [
-      "/**",
-      " * An HTML <menu> element.",
-      " *",
-      " * A <menu> element represents an unordered list of menu commands.",
-      " *",
-      " * See also:",
-      " *",
-      " *  * [Menu Element](https://developer.mozilla.org/en-US/docs/HTML/Element/menu) from MDN.",
-      " *  * [Menu Element](http://www.w3.org/TR/html5/the-menu-element.html#the-menu-element) from the W3C.",
-      " */"
-    ]
-  },
-"MessageChannel.dart":
-  {
-
-  },
-"MessageEvent.dart":
-  {
-
-  },
-"MessagePort.dart":
-  {
-
-  },
-"MetaElement.dart":
-  {
-
-  },
-"Metadata.dart":
-  {
-
-  },
-"MetadataCallback.dart":
-  {
-
-  },
-"MeterElement.dart":
-  {
-
-  },
-"ModElement.dart":
-  {
-
-  },
-"MouseEvent.dart":
-  {
-
-  },
-"MutationCallback.dart":
-  {
-
-  },
-"MutationEvent.dart":
-  {
-
-  },
-"MutationObserver.dart":
-  {
-
-  },
-"MutationRecord.dart":
-  {
-
-  },
-"NamedNodeMap.dart":
-  {
-
-  },
-"Navigator.dart":
-  {
-
-  },
-"NavigatorUserMediaError.dart":
-  {
-
-  },
-"NavigatorUserMediaErrorCallback.dart":
-  {
-
-  },
-"NavigatorUserMediaSuccessCallback.dart":
-  {
-
-  },
-"Node.dart":
-  {
-
-  },
-"NodeFilter.dart":
-  {
-
-  },
-"NodeIterator.dart":
-  {
-
-  },
-"NodeList.dart":
-  {
-
-  },
-"Notation.dart":
-  {
-
-  },
-"Notification.dart":
-  {
-
-  },
-"NotificationCenter.dart":
-  {
-
-  },
-"NotificationPermissionCallback.dart":
-  {
-
-  },
-"OESElementIndexUint.dart":
-  {
-
-  },
-"OESStandardDerivatives.dart":
-  {
-
-  },
-"OESTextureFloat.dart":
-  {
-
-  },
-"OESVertexArrayObject.dart":
-  {
-
-  },
-"OListElement.dart":
-  {
-
-  },
-"ObjectElement.dart":
-  {
-
-  },
-"OesElementIndexUint.dart":
-  {
-
-  },
-"OesStandardDerivatives.dart":
-  {
-
-  },
-"OesTextureFloat.dart":
-  {
-
-  },
-"OesVertexArrayObject.dart":
-  {
-
-  },
-"OfflineAudioCompletionEvent.dart":
-  {
-
-  },
-"OptGroupElement.dart":
-  {
-
-  },
-"OptionElement.dart":
-  {
-
-  },
-"OscillatorNode.dart":
-  {
-
-  },
-"OutputElement.dart":
-  {
-
-  },
-"OverflowEvent.dart":
-  {
-
-  },
-"PagePopupController.dart":
-  {
-
-  },
-"PageTransitionEvent.dart":
-  {
-
-  },
-"PannerNode.dart":
-  {
-
-  },
-"ParagraphElement.dart":
-  {
-
-  },
-"ParamElement.dart":
-  {
-
-  },
-"PeerConnection00.dart":
-  {
-
-  },
-"Performance.dart":
-  {
-
-  },
-"PerformanceNavigation.dart":
-  {
-
-  },
-"PerformanceTiming.dart":
-  {
-
-  },
-"Point.dart":
-  {
-
-  },
-"PopStateEvent.dart":
-  {
-
-  },
-"PositionCallback.dart":
-  {
-
-  },
-"PositionError.dart":
-  {
-
-  },
-"PositionErrorCallback.dart":
-  {
-
-  },
-"PreElement.dart":
-  {
-
-  },
-"ProcessingInstruction.dart":
-  {
-
-  },
-"ProgressElement.dart":
-  {
-
-  },
-"ProgressEvent.dart":
-  {
-
-  },
-"QuoteElement.dart":
-  {
-
-  },
-"RGBColor.dart":
-  {
-
-  },
-"RTCDataChannel.dart":
-  {
-
-  },
-"RTCDataChannelEvent.dart":
-  {
-
-  },
-"RTCErrorCallback.dart":
-  {
-
-  },
-"RTCIceCandidate.dart":
-  {
-
-  },
-"RTCIceCandidateEvent.dart":
-  {
-
-  },
-"RTCPeerConnection.dart":
-  {
-
-  },
-"RTCSessionDescription.dart":
-  {
-
-  },
-"RTCSessionDescriptionCallback.dart":
-  {
-
-  },
-"RTCStatsCallback.dart":
-  {
-
-  },
-"RTCStatsElement.dart":
-  {
-
-  },
-"RTCStatsReport.dart":
-  {
-
-  },
-"RTCStatsResponse.dart":
-  {
-
-  },
-"RadioNodeList.dart":
-  {
-
-  },
-"Range.dart":
-  {
-
-  },
-"RangeException.dart":
-  {
-
-  },
-"Rect.dart":
-  {
-
-  },
-"RequestAnimationFrameCallback.dart":
-  {
-
-  },
-"RgbColor.dart":
-  {
-
-  },
-"RtcDataChannel.dart":
-  {
-
-  },
-"RtcDataChannelEvent.dart":
-  {
-
-  },
-"RtcIceCandidate.dart":
-  {
-
-  },
-"RtcIceCandidateEvent.dart":
-  {
-
-  },
-"RtcPeerConnection.dart":
-  {
-
-  },
-"RtcSessionDescription.dart":
-  {
-
-  },
-"RtcStatsElement.dart":
-  {
-
-  },
-"RtcStatsReport.dart":
-  {
-
-  },
-"RtcStatsResponse.dart":
-  {
-
-  },
-"SQLError.dart":
-  {
-
-  },
-"SQLException.dart":
-  {
-
-  },
-"SQLResultSet.dart":
-  {
-
-  },
-"SQLResultSetRowList.dart":
-  {
-
-  },
-"SQLStatementCallback.dart":
-  {
-
-  },
-"SQLStatementErrorCallback.dart":
-  {
-
-  },
-"SQLTransaction.dart":
-  {
-
-  },
-"SQLTransactionCallback.dart":
-  {
-
-  },
-"SQLTransactionErrorCallback.dart":
-  {
-
-  },
-"SQLTransactionSync.dart":
-  {
-
-  },
-"SQLTransactionSyncCallback.dart":
-  {
-
-  },
-"Screen.dart":
-  {
-
-  },
-"ScriptElement.dart":
-  {
-
-  },
-"ScriptProcessorNode.dart":
-  {
-
-  },
-"ScriptProfile.dart":
-  {
-
-  },
-"ScriptProfileNode.dart":
-  {
-
-  },
-"SelectElement.dart":
-  {
-
-  },
-"SessionDescription.dart":
-  {
-
-  },
-"ShadowElement.dart":
-  {
-
-  },
-"ShadowRoot.dart":
-  {
-
-  },
-"SharedWorker.dart":
-  {
-
-  },
-"SharedWorkerContext.dart":
-  {
-
-  },
-"SourceBuffer.dart":
-  {
-
-  },
-"SourceBufferList.dart":
-  {
-
-  },
-"SourceElement.dart":
-  {
-
-  },
-"SpanElement.dart":
-  {
-
-  },
-"SpeechGrammar.dart":
-  {
-
-  },
-"SpeechGrammarList.dart":
-  {
-
-  },
-"SpeechInputEvent.dart":
-  {
-
-  },
-"SpeechInputResult.dart":
-  {
-
-  },
-"SpeechRecognition.dart":
-  {
-
-  },
-"SpeechRecognitionAlternative.dart":
-  {
-
-  },
-"SpeechRecognitionError.dart":
-  {
-
-  },
-"SpeechRecognitionEvent.dart":
-  {
-
-  },
-"SpeechRecognitionResult.dart":
-  {
-
-  },
-"SqlError.dart":
-  {
-
-  },
-"SqlException.dart":
-  {
-
-  },
-"SqlResultSet.dart":
-  {
-
-  },
-"SqlResultSetRowList.dart":
-  {
-
-  },
-"SqlTransaction.dart":
-  {
-
-  },
-"SqlTransactionSync.dart":
-  {
-
-  },
-"Storage.dart":
-  {
-
-  },
-"StorageEvent.dart":
-  {
-
-  },
-"StorageInfo.dart":
-  {
-
-  },
-"StorageInfoErrorCallback.dart":
-  {
-
-  },
-"StorageInfoQuotaCallback.dart":
-  {
-
-  },
-"StorageInfoUsageCallback.dart":
-  {
-
-  },
-"StringCallback.dart":
-  {
-
-  },
-"StyleElement.dart":
-  {
-
-  },
-"StyleMedia.dart":
-  {
-
-  },
-"StyleSheet.dart":
-  {
-
-  },
-"TableCaptionElement.dart":
-  {
-
-  },
-"TableCellElement.dart":
-  {
-
-  },
-"TableColElement.dart":
-  {
-
-  },
-"TableElement.dart":
-  {
-
-  },
-"TableRowElement.dart":
-  {
-
-  },
-"TableSectionElement.dart":
-  {
-
-  },
-"Text.dart":
-  {
-
-  },
-"TextAreaElement.dart":
-  {
-
-  },
-"TextEvent.dart":
-  {
-
-  },
-"TextMetrics.dart":
-  {
-
-  },
-"TextTrack.dart":
-  {
-
-  },
-"TextTrackCue.dart":
-  {
-
-  },
-"TextTrackCueList.dart":
-  {
-
-  },
-"TextTrackList.dart":
-  {
-
-  },
-"TimeRanges.dart":
-  {
-
-  },
-"TimeoutHandler.dart":
-  {
-
-  },
-"TitleElement.dart":
-  {
-
-  },
-"Touch.dart":
-  {
-
-  },
-"TouchEvent.dart":
-  {
-
-  },
-"TouchList.dart":
-  {
-
-  },
-"TrackElement.dart":
-  {
-
-  },
-"TrackEvent.dart":
-  {
-
-  },
-"TransitionEvent.dart":
-  {
-
-  },
-"TreeWalker.dart":
-  {
-
-  },
-"UIEvent.dart":
-  {
-
-  },
-"UListElement.dart":
-  {
-
-  },
-"Uint16Array.dart":
-  {
-
-  },
-"Uint32Array.dart":
-  {
-
-  },
-"Uint8Array.dart":
-  {
-
-  },
-"Uint8ClampedArray.dart":
-  {
-
-  },
-"UnknownElement.dart":
-  {
-
-  },
-"Url.dart":
-  {
-
-  },
-"ValidityState.dart":
-  {
-
-  },
-"VideoElement.dart":
-  {
-
-  },
-"VoidCallback.dart":
-  {
-
-  },
-"WaveShaperNode.dart":
-  {
-
-  },
-"WaveTable.dart":
-  {
-
-  },
-"WebGLActiveInfo.dart":
-  {
-
-  },
-"WebGLBuffer.dart":
-  {
-
-  },
-"WebGLCompressedTextureS3TC.dart":
-  {
-
-  },
-"WebGLContextAttributes.dart":
-  {
-
-  },
-"WebGLContextEvent.dart":
-  {
-
-  },
-"WebGLDebugRendererInfo.dart":
-  {
-
-  },
-"WebGLDebugShaders.dart":
-  {
-
-  },
-"WebGLDepthTexture.dart":
-  {
-
-  },
-"WebGLFramebuffer.dart":
-  {
-
-  },
-"WebGLLoseContext.dart":
-  {
-
-  },
-"WebGLProgram.dart":
-  {
-
-  },
-"WebGLRenderbuffer.dart":
-  {
-
-  },
-"WebGLRenderingContext.dart":
-  {
-
-  },
-"WebGLShader.dart":
-  {
-
-  },
-"WebGLShaderPrecisionFormat.dart":
-  {
-
-  },
-"WebGLTexture.dart":
-  {
-
-  },
-"WebGLUniformLocation.dart":
-  {
-
-  },
-"WebGLVertexArrayObject.dart":
-  {
-
-  },
-"WebGLVertexArrayObjectOES.dart":
-  {
-
-  },
-"WebKitCSSFilterValue.dart":
-  {
-
-  },
-"WebKitCssFilterValue.dart":
-  {
-
-  },
-"WebKitNamedFlow.dart":
-  {
-
-  },
-"WebSocket.dart":
-  {
-
-  },
-"WheelEvent.dart":
-  {
-
-  },
-"Worker.dart":
-  {
-
-  },
-"WorkerContext.dart":
-  {
-
-  },
-"WorkerLocation.dart":
-  {
-
-  },
-"WorkerNavigator.dart":
-  {
-
-  },
-"XMLSerializer.dart":
-  {
-
-  },
-"XPathEvaluator.dart":
-  {
-
-  },
-"XPathException.dart":
-  {
-
-  },
-"XPathExpression.dart":
-  {
-
-  },
-"XPathNSResolver.dart":
-  {
-
-  },
-"XPathResult.dart":
-  {
-
-  },
-"XSLTProcessor.dart":
-  {
-
-  },
-"XmlSerializer.dart":
-  {
-
-  },
-"XsltProcessor.dart":
-  {
-
-  }
-}
diff --git a/tools/dom/docs/lib/docs.dart b/tools/dom/docs/lib/docs.dart
index 74529c4..9e89782 100644
--- a/tools/dom/docs/lib/docs.dart
+++ b/tools/dom/docs/lib/docs.dart
@@ -15,9 +15,10 @@
 
 /// The various HTML libraries.
 const List<String> HTML_LIBRARY_NAMES = const ['dart:html',
+                                               'dart:indexed_db',
                                                'dart:svg',
                                                'dart:web_audio',
-                                               'dart:indexed_db'];
+                                               'dart:web_sql'];
 /**
  * Converts the libraries in [HTML_LIBRARY_NAMES] to a json file at [jsonPath]
  * given the library path at [libPath].
@@ -185,4 +186,4 @@
   } else {
     return <String>[];
   }
-}
\ No newline at end of file
+}
diff --git a/tools/dom/docs/svg_docs.json b/tools/dom/docs/svg_docs.json
deleted file mode 100644
index d0dec29..0000000
--- a/tools/dom/docs/svg_docs.json
+++ /dev/null
@@ -1,606 +0,0 @@
-{
-"PathSegLinetoVerticalRel.dart":
-  {
-
-  },
-"DefsElement.dart":
-  {
-
-  },
-"LineElement.dart":
-  {
-
-  },
-"SwitchElement.dart":
-  {
-
-  },
-"Rect.dart":
-  {
-
-  },
-"Matrix.dart":
-  {
-
-  },
-"VKernElement.dart":
-  {
-
-  },
-"RenderingIntent.dart":
-  {
-
-  },
-"AnimatedBoolean.dart":
-  {
-
-  },
-"Angle.dart":
-  {
-
-  },
-"MissingGlyphElement.dart":
-  {
-
-  },
-"ZoomEvent.dart":
-  {
-
-  },
-"RadialGradientElement.dart":
-  {
-
-  },
-"AltGlyphDefElement.dart":
-  {
-
-  },
-"PathSegCurvetoQuadraticRel.dart":
-  {
-
-  },
-"FEPointLightElement.dart":
-  {
-
-  },
-"ScriptElement.dart":
-  {
-
-  },
-"GradientElement.dart":
-  {
-
-  },
-"FETileElement.dart":
-  {
-
-  },
-"PathSegList.dart":
-  {
-
-  },
-"AnimateTransformElement.dart":
-  {
-
-  },
-"TSpanElement.dart":
-  {
-
-  },
-"FEGaussianBlurElement.dart":
-  {
-
-  },
-"PathSegCurvetoQuadraticAbs.dart":
-  {
-
-  },
-"AnimateElement.dart":
-  {
-
-  },
-"ExternalResourcesRequired.dart":
-  {
-
-  },
-"FontFaceNameElement.dart":
-  {
-
-  },
-"UriReference.dart":
-  {
-
-  },
-"Length.dart":
-  {
-
-  },
-"FEMergeElement.dart":
-  {
-
-  },
-"Point.dart":
-  {
-
-  },
-"AnimatedTransformList.dart":
-  {
-
-  },
-"ViewSpec.dart":
-  {
-
-  },
-"Transformable.dart":
-  {
-
-  },
-"FEDisplacementMapElement.dart":
-  {
-
-  },
-"PathSegArcRel.dart":
-  {
-
-  },
-"Stylable.dart":
-  {
-
-  },
-"PathSegLinetoRel.dart":
-  {
-
-  },
-"PathSegCurvetoCubicSmoothRel.dart":
-  {
-
-  },
-"FEMorphologyElement.dart":
-  {
-
-  },
-"ElementInstance.dart":
-  {
-
-  },
-"AnimateMotionElement.dart":
-  {
-
-  },
-"AElement.dart":
-  {
-
-  },
-"FontElement.dart":
-  {
-
-  },
-"AnimatedInteger.dart":
-  {
-
-  },
-"PathElement.dart":
-  {
-
-  },
-"FEColorMatrixElement.dart":
-  {
-
-  },
-"PathSegLinetoHorizontalAbs.dart":
-  {
-
-  },
-"NumberList.dart":
-  {
-
-  },
-"RectElement.dart":
-  {
-
-  },
-"MPathElement.dart":
-  {
-
-  },
-"PathSegClosePath.dart":
-  {
-
-  },
-"FEFloodElement.dart":
-  {
-
-  },
-"FontFaceSrcElement.dart":
-  {
-
-  },
-"Number.dart":
-  {
-
-  },
-"PolylineElement.dart":
-  {
-
-  },
-"AnimatedLengthList.dart":
-  {
-
-  },
-"FECompositeElement.dart":
-  {
-
-  },
-"FontFaceFormatElement.dart":
-  {
-
-  },
-"TransformList.dart":
-  {
-
-  },
-"FEDropShadowElement.dart":
-  {
-
-  },
-"SvgSvgElement.dart":
-  {
-
-  },
-"PreserveAspectRatio.dart":
-  {
-
-  },
-"ForeignObjectElement.dart":
-  {
-
-  },
-"FESpotLightElement.dart":
-  {
-
-  },
-"DescElement.dart":
-  {
-
-  },
-"FontFaceUriElement.dart":
-  {
-
-  },
-"ImageElement.dart":
-  {
-
-  },
-"AnimatedPreserveAspectRatio.dart":
-  {
-
-  },
-"PathSegCurvetoQuadraticSmoothAbs.dart":
-  {
-
-  },
-"GElement.dart":
-  {
-
-  },
-"PathSegMovetoRel.dart":
-  {
-
-  },
-"Paint.dart":
-  {
-
-  },
-"AnimatedEnumeration.dart":
-  {
-
-  },
-"FEFuncAElement.dart":
-  {
-
-  },
-"CircleElement.dart":
-  {
-
-  },
-"SetElement.dart":
-  {
-
-  },
-"TitleElement.dart":
-  {
-
-  },
-"PatternElement.dart":
-  {
-
-  },
-"AnimatedString.dart":
-  {
-
-  },
-"FEFuncRElement.dart":
-  {
-
-  },
-"SvgDocument.dart":
-  {
-
-  },
-"FEMergeNodeElement.dart":
-  {
-
-  },
-"SvgException.dart":
-  {
-
-  },
-"UseElement.dart":
-  {
-
-  },
-"PathSegLinetoVerticalAbs.dart":
-  {
-
-  },
-"FontFaceElement.dart":
-  {
-
-  },
-"PathSegCurvetoCubicRel.dart":
-  {
-
-  },
-"Color.dart":
-  {
-
-  },
-"PathSegArcAbs.dart":
-  {
-
-  },
-"FilterPrimitiveStandardAttributes.dart":
-  {
-
-  },
-"AnimationElement.dart":
-  {
-
-  },
-"AltGlyphElement.dart":
-  {
-
-  },
-"MarkerElement.dart":
-  {
-
-  },
-"FEDiffuseLightingElement.dart":
-  {
-
-  },
-"FETurbulenceElement.dart":
-  {
-
-  },
-"SvgElement.dart":
-  {
-
-  },
-"Transform.dart":
-  {
-
-  },
-"Locatable.dart":
-  {
-
-  },
-"UnitTypes.dart":
-  {
-
-  },
-"ViewElement.dart":
-  {
-
-  },
-"FEConvolveMatrixElement.dart":
-  {
-
-  },
-"FEDistantLightElement.dart":
-  {
-
-  },
-"PolygonElement.dart":
-  {
-
-  },
-"MetadataElement.dart":
-  {
-
-  },
-"ZoomAndPan.dart":
-  {
-
-  },
-"ClipPathElement.dart":
-  {
-
-  },
-"TextPositioningElement.dart":
-  {
-
-  },
-"StopElement.dart":
-  {
-
-  },
-"SymbolElement.dart":
-  {
-
-  },
-"HKernElement.dart":
-  {
-
-  },
-"GlyphRefElement.dart":
-  {
-
-  },
-"PathSegCurvetoCubicAbs.dart":
-  {
-
-  },
-"GlyphElement.dart":
-  {
-
-  },
-"MaskElement.dart":
-  {
-
-  },
-"TextContentElement.dart":
-  {
-
-  },
-"FilterElement.dart":
-  {
-
-  },
-"FEFuncGElement.dart":
-  {
-
-  },
-"EllipseElement.dart":
-  {
-
-  },
-"Tests.dart":
-  {
-
-  },
-"AnimatedLength.dart":
-  {
-
-  },
-"PathSegCurvetoQuadraticSmoothRel.dart":
-  {
-
-  },
-"StyleElement.dart":
-  {
-
-  },
-"CursorElement.dart":
-  {
-
-  },
-"FitToViewBox.dart":
-  {
-
-  },
-"TextElement.dart":
-  {
-
-  },
-"FEFuncBElement.dart":
-  {
-
-  },
-"FEOffsetElement.dart":
-  {
-
-  },
-"FEImageElement.dart":
-  {
-
-  },
-"LangSpace.dart":
-  {
-
-  },
-"FESpecularLightingElement.dart":
-  {
-
-  },
-"PointList.dart":
-  {
-
-  },
-"LinearGradientElement.dart":
-  {
-
-  },
-"PathSegMovetoAbs.dart":
-  {
-
-  },
-"AnimatedNumberList.dart":
-  {
-
-  },
-"PathSegLinetoHorizontalRel.dart":
-  {
-
-  },
-"LengthList.dart":
-  {
-
-  },
-"ComponentTransferFunctionElement.dart":
-  {
-
-  },
-"StringList.dart":
-  {
-
-  },
-"FEComponentTransferElement.dart":
-  {
-
-  },
-"PathSegCurvetoCubicSmoothAbs.dart":
-  {
-
-  },
-"PathSegLinetoAbs.dart":
-  {
-
-  },
-"AnimatedNumber.dart":
-  {
-
-  },
-"TextPathElement.dart":
-  {
-
-  },
-"AnimatedRect.dart":
-  {
-
-  },
-"AnimatedAngle.dart":
-  {
-
-  },
-"AltGlyphItemElement.dart":
-  {
-
-  },
-"TRefElement.dart":
-  {
-
-  },
-"AnimateColorElement.dart":
-  {
-
-  },
-"PathSeg.dart":
-  {
-
-  },
-"FEBlendElement.dart":
-  {
-
-  }
-}
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 713efe3..0450497 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -41,7 +41,7 @@
   [Suppressed] DOMString toDataURL([TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=DefaultIsUndefined] in DOMString type) raises(DOMException);
   [Custom] DOMString toDataURL([TreatNullAs=NullString, TreatUndefinedAs=NullString,Optional=DefaultIsUndefined] in DOMString type, [Optional] in float quality) raises(DOMException);
 
-  [Suppressed] DOMObject getContext(in DOMString contextId);
+  [Suppressed] any getContext(in DOMString contextId);
   [Custom] CanvasRenderingContext getContext(in DOMString contextId, [Optional] in Dictionary attrs);
 };
 
@@ -54,8 +54,6 @@
 interface HTMLSelectElement {
   [Suppressed] void add([Optional=DefaultIsUndefined] in HTMLElement element, [Optional=DefaultIsUndefined] in HTMLElement before);
   [Suppressed, Custom] void remove();
-  [Custom] void remove(in long index);
-  [Custom] void remove(in HTMLOptionElement option);
 };
 
 [Supplemental]
@@ -209,8 +207,8 @@
   // We have to use custom code because our code generator does not support int8_t type.
   // int8_t getInt8(in unsigned long byteOffset);
   // uint8_t getUint8(in unsigned long byteOffset);
-  [Suppressed] DOMObject getInt8();
-  [Suppressed] DOMObject getUint8();
+  [Suppressed] any getInt8();
+  [Suppressed] any getUint8();
   byte getInt8(in unsigned long byteOffset)
       raises (DOMException);
   octet getUint8(in unsigned long byteOffset)
@@ -322,7 +320,7 @@
 interface SQLResultSetRowList {
   // Change the return type to Dictionary so that rows are exposed in the Dart
   // API as a Maps, with the appropriate conversion in JavaScript.
-  [Suppressed] DOMObject item(in unsigned long index);
+  [Suppressed] any item(in unsigned long index);
   [Custom] Dictionary item(in unsigned long index);
 };
 
@@ -341,5 +339,24 @@
   [Custom] void send(ArrayBufferView data) raises(DOMException);
 };
 
+[Supplemental]
+interface XMLHttpRequest {
+   [Custom] void send()
+       raises(DOMException);
+   [Custom] void send(in ArrayBuffer data) // FIXME: this should be eventually deprecated.
+       raises(DOMException);
+   [Custom] void send(in ArrayBufferView data)
+       raises(DOMException);
+   [Conditional=BLOB, Custom] void send(in Blob data)
+       raises(DOMException);
+   [Custom] void send(in Document data)
+       raises(DOMException);
+   [Custom] void send([StrictTypeChecking] in DOMString data)
+       raises(DOMException);
+   [Custom] void send(in DOMFormData data)
+       raises(DOMException);
+};
+
+
 [Suppressed]
 interface Entity {};
diff --git a/tools/dom/scripts/databasebuilder.py b/tools/dom/scripts/databasebuilder.py
index 81d6c0e..96e724d 100755
--- a/tools/dom/scripts/databasebuilder.py
+++ b/tools/dom/scripts/databasebuilder.py
@@ -87,7 +87,7 @@
   def _resolve_type_defs(self, idl_file):
     type_def_map = {}
     # build map
-    for type_def in idl_file.all(IDLTypeDef):
+    for type_def in idl_file.typeDefs:
       if type_def.type.id != type_def.id: # sanity check
         type_def_map[type_def.id] = type_def.type.id
     # use the map
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index fa6fcac..20f6905 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -421,6 +421,10 @@
                            'dynamic', 'dynamic')
 
 dart2js_conversions = monitored.Dict('generator.dart2js_conversions', {
+    'Date get':
+      Conversion('_convertNativeToDart_DateTime', 'dynamic', 'DateTime'),
+    'Date set':
+      Conversion('_convertDartToNative_DateTime', 'DateTime', 'dynamic'),
     # Wrap non-local Windows.  We need to check EventTarget (the base type)
     # as well.  Note, there are no functions that take a non-local Window
     # as a parameter / setter.
@@ -583,6 +587,7 @@
     'IDBRequest.source':  ["@Creates('Null')"],
 
     'IDBFactory.open': ["@Creates('Database')"],
+    'IDBFactory.webkitGetDatabaseNames': ["@Creates('DomStringList')"],
 
     'IDBObjectStore.put': ["@_annotation_Creates_IDBKey"],
     'IDBObjectStore.add': ["@_annotation_Creates_IDBKey"],
@@ -635,6 +640,15 @@
 
     'SQLResultSetRowList.item': ["@Creates('=Object')"],
 
+    'WebGLRenderingContext.getParameter': [
+      # Taken from http://www.khronos.org/registry/webgl/specs/latest/
+      # Section 5.14.3 Setting and getting state
+      "@Creates('Null|num|String|bool|=List|Float32Array|Int32Array|Uint32Array"
+                "|WebGLFramebuffer|WebGLRenderbuffer|WebGLTexture')",
+      "@Returns('Null|num|String|bool|=List|Float32Array|Int32Array|Uint32Array"
+                "|WebGLFramebuffer|WebGLRenderbuffer|WebGLTexture')",
+    ],
+
     'XMLHttpRequest.response': [
       "@Creates('ArrayBuffer|Blob|Document|=Object|=List|String|num')",
     ],
@@ -710,6 +724,7 @@
 dart_annotations = monitored.Dict('generator.dart_annotations', {
   'ArrayBuffer': _all_but_ie9_annotations,
   'ArrayBufferView': _all_but_ie9_annotations,
+  'Crypto': _webkit_experimental_annotations,
   'Database': _web_sql_annotations,
   'DatabaseSync': _web_sql_annotations,
   'DOMApplicationCache': [
@@ -1200,7 +1215,10 @@
       type = 'RefPtr<%s>' % type
     if type == 'String':
       type = 'DartStringAdapter'
-    return '%s', type, 'DartUtilities', 'dartTo%s' % self._capitalized_native_type()
+    target_type = self._capitalized_native_type()
+    if self.idl_type() == 'Date':
+      target_type = 'Date'
+    return '%s', type, 'DartUtilities', 'dartTo%s' % target_type
 
   def parameter_type(self):
     if self.native_type() == 'String':
@@ -1211,8 +1229,14 @@
     return []
 
   def to_dart_conversion(self, value, interface_name=None, attributes=None):
-    function_name = self._capitalized_native_type()
-    function_name = function_name[0].lower() + function_name[1:]
+    # TODO(antonm): if there are more instances of the case
+    # when conversion depends on both Dart type and C++ type,
+    # consider introducing a corresponding argument/class.
+    if self.idl_type() == 'Date':
+      function_name = 'date'
+    else:
+      function_name = self._capitalized_native_type()
+      function_name = function_name[0].lower() + function_name[1:]
     function_name = 'DartUtilities::%sToDart' % function_name
     if attributes and 'TreatReturnedNullStringAs' in attributes:
       function_name += 'WithNullCheck'
@@ -1321,7 +1345,7 @@
     'any': TypeData(clazz='Primitive', dart_type='Object', native_type='ScriptValue'),
     'Array': TypeData(clazz='Primitive', dart_type='List'),
     'custom': TypeData(clazz='Primitive', dart_type='dynamic'),
-    'Date': TypeData(clazz='Primitive', dart_type='Date', native_type='double'),
+    'Date': TypeData(clazz='Primitive', dart_type='DateTime', native_type='double'),
     'DOMObject': TypeData(clazz='Primitive', dart_type='Object', native_type='ScriptValue'),
     'DOMString': TypeData(clazz='Primitive', dart_type='String', native_type='String'),
     # TODO(vsm): This won't actually work until we convert the Map to
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index c312a9f..705232a 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -154,11 +154,36 @@
   'Geolocation.getCurrentPosition',
   'Geolocation.watchPosition',
   'HashChangeEvent.initHashChangeEvent',
+  'HTMLTableElement.createCaption',
+  'HTMLTableElement.createTBody',
+  'HTMLTableElement.createTFoot',
+  'HTMLTableElement.createTHead',
+  'HTMLTableElement.insertRow',
+  'HTMLTableElement.rows',
+  'HTMLTableElement.tBodies',
+  'HTMLTableRowElement.cells',
+  'HTMLTableRowElement.insertCell',
+  'HTMLTableSectionElement.insertRow',
+  'HTMLTableSectionElement.rows',
+  'IDBCursor.delete',
+  'IDBCursor.update',
+  'IDBDatabase.createObjectStore',
   'IDBFactory.deleteDatabase',
+  'IDBFactory.webkitGetDatabaseNames',
   'IDBFactory.open',
-  'IDBObjectStore.put',
+  'IDBIndex.count',
+  'IDBIndex.get',
+  'IDBIndex.getKey',
+  'IDBIndex.openCursor',
+  'IDBIndex.openKeyCursor',
+  'IDBObjectStore.add',
+  'IDBObjectStore.clear',
+  'IDBObjectStore.count',
+  'IDBObjectStore.createIndex',
+  'IDBObjectStore.delete',
   'IDBObjectStore.getObject',
   'IDBObjectStore.openCursor',
+  'IDBObjectStore.put',
   'KeyboardEvent.initKeyboardEvent',
   'KeyboardEvent.keyIdentifier',
   'MessageEvent.initMessageEvent',
diff --git a/tools/dom/scripts/idlnode.py b/tools/dom/scripts/idlnode.py
index 7442912..f8dc742 100755
--- a/tools/dom/scripts/idlnode.py
+++ b/tools/dom/scripts/idlnode.py
@@ -258,9 +258,11 @@
     modules = self._convert_all(ast, 'Module', IDLModule)
     self.implementsStatements = self._convert_all(ast, 'ImplStmt',
       IDLImplementsStatement)
+    self.typeDefs = self._convert_all(ast, 'TypeDef', IDLTypeDef)
     for module in modules:
       self.interfaces.extend(module.interfaces)
       self.implementsStatements.extend(module.implementsStatements)
+      self.typeDefs.extend(module.typeDefs)
 
 
 class IDLModule(IDLNode):
diff --git a/tools/dom/scripts/idlparser.py b/tools/dom/scripts/idlparser.py
index a3ee82f..e3c47b3 100755
--- a/tools/dom/scripts/idlparser.py
+++ b/tools/dom/scripts/idlparser.py
@@ -70,7 +70,7 @@
         OR(Module, Interface, ExceptionDef, TypeDef, ImplStmt,
            ValueTypeDef, Const, Enum),
         # WebKit:
-        OR(Module, Interface, Enum))
+        OR(Module, Interface, Enum, TypeDef))
 
     def Enum():
       def StringLiteral():
diff --git a/tools/dom/scripts/idlsync.py b/tools/dom/scripts/idlsync.py
index 1439399..94f435e 100755
--- a/tools/dom/scripts/idlsync.py
+++ b/tools/dom/scripts/idlsync.py
@@ -31,7 +31,6 @@
 WEBKIT_REV_PATTERN = r'"dartium_webkit_revision": "(\d+)",'
 WEBCORE_SUBPATH = 'Source/WebCore'
 LOCAL_WEBKIT_IDL_PATH = os.path.join(DART_PATH, 'third_party', 'WebCore')
-LOCAL_WEBKIT_README = os.path.join(LOCAL_WEBKIT_IDL_PATH, 'README')
 LOCAL_WEBKIT_README = """\
 This directory contains a copy of WebKit/WebCore IDL files.
 See the attached LICENSE-* files in this directory.
@@ -48,10 +47,19 @@
 CHROME_URL_PATTERN = r'"chromium_url": "(\S+)",'
 CHROME_REV_PATTERN = r'"chromium_revision": "(\d+)",'
 CHROME_IDL_SUBPATH = 'trunk/src/chrome/common/extensions/api'
-CHROME_TOOLS_SUBPATH = 'trunk/src/tools/json_schema_compiler'
+CHROME_TOOLS_SUBPATH = 'trunk/src/tools'
+CHROME_COMPILER_SUBPATH = 'trunk/src/tools/json_schema_compiler'
+CHROME_IDL_PARSER_SUBPATH = 'trunk/src/ppapi/generators'
+CHROME_PLY_SUBPATH = 'trunk/src/third_party/ply'
 LOCAL_CHROME_IDL_PATH = os.path.join(DART_PATH, 'third_party', 'chrome', 'idl')
 LOCAL_CHROME_TOOLS_PATH = os.path.join(DART_PATH, 'third_party', 'chrome',
                                        'tools')
+LOCAL_CHROME_COMPILER_PATH = os.path.join(DART_PATH, 'third_party', 'chrome',
+                                          'tools', 'json_schema_compiler')
+LOCAL_CHROME_IDL_PARSER_PATH = os.path.join(DART_PATH, 'third_party', 'chrome',
+                                            'ppapi', 'generators')
+LOCAL_CHROME_PLY_PATH = os.path.join(DART_PATH, 'third_party', 'chrome',
+                                     'third_party', 'ply')
 LOCAL_CHROME_README = """\
 This directory contains a copy of Chromium IDL and generation scripts
 used to generate Dart APIs for Chrome Apps.
@@ -63,6 +71,8 @@
 Please see the corresponding LICENSE file at
 %(url)s/trunk/src/LICENSE.
 """
+DEPTH_FILES = 'files'
+DEPTH_INFINITY = 'infinity'
 
 # Regular expressions corresponding to URL/revision patters in the
 # DEPS file.
@@ -73,15 +83,28 @@
 
 # List of components to update.
 UPDATE_LIST = [
-    # (component, remote subpath, local path, local readme file)
+    # (component, remote subpath, local path, local readme file, depth)
 
     # WebKit IDL.
-    ('webkit', WEBCORE_SUBPATH, LOCAL_WEBKIT_IDL_PATH, LOCAL_WEBKIT_README),
+    ('webkit', WEBCORE_SUBPATH, LOCAL_WEBKIT_IDL_PATH, LOCAL_WEBKIT_README,
+     DEPTH_INFINITY),
     # Chrome IDL.
-    ('chrome', CHROME_IDL_SUBPATH, LOCAL_CHROME_IDL_PATH, LOCAL_CHROME_README),
-    # Chrome IDL compiler files.
+    ('chrome', CHROME_IDL_SUBPATH, LOCAL_CHROME_IDL_PATH, LOCAL_CHROME_README,
+     DEPTH_INFINITY),
+    # Chrome PPAPI generators. Contains idl_parser.py which is used by the
+    # Chrome IDL compiler.
+    ('chrome', CHROME_IDL_PARSER_SUBPATH, LOCAL_CHROME_IDL_PARSER_PATH,
+     LOCAL_CHROME_README, DEPTH_FILES),
+    # ply files.
+    ('chrome', CHROME_PLY_SUBPATH, LOCAL_CHROME_PLY_PATH, LOCAL_CHROME_README,
+     DEPTH_INFINITY),
+    # Top level Chrome tools folder. Contains json_comment_eater.py which is
+    # needed by the Chrome IDL compiler.
     ('chrome', CHROME_TOOLS_SUBPATH, LOCAL_CHROME_TOOLS_PATH,
-     LOCAL_CHROME_README),
+     LOCAL_CHROME_README, DEPTH_FILES),
+    # Chrome IDL compiler files.
+    ('chrome', CHROME_COMPILER_SUBPATH, LOCAL_CHROME_COMPILER_PATH,
+     LOCAL_CHROME_README, DEPTH_INFINITY),
     ]
 
 
@@ -111,9 +134,9 @@
   return (url, revision)
 
 
-def RefreshIDL(url, revision, remote_path, local_path):
+def RefreshFiles(url, revision, remote_path, local_path, depth):
   """Refreshes refreshes files in the local_path to specific url /
-  revision / remote_path."""
+  revision / remote_path, exporting to depth"""
   cwd = os.getcwd()
   try:
     if os.path.exists(local_path):
@@ -122,7 +145,8 @@
     if not os.path.exists(head):
       os.makedirs(head)
     os.chdir(head)
-    RunCommand(['svn', 'export', '-r', revision, url + '/' + remote_path, tail])
+    RunCommand(['svn', 'export', '--depth', depth, '-r', revision,
+                url + '/' + remote_path, tail])
   finally:
     os.chdir(cwd)
 
@@ -174,13 +198,13 @@
 def main():
   deps = GetDeps()
   update = ParseOptions()
-  for (component, remote_path, local_path, readme) in UPDATE_LIST:
+  for (component, remote_path, local_path, readme, depth) in UPDATE_LIST:
     if component in update.keys():
       revision = update[component]
       url, latest = GetSvnRevision(deps, component)
       if revision is None:
         revision = latest
-      RefreshIDL(url, revision, remote_path, local_path)
+      RefreshFiles(url, revision, remote_path, local_path, depth)
       PruneExtraFiles(local_path)
       GenerateReadme(local_path, readme, url, revision)
 
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index e3ba590..7a0c5dd 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -359,6 +359,8 @@
 
 js_support_checks = dict({
     'ArrayBuffer': "JS('bool', 'typeof window.ArrayBuffer != \"undefined\"')",
+    'Crypto':
+        "JS('bool', '!!(window.crypto && window.crypto.getRandomValues)')",
     'Database': "JS('bool', '!!(window.openDatabase)')",
     'DOMApplicationCache': "JS('bool', '!!(window.applicationCache)')",
     'DOMFileSystem': "JS('bool', '!!(window.webkitRequestFileSystem)')",
@@ -669,10 +671,27 @@
     #
     #   class YImpl extends ListBase<T> { copies of transitive XImpl methods; }
     #
-    self._members_emitter.Emit(
-        '\n'
-        '  $TYPE operator[](int index) => JS("$TYPE", "#[#]", this, index);\n',
-        TYPE=self.SecureOutputType(element_type))
+
+    ext_attrs = self._interface.ext_attrs
+    has_indexed_getter = ('IndexedGetter' in ext_attrs or
+      'CustomIndexedSetter' in ext_attrs)
+
+    if has_indexed_getter:
+      self._members_emitter.Emit(
+          '\n'
+          '  $TYPE operator[](int index) => '
+          'JS("$TYPE", "#[#]", this, index);\n',
+          TYPE=self.SecureOutputType(element_type))
+    else:
+      if any(op.id == 'getItem' for op in self._interface.operations):
+        indexed_getter = 'this.getItem(index)'
+      elif any(op.id == 'item' for op in self._interface.operations):
+        indexed_getter = 'this.item(index)'
+      self._members_emitter.Emit(
+          '\n'
+          '  $TYPE operator[](int index) => $INDEXED_GETTER;\n',
+          INDEXED_GETTER=indexed_getter,
+          TYPE=self.SecureOutputType(element_type))
 
     if 'CustomIndexedSetter' in self._interface.ext_attrs:
       self._members_emitter.Emit(
@@ -801,9 +820,9 @@
 
   def _AddConvertingGetter(self, attr, html_name, conversion):
     self._members_emitter.Emit(
-        '\n  $RETURN_TYPE get $HTML_NAME => $CONVERT(this._$(HTML_NAME));'
+        '\n  $RETURN_TYPE get $HTML_NAME => $CONVERT(this._get_$(HTML_NAME));'
         "\n  @JSName('$NAME')"
-        '\n  $(ANNOTATIONS)final $NATIVE_TYPE _$HTML_NAME;'
+        '\n  $(ANNOTATIONS)final $NATIVE_TYPE _get_$HTML_NAME;'
         '\n',
         ANNOTATIONS=self._Annotations(attr.type.id, html_name),
         CONVERT=conversion.function_name,
@@ -816,9 +835,9 @@
     self._members_emitter.Emit(
         # TODO(sra): Use metadata to provide native name.
         '\n  void set $HTML_NAME($INPUT_TYPE value) {'
-        '\n    this._$HTML_NAME = $CONVERT(value);'
+        '\n    this._set_$HTML_NAME = $CONVERT(value);'
         '\n  }'
-        '\n  void set _$HTML_NAME(/*$NATIVE_TYPE*/ value) {'
+        '\n  void set _set_$HTML_NAME(/*$NATIVE_TYPE*/ value) {'
         '\n    JS("void", "#.$NAME = #", this, value);'
         '\n  }'
         '\n',
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index 51dd3b5..65528b4 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -114,7 +114,8 @@
   String get first => readClasses().first;
   String get last => readClasses().last;
   String get single => readClasses().single;
-  List<String> toList() => readClasses().toList();
+  List<String> toList({ bool growable: true }) =>
+      readClasses().toList(growable: growable);
   Set<String> toSet() => readClasses().toSet();
   String min([int compare(String a, String b)]) =>
       readClasses().min(compare);
diff --git a/tools/dom/src/KeyboardEventController.dart b/tools/dom/src/KeyboardEventController.dart
index 73a7602..4235b75 100644
--- a/tools/dom/src/KeyboardEventController.dart
+++ b/tools/dom/src/KeyboardEventController.dart
@@ -35,7 +35,7 @@
   EventTarget _target;
 
   // The distance to shift from upper case alphabet Roman letters to lower case.
-  final int _ROMAN_ALPHABET_OFFSET = "a".charCodes[0] - "A".charCodes[0];
+  final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
 
   StreamSubscription _keyUpSubscription, _keyDownSubscription,
       _keyPressSubscription;
@@ -170,8 +170,8 @@
       if (prevEvent._shadowCharCode == event.charCode) {
         return prevEvent.keyCode;
       }
-      if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".charCodes[0]
-          && event.charCode <= "Z".charCodes[0] && event.charCode +
+      if ((event.shiftKey || _capsLockOn) && event.charCode >= "A".codeUnits[0]
+          && event.charCode <= "Z".codeUnits[0] && event.charCode +
           _ROMAN_ALPHABET_OFFSET == prevEvent._shadowCharCode) {
         return prevEvent.keyCode;
       }
diff --git a/tools/dom/src/Serialization.dart b/tools/dom/src/Serialization.dart
index 0d1cc82..df29f58 100644
--- a/tools/dom/src/Serialization.dart
+++ b/tools/dom/src/Serialization.dart
@@ -98,7 +98,7 @@
 
   _serializeList(List list) {
     int len = list.length;
-    var result = new List.fixedLength(len);
+    var result = new List(len);
     for (int i = 0; i < len; i++) {
       result[i] = _dispatch(list[i]);
     }
diff --git a/tools/dom/src/WrappedList.dart b/tools/dom/src/WrappedList.dart
new file mode 100644
index 0000000..7b27218
--- /dev/null
+++ b/tools/dom/src/WrappedList.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.dom.html;
+
+/**
+ * A list which just wraps another list, for either intercepting list calls or
+ * retyping the list (for example, from List<A> to List<B> where B extends A).
+ */
+class _WrappedList<E> implements List<E> {
+  final List _list;
+
+  _WrappedList(this._list);
+
+  // Iterable APIs
+
+  Iterator<E> get iterator => new _WrappedIterator(_list.iterator);
+
+  Iterable map(f(E element)) => _list.map(f);
+
+  Iterable<E> where(bool f(E element)) => _list.where(f);
+
+  Iterable expand(Iterable f(E element)) => _list.expand(f);
+
+  bool contains(E element) => _list.contains(element);
+
+  void forEach(void f(E element)) { _list.forEach(f); }
+
+  dynamic reduce(initialValue, combine(previousValue, E element)) =>
+      _list.reduce(initialValue, combine);
+
+  bool every(bool f(E element)) => _list.every(f);
+
+  String join([String separator]) => _list.join(separator);
+
+  bool any(bool f(E element)) => _list.any(f);
+
+  List<E> toList({ bool growable: true }) =>
+      new List.from(_list, growable: growable);
+
+  Set<E> toSet() => _list.toSet();
+
+  int get length => _list.length;
+
+  E min([int compare(E a, E b)]) => _list.min(compare);
+
+  E max([int compare(E a, E b)]) => _list.max(compare);
+
+  bool get isEmpty => _list.isEmpty;
+
+  Iterable<E> take(int n) => _list.take(n);
+
+  Iterable<E> takeWhile(bool test(E value)) => _list.takeWhile(test);
+
+  Iterable<E> skip(int n) => _list.skip(n);
+
+  Iterable<E> skipWhile(bool test(E value)) => _list.skipWhile(test);
+
+  E get first => _list.first;
+
+  E get last => _list.last;
+
+  E get single => _list.single;
+
+  E firstMatching(bool test(E value), { E orElse() }) =>
+      _list.firstMatching(test, orElse: orElse);
+
+  E lastMatching(bool test(E value), {E orElse()}) =>
+      _list.lastMatching(test, orElse: orElse);
+
+  E singleMatching(bool test(E value)) => _list.singleMatching(test);
+
+  E elementAt(int index) => _list.elementAt(index);
+
+  // Collection APIs
+
+  void add(E element) { _list.add(element); }
+
+  void addAll(Iterable<E> elements) { _list.addAll(elements); }
+
+  void remove(Object element) { _list.remove(element); }
+
+  void removeAll(Iterable elements) { _list.removeAll(elements); }
+
+  void retainAll(Iterable elements) { _list.retainAll(elements); }
+
+  void removeMatching(bool test(E element)) { _list.removeMatching(test); }
+
+  void retainMatching(bool test(E element)) { _list.retainMatching(test); }
+
+  void clear() { _list.clear(); }
+
+  // List APIs
+
+  E operator [](int index) => _list[index];
+
+  void operator []=(int index, E value) { _list[index] = value; }
+
+  void set length(int newLength) { _list.length = newLength; }
+
+  void addLast(E value) { _list.addLast(value); }
+
+  Iterable<E> get reversed => _list.reversed;
+
+  void sort([int compare(E a, E b)]) { _list.sort(compare); }
+
+  int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+
+  int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+
+  E removeAt(int index) => _list.removeAt(index);
+
+  E removeLast() => _list.removeLast();
+
+  List<E> getRange(int start, int length) => _list.getRange(start, length);
+
+  void setRange(int start, int length, List<E> from, [int startFrom]) {
+    _list.setRange(start, length, from, startFrom);
+  }
+
+  void removeRange(int start, int length) { _list.removeRange(start, length); }
+
+  void insertRange(int start, int length, [E fill]) {
+    _list.insertRange(start, length, fill);
+  }
+
+  Map<int, E> asMap() => IterableMixinWorkaround.asMapList(_list);
+}
+
+/**
+ * Iterator wrapper for _WrappedList.
+ */
+class _WrappedIterator<E> implements Iterator<E> {
+  Iterator _iterator;
+
+  _WrappedIterator(this._iterator);
+
+  bool moveNext() {
+    return _iterator.moveNext();
+  }
+
+  E get current => _iterator.current;
+}
diff --git a/tools/dom/src/dart2js_Conversions.dart b/tools/dom/src/dart2js_Conversions.dart
index 8b75d71..7e9ee41 100644
--- a/tools/dom/src/dart2js_Conversions.dart
+++ b/tools/dom/src/dart2js_Conversions.dart
@@ -11,6 +11,15 @@
 
 part of html;
 
+DateTime _convertNativeToDart_DateTime(date) {
+  var millisSinceEpoch = JS('int', '#.getTime()', date);
+  return new DateTime.fromMillisecondsSinceEpoch(millisSinceEpoch, isUtc: true);
+}
+
+_convertDartToNative_DateTime(DateTime date) {
+  return JS('', 'new Date(#)', date.millisecondsSinceEpoch);
+}
+
 WindowBase _convertNativeToDart_Window(win) {
   return _DOMWindowCrossFrame._createSafe(win);
 }
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 2f91ab1..cd98baf 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -5,10 +5,15 @@
 part of html;
 
 class _Utils {
+  static double dateTimeToDouble(DateTime dateTime) =>
+      dateTime.millisecondsSinceEpoch.toDouble();
+  static DateTime doubleToDateTime(double dateTime) =>
+      new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
+
   static List convertToList(List list) {
     // FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it.
     final length = list.length;
-    List result = new List.fixedLength(length);
+    List result = new List(length);
     result.setRange(0, length, list);
     return result;
   }
diff --git a/tools/dom/templates/html/dart2js/chrome_dart2js.darttemplate b/tools/dom/templates/html/dart2js/chrome_dart2js.darttemplate
index 6449f29..5b2ec9b 100644
--- a/tools/dom/templates/html/dart2js/chrome_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/chrome_dart2js.darttemplate
@@ -12,8 +12,8 @@
 /// These functions allow direct access to the Packaged App APIs, allowing
 /// Chrome Packaged Apps to be written using Dart.
 ///
-/// For more information on these APIs, see the Chrome.* APIs Documentation:
-///   http://developer.chrome.com/extensions/api_index.html
+/// For more information on these APIs, see the
+/// [Chrome APIs Documentation](http://developer.chrome.com/extensions/api_index.html)
 library chrome;
 
 import 'dart:_foreign_helper' show JS;
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 2823cdd..728b9d0 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -42,6 +42,7 @@
 part '$AUXILIARY_DIR/Isolates.dart';
 part '$AUXILIARY_DIR/Microtask.dart';
 part '$AUXILIARY_DIR/Serialization.dart';
+part '$AUXILIARY_DIR/WrappedList.dart';
 part '$AUXILIARY_DIR/shared_FactoryProviders.dart';
 part '$AUXILIARY_DIR/dart2js_Conversions.dart';
 part '$AUXILIARY_DIR/dart2js_DOMImplementation.dart';
diff --git a/tools/dom/templates/html/dart2js/impl_Console.darttemplate b/tools/dom/templates/html/dart2js/impl_Console.darttemplate
index 0bc592c..25d08e1 100644
--- a/tools/dom/templates/html/dart2js/impl_Console.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_Console.darttemplate
@@ -8,7 +8,7 @@
 
   static Console safeConsole = new Console();
 
-  bool get _isConsoleDefined => JS('bool', "typeof console != 'undefined'");
+  bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
 
   @DomName('Console.memory')
   MemoryInfo get memory => _isConsoleDefined ?
diff --git a/tools/dom/templates/html/dart2js/impl_HTMLTableElement.darttemplate b/tools/dom/templates/html/dart2js/impl_HTMLTableElement.darttemplate
deleted file mode 100644
index b41ec58..0000000
--- a/tools/dom/templates/html/dart2js/impl_HTMLTableElement.darttemplate
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of $LIBRARYNAME;
-
-$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
-$!MEMBERS
-
-  Element createTBody() {
-    if (JS('bool', '!!#.createTBody', this)) {
-      return this._createTBody();
-    }
-    var tbody = new Element.tag('tbody');
-    this.children.add(tbody);
-    return tbody;
-  }
-
-  @JSName('createTBody')
-  Element _createTBody() native;
-}
diff --git a/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate b/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
index 2c6fec6..6a599c1 100644
--- a/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/web_sql_dart2js.darttemplate
@@ -2,6 +2,16 @@
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
 // Auto-generated dart:audio library.
 
+/**
+ * An API for storing data in the browser that can be queried with SQL.
+ *
+ * **Caution:** this specification is no longer actively maintained by the Web
+ * Applications Working Group and may be removed at any time.
+ * See [the W3C Web SQL Database specification](http://www.w3.org/TR/webdatabase/)
+ * for more information.
+ *
+ * The [dart:indexed_db] APIs is a recommended alternatives.
+ */
 library dart.dom.web_sql;
 
 import 'dart:async';
diff --git a/tools/dom/templates/html/dartium/chrome_dartium.darttemplate b/tools/dom/templates/html/dartium/chrome_dartium.darttemplate
index 38db7cd..03a6cb4 100644
--- a/tools/dom/templates/html/dartium/chrome_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/chrome_dartium.darttemplate
@@ -5,4 +5,11 @@
 // DO NOT EDIT
 // Auto-generated dart:chrome library.
 
+/// Native wrappers for the Chrome Packaged App APIs.
+///
+/// These functions allow direct access to the Packaged App APIs, allowing
+/// Chrome Packaged Apps to be written using Dart.
+///
+/// For more information on these APIs, see the
+/// [Chrome APIs Documentation](http://developer.chrome.com/extensions/api_index.html)
 library chrome;
diff --git a/tools/dom/templates/html/dartium/html_dartium.darttemplate b/tools/dom/templates/html/dartium/html_dartium.darttemplate
index 4e2b5e7..77ca4f5 100644
--- a/tools/dom/templates/html/dartium/html_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/html_dartium.darttemplate
@@ -5,6 +5,7 @@
 // DO NOT EDIT
 // Auto-generated dart:html library.
 
+/// The Dart HTML library.
 library dart.dom.html;
 
 import 'dart:async';
@@ -32,6 +33,7 @@
 part '$AUXILIARY_DIR/KeyName.dart';
 part '$AUXILIARY_DIR/ReadyState.dart';
 part '$AUXILIARY_DIR/Timer.dart';
+part '$AUXILIARY_DIR/WrappedList.dart';
 part '$AUXILIARY_DIR/_HttpRequestUtils.dart';
 part '$AUXILIARY_DIR/shared_FactoryProviders.dart';
 part '$AUXILIARY_DIR/dartium_KeyEvent.dart';
diff --git a/tools/dom/templates/html/dartium/web_sql_dartium.darttemplate b/tools/dom/templates/html/dartium/web_sql_dartium.darttemplate
index 0556070..bfb9155 100644
--- a/tools/dom/templates/html/dartium/web_sql_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/web_sql_dartium.darttemplate
@@ -2,6 +2,16 @@
 // https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
 // Auto-generated dart:audio library.
 
+/**
+ * An API for storing data in the browser that can be queried with SQL.
+ *
+ * **Caution:** this specification is no longer actively maintained by the Web
+ * Applications Working Group and may be removed at any time.
+ * See [the W3C Web SQL Database specification](http://www.w3.org/TR/webdatabase/)
+ * for more information.
+ *
+ * The [dart:indexed_db] APIs is a recommended alternatives.
+ */
 library dart.dom.web_sql;
 
 import 'dart:async';
diff --git a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
index 6c73249..040a646 100644
--- a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
@@ -53,11 +53,14 @@
 
 $if DART2JS
   void setProperty(String propertyName, String value, [String priority]) {
-    JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
-    // Bug #2772, IE9 requires a poke to actually apply the value.
-    if (JS('bool', '!!#.setAttribute', this)) {
-      JS('void', '#.setAttribute(#, #)', this, propertyName, value);
-    }
+    // try/catch for IE9 which throws on unsupported values.
+    try {
+      JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
+      // Bug #2772, IE9 requires a poke to actually apply the value.
+      if (JS('bool', '!!#.setAttribute', this)) {
+        JS('void', '#.setAttribute(#, #)', this, propertyName, value);
+      }
+    } catch (e) {}
   }
 
   /**
diff --git a/tools/dom/templates/html/impl/impl_Document.darttemplate b/tools/dom/templates/html/impl/impl_Document.darttemplate
index ad71764..c1714b0 100644
--- a/tools/dom/templates/html/impl/impl_Document.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Document.darttemplate
@@ -61,7 +61,7 @@
       final mutableMatches = $dom_getElementsByName(
           selectors.substring(7,selectors.length - 2));
       int len = mutableMatches.length;
-      final copyOfMatches = new List<Element>.fixedLength(len);
+      final copyOfMatches = new List<Element>(len);
       for (int i = 0; i < len; ++i) {
         copyOfMatches[i] = mutableMatches[i];
       }
@@ -69,7 +69,7 @@
     } else if (new RegExp("^[*a-zA-Z0-9]+\$").hasMatch(selectors)) {
       final mutableMatches = $dom_getElementsByTagName(selectors);
       int len = mutableMatches.length;
-      final copyOfMatches = new List<Element>.fixedLength(len);
+      final copyOfMatches = new List<Element>(len);
       for (int i = 0; i < len; ++i) {
         copyOfMatches[i] = mutableMatches[i];
       }
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 3e0080a..35e8e2f 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -15,8 +15,14 @@
     : _childElements = element.$dom_children,
       _element = element;
 
-  List<Element> toList() {
-    final output = new List<Element>.fixedLength(_childElements.length);
+  List<Element> toList({ bool growable: true }) {
+    List<Element> output;
+    if (growable) {
+      output = <Element>[];
+      output.length = _childElements.length;
+    } else {
+      output = new List<Element>(_childElements.length);
+    }
     for (int i = 0, len = _childElements.length; i < len; i++) {
       output[i] = _childElements[i];
     }
@@ -254,6 +260,10 @@
   Element max([int compare(Element a, Element b)]) {
     return IterableMixinWorkaround.max(this, compare);
   }
+
+  Map<int, Element> asMap() {
+    return IterableMixinWorkaround.asMapList(this);
+  }
 }
 
 // TODO(jacobr): this is an inefficient implementation but it is hard to see
@@ -312,7 +322,8 @@
     return false;
   }
 
-  List<Element> toList() => new List<Element>.from(this);
+  List<Element> toList({ bool growable: true }) =>
+      new List<Element>.from(this, growable: growable);
   Set<Element> toSet() => new Set<Element>.from(this);
 
   Iterable<Element> take(int n) {
@@ -454,6 +465,10 @@
   Element max([int compare(Element a, Element b)]) {
     return IterableMixinWorkaround.max(this, compare);
   }
+
+  Map<int, Element> asMap() {
+    return IterableMixinWorkaround.asMapList(this);
+  }
 }
 
 class _FrozenElementListIterator implements Iterator<Element> {
diff --git a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
index f2777b6..c64f11a 100644
--- a/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLDocument.darttemplate
@@ -16,17 +16,6 @@
     document.$dom_body = value;
   }
 
-  /**
-   * Registers a custom Element subclass as an available HTML tag.
-   *
-   * Not yet implemented.
-   */
-  @Experimental
-  void register(String tagName, Type elementClass) {
-    // TODO: tagName validation
-    throw new Exception('Not yet implemented');
-  }
-
   @DomName('Document.caretRangeFromPoint')
   Range caretRangeFromPoint(int x, int y) {
     return document.$dom_caretRangeFromPoint(x, y);
diff --git a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
index deced63..bcac38d 100644
--- a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -12,7 +12,6 @@
     TelephoneInputElement,
     EmailInputElement,
     PasswordInputElement,
-    DateTimeInputElement,
     DateInputElement,
     MonthInputElement,
     WeekInputElement,
@@ -303,32 +302,6 @@
 }
 
 /**
- * A date and time (year, month, day, hour, minute, second, fraction of a
- * second) with the time zone set to UTC.
- *
- * Use [supported] to check if this is supported on the current platform.
- */
-@SupportedBrowser(SupportedBrowser.CHROME, '25')
-@Experimental
-abstract class DateTimeInputElement implements RangeInputElementBase {
-  factory DateTimeInputElement() => new InputElement(type: 'datetime');
-
-  @DomName('HTMLInputElement.valueAsDate')
-  DateTime valueAsDate;
-
-  @DomName('HTMLInputElement.readOnly')
-  bool readOnly;
-
-  @DomName('HTMLInputElement.required')
-  bool required;
-
-  /// Returns true if this input type is supported on the current platform.
-  static bool get supported {
-    return (new InputElement(type: 'datetime')).type == 'datetime';
-  }
-}
-
-/**
  * A date (year, month, day) with no time zone.
  *
  * Use [supported] to check if this is supported on the current platform.
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate
new file mode 100644
index 0000000..32cd109
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_HTMLTableElement.darttemplate
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+@DocsEditable
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+  @DomName('HTMLTableElement.tBodies')
+  List<TableSectionElement> get tBodies =>
+  new _WrappedList<TableSectionElement>($dom_tBodies);
+
+  @DomName('HTMLTableElement.rows')
+  List<TableRowElement> get rows =>
+      new _WrappedList<TableRowElement>($dom_rows);
+
+  TableRowElement addRow() {
+    return insertRow(-1);
+  }
+
+  TableCaptionElement createCaption() => $dom_createCaption();
+  TableSectionElement createTBody() => $dom_createTBody();
+  TableSectionElement createTFoot() => $dom_createTFoot();
+  TableSectionElement createTHead() => $dom_createTHead();
+  TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+$if DART2JS
+  TableSectionElement $dom_createTBody() {
+    if (JS('bool', '!!#.createTBody', this)) {
+      return this._createTBody();
+    }
+    var tbody = new Element.tag('tbody');
+    this.children.add(tbody);
+    return tbody;
+  }
+
+  @JSName('createTBody')
+  TableSectionElement _createTBody() native;
+$endif
+
+$!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate
new file mode 100644
index 0000000..af5ef17
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_HTMLTableRowElement.darttemplate
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+@DocsEditable
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+  @DomName('HTMLTableRowElement.cells')
+  List<TableCellElement> get cells =>
+      new _WrappedList<TableCellElement>($dom_cells);
+
+  TableCellElement addCell() {
+    return insertCell(-1);
+  }
+
+  TableCellElement insertCell(int index) => $dom_insertCell(index);
+
+$!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate
new file mode 100644
index 0000000..cb5dd96
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_HTMLTableSectionElement.darttemplate
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+@DocsEditable
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+  @DomName('HTMLTableSectionElement.rows')
+  List<TableRowElement> get rows =>
+    new _WrappedList<TableRowElement>($dom_rows);
+
+  TableRowElement addRow() {
+    return insertRow(-1);
+  }
+
+  TableRowElement insertRow(int index) => $dom_insertRow(index);
+
+$!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate b/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate
new file mode 100644
index 0000000..3464b5b
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_IDBCursor.darttemplate
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+  @DomName('IDBCursor.delete')
+  Future delete() {
+   try {
+      return _completeRequest($dom_delete());
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBCursor.value')
+  Future update(value) {
+   try {
+      return _completeRequest($dom_update(value));
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  $!MEMBERS
+}
diff --git a/tools/dom/templates/html/dart2js/impl_IDBDatabase.darttemplate b/tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
similarity index 64%
rename from tools/dom/templates/html/dart2js/impl_IDBDatabase.darttemplate
rename to tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
index cc7154d..fc77a04 100644
--- a/tools/dom/templates/html/dart2js/impl_IDBDatabase.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBDatabase.darttemplate
@@ -1,11 +1,27 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
 part of $LIBRARYNAME;
 
+@DocsEditable
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+  @DomName('IDBDatabase.createObjectStore')
+  @DocsEditable
+  ObjectStore createObjectStore(String name,
+      {String keyPath, bool autoIncrement}) {
+    var options = {};
+    if (keyPath != null) {
+      options['keyPath'] = keyPath;
+    }
+    if (autoIncrement != null) {
+      options['autoIncrement'] = autoIncrement;
+    }
 
+    return $dom_createObjectStore(name, options);
+  }
+
+$if DART2JS
   Transaction transaction(storeName_OR_storeNames, String mode) {
     if (mode != 'readonly' && mode != 'readwrite') {
       throw new ArgumentError(mode);
@@ -22,5 +38,6 @@
 
   @JSName('transaction')
   Transaction _transaction(stores, mode) native;
+$endif
 
 $!MEMBERS}
diff --git a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
index 7220e51..01031d6 100644
--- a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
@@ -62,6 +62,31 @@
     }
   }
 
+  @DomName('IDBFactory.getDatabaseNames')
+  @SupportedBrowser(SupportedBrowser.CHROME)
+  @Experimental
+  Future<List<String>> getDatabaseNames() {
+    try {
+      var request = $dom_webkitGetDatabaseNames();
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  /**
+   * Checks to see if getDatabaseNames is supported by the current platform.
+   */
+  bool get supportsDatabaseNames {
+$if DART2JS
+    return supported && JS('bool',
+        '!!(#.getDatabaseNames || #.webkitGetDatabaseNames)', this, this);
+$else
+    return true;
+$endif
+  }
+
 $!MEMBERS
 }
 
diff --git a/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate b/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate
new file mode 100644
index 0000000..08c5d07
--- /dev/null
+++ b/tools/dom/templates/html/impl/impl_IDBIndex.darttemplate
@@ -0,0 +1,100 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of $LIBRARYNAME;
+
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+  @DomName('IDBIndex.count')
+  Future<int> count([key_OR_range]) {
+   try {
+      var request;
+      if (key_OR_range != null) {
+        request = $dom_count(key_OR_range);
+      } else {
+        request = $dom_count();
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBIndex.get')
+  Future get(key) {
+    try {
+      var request = $dom_get(key);
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBIndex.getKey')
+  Future getKey(key) {
+    try {
+      var request = $dom_getKey(key);
+
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  /**
+   * Creates a stream of cursors over the records in this object store.
+   *
+   * See also:
+   *
+   * * [ObjectStore.openCursor]
+   */
+  Stream<CursorWithValue> openCursor({key, KeyRange range, String direction,
+      bool autoAdvance}) {
+    var key_OR_range = null;
+    if (key != null) {
+      if (range != null) {
+        throw new ArgumentError('Cannot specify both key and range.');
+      }
+      key_OR_range = key;
+    } else {
+      key_OR_range = range;
+    }
+    var request;
+    if (direction == null) {
+      request = $dom_openCursor(key_OR_range);
+    } else {
+      request = $dom_openCursor(key_OR_range, direction);
+    }
+    return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+  }
+
+  /**
+   * Creates a stream of cursors over the records in this object store.
+   *
+   * See also:
+   *
+   * * [ObjectStore.openCursor]
+   */
+  Stream<Cursor> openKeyCursor({key, KeyRange range, String direction,
+      bool autoAdvance}) {
+    var key_OR_range = null;
+    if (key != null) {
+      if (range != null) {
+        throw new ArgumentError('Cannot specify both key and range.');
+      }
+      key_OR_range = key;
+    } else {
+      key_OR_range = range;
+    }
+    var request;
+    if (direction == null) {
+      request = $dom_openKeyCursor(key_OR_range);
+    } else {
+      request = $dom_openKeyCursor(key_OR_range, direction);
+    }
+    return ObjectStore._cursorStreamFromResult(request, autoAdvance);
+  }
+
+  $!MEMBERS
+}
diff --git a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
index ec7d9b3..6f22f93 100644
--- a/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBObjectStore.darttemplate
@@ -6,6 +6,54 @@
 
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
 
+  @DomName('IDBObjectStore.add')
+  Future add(value, [key]) {
+    try {
+      var request;
+      if (key != null) {
+        request = $dom_add(value, key);
+      } else {
+        request = $dom_add(value);
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.clear')
+  Future clear() {
+    try {
+      return _completeRequest($dom_clear());
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.delete')
+  Future delete(key_OR_keyRange){
+    try {
+      return _completeRequest($dom_delete(key_OR_keyRange));
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
+  @DomName('IDBObjectStore.count')
+  Future<int> count([key_OR_range]) {
+   try {
+      var request;
+      if (key_OR_range != null) {
+        request = $dom_count(key_OR_range);
+      } else {
+        request = $dom_count();
+      }
+      return _completeRequest(request);
+    } catch (e, stacktrace) {
+      return new Future.immediateError(e, stacktrace);
+    }
+  }
+
   @DomName('IDBObjectStore.put')
   Future put(value, [key]) {
     try {
@@ -76,6 +124,19 @@
     return _cursorStreamFromResult(request, autoAdvance);
   }
 
+  @DomName('IDBObjectStore.createIndex')
+  Index createIndex(String name, keyPath, {bool unique, bool multiEntry}) {
+    var options = {};
+    if (unique != null) {
+      options['unique'] = unique;
+    }
+    if (multiEntry != null) {
+      options['multiEntry'] = multiEntry;
+    }
+
+    return $dom_createIndex(name, keyPath, options);
+  }
+
 $!MEMBERS
 
   /**
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate
index aee4497..b113a5a 100644
--- a/tools/dom/templates/html/impl/impl_Node.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -70,7 +70,13 @@
 
   void addAll(Iterable<Node> iterable) {
     if (iterable is _ChildNodeListLazy) {
-      iterable = new List.from(iterable);
+      if (iterable._this != _this) {
+        // Optimized route for copying between nodes.
+        for (var i = 0, len = iterable.length; i < len; ++i) {
+          _this.$dom_appendChild(iterable[0]);
+        }
+      }
+      return;
     }
     for (Node node in iterable) {
       _this.$dom_appendChild(node);
@@ -157,7 +163,8 @@
 
   bool any(bool f(Node element)) => IterableMixinWorkaround.any(this, f);
 
-  List<Node> toList() => new List<Node>.from(this);
+  List<Node> toList({ bool growable: true }) =>
+      new List<Node>.from(this, growable: growable);
   Set<Node> toSet() => new Set<Node>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -240,6 +247,8 @@
   }
 
   Node operator[](int index) => _this.$dom_childNodes[index];
+
+  Map<int, Node> asMap() => IterableMixinWorkaround.asMapList(this);
 }
 
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 083aebd..682813b 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -20,7 +20,7 @@
    * frame unwinds, causing the future to complete after all processing has
    * completed for the current event, but before any subsequent events.
    */
-  void setImmediate(TimeoutHandler callback) { 
+  void setImmediate(TimeoutHandler callback) {
     _addMicrotaskCallback(callback);
   }
   /**
@@ -28,8 +28,11 @@
    * registered under [name].
    */
   SendPortSync lookupPort(String name) {
-    var port =
-        json.parse(document.documentElement.attributes['dart-port:$name']);
+    var portStr = document.documentElement.attributes['dart-port:$name'];
+    if (portStr == null) {
+      return null;
+    }
+    var port = json.parse(portStr);
     return _deserialize(port);
   }
 
@@ -51,7 +54,7 @@
    * If you need to later cancel this animation, use [requestAnimationFrame]
    * instead.
    *
-   * Note: The code that runs when the future completes should call 
+   * Note: The code that runs when the future completes should call
    * [animationFrame] again for the animation to continue.
    */
   Future<num> get animationFrame {
@@ -127,7 +130,7 @@
 
   /**
    * Called to draw an animation frame and then request the window to repaint
-   * after [callback] has finished (creating the animation). 
+   * after [callback] has finished (creating the animation).
    *
    * Use this method only if you need to later call [cancelAnimationFrame]. If
    * not, the preferred Dart idiom is to set animation frames by calling
diff --git a/tools/dom/templates/immutable_list_mixin.darttemplate b/tools/dom/templates/immutable_list_mixin.darttemplate
index 850c2f8..7f2497f 100644
--- a/tools/dom/templates/immutable_list_mixin.darttemplate
+++ b/tools/dom/templates/immutable_list_mixin.darttemplate
@@ -42,7 +42,9 @@
 
   bool any(bool f($E element)) => IterableMixinWorkaround.any(this, f);
 
-  List<$E> toList() => new List<$E>.from(this);
+  List<$E> toList({ bool growable: true }) =>
+      new List<$E>.from(this, growable: growable);
+
   Set<$E> toSet() => new Set<$E>.from(this);
 
   bool get isEmpty => this.length == 0;
@@ -185,4 +187,7 @@
   List<$E> getRange(int start, int rangeLength) =>
       Lists.getRange(this, start, rangeLength, <$E>[]);
 
+  Map<int, $E> asMap() =>
+    IterableMixinWorkaround.asMapList(this);
+
   // -- end List<$E> mixins.
diff --git a/tools/line_doc_comments.dart b/tools/line_doc_comments.dart
index a51d84d..50727ee 100755
--- a/tools/line_doc_comments.dart
+++ b/tools/line_doc_comments.dart
@@ -4,7 +4,7 @@
 library line_doc_comments;
 import 'dart:io';
 
-import '../pkg/path/lib/path.dart' as path;
+import '../pkg/pathos/lib/path.dart' as path;
 
 final oneLineBlock = new RegExp(r'^(\s*)/\*\*\s?(.*)\*/\s*$');
 final startBlock = new RegExp(r'^(\s*)/\*\*(.*)$');
diff --git a/tools/test-runtime.dart b/tools/test-runtime.dart
index 32e4e07..3f30059 100755
--- a/tools/test-runtime.dart
+++ b/tools/test-runtime.dart
@@ -50,6 +50,7 @@
   var verbose = firstConf['verbose'];
   var printTiming = firstConf['time'];
   var listTests = firstConf['list'];
+  var useContentSecurityPolicy = firstConf['csp'];
 
   if (!firstConf['append_logs'])  {
     var file = new File(TestUtils.flakyFileName());
@@ -72,13 +73,27 @@
     print(output_words.join(' '));
   }
 
+  var runningBrowserTests = configurations.any((config) {
+    return TestUtils.isBrowserRuntime(config['runtime']);
+  });
+
   var testSuites = new List<TestSuite>();
-  TestingServerRunner.setBuildDir(firstConf);
-  TestingServerRunner.setPackageRootDir(firstConf);
   for (var conf in configurations) {
+    if (!listTests && runningBrowserTests) {
+      // Start global http servers that serve the entire dart repo.
+      // The http server is available on window.location.port, and a second
+      // server for cross-domain tests can be found by calling
+      // getCrossOriginPortNumber().
+      var servers = new TestingServers(new Path(TestUtils.buildDir(conf)),
+                                       useContentSecurityPolicy);
+      servers.startServers('127.0.0.1');
+      conf['_servers_'] = servers;
+    }
+
     if (selectors.containsKey('co19')) {
       testSuites.add(new Co19TestSuite(conf));
     }
+
     if (conf['runtime'] == 'vm' && selectors.containsKey('vm')) {
       // vm tests contain both cc tests (added here) and dart tests (added in
       // [TEST_SUITE_DIRECTORIES]).
@@ -93,15 +108,13 @@
     }
   }
 
-  // Start global http server that serves the entire dart repo.
-  // The http server is available on localhost:9876 for any
-  // test that needs to load resources from the repo over http.
-  if (!listTests) {
-    // Only start the server if we are running browser tests.
-    var runningBrowserTests = configurations.any((config) {
-      return TestUtils.isBrowserRuntime(config['runtime']);
-    });
-    if (runningBrowserTests) startHttpServer('127.0.0.1', 9876);
+  void allTestsFinished() {
+    for (var conf in configurations) {
+      if (conf.containsKey('_servers_')) {
+        conf['_servers_'].stopServers();
+      }
+    }
+    DebugLogger.close();
   }
 
   var maxBrowserProcesses = maxProcesses;
@@ -114,7 +127,7 @@
       startTime,
       printTiming,
       testSuites,
-      () => TestingServerRunner.terminateHttpServers(),
+      allTestsFinished,
       verbose,
       listTests);
 }
diff --git a/tools/test.dart b/tools/test.dart
index 398230d..00eb7f1 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -66,6 +66,7 @@
     new Path('utils/tests/css'),
     new Path('utils/tests/peg'),
     new Path('utils/tests/pub'),
+    new Path('sdk/lib/_internal/dartdoc'),
 ];
 
 main() {
@@ -83,6 +84,7 @@
   var verbose = firstConf['verbose'];
   var printTiming = firstConf['time'];
   var listTests = firstConf['list'];
+  var useContentSecurityPolicy = firstConf['csp'];
 
   if (!firstConf['append_logs'])  {
     var file = new File(TestUtils.flakyFileName());
@@ -109,35 +111,31 @@
     print(output_words.join(' '));
   }
 
-  // Start global http servers that serve the entire dart repo.
-  // The http server is available on window.location.port, and a second server
-  // for cross-domain tests can be found by calling getCrossOriginPortNumber().
-  if (!listTests) {
-    // Only start the server if we are running browser tests.
-    var runningBrowserTests = configurations.any((config) {
-      return TestUtils.isBrowserRuntime(config['runtime']);
-    });
-    if (runningBrowserTests) {
-      TestingServerRunner.startHttpServer('127.0.0.1');
-      // We start two servers so that we can test cross-domain tests.
-      TestingServerRunner.startHttpServer('127.0.0.1',
-          allowedPort: TestingServerRunner.serverList[0].port);
-    }
-  }
+  var runningBrowserTests = configurations.any((config) {
+    return TestUtils.isBrowserRuntime(config['runtime']);
+  });
 
   var testSuites = new List<TestSuite>();
-  // FIXME(kustermann,ricow): This is broken and should be fixed ASAP.
-  // Issue: 8366
-  TestingServerRunner.setBuildDir(firstConf);
-  TestingServerRunner.setPackageRootDir(firstConf);
   var maxBrowserProcesses = maxProcesses;
   for (var conf in configurations) {
+    if (!listTests && runningBrowserTests) {
+      // Start global http servers that serve the entire dart repo.
+      // The http server is available on window.location.port, and a second
+      // server for cross-domain tests can be found by calling
+      // getCrossOriginPortNumber().
+      var servers = new TestingServers(new Path(TestUtils.buildDir(conf)),
+                                       useContentSecurityPolicy);
+      servers.startServers('127.0.0.1');
+      conf['_servers_'] = servers;
+    }
+
     // There should not be more than one InternetExplorerDriver instance
     // running at a time. For details, see
     // http://code.google.com/p/selenium/wiki/InternetExplorerDriver.
     if (conf['runtime'].startsWith('ie')) {
       maxBrowserProcesses = 1;
     }
+
     for (String key in selectors.keys) {
       if (key == 'co19') {
         testSuites.add(new Co19TestSuite(conf));
@@ -155,14 +153,17 @@
       final name = testSuiteDir.filename;
       if (selectors.containsKey(name)) {
         testSuites.add(
-            new StandardTestSuite.forDirectory(conf, testSuiteDir,
-            serverList: TestingServerRunner.serverList));
+            new StandardTestSuite.forDirectory(conf, testSuiteDir));
       }
     }
   }
 
   void allTestsFinished() {
-    TestingServerRunner.terminateHttpServers();
+    for (var conf in configurations) {
+      if (conf.containsKey('_servers_')) {
+        conf['_servers_'].stopServers();
+      }
+    }
     DebugLogger.close();
   }
 
diff --git a/tools/testing/dart/http_server.dart b/tools/testing/dart/http_server.dart
index 6ab495b..d065e0b 100644
--- a/tools/testing/dart/http_server.dart
+++ b/tools/testing/dart/http_server.dart
@@ -18,7 +18,7 @@
 
 /// Interface of the HTTP server:
 ///
-/// /echo: This will stream the data received in the request stream back 
+/// /echo: This will stream the data received in the request stream back
 ///        to the client.
 /// /root_dart/X: This will serve the corresponding file from the dart
 ///               directory (i.e. '$DartDirectory/X').
@@ -37,7 +37,6 @@
 // http://host:port/root_packages/X -> $BuildDir/packages/X
 // Issue: 8368
 
-
 main() {
   /** Convenience method for local testing. */
   var parser = new ArgParser();
@@ -47,15 +46,13 @@
   parser.addOption('crossOriginPort', abbr: 'c',
       help: 'A different port that accepts request from the main server port.',
       defaultsTo: '0');
-  parser.addOption('mode', abbr: 'm', help: 'Testing mode.',
-      defaultsTo: 'release');
-  parser.addOption('arch', abbr: 'a', help: 'Testing architecture.',
-      defaultsTo: 'ia32');
   parser.addFlag('help', abbr: 'h', negatable: false,
       help: 'Print this usage information.');
-  parser.addOption('package-root', help: 'The package root to use.');
+  parser.addOption('build-directory', help: 'The build directory to use.');
   parser.addOption('network', help: 'The network interface to use.',
       defaultsTo: '127.0.0.1');
+  parser.addFlag('csp', help: 'Use Content Security Policy restrictions.',
+      defaultsTo: false);
   var args = parser.parse(new Options().arguments);
   if (args['help']) {
     print(parser.getUsage());
@@ -68,81 +65,99 @@
         .join(new Path('../../test.dart'))
         .canonicalize()
         .toNativePath();
-    // Note: args['package-root'] is always the build directory. We have the
-    // implicit assumption that it contains the 'packages' subdirectory.
-    // TODO: We should probably rename 'package-root' to 'build-directory'.
-    TestingServerRunner._packageRootDir = new Path(args['package-root']);
-    TestingServerRunner._buildDirectory = new Path(args['package-root']);
-    var network = args['network'];
-    TestingServerRunner.startHttpServer(network,
-        port: int.parse(args['port']));
-    print('Server listening on port '
-          '${TestingServerRunner.serverList[0].port}.');
-    TestingServerRunner.startHttpServer(network,
-        allowedPort: TestingServerRunner.serverList[0].port, port:
-        int.parse(args['crossOriginPort']));
-    print(
-        'Server listening on port ${TestingServerRunner.serverList[1].port}.');
+    var servers = new TestingServers(new Path(args['build-directory']),
+                                     args['csp']);
+    var port = int.parse(args['port']);
+    var crossOriginPort = int.parse(args['crossOriginPort']);
+    servers.startServers(args['network'],
+                         port: port,
+                         crossOriginPort: crossOriginPort);
+    DebugLogger.info('Server listening on port ${servers.port}');
+    DebugLogger.info('Server listening on port ${servers.crossOriginPort}');
   }
 }
+
 /**
  * Runs a set of servers that are initialized specifically for the needs of our
  * test framework, such as dealing with package-root.
  */
-class TestingServerRunner {
-  static List serverList = [];
-  static Path _packageRootDir = null;
-  static Path _buildDirectory = null;
+class TestingServers {
+  List _serverList = [];
+  Path _buildDirectory = null;
+  final bool useContentSecurityPolicy;
 
-  // Added as a getter so that the function will be called again each time the
-  // default request handler closure is executed.
-  static Path get packageRootDir => _packageRootDir;
-  static Path get buildDirectory => _buildDirectory;
-
-  static setPackageRootDir(Map configuration) {
-    _packageRootDir = TestUtils.absolutePath(
-        new Path(TestUtils.buildDir(configuration)));
+  TestingServers(Path buildDirectory, this.useContentSecurityPolicy) {
+    _buildDirectory = TestUtils.absolutePath(buildDirectory);
   }
 
-  static setBuildDir(Map configuration) {
-    _buildDirectory = TestUtils.absolutePath(
-        new Path(TestUtils.buildDir(configuration)));
+  int get port => _serverList[0].port;
+  int get crossOriginPort => _serverList[1].port;
+
+  /**
+   * [startServers] will start two Http servers.
+   * The first server listens on [port] and sets
+   *   "Access-Control-Allow-Origin: *"
+   * The second server listens on [crossOriginPort] and sets
+   *   "Access-Control-Allow-Origin: client:port1
+   *   "Access-Control-Allow-Credentials: true"
+   */
+  void startServers(String host, {int port: 0, int crossOriginPort: 0}) {
+    _startHttpServer(host, port: port);
+    _startHttpServer(host,
+                     port: crossOriginPort,
+                     allowedPort:_serverList[0].port);
   }
 
-  static startHttpServer(String host, {int allowedPort:-1, int port: 0}) {
+  String httpServerCommandline() {
+    var dart = TestUtils.dartTestExecutable.toNativePath();
+    var dartDir = TestUtils.dartDir();
+    var script = dartDir.join(new Path("tools/testing/dart/http_server.dart"));
+    var buildDirectory = _buildDirectory.toNativePath();
+    var csp = useContentSecurityPolicy ? '--csp ' : '';
+
+    return '$dart $script -p $port -c $crossOriginPort $csp'
+           '--build-directory=$buildDirectory';
+  }
+
+  void stopServers() {
+    for (var server in _serverList) {
+      server.close();
+    }
+  }
+
+  void _startHttpServer(String host, {int port: 0, int allowedPort: -1}) {
     var httpServer = new HttpServer();
     httpServer.onError = (e) {
       DebugLogger.error('HttpServer: an error occured: $e');
     };
     httpServer.defaultRequestHandler = (request, response) {
-      handleFileOrDirectoryRequest(request, response, allowedPort);
+      _handleFileOrDirectoryRequest(request, response, allowedPort);
     };
     httpServer.addRequestHandler(
-        (req) => req.path == "/echo", handleEchoRequest);
+        (req) => req.path == "/echo", _handleEchoRequest);
 
     httpServer.listen(host, port);
-    serverList.add(httpServer);
+    _serverList.add(httpServer);
   }
 
-
-  static void handleFileOrDirectoryRequest(HttpRequest request,
-                                           HttpResponse response,
-                                           int allowedPort) {
-    var path = getFilePathFromRequestPath(request.path);
+  void _handleFileOrDirectoryRequest(HttpRequest request,
+                                     HttpResponse response,
+                                     int allowedPort) {
+    var path = _getFilePathFromRequestPath(request.path);
     if (path != null) {
       var file = new File.fromPath(path);
       file.exists().then((exists) {
         if (exists) {
-          sendFileContent(request, response, allowedPort, path, file);
+          _sendFileContent(request, response, allowedPort, path, file);
         } else {
           var directory = new Directory.fromPath(path);
           directory.exists().then((exists) {
             if (exists) {
-              listDirectory(directory).then((entries) {
-                sendDirectoryListing(entries, request, response);
+              _listDirectory(directory).then((entries) {
+                _sendDirectoryListing(entries, request, response);
               });
             } else {
-              sendNotFound(request, response);
+              _sendNotFound(request, response);
             }
           });
         }
@@ -152,19 +167,19 @@
         var entries = [new _Entry('root_dart', 'root_dart/'),
                        new _Entry('root_build', 'root_build/'),
                        new _Entry('echo', 'echo')];
-        sendDirectoryListing(entries, request, response);
+        _sendDirectoryListing(entries, request, response);
       } else {
-        sendNotFound(request, response);
+        _sendNotFound(request, response);
       }
     }
   }
 
-  static void handleEchoRequest(HttpRequest request, HttpResponse response) {
+  void _handleEchoRequest(HttpRequest request, HttpResponse response) {
     response.headers.set("Access-Control-Allow-Origin", "*");
     request.inputStream.pipe(response.outputStream);
   }
 
-  static Path getFilePathFromRequestPath(String urlRequestPath) {
+  Path _getFilePathFromRequestPath(String urlRequestPath) {
     // Go to the top of the file to see an explanation of the URL path scheme.
     var requestPath = new Path(urlRequestPath.substring(1)).canonicalize();
     var pathSegments = requestPath.segments();
@@ -185,7 +200,7 @@
       if (packagesIndex != -1) {
         var start = packagesIndex + 1;
         var length = pathSegments.length - start;
-        basePath = _packageRootDir.append(packagesDirName);
+        basePath = _buildDirectory.append(packagesDirName);
         relativePath = new Path(
             pathSegments.getRange(start, length).join('/'));
       }
@@ -196,7 +211,7 @@
     return null;
   }
 
-  static Future<List<_Entry>> listDirectory(Directory directory) {
+  Future<List<_Entry>> _listDirectory(Directory directory) {
     var completer = new Completer();
     var entries = [];
 
@@ -215,16 +230,9 @@
     return completer.future;
   }
 
-  /**
-   * Sends a simple listing of all the files and sub-directories within
-   * directory.
-   *
-   * This is intended to make it easier to browse tests when manually running
-   * tests against this test server.
-   */
-  static void sendDirectoryListing(entries,
-                                   HttpRequest request,
-                                   HttpResponse response) {
+  void _sendDirectoryListing(List<_Entry> entries,
+                             HttpRequest request,
+                             HttpResponse response) {
     response.headers.set('Content-Type', 'text/html');
     var header = '''<!DOCTYPE html>
     <html>
@@ -254,11 +262,11 @@
     response.outputStream.close();
   }
 
-  static void sendFileContent(HttpRequest request,
-                              HttpResponse response,
-                              int allowedPort,
-                              Path path,
-                              File file) {
+  void _sendFileContent(HttpRequest request,
+                        HttpResponse response,
+                        int allowedPort,
+                        Path path,
+                        File file) {
     if (allowedPort != -1) {
       var origin = new Uri(request.headers.value('Origin'));
       // Allow loading from http://*:$allowedPort in browsers.
@@ -271,6 +279,16 @@
       // requests *with credentials* will fail because you can't use "*").
       response.headers.set("Access-Control-Allow-Origin", "*");
     }
+    if (useContentSecurityPolicy) {
+      // Chrome respects the standardized Content-Security-Policy header,
+      // whereas Firefox and IE10 use X-Content-Security-Policy. Safari
+      // still uses the WebKit- prefixed version.
+      for (var header in ["Content-Security-Policy",
+                          "X-Content-Security-Policy",
+                          "X-WebKit-CSP"]) {
+        response.headers.set(header, "script-src 'self'; object-src 'self'");
+      }
+    }
     if (path.filename.endsWith('.html')) {
       response.headers.set('Content-Type', 'text/html');
     } else if (path.filename.endsWith('.js')) {
@@ -281,7 +299,7 @@
     file.openInputStream().pipe(response.outputStream);
   }
 
-  static void sendNotFound(HttpRequest request, HttpResponse response) {
+  void _sendNotFound(HttpRequest request, HttpResponse response) {
     // NOTE: Since some tests deliberately try to access non-existent files.
     // We might want to remove this warning (otherwise it will show
     // up in the debug.log every time).
@@ -299,10 +317,6 @@
       }
     }
   }
-
-  static terminateHttpServers() {
-    for (var server in serverList) server.close();
-  }
 }
 
 // Helper class for displaying directory listings.
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 44b7f2e..d6ca633 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -138,6 +138,13 @@
               false,
               'bool'),
           new _TestOptionSpecification(
+              'csp',
+              'Run tests under Content Security Policy restrictions',
+              ['--csp'],
+              [],
+              false,
+              'bool'),
+          new _TestOptionSpecification(
               'timeout',
               'Timeout in seconds',
               ['-t', '--timeout'],
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index 3de6e2f..b6d5d29 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -202,20 +202,15 @@
     }
     if (test is BrowserTestCase) {
       // Additional command for rerunning the steps locally after the fact.
-      output.add('To retest, run: '
-          '${TestUtils.dartTestExecutable.toNativePath()} '
-          '${TestUtils.dartDir().toNativePath()}/tools/testing/dart/'
-          'http_server.dart -m ${test.configuration["mode"]} '
-          '-a ${test.configuration["arch"]} '
-          '-p ${http_server.TestingServerRunner.serverList[0].port} '
-          '-c ${http_server.TestingServerRunner.serverList[1].port} '
-          '--package-root=${http_server.TestingServerRunner.packageRootDir}');
+      var command =
+        test.configuration["_servers_"].httpServerCommandline();
+      output.add('To retest, run:  $command');
     }
     for (Command c in test.commands) {
       output.add('');
       String message = (c == test.commands.last
           ? "Command line" : "Compilation command");
-      output.add('$message: ${c.commandLine}');
+      output.add('$message: $c');
     }
     return output;
   }
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 6ebd60c..262440f 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -107,7 +107,9 @@
       // TODO(efortuna): Remove this when fixed (Issue 1306).
       executable = executable.replaceAll('/', '\\');
     }
-    commandLine = "$executable ${arguments.join(' ')}";
+    var quotedArguments = [];
+    arguments.forEach((argument) => quotedArguments.add('"$argument"'));
+    commandLine = "$executable ${quotedArguments.join(' ')}";
   }
 
   String toString() => commandLine;
@@ -303,10 +305,6 @@
         newArguments.addAll(c.arguments);
         final newCommand = new Command(newExecutablePath, newArguments);
         newCommands.add(newCommand);
-        // If there are extra spaces inside the prefix or suffix, this fails.
-        String expected =
-            '$prefix ${c.executable} $suffix ${c.arguments.join(' ')}';
-        Expect.stringEquals(expected.trim(), newCommand.commandLine);
       }
       commands = newCommands;
     }
@@ -1600,18 +1598,13 @@
         int i = 1;
         if (test is BrowserTestCase) {
           // Additional command for rerunning the steps locally after the fact.
-          print('$i. ${TestUtils.dartTestExecutable.toNativePath()} '
-                '${TestUtils.dartDir().toNativePath()}/tools/testing/dart/'
-                'http_server.dart -m ${test.configuration["mode"]} '
-                '-a ${test.configuration["arch"]} '
-                '-p ${http_server.TestingServerRunner.serverList[0].port} '
-                '-c ${http_server.TestingServerRunner.serverList[1].port} '
-                '--package-root='
-                '${http_server.TestingServerRunner.packageRootDir}');
+          var command =
+            test.configuration["_servers_"].httpServerCommandline();
+          print('$i. $command');
           i++;
         }
         for (Command command in test.commands) {
-          print('$i. ${command.commandLine}');
+          print('$i. $command');
           i++;
         }
       }
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index f6ff12c..12e8929 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -410,11 +410,6 @@
   final Path dartDir;
   Predicate<String> isTestFilePredicate;
   final bool listRecursively;
-  /**
-   * The set of servers that have been started to run these tests (Could be
-   * none).
-   */
-  List serverList;
 
   static final RegExp multiTestRegExp = new RegExp(r"/// [0-9][0-9]:(.*)");
 
@@ -423,8 +418,7 @@
                     Path suiteDirectory,
                     this.statusFilePaths,
                     {this.isTestFilePredicate,
-                    bool recursive: false,
-                    this.serverList: const []})
+                    bool recursive: false})
   : super(configuration, suiteName),
     dartDir = TestUtils.dartDir(),
     listRecursively = recursive,
@@ -461,14 +455,14 @@
    * been started up by the test harness, to be used by browser tests.
    */
   factory StandardTestSuite.forDirectory(
-      Map configuration, Path directory, {List serverList : const []}) {
+      Map configuration, Path directory) {
     final name = directory.filename;
 
     return new StandardTestSuite(configuration,
         name, directory,
         ['$directory/$name.status', '$directory/${name}_dart2js.status'],
         isTestFilePredicate: (filename) => filename.endsWith('_test.dart'),
-        recursive: true, serverList: serverList);
+        recursive: true);
   }
 
   Collection<Uri> get dart2JsBootstrapDependencies {
@@ -843,13 +837,13 @@
                             subtestNames,
                             subtestIndex) {
     // Note: If we run test.py with the "--list" option, no http servers
-    // will be started. Therefore serverList is an empty list in this
-    // case. So we use PORT/CROSS_ORIGIN_PORT instead of real ports.
+    // will be started. So we use PORT/CROSS_ORIGIN_PORT instead of real ports.
     var serverPort = "PORT";
     var crossOriginPort = "CROSS_ORIGIN_PORT";
     if (!configuration['list']) {
-      serverPort = serverList[0].port.toString();
-      crossOriginPort = serverList[1].port.toString();
+      Expect.isTrue(configuration.containsKey('_servers_'));
+      serverPort = configuration['_servers_'].port;
+      crossOriginPort = configuration['_servers_'].crossOriginPort;
     }
 
     var url= 'http://127.0.0.1:$serverPort$pathComponent'
@@ -1024,7 +1018,7 @@
               dartDir.append('tools/testing/run_selenium.py').toNativePath(),
               '--browser=$runtime',
               '--timeout=${configuration["timeout"] - 2}',
-              '--out="$fullHtmlPath"'];
+              '--out=$fullHtmlPath'];
           if (runtime == 'dartium') {
             args.add('--executable=$dartiumFilename');
           }
@@ -1102,7 +1096,6 @@
         if (packageRoot != null) {
           args.add(packageRoot);
         }
-        if (compiler == 'dart2dart') args.add('--out=$outputFile');
         args.add('--out=$outputFile');
         args.add(inputFile);
         break;
@@ -1151,8 +1144,9 @@
     // '$compile-$runtime' directory name.
     var checked = configuration['checked'] ? '-checked' : '';
     var minified = configuration['minified'] ? '-minified' : '';
+    var csp = configuration['csp'] ? '-csp' : '';
     var dirName = "${configuration['compiler']}-${configuration['runtime']}"
-                  "$checked$minified";
+                  "$checked$minified$csp";
     Path generatedTestPath = new Path(buildDir)
         .append('generated_tests')
         .append(dirName)
@@ -1665,7 +1659,7 @@
          '$buildDir/analyzer/dart_analyzer_tests.jar',
          // Third party libraries.
          '$dartDir/third_party/args4j/2.0.12/args4j-2.0.12.jar',
-         '$dartDir/third_party/guava/r09/guava-r09.jar',
+         '$dartDir/third_party/guava/r13/guava-13.0.1.jar',
          '$dartDir/third_party/rhino/1_7R3/js.jar',
          '$dartDir/third_party/hamcrest/v1_3/hamcrest-core-1.3.0RC2.jar',
          '$dartDir/third_party/hamcrest/v1_3/hamcrest-generator-1.3.0RC2.jar',
@@ -1820,6 +1814,9 @@
         configuration["minified"]) {
       args.add("--minify");
     }
+    if (compiler == "dart2js" && configuration["csp"]) {
+      args.add("--disallow-unsafe-eval");
+    }
     return args;
   }
 
diff --git a/utils/apidoc/apidoc.dart b/utils/apidoc/apidoc.dart
index fcaf106..802471c 100644
--- a/utils/apidoc/apidoc.dart
+++ b/utils/apidoc/apidoc.dart
@@ -116,6 +116,11 @@
           var path = new Path(entity.path);
           var libName = path.filename;
 
+          // Ignore hidden directories (like .svn) as well as pkg.xcodeproj.
+          if (libName.startsWith('.') || libName.endsWith('.xcodeproj')) {
+            return;
+          }
+
           // TODO(rnystrom): Get rid of oldStylePath support when all
           // packages are using new layout. See #5106.
           var oldStylePath = path.append('${libName}.dart');
diff --git a/utils/apidoc/apidoc.gyp b/utils/apidoc/apidoc.gyp
index b5c0689..dd5d3a7 100644
--- a/utils/apidoc/apidoc.gyp
+++ b/utils/apidoc/apidoc.gyp
@@ -38,6 +38,9 @@
             '../../sdk/bin/dart2js',
             '../../sdk/bin/dart2js.bat',
           ],
+          'inputs': [
+            '<!@(["python", "../../tools/list_files.py", "\\.(css|png|dart)$", "."])',
+          ],
           'outputs': [
             '<(PRODUCT_DIR)/api_docs/index.html',
             '<(PRODUCT_DIR)/api_docs/client-static.js',
@@ -52,7 +55,7 @@
             '--exclude-lib=dartdoc',
             '--exclude-lib=http',
             '--exclude-lib=oauth2',
-            '--exclude-lib=path',
+            '--exclude-lib=pathos',
             '--exclude-lib=webdriver',
             '--exclude-lib=yaml',
             '--include-lib=matcher',
diff --git a/utils/apidoc/mdn/extract.dart b/utils/apidoc/mdn/extract.dart
index d9622b5..da3a7f3 100644
--- a/utils/apidoc/mdn/extract.dart
+++ b/utils/apidoc/mdn/extract.dart
@@ -748,7 +748,7 @@
 
       // Figure out which column in the table contains member names by
       // tracking how many member names each column contains.
-      final numMatches = new List<int>.fixedLength(i);
+      final numMatches = new List<int>(i);
       for (int j = 0; j < i; j++) {
         numMatches[j] = 0;
       }
diff --git a/utils/css/parser.dart b/utils/css/parser.dart
index 4e0c187..d799e43 100644
--- a/utils/css/parser.dart
+++ b/utils/css/parser.dart
@@ -999,7 +999,7 @@
     var result = 0;
 
     for (int i = 0; i < hex.length; i++) {
-      var digit = _hexDigit(hex.charCodeAt(i));
+      var digit = _hexDigit(hex.codeUnitAt(i));
       if (digit < 0) {
         throw new HexNumberException();
       }
diff --git a/utils/css/tokenizer.dart b/utils/css/tokenizer.dart
index fccb3c04..63573df 100644
--- a/utils/css/tokenizer.dart
+++ b/utils/css/tokenizer.dart
@@ -191,8 +191,8 @@
   // Need to override so CSS version of isIdentifierPart is used.
   Token finishIdentifier(int ch) {
     while (_index < _text.length) {
-//      if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
-      if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index))) {
+//      if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) {
+      if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index))) {
 //        _index--;
         break;
       } else {
@@ -211,7 +211,7 @@
   }
 
   Token finishImportant() {
-    
+
   }
 
   Token finishNumber() {
@@ -233,7 +233,7 @@
 
   bool maybeEatDigit() {
     if (_index < _text.length
-        && TokenizerHelpers.isDigit(_text.charCodeAt(_index))) {
+        && TokenizerHelpers.isDigit(_text.codeUnitAt(_index))) {
       _index += 1;
       return true;
     }
@@ -242,7 +242,7 @@
 
   void eatHexDigits() {
     while (_index < _text.length) {
-     if (TokenizerHelpers.isHexDigit(_text.charCodeAt(_index))) {
+     if (TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) {
        _index += 1;
      } else {
        return;
@@ -252,7 +252,7 @@
 
   bool maybeEatHexDigit() {
     if (_index < _text.length
-        && TokenizerHelpers.isHexDigit(_text.charCodeAt(_index))) {
+        && TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) {
       _index += 1;
       return true;
     }
@@ -293,7 +293,7 @@
 /** Static helper methods. */
 /** Static helper methods. */
 class TokenizerHelpers {
-  
+
   static bool isIdentifierStart(int c) {
     return ((c >= 97/*a*/ && c <= 122/*z*/) || (c >= 65/*A*/ && c <= 90/*Z*/) ||
         c == 95/*_*/ || c == 45 /*-*/);
diff --git a/utils/css/tokenizer_base.dart b/utils/css/tokenizer_base.dart
index af666b4..f98f245 100644
--- a/utils/css/tokenizer_base.dart
+++ b/utils/css/tokenizer_base.dart
@@ -52,7 +52,7 @@
 
   int _nextChar() {
     if (_index < _text.length) {
-      return _text.charCodeAt(_index++);
+      return _text.codeUnitAt(_index++);
     } else {
       return 0;
     }
@@ -60,7 +60,7 @@
 
   int _peekChar() {
     if (_index < _text.length) {
-      return _text.charCodeAt(_index);
+      return _text.codeUnitAt(_index);
     } else {
       return 0;
     }
@@ -68,7 +68,7 @@
 
   bool _maybeEatChar(int ch) {
     if (_index < _text.length) {
-      if (_text.charCodeAt(_index) == ch) {
+      if (_text.codeUnitAt(_index) == ch) {
         _index++;
         return true;
       } else {
@@ -99,7 +99,7 @@
   Token finishWhitespace() {
     _index--;
     while (_index < _text.length) {
-      final ch = _text.charCodeAt(_index++);
+      final ch = _text.codeUnitAt(_index++);
       if (ch == 32/*' '*/ || ch == 9/*'\t'*/ || ch == 13/*'\r'*/) {
         // do nothing
       } else if (ch == 10/*'\n'*/) {
@@ -158,7 +158,7 @@
 
   void eatDigits() {
     while (_index < _text.length) {
-      if (TokenizerHelpers.isDigit(_text.charCodeAt(_index))) {
+      if (TokenizerHelpers.isDigit(_text.codeUnitAt(_index))) {
         _index++;
       } else {
         return;
@@ -189,7 +189,7 @@
     }
     var result = 0;
     while (_index < maxIndex) {
-      final digit = _hexDigit(_text.charCodeAt(_index));
+      final digit = _hexDigit(_text.codeUnitAt(_index));
       if (digit == -1) {
         if (hexLength == null) {
           return result;
@@ -197,7 +197,7 @@
           return -1;
         }
       }
-      _hexDigit(_text.charCodeAt(_index));
+      _hexDigit(_text.codeUnitAt(_index));
       // Multiply by 16 rather than shift by 4 since that will result in a
       // correct value for numbers that exceed the 32 bit precision of JS
       // 'integers'.
@@ -438,7 +438,7 @@
 
   Token finishIdentifier(int ch) {
     while (_index < _text.length) {
-      if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
+      if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) {
         _index--;
         break;
       }
diff --git a/utils/css/tokenkind.dart b/utils/css/tokenkind.dart
index 32e994e..6112e82 100644
--- a/utils/css/tokenkind.dart
+++ b/utils/css/tokenkind.dart
@@ -93,7 +93,7 @@
   static const int COMBINATOR_TILDE = 517;      // ~ combinator
 
   static const int UNARY_OP_NONE = 518;         // No unary operator present.
-  
+
   // Attribute match types:
   static const int INCLUDES = 530;              // '~='
   static const int DASH_MATCH = 531;            // '|='
@@ -383,8 +383,8 @@
         int idx = offset;
         bool match = true;
         for (int identIdx = 0; identIdx < ident.length; identIdx++) {
-          int identChar = ident.charCodeAt(identIdx);
-          int char = text.charCodeAt(idx++);
+          int identChar = ident.codeUnitAt(identIdx);
+          int char = text.codeUnitAt(idx++);
           // Compare lowercase to lowercase then check if char is uppercase.
           match = match && (char == identChar ||
               ((char >= ASCII_UPPER_A && char <= ASCII_UPPER_Z) &&
@@ -448,8 +448,8 @@
         int idx = 0;
         bool match = true;
         for (int identIdx = 0; identIdx < ident.length; identIdx++) {
-          int identChar = ident.charCodeAt(identIdx);
-          int char = text.charCodeAt(idx++);
+          int identChar = ident.codeUnitAt(identIdx);
+          int char = text.codeUnitAt(idx++);
           // Compare lowercase to lowercase then check if char is uppercase.
           match = match && (char == identChar ||
               ((char >= ASCII_UPPER_A && char <= ASCII_UPPER_Z) &&
@@ -545,39 +545,39 @@
     // All tokens must be in TokenKind order.
     tokens.add(-1);                 // TokenKind.UNUSED
     tokens.add(0);                  // TokenKind.END_OF_FILE match base
-    tokens.add(TokenKind.kindToString(TokenKind.LPAREN).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.RPAREN).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.LBRACK).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.RBRACK).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.LBRACE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.RBRACE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.DOT).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.SEMICOLON).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.AT).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.HASH).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.PLUS).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.GREATER).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.TILDE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.ASTERISK).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.NAMESPACE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.COLON).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.PRIVATE_NAME).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.COMMA).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.SPACE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.TAB).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.NEWLINE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.RETURN).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.PERCENT).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.SINGLE_QUOTE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.DOUBLE_QUOTE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.SLASH).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.EQUALS).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.OR).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.CARET).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.DOLLAR).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.LESS).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.BANG).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.MINUS).charCodeAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.LPAREN).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.RPAREN).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.LBRACK).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.RBRACK).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.LBRACE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.RBRACE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.DOT).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.SEMICOLON).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.AT).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.HASH).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.PLUS).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.GREATER).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.TILDE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.ASTERISK).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.NAMESPACE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.COLON).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.PRIVATE_NAME).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.COMMA).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.SPACE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.TAB).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.NEWLINE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.RETURN).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.PERCENT).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.SINGLE_QUOTE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.DOUBLE_QUOTE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.SLASH).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.EQUALS).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.OR).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.CARET).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.DOLLAR).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.LESS).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.BANG).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.MINUS).codeUnitAt(0));
 
     assert(tokens.length == TokenKind.END_TOKENS);
   }
diff --git a/utils/lib/file_system_vm.dart b/utils/lib/file_system_vm.dart
index cc0c05c..12fb712 100644
--- a/utils/lib/file_system_vm.dart
+++ b/utils/lib/file_system_vm.dart
@@ -20,7 +20,7 @@
   String readAll(String filename) {
     var file = (new File(filename)).openSync();
     var length = file.lengthSync();
-    var buffer = new List<int>.fixedLength(length);
+    var buffer = new List<int>(length);
     var bytes = file.readListSync(buffer, 0, length);
     file.closeSync();
     return new String.fromCharCodes(new Utf8Decoder(buffer).decodeRest());
diff --git a/utils/peg/pegparser.dart b/utils/peg/pegparser.dart
index 9072e2d..bd329c7 100644
--- a/utils/peg/pegparser.dart
+++ b/utils/peg/pegparser.dart
@@ -62,14 +62,14 @@
 
   // Find the range of character codes and construct an array of flags for codes
   // within the range.
-  List<int> codes = characters.charCodes;
+  List<int> codes = characters.codeUnits;
   codes.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
   int lo = codes[0];
   int hi = codes[codes.length - 1];
   if (lo == hi)
     return CHARCODE(lo);
   int len = hi - lo + 1;
-  var flags = new List<bool>.fixedLength(len);
+  var flags = new List<bool>(len);
   for (int i = 0; i < len; ++i)
     flags[i] = false;
   for (int code in codes)
@@ -452,7 +452,7 @@
   _match(_ParserState state, int pos) {
     if (pos == state._end)
       return null;
-    int code = state._text.charCodeAt(pos);
+    int code = state._text.codeUnitAt(pos);
     if (_predicate(code))
       return [pos + 1, null];
     return null;
@@ -511,7 +511,7 @@
     if (pos + _len > state._end)
       return null;
     for (int i = 0; i < _len; i++) {
-      if (state._text.charCodeAt(pos + i) != _string.charCodeAt(i))
+      if (state._text.codeUnitAt(pos + i) != _string.codeUnitAt(i))
         return null;
     }
     return [pos + _len, null];
diff --git a/utils/pub/command_lish.dart b/utils/pub/command_lish.dart
index d2a033b..356ed52 100644
--- a/utils/pub/command_lish.dart
+++ b/utils/pub/command_lish.dart
@@ -11,7 +11,7 @@
 
 import '../../pkg/args/lib/args.dart';
 import '../../pkg/http/lib/http.dart' as http;
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 import 'directory_tree.dart';
 import 'exit_codes.dart' as exit_codes;
 import 'git.dart' as git;
diff --git a/utils/pub/command_uploader.dart b/utils/pub/command_uploader.dart
index a8c2100..6541653 100644
--- a/utils/pub/command_uploader.dart
+++ b/utils/pub/command_uploader.dart
@@ -9,7 +9,7 @@
 import 'dart:uri';
 
 import '../../pkg/args/lib/args.dart';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 import 'entrypoint.dart';
 import 'exit_codes.dart' as exit_codes;
 import 'http.dart';
diff --git a/utils/pub/directory_tree.dart b/utils/pub/directory_tree.dart
index cffff62..3610e72 100644
--- a/utils/pub/directory_tree.dart
+++ b/utils/pub/directory_tree.dart
@@ -5,7 +5,7 @@
 /// A simple library for rendering a list of files as a directory tree.
 library directory_tree;
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 import 'log.dart' as log;
 
 /// Draws a directory tree for the given list of files. Given a list of files
diff --git a/utils/pub/entrypoint.dart b/utils/pub/entrypoint.dart
index ab65950..e1bed5f 100644
--- a/utils/pub/entrypoint.dart
+++ b/utils/pub/entrypoint.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'io.dart';
 import 'lock_file.dart';
@@ -193,8 +193,8 @@
       }
 
       if (errors.length > 0) {
-        log.error("Some packages are not compatible with your SDK version "
-                "${sdk.version}:\n"
+        log.error("Some packages that were installed are not compatible with "
+                "your SDK version ${sdk.version} and may not work:\n"
             "${errors.join('\n')}\n\n"
             "You may be able to resolve this by upgrading to the latest Dart "
                 "SDK\n"
diff --git a/utils/pub/git_source.dart b/utils/pub/git_source.dart
index 2b54c72..bbe7952 100644
--- a/utils/pub/git_source.dart
+++ b/utils/pub/git_source.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'git.dart' as git;
 import 'io.dart';
diff --git a/utils/pub/hosted_source.dart b/utils/pub/hosted_source.dart
index 44f7195..ef64d59 100644
--- a/utils/pub/hosted_source.dart
+++ b/utils/pub/hosted_source.dart
@@ -11,7 +11,7 @@
 
 // TODO(nweiz): Make this import better.
 import '../../pkg/http/lib/http.dart' as http;
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'http.dart';
 import 'io.dart';
@@ -95,7 +95,7 @@
     var parsed = _parseDescription(id.description);
     var url = parsed.last.replaceAll(new RegExp(r"^https?://"), "");
     var urlDir = replace(url, new RegExp(r'[<>:"\\/|?*%]'), (match) {
-      return '%${match[0].charCodeAt(0)}';
+      return '%${match[0].codeUnitAt(0)}';
     });
 
     return new Future.immediate(
diff --git a/utils/pub/io.dart b/utils/pub/io.dart
index 2a4be97..6e5ef86 100644
--- a/utils/pub/io.dart
+++ b/utils/pub/io.dart
@@ -11,7 +11,7 @@
 import 'dart:json';
 import 'dart:uri';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 import '../../pkg/http/lib/http.dart' show ByteStream;
 import 'error_group.dart';
 import 'exit_codes.dart' as exit_codes;
@@ -161,7 +161,7 @@
     lister.listen(
         (entity) {
           if (entity is File) {
-            var file = entity.name;
+            var file = entity.path;
             if (!includeHiddenFiles && path.basename(file).startsWith('.')) {
               return;
             }
@@ -188,7 +188,7 @@
           log.fine("Listed directory $dir:\n${contents.join('\n')}");
           completer.complete(contents);
         },
-        onError: (error) => completer.completeError(error, stackTrace));
+        onError: (error) => completer.completeError(error));
 
     return completer.future.then((contents) {
       return Future.wait(children).then((childContents) {
@@ -383,7 +383,7 @@
 /// should just be a fragment like, "Are you sure you want to proceed".
 Future<bool> confirm(String message) {
   log.fine('Showing confirm message: $message');
-  stdoutSink.add("$message (y/n)? ".charCodes);
+  stdoutSink.add("$message (y/n)? ".codeUnits);
   return streamFirst(stdinLines)
       .then((line) => new RegExp(r"^[yY]").hasMatch(line));
 }
@@ -591,21 +591,19 @@
 /// Note that timing out will not cancel the asynchronous operation behind
 /// [input].
 Future timeout(Future input, int milliseconds, String description) {
-  bool completed = false;
   var completer = new Completer();
-  var timer = new Timer(new Duration(milliseconds: milliseconds), (_) {
-    completed = true;
+  var timer = new Timer(new Duration(milliseconds: milliseconds), () {
     completer.completeError(new TimeoutException(
         'Timed out while $description.'));
   });
   input.then((value) {
-    if (completed) return;
+    if (completer.isCompleted) return;
     timer.cancel();
     completer.complete(value);
   }).catchError((e) {
-    if (completed) return;
+    if (completer.isCompleted) return;
     timer.cancel();
-    completer.completeError(e.error, e.stackTrace);
+    completer.completeError(e);
   });
   return completer.future;
 }
@@ -716,8 +714,8 @@
 /// Returns a [ByteStream] that will emit the contents of the archive.
 ByteStream createTarGz(List contents, {baseDir}) {
   var buffer = new StringBuffer();
-  buffer.add('Creating .tag.gz stream containing:\n');
-  contents.forEach((file) => buffer.add('$file\n'));
+  buffer.write('Creating .tag.gz stream containing:\n');
+  contents.forEach((file) => buffer.write('$file\n'));
   log.fine(buffer.toString());
 
   var controller = new StreamController<List<int>>();
diff --git a/utils/pub/log.dart b/utils/pub/log.dart
index 9a555ea..5f1c578 100644
--- a/utils/pub/log.dart
+++ b/utils/pub/log.dart
@@ -117,22 +117,22 @@
 void processResult(String executable, PubProcessResult result) {
   // Log it all as one message so that it shows up as a single unit in the logs.
   var buffer = new StringBuffer();
-  buffer.add("Finished $executable. Exit code ${result.exitCode}.");
+  buffer.write("Finished $executable. Exit code ${result.exitCode}.");
 
   dumpOutput(String name, List<String> output) {
     if (output.length == 0) {
-      buffer.add("Nothing output on $name.");
+      buffer.write("Nothing output on $name.");
     } else {
-      buffer.add("$name:");
+      buffer.write("$name:");
       var numLines = 0;
       for (var line in output) {
         if (++numLines > 1000) {
-          buffer.add('[${output.length - 1000}] more lines of output '
-                     'truncated...]');
+          buffer.write('[${output.length - 1000}] more lines of output '
+              'truncated...]');
           break;
         }
 
-        buffer.add(line);
+        buffer.write(line);
       }
     }
   }
@@ -153,11 +153,11 @@
 void dumpTranscript() {
   if (_transcript == null) return;
 
-  stderrSink.add('---- Log transcript ----\n'.charCodes);
+  stderrSink.add('---- Log transcript ----\n'.codeUnits);
   for (var entry in _transcript) {
     _logToStderrWithLabel(entry);
   }
-  stderrSink.add('---- End log transcript ----\n'.charCodes);
+  stderrSink.add('---- End log transcript ----\n'.codeUnits);
 }
 
 /// Sets the verbosity to "normal", which shows errors, warnings, and messages.
@@ -213,15 +213,15 @@
   for (var line in entry.lines) {
     if (showLabel) {
       if (firstLine) {
-        sink.add(entry.level.name.charCodes);
-        sink.add(': '.charCodes);
+        sink.add(entry.level.name.codeUnits);
+        sink.add(': '.codeUnits);
       } else {
-        sink.add('    | '.charCodes);
+        sink.add('    | '.codeUnits);
       }
     }
 
-    sink.add(line.charCodes);
-    sink.add('\n'.charCodes);
+    sink.add(line.codeUnits);
+    sink.add('\n'.codeUnits);
 
     firstLine = false;
   }
diff --git a/utils/pub/oauth2.dart b/utils/pub/oauth2.dart
index f2ec1b5..cc80d86 100644
--- a/utils/pub/oauth2.dart
+++ b/utils/pub/oauth2.dart
@@ -10,7 +10,7 @@
 
 // TODO(nweiz): Make this a "package:" URL, or something nicer than this.
 import '../../pkg/oauth2/lib/oauth2.dart';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'http.dart';
 import 'io.dart';
diff --git a/utils/pub/package.dart b/utils/pub/package.dart
index 8731655..8e96cbd 100644
--- a/utils/pub/package.dart
+++ b/utils/pub/package.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'io.dart';
 import 'pubspec.dart';
diff --git a/utils/pub/path_source.dart b/utils/pub/path_source.dart
index 69471f8..bfa09e7 100644
--- a/utils/pub/path_source.dart
+++ b/utils/pub/path_source.dart
@@ -7,7 +7,9 @@
 import 'dart:async';
 import 'dart:io';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
+
+import 'log.dart' as log;
 
 import 'io.dart';
 import 'package.dart';
@@ -30,6 +32,13 @@
     });
   }
 
+  bool descriptionsEqual(description1, description2) {
+    // Compare real paths after normalizing and resolving symlinks.
+    var path1 = new File(description1["path"]).fullPathSync();
+    var path2 = new File(description2["path"]).fullPathSync();
+    return path1 == path2;
+  }
+
   Future<bool> install(PackageId id, String destination) {
     return defer(() {
       try {
@@ -44,7 +53,7 @@
   }
 
   /// Parses a path dependency. This takes in a path string and returns a map.
-  /// The "path" key will be the original path but resolves relative to the
+  /// The "path" key will be the original path but resolved relative to the
   /// containing path. The "relative" key will be `true` if the original path
   /// was relative.
   ///
diff --git a/utils/pub/pub.dart b/utils/pub/pub.dart
index 00abe4c..f18d9c9 100644
--- a/utils/pub/pub.dart
+++ b/utils/pub/pub.dart
@@ -10,7 +10,7 @@
 import 'dart:math';
 
 import '../../pkg/args/lib/args.dart';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'command_help.dart';
 import 'command_install.dart';
@@ -227,7 +227,7 @@
     globalOptions = globalOptions_;
 
     try {
-     commandOptions = commandParser.parse(commandArgs);
+      commandOptions = commandParser.parse(commandArgs);
     } on FormatException catch (e) {
       log.error(e.message);
       log.error('Use "pub help" for more information.');
diff --git a/utils/pub/pubspec.dart b/utils/pub/pubspec.dart
index 55b775d..81678af 100644
--- a/utils/pub/pubspec.dart
+++ b/utils/pub/pubspec.dart
@@ -5,7 +5,7 @@
 library pubspec;
 
 import '../../pkg/yaml/lib/yaml.dart';
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'io.dart';
 import 'package.dart';
diff --git a/utils/pub/sdk.dart b/utils/pub/sdk.dart
index 1db2a04..59eea86 100644
--- a/utils/pub/sdk.dart
+++ b/utils/pub/sdk.dart
@@ -7,7 +7,7 @@
 
 import 'dart:io';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'io.dart';
 import 'log.dart' as log;
diff --git a/utils/pub/sdk_source.dart b/utils/pub/sdk_source.dart
index 1544152..1d6a881 100644
--- a/utils/pub/sdk_source.dart
+++ b/utils/pub/sdk_source.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'io.dart';
 import 'package.dart';
diff --git a/utils/pub/source.dart b/utils/pub/source.dart
index 0568d95..0e3af3e 100644
--- a/utils/pub/source.dart
+++ b/utils/pub/source.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'io.dart';
 import 'package.dart';
diff --git a/utils/pub/system_cache.dart b/utils/pub/system_cache.dart
index 8bd3178..7670b76 100644
--- a/utils/pub/system_cache.dart
+++ b/utils/pub/system_cache.dart
@@ -7,7 +7,7 @@
 import 'dart:io';
 import 'dart:async';
 
-import '../../pkg/path/lib/path.dart' as path;
+import '../../pkg/pathos/lib/path.dart' as path;
 
 import 'git_source.dart';
 import 'hosted_source.dart';
diff --git a/utils/pub/utils.dart b/utils/pub/utils.dart
index f7589da..098916e 100644
--- a/utils/pub/utils.dart
+++ b/utils/pub/utils.dart
@@ -72,10 +72,10 @@
 /// Pads [source] to [length] by adding spaces at the end.
 String padRight(String source, int length) {
   final result = new StringBuffer();
-  result.add(source);
+  result.write(source);
 
   while (result.length < length) {
-    result.add(' ');
+    result.write(' ');
   }
 
   return result.toString();
@@ -122,11 +122,11 @@
   var buffer = new StringBuffer();
   var start = 0;
   for (var match in matcher.allMatches(source)) {
-    buffer.add(source.substring(start, match.start));
+    buffer.write(source.substring(start, match.start));
     start = match.end;
-    buffer.add(fn(match));
+    buffer.write(fn(match));
   }
-  buffer.add(source.substring(start));
+  buffer.write(source.substring(start));
   return buffer.toString();
 }
 
@@ -141,7 +141,7 @@
 /// Returns the hex-encoded sha1 hash of [source].
 String sha1(String source) {
   var sha = new SHA1();
-  sha.add(source.charCodes);
+  sha.add(source.codeUnits);
   return CryptoUtils.bytesToHex(sha.close());
 }
 
@@ -158,8 +158,7 @@
 /// Returns a [Future] that completes in [milliseconds].
 Future sleep(int milliseconds) {
   var completer = new Completer();
-  new Timer(new Duration(milliseconds: milliseconds),
-      (_) => completer.complete());
+  new Timer(new Duration(milliseconds: milliseconds), completer.complete);
   return completer.future;
 }
 
@@ -237,38 +236,25 @@
 /// newline is ignored.
 Stream<String> streamToLines(Stream<String> stream) {
   var buffer = new StringBuffer();
-  return wrapStream(stream.transform(new StreamTransformer(
+  return stream.transform(new StreamTransformer(
       handleData: (chunk, sink) {
         var lines = chunk.split(_lineRegexp);
         var leftover = lines.removeLast();
         for (var line in lines) {
           if (!buffer.isEmpty) {
-            buffer.add(line);
+            buffer.write(line);
             line = buffer.toString();
-            buffer.clear();
+            buffer = new StringBuffer();
           }
 
           sink.add(line);
         }
-        buffer.add(leftover);
+        buffer.write(leftover);
       },
       handleDone: (sink) {
         if (!buffer.isEmpty) sink.add(buffer.toString());
         sink.close();
-      })));
-}
-
-// TODO(nweiz): remove this when issue 8310 is fixed.
-/// Returns a [Stream] identical to [stream], but piped through a new
-/// [StreamController]. This exists to work around issue 8310.
-Stream wrapStream(Stream stream) {
-  var controller = stream.isBroadcast
-      ? new StreamController.broadcast()
-      : new StreamController();
-  stream.listen(controller.add,
-      onError: (e) => controller.signalError(e),
-      onDone: controller.close);
-  return controller.stream;
+      }));
 }
 
 /// Like [Iterable.where], but allows [test] to return [Future]s and uses the
diff --git a/utils/pub/validator/compiled_dartdoc.dart b/utils/pub/validator/compiled_dartdoc.dart
index 2d340ba..cd83e76 100644
--- a/utils/pub/validator/compiled_dartdoc.dart
+++ b/utils/pub/validator/compiled_dartdoc.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 
 import '../entrypoint.dart';
 import '../io.dart';
diff --git a/utils/pub/validator/directory.dart b/utils/pub/validator/directory.dart
index 1d1c2b8..cabf45d 100644
--- a/utils/pub/validator/directory.dart
+++ b/utils/pub/validator/directory.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 
 import '../entrypoint.dart';
 import '../io.dart';
diff --git a/utils/pub/validator/lib.dart b/utils/pub/validator/lib.dart
index 5a637a4..9a5b9d0 100644
--- a/utils/pub/validator/lib.dart
+++ b/utils/pub/validator/lib.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 import 'dart:io';
 
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 
 import '../entrypoint.dart';
 import '../io.dart';
diff --git a/utils/pub/validator/license.dart b/utils/pub/validator/license.dart
index 63b9aa8..29fb318 100644
--- a/utils/pub/validator/license.dart
+++ b/utils/pub/validator/license.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 
 import '../entrypoint.dart';
 import '../io.dart';
diff --git a/utils/pub/validator/name.dart b/utils/pub/validator/name.dart
index c183f9c..c953d78 100644
--- a/utils/pub/validator/name.dart
+++ b/utils/pub/validator/name.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 import 'dart:io';
 
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 
 import '../entrypoint.dart';
 import '../io.dart';
@@ -91,12 +91,12 @@
     var lastMatchEnd = 0;
     for (var match in new RegExp(r"[a-z]([A-Z])").allMatches(source)) {
       builder
-        ..add(source.substring(lastMatchEnd, match.start + 1))
-        ..add("_")
-        ..add(match.group(1).toLowerCase());
+        ..write(source.substring(lastMatchEnd, match.start + 1))
+        ..write("_")
+        ..write(match.group(1).toLowerCase());
       lastMatchEnd = match.end;
     }
-    builder.add(source.substring(lastMatchEnd));
+    builder.write(source.substring(lastMatchEnd));
     return builder.toString().toLowerCase();
   }
 }
diff --git a/utils/pub/validator/utf8_readme.dart b/utils/pub/validator/utf8_readme.dart
index e586230..edfdde3 100644
--- a/utils/pub/validator/utf8_readme.dart
+++ b/utils/pub/validator/utf8_readme.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 import 'dart:utf';
 
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 
 import '../entrypoint.dart';
 import '../io.dart';
diff --git a/utils/pub/version_solver.dart b/utils/pub/version_solver.dart
index a45af91..45d47e8 100644
--- a/utils/pub/version_solver.dart
+++ b/utils/pub/version_solver.dart
@@ -601,14 +601,14 @@
 
   String toString() {
     var buffer = new StringBuffer();
-    buffer.add("Package '$package' has no versions that match $constraint "
+    buffer.write("Package '$package' has no versions that match $constraint "
         "derived from:\n");
 
     var keys = new List.from(_dependencies.keys);
     keys.sort();
 
     for (var key in keys) {
-      buffer.add("- '$key' depends on version "
+      buffer.write("- '$key' depends on version "
           "${_dependencies[key].constraint}\n");
     }
 
@@ -641,13 +641,13 @@
 
   String toString() {
     var buffer = new StringBuffer();
-    buffer.add("Incompatible version constraints on '$package':\n");
+    buffer.write("Incompatible version constraints on '$package':\n");
 
     var keys = new List.from(_dependencies.keys);
     keys.sort();
 
     for (var key in keys) {
-      buffer.add("- '$key' depends on version "
+      buffer.write("- '$key' depends on version "
           "${_dependencies[key].constraint}\n");
     }
 
diff --git a/utils/template/codegen.dart b/utils/template/codegen.dart
index 6f566a6..5d8ed2f 100644
--- a/utils/template/codegen.dart
+++ b/utils/template/codegen.dart
@@ -757,7 +757,7 @@
 
       bool identifier = true;
       if (m.start > 0)  {
-        int charCode = expr.charCodeAt(m.start - 1);
+        int charCode = expr.codeUnitAt(m.start - 1);
         // Starts with ' or " then it's not an identifier.
         identifier = charCode != 34 /* " */ && charCode != 39 /* ' */;
       }
diff --git a/utils/template/tokenizer.dart b/utils/template/tokenizer.dart
index 8c1b7f2..cb1b516 100644
--- a/utils/template/tokenizer.dart
+++ b/utils/template/tokenizer.dart
@@ -133,8 +133,8 @@
   // Need to override so CSS version of isIdentifierPart is used.
   Token finishIdentifier() {
     while (_index < _text.length) {
-//      if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
-      if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index))) {
+//      if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) {
+      if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index))) {
 //        _index--;
         break;
       } else {
@@ -209,7 +209,7 @@
 
   bool maybeEatDigit() {
     if (_index < _text.length && TokenizerHelpers.isDigit(
-        _text.charCodeAt(_index))) {
+        _text.codeUnitAt(_index))) {
       _index += 1;
       return true;
     }
@@ -218,7 +218,7 @@
 
   void eatHexDigits() {
     while (_index < _text.length) {
-     if (TokenizerHelpers.isHexDigit(_text.charCodeAt(_index))) {
+     if (TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) {
        _index += 1;
      } else {
        return;
@@ -228,7 +228,7 @@
 
   bool maybeEatHexDigit() {
     if (_index < _text.length && TokenizerHelpers.isHexDigit(
-        _text.charCodeAt(_index))) {
+        _text.codeUnitAt(_index))) {
       _index += 1;
       return true;
     }
diff --git a/utils/template/tokenizer_base.dart b/utils/template/tokenizer_base.dart
index 65b96cd..eb1bcdf 100644
--- a/utils/template/tokenizer_base.dart
+++ b/utils/template/tokenizer_base.dart
@@ -52,7 +52,7 @@
 
   int _nextChar() {
     if (_index < _text.length) {
-      return _text.charCodeAt(_index++);
+      return _text.codeUnitAt(_index++);
     } else {
       return 0;
     }
@@ -60,7 +60,7 @@
 
   int _peekChar() {
     if (_index < _text.length) {
-      return _text.charCodeAt(_index);
+      return _text.codeUnitAt(_index);
     } else {
       return 0;
     }
@@ -68,7 +68,7 @@
 
   bool _maybeEatChar(int ch) {
     if (_index < _text.length) {
-      if (_text.charCodeAt(_index) == ch) {
+      if (_text.codeUnitAt(_index) == ch) {
         _index++;
         return true;
       } else {
@@ -99,7 +99,7 @@
   Token finishWhitespace() {
     _index--;
     while (_index < _text.length) {
-      final ch = _text.charCodeAt(_index++);
+      final ch = _text.codeUnitAt(_index++);
       if (ch == 32/*' '*/ || ch == 9/*'\t'*/ || ch == 13/*'\r'*/) {
         // do nothing
       } else if (ch == 10/*'\n'*/) {
@@ -158,7 +158,7 @@
 
   void eatDigits() {
     while (_index < _text.length) {
-      if (TokenizerHelpers.isDigit(_text.charCodeAt(_index))) {
+      if (TokenizerHelpers.isDigit(_text.codeUnitAt(_index))) {
         _index++;
       } else {
         return;
@@ -189,7 +189,7 @@
     }
     var result = 0;
     while (_index < maxIndex) {
-      final digit = _hexDigit(_text.charCodeAt(_index));
+      final digit = _hexDigit(_text.codeUnitAt(_index));
       if (digit == -1) {
         if (hexLength == null) {
           return result;
@@ -197,7 +197,7 @@
           return -1;
         }
       }
-      _hexDigit(_text.charCodeAt(_index));
+      _hexDigit(_text.codeUnitAt(_index));
       // Multiply by 16 rather than shift by 4 since that will result in a
       // correct value for numbers that exceed the 32 bit precision of JS
       // 'integers'.
@@ -441,14 +441,14 @@
       _interpStack.depth = 0;
       while (_index < _text.length) {
         if (!TokenizerHelpers.isInterpIdentifierPart(
-            _text.charCodeAt(_index++))) {
+            _text.codeUnitAt(_index++))) {
           _index--;
           break;
         }
       }
     } else {
       while (_index < _text.length) {
-        if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) {
+        if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) {
           _index--;
           break;
         }
diff --git a/utils/template/tokenkind.dart b/utils/template/tokenkind.dart
index 6f6ea19..29da694 100644
--- a/utils/template/tokenkind.dart
+++ b/utils/template/tokenkind.dart
@@ -312,8 +312,8 @@
         int idx = offset;
         bool match = true;
         for (int identIdx = 0; identIdx < ident.length; identIdx++) {
-          int identChar = ident.charCodeAt(identIdx);
-          int char = text.charCodeAt(idx++);
+          int identChar = ident.codeUnitAt(identIdx);
+          int char = text.codeUnitAt(idx++);
           // Compare lowercase to lowercase then check if char is uppercase.
           match = match && (char == identChar ||
               ((char >= ASCII_UPPER_A && char <= ASCII_UPPER_Z) &&
@@ -425,29 +425,29 @@
     // All tokens must be in TokenKind order.
     tokens.add(-1);                 // TokenKind.UNUSED
     tokens.add(0);                  // TokenKind.END_OF_FILE match base
-    tokens.add(TokenKind.kindToString(TokenKind.LPAREN).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.RPAREN).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.LBRACK).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.RBRACK).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.LBRACE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.RBRACE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.DOT).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.SEMICOLON).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.SPACE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.TAB).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.NEWLINE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.RETURN).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.COMMA).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.LESS_THAN).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.GREATER_THAN).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.SLASH).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.DOLLAR).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.HASH).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.MINUS).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.EQUAL).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.DOUBLE_QUOTE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.SINGLE_QUOTE).charCodeAt(0));
-    tokens.add(TokenKind.kindToString(TokenKind.ASTERISK).charCodeAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.LPAREN).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.RPAREN).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.LBRACK).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.RBRACK).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.LBRACE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.RBRACE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.DOT).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.SEMICOLON).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.SPACE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.TAB).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.NEWLINE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.RETURN).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.COMMA).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.LESS_THAN).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.GREATER_THAN).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.SLASH).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.DOLLAR).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.HASH).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.MINUS).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.EQUAL).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.DOUBLE_QUOTE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.SINGLE_QUOTE).codeUnitAt(0));
+    tokens.add(TokenKind.kindToString(TokenKind.ASTERISK).codeUnitAt(0));
 
     assert(tokens.length == TokenKind.END_TOKENS);
   }
diff --git a/utils/testrunner/layout_test_controller.dart b/utils/testrunner/layout_test_controller.dart
index ddaa0cf..622e210 100644
--- a/utils/testrunner/layout_test_controller.dart
+++ b/utils/testrunner/layout_test_controller.dart
@@ -232,7 +232,7 @@
       process.close();
       var labelMarker = 'CONSOLE MESSAGE: #TEST ';
       var contentMarker = 'Content-Length: ';
-      var eol = '\n'.charCodeAt(0);
+      var eol = '\n'.codeUnitAt(0);
       var pos = -1;
       var label = null;
       var done = false;
diff --git a/utils/tests/peg/peg_test.dart b/utils/tests/peg/peg_test.dart
index c285b01..59d2d55 100644
--- a/utils/tests/peg/peg_test.dart
+++ b/utils/tests/peg/peg_test.dart
@@ -68,9 +68,9 @@
       TEXT(LEX(MANY(OR(['0','1']))),
            (str, start, end) {
              var r = 0;
-             var zero = '0'.charCodeAt(0);
+             var zero = '0'.codeUnitAt(0);
              for (int i = start; i < end; i++)
-               r = r * 2 + (str.charCodeAt(i) - zero);
+               r = r * 2 + (str.codeUnitAt(i) - zero);
              return r;
            });
 
diff --git a/utils/tests/pub/command_line_config.dart b/utils/tests/pub/command_line_config.dart
index b7b7b34..df4a28a 100644
--- a/utils/tests/pub/command_line_config.dart
+++ b/utils/tests/pub/command_line_config.dart
@@ -6,7 +6,7 @@
 
 import 'dart:io';
 
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 import '../../../pkg/unittest/lib/unittest.dart';
 import '../../pub/utils.dart';
 
@@ -50,7 +50,7 @@
 
     _printStackTrace(testCase.stackTrace);
 
-    currentTestCase = null;
+    super.onTestResult(testCase);
   }
 
   void onSummary(int passed, int failed, int errors, List<TestCase> results,
@@ -105,9 +105,9 @@
     if (string.length >= length) return string;
 
     var result = new StringBuffer();
-    result.add(string);
+    result.write(string);
     for (var i = 0; i < length - string.length; i++) {
-      result.add(' ');
+      result.write(' ');
     }
 
     return result.toString();
diff --git a/utils/tests/pub/install/hosted/repair_cache_test.dart b/utils/tests/pub/install/hosted/repair_cache_test.dart
index 8f2f79f..1636c0f 100644
--- a/utils/tests/pub/install/hosted/repair_cache_test.dart
+++ b/utils/tests/pub/install/hosted/repair_cache_test.dart
@@ -4,7 +4,7 @@
 
 library pub_tests;
 
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/io.dart';
 import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/absolute_path_test.dart b/utils/tests/pub/install/path/absolute_path_test.dart
index cef0a76..2445b26 100644
--- a/utils/tests/pub/install/path/absolute_path_test.dart
+++ b/utils/tests/pub/install/path/absolute_path_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../test_pub.dart';
 
diff --git a/utils/tests/pub/install/path/absolute_symlink_test.dart b/utils/tests/pub/install/path/absolute_symlink_test.dart
index 37aec85..3e65f19 100644
--- a/utils/tests/pub/install/path/absolute_symlink_test.dart
+++ b/utils/tests/pub/install/path/absolute_symlink_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
 import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/no_pubspec_test.dart b/utils/tests/pub/install/path/no_pubspec_test.dart
index 92f54fd..8481617 100644
--- a/utils/tests/pub/install/path/no_pubspec_test.dart
+++ b/utils/tests/pub/install/path/no_pubspec_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:io';
 
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../test_pub.dart';
 
diff --git a/utils/tests/pub/install/path/nonexistent_dir_test.dart b/utils/tests/pub/install/path/nonexistent_dir_test.dart
index 4a129f4..915a683 100644
--- a/utils/tests/pub/install/path/nonexistent_dir_test.dart
+++ b/utils/tests/pub/install/path/nonexistent_dir_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:io';
 
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
 import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/path_is_file_test.dart b/utils/tests/pub/install/path/path_is_file_test.dart
index 8717b49..093e9f5 100644
--- a/utils/tests/pub/install/path/path_is_file_test.dart
+++ b/utils/tests/pub/install/path/path_is_file_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
 import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/relative_path_test.dart b/utils/tests/pub/install/path/relative_path_test.dart
index 497283b..691beed 100644
--- a/utils/tests/pub/install/path/relative_path_test.dart
+++ b/utils/tests/pub/install/path/relative_path_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
 import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/relative_symlink_test.dart b/utils/tests/pub/install/path/relative_symlink_test.dart
index 9460d7d..66c41c8 100644
--- a/utils/tests/pub/install/path/relative_symlink_test.dart
+++ b/utils/tests/pub/install/path/relative_symlink_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:io';
 
-import '../../../../../pkg/path/lib/path.dart' as path;
+import '../../../../../pkg/pathos/lib/path.dart' as path;
 
 import '../../../../pub/exit_codes.dart' as exit_codes;
 import '../../test_pub.dart';
diff --git a/utils/tests/pub/install/path/shared_dependency_symlink_test.dart b/utils/tests/pub/install/path/shared_dependency_symlink_test.dart
new file mode 100644
index 0000000..fddff6b
--- /dev/null
+++ b/utils/tests/pub/install/path/shared_dependency_symlink_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+
+import '../../test_pub.dart';
+
+main() {
+  // new File().fullPathSync() does not resolve through NTFS junction points,
+  // so this feature does not work on Windows.
+  if (Platform.operatingSystem == "windows") return;
+
+  initConfig();
+  integration("shared dependency with symlink", () {
+    dir("shared", [
+      libDir("shared"),
+      libPubspec("shared", "0.0.1")
+    ]).scheduleCreate();
+
+    dir("foo", [
+      libDir("foo"),
+      libPubspec("foo", "0.0.1", deps: [
+        {"path": "../shared"}
+      ])
+    ]).scheduleCreate();
+
+    dir("bar", [
+      libDir("bar"),
+      libPubspec("bar", "0.0.1", deps: [
+        {"path": "../link/shared"}
+      ])
+    ]).scheduleCreate();
+
+    dir(appPath, [
+      pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "foo": {"path": "../foo"},
+          "bar": {"path": "../bar"}
+        }
+      })
+    ]).scheduleCreate();
+
+    dir("link").scheduleCreate();
+    scheduleSymlink("shared", path.join("link", "shared"));
+
+    schedulePub(args: ["install"],
+        output: new RegExp(r"Dependencies installed!$"));
+
+    dir(packagesPath, [
+      dir("foo", [file("foo.dart", 'main() => "foo";')]),
+      dir("bar", [file("bar.dart", 'main() => "bar";')]),
+      dir("shared", [file("shared.dart", 'main() => "shared";')])
+    ]).scheduleValidate();
+  });
+}
\ No newline at end of file
diff --git a/utils/tests/pub/install/path/shared_dependency_test.dart b/utils/tests/pub/install/path/shared_dependency_test.dart
new file mode 100644
index 0000000..b7e1596
--- /dev/null
+++ b/utils/tests/pub/install/path/shared_dependency_test.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.
+
+import '../../../../../pkg/pathos/lib/path.dart' as path;
+
+import '../../test_pub.dart';
+
+main() {
+  initConfig();
+  integration("shared dependency with same path", () {
+    dir("shared", [
+      libDir("shared"),
+      libPubspec("shared", "0.0.1")
+    ]).scheduleCreate();
+
+    dir("foo", [
+      libDir("foo"),
+      libPubspec("foo", "0.0.1", deps: [
+        {"path": "../shared"}
+      ])
+    ]).scheduleCreate();
+
+    dir("bar", [
+      libDir("bar"),
+      libPubspec("bar", "0.0.1", deps: [
+        {"path": "../shared"}
+      ])
+    ]).scheduleCreate();
+
+    dir(appPath, [
+      pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "foo": {"path": "../foo"},
+          "bar": {"path": "../bar"}
+        }
+      })
+    ]).scheduleCreate();
+
+    schedulePub(args: ["install"],
+        output: new RegExp(r"Dependencies installed!$"));
+
+    dir(packagesPath, [
+      dir("foo", [file("foo.dart", 'main() => "foo";')]),
+      dir("bar", [file("bar.dart", 'main() => "bar";')]),
+      dir("shared", [file("shared.dart", 'main() => "shared";')])
+    ]).scheduleValidate();
+  });
+
+  integration("shared dependency with paths that normalize the same", () {
+    dir("shared", [
+      libDir("shared"),
+      libPubspec("shared", "0.0.1")
+    ]).scheduleCreate();
+
+    dir("foo", [
+      libDir("foo"),
+      libPubspec("foo", "0.0.1", deps: [
+        {"path": "../shared"}
+      ])
+    ]).scheduleCreate();
+
+    dir("bar", [
+      libDir("bar"),
+      libPubspec("bar", "0.0.1", deps: [
+        {"path": "../././shared"}
+      ])
+    ]).scheduleCreate();
+
+    dir(appPath, [
+      pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "foo": {"path": "../foo"},
+          "bar": {"path": "../bar"}
+        }
+      })
+    ]).scheduleCreate();
+
+    schedulePub(args: ["install"],
+        output: new RegExp(r"Dependencies installed!$"));
+
+    dir(packagesPath, [
+      dir("foo", [file("foo.dart", 'main() => "foo";')]),
+      dir("bar", [file("bar.dart", 'main() => "bar";')]),
+      dir("shared", [file("shared.dart", 'main() => "shared";')])
+    ]).scheduleValidate();
+  });
+
+  integration("shared dependency with absolute and relative path", () {
+    dir("shared", [
+      libDir("shared"),
+      libPubspec("shared", "0.0.1")
+    ]).scheduleCreate();
+
+    dir("foo", [
+      libDir("foo"),
+      libPubspec("foo", "0.0.1", deps: [
+        {"path": "../shared"}
+      ])
+    ]).scheduleCreate();
+
+    dir("bar", [
+      libDir("bar"),
+      libPubspec("bar", "0.0.1", deps: [
+        {"path": path.join(sandboxDir, "shared")}
+      ])
+    ]).scheduleCreate();
+
+    dir(appPath, [
+      pubspec({
+        "name": "myapp",
+        "dependencies": {
+          "foo": {"path": "../foo"},
+          "bar": {"path": "../bar"}
+        }
+      })
+    ]).scheduleCreate();
+
+    schedulePub(args: ["install"],
+        output: new RegExp(r"Dependencies installed!$"));
+
+    dir(packagesPath, [
+      dir("foo", [file("foo.dart", 'main() => "foo";')]),
+      dir("bar", [file("bar.dart", 'main() => "bar";')]),
+      dir("shared", [file("shared.dart", 'main() => "shared";')])
+    ]).scheduleValidate();
+  });
+}
\ No newline at end of file
diff --git a/utils/tests/pub/io_test.dart b/utils/tests/pub/io_test.dart
index 990dd6c..526283d 100644
--- a/utils/tests/pub/io_test.dart
+++ b/utils/tests/pub/io_test.dart
@@ -4,7 +4,7 @@
 
 library io_test;
 
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 import '../../../pkg/unittest/lib/unittest.dart';
 
 import '../../pub/io.dart';
diff --git a/utils/tests/pub/pub.status b/utils/tests/pub/pub.status
index 254abd7..7184677 100644
--- a/utils/tests/pub/pub.status
+++ b/utils/tests/pub/pub.status
@@ -6,8 +6,11 @@
 oauth2_test: Pass,Fail
 pub_uploader_test: Pass,Fail
 
+pub_lish_test: Pass, Fail # Issue 8868
+validator_test: Pass, Fail # Issue 8868
+
 # Pub only runs on the VM, so just rule out all compilers.
-[ $compiler == dart2js || $compiler == dart2dart || $compiler == dartc ]
+[ $compiler == dart2js || $compiler == dart2dart ]
 *: Skip
 
 # Pub only runs on the standalone VM, not the browser.
diff --git a/utils/tests/pub/real_version_test.dart b/utils/tests/pub/real_version_test.dart
index b0329a6..0d1882c 100644
--- a/utils/tests/pub/real_version_test.dart
+++ b/utils/tests/pub/real_version_test.dart
@@ -7,7 +7,7 @@
 import 'dart:io';
 
 import 'test_pub.dart';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 import '../../../pkg/unittest/lib/unittest.dart';
 
 main() {
diff --git a/utils/tests/pub/sdk_constraint_test.dart b/utils/tests/pub/sdk_constraint_test.dart
index 33d4686..7032c61 100644
--- a/utils/tests/pub/sdk_constraint_test.dart
+++ b/utils/tests/pub/sdk_constraint_test.dart
@@ -35,7 +35,7 @@
       schedulePub(args: [command],
           error:
             """
-            Some packages are not compatible with your SDK version 0.1.2+3:
+            Some packages that were installed are not compatible with your SDK version 0.1.2+3 and may not work:
             - 'myapp' requires >2.0.0
 
             You may be able to resolve this by upgrading to the latest Dart SDK
@@ -72,7 +72,7 @@
       schedulePub(args: [command],
           error:
             """
-            Some packages are not compatible with your SDK version 0.1.2+3:
+            Some packages that were installed are not compatible with your SDK version 0.1.2+3 and may not work:
             - 'myapp' requires >2.0.0
             - 'foo' requires >0.1.3
 
@@ -110,7 +110,7 @@
       schedulePub(args: [command],
           error:
             """
-            Some packages are not compatible with your SDK version 0.1.2+3:
+            Some packages that were installed are not compatible with your SDK version 0.1.2+3 and may not work:
             - 'bar' requires <0.1.1
 
             You may be able to resolve this by upgrading to the latest Dart SDK
@@ -144,7 +144,7 @@
       schedulePub(args: [command],
           error:
             """
-            Some packages are not compatible with your SDK version 0.1.2+3:
+            Some packages that were installed are not compatible with your SDK version 0.1.2+3 and may not work:
             - 'myapp' requires >2.0.0
             - 'foo' requires >3.0.0
 
diff --git a/utils/tests/pub/test_pub.dart b/utils/tests/pub/test_pub.dart
index 64ca423..3f56b3d 100644
--- a/utils/tests/pub/test_pub.dart
+++ b/utils/tests/pub/test_pub.dart
@@ -18,7 +18,7 @@
 
 import '../../../pkg/http/lib/testing.dart';
 import '../../../pkg/oauth2/lib/oauth2.dart' as oauth2;
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 import '../../../pkg/unittest/lib/unittest.dart';
 import '../../../pkg/yaml/lib/yaml.dart';
 import '../../lib/file_system.dart' as fs;
@@ -430,7 +430,7 @@
   case "git":
     var url = description is String ? description : description['url'];
     // TODO(rnystrom): Using path.basename on a URL is hacky. If we add URL
-    // support to pkg/path, should use an explicit builder for that.
+    // support to pkg/pathos, should use an explicit builder for that.
     return path.basename(url.replaceFirst(new RegExp(r"(\.git)?/?$"), ""));
   case "hosted":
     if (description is String) return description;
@@ -559,6 +559,16 @@
   });
 }
 
+
+/// Schedules creating a symlink at path [symlink] that points to [target],
+/// both of which are assumed to be relative to [sandboxDir].
+void scheduleSymlink(String target, String symlink) {
+  _schedule((sandboxDir) {
+    return createSymlink(path.join(sandboxDir, target),
+        path.join(sandboxDir, symlink));
+  });
+}
+
 /// Schedules a call to the Pub command-line utility. Runs Pub with [args] and
 /// validates that its results match [output], [error], and [exitCode].
 void schedulePub({List args, Pattern output, Pattern error,
@@ -582,7 +592,7 @@
           failures.addAll(result.stderr.map((line) => '| $line'));
         }
 
-        throw new ExpectException(failures.join('\n'));
+        throw new TestFailure(failures.join('\n'));
       }
 
       return null;
@@ -859,7 +869,7 @@
       var entry = path.join(dir, name);
       return defer(() {
         if (!entryExists(entry)) {
-          throw new ExpectException('Entry $entry not found.');
+          throw new TestFailure('Entry $entry not found.');
         }
         return validate(entry);
       });
@@ -876,7 +886,7 @@
     return listDir(dir).then((files) {
       var matches = files.where((file) => endsWithPattern(file, name)).toList();
       if (matches.isEmpty) {
-        throw new ExpectException('No files in $dir match pattern $name.');
+        throw new TestFailure('No files in $dir match pattern $name.');
       }
       if (matches.length == 1) return validate(matches[0]);
 
@@ -891,12 +901,12 @@
         }
 
         var error = new StringBuffer();
-        error.add("No files named $name in $dir were valid:\n");
+        error.write("No files named $name in $dir were valid:\n");
         for (var failure in failures) {
-          error.add("  $failure\n");
+          error.write("  $failure\n");
         }
         completer.completeError(
-            new ExpectException(error.toString()), stackTrace);
+            new TestFailure(error.toString()), stackTrace);
       }
 
       for (var match in matches) {
@@ -943,7 +953,7 @@
       var text = readTextFile(file);
       if (text == textContents) return null;
 
-      throw new ExpectException(
+      throw new TestFailure(
           'File $file should contain:\n\n$textContents\n\n'
           'but contained:\n\n$text');
     });
@@ -1173,7 +1183,7 @@
   Future validate(String dir) {
     return defer(() {
       if (entryExists(path.join(dir, name))) {
-        throw new ExpectException('File $name in $dir should not exist.');
+        throw new TestFailure('File $name in $dir should not exist.');
       }
     });
   }
@@ -1305,10 +1315,9 @@
       _process = p;
 
       byteStreamToLines(stream) {
-        var handledErrors = wrapStream(stream.handleError((e) {
+        return streamToLines(new ByteStream(stream.handleError((e) {
           registerException(e.error, e.stackTrace);
-        }));
-        return streamToLines(new ByteStream(handledErrors).toStringStream());
+        })).toStringStream());
       }
 
       var stdoutTee = tee(byteStreamToLines(p.stdout));
@@ -1350,7 +1359,7 @@
 
           return _printStreams();
         }).then((_) {
-          registerException(new ExpectException("Process $name ended "
+          registerException(new TestFailure("Process $name ended "
               "earlier than scheduled with exit code $exitCode"));
         });
       }).catchError((e) => registerException(e.error, e.stackTrace));
@@ -1430,7 +1439,7 @@
   /// Writes [line] to the process as stdin.
   void writeLine(String line) {
     _schedule((_) => _processFuture.then(
-        (p) => p.stdin.add('$line\n'.charCodes)));
+        (p) => p.stdin.add('$line\n'.codeUnits)));
   }
 
   /// Kills the process, and waits until it's dead.
diff --git a/utils/tests/pub/validator_test.dart b/utils/tests/pub/validator_test.dart
index 4f59bba..c439633 100644
--- a/utils/tests/pub/validator_test.dart
+++ b/utils/tests/pub/validator_test.dart
@@ -11,7 +11,7 @@
 
 import '../../../pkg/http/lib/http.dart' as http;
 import '../../../pkg/http/lib/testing.dart';
-import '../../../pkg/path/lib/path.dart' as path;
+import '../../../pkg/pathos/lib/path.dart' as path;
 import '../../../pkg/unittest/lib/unittest.dart';
 
 import 'test_pub.dart';
diff --git a/utils/tests/string_encoding/benchmark_runner.dart b/utils/tests/string_encoding/benchmark_runner.dart
index 3f8bf39..514e87e 100644
--- a/utils/tests/string_encoding/benchmark_runner.dart
+++ b/utils/tests/string_encoding/benchmark_runner.dart
@@ -89,7 +89,7 @@
  */
 class TestReport {
   TestReport(this.id, this.desc, this.warmup, this.results) {
-    spaceChar = " ".charCodes[0];
+    spaceChar = " ".codeUnits[0];
   }
 
   int spaceChar;
@@ -168,7 +168,7 @@
   String _leftAlign(String s, int width) {
     List<int> outCodes = [];
     outCodes.insertRange(0, width, spaceChar);
-    outCodes.setRange(0, Math.min(width, s.length), s.charCodes);
+    outCodes.setRange(0, Math.min(width, s.length), s.codeUnits);
     return new String.fromCharCodes(outCodes);
   }
 
@@ -176,7 +176,7 @@
     List<int> outCodes = [];
     outCodes.insertRange(0, width, spaceChar);
     outCodes.setRange(Math.max(0, width - s.length), Math.min(width, s.length),
-        s.charCodes);
+        s.codeUnits);
     return new String.fromCharCodes(outCodes);
   }
 
diff --git a/utils/tests/string_encoding/dunit.dart b/utils/tests/string_encoding/dunit.dart
index 3c092b3..e2302e3 100644
--- a/utils/tests/string_encoding/dunit.dart
+++ b/utils/tests/string_encoding/dunit.dart
@@ -33,19 +33,19 @@
   }
 
   void reportResults(List<TestResult> results) {
-    if(results.every(bool _(TestResult r) => r is PassedTest)) {
+    if(results.every((TestResult r) => r is PassedTest)) {
       print("OK -- ALL TESTS PASS (${results.length} run)");
     } else {
       for(TestResult r in
-          results.where(bool _(TestResult r) => !(r is PassedTest))) {
+          results.where((TestResult r) => !(r is PassedTest))) {
         print(r);
       }
       int passedTests =
-          results.where(bool _(TestResult r) => r is PassedTest).length;
+          results.where((TestResult r) => r is PassedTest).length;
       int failures =
-          results.where(bool _(TestResult r) => r is FailedTest).length;
+          results.where((TestResult r) => r is FailedTest).length;
       int errors =
-          results.where(bool _(TestResult r) => r is TestError).length;
+          results.where((TestResult r) => r is TestError).length;
       print("FAIL -- TESTS RUN: ${results.length}");
       print("        PASSED: ${passedTests}");
       print("        FAILED: ${failures}");
@@ -97,7 +97,7 @@
 
 class TestClass {
   void register(String description, Function test, TestSuite suite) {
-    suite._registerTest(TestResult _() {
+    suite._registerTest(() {
       setUp();
       try {
         test();
@@ -113,7 +113,7 @@
     });
   }
 
-  abstract void registerTests(TestSuite suite);
+  void registerTests(TestSuite suite);
   void setUp() {}
   void tearDown() {}
 }
diff --git a/utils/tests/string_encoding/unicode_test.dart b/utils/tests/string_encoding/unicode_test.dart
index 054ff45..5b57377 100755
--- a/utils/tests/string_encoding/unicode_test.dart
+++ b/utils/tests/string_encoding/unicode_test.dart
@@ -5,7 +5,7 @@
 
 library unicode_tests;
 import 'dunit.dart';
-import '../../../lib/utf/utf.dart';
+import '../../../sdk/lib/utf/utf.dart';
 
 void main() {
   TestSuite suite = new TestSuite();
@@ -30,7 +30,7 @@
   }
 
   void testStringCharCodes() {
-    Expect.listEquals(testCodepoints, testPhrase.charCodes());
+    Expect.listEquals(testCodepoints, testPhrase.codeUnits);
   }
 
   void testCodepointsToString() {
@@ -42,6 +42,6 @@
   }
 
   void testEmptyStringCharCodes() {
-    Expect.listEquals([], "".charCodes());
+    Expect.listEquals([], "".codeUnits);
   }
 }
diff --git a/utils/tests/string_encoding/utf16_test.dart b/utils/tests/string_encoding/utf16_test.dart
index 004dcf0..7e58a6c 100755
--- a/utils/tests/string_encoding/utf16_test.dart
+++ b/utils/tests/string_encoding/utf16_test.dart
@@ -118,7 +118,7 @@
     IterableUtf16Decoder koreanDecoder =
       decodeUtf16AsIterable(testKoreanCharSubsetUtf16beBom);
     // get the first character
-    Expect.equals(testKoreanCharSubset.charCodes[0], koreanDecoder.first);
+    Expect.equals(testKoreanCharSubset.codeUnits[0], koreanDecoder.first);
     // get the whole translation using the Iterable interface
     Expect.stringEquals(testKoreanCharSubset,
         new String.fromCharCodes(new List<int>.from(koreanDecoder)));
diff --git a/utils/tests/string_encoding/utf32_test.dart b/utils/tests/string_encoding/utf32_test.dart
index eb727bc..ed6ace8 100755
--- a/utils/tests/string_encoding/utf32_test.dart
+++ b/utils/tests/string_encoding/utf32_test.dart
@@ -170,7 +170,7 @@
     IterableUtf32Decoder koreanDecoder =
       decodeUtf32AsIterable(testKoreanCharSubsetUtf32beBom);
     // get the first character
-    Expect.equals(testKoreanCharSubset.charCodes[0],
+    Expect.equals(testKoreanCharSubset.codeUnits[0],
         koreanDecoder.iterator.first);
     // get the whole translation using the Iterable interface
     Expect.stringEquals(testKoreanCharSubset,
diff --git a/utils/tests/string_encoding/utf8_test.dart b/utils/tests/string_encoding/utf8_test.dart
index 596626e..09fee3c 100755
--- a/utils/tests/string_encoding/utf8_test.dart
+++ b/utils/tests/string_encoding/utf8_test.dart
@@ -466,7 +466,7 @@
 
     IterableUtf8Decoder kataDecoder = decodeUtf8AsIterable(testKatakanaUtf8);
     // get the first character
-    Expect.equals(testKatakanaPhrase.charCodes[0], kataDecoder.first);
+    Expect.equals(testKatakanaPhrase.codeUnits[0], kataDecoder.first);
     // get the whole translation using the Iterable interface
     Expect.stringEquals(testKatakanaPhrase,
         new String.fromCharCodes(new List<int>.from(kataDecoder)));