Version 0.2.5.0

svn merge -r 15013:15295  https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@15296 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/.gitignore b/.gitignore
index 5c2afd1..ce9b95f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,3 +74,6 @@
 
 # Pub generated "packages" directories
 packages
+
+# Vim temporary swap files.
+*.swp
diff --git a/client/dart.js b/client/dart.js
index c76e3fa..1c8b333 100644
--- a/client/dart.js
+++ b/client/dart.js
@@ -159,11 +159,21 @@
 
   window.registerPort = function(name, port) {
     var stringified = JSON.stringify(serialize(port));
-    window.localStorage['dart-port:' + name] = stringified;
+    var attrName = 'dart-port:' + name;
+    document.documentElement.setAttribute(attrName, stringified);
+    // TODO(vsm): Phase out usage of localStorage.  We're leaving it in
+    // temporarily for backwards compatibility.
+    window.localStorage[attrName] = stringified;
   };
 
   window.lookupPort = function(name) {
-    var stringified = window.localStorage['dart-port:' + name];
+    var attrName = 'dart-port:' + name;
+    var stringified = document.documentElement.getAttribute(attrName);
+    // TODO(vsm): Phase out usage of localStorage.  We're leaving it in
+    // temporarily for backwards compatibility.
+    if (!stringified) {
+      stringified = window.localStorage[attrName];
+    }
     return deserialize(JSON.parse(stringified));
   };
 
diff --git a/compiler/java/com/google/dart/compiler/UrlLibrarySource.java b/compiler/java/com/google/dart/compiler/UrlLibrarySource.java
index efc71d3..f5ec48c 100644
--- a/compiler/java/com/google/dart/compiler/UrlLibrarySource.java
+++ b/compiler/java/com/google/dart/compiler/UrlLibrarySource.java
@@ -70,6 +70,12 @@
     try {
       // Force the creation of an escaped relative URI to deal with spaces, etc.
       URI uri = getUri().resolve(new URI(null, null, relPath, null, null)).normalize();
+      if (PackageLibraryManager.isPackageUri(uri)) {
+        URI fileUri = packageLibraryManager.resolveDartUri(uri);
+        if (fileUri != null) {
+          uri = fileUri;
+        }
+      }
       return createDartSource(uri, relPath, this, packageLibraryManager);
     } catch (Throwable e) {
       return null;
diff --git a/compiler/java/com/google/dart/compiler/ast/DartDeclaration.java b/compiler/java/com/google/dart/compiler/ast/DartDeclaration.java
index 5080bb1..35f3013 100644
--- a/compiler/java/com/google/dart/compiler/ast/DartDeclaration.java
+++ b/compiler/java/com/google/dart/compiler/ast/DartDeclaration.java
@@ -10,7 +10,8 @@
  * considered a part of the declaration, not an independent node. So the name is not visited when
  * traversing the AST.
  */
-public abstract class DartDeclaration<N extends DartExpression> extends DartNodeWithMetadata {
+public abstract class DartDeclaration<N extends DartExpression> extends DartNodeWithMetadata
+    implements HasObsoleteMetadata {
 
   private N name; // Not visited.
   private DartComment dartDoc;
diff --git a/compiler/java/com/google/dart/compiler/ast/DartDirective.java b/compiler/java/com/google/dart/compiler/ast/DartDirective.java
index ad1a9ec..7c039c1 100644
--- a/compiler/java/com/google/dart/compiler/ast/DartDirective.java
+++ b/compiler/java/com/google/dart/compiler/ast/DartDirective.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -9,9 +9,19 @@
 /**
  * Base class for directives.
  */
-public abstract class DartDirective extends DartNodeWithMetadata {
+public abstract class DartDirective extends DartNodeWithMetadata implements HasObsoleteMetadata {
+  private DartObsoleteMetadata obsoleteMetadata = DartObsoleteMetadata.EMPTY;
+
   @Override
   public NodeElement getElement() {
     throw new UnsupportedOperationException(getClass().getSimpleName());
   }
+
+  public DartObsoleteMetadata getObsoleteMetadata() {
+    return obsoleteMetadata;
+  }
+
+  public void setObsoleteMetadata(DartObsoleteMetadata metadata) {
+    this.obsoleteMetadata = metadata;
+  }
 }
diff --git a/compiler/java/com/google/dart/compiler/ast/DartStringLiteral.java b/compiler/java/com/google/dart/compiler/ast/DartStringLiteral.java
index 91c69d9..e2a83bf 100644
--- a/compiler/java/com/google/dart/compiler/ast/DartStringLiteral.java
+++ b/compiler/java/com/google/dart/compiler/ast/DartStringLiteral.java
@@ -5,6 +5,7 @@
 package com.google.dart.compiler.ast;
 
 import com.google.common.collect.ImmutableList;
+import com.google.dart.compiler.resolver.Element;
 
 import java.util.List;
 
@@ -12,6 +13,8 @@
  * Represents a Dart string literal value.
  */
 public class DartStringLiteral extends DartLiteral {
+  
+  private Element element;
 
   public static DartStringLiteral get(String x) {
     return new DartStringLiteral(x, null);
@@ -43,6 +46,16 @@
     }
     return parts;
   }
+  
+  @Override
+  public void setElement(Element element) {
+    this.element = element;
+  }
+  
+  @Override
+  public Element getElement() {
+    return element;
+  }
 
   @Override
   public void visitChildren(ASTVisitor<?> visitor) {
diff --git a/compiler/java/com/google/dart/compiler/ast/HasObsoleteMetadata.java b/compiler/java/com/google/dart/compiler/ast/HasObsoleteMetadata.java
new file mode 100644
index 0000000..b1648aa
--- /dev/null
+++ b/compiler/java/com/google/dart/compiler/ast/HasObsoleteMetadata.java
@@ -0,0 +1,12 @@
+// 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.
+
+package com.google.dart.compiler.ast;
+
+public interface HasObsoleteMetadata {
+
+  DartObsoleteMetadata getObsoleteMetadata();
+
+  void setObsoleteMetadata(DartObsoleteMetadata metadata);
+}
diff --git a/compiler/java/com/google/dart/compiler/ast/LibraryUnit.java b/compiler/java/com/google/dart/compiler/ast/LibraryUnit.java
index d6e2a31..2bd491f 100644
--- a/compiler/java/com/google/dart/compiler/ast/LibraryUnit.java
+++ b/compiler/java/com/google/dart/compiler/ast/LibraryUnit.java
@@ -187,6 +187,14 @@
 
   public void setSelfDartUnit(DartUnit unit) {
     this.selfDartUnit = unit;
+    // set DartObsoleteMetadata for LibraryElement
+    if (unit != null) {
+      List<DartDirective> directives = unit.getDirectives();
+      if (!directives.isEmpty() && directives.get(0) instanceof DartLibraryDirective) {
+        DartLibraryDirective libraryDirective = (DartLibraryDirective) directives.get(0);
+        Elements.setLibraryMetadata(element, libraryDirective.getObsoleteMetadata());
+      }
+    }
   }
 
   /**
diff --git a/compiler/java/com/google/dart/compiler/parser/DartParser.java b/compiler/java/com/google/dart/compiler/parser/DartParser.java
index 7537e43..a79148c 100644
--- a/compiler/java/com/google/dart/compiler/parser/DartParser.java
+++ b/compiler/java/com/google/dart/compiler/parser/DartParser.java
@@ -96,6 +96,7 @@
 import com.google.dart.compiler.ast.DartVariable;
 import com.google.dart.compiler.ast.DartVariableStatement;
 import com.google.dart.compiler.ast.DartWhileStatement;
+import com.google.dart.compiler.ast.HasObsoleteMetadata;
 import com.google.dart.compiler.ast.ImportCombinator;
 import com.google.dart.compiler.ast.ImportHideCombinator;
 import com.google.dart.compiler.ast.ImportShowCombinator;
@@ -336,8 +337,7 @@
           // TODO(scheglov) remove after http://code.google.com/p/dart/issues/detail?id=6318 
           if (!Elements.isCoreLibrarySource(source)
               && !Elements.isLibrarySource(source, "/isolate/isolate.dart")
-              && !Elements.isLibrarySource(source, "crypto/crypto.dart")
-              && !Elements.isDart2JsLibrarySource(source)) {
+              && !Elements.isLibrarySource(source, "crypto/crypto.dart")) {
             reportError(position(), ParserErrorCode.DEPRECATED_INTERFACE);
           }
           node = done(parseClass());
@@ -385,19 +385,26 @@
    * @param metadata the metadata to be associated with the node
    */
   private void setMetadata(DartNodeWithMetadata node, List<DartAnnotation> annotations) {
+    if (node instanceof DartFieldDefinition) {
+      DartFieldDefinition fieldDefinition = (DartFieldDefinition) node;
+      List<DartField> fields = fieldDefinition.getFields();
+      for (DartField field : fields) {
+        setMetadata(field, annotations);
+      }
+      return;
+    }
     if (annotations != null && !annotations.isEmpty()) {
       node.setMetadata(annotations);
-      if (node instanceof DartDeclaration<?>) {
+      if (node instanceof HasObsoleteMetadata) {
+        HasObsoleteMetadata declaration = (HasObsoleteMetadata) node;
         for (int i = 0, size = annotations.size(); i < size; i++) {
           DartAnnotation annotation = annotations.get(i);
           DartExpression nameNode = annotation.getName();
           if (nameNode instanceof DartIdentifier) {
             String name = ((DartIdentifier) nameNode).getName();
             if (name.equals("deprecated")) {
-              DartDeclaration<?> declaration = (DartDeclaration<?>) node;
               declaration.setObsoleteMetadata(declaration.getObsoleteMetadata().makeDeprecated());
             } else if (name.equals("override")) {
-              DartDeclaration<?> declaration = (DartDeclaration<?>) node;
               declaration.setObsoleteMetadata(declaration.getObsoleteMetadata().makeOverride());
             }
           }
@@ -1319,8 +1326,7 @@
           && !Elements.isLibrarySource(source, "/math/math.dart")
           && !Elements.isLibrarySource(source, "/io/io_runtime.dart")
           && !Elements.isLibrarySource(source, "/crypto/crypto.dart")
-          && !Elements.isLibrarySource(source, "/utf/utf.dart")
-          && !Elements.isDart2JsLibrarySource(source)) {
+          && !Elements.isLibrarySource(source, "/utf/utf.dart")) {
         reportError(position(), ParserErrorCode.DEPRECATED_ABSTRACT_METHOD);
       }
     }
@@ -3750,9 +3756,8 @@
           constructor = doneWithoutConsuming(toPrefixedType(parts));
         } else {
           // Named constructor.
-          DartIdentifier identifier = (DartIdentifier)part2.getIdentifier();
-          constructor = doneWithoutConsuming(new DartPropertyAccess(doneWithoutConsuming(part1),
-                                                                    identifier));
+          DartIdentifier identifier = (DartIdentifier) part2.getIdentifier();
+          constructor = doneWithoutConsuming(new DartPropertyAccess(part1, identifier));
         }
         break;
       }
diff --git a/compiler/java/com/google/dart/compiler/resolver/Elements.java b/compiler/java/com/google/dart/compiler/resolver/Elements.java
index 5fadc57..b95d48c 100644
--- a/compiler/java/com/google/dart/compiler/resolver/Elements.java
+++ b/compiler/java/com/google/dart/compiler/resolver/Elements.java
@@ -87,6 +87,10 @@
     return new LibraryElementImplementation(libraryUnit);
   }
   
+  public static void setLibraryMetadata(LibraryElement element, DartObsoleteMetadata metadata) {
+    ((LibraryElementImplementation) element).setMetadata(metadata);
+  }
+  
   public static void addExportedElement(LibraryElement libraryElement, Element element) {
     ((LibraryElementImplementation) libraryElement).addExportedElements(element);
   }
@@ -744,21 +748,6 @@
     }
     return false;
   }
-  
-  /**
-   * @return <code>true</code> if given {@link Source} represents library with given name.
-   */
-  public static boolean isDart2JsLibrarySource(Source source) {
-    if (source instanceof DartSource) {
-      DartSource dartSource = (DartSource) source;
-      LibrarySource library = dartSource.getLibrary();
-      if (library != null) {
-        String libraryName = library.getName();
-        return libraryName.contains("lib/compiler/implementation/");
-      }
-    }
-    return false;
-  }
 
   /**
    * @return <code>true</code> if given {@link Source} represents code library declaration or
diff --git a/compiler/java/com/google/dart/compiler/resolver/LibraryElementImplementation.java b/compiler/java/com/google/dart/compiler/resolver/LibraryElementImplementation.java
index 8059600..ea4d530 100644
--- a/compiler/java/com/google/dart/compiler/resolver/LibraryElementImplementation.java
+++ b/compiler/java/com/google/dart/compiler/resolver/LibraryElementImplementation.java
@@ -5,6 +5,7 @@
 package com.google.dart.compiler.resolver;
 
 import com.google.common.collect.Lists;
+import com.google.dart.compiler.ast.DartObsoleteMetadata;
 import com.google.dart.compiler.ast.LibraryUnit;
 
 import java.util.Collection;
@@ -17,6 +18,7 @@
   private final List<Element> exportedElements = Lists.newArrayList();
   private LibraryUnit libraryUnit;
   private MethodElement entryPoint;
+  private DartObsoleteMetadata metadata;
 
   public LibraryElementImplementation(LibraryUnit libraryUnit) {
     // TODO(ngeoffray): What should we pass the super? Should a LibraryUnit be a node?
@@ -85,4 +87,13 @@
   void addMethod(MethodElement method) {
     scope.declareElement(method.getName(), method);
   }
+  
+  @Override
+  public DartObsoleteMetadata getMetadata() {
+    return metadata;
+  }
+
+  public void setMetadata(DartObsoleteMetadata metadata) {
+    this.metadata = metadata;
+  }
 }
diff --git a/compiler/java/com/google/dart/compiler/resolver/ResolveVisitor.java b/compiler/java/com/google/dart/compiler/resolver/ResolveVisitor.java
index ad1da78..3068877 100644
--- a/compiler/java/com/google/dart/compiler/resolver/ResolveVisitor.java
+++ b/compiler/java/com/google/dart/compiler/resolver/ResolveVisitor.java
@@ -16,6 +16,7 @@
 import com.google.dart.compiler.ast.DartThisExpression;
 import com.google.dart.compiler.ast.DartTypeNode;
 import com.google.dart.compiler.ast.DartTypeParameter;
+import com.google.dart.compiler.common.HasSourceInfo;
 import com.google.dart.compiler.type.FunctionType;
 import com.google.dart.compiler.type.Type;
 import com.google.dart.compiler.type.Types;
@@ -143,11 +144,15 @@
     node.setType(type);
     Element element = type.getElement();
     recordElement(node.getIdentifier(), element);
+    checkDeprecated(node, element);
+    return type;
+  }
+
+  protected final void checkDeprecated(HasSourceInfo nameNode, Element element) {
     if (element != null && element.getMetadata().isDeprecated()) {
-      getContext().onError(node.getIdentifier(), TypeErrorCode.DEPRECATED_ELEMENT,
+      getContext().onError(nameNode, TypeErrorCode.DEPRECATED_ELEMENT,
          Elements.getDeprecatedElementTitle(element));
     }
-    return type;
   }
 
   protected <E extends Element> E recordElement(DartNode node, E element) {
diff --git a/compiler/java/com/google/dart/compiler/resolver/Resolver.java b/compiler/java/com/google/dart/compiler/resolver/Resolver.java
index 71d67b2..88b06e4 100644
--- a/compiler/java/com/google/dart/compiler/resolver/Resolver.java
+++ b/compiler/java/com/google/dart/compiler/resolver/Resolver.java
@@ -40,6 +40,7 @@
 import com.google.dart.compiler.ast.DartGotoStatement;
 import com.google.dart.compiler.ast.DartIdentifier;
 import com.google.dart.compiler.ast.DartIfStatement;
+import com.google.dart.compiler.ast.DartImportDirective;
 import com.google.dart.compiler.ast.DartInitializer;
 import com.google.dart.compiler.ast.DartIntegerLiteral;
 import com.google.dart.compiler.ast.DartInvocation;
@@ -76,6 +77,8 @@
 import com.google.dart.compiler.ast.DartVariable;
 import com.google.dart.compiler.ast.DartVariableStatement;
 import com.google.dart.compiler.ast.DartWhileStatement;
+import com.google.dart.compiler.ast.LibraryImport;
+import com.google.dart.compiler.ast.LibraryUnit;
 import com.google.dart.compiler.ast.Modifiers;
 import com.google.dart.compiler.common.HasSourceInfo;
 import com.google.dart.compiler.common.SourceInfo;
@@ -230,11 +233,33 @@
 
     @Override
     public Element visitUnit(DartUnit unit) {
+      List<DartImportDirective> importDirectives = Lists.newArrayList();
       for (DartDirective directive : unit.getDirectives()) {
+        if (directive instanceof DartImportDirective) {
+          importDirectives.add((DartImportDirective) directive);
+        }
         if (directive instanceof DartPartOfDirective) {
           directive.accept(this);
         }
       }
+      // set LibraryElement for "import" directives
+      {
+        LibraryUnit library = unit.getLibrary();
+        if (library != null) {
+          Iterator<LibraryImport> importIterator = library.getImports().iterator();
+          Iterator<DartImportDirective> directiveIterator = importDirectives.iterator();
+          while (importIterator.hasNext() && directiveIterator.hasNext()) {
+            LibraryImport imp = importIterator.next();
+            DartImportDirective dir = directiveIterator.next();
+            DartStringLiteral uri = dir.getLibraryUri();
+            LibraryUnit impLibrary = imp.getLibrary();
+            if (uri != null && impLibrary != null) {
+              uri.setElement(impLibrary.getElement());
+            }
+          }
+        }
+      }
+      // visit top-level nodes
       for (DartNode node : unit.getTopLevelNodes()) {
         node.accept(this);
       }
@@ -715,10 +740,19 @@
       }
       resolve(functionNode.getBody());
 
-      if (Elements.isNonFactoryConstructor(member)
-          && !(body instanceof DartNativeBlock)) {
+      if (Elements.isNonFactoryConstructor(member) && !(body instanceof DartNativeBlock)) {
         resolveInitializers(node, initializedFields);
       }
+
+      // only generative constructor can have initializers, so resolve them, but report error 
+      if (!member.isConstructor() || member.getModifiers().isFactory()) {
+        for (DartInitializer initializer : node.getInitializers()) {
+          resolve(initializer);
+          if (initializer.getName() != null) {
+            onError(initializer, ResolverErrorCode.INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR);
+          }
+        }
+      }
       
       // resolve redirecting factory constructor
       {
@@ -1253,6 +1287,20 @@
         }
       }
 
+      if (ElementKind.of(element) == ElementKind.FIELD) {
+        FieldElement fieldElement = (FieldElement) element;
+        if (fieldElement.getModifiers().isAbstractField()) {
+          if (fieldElement.getGetter() == null && ASTNodes.inGetterContext(x)) {
+            topLevelContext.onError(x, ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER);
+            x.markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
+          }
+          if (fieldElement.getSetter() == null && ASTNodes.inSetterContext(x)) {
+            topLevelContext.onError(x, ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER);
+            x.markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
+          }
+        }
+      }
+
       // May be local variable declared in lexical scope, but its declaration is not visited yet.
       if (getContext().getScope().isDeclaredButNotReachedVariable(name)) {
         onError(x, ResolverErrorCode.USING_LOCAL_VARIABLE_BEFORE_DECLARATION, x);
@@ -1278,6 +1326,7 @@
       // If we we haven't resolved the identifier, it will be normalized to
       // this.<identifier>.
 
+      checkDeprecated(x, element);
       return recordElement(x, element);
     }
 
@@ -1319,19 +1368,9 @@
             return typeProvider.getTypeType().getElement();
           }
           break;
+        case FUNCTION_TYPE_ALIAS:
         case TYPE_VARIABLE:
-          // Type variables are not legal in identifier expressions, but the type variable
-          // may be hiding a class element.
-          LibraryElement libraryElement = scope.getLibrary();
-          Scope libraryScope = libraryElement.getScope();
-          // dip again at the library level.
-          element = libraryScope.findElement(libraryElement, name);
-          if (element == null) {
-            onError(x, ResolverErrorCode.TYPE_VARIABLE_NOT_ALLOWED_IN_IDENTIFIER);
-          } else {
-            return checkResolvedIdentifier(x, isQualifier, libraryScope, name, element);
-          }
-          break;
+          return typeProvider.getTypeType().getElement();
         default:
           break;
       }
diff --git a/compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java b/compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java
index 550ea7e..f6d91c6 100644
--- a/compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java
+++ b/compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java
@@ -127,6 +127,7 @@
   ILLEGAL_ACCESS_TO_PRIVATE_MEMBER("\"%s\" refers to \"%s\" which is in a different library"),
   ILLEGAL_FIELD_ACCESS_FROM_STATIC("Illegal access of instance field %s from static scope"),
   ILLEGAL_METHOD_ACCESS_FROM_STATIC("Illegal access of instance method %s from static scope"),
+  INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR("Initializers are allowed only in non-redirecting generative constructors"),
   INIT_FIELD_ONLY_IMMEDIATELY_SURROUNDING_CLASS(
       "Only fields of immediately surrounding class can be initialized"),
   INSTANCE_METHOD_FROM_INITIALIZER("Instance methods cannot be referenced from constructor initializer"),
diff --git a/compiler/java/com/google/dart/compiler/type/InterfaceType.java b/compiler/java/com/google/dart/compiler/type/InterfaceType.java
index 7a746c1..99b7c9d 100644
--- a/compiler/java/com/google/dart/compiler/type/InterfaceType.java
+++ b/compiler/java/com/google/dart/compiler/type/InterfaceType.java
@@ -35,6 +35,10 @@
   
   void registerSubClass(ClassElement subClass);
   void unregisterSubClass(ClassElement subClass);
+  /**
+   * @return the unique {@link Member} with given name, defined in one of the subtypes. May be
+   *         <code>null</code> if not found or not unique.
+   */
   Member lookupSubTypeMember(String name);
 
   interface Member {
diff --git a/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java b/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
index fac151a..52c63ce 100644
--- a/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
+++ b/compiler/java/com/google/dart/compiler/type/InterfaceTypeImplementation.java
@@ -233,21 +233,32 @@
   
   @Override
   public Member lookupSubTypeMember(String name) {
+    Member foundMember = null;
     for (ClassElement subClass : subClasses.keySet()) {
+      // find one or more members in subClass elements
       {
         Element element = subClass.lookupLocalElement(name);
         if (element != null) {
-          return new MemberImplementation(this, element);
+          if (foundMember != null) {
+            return null;
+          }
+          foundMember = new MemberImplementation(this, element);
+          continue;
         }
       }
+      // try to find deeper
       InterfaceType type = subClass.getType();
       if (type != null) {
         Member member = type.lookupSubTypeMember(name);
         if (member != null) {
-          return member;
+          if (foundMember != null) {
+            return null;
+          }
+          foundMember = member;
         }
       }
     }
-    return null;
+    // may be found
+    return foundMember;
   }
 }
diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
index 1ca3593..e6a6419 100644
--- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
+++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
@@ -1860,7 +1860,7 @@
     @Override
     public Type visitFunctionExpression(DartFunctionExpression node) {
       node.visitChildren(this);
-      Type result = ((Element) node.getElement()).getType();
+      Type result = node.getElement().getType();
       result.getClass(); // quick null check
       return result;
     }
diff --git a/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java b/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java
index 75dfde1..90d8486 100644
--- a/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java
+++ b/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java
@@ -823,8 +823,7 @@
         "  try {",
         "    0.25 - f;",
         "  } catch(e) {}",
-        "}"),
-        ResolverErrorCode.CANNOT_USE_TYPE);
+        "}"));
   }
 
   public void test_classUsedAsExpression() {
@@ -841,11 +840,11 @@
         "class A<B> {",
         "  var field = B;",
         "  f() {",
-        "    0.25 - B;",
+        "    process(x);",
         "  }",
-        "}"),
-        ResolverErrorCode.TYPE_VARIABLE_NOT_ALLOWED_IN_IDENTIFIER,
-    ResolverErrorCode.TYPE_VARIABLE_NOT_ALLOWED_IN_IDENTIFIER);
+        "}",
+        "process(x) {}",
+        ""));
   }
 
   public void test_shadowType_withVariable() throws Exception {
@@ -1057,6 +1056,8 @@
         "  result = instance.setter3;",
         "  instance.setter3 = 1;",
         "}"),
+        errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER, 13, 3, 7),
+        errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER, 14, 12, 7),
         errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER, 17, 5, 7),
         errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER, 18, 14, 7));
   }
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
index f1a8dcb..5f72504 100644
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java
@@ -3707,6 +3707,8 @@
         "const deprecated = 0;",
         "@deprecated",
         "ttt() {}",
+        "@deprecated",
+        "get topLevelGet => 42;",
         "class A {",
         "  var @deprecated fff;",
         "  @deprecated",
@@ -3716,6 +3718,7 @@
         "}",
         "method() {",
         "  ttt();",
+        "  print(topLevelGet);",
         "  A a = new A();",
         "  a.fff = 0;",
         "  a.mmmm();",
@@ -3724,10 +3727,11 @@
         "");
     assertErrors(
         libraryResult.getErrors(),
-        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 13, 3, 3),
-        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 15, 5, 3),
-        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 16, 5, 4),
-        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 17, 5, 1));
+        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 16, 9, 11),
+        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 15, 3, 3),
+        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 18, 5, 3),
+        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 19, 5, 4),
+        errEx(TypeErrorCode.DEPRECATED_ELEMENT, 20, 5, 1));
   }
 
   public void test_metadataComment_deprecated_2() throws Exception {
@@ -5351,6 +5355,32 @@
     assertErrors(result.getErrors(), errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 5, 1));
   }
 
+  public void test_field_unqualifiedAccess_read() throws Exception {
+    AnalyzeLibraryResult result = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class A {",
+        "  set f(x) {}",
+        "  run() {",
+        "    var v = f;",
+        "  }",
+        "}",
+        "");
+    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",
+        "class A {",
+        "  get f => 0;",
+        "  run() {",
+        "    f = 1;",
+        "  }",
+        "}",
+        "");
+    assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER, 5, 5, 1));
+  }
+
   public void test_typeVariableScope_staticField() throws Exception {
     AnalyzeLibraryResult result = analyzeLibrary(
         "// filler filler filler filler filler filler filler filler filler filler",
@@ -5470,6 +5500,41 @@
   }
   
   /**
+   * We should resolve sub-type member only if there is only sub-type with such member.
+   * <p>
+   * http://code.google.com/p/dart/issues/detail?id=6776
+   */
+  public void test_trySubTypeMember_moreThanOneMember() throws Exception {
+    compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() {
+      @Override
+      public boolean typeChecksForInferredTypes() {
+        return true;
+      }
+    });
+    AnalyzeLibraryResult result = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class Event {}",
+        "class MouseEvent extends Event {",
+        "  int clientX;",
+        "}",
+        "class ScreenEvent extends Event {",
+        "  int clientX;",
+        "}",
+        "typedef Listener(Event event);",
+        "class Button {",
+        "  addListener(Listener listener) {}",
+        "}",
+        "main() {",
+        "  Button button = new Button();",
+        "  button.addListener((event) {",
+        "    event.clientX;",
+        "  });",
+        "}",
+        "");
+    assertErrors(result.getErrors(), errEx(TypeErrorCode.NOT_A_MEMBER_OF_INFERRED, 16, 11, 7));
+  }
+  
+  /**
    * <p>
    * http://code.google.com/p/dart/issues/detail?id=6491
    */
@@ -5625,4 +5690,20 @@
     assertErrors(result.getErrors(),
         errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 8, 9, 13));
   }
+  
+  /**
+   * <p>
+   * http://code.google.com/p/dart/issues/detail?id=6718
+   */
+  public void test_initializerInMethod() throws Exception {
+    AnalyzeLibraryResult result = analyzeLibrary(
+        "// filler filler filler filler filler filler filler filler filler filler",
+        "class A {",
+        "  var x;",
+        "  B() : x = (foo() { }) {}",
+        "}",
+        "");
+    assertErrors(result.getErrors(),
+        errEx(ResolverErrorCode.INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR, 4, 9, 15));
+  }
 }
diff --git a/dart.gyp b/dart.gyp
index 3ec8489..b76a758 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -13,6 +13,9 @@
       'actions': []
     },
     {
+      # This is the target that is built on the VM build bots.  It
+      # must depend on anything that is required by the VM test
+      # suites.
       'target_name': 'runtime',
       'type': 'none',
       'dependencies': [
@@ -21,6 +24,7 @@
         'runtime/dart-runtime.gyp:run_vm_tests',
         'runtime/dart-runtime.gyp:process_test',
         'runtime/dart-runtime.gyp:test_extension',
+        'packages',
       ],
     },
     {
@@ -104,11 +108,15 @@
       ],
     },
     {
+      # This is the target that is built on the dart2js build bots.
+      # It must depend on anything that is required by the dart2js
+      # test suites.
       'target_name': 'dart2js_bot',
       'type': 'none',
       'dependencies': [
         'third_party/v8/src/d8.gyp:d8',
         'create_sdk',
+        'packages',
       ],
     },
     {
@@ -125,5 +133,12 @@
         'samples/sample_extension/sample_extension.gyp:sample_extension',
       ],
     },
+    {
+      'target_name': 'packages',
+      'type': 'none',
+      'dependencies': [
+        'pkg/pkg.gyp:pkg_packages',
+      ],
+    },
   ],
 }
diff --git a/pkg/args/test/args_test.dart b/pkg/args/test/args_test.dart
index 10c68fe..728ff7d 100644
--- a/pkg/args/test/args_test.dart
+++ b/pkg/args/test/args_test.dart
@@ -6,8 +6,7 @@
 
 import '../../../pkg/unittest/lib/unittest.dart';
 
-// TODO(rnystrom): Use "package:" URL here when test.dart can handle pub.
-import '../lib/args.dart';
+import 'package:args/args.dart';
 
 main() {
   group('ArgParser.addFlag()', () {
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index 80f5f3c..ac92a7e 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -142,7 +142,7 @@
   // will be truncated.
   int _convert(other) {
     if (other == null) {
-      throw new NullPointerException();
+      throw new ArgumentError(null);
     } else if (other is intx) {
       return other.toInt32()._i;
     } else if (other is int) {
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
index cefb2c0..3ef0bc0 100644
--- a/pkg/fixnum/lib/src/int64.dart
+++ b/pkg/fixnum/lib/src/int64.dart
@@ -242,7 +242,7 @@
 
   int64 _promote(other) {
     if (other == null) {
-      throw new NullPointerException();
+      throw new ArgumentError(null);
     } else if (other is intx) {
       other = other.toInt64();
     } else if (other is int) {
diff --git a/pkg/fixnum/test/int_32_test.dart b/pkg/fixnum/test/int_32_test.dart
index 7ea6591..e719fa6 100644
--- a/pkg/fixnum/test/int_32_test.dart
+++ b/pkg/fixnum/test/int_32_test.dart
@@ -132,26 +132,26 @@
 
   try {
     new int32.fromInt(17) < null;
-    Expect.fail("x < null should throw NullPointerException");
-  } on NullPointerException catch (e) {
+    Expect.fail("x < null should throw ArgumentError");
+  } on ArgumentError catch (e) {
   }
 
   try {
     new int32.fromInt(17) <= null;
-    Expect.fail("x <= null should throw NullPointerException");
-  } on NullPointerException catch (e) {
+    Expect.fail("x <= null should throw ArgumentError");
+  } on ArgumentError catch (e) {
   }
 
   try {
     new int32.fromInt(17) > null;
-    Expect.fail("x > null should throw NullPointerException");
-  } on NullPointerException catch (e) {
+    Expect.fail("x > null should throw ArgumentError");
+  } on ArgumentError catch (e) {
   }
 
   try {
     new int32.fromInt(17) < null;
-    Expect.fail("x >= null should throw NullPointerException");
-  } on NullPointerException catch (e) {
+    Expect.fail("x >= null should throw ArgumentError");
+  } on ArgumentError catch (e) {
   }
 
   Expect.isFalse(new int32.fromInt(17) == null);
diff --git a/pkg/fixnum/test/int_64_test.dart b/pkg/fixnum/test/int_64_test.dart
index 65d47b3..f41f45c 100644
--- a/pkg/fixnum/test/int_64_test.dart
+++ b/pkg/fixnum/test/int_64_test.dart
@@ -145,26 +145,26 @@
 
   try {
     new int64.fromInt(17) < null;
-    Expect.fail("x < null should throw NullPointerException");
-  } on NullPointerException catch (e) {
+    Expect.fail("x < null should throw ArgumentError");
+  } on ArgumentError catch (e) {
   }
 
   try {
     new int64.fromInt(17) <= null;
-    Expect.fail("x <= null should throw NullPointerException");
-  } on NullPointerException catch (e) {
+    Expect.fail("x <= null should throw ArgumentError");
+  } on ArgumentError catch (e) {
   }
 
   try {
     new int64.fromInt(17) > null;
-    Expect.fail("x > null should throw NullPointerException");
-  } on NullPointerException catch (e) {
+    Expect.fail("x > null should throw ArgumentError");
+  } on ArgumentError catch (e) {
   }
 
   try {
     new int64.fromInt(17) < null;
-    Expect.fail("x >= null should throw NullPointerException");
-  } on NullPointerException catch (e) {
+    Expect.fail("x >= null should throw ArgumentError");
+  } on ArgumentError catch (e) {
   }
 
   Expect.isFalse(new int64.fromInt(17) == null);
diff --git a/pkg/http/lib/http.dart b/pkg/http/lib/http.dart
index 4ee2c61..ee074f7 100644
--- a/pkg/http/lib/http.dart
+++ b/pkg/http/lib/http.dart
@@ -37,11 +37,11 @@
 /// This package is designed to be composable. This makes it easy for external
 /// libraries to work with one another to add behavior to it. Libraries wishing
 /// to add behavior should create a subclass of [BaseClient] that wraps another
-/// [BaseClient] and adds the desired behavior:
+/// [Client] and adds the desired behavior:
 ///
 ///     class UserAgentClient extends http.BaseClient {
 ///       final String userAgent;
-///       final HttpClient _inner;
+///       final http.Client _inner;
 ///
 ///       UserAgentClient(this.userAgent, this._inner);
 ///
@@ -50,9 +50,6 @@
 ///         return _inner.send(request);
 ///       }
 ///     }
-///
-/// In turn, libraries using [Client] should take a [BaseClient] so that the
-/// decorated clients can be used transparently.
 
 library http;
 
@@ -65,7 +62,6 @@
 export 'src/base_client.dart';
 export 'src/base_request.dart';
 export 'src/base_response.dart';
-export 'src/curl_client.dart';
 export 'src/client.dart';
 export 'src/multipart_file.dart';
 export 'src/multipart_request.dart';
diff --git a/pkg/http/lib/src/base_client.dart b/pkg/http/lib/src/base_client.dart
index 0b9c52d..1662f00 100644
--- a/pkg/http/lib/src/base_client.dart
+++ b/pkg/http/lib/src/base_client.dart
@@ -9,6 +9,7 @@
 import 'dart:uri';
 
 import 'base_request.dart';
+import 'client.dart';
 import 'request.dart';
 import 'response.dart';
 import 'streamed_response.dart';
@@ -17,7 +18,7 @@
 /// The abstract base class for an HTTP client. This is a mixin-style class;
 /// subclasses only need to implement [send] and maybe [close], and then they
 /// get various convenience methods for free.
-abstract class BaseClient {
+abstract class BaseClient implements Client {
   /// Sends an HTTP HEAD request with the given headers to the given URL, which
   /// can be a [Uri] or a [String].
   ///
diff --git a/pkg/http/lib/src/client.dart b/pkg/http/lib/src/client.dart
index bbee58d..d60df93 100644
--- a/pkg/http/lib/src/client.dart
+++ b/pkg/http/lib/src/client.dart
@@ -8,75 +8,89 @@
 
 import 'base_client.dart';
 import 'base_request.dart';
+import 'io_client.dart';
 import 'streamed_response.dart';
 import 'utils.dart';
 
-/// An HTTP client which takes care of maintaining persistent connections across
-/// multiple requests to the same server. If you only need to send a single
-/// request, it's usually easier to use [head], [get], [post],
+/// The interface for HTTP clients that take care of maintaining persistent
+/// connections across multiple requests to the same server. If you only need to
+/// send a single request, it's usually easier to use [head], [get], [post],
 /// [put], or [delete] instead.
 ///
-/// When creating an HTTP client class with additional functionality, it's
-/// recommended that you subclass [BaseClient] and wrap another instance of
-/// [BaseClient] rather than subclassing [Client] directly. This allows all
-/// subclasses of [BaseClient] to be mutually composable.
-class Client extends BaseClient {
-  /// The underlying `dart:io` HTTP client.
-  HttpClient _inner;
+/// When creating an HTTP client class with additional functionality, you must
+/// extend [BaseClient] rather than [Client]. In most cases, you can wrap
+/// another instance of [Client] and add functionality on top of that. This
+/// allows all classes implementing [Client] to be mutually composable.
+abstract class Client {
+  /// Creates a new Client using the default implementation. This implementation
+  /// uses an underlying `dart:io` [HttpClient] to make requests.
+  factory Client() => new IOClient();
 
-  /// Creates a new HTTP client.
-  Client() : _inner = new HttpClient();
+  /// Sends an HTTP HEAD request with the given headers to the given URL, which
+  /// can be a [Uri] or a [String].
+  ///
+  /// For more fine-grained control over the request, use [send] instead.
+  Future<Response> head(url, {Map<String, String> headers});
+
+  /// Sends an HTTP GET request with the given headers to the given URL, which
+  /// can be a [Uri] or a [String].
+  ///
+  /// For more fine-grained control over the request, use [send] instead.
+  Future<Response> get(url, {Map<String, String> headers});
+
+  /// Sends an HTTP POST request with the given headers and fields to the given
+  /// URL, which can be a [Uri] or a [String]. If any fields are specified, the
+  /// content-type is automatically set to
+  /// `"application/x-www-form-urlencoded"`.
+  ///
+  /// For more fine-grained control over the request, use [send] instead.
+  Future<Response> post(url,
+      {Map<String, String> headers,
+       Map<String, String> fields});
+
+  /// Sends an HTTP PUT request with the given headers and fields to the given
+  /// URL, which can be a [Uri] or a [String]. If any fields are specified, the
+  /// content-type is automatically set to
+  /// `"application/x-www-form-urlencoded"`.
+  ///
+  /// For more fine-grained control over the request, use [send] instead.
+  Future<Response> put(url,
+      {Map<String, String> headers,
+       Map<String, String> fields});
+
+  /// Sends an HTTP DELETE request with the given headers to the given URL,
+  /// which can be a [Uri] or a [String].
+  ///
+  /// For more fine-grained control over the request, use [send] instead.
+  Future<Response> delete(url, {Map<String, String> headers});
+
+  /// Sends an HTTP GET request with the given headers to the given URL, which
+  /// can be a [Uri] or a [String], and returns a Future that completes to the
+  /// body of the response as a String.
+  ///
+  /// The Future will emit an [HttpException] if the response doesn't have a
+  /// success status code.
+  ///
+  /// For more fine-grained control over the request and response, use [send] or
+  /// [get] instead.
+  Future<String> read(url, {Map<String, String> headers});
+
+  /// Sends an HTTP GET request with the given headers to the given URL, which
+  /// can be a [Uri] or a [String], and returns a Future that completes to the
+  /// body of the response as a list of bytes.
+  ///
+  /// The Future will emit an [HttpException] if the response doesn't have a
+  /// success status code.
+  ///
+  /// For more fine-grained control over the request and response, use [send] or
+  /// [get] instead.
+  Future<Uint8List> readBytes(url, {Map<String, String> headers});
 
   /// Sends an HTTP request and asynchronously returns the response.
-  Future<StreamedResponse> send(BaseRequest request) {
-    var stream = request.finalize();
+  Future<StreamedResponse> send(BaseRequest request);
 
-    var completer = new Completer<StreamedResponse>();
-    var connection = _inner.openUrl(request.method, request.url);
-    connection.onError = (e) {
-      async.then((_) {
-        // TODO(nweiz): remove this when issue 4974 is fixed
-        if (completer.future.isComplete) throw e;
-
-        completer.completeException(e);
-      });
-    };
-
-    connection.onRequest = (underlyingRequest) {
-      underlyingRequest.contentLength = request.contentLength;
-      underlyingRequest.persistentConnection = request.persistentConnection;
-      request.headers.forEach((name, value) {
-        underlyingRequest.headers.set(name, value);
-      });
-
-      if (stream.closed) {
-        underlyingRequest.outputStream.close();
-      } else {
-        stream.pipe(underlyingRequest.outputStream);
-      }
-    };
-
-    connection.onResponse = (response) {
-      var headers = <String>{};
-      response.headers.forEach((key, value) => headers[key] = value);
-
-      completer.complete(new StreamedResponse(
-          response.inputStream,
-          response.statusCode,
-          response.contentLength,
-          headers: headers,
-          isRedirect: response.isRedirect,
-          persistentConnection: response.persistentConnection,
-          reasonPhrase: response.reasonPhrase));
-    };
-
-    return completer.future;
-  }
-
-  /// Closes the client. This terminates all active connections. If a client
-  /// remains unclosed, the Dart process may not terminate.
-  void close() {
-    if (_inner != null) _inner.shutdown();
-    _inner = null;
-  }
+  /// Closes the client and cleans up any resources associated with it. It's
+  /// important to close each client when it's done being used; failing to do so
+  /// can cause the Dart process to hang.
+  void close();
 }
diff --git a/pkg/http/lib/src/io_client.dart b/pkg/http/lib/src/io_client.dart
new file mode 100644
index 0000000..995ff3b
--- /dev/null
+++ b/pkg/http/lib/src/io_client.dart
@@ -0,0 +1,74 @@
+// 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 io_client;
+
+import 'dart:io';
+
+import 'base_client.dart';
+import 'base_request.dart';
+import 'streamed_response.dart';
+import 'utils.dart';
+
+/// A `dart:io`-based HTTP client. This is the default client.
+class IOClient extends BaseClient {
+  /// The underlying `dart:io` HTTP client.
+  HttpClient _inner;
+
+  /// Creates a new HTTP client.
+  IOClient() : _inner = new HttpClient();
+
+  /// Sends an HTTP request and asynchronously returns the response.
+  Future<StreamedResponse> send(BaseRequest request) {
+    var stream = request.finalize();
+
+    var completer = new Completer<StreamedResponse>();
+    var connection = _inner.openUrl(request.method, request.url);
+    connection.onError = (e) {
+      async.then((_) {
+        // TODO(nweiz): remove this when issue 4974 is fixed
+        if (completer.future.isComplete) throw e;
+
+        completer.completeException(e);
+      });
+    };
+
+    connection.onRequest = (underlyingRequest) {
+      underlyingRequest.contentLength = request.contentLength;
+      underlyingRequest.persistentConnection = request.persistentConnection;
+      request.headers.forEach((name, value) {
+        underlyingRequest.headers.set(name, value);
+      });
+
+      if (stream.closed) {
+        underlyingRequest.outputStream.close();
+      } else {
+        stream.pipe(underlyingRequest.outputStream);
+      }
+    };
+
+    connection.onResponse = (response) {
+      var headers = <String>{};
+      response.headers.forEach((key, value) => headers[key] = value);
+
+      completer.complete(new StreamedResponse(
+          response.inputStream,
+          response.statusCode,
+          response.contentLength,
+          headers: headers,
+          isRedirect: response.isRedirect,
+          persistentConnection: response.persistentConnection,
+          reasonPhrase: response.reasonPhrase));
+    };
+
+    return completer.future;
+  }
+
+  /// Closes the client. This terminates all active connections. If a client
+  /// remains unclosed, the Dart process may not terminate.
+  void close() {
+    if (_inner != null) _inner.shutdown();
+    _inner = null;
+  }
+}
diff --git a/pkg/http/lib/src/utils.dart b/pkg/http/lib/src/utils.dart
index 665ee1e..8431603 100644
--- a/pkg/http/lib/src/utils.dart
+++ b/pkg/http/lib/src/utils.dart
@@ -185,26 +185,3 @@
   }
   return nextElement(null);
 }
-
-/// Creates a temporary directory and passes its path to [fn]. Once the [Future]
-/// returned by [fn] completes, the temporary directory and all its contents
-/// will be deleted.
-Future withTempDir(Future fn(String path)) {
-  var tempDir;
-  var future = new Directory('').createTemp().chain((dir) {
-    tempDir = dir;
-    return fn(tempDir.path);
-  });
-  future.onComplete((_) => tempDir.delete(recursive: true));
-  return future;
-}
-
-/// Configures [future] so that its result (success or exception) is passed on
-/// to [completer].
-void chainToCompleter(Future future, Completer completer) {
-  future.handleException((e) {
-    completer.completeException(e);
-    return true;
-  });
-  future.then(completer.complete);
-}
diff --git a/pkg/http/test/request_test.dart b/pkg/http/test/request_test.dart
index 5c2d98c..319abfb 100644
--- a/pkg/http/test/request_test.dart
+++ b/pkg/http/test/request_test.dart
@@ -13,23 +13,16 @@
 
 void main() {
   test('.send', () {
-    print("This test is known to be flaky, please ignore "
-          "(debug prints below added by sgjesse@)");
-    print(".send test starting server...");
     startServer();
-    print(".send test server running");
 
     var request = new http.Request('POST', serverUrl);
     request.body = "hello";
     var future = request.send().chain((response) {
-      print(".send test response received");
       expect(response.statusCode, equals(200));
       return consumeInputStream(response.stream);
     }).transform((bytes) => new String.fromCharCodes(bytes));
     future.onComplete((_) {
-      print(".send test stopping server...");
       stopServer();
-      print(".send test server stopped");
     });
 
     expect(future, completion(parse(equals({
@@ -41,7 +34,6 @@
       },
       'body': 'hello'
     }))));
-    print(".send test started");
   });
 
   group('#contentLength', () {
diff --git a/pkg/oauth2/lib/oauth2.dart b/pkg/oauth2/lib/oauth2.dart
new file mode 100644
index 0000000..a7e9307
--- /dev/null
+++ b/pkg/oauth2/lib/oauth2.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A client library for authenticating with a remote service via OAuth2 on
+/// behalf of a user, and making authorized HTTP requests with the user's OAuth2
+/// credentials.
+///
+/// OAuth2 allows a client (the program using this library) to access and
+/// manipulate a resource that's owned by a resource owner (the end user) and
+/// lives on a remote server. The client directs the resource owner to an
+/// authorization server (usually but not always the same as the server that
+/// hosts the resource), where the resource owner tells the authorization server
+/// to give the client an access token. This token serves as proof that the
+/// client has permission to access resources on behalf of the resource owner.
+///
+/// OAuth2 provides several different methods for the client to obtain
+/// authorization. At the time of writing, this library only supports the
+/// [AuthorizationCodeGrant] method, but further methods may be added in the
+/// future. The following example uses this method to authenticate, and assumes
+/// that the library is being used by a server-side application.
+///
+///     import 'dart:io'
+///     import 'dart:uri'
+///     import 'package:oauth2/oauth2.dart' as oauth2;
+///
+///     // These URLs are endpoints that are provided by the authorization
+///     // server. They're usually included in the server's documentation of its
+///     // OAuth2 API.
+///     final authorizationEndpoint =
+///         new Uri.fromString("http://example.com/oauth2/authorization");
+///     final tokenEndpoint =
+///         new Uri.fromString("http://example.com/oauth2/token");
+///     
+///     // The authorization server will issue each client a separate client
+///     // identifier and secret, which allows the server to tell which client
+///     // is accessing it. Some servers may also have an anonymous
+///     // identifier/secret pair that any client may use.
+///     //
+///     // Note that clients whose source code or binary executable is readily
+///     // available may not be able to make sure the client secret is kept a
+///     // secret. This is fine; OAuth2 servers generally won't rely on knowing
+///     // with certainty that a client is who it claims to be.
+///     final identifier = "my client identifier";
+///     final secret = "my client secret";
+///
+///     // This is a URL on your application's server. The authorization server
+///     // will redirect the resource owner here once they've authorized the
+///     // client. The redirection will include the authorization code in the
+///     // query parameters.
+///     final redirectUrl = new Uri.fromString(
+///         "http://my-site.com/oauth2-redirect");
+///     
+///     var credentialsFile = new File("~/.myapp/credentials.json");
+///     return credentialsFile.exists().chain((exists) {
+///       // If the OAuth2 credentials have already been saved from a previous
+///       // run, we just want to reload them.
+///       if (exists) {
+///         return credentialsFile.readAsText().transform((json) {
+///           var credentials = new oauth2.Credentials.fromJson(json);
+///           return new oauth2.Client(identifier, secret, credentials);
+///         });
+///       }
+///     
+///       // If we don't have OAuth2 credentials yet, we need to get the
+///       // resource owner to authorize us. We're assuming here that we're a
+///       // command-line application.
+///       var grant = new oauth2.AuthorizationCodeGrant(
+///           identifier, secret, authorizationEndpoint, tokenEndpoint);
+///     
+///       // Redirect the resource owner to the authorization URL. This will be
+///       // a URL on the authorization server (authorizationEndpoint with some
+///       // additional query parameters). Once the resource owner has
+///       // authorized, they'll be redirected to `redirectUrl` with an
+///       // authorization code.
+///       //
+///       // `redirect` is an imaginary function that redirects the resource
+///       // owner's browser.
+///       return redirect(grant.getAuthorizationUrl(redirectUrl)).chain((_) {
+///         // Another imaginary function that listens for a request to
+///         // `redirectUrl`.
+///         return listen(redirectUrl);
+///       }).transform((request) {
+///         // Once the user is redirected to `redirectUrl`, pass the query
+///         // parameters to the AuthorizationCodeGrant. It will validate them
+///         // and extract the authorization code to create a new Client.
+///         return grant.handleAuthorizationResponse(request.queryParameters);
+///       })
+///     }).chain((client) {
+///       // Once you have a Client, you can use it just like any other HTTP
+///       // client.
+///       return client.read("http://example.com/protected-resources.txt")
+///           .transform((result) {
+///         // Once we're done with the client, save the credentials file. This
+///         // ensures that if the credentials were automatically refreshed
+///         // while using the client, the new credentials are available for the
+///         // next run of the program.
+///         return credentialsFile.open(FileMode.WRITE).chain((file) {
+///           return file.writeString(client.credentials.toJson());
+///         }).chain((file) => file.close()).transform((_) => result);
+///       });
+///     }).then(print);
+library oauth2;
+
+export 'src/authorization_code_grant.dart';
+export 'src/client.dart';
+export 'src/credentials.dart';
+export 'src/authorization_exception.dart';
+export 'src/expiration_exception.dart';
diff --git a/pkg/oauth2/lib/src/authorization_code_grant.dart b/pkg/oauth2/lib/src/authorization_code_grant.dart
new file mode 100644
index 0000000..dcb36d06
--- /dev/null
+++ b/pkg/oauth2/lib/src/authorization_code_grant.dart
@@ -0,0 +1,258 @@
+// 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 authorization_code_grant;
+
+import 'dart:uri';
+
+// TODO(nweiz): This should be a "package:" import. See issue 6745.
+import '../../../http/lib/http.dart' as http;
+
+import 'client.dart';
+import 'authorization_exception.dart';
+import 'handle_access_token_response.dart';
+import 'utils.dart';
+
+/// A class for obtaining credentials via an [authorization code grant][]. This
+/// method of authorization involves sending the resource owner to the
+/// authorization server where they will authorize the client. They're then
+/// redirected back to your server, along with an authorization code. This is
+/// used to obtain [Credentials] and create a fully-authorized [Client].
+///
+/// To use this class, you must first call [getAuthorizationUrl] to get the URL
+/// to which to redirect the resource owner. Then once they've been redirected
+/// back to your application, call [handleAuthorizationResponse] or
+/// [handleAuthorizationCode] to process the authorization server's response and
+/// construct a [Client].
+///
+/// [authorization code grant]: http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.1
+class AuthorizationCodeGrant {
+  /// An enum value for [_state] indicating that [getAuthorizationUrl] has not
+  /// yet been called for this grant.
+  static const _INITIAL_STATE = 0;
+
+  // An enum value for [_state] indicating that [getAuthorizationUrl] has been
+  // called but neither [handleAuthorizationResponse] nor
+  // [handleAuthorizationCode] has been called.
+  static const _AWAITING_RESPONSE_STATE = 1;
+
+  // An enum value for [_state] indicating that [getAuthorizationUrl] and either
+  // [handleAuthorizationResponse] or [handleAuthorizationCode] have been
+  // called.
+  static const _FINISHED_STATE = 2;
+
+  /// The client identifier for this client. The authorization server will issue
+  /// each client a separate client identifier and secret, which allows the
+  /// server to tell which client is accessing it. Some servers may also have an
+  /// anonymous identifier/secret pair that any client may use.
+  ///
+  /// This is usually global to the program using this library.
+  final String identifier;
+
+  /// The client secret for this client. The authorization server will issue
+  /// each client a separate client identifier and secret, which allows the
+  /// server to tell which client is accessing it. Some servers may also have an
+  /// anonymous identifier/secret pair that any client may use.
+  ///
+  /// This is usually global to the program using this library.
+  ///
+  /// Note that clients whose source code or binary executable is readily
+  /// available may not be able to make sure the client secret is kept a secret.
+  /// This is fine; OAuth2 servers generally won't rely on knowing with
+  /// certainty that a client is who it claims to be.
+  final String secret;
+
+  /// A URL provided by the authorization server that serves as the base for the
+  /// URL that the resource owner will be redirected to to authorize this
+  /// client. This will usually be listed in the authorization server's
+  /// OAuth2 API documentation.
+  final Uri authorizationEndpoint;
+
+  /// A URL provided by the authorization server that this library uses to
+  /// obtain long-lasting credentials. This will usually be listed in the
+  /// authorization server's OAuth2 API documentation.
+  final Uri tokenEndpoint;
+
+  /// The HTTP client used to make HTTP requests.
+  http.Client _httpClient;
+
+  /// The URL to which the resource owner will be redirected after they
+  /// authorize this client with the authorization server.
+  Uri _redirectEndpoint;
+
+  /// The scopes that the client is requesting access to.
+  List<String> _scopes;
+
+  /// An opaque string that users of this library may specify that will be
+  /// included in the response query parameters.
+  String _stateString;
+
+  /// The current state of the grant object. One of [_INITIAL_STATE],
+  /// [_AWAITING_RESPONSE_STATE], or [_FINISHED_STATE].
+  int _state = _INITIAL_STATE;
+
+  /// Creates a new grant.
+  ///
+  /// [httpClient] is used for all HTTP requests made by this grant, as well as
+  /// those of the [Client] is constructs.
+  AuthorizationCodeGrant(
+      this.identifier,
+      this.secret,
+      this.authorizationEndpoint,
+      this.tokenEndpoint,
+      {http.Client httpClient})
+    : _httpClient = httpClient == null ? new http.Client() : httpClient;
+
+  /// Returns the URL to which the resource owner should be redirected to
+  /// authorize this client. The resource owner will then be redirected to
+  /// [redirect], which should point to a server controlled by the client. This
+  /// redirect will have additional query parameters that should be passed to
+  /// [handleAuthorizationResponse].
+  ///
+  /// The specific permissions being requested from the authorization server may
+  /// be specified via [scopes]. The scope strings are specific to the
+  /// authorization server and may be found in its documentation. Note that you
+  /// may not be granted access to every scope you request; you may check the
+  /// [Credentials.scopes] field of [Client.credentials] to see which scopes you
+  /// were granted.
+  ///
+  /// An opaque [state] string may also be passed that will be present in the
+  /// query parameters provided to the redirect URL.
+  ///
+  /// It is a [StateError] to call this more than once.
+  Uri getAuthorizationUrl(Uri redirect,
+      {List<String> scopes: const <String>[], String state}) {
+    if (_state != _INITIAL_STATE) {
+      throw new StateError('The authorization URL has already been generated.');
+    }
+    _state = _AWAITING_RESPONSE_STATE;
+
+    this._redirectEndpoint = redirect;
+    this._scopes = scopes;
+    this._stateString = state;
+    var parameters = {
+      "response_type": "code",
+      "client_id": this.identifier,
+      "redirect_uri": redirect.toString()
+    };
+
+    if (state != null) parameters['state'] = state;
+    if (!scopes.isEmpty) parameters['scope'] = Strings.join(scopes, ' ');
+
+    return addQueryParameters(this.authorizationEndpoint, parameters);
+  }
+
+  /// Processes the query parameters added to a redirect from the authorization
+  /// server. Note that this "response" is not an HTTP response, but rather the
+  /// data passed to a server controlled by the client as query parameters on
+  /// the redirect URL.
+  ///
+  /// It is a [StateError] to call this more than once, to call it before
+  /// [getAuthorizationUrl] is called, or to call it after
+  /// [handleAuthorizationCode] is called.
+  ///
+  /// Throws [FormatError] if [parameters] is invalid according to the OAuth2
+  /// spec or if the authorization server otherwise provides invalid responses.
+  /// If `state` was passed to [getAuthorizationUrl], this will throw a
+  /// [FormatError] if the `state` parameter doesn't match the original value.
+  ///
+  /// Throws [AuthorizationException] if the authorization fails.
+  Future<Client> handleAuthorizationResponse(Map<String, String> parameters) {
+    return async.chain((_) {
+      if (_state == _INITIAL_STATE) {
+        throw new StateError(
+            'The authorization URL has not yet been generated.');
+      } else if (_state == _FINISHED_STATE) {
+        throw new StateError(
+            'The authorization code has already been received.');
+      }
+      _state = _FINISHED_STATE;
+
+      if (_stateString != null) {
+        if (!parameters.containsKey('state')) {
+          throw new FormatException('Invalid OAuth response for '
+              '"$authorizationEndpoint": parameter "state" expected to be '
+              '"$_stateString", was missing.');
+        } else if (parameters['state'] != _stateString) {
+          throw new FormatException('Invalid OAuth response for '
+              '"$authorizationEndpoint": parameter "state" expected to be '
+              '"$_stateString", was "${parameters['state']}".');
+        }
+      }
+
+      if (parameters.containsKey('error')) {
+        var description = parameters['error_description'];
+        var uriString = parameters['error_uri'];
+        var uri = uriString == null ? null : new Uri.fromString(uriString);
+        throw new AuthorizationException(parameters['error'], description, uri);
+      } else if (!parameters.containsKey('code')) {
+        throw new FormatException('Invalid OAuth response for '
+            '"$authorizationEndpoint": did not contain required parameter '
+            '"code".');
+      }
+
+      return _handleAuthorizationCode(parameters['code']);
+    });
+  }
+
+  /// Processes an authorization code directly. Usually
+  /// [handleAuthorizationResponse] is preferable to this method, since it
+  /// validates all of the query parameters. However, some authorization servers
+  /// allow the user to copy and paste an authorization code into a command-line
+  /// application, in which case this method must be used.
+  ///
+  /// It is a [StateError] to call this more than once, to call it before
+  /// [getAuthorizationUrl] is called, or to call it after
+  /// [handleAuthorizationCode] is called.
+  ///
+  /// Throws [FormatError] if the authorization server provides invalid
+  /// responses while retrieving credentials.
+  ///
+  /// Throws [AuthorizationException] if the authorization fails.
+  Future<Client> handleAuthorizationCode(String authorizationCode) {
+    return async.chain((_) {
+      if (_state == _INITIAL_STATE) {
+        throw new StateError(
+            'The authorization URL has not yet been generated.');
+      } else if (_state == _FINISHED_STATE) {
+        throw new StateError(
+            'The authorization code has already been received.');
+      }
+      _state = _FINISHED_STATE;
+
+      return _handleAuthorizationCode(authorizationCode);
+    });
+  }
+
+  /// This works just like [handleAuthorizationCode], except it doesn't validate
+  /// the state beforehand.
+  Future<Client> _handleAuthorizationCode(String authorizationCode) {
+    var startTime = new Date.now();
+    return _httpClient.post(this.tokenEndpoint, fields: {
+      "grant_type": "authorization_code",
+      "code": authorizationCode,
+      "redirect_uri": this._redirectEndpoint.toString(),
+      // TODO(nweiz): the spec recommends that HTTP basic auth be used in
+      // preference to form parameters, but Google doesn't support that. Should
+      // it be configurable?
+      "client_id": this.identifier,
+      "client_secret": this.secret
+    }).transform((response) {
+      var credentials = handleAccessTokenResponse(
+          response, tokenEndpoint, startTime, _scopes);
+      return new Client(
+          this.identifier, this.secret, credentials, httpClient: _httpClient);
+    });
+  }
+
+  /// Closes the grant and frees its resources.
+  ///
+  /// This will close the underlying HTTP client, which is shared by the
+  /// [Client] created by this grant, so it's not safe to close the grant and
+  /// continue using the client.
+  void close() {
+    if (_httpClient != null) _httpClient.close();
+    _httpClient = null;
+  }
+}
diff --git a/pkg/oauth2/lib/src/authorization_exception.dart b/pkg/oauth2/lib/src/authorization_exception.dart
new file mode 100644
index 0000000..1062aa9
--- /dev/null
+++ b/pkg/oauth2/lib/src/authorization_exception.dart
@@ -0,0 +1,37 @@
+// 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 authorization_exception;
+
+import 'dart:io';
+import 'dart:uri';
+
+/// An exception raised when OAuth2 authorization fails.
+class AuthorizationException implements Exception {
+  /// The name of the error. Possible names are enumerated in [the spec][].
+  ///
+  /// [the spec]: http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-5.2
+  final String error;
+
+  /// The description of the error, provided by the server. Defaults to null.
+  final String description;
+
+  /// A URI for a page that describes the error in more detail, provided by the
+  /// server. Defaults to null.
+  final Uri uri;
+
+  /// Creates an AuthorizationException.
+  AuthorizationException(this.error, this.description, this.uri);
+
+  /// Provides a string description of the AuthorizationException.
+  String toString() {
+    var header = 'OAuth authorization error ($error)';
+    if (description != null) {
+      header = '$header: $description';
+    } else if (uri != null) {
+      header = '$header: $uri';
+    }
+    return '$header.';
+  }
+}
diff --git a/pkg/oauth2/lib/src/client.dart b/pkg/oauth2/lib/src/client.dart
new file mode 100644
index 0000000..7322afa
--- /dev/null
+++ b/pkg/oauth2/lib/src/client.dart
@@ -0,0 +1,124 @@
+// 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 client;
+
+import 'dart:uri';
+
+import '../../../http/lib/http.dart' as http;
+
+import 'credentials.dart';
+import 'expiration_exception.dart';
+import 'utils.dart';
+
+// TODO(nweiz): Add an onCredentialsRefreshed event once we have some event
+// infrastructure.
+/// An OAuth2 client. This acts as a drop-in replacement for an [http.Client],
+/// while sending OAuth2 authorization credentials along with each request.
+///
+/// The client also automatically refreshes its credentials if possible. When it
+/// makes a request, if its credentials are expired, it will first refresh them.
+/// This means that any request may throw an [AuthorizationException] if the
+/// refresh is not authorized for some reason, a [FormatException] if the
+/// authorization server provides ill-formatted responses, or an
+/// [ExpirationException] if the credentials are expired and can't be refreshed.
+///
+/// Currently this client doesn't attempt to identify errors from the resource
+/// server that are caused by authentication failure. However, it may throw
+/// [AuthorizationException]s for such errors in the future.
+///
+/// If you already have a set of [Credentials], you can construct a [Client]
+/// directly. However, in order to first obtain the credentials, you must
+/// authorize. At the time of writing, the only authorization method this
+/// library supports is [AuthorizationCodeGrant].
+class Client extends http.BaseClient {
+  /// The client identifier for this client. The authorization server will issue
+  /// each client a separate client identifier and secret, which allows the
+  /// server to tell which client is accessing it. Some servers may also have an
+  /// anonymous identifier/secret pair that any client may use.
+  ///
+  /// This is usually global to the program using this library.
+  final String identifier;
+
+  /// The client secret for this client. The authorization server will issue
+  /// each client a separate client identifier and secret, which allows the
+  /// server to tell which client is accessing it. Some servers may also have an
+  /// anonymous identifier/secret pair that any client may use.
+  ///
+  /// This is usually global to the program using this library.
+  ///
+  /// Note that clients whose source code or binary executable is readily
+  /// available may not be able to make sure the client secret is kept a secret.
+  /// This is fine; OAuth2 servers generally won't rely on knowing with
+  /// certainty that a client is who it claims to be.
+  final String secret;
+
+  /// The credentials this client uses to prove to the resource server that it's
+  /// authorized. This may change from request to request as the credentials
+  /// expire and the client refreshes them automatically.
+  Credentials get credentials => _credentials;
+  Credentials _credentials;
+
+  /// The underlying HTTP client.
+  http.Client _httpClient;
+
+  /// Creates a new client from a pre-existing set of credentials. When
+  /// authorizing a client for the first time, you should use
+  /// [AuthorizationCodeGrant] instead of constructing a [Client] directly.
+  ///
+  /// [httpClient] is the underlying client that this forwards requests to after
+  /// adding authorization credentials to them.
+  Client(
+      this.identifier,
+      this.secret,
+      this._credentials,
+      {http.Client httpClient})
+    : _httpClient = httpClient == null ? new http.Client() : httpClient;
+
+  /// Sends an HTTP request with OAuth2 authorization credentials attached. This
+  /// will also automatically refresh this client's [Credentials] before sending
+  /// the request if necessary.
+  Future<http.StreamedResponse> send(http.BaseRequest request) {
+    return async.chain((_) {
+      if (!credentials.isExpired) return new Future.immediate(null);
+      if (!credentials.canRefresh) throw new ExpirationException(credentials);
+      return refreshCredentials();
+    }).chain((_) {
+      request.headers['authorization'] = "Bearer ${credentials.accessToken}";
+      return _httpClient.send(request);
+    });
+    // TODO(nweiz): parse 401 errors that are caused by OAuth errors here.
+  }
+
+  /// Explicitly refreshes this client's credentials. Returns this client.
+  ///
+  /// This will throw a [StateError] if the [Credentials] can't be refreshed, an
+  /// [AuthorizationException] if refreshing the credentials fails, or a
+  /// [FormatError] if the authorization server returns invalid responses.
+  ///
+  /// You may request different scopes than the default by passing in
+  /// [newScopes]. These must be a subset of the scopes in the
+  /// [Credentials.scopes] field of [Client.credentials].
+  Future<Client> refreshCredentials([List<String> newScopes]) {
+    return async.chain((_) {
+      if (!credentials.canRefresh) {
+        var prefix = "OAuth credentials";
+        if (credentials.isExpired) prefix = "$prefix have expired and";
+        throw new StateError("$prefix can't be refreshed.");
+      }
+
+      return credentials.refresh(identifier, secret,
+          newScopes: newScopes, httpClient: _httpClient);
+    }).transform((credentials) {
+      _credentials = credentials;
+      return this;
+    });
+  }
+
+  /// Closes this client and its underlying HTTP client.
+  void close() {
+    if (_httpClient != null) _httpClient.close();
+    _httpClient = null;
+  }
+}
diff --git a/pkg/oauth2/lib/src/credentials.dart b/pkg/oauth2/lib/src/credentials.dart
new file mode 100644
index 0000000..89af777
--- /dev/null
+++ b/pkg/oauth2/lib/src/credentials.dart
@@ -0,0 +1,191 @@
+// 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 credentials;
+
+import 'dart:json';
+import 'dart:uri';
+
+import '../../../http/lib/http.dart' as http;
+import 'handle_access_token_response.dart';
+import 'utils.dart';
+
+/// Credentials that prove that a client is allowed to access a resource on the
+/// resource owner's behalf. These credentials are long-lasting and can be
+/// safely persisted across multiple runs of the program.
+///
+/// Many authorization servers will attach an expiration date to a set of
+/// credentials, along with a token that can be used to refresh the credentials
+/// once they've expired. The [Client] will automatically refresh its
+/// credentials when necessary. It's also possible to explicitly refresh them
+/// via [Client.refreshCredentials] or [Credentials.refresh].
+///
+/// Note that a given set of credentials can only be refreshed once, so be sure
+/// to save the refreshed credentials for future use.
+class Credentials {
+  /// The token that is sent to the resource server to prove the authorization
+  /// of a client.
+  final String accessToken;
+
+  /// The token that is sent to the authorization server to refresh the
+  /// credentials. This is optional.
+  final String refreshToken;
+
+  /// The URL of the authorization server endpoint that's used to refresh the
+  /// credentials. This is optional.
+  final Uri tokenEndpoint;
+
+  /// The specific permissions being requested from the authorization server.
+  /// The scope strings are specific to the authorization server and may be
+  /// found in its documentation.
+  final List<String> scopes;
+
+  /// The date at which these credentials will expire. This is likely to be a
+  /// few seconds earlier than the server's idea of the expiration date.
+  final Date expiration;
+
+  /// Whether or not these credentials have expired. Note that it's possible the
+  /// 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 Date.now() > expiration;
+
+  /// Whether it's possible to refresh these credentials.
+  bool get canRefresh => refreshToken != null && tokenEndpoint != null;
+
+  /// Creates a new set of credentials.
+  ///
+  /// This class is usually not constructed directly; rather, it's accessed via
+  /// [Client.credentials] after a [Client] is created by
+  /// [AuthorizationCodeGrant]. Alternately, it may be loaded from a serialized
+  /// form via [Credentials.fromJson].
+  Credentials(
+      this.accessToken,
+      [this.refreshToken,
+       this.tokenEndpoint,
+       this.scopes,
+       this.expiration]);
+
+  /// Loads a set of credentials from a JSON-serialized form. Throws
+  /// [FormatException] if the JSON is incorrectly formatted.
+  factory Credentials.fromJson(String json) {
+    void validate(bool condition, String message) {
+      if (condition) return;
+      throw new FormatException(
+          "Failed to load credentials: $message.\n\n$json");
+    }
+
+    var parsed;
+    try {
+      parsed = JSON.parse(json);
+    } catch (e) {
+      // TODO(nweiz): narrow this catch clause once issue 6775 is fixed.
+      validate(false, 'invalid JSON');
+    }
+
+    validate(parsed is Map, 'was not a JSON map');
+    validate(parsed.containsKey('accessToken'),
+        'did not contain required field "accessToken"');
+    validate(parsed['accessToken'] is String,
+        'required field "accessToken" was not a string, was '
+        '${parsed["accessToken"]}');
+
+
+    for (var stringField in ['refreshToken', 'tokenEndpoint']) {
+      var value = parsed[stringField];
+      validate(value == null || value is String,
+          'field "$stringField" was not a string, was "$value"');
+    }
+
+    var scopes = parsed['scopes'];
+    validate(scopes == null || scopes is List,
+        'field "scopes" was not a list, was "$scopes"');
+
+    var tokenEndpoint = parsed['tokenEndpoint'];
+    if (tokenEndpoint != null) {
+      tokenEndpoint = new Uri.fromString(tokenEndpoint);
+    }
+    var expiration = parsed['expiration'];
+    if (expiration != null) {
+      validate(expiration is int,
+          'field "expiration" was not an int, was "$expiration"');
+      expiration = new Date.fromMillisecondsSinceEpoch(expiration);
+    }
+
+    return new Credentials(
+        parsed['accessToken'],
+        parsed['refreshToken'],
+        tokenEndpoint,
+        scopes,
+        expiration);
+  }
+
+  /// Serializes a set of credentials to JSON. Nothing is guaranteed about the
+  /// output except that it's valid JSON and compatible with
+  /// [Credentials.toJson].
+  String toJson() => JSON.stringify({
+    'accessToken': accessToken,
+    'refreshToken': refreshToken,
+    'tokenEndpoint': tokenEndpoint == null ? null : tokenEndpoint.toString(),
+    'scopes': scopes,
+    'expiration': expiration == null ? null : expiration.millisecondsSinceEpoch
+  });
+
+  /// Returns a new set of refreshed credentials. See [Client.identifier] and
+  /// [Client.secret] for explanations of those parameters.
+  ///
+  /// You may request different scopes than the default by passing in
+  /// [newScopes]. These must be a subset of [scopes].
+  ///
+  /// This will throw a [StateError] if these credentials can't be refreshed, an
+  /// [AuthorizationException] if refreshing the credentials fails, or a
+  /// [FormatError] if the authorization server returns invalid responses.
+  Future<Credentials> refresh(
+      String identifier,
+      String secret,
+      {List<String> newScopes,
+       http.Client httpClient}) {
+    var scopes = this.scopes;
+    if (newScopes != null) scopes = newScopes;
+    if (scopes == null) scopes = <String>[];
+    if (httpClient == null) httpClient = new http.Client();
+
+    var startTime = new Date.now();
+    return async.chain((_) {
+      if (refreshToken == null) {
+        throw new StateError("Can't refresh credentials without a refresh "
+            "token.");
+      } else if (tokenEndpoint == null) {
+        throw new StateError("Can't refresh credentials without a token "
+            "endpoint.");
+      }
+
+      var fields = {
+        "grant_type": "refresh_token",
+        "refresh_token": refreshToken,
+        // TODO(nweiz): the spec recommends that HTTP basic auth be used in
+        // preference to form parameters, but Google doesn't support that.
+        // Should it be configurable?
+        "client_id": identifier,
+        "client_secret": secret
+      };
+      if (!scopes.isEmpty) fields["scope"] = Strings.join(scopes, ' ');
+
+      return httpClient.post(tokenEndpoint, fields: fields);
+    }).transform((response) {
+      return handleAccessTokenResponse(
+          response, tokenEndpoint, startTime, scopes);
+    }).transform((credentials) {
+      // The authorization server may issue a new refresh token. If it doesn't,
+      // we should re-use the one we already have.
+      if (credentials.refreshToken != null) return credentials;
+      return new Credentials(
+          credentials.accessToken,
+          this.refreshToken,
+          credentials.tokenEndpoint,
+          credentials.scopes,
+          credentials.expiration);
+    });
+  }
+}
diff --git a/pkg/oauth2/lib/src/expiration_exception.dart b/pkg/oauth2/lib/src/expiration_exception.dart
new file mode 100644
index 0000000..8c8ad1f
--- /dev/null
+++ b/pkg/oauth2/lib/src/expiration_exception.dart
@@ -0,0 +1,22 @@
+// 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 expiration_exception;
+
+import 'dart:io';
+
+import 'credentials.dart';
+
+/// An exception raised when attempting to use expired OAuth2 credentials.
+class ExpirationException implements Exception {
+  /// The expired credentials.
+  final Credentials credentials;
+
+  /// Creates an ExpirationException.
+  ExpirationException(this.credentials);
+
+  /// Provides a string description of the ExpirationException.
+  String toString() =>
+    "OAuth2 credentials have expired and can't be refreshed.";
+}
diff --git a/pkg/oauth2/lib/src/handle_access_token_response.dart b/pkg/oauth2/lib/src/handle_access_token_response.dart
new file mode 100644
index 0000000..cb08d8f
--- /dev/null
+++ b/pkg/oauth2/lib/src/handle_access_token_response.dart
@@ -0,0 +1,145 @@
+// 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 handle_access_token_response;
+
+import 'dart:io';
+import 'dart:json';
+import 'dart:uri';
+
+import '../../../http/lib/http.dart' as http;
+
+import 'credentials.dart';
+import 'authorization_exception.dart';
+
+/// The amount of time, in seconds, to add as a "grace period" for credential
+/// expiration. This allows credential expiration checks to remain valid for a
+/// reasonable amount of time.
+const _EXPIRATION_GRACE = 10;
+
+/// Handles a response from the authorization server that contains an access
+/// token. This response format is common across several different components of
+/// the OAuth2 flow.
+Credentials handleAccessTokenResponse(
+    http.Response response,
+    Uri tokenEndpoint,
+    Date startTime,
+    List<String> scopes) {
+  if (response.statusCode != 200) _handleErrorResponse(response, tokenEndpoint);
+
+  void validate(bool condition, String message) =>
+    _validate(response, tokenEndpoint, condition, message);
+
+  var contentType = response.headers['content-type'];
+  if (contentType != null) {
+    contentType = new ContentType.fromString(contentType);
+  }
+  validate(contentType != null && contentType.value == "application/json",
+      'content-type was "$contentType", expected "application/json"');
+
+  var parameters;
+  try {
+    parameters = JSON.parse(response.body);
+  } catch (e) {
+    // TODO(nweiz): narrow this catch clause once issue 6775 is fixed.
+    validate(false, 'invalid JSON');
+  }
+
+  for (var requiredParameter in ['access_token', 'token_type']) {
+    validate(parameters.containsKey(requiredParameter),
+        'did not contain required parameter "$requiredParameter"');
+    validate(parameters[requiredParameter] is String,
+        'required parameter "$requiredParameter" was not a string, was '
+        '"${parameters[requiredParameter]}"');
+  }
+
+  // TODO(nweiz): support the "mac" token type
+  // (http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01)
+  validate(parameters['token_type'].toLowerCase() == 'bearer',
+      '"$tokenEndpoint": unknown token type "${parameters['token_type']}"');
+
+  var expiresIn = parameters['expires_in'];
+  validate(expiresIn == null || expiresIn is int,
+      'parameter "expires_in" was not an int, was "$expiresIn"');
+
+  for (var name in ['refresh_token', 'scope']) {
+    var value = parameters[name];
+    validate(value == null || value is String,
+        'parameter "$name" was not a string, was "$value"');
+  }
+
+  var scope = parameters['scope'];
+  if (scope != null) scopes = scope.split(" ");
+
+  var expiration = expiresIn == null ? null :
+      startTime.add(new Duration(seconds: expiresIn - _EXPIRATION_GRACE));
+
+  return new Credentials(
+      parameters['access_token'],
+      parameters['refresh_token'],
+      tokenEndpoint,
+      scopes,
+      expiration);
+}
+
+/// Throws the appropriate exception for an error response from the
+/// authorization server.
+void _handleErrorResponse(http.Response response, Uri tokenEndpoint) {
+  void validate(bool condition, String message) =>
+    _validate(response, tokenEndpoint, condition, message);
+
+  // OAuth2 mandates a 400 or 401 response code for access token error
+  // responses. If it's not a 400 reponse, the server is either broken or
+  // off-spec.
+  if (response.statusCode != 400 && response.statusCode != 401) {
+    var reason = '';
+    if (response.reasonPhrase != null && !response.reasonPhrase.isEmpty) {
+      ' ${response.reasonPhrase}';
+    }
+    throw new FormatException('OAuth request for "$tokenEndpoint" failed '
+        'with status ${response.statusCode}$reason.\n\n${response.body}');
+  }
+
+  var contentType = response.headers['content-type'];
+  if (contentType != null) {
+    contentType = new ContentType.fromString(contentType);
+  }
+  validate(contentType != null && contentType.value == "application/json",
+      'content-type was "$contentType", expected "application/json"');
+
+  var parameters;
+  try {
+    parameters = JSON.parse(response.body);
+  } catch (e) {
+    // TODO(nweiz): narrow this catch clause once issue 6775 is fixed.
+    validate(false, 'invalid JSON');
+  }
+
+  validate(parameters.containsKey('error'),
+      'did not contain required parameter "error"');
+  validate(parameters["error"] is String,
+      'required parameter "error" was not a string, was '
+      '"${parameters["error"]}"');
+
+  for (var name in ['error_description', 'error_uri']) {
+    var value = parameters[name];
+    validate(value == null || value is String,
+        'parameter "$name" was not a string, was "$value"');
+  }
+
+  var description = parameters['error_description'];
+  var uriString = parameters['error_uri'];
+  var uri = uriString == null ? null : new Uri.fromString(uriString);
+  throw new AuthorizationException(parameters['error'], description, uri);
+}
+
+void _validate(
+    http.Response response,
+    Uri tokenEndpoint,
+    bool condition,
+    String message) {
+  if (condition) return;
+  throw new FormatException('Invalid OAuth response for "$tokenEndpoint": '
+      '$message.\n\n${response.body}');
+}
diff --git a/pkg/oauth2/lib/src/utils.dart b/pkg/oauth2/lib/src/utils.dart
new file mode 100644
index 0000000..583a5bc
--- /dev/null
+++ b/pkg/oauth2/lib/src/utils.dart
@@ -0,0 +1,73 @@
+// 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 utils;
+
+import 'dart:uri';
+import 'dart:isolate';
+import 'dart:crypto';
+
+/// Adds additional query parameters to [url], overwriting the original
+/// parameters if a name conflict occurs.
+Uri addQueryParameters(Uri url, Map<String, String> parameters) {
+  var queryMap = queryToMap(url.query);
+  mapAddAll(queryMap, parameters);
+  return url.resolve("?${mapToQuery(queryMap)}");
+}
+
+/// Convert a URL query string (or `application/x-www-form-urlencoded` body)
+/// into a [Map] from parameter names to values.
+Map<String, String> queryToMap(String queryList) {
+  var map = <String>{};
+  for (var pair in queryList.split("&")) {
+    var split = split1(pair, "=");
+    if (split.isEmpty) continue;
+    var key = urlDecode(split[0]);
+    var value = split.length > 1 ? urlDecode(split[1]) : "";
+    map[key] = value;
+  }
+  return map;
+}
+
+/// Convert a [Map] from parameter names to values to a URL query string.
+String mapToQuery(Map<String, String> map) {
+  var pairs = <List<String>>[];
+  map.forEach((key, value) {
+    key = encodeUriComponent(key);
+    value = (value == null || value.isEmpty) ? null : encodeUriComponent(value);
+    pairs.add([key, value]);
+  });
+  return Strings.join(pairs.map((pair) {
+    if (pair[1] == null) return pair[0];
+    return "${pair[0]}=${pair[1]}";
+  }), "&");
+}
+
+/// Add all key/value pairs from [source] to [destination], overwriting any
+/// pre-existing values.
+void mapAddAll(Map destination, Map source) =>
+  source.forEach((key, value) => destination[key] = value);
+
+/// Decode a URL-encoded string. Unlike [decodeUriComponent], this includes
+/// replacing `+` with ` `.
+String urlDecode(String encoded) =>
+  decodeUriComponent(encoded.replaceAll("+", " "));
+
+/// Like [String.split], but only splits on the first occurrence of the pattern.
+/// This will always return a list of two elements or fewer.
+List<String> split1(String toSplit, String pattern) {
+  if (toSplit.isEmpty) return <String>[];
+
+  var index = toSplit.indexOf(pattern);
+  if (index == -1) return [toSplit];
+  return [toSplit.substring(0, index),
+      toSplit.substring(index + pattern.length)];
+}
+
+/// Returns a [Future] that asynchronously completes to `null`.
+Future get async {
+  var completer = new Completer();
+  new Timer(0, (_) => completer.complete(null));
+  return completer.future;
+}
diff --git a/pkg/oauth2/test/authorization_code_grant_test.dart b/pkg/oauth2/test/authorization_code_grant_test.dart
new file mode 100644
index 0000000..c4ccc21
--- /dev/null
+++ b/pkg/oauth2/test/authorization_code_grant_test.dart
@@ -0,0 +1,196 @@
+// 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 authorization_code_grant_test;
+
+import 'dart:io';
+import 'dart:json';
+import 'dart:uri';
+
+import '../../unittest/lib/unittest.dart';
+import '../../http/lib/http.dart' as http;
+import '../../http/lib/testing.dart';
+import '../lib/oauth2.dart' as oauth2;
+import 'utils.dart';
+
+final redirectUrl = new Uri.fromString('http://example.com/redirect');
+
+ExpectClient client;
+
+oauth2.AuthorizationCodeGrant grant;
+
+void createGrant() {
+  client = new ExpectClient();
+  grant = new oauth2.AuthorizationCodeGrant(
+      'identifier',
+      'secret',
+      new Uri.fromString('https://example.com/authorization'),
+      new Uri.fromString('https://example.com/token'),
+      httpClient: client);
+}
+
+void main() {
+  group('.getAuthorizationUrl', () {
+    setUp(createGrant);
+
+    test('builds the correct URL', () {
+      expect(grant.getAuthorizationUrl(redirectUrl).toString(),
+          equals('https://example.com/authorization'
+              '?response_type=code'
+              '&client_id=identifier'
+              '&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'));
+    });
+
+    test('builds the correct URL with scopes', () {
+      var authorizationUrl = grant.getAuthorizationUrl(
+          redirectUrl, scopes: ['scope', 'other/scope']);
+      expect(authorizationUrl.toString(),
+          equals('https://example.com/authorization'
+              '?response_type=code'
+              '&client_id=identifier'
+              '&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'
+              '&scope=scope%20other%2Fscope'));
+    });
+
+    test('builds the correct URL with state', () {
+      var authorizationUrl = grant.getAuthorizationUrl(
+          redirectUrl, state: 'state');
+      expect(authorizationUrl.toString(),
+          equals('https://example.com/authorization'
+              '?response_type=code'
+              '&client_id=identifier'
+              '&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'
+              '&state=state'));
+    });
+
+    test('merges with existing query parameters', () {
+      grant = new oauth2.AuthorizationCodeGrant(
+          'identifier',
+          'secret',
+          new Uri.fromString('https://example.com/authorization?query=value'),
+          new Uri.fromString('https://example.com/token'),
+          httpClient: client);
+
+      var authorizationUrl = grant.getAuthorizationUrl(redirectUrl);
+      expect(authorizationUrl.toString(),
+          equals('https://example.com/authorization'
+              '?query=value'
+              '&response_type=code'
+              '&client_id=identifier'
+              '&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect'));
+    });
+
+    test("can't be called twice", () {
+      grant.getAuthorizationUrl(redirectUrl);
+      expect(() => grant.getAuthorizationUrl(redirectUrl), throwsStateError);
+    });
+  });
+
+  group('.handleAuthorizationResponse', () {
+    setUp(createGrant);
+
+    test("can't be called before .getAuthorizationUrl", () {
+      expect(grant.handleAuthorizationResponse({}), throwsStateError);
+    });
+
+    test("can't be called twice", () {
+      grant.getAuthorizationUrl(redirectUrl);
+      grant.handleAuthorizationResponse({'code': 'auth code'});
+      expect(grant.handleAuthorizationResponse({'code': 'auth code'}),
+          throwsStateError);
+    });
+
+    test('must have a state parameter if the authorization URL did', () {
+      grant.getAuthorizationUrl(redirectUrl, state: 'state');
+      expect(grant.handleAuthorizationResponse({'code': 'auth code'}),
+          throwsFormatException);
+    });
+
+    test('must have the same state parameter the authorization URL did', () {
+      grant.getAuthorizationUrl(redirectUrl, state: 'state');
+      expect(grant.handleAuthorizationResponse({
+        'code': 'auth code',
+        'state': 'other state'
+      }), throwsFormatException);
+    });
+
+    test('must have a code parameter', () {
+      grant.getAuthorizationUrl(redirectUrl);
+      expect(grant.handleAuthorizationResponse({}), throwsFormatException);
+    });
+
+    test('with an error parameter throws an AuthorizationException', () {
+      grant.getAuthorizationUrl(redirectUrl);
+      expect(grant.handleAuthorizationResponse({'error': 'invalid_request'}),
+          throwsAuthorizationException);
+    });
+
+    test('sends an authorization code request', () {
+      grant.getAuthorizationUrl(redirectUrl);
+      client.expectRequest((request) {
+        expect(request.method, equals('POST'));
+        expect(request.url.toString(), equals(grant.tokenEndpoint.toString()));
+        expect(request.bodyFields, equals({
+          'grant_type': 'authorization_code',
+          'code': 'auth code',
+          'redirect_uri': redirectUrl.toString(),
+          'client_id': 'identifier',
+          'client_secret': 'secret'
+        }));
+
+        return new Future.immediate(new http.Response(JSON.stringify({
+          'access_token': 'access token',
+          'token_type': 'bearer',
+        }), 200, headers: {'content-type': 'application/json'}));
+      });
+
+      expect(grant.handleAuthorizationResponse({'code': 'auth code'}),
+          completion(predicate((client) {
+            expect(client.credentials.accessToken, equals('access token'));
+            return true;
+          })));
+    });
+  });
+
+  group('.handleAuthorizationCode', () {
+    setUp(createGrant);
+
+    test("can't be called before .getAuthorizationUrl", () {
+      expect(grant.handleAuthorizationCode('auth code'), throwsStateError);
+    });
+
+    test("can't be called twice", () {
+      grant.getAuthorizationUrl(redirectUrl);
+      grant.handleAuthorizationCode('auth code');
+      expect(grant.handleAuthorizationCode('auth code'),
+          throwsStateError);
+    });
+
+    test('sends an authorization code request', () {
+      grant.getAuthorizationUrl(redirectUrl);
+      client.expectRequest((request) {
+        expect(request.method, equals('POST'));
+        expect(request.url.toString(), equals(grant.tokenEndpoint.toString()));
+        expect(request.bodyFields, equals({
+          'grant_type': 'authorization_code',
+          'code': 'auth code',
+          'redirect_uri': redirectUrl.toString(),
+          'client_id': 'identifier',
+          'client_secret': 'secret'
+        }));
+
+        return new Future.immediate(new http.Response(JSON.stringify({
+          'access_token': 'access token',
+          'token_type': 'bearer',
+        }), 200, headers: {'content-type': 'application/json'}));
+      });
+
+      expect(grant.handleAuthorizationCode('auth code'),
+          completion(predicate((client) {
+            expect(client.credentials.accessToken, equals('access token'));
+            return true;
+          })));
+    });
+  });
+}
diff --git a/pkg/oauth2/test/client_test.dart b/pkg/oauth2/test/client_test.dart
new file mode 100644
index 0000000..94b7920
--- /dev/null
+++ b/pkg/oauth2/test/client_test.dart
@@ -0,0 +1,120 @@
+// 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 client_test;
+
+import 'dart:io';
+import 'dart:json';
+import 'dart:uri';
+
+import '../../unittest/lib/unittest.dart';
+import '../../http/lib/http.dart' as http;
+import '../lib/oauth2.dart' as oauth2;
+import 'utils.dart';
+
+final Uri requestUri = new Uri.fromString("http://example.com/resource");
+
+final Uri tokenEndpoint = new Uri.fromString('http://example.com/token');
+
+ExpectClient httpClient;
+
+void createHttpClient() {
+  httpClient = new ExpectClient();
+}
+
+void main() {
+  group('with expired credentials', () {
+    setUp(createHttpClient);
+
+    test("that can't be refreshed throws an ExpirationException on send", () {
+      var expiration = new Date.now().subtract(new Duration(hours: 1));
+      var credentials = new oauth2.Credentials(
+          'access token', null, null, [], expiration);
+      var client = new oauth2.Client('identifier', 'secret', credentials,
+          httpClient: httpClient);
+
+      expect(client.get(requestUri), throwsExpirationException);
+    });
+
+    test("that can be refreshed refreshes the credentials and sends the "
+        "request", () {
+      var expiration = new Date.now().subtract(new Duration(hours: 1));
+      var credentials = new oauth2.Credentials(
+          'access token', 'refresh token', tokenEndpoint, [], expiration);
+      var client = new oauth2.Client('identifier', 'secret', credentials,
+          httpClient: httpClient);
+
+      httpClient.expectRequest((request) {
+        expect(request.method, equals('POST'));
+        expect(request.url.toString(), equals(tokenEndpoint.toString()));
+        return new Future.immediate(new http.Response(JSON.stringify({
+          'access_token': 'new access token',
+          'token_type': 'bearer'
+        }), 200, headers: {'content-type': 'application/json'}));
+      });
+
+      httpClient.expectRequest((request) {
+        expect(request.method, equals('GET'));
+        expect(request.url.toString(), equals(requestUri.toString()));
+        expect(request.headers['authorization'],
+            equals('Bearer new access token'));
+
+        return new Future.immediate(new http.Response('good job', 200));
+      });
+
+      expect(client.read(requestUri).transform((_) {
+        expect(client.credentials.accessToken, equals('new access token'));
+      }), completes);
+    });
+  });
+
+  group('with valid credentials', () {
+    setUp(createHttpClient);
+
+    test("sends a request with bearer authorization", () {
+      var credentials = new oauth2.Credentials('access token');
+      var client = new oauth2.Client('identifier', 'secret', credentials,
+          httpClient: httpClient);
+
+      httpClient.expectRequest((request) {
+        expect(request.method, equals('GET'));
+        expect(request.url.toString(), equals(requestUri.toString()));
+        expect(request.headers['authorization'],
+            equals('Bearer access token'));
+
+        return new Future.immediate(new http.Response('good job', 200));
+      });
+
+      expect(client.read(requestUri), completion(equals('good job')));
+    });
+
+    test("can manually refresh the credentials", () {
+      var credentials = new oauth2.Credentials(
+          'access token', 'refresh token', tokenEndpoint);
+      var client = new oauth2.Client('identifier', 'secret', credentials,
+          httpClient: httpClient);
+
+      httpClient.expectRequest((request) {
+        expect(request.method, equals('POST'));
+        expect(request.url.toString(), equals(tokenEndpoint.toString()));
+        return new Future.immediate(new http.Response(JSON.stringify({
+          'access_token': 'new access token',
+          'token_type': 'bearer'
+        }), 200, headers: {'content-type': 'application/json'}));
+      });
+
+      expect(client.refreshCredentials().transform((_) {
+        expect(client.credentials.accessToken, equals('new access token'));
+      }), completes);
+    });
+
+    test("without a refresh token can't manually refresh the credentials", () {
+      var credentials = new oauth2.Credentials('access token');
+      var client = new oauth2.Client('identifier', 'secret', credentials,
+          httpClient: httpClient);
+
+      expect(client.refreshCredentials(), throwsStateError);
+    });
+  });
+}
diff --git a/pkg/oauth2/test/credentials_test.dart b/pkg/oauth2/test/credentials_test.dart
new file mode 100644
index 0000000..5faf2d0
--- /dev/null
+++ b/pkg/oauth2/test/credentials_test.dart
@@ -0,0 +1,174 @@
+// 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 credentials_test;
+
+import 'dart:io';
+import 'dart:json';
+import 'dart:uri';
+
+import '../../unittest/lib/unittest.dart';
+import '../../http/lib/http.dart' as http;
+import '../lib/oauth2.dart' as oauth2;
+import 'utils.dart';
+
+final Uri tokenEndpoint = new Uri.fromString('http://example.com/token');
+
+ExpectClient httpClient;
+
+void main() {
+  setUp(() => httpClient = new ExpectClient());
+
+  test('is not expired if no expiration exists', () {
+    var credentials = new oauth2.Credentials('access token');
+    expect(credentials.isExpired, isFalse);
+  });
+
+  test('is not expired if the expiration is in the future', () {
+    var expiration = new Date.now().add(new Duration(hours: 1));
+    var credentials = new oauth2.Credentials(
+        'access token', null, null, null, expiration);
+    expect(credentials.isExpired, isFalse);
+  });
+
+  test('is expired if the expiration is in the past', () {
+    var expiration = new Date.now().subtract(new Duration(hours: 1));
+    var credentials = new oauth2.Credentials(
+        'access token', null, null, null, expiration);
+    expect(credentials.isExpired, isTrue);
+  });
+
+  test("can't refresh without a refresh token", () {
+    var credentials = new oauth2.Credentials(
+        'access token', null, tokenEndpoint);
+    expect(credentials.canRefresh, false);
+    expect(credentials.refresh('identifier', 'secret', httpClient: httpClient),
+        throwsStateError);
+  });
+
+  test("can't refresh without a token endpoint", () {
+    var credentials = new oauth2.Credentials('access token', 'refresh token');
+    expect(credentials.canRefresh, false);
+    expect(credentials.refresh('identifier', 'secret', httpClient: httpClient),
+        throwsStateError);
+  });
+
+  test("can refresh with a refresh token and a token endpoint", () {
+    var credentials = new oauth2.Credentials(
+        'access token', 'refresh token', tokenEndpoint, ['scope1', 'scope2']);
+    expect(credentials.canRefresh, true);
+
+    httpClient.expectRequest((request) {
+      expect(request.method, equals('POST'));
+      expect(request.url.toString(), equals(tokenEndpoint.toString()));
+      expect(request.bodyFields, equals({
+        "grant_type": "refresh_token",
+        "refresh_token": "refresh token",
+        "scope": "scope1 scope2",
+        "client_id": "identifier",
+        "client_secret": "secret"
+      }));
+
+      return new Future.immediate(new http.Response(JSON.stringify({
+        'access_token': 'new access token',
+        'token_type': 'bearer',
+        'refresh_token': 'new refresh token'
+      }), 200, headers: {'content-type': 'application/json'}));
+    });
+
+    
+    expect(credentials.refresh('identifier', 'secret', httpClient: httpClient)
+        .transform((credentials) {
+      expect(credentials.accessToken, equals('new access token'));
+      expect(credentials.refreshToken, equals('new refresh token'));
+    }), completes);
+  });
+
+  test("uses the old refresh token if a new one isn't provided", () {
+    var credentials = new oauth2.Credentials(
+        'access token', 'refresh token', tokenEndpoint);
+    expect(credentials.canRefresh, true);
+
+    httpClient.expectRequest((request) {
+      expect(request.method, equals('POST'));
+      expect(request.url.toString(), equals(tokenEndpoint.toString()));
+      expect(request.bodyFields, equals({
+        "grant_type": "refresh_token",
+        "refresh_token": "refresh token",
+        "client_id": "identifier",
+        "client_secret": "secret"
+      }));
+
+      return new Future.immediate(new http.Response(JSON.stringify({
+        'access_token': 'new access token',
+        'token_type': 'bearer'
+      }), 200, headers: {'content-type': 'application/json'}));
+    });
+
+    
+    expect(credentials.refresh('identifier', 'secret', httpClient: httpClient)
+        .transform((credentials) {
+      expect(credentials.accessToken, equals('new access token'));
+      expect(credentials.refreshToken, equals('refresh token'));
+    }), completes);
+  });
+
+  group("fromJson", () {
+    oauth2.Credentials fromMap(Map map) =>
+      new oauth2.Credentials.fromJson(JSON.stringify(map));
+
+    test("should load the same credentials from toJson", () {
+      var expiration = new Date.now().subtract(new Duration(hours: 1));
+      var credentials = new oauth2.Credentials(
+          'access token', 'refresh token', tokenEndpoint, ['scope1', 'scope2'],
+          expiration);
+      var reloaded = new oauth2.Credentials.fromJson(credentials.toJson());
+
+      expect(reloaded.accessToken, equals(credentials.accessToken));
+      expect(reloaded.refreshToken, equals(credentials.refreshToken));
+      expect(reloaded.tokenEndpoint.toString(),
+          equals(credentials.tokenEndpoint.toString()));
+      expect(reloaded.scopes, equals(credentials.scopes));
+      expect(reloaded.expiration, equals(credentials.expiration));
+    });
+
+    test("should throw a FormatException for invalid JSON", () {
+      expect(() => new oauth2.Credentials.fromJson("foo bar"),
+          throwsFormatException);
+    });
+
+    test("should throw a FormatException for JSON that's not a map", () {
+      expect(() => new oauth2.Credentials.fromJson("null"),
+          throwsFormatException);
+    });
+
+    test("should throw a FormatException if there is no accessToken", () {
+      expect(() => fromMap({}), throwsFormatException);
+    });
+
+    test("should throw a FormatException if accessToken is not a string", () {
+      expect(() => fromMap({"accessToken": 12}), throwsFormatException);
+    });
+
+    test("should throw a FormatException if refreshToken is not a string", () {
+      expect(() => fromMap({"accessToken": "foo", "refreshToken": 12}),
+          throwsFormatException);
+    });
+
+    test("should throw a FormatException if tokenEndpoint is not a string", () {
+      expect(() => fromMap({"accessToken": "foo", "tokenEndpoint": 12}),
+          throwsFormatException);
+    });
+
+    test("should throw a FormatException if scopes is not a list", () {
+      expect(() => fromMap({"accessToken": "foo", "scopes": 12}),
+          throwsFormatException);
+    });
+
+    test("should throw a FormatException if expiration is not an int", () {
+      expect(() => fromMap({"accessToken": "foo", "expiration": "12"}),
+          throwsFormatException);
+    });
+  });
+}
diff --git a/pkg/oauth2/test/handle_access_token_response_test.dart b/pkg/oauth2/test/handle_access_token_response_test.dart
new file mode 100644
index 0000000..4757dc1
--- /dev/null
+++ b/pkg/oauth2/test/handle_access_token_response_test.dart
@@ -0,0 +1,191 @@
+// 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 handle_access_token_response_test;
+
+import 'dart:io';
+import 'dart:json';
+import 'dart:uri';
+
+import '../../unittest/lib/unittest.dart';
+import '../../http/lib/http.dart' as http;
+import '../lib/oauth2.dart' as oauth2;
+import '../lib/src/handle_access_token_response.dart';
+import 'utils.dart';
+
+final Uri tokenEndpoint = new Uri.fromString("https://example.com/token");
+
+final Date startTime = new Date.now();
+
+oauth2.Credentials handle(http.Response response) =>
+  handleAccessTokenResponse(response, tokenEndpoint, startTime, ["scope"]);
+
+void main() {
+  group('an error response', () {
+    oauth2.Credentials handleError(
+        {String body: '{"error": "invalid_request"}',
+         int statusCode: 400,
+         Map<String, String> headers:
+             const {"content-type": "application/json"}}) =>
+      handle(new http.Response(body, statusCode, headers: headers));
+
+    test('causes an AuthorizationException', () {
+      expect(() => handleError(), throwsAuthorizationException);
+    });
+
+    test('with a 401 code causes an AuthorizationException', () {
+      expect(() => handleError(statusCode: 401), throwsAuthorizationException);
+    });
+
+    test('with an unexpected code causes a FormatException', () {
+      expect(() => handleError(statusCode: 500),
+          throwsFormatException);
+    });
+
+    test('with no content-type causes a FormatException', () {
+      expect(() => handleError(headers: {}), throwsFormatException);
+    });
+
+    test('with a non-JSON content-type causes a FormatException', () {
+      expect(() => handleError(headers: {
+        'content-type': 'text/plain'
+      }), throwsFormatException);
+    });
+
+    test('with a JSON content-type and charset causes an '
+        'AuthorizationException', () {
+      expect(() => handleError(headers: {
+        'content-type': 'application/json; charset=UTF-8'
+      }), throwsAuthorizationException);
+    });
+
+    test('with invalid JSON causes a FormatException', () {
+      expect(() => handleError(body: 'not json'),
+          throwsFormatException);
+    });
+
+    test('with a non-string error causes a FormatException', () {
+      expect(() => handleError(body: '{"error": 12}'),
+          throwsFormatException);
+    });
+
+    test('with a non-string error_description causes a FormatException', () {
+      expect(() => handleError(body: JSON.stringify({
+        "error": "invalid_request",
+        "error_description": 12
+      })), throwsFormatException);
+    });
+
+    test('with a non-string error_uri causes a FormatException', () {
+      expect(() => handleError(body: JSON.stringify({
+        "error": "invalid_request",
+        "error_uri": 12
+      })), throwsFormatException);
+    });
+
+    test('with a string error_description causes a AuthorizationException', () {
+      expect(() => handleError(body: JSON.stringify({
+        "error": "invalid_request",
+        "error_description": "description"
+      })), throwsAuthorizationException);
+    });
+
+    test('with a string error_uri causes a AuthorizationException', () {
+      expect(() => handleError(body: JSON.stringify({
+        "error": "invalid_request",
+        "error_uri": "http://example.com/error"
+      })), throwsAuthorizationException);
+    });
+  });
+
+  group('a success response', () {
+    oauth2.Credentials handleSuccess(
+        {String contentType: "application/json",
+         accessToken: 'access token',
+         tokenType: 'bearer',
+         expiresIn,
+         refreshToken,
+         scope}) {
+      return handle(new http.Response(JSON.stringify({
+        'access_token': accessToken,
+        'token_type': tokenType,
+        'expires_in': expiresIn,
+        'refresh_token': refreshToken,
+        'scope': scope
+      }), 200, headers: {'content-type': contentType}));
+    }
+
+    test('returns the correct credentials', () {
+      var credentials = handleSuccess();
+      expect(credentials.accessToken, equals('access token'));
+      expect(credentials.tokenEndpoint.toString(),
+          equals(tokenEndpoint.toString()));
+    });
+
+    test('with no content-type causes a FormatException', () {
+      expect(() => handleSuccess(contentType: null), throwsFormatException);
+    });
+
+    test('with a non-JSON content-type causes a FormatException', () {
+      expect(() => handleSuccess(contentType: 'text/plain'),
+          throwsFormatException);
+    });
+
+    test('with a JSON content-type and charset returns the correct '
+        'credentials', () {
+      var credentials = handleSuccess(
+          contentType: 'application/json; charset=UTF-8');
+      expect(credentials.accessToken, equals('access token'));
+    });
+
+    test('with a null access token throws a FormatException', () {
+      expect(() => handleSuccess(accessToken: null), throwsFormatException);
+    });
+
+    test('with a non-string access token throws a FormatException', () {
+      expect(() => handleSuccess(accessToken: 12), throwsFormatException);
+    });
+
+    test('with a null token type throws a FormatException', () {
+      expect(() => handleSuccess(tokenType: null), throwsFormatException);
+    });
+
+    test('with a non-string token type throws a FormatException', () {
+      expect(() => handleSuccess(tokenType: 12), throwsFormatException);
+    });
+
+    test('with a non-"bearer" token type throws a FormatException', () {
+      expect(() => handleSuccess(tokenType: "mac"), throwsFormatException);
+    });
+
+    test('with a non-int expires-in throws a FormatException', () {
+      expect(() => handleSuccess(expiresIn: "whenever"), throwsFormatException);
+    });
+
+    test('with expires-in sets the expiration to ten seconds earlier than the '
+        'server says', () {
+      var credentials = handleSuccess(expiresIn: 100);
+      expect(credentials.expiration.millisecondsSinceEpoch,
+          startTime.millisecondsSinceEpoch + 90 * 1000);
+    });
+
+    test('with a non-string refresh token throws a FormatException', () {
+      expect(() => handleSuccess(refreshToken: 12), throwsFormatException);
+    });
+
+    test('with a refresh token sets the refresh token', () {
+      var credentials = handleSuccess(refreshToken: "refresh me");
+      expect(credentials.refreshToken, equals("refresh me"));
+    });
+
+    test('with a non-string scope throws a FormatException', () {
+      expect(() => handleSuccess(scope: 12), throwsFormatException);
+    });
+
+    test('with a scope sets the scopes', () {
+      var credentials = handleSuccess(scope: "scope1 scope2");
+      expect(credentials.scopes, equals(["scope1", "scope2"]));
+    });
+  });
+}
diff --git a/pkg/oauth2/test/utils.dart b/pkg/oauth2/test/utils.dart
new file mode 100644
index 0000000..631ea95
--- /dev/null
+++ b/pkg/oauth2/test/utils.dart
@@ -0,0 +1,82 @@
+// 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 utils;
+
+import '../../unittest/lib/unittest.dart';
+import '../../http/lib/http.dart' as http;
+import '../../http/lib/testing.dart';
+import '../lib/oauth2.dart' as oauth2;
+
+class ExpectClient extends MockClient {
+  final Queue<MockClientHandler> _handlers;
+
+  ExpectClient._(MockClientHandler fn)
+    : _handlers = new Queue<MockClientHandler>(),
+      super(fn);
+
+  factory ExpectClient() {
+    var client;
+    client = new ExpectClient._((request) =>
+        client._handleRequest(request));
+    return client;
+  }
+
+  void expectRequest(MockClientHandler fn) {
+    var completer = new Completer();
+    expect(completer.future, completes);
+
+    _handlers.add((request) {
+      completer.complete(null);
+      return fn(request);
+    });
+  }
+
+  Future<http.Response> _handleRequest(http.Request request) {
+    if (_handlers.isEmpty) {
+      return new Future.immediate(new http.Response('not found', 404));
+    } else {
+      return _handlers.removeFirst()(request);
+    }
+  }
+}
+
+// TODO(nweiz): remove this once it's built in to unittest
+/// A matcher for StateErrors.
+const isStateError = const _StateError();
+
+/// A matcher for functions that throw StateError.
+const Matcher throwsStateError =
+    const Throws(isStateError);
+
+class _StateError extends TypeMatcher {
+  const _StateError() : super("StateError");
+  bool matches(item, MatchState matchState) => item is StateError;
+}
+
+/// A matcher for AuthorizationExceptions.
+const isAuthorizationException = const _AuthorizationException();
+
+/// A matcher for functions that throw AuthorizationException.
+const Matcher throwsAuthorizationException =
+    const Throws(isAuthorizationException);
+
+class _AuthorizationException extends TypeMatcher {
+  const _AuthorizationException() : super("AuthorizationException");
+  bool matches(item, MatchState matchState) =>
+    item is oauth2.AuthorizationException;
+}
+
+/// A matcher for ExpirationExceptions.
+const isExpirationException = const _ExpirationException();
+
+/// A matcher for functions that throw ExpirationException.
+const Matcher throwsExpirationException =
+    const Throws(isExpirationException);
+
+class _ExpirationException extends TypeMatcher {
+  const _ExpirationException() : super("ExpirationException");
+  bool matches(item, MatchState matchState) =>
+    item is oauth2.ExpirationException;
+}
diff --git a/pkg/pkg.gyp b/pkg/pkg.gyp
new file mode 100644
index 0000000..e5c2c35
--- /dev/null
+++ b/pkg/pkg.gyp
@@ -0,0 +1,45 @@
+# 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.
+
+{
+  'targets': [
+    {
+      'target_name': 'pkg_packages',
+      'type': 'none',
+      'actions': [
+        {
+          'action_name': 'make_pkg_packages',
+          'inputs': [
+            '../tools/make_links.py',
+            'args/lib',
+            'fixnum/lib',
+            'htmlescape/lib',
+            'http/lib',
+            'intl/lib',
+            'logging/lib',
+            'meta/lib',
+            'unittest/lib',
+            'webdriver/lib',
+          ],
+          'outputs': [
+            '<(PRODUCT_DIR)/packages/args',
+            '<(PRODUCT_DIR)/packages/fixnum',
+            '<(PRODUCT_DIR)/packages/htmlescape',
+            '<(PRODUCT_DIR)/packages/http',
+            '<(PRODUCT_DIR)/packages/intl',
+            '<(PRODUCT_DIR)/packages/logging',
+            '<(PRODUCT_DIR)/packages/meta',
+            '<(PRODUCT_DIR)/packages/unittest',
+            '<(PRODUCT_DIR)/packages/webdriver',
+          ],
+          'action': [
+            'python', '../tools/make_links.py',
+            '<(PRODUCT_DIR)/packages',
+            '<@(_inputs)',
+          ],
+        },
+      ],
+    }
+  ],
+}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index d7aadb7..32d4068 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -9,20 +9,18 @@
 # arithmetic natively, i.e., the VM.
 fixnum/test/int_64_vm_test: Skip
 
-# Skip the cURL tests until we have bundled binaries to run them on all
-# platforms.
-http/test/curl_client_test: Skip
-
 [$compiler == dart2dart]
 *: Skip
 
 # Don't compiile tests that use dart:io to JS
 [ $compiler == dart2js || $compiler == dart2dart || $compiler == dartc ]
 http/test/*: Skip
+oauth2/test/*: Skip
 
 # Skip tests that use local file access if we're running in any browser
 [ $runtime == opera || $runtime == ff || $runtime == ie9 || $runtime == dartium || $runtime == chrome || $runtime == safari || $runtime == drt ]
 http/test/*: Skip
+oauth2/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
@@ -50,13 +48,11 @@
 [ $compiler == dartc ]
 unittest/test/mock_regexp_negative_test: Fail
 unittest/test/mock_stepwise_negative_test: Fail
-
-[ $system == windows ]
-http/test/request_test: Pass, Timeout # Issue 6594
+args/test/args_test: Fail # http://dartbug.com/6790
 
 [ $compiler == dart2js || $compiler == dartc ]
 unittest/test/instance_test: Skip
 
 [ $compiler == none && $runtime == drt ]
 dartdoc/test/dartdoc_test: Skip # See dartbug.com/4541.
-
+args/test/args_test: Skip # http://dartbug.com/6744
diff --git a/pkg/unittest/lib/src/core_matchers.dart b/pkg/unittest/lib/src/core_matchers.dart
index 20e9db2..3846fdd 100644
--- a/pkg/unittest/lib/src/core_matchers.dart
+++ b/pkg/unittest/lib/src/core_matchers.dart
@@ -489,18 +489,6 @@
   bool matches(item, MatchState matchState) => item is UnimplementedError;
 }
 
-/** A matcher for NullPointerExceptions. */
-const isNullPointerException = const _NullPointerException();
-
-/** A matcher for functions that throw NotNullPointerException. */
-const Matcher throwsNullPointerException =
-    const Throws(isNullPointerException);
-
-class _NullPointerException extends TypeMatcher {
-  const _NullPointerException() : super("NullPointerException");
-  bool matches(item, MatchState matchState) => item is NullPointerException;
-}
-
 /** A matcher for UnsupportedError. */
 const isUnsupportedError = const _UnsupportedError();
 
diff --git a/pkg/unittest/test/matchers_test.dart b/pkg/unittest/test/matchers_test.dart
index c9045ad..81be8fb 100644
--- a/pkg/unittest/test/matchers_test.dart
+++ b/pkg/unittest/test/matchers_test.dart
@@ -155,16 +155,6 @@
             "UnimplementedError.");
     });
 
-    test('throwsNullPointerException', () {
-      shouldPass(() { throw new NullPointerException(''); },
-          throwsNullPointerException);
-      shouldFail(() { throw new Exception(); },
-          throwsNullPointerException,
-        "Expected: throws an exception which matches NullPointerException "
-        "but:  exception <Exception> does not match "
-            "NullPointerException.");
-    });
-
     test('throwsUnsupportedError', () {
       shouldPass(() { throw new UnsupportedError(''); },
           throwsUnsupportedError);
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 084cd51..c8108b7 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -268,6 +268,10 @@
         'builtin_natives.cc',
         'builtin.h',
         'io_natives.h',
+        'log_android.cc',
+        'log_linux.cc',
+        'log_macos.cc',
+        'log_win.cc',
       ],
       'includes': [
         'builtin_impl_sources.gypi',
@@ -391,7 +395,13 @@
           'link_settings': {
             'libraries': [ '-lws2_32.lib', '-lRpcrt4.lib' ],
           },
-       }]],
+       }],
+        ['OS=="android"', {
+          'link_settings': {
+            'libraries': [ '-llog' ],
+          },
+       }]
+      ],
     },
     {
       # Generate snapshot bin file.
@@ -482,7 +492,14 @@
             },
           },
         }],
-       ],
+        ['OS=="linux"', {
+          # Have the linker add all symbols to the dynamic symbol table
+          # so that extensions can look them up dynamically in the binary.
+          'ldflags': [
+            '-rdynamic',
+          ],
+        }],
+      ],
     },
     {
       # dart binary without any snapshot built in.
@@ -521,7 +538,15 @@
               'AdditionalOptions': [ '/EXPORT:Dart_True' ],
             },
           },
-       }]],
+        }],
+        ['OS=="linux"', {
+          # Have the linker add all symbols to the dynamic symbol table
+          # so that extensions can look them up dynamically in the binary.
+          'ldflags': [
+            '-rdynamic',
+          ],
+        }],
+      ],
     },
     {
       'target_name': 'process_test',
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 4aea641..f84a50f 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -71,12 +71,20 @@
   var baseUri = new Uri.fromString(base);
   _logResolution("# Resolving: $userString from $base");
 
-  // Relative URIs with scheme dart-ext should be resolved as if with no scheme.
   var uri = new Uri.fromString(userString);
   var resolved;
   if ('dart-ext' == uri.scheme) {
+    // Relative URIs with scheme dart-ext should be resolved as if with no
+    // scheme.
     resolved = baseUri.resolve(uri.path);
-    resolved = new Uri.fromComponents(scheme: "dart-ext", path: resolved.path);
+    var path = resolved.path;
+    if (resolved.scheme == 'package') {
+      // If we are resolving relative to a package URI we go directly to the
+      // file path and keep the dart-ext scheme. Otherwise, we will lose the
+      // package URI path part.
+      path = _filePathFromPackageUri(resolved);
+    }
+    resolved = new Uri.fromComponents(scheme: "dart-ext", path: path);
   } else {
     resolved = baseUri.resolve(userString);
   }
diff --git a/runtime/bin/dbg_connection.cc b/runtime/bin/dbg_connection.cc
index 4c23dd4..4918d0d 100644
--- a/runtime/bin/dbg_connection.cc
+++ b/runtime/bin/dbg_connection.cc
@@ -5,6 +5,7 @@
 #include "bin/dbg_connection.h"
 #include "bin/dbg_message.h"
 #include "bin/dartutils.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
@@ -198,7 +199,8 @@
       FATAL("Illegal JSON message received");
     }
     if (!found) {
-      printf("'command' not found in JSON message: '%s'\n", msgbuf_->buf());
+      Log::Print("'command' not found in JSON message: '%s'\n",
+                      msgbuf_->buf());
       msgbuf_->PopMessage();
     }
 
@@ -242,7 +244,7 @@
       }
 
       // This is an unrecognized command, report error and move on to next.
-      printf("unrecognized command received: '%s'\n", msgbuf_->buf());
+      Log::Print("unrecognized command received: '%s'\n", msgbuf_->buf());
       HandleUnknownMsg();
       msgbuf_->PopMessage();
     }
diff --git a/runtime/bin/dbg_connection_android.cc b/runtime/bin/dbg_connection_android.cc
index 7fe7e94..a0bce37 100644
--- a/runtime/bin/dbg_connection_android.cc
+++ b/runtime/bin/dbg_connection_android.cc
@@ -9,6 +9,7 @@
 
 #include "bin/dbg_connection.h"
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 
 int DebuggerConnectionImpl::epoll_fd_ = -1;
@@ -32,7 +33,7 @@
     // Sync message. Not yet implemented.
     UNIMPLEMENTED();
   } else {
-    printf("unexpected: receiving debugger connection event.\n");
+    Log::Print("unexpected: receiving debugger connection event.\n");
     UNIMPLEMENTED();
   }
 }
diff --git a/runtime/bin/dbg_connection_linux.cc b/runtime/bin/dbg_connection_linux.cc
index 7fe7e94..a0bce37 100644
--- a/runtime/bin/dbg_connection_linux.cc
+++ b/runtime/bin/dbg_connection_linux.cc
@@ -9,6 +9,7 @@
 
 #include "bin/dbg_connection.h"
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 
 int DebuggerConnectionImpl::epoll_fd_ = -1;
@@ -32,7 +33,7 @@
     // Sync message. Not yet implemented.
     UNIMPLEMENTED();
   } else {
-    printf("unexpected: receiving debugger connection event.\n");
+    Log::Print("unexpected: receiving debugger connection event.\n");
     UNIMPLEMENTED();
   }
 }
diff --git a/runtime/bin/dbg_connection_macos.cc b/runtime/bin/dbg_connection_macos.cc
index cc0f13a..8464abf 100644
--- a/runtime/bin/dbg_connection_macos.cc
+++ b/runtime/bin/dbg_connection_macos.cc
@@ -12,6 +12,7 @@
 #include "bin/dartutils.h"
 #include "bin/dbg_connection.h"
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 #include "platform/thread.h"
 #include "platform/utils.h"
@@ -87,10 +88,10 @@
   } else if (ident == wakeup_fds_[0]) {
     Message msg;
     if (ReceiveMessage(&msg)) {
-      printf("Received sync message id %d.\n", msg.msg_id);
+      Log::Print("Received sync message id %d.\n", msg.msg_id);
     }
   } else {
-    printf("unexpected: receiving debugger connection event.\n");
+    Log::Print("unexpected: receiving debugger connection event.\n");
     UNIMPLEMENTED();
   }
 }
@@ -113,7 +114,7 @@
       }
     }
   }
-  printf("shutting down debugger thread\n");
+  Log::Print("shutting down debugger thread\n");
 }
 
 
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index 9508dae..ca6c601 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -7,8 +7,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 
-#include "bin/platform.h"
-
+#include "bin/log.h"
 
 static int SetOsErrorMessage(char* os_error_message,
                              int os_error_message_len) {
@@ -23,7 +22,7 @@
                     NULL);
   if (message_size == 0) {
     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      fprintf(stderr, "FormatMessage failed %d\n", GetLastError());
+      Log::PrintErr("FormatMessage failed %d\n", GetLastError());
     }
     snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code);
   }
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index de28f03..878c7eb 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -15,6 +15,7 @@
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "platform/hashmap.h"
 #include "platform/thread.h"
 #include "platform/utils.h"
@@ -229,21 +230,21 @@
 
 #ifdef DEBUG_POLL
 static void PrintEventMask(intptr_t fd, intptr_t events) {
-  printf("%d ", fd);
-  if ((events & EPOLLIN) != 0) printf("EPOLLIN ");
-  if ((events & EPOLLPRI) != 0) printf("EPOLLPRI ");
-  if ((events & EPOLLOUT) != 0) printf("EPOLLOUT ");
-  if ((events & EPOLLERR) != 0) printf("EPOLLERR ");
-  if ((events & EPOLLHUP) != 0) printf("EPOLLHUP ");
-  if ((events & EPOLLRDHUP) != 0) printf("EPOLLRDHUP ");
+  Log::Print("%d ", fd);
+  if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
+  if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
+  if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT ");
+  if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR ");
+  if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP ");
+  if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP ");
   int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT |
       EPOLLERR | EPOLLHUP | EPOLLRDHUP;
   if ((events & ~all_events) != 0) {
-    printf("(and %08x) ", events & ~all_events);
+    Log::Print("(and %08x) ", events & ~all_events);
   }
-  printf("(available %d) ", FDUtils::AvailableBytes(fd));
+  Log::Print("(available %d) ", FDUtils::AvailableBytes(fd));
 
-  printf("\n");
+  Log::Print("\n");
 }
 #endif
 
@@ -299,7 +300,7 @@
             event_mask = (1 << kCloseEvent);
             sd->MarkClosedRead();
           } else if (errno != EWOULDBLOCK) {
-            fprintf(stderr, "Error recv: %s\n", strerror(errno));
+            Log::PrintErr("Error recv: %s\n", strerror(errno));
           }
         }
       }
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 886388f3..49b6ca1 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -15,6 +15,7 @@
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "platform/hashmap.h"
 #include "platform/thread.h"
 #include "platform/utils.h"
@@ -229,21 +230,21 @@
 
 #ifdef DEBUG_POLL
 static void PrintEventMask(intptr_t fd, intptr_t events) {
-  printf("%d ", fd);
-  if ((events & EPOLLIN) != 0) printf("EPOLLIN ");
-  if ((events & EPOLLPRI) != 0) printf("EPOLLPRI ");
-  if ((events & EPOLLOUT) != 0) printf("EPOLLOUT ");
-  if ((events & EPOLLERR) != 0) printf("EPOLLERR ");
-  if ((events & EPOLLHUP) != 0) printf("EPOLLHUP ");
-  if ((events & EPOLLRDHUP) != 0) printf("EPOLLRDHUP ");
+  Log::Print("%d ", fd);
+  if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
+  if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
+  if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT ");
+  if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR ");
+  if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP ");
+  if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP ");
   int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT |
       EPOLLERR | EPOLLHUP | EPOLLRDHUP;
   if ((events & ~all_events) != 0) {
-    printf("(and %08x) ", events & ~all_events);
+    Log::Print("(and %08x) ", events & ~all_events);
   }
-  printf("(available %d) ", FDUtils::AvailableBytes(fd));
+  Log::Print("(available %d) ", FDUtils::AvailableBytes(fd));
 
-  printf("\n");
+  Log::Print("\n");
 }
 #endif
 
@@ -299,7 +300,7 @@
             event_mask = (1 << kCloseEvent);
             sd->MarkClosedRead();
           } else if (errno != EWOULDBLOCK) {
-            fprintf(stderr, "Error recv: %s\n", strerror(errno));
+            Log::PrintErr("Error recv: %s\n", strerror(errno));
           }
         }
       }
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index 59a3d65..3954190 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -14,6 +14,7 @@
 
 #include "bin/dartutils.h"
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "platform/hashmap.h"
 #include "platform/thread.h"
 #include "platform/utils.h"
@@ -240,15 +241,16 @@
 
 #ifdef DEBUG_KQUEUE
 static void PrintEventMask(intptr_t fd, struct kevent* event) {
-  printf("%d ", static_cast<int>(fd));
-  if (event->filter == EVFILT_READ) printf("EVFILT_READ ");
-  if (event->filter == EVFILT_WRITE) printf("EVFILT_WRITE ");
-  printf("flags: %x: ", event->flags);
-  if ((event->flags & EV_EOF) != 0) printf("EV_EOF ");
-  if ((event->flags & EV_ERROR) != 0) printf("EV_ERROR ");
-  printf("- fflags: %d ", event->fflags);
-  printf("(available %d) ", static_cast<int>(FDUtils::AvailableBytes(fd)));
-  printf("\n");
+  Log::Print("%d ", static_cast<int>(fd));
+  if (event->filter == EVFILT_READ) Log::Print("EVFILT_READ ");
+  if (event->filter == EVFILT_WRITE) Log::Print("EVFILT_WRITE ");
+  Log::Print("flags: %x: ", event->flags);
+  if ((event->flags & EV_EOF) != 0) Log::Print("EV_EOF ");
+  if ((event->flags & EV_ERROR) != 0) Log::Print("EV_ERROR ");
+  Log::Print("- fflags: %d ", event->fflags);
+  Log::Print("(available %d) ",
+      static_cast<int>(FDUtils::AvailableBytes(fd)));
+  Log::Print("\n");
 }
 #endif
 
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 2d4343b..bc2f480 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -11,6 +11,7 @@
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 #include "platform/thread.h"
 
@@ -143,7 +144,7 @@
                                             reinterpret_cast<ULONG_PTR>(this),
                                             0);
   if (completion_port_ == NULL) {
-    fprintf(stderr, "Error CreateIoCompletionPort: %d\n", GetLastError());
+    Log::PrintErr("Error CreateIoCompletionPort: %d\n", GetLastError());
     return false;
   }
   return true;
@@ -224,7 +225,7 @@
                      NULL);
   if (!ok) {
     if (GetLastError() != ERROR_BROKEN_PIPE) {
-      fprintf(stderr, "ReadFile failed %d\n", GetLastError());
+      Log::PrintErr("ReadFile failed %d\n", GetLastError());
     }
     bytes_read = 0;
   }
@@ -259,7 +260,7 @@
     }
 
     if (GetLastError() != ERROR_BROKEN_PIPE) {
-      fprintf(stderr, "ReadFile failed: %d\n", GetLastError());
+      Log::PrintErr("ReadFile failed: %d\n", GetLastError());
     }
     event_handler_->HandleClosed(this);
     IOBuffer::DisposeBuffer(buffer);
@@ -298,7 +299,7 @@
   }
 
   if (GetLastError() != ERROR_BROKEN_PIPE) {
-    fprintf(stderr, "WriteFile failed: %d\n", GetLastError());
+    Log::PrintErr("WriteFile failed: %d\n", GetLastError());
   }
   event_handler_->HandleClosed(this);
   IOBuffer::DisposeBuffer(buffer);
@@ -344,7 +345,7 @@
                         NULL,
                         NULL);
   if (status == SOCKET_ERROR) {
-    fprintf(stderr, "Error WSAIoctl failed: %d\n", WSAGetLastError());
+    Log::PrintErr("Error WSAIoctl failed: %d\n", WSAGetLastError());
     return false;
   }
   return true;
@@ -376,7 +377,7 @@
                  buffer->GetCleanOverlapped());
   if (!ok) {
     if (WSAGetLastError() != WSA_IO_PENDING) {
-      fprintf(stderr, "AcceptEx failed: %d\n", WSAGetLastError());
+      Log::PrintErr("AcceptEx failed: %d\n", WSAGetLastError());
       closesocket(buffer->client());
       IOBuffer::DisposeBuffer(buffer);
       return false;
@@ -422,7 +423,7 @@
         accepted_tail_ = client_socket;
       }
     } else {
-      fprintf(stderr, "setsockopt failed: %d\n", WSAGetLastError());
+      Log::PrintErr("setsockopt failed: %d\n", WSAGetLastError());
       closesocket(buffer->client());
     }
   }
@@ -514,7 +515,7 @@
                         NULL);
     if (!ok) {
       if (GetLastError() != ERROR_BROKEN_PIPE) {
-        fprintf(stderr, "WriteFile failed: %d\n", GetLastError());
+        Log::PrintErr("WriteFile failed: %d\n", GetLastError());
       }
       event_handler_->HandleClosed(this);
     }
@@ -526,7 +527,7 @@
 void ClientSocket::Shutdown(int how) {
   int rc = shutdown(socket(), how);
   if (rc == SOCKET_ERROR) {
-    fprintf(stderr, "shutdown failed: %d %d\n", socket(), WSAGetLastError());
+    Log::PrintErr("shutdown failed: %d %d\n", socket(), WSAGetLastError());
   }
   if (how == SD_RECEIVE) MarkClosedRead();
   if (how == SD_SEND) MarkClosedWrite();
@@ -559,7 +560,7 @@
   }
 
   if (WSAGetLastError() != WSAECONNRESET) {
-    fprintf(stderr, "WSARecv failed: %d\n", WSAGetLastError());
+    Log::PrintErr("WSARecv failed: %d\n", WSAGetLastError());
   }
   event_handler_->HandleClosed(this);
   IOBuffer::DisposeBuffer(buffer);
@@ -584,7 +585,7 @@
     return true;
   }
 
-  fprintf(stderr, "WSASend failed: %d\n", WSAGetLastError());
+  Log::PrintErr("WSASend failed: %d\n", WSAGetLastError());
   IOBuffer::DisposeBuffer(pending_write_);
   pending_write_ = NULL;
   return false;
@@ -876,7 +877,7 @@
     if (!ok && overlapped == NULL) {
       if (GetLastError() == ERROR_ABANDONED_WAIT_0) {
         // The completion port should never be closed.
-        printf("Completion port closed\n");
+        Log::Print("Completion port closed\n");
         UNREACHABLE();
       } else {
         // Timeout is signalled by false result and NULL in overlapped.
diff --git a/runtime/bin/extensions.cc b/runtime/bin/extensions.cc
index 244a631..d8b13f9 100644
--- a/runtime/bin/extensions.cc
+++ b/runtime/bin/extensions.cc
@@ -15,17 +15,18 @@
 Dart_Handle Extensions::LoadExtension(const char* extension_url,
                                       Dart_Handle parent_library) {
   char* library_path = strdup(extension_url);
-  if (!library_path || !File::IsAbsolutePath(library_path)) {
-    free(library_path);
-    return Dart_Error("unexpected error in library path");
+
+  if (library_path == NULL) {
+    return Dart_Error("Out of memory in LoadExtension");
   }
+
   // Extract the path and the extension name from the url.
   char* last_path_separator = strrchr(library_path, '/');
   char* extension_name = last_path_separator + 1;
   *last_path_separator = '\0';  // Terminate library_path at last separator.
 
   void* library_handle = LoadExtensionLibrary(library_path, extension_name);
-  if (!library_handle) {
+  if (library_handle == NULL) {
     free(library_path);
     return Dart_Error("cannot find extension library");
   }
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index 66e6251..ddcec13 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -11,6 +11,7 @@
 #include <libgen.h>
 
 #include "bin/builtin.h"
+#include "bin/log.h"
 
 class FileHandle {
  public:
@@ -42,7 +43,7 @@
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
     strerror_r(errno, error_message, kBufferSize);
-    fprintf(stderr, "%s\n", error_message);
+    Log::PrintErr("%s\n", error_message);
   }
   handle_->set_fd(kClosedFd);
 }
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 66e6251..ddcec13 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -11,6 +11,7 @@
 #include <libgen.h>
 
 #include "bin/builtin.h"
+#include "bin/log.h"
 
 class FileHandle {
  public:
@@ -42,7 +43,7 @@
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
     strerror_r(errno, error_message, kBufferSize);
-    fprintf(stderr, "%s\n", error_message);
+    Log::PrintErr("%s\n", error_message);
   }
   handle_->set_fd(kClosedFd);
 }
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index b5bc95a..0fd0c8d 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -13,6 +13,7 @@
 
 #include "bin/builtin.h"
 #include "bin/fdutils.h"
+#include "bin/log.h"
 
 class FileHandle {
  public:
@@ -44,7 +45,7 @@
     const int kBufferSize = 1024;
     char error_message[kBufferSize];
     strerror_r(errno, error_message, kBufferSize);
-    fprintf(stderr, "%s\n", error_message);
+    Log::PrintErr("%s\n", error_message);
   }
   handle_->set_fd(kClosedFd);
 }
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 97a98a6..a9cef38 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -11,6 +11,7 @@
 #include <sys/stat.h>
 
 #include "bin/builtin.h"
+#include "bin/log.h"
 
 class FileHandle {
  public:
@@ -39,7 +40,7 @@
   ASSERT(handle_->fd() >= 0);
   int err = close(handle_->fd());
   if (err != 0) {
-    fprintf(stderr, "%s\n", strerror(errno));
+    Log::PrintErr("%s\n", strerror(errno));
   }
   handle_->set_fd(kClosedFd);
 }
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index b3513e4..2f2c6f2 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -14,12 +14,14 @@
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
 #include "bin/file.h"
+#include "bin/log.h"
+
 #include "platform/globals.h"
 
 #define CHECK_RESULT(result)                                                   \
   if (Dart_IsError(result)) {                                                  \
     free(snapshot_buffer);                                                     \
-    fprintf(stderr, "Error: %s", Dart_GetError(result));                       \
+    Log::PrintErr("Error: %s", Dart_GetError(result));                    \
     Dart_ExitScope();                                                          \
     Dart_ShutdownIsolate();                                                    \
     exit(255);                                                                 \
@@ -205,16 +207,14 @@
 
 
 static void PrintUsage() {
-  fprintf(stderr,
-          "dart [<vm-flags>] "
-          "[<dart-script-file>]\n");
+  Log::PrintErr("dart [<vm-flags>] [<dart-script-file>]\n");
 }
 
 
 static void VerifyLoaded(Dart_Handle library) {
   if (Dart_IsError(library)) {
     const char* err_msg = Dart_GetError(library);
-    fprintf(stderr, "Errors encountered while loading: %s\n", err_msg);
+    Log::PrintErr("Errors encountered while loading: %s\n", err_msg);
     Dart_ExitScope();
     Dart_ShutdownIsolate();
     exit(255);
@@ -251,7 +251,7 @@
   // Set up the library tag handler for this isolate.
   Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
   if (Dart_IsError(result)) {
-    fprintf(stderr, "%s", Dart_GetError(result));
+    Log::PrintErr("%s", Dart_GetError(result));
     Dart_ExitScope();
     Dart_ShutdownIsolate();
     exit(255);
@@ -290,7 +290,7 @@
   }
 
   if (snapshot_filename == NULL) {
-    fprintf(stderr, "No snapshot output file specified\n");
+    Log::PrintErr("No snapshot output file specified\n");
     return 255;
   }
 
@@ -302,14 +302,14 @@
   // Note: We don't expect isolates to be created from dart code during
   // snapshot generation.
   if (!Dart_Initialize(NULL, NULL, NULL)) {
-    fprintf(stderr, "VM initialization failed\n");
+    Log::PrintErr("VM initialization failed\n");
     return 255;
   }
 
   char* error;
   Dart_Isolate isolate = Dart_CreateIsolate(NULL, NULL, NULL, NULL, &error);
   if (isolate == NULL) {
-    fprintf(stderr, "Error: %s", error);
+    Log::PrintErr("Error: %s", error);
     free(error);
     exit(255);
   }
@@ -360,7 +360,7 @@
                                                 NULL,
                                                 &error);
       if (isolate == NULL) {
-        fprintf(stderr, "%s", error);
+        Log::PrintErr("%s", error);
         free(error);
         free(snapshot_buffer);
         exit(255);
diff --git a/runtime/bin/io_impl_sources.gypi b/runtime/bin/io_impl_sources.gypi
index f86ca02..552ac3d 100644
--- a/runtime/bin/io_impl_sources.gypi
+++ b/runtime/bin/io_impl_sources.gypi
@@ -41,7 +41,7 @@
     'socket_linux.cc',
     'socket_macos.cc',
     'socket_win.cc',
-    'tls_socket.cc',
-    'tls_socket.h',
+    'secure_socket.cc',
+    'secure_socket.h',
   ],
 }
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 1cd0236..16fd532 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -40,13 +40,13 @@
   V(Socket_GetError, 1)                                                        \
   V(Socket_GetStdioHandle, 2)                                                  \
   V(Socket_NewServicePort, 0)                                                  \
-  V(TlsSocket_Connect, 3)                                                      \
-  V(TlsSocket_Destroy, 1)                                                      \
-  V(TlsSocket_Handshake, 1)                                                    \
-  V(TlsSocket_Init, 1)                                                         \
-  V(TlsSocket_ProcessBuffer, 2)                                                \
-  V(TlsSocket_RegisterHandshakeCompleteCallback, 2)                            \
-  V(TlsSocket_SetCertificateDatabase, 1)
+  V(SecureSocket_Connect, 5)                                                   \
+  V(SecureSocket_Destroy, 1)                                                   \
+  V(SecureSocket_Handshake, 1)                                                 \
+  V(SecureSocket_Init, 1)                                                      \
+  V(SecureSocket_ProcessBuffer, 2)                                             \
+  V(SecureSocket_RegisterHandshakeCompleteCallback, 2)                         \
+  V(SecureSocket_SetCertificateDatabase, 2)
 
 IO_NATIVE_LIST(DECLARE_FUNCTION);
 
diff --git a/runtime/bin/io_sources.gypi b/runtime/bin/io_sources.gypi
index 9300c1c..69100f0 100644
--- a/runtime/bin/io_sources.gypi
+++ b/runtime/bin/io_sources.gypi
@@ -14,6 +14,6 @@
     'process_patch.dart',
     'socket_patch.dart',
     'stdio_patch.dart',
-    'tls_socket_patch.dart',
+    'secure_socket_patch.dart',
   ],
 }
diff --git a/runtime/bin/log.h b/runtime/bin/log.h
new file mode 100644
index 0000000..c495840
--- /dev/null
+++ b/runtime/bin/log.h
@@ -0,0 +1,37 @@
+// 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.
+
+#ifndef BIN_LOG_H_
+#define BIN_LOG_H_
+
+#include <stdarg.h>
+
+#include "platform/globals.h"
+
+class Log {
+ public:
+  // Print formatted output for debugging.
+  static void Print(const char* format, ...) PRINTF_ATTRIBUTE(1, 2) {
+    va_list args;
+    va_start(args, format);
+    VPrint(format, args);
+    va_end(args);
+  }
+
+  static void VPrint(const char* format, va_list args);
+
+  static void PrintErr(const char* format, ...) PRINTF_ATTRIBUTE(1, 2) {
+    va_list args;
+    va_start(args, format);
+    VPrintErr(format, args);
+    va_end(args);
+  }
+
+  static void VPrintErr(const char* format, va_list args);
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Log);
+};
+
+#endif  // BIN_LOG_H_
diff --git a/runtime/bin/log_android.cc b/runtime/bin/log_android.cc
new file mode 100644
index 0000000..0a6b552
--- /dev/null
+++ b/runtime/bin/log_android.cc
@@ -0,0 +1,20 @@
+// 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.
+
+#include "bin/log.h"
+
+#include <stdio.h>
+#include <android/log.h>
+
+// TODO(gram): We should be buffering the data and only outputting
+// it when we see a '\n'.
+
+void Log::VPrint(const char* format, va_list args) {
+  __android_log_vprint(ANDROID_LOG_INFO, "Dart", format, args);
+}
+
+void Log::VPrintErr(const char* format, va_list args) {
+  __android_log_vprint(ANDROID_LOG_ERROR, "Dart", format, args);
+}
+
diff --git a/runtime/bin/log_linux.cc b/runtime/bin/log_linux.cc
new file mode 100644
index 0000000..1b99c70
--- /dev/null
+++ b/runtime/bin/log_linux.cc
@@ -0,0 +1,18 @@
+// 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.
+
+#include "bin/log.h"
+
+#include <stdio.h>
+
+void Log::VPrint(const char* format, va_list args) {
+  vfprintf(stdout, format, args);
+  fflush(stdout);
+}
+
+void Log::VPrintErr(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+  fflush(stdout);
+}
+
diff --git a/runtime/bin/log_macos.cc b/runtime/bin/log_macos.cc
new file mode 100644
index 0000000..2f0d371
--- /dev/null
+++ b/runtime/bin/log_macos.cc
@@ -0,0 +1,17 @@
+// 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.
+
+#include "bin/log.h"
+
+#include <stdio.h>
+
+void Log::VPrint(const char* format, va_list args) {
+  vfprintf(stdout, format, args);
+  fflush(stdout);
+}
+
+void Log::VPrintErr(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+  fflush(stderr);
+}
diff --git a/runtime/bin/log_win.cc b/runtime/bin/log_win.cc
new file mode 100644
index 0000000..2f0d371
--- /dev/null
+++ b/runtime/bin/log_win.cc
@@ -0,0 +1,17 @@
+// 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.
+
+#include "bin/log.h"
+
+#include <stdio.h>
+
+void Log::VPrint(const char* format, va_list args) {
+  vfprintf(stdout, format, args);
+  fflush(stdout);
+}
+
+void Log::VPrintErr(const char* format, va_list args) {
+  vfprintf(stderr, format, args);
+  fflush(stderr);
+}
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 534f886..81c1373 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -17,6 +17,7 @@
 #include "bin/extensions.h"
 #include "bin/file.h"
 #include "bin/isolate_data.h"
+#include "bin/log.h"
 #include "bin/platform.h"
 #include "bin/process.h"
 #include "platform/globals.h"
@@ -142,7 +143,7 @@
     }
   }
   if (debug_port == 0) {
-    fprintf(stderr, "unrecognized --debug option syntax. "
+    Log::PrintErr("unrecognized --debug option syntax. "
                     "Use --debug[:<port number>]\n");
     return false;
   }
@@ -516,25 +517,25 @@
 
 
 static void PrintVersion() {
-  fprintf(stderr, "Dart VM version: %s\n", Dart_VersionString());
+  Log::PrintErr("Dart VM version: %s\n", Dart_VersionString());
 }
 
 
 static void PrintUsage() {
-  fprintf(stderr,
+  Log::PrintErr(
       "Usage: dart [<vm-flags>] <dart-script-file> [<dart-options>]\n"
       "\n"
       "Executes the Dart script passed as <dart-script-file>.\n"
       "\n");
   if (!has_verbose_option) {
-    fprintf(stderr,
+    Log::PrintErr(
 "Common options:\n"
 "--checked Insert runtime type checks and enable assertions (checked mode).\n"
 "--version Print the VM version.\n"
 "--help    Display this message (add --verbose for information about all\n"
 "          VM options).\n");
   } else {
-    fprintf(stderr,
+    Log::PrintErr(
 "Supported options:\n"
 "--checked\n"
 "  Insert runtime type checks and enable assertions (checked mode).\n"
@@ -626,8 +627,9 @@
 static int ErrorExit(const char* format, ...) {
   va_list arguments;
   va_start(arguments, format);
-  vfprintf(stderr, format, arguments);
+  Log::VPrintErr(format, arguments);
   va_end(arguments);
+  fflush(stderr);
 
   Dart_ExitScope();
   Dart_ShutdownIsolate();
@@ -653,7 +655,7 @@
 
   // Perform platform specific initialization.
   if (!Platform::Initialize()) {
-    fprintf(stderr, "Initialization failed\n");
+    Log::PrintErr("Initialization failed\n");
   }
 
   // On Windows, the argv strings are code page encoded and not
@@ -691,7 +693,9 @@
   if (!Dart_Initialize(CreateIsolateAndSetup,
                        NULL,
                        ShutdownIsolate)) {
-    return ErrorExit("VM initialization failed\n");
+    fprintf(stderr, "%s", "VM initialization failed\n");
+    fflush(stderr);
+    return kErrorExitCode;
   }
 
   DartUtils::SetOriginalWorkingDirectory();
@@ -710,7 +714,7 @@
                                    "main",
                                    new IsolateData(),
                                    &error)) {
-    fprintf(stderr, "%s\n", error);
+    Log::PrintErr("%s\n", error);
     free(error);
     delete [] isolate_name;
     return kErrorExitCode;  // Indicates we encountered an error.
diff --git a/runtime/bin/net/nss.gyp b/runtime/bin/net/nss.gyp
index ad5d888..64402b5 100644
--- a/runtime/bin/net/nss.gyp
+++ b/runtime/bin/net/nss.gyp
@@ -7,7 +7,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file is a modified copy of Chromium's deps/third_party/nss/nss.gyp.
-# Revision 165464 (this should agree with "nss_rev" in DEPS).
+# Revision 169195 (this should agree with "nss_rev" in DEPS).
 {
   # Added by Dart. All Dart comments refer to the following block or line.
   'includes': [
@@ -88,7 +88,7 @@
   'conditions': [[ 'dart_io_support==1', {
   'targets': [
     {
-      'target_name': 'nspr_dart',
+      'target_name': 'nspr_dart',  # Added by Dart (the _dart postfix)
       'product_name': 'crnspr',
       'type': '<(component)',
       # Changed by Dart: '<(nss_directory)/' added to all paths.
@@ -455,14 +455,14 @@
       ],
     },
     {
-      'target_name': 'nss_dart',
+      'target_name': 'nss_dart',  # Added by Dart (the _dart postfix)
       'product_name': 'crnss',
       'type': '<(component)',
       'dependencies': [
-        'nss_static_dart',
+        'nss_static_dart',  # Added by Dart (the _dart postfix)
       ],
       'export_dependent_settings': [
-        'nss_static_dart',
+        'nss_static_dart',  # Added by Dart (the _dart postfix)
       ],
       'sources': [
         # Ensure at least one object file is produced, so that MSVC does not
@@ -473,10 +473,10 @@
       'conditions': [
         ['exclude_nss_root_certs==0', {
           'dependencies': [
-            'nssckbi_dart',
+            'nssckbi_dart',  # Added by Dart (the _dart postfix)
           ],
           'export_dependent_settings': [
-            'nssckbi_dart',
+            'nssckbi_dart',  # Added by Dart (the _dart postfix)
           ],
         }],
         ['OS == "mac" and component == "shared_library"', {
@@ -506,7 +506,7 @@
       #
       # TODO(rsleevi): http://crbug.com/128134 - Break the circular dependency
       # without requiring nssckbi to be built as a shared library.
-      'target_name': 'nssckbi_dart',
+      'target_name': 'nssckbi_dart',  # Added by Dart (the _dart postfix)
       'product_name': 'crnssckbi',
       'type': 'static_library',
       # This target is an implementation detail - the public dependencies
@@ -554,10 +554,10 @@
         '<(nss_directory)/mozilla/security/nss/lib/ckfw/wrap.c',
       ],
       'dependencies': [
-        'nss_static_dart',
+        'nss_static_dart',  # Added by Dart (the _dart postfix)
       ],
       'export_dependent_settings': [
-        'nss_static_dart',
+        'nss_static_dart',  # Added by Dart (the _dart postfix)
       ],
       'include_dirs': [
         '<(nss_directory)/mozilla/security/nss/lib/ckfw',
@@ -569,7 +569,7 @@
       },
     },
     {
-      'target_name': 'nss_static_dart',
+      'target_name': 'nss_static_dart',  # Added by Dart (the _dart postfix)
       'type': 'static_library',
       # This target is an implementation detail - the public dependencies
       # should be on 'nss'.
@@ -630,6 +630,7 @@
         '<(nss_directory)/mozilla/security/nss/lib/cryptohi/keyt.h',
         '<(nss_directory)/mozilla/security/nss/lib/cryptohi/keythi.h',
         '<(nss_directory)/mozilla/security/nss/lib/cryptohi/sechash.c',
+        '<(nss_directory)/mozilla/security/nss/lib/cryptohi/sechash.h',
         '<(nss_directory)/mozilla/security/nss/lib/cryptohi/seckey.c',
         '<(nss_directory)/mozilla/security/nss/lib/cryptohi/secsign.c',
         '<(nss_directory)/mozilla/security/nss/lib/cryptohi/secvfy.c',
@@ -678,7 +679,6 @@
         '<(nss_directory)/mozilla/security/nss/lib/freebl/ecl/ecp_jm.c',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/ecl/ecp_mont.c',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/ecl/ec_naf.c',
-        '<(nss_directory)/mozilla/security/nss/lib/freebl/hasht.h',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/jpake.c',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/md2.c',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/md5.c',
@@ -700,12 +700,12 @@
         '<(nss_directory)/mozilla/security/nss/lib/freebl/mpi/mp_gf2m.h',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/mpi/primes.c',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/pqg.c',
+        '<(nss_directory)/mozilla/security/nss/lib/freebl/pqg.h',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/rawhash.c',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/rijndael.c',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/rijndael.h',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/rijndael32.tab',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/rsa.c',
-        '<(nss_directory)/mozilla/security/nss/lib/freebl/sechash.h',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/secmpi.h',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/secrng.h',
         '<(nss_directory)/mozilla/security/nss/lib/freebl/seed.c',
@@ -920,6 +920,7 @@
         '<(nss_directory)/mozilla/security/nss/lib/pk11wrap/pk11util.c',
         '<(nss_directory)/mozilla/security/nss/lib/pk11wrap/secmod.h',
         '<(nss_directory)/mozilla/security/nss/lib/pk11wrap/secmodi.h',
+        '<(nss_directory)/mozilla/security/nss/lib/pk11wrap/secmodt.h',
         '<(nss_directory)/mozilla/security/nss/lib/pk11wrap/secmodti.h',
         '<(nss_directory)/mozilla/security/nss/lib/pk11wrap/secpkcs5.h',
         '<(nss_directory)/mozilla/security/nss/lib/pkcs7/certread.c',
@@ -969,8 +970,6 @@
         '<(nss_directory)/mozilla/security/nss/lib/softoken/lowpbe.c',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/lowpbe.h',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/padbuf.c',
-        '<(nss_directory)/mozilla/security/nss/lib/softoken/pk11init.h',
-        '<(nss_directory)/mozilla/security/nss/lib/softoken/pk11pars.h',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/pkcs11.c',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/pkcs11c.c',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/pkcs11i.h',
@@ -979,12 +978,10 @@
         '<(nss_directory)/mozilla/security/nss/lib/softoken/rsawrapr.c',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sdb.c',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sdb.h',
-        '<(nss_directory)/mozilla/security/nss/lib/softoken/secmodt.h',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sftkdb.c',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sftkdb.h',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sftkdbt.h',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sftkdbti.h',
-        '<(nss_directory)/mozilla/security/nss/lib/softoken/sftkmod.c',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sftkpars.c',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sftkpars.h',
         '<(nss_directory)/mozilla/security/nss/lib/softoken/sftkpwd.c',
@@ -1002,6 +999,7 @@
         '<(nss_directory)/mozilla/security/nss/lib/util/dersubr.c',
         '<(nss_directory)/mozilla/security/nss/lib/util/dertime.c',
         '<(nss_directory)/mozilla/security/nss/lib/util/errstrs.c',
+        '<(nss_directory)/mozilla/security/nss/lib/util/hasht.h',
         '<(nss_directory)/mozilla/security/nss/lib/util/nssb64.h',
         '<(nss_directory)/mozilla/security/nss/lib/util/nssb64d.c',
         '<(nss_directory)/mozilla/security/nss/lib/util/nssb64e.c',
@@ -1047,6 +1045,11 @@
         '<(nss_directory)/mozilla/security/nss/lib/util/sectime.c',
         '<(nss_directory)/mozilla/security/nss/lib/util/templates.c',
         '<(nss_directory)/mozilla/security/nss/lib/util/utf8.c',
+        '<(nss_directory)/mozilla/security/nss/lib/util/utilmod.c',
+        '<(nss_directory)/mozilla/security/nss/lib/util/utilmodt.h',
+        '<(nss_directory)/mozilla/security/nss/lib/util/utilpars.c',
+        '<(nss_directory)/mozilla/security/nss/lib/util/utilpars.h',
+        '<(nss_directory)/mozilla/security/nss/lib/util/utilparst.h',
         '<(nss_directory)/mozilla/security/nss/lib/util/utilrename.h',
       ],
       'sources!': [
@@ -1059,11 +1062,11 @@
         '<(nss_directory)/mozilla/security/nss/lib/pk11wrap/debug_module.c',
       ],
       'dependencies': [
-        'nspr_dart',
-        'sqlite.gyp:sqlite_dart',
+        'nspr_dart',  # Added by Dart (the _dart postfix)
+        'sqlite.gyp:sqlite_dart',  # Changed by Dart prefix ../sqllite removed _dart postfix added.
       ],
       'export_dependent_settings': [
-        'nspr_dart',
+        'nspr_dart',  # Added by Dart (the _dart postfix)
       ],
       'defines': [
         'MP_API_COMPATIBLE',
@@ -1148,6 +1151,9 @@
           'defines': [
             'NSS_DISABLE_LIBPKIX',
           ],
+          # Changed by Dart:
+          # nss_directory contains .., which is bad in a regular expression.
+          # So we use the partial match by dropping '^' from '^mozilla/...
           'sources/': [
             ['exclude', 'mozilla/security/nss/lib/libpkix/'],
           ],
@@ -1155,6 +1161,9 @@
             '<(nss_directory)/mozilla/security/nss/lib/certhigh/certvfypkix.c',
             '<(nss_directory)/mozilla/security/nss/lib/certhigh/certvfypkixprint.c',
           ],
+          # Changed by Dart:
+          # nss_directory contains .., which is bad in a regular expression.
+          # So we use the partial match by dropping '^' from '^mozilla/...
           'include_dirs/': [
             ['exclude', 'mozilla/security/nss/lib/libpkix/'],
           ],
@@ -1164,7 +1173,6 @@
             ['exclude', 'amd64'],
           ],
         }],
-        # Added by Dart.
         ['OS=="linux"', {
           'defines': [
             'XP_UNIX',
diff --git a/runtime/bin/net/sqlite.gyp b/runtime/bin/net/sqlite.gyp
index 543ca77..aa7ec81 100644
--- a/runtime/bin/net/sqlite.gyp
+++ b/runtime/bin/net/sqlite.gyp
@@ -7,7 +7,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file is a modified copy of Chromium's src/third_party/sqlite/sqlite.gyp.
-# Revision 165464 (this should agree with "nss_rev" in DEPS).
+# Revision 169195 (this should agree with "nss_rev" in DEPS).
 {
   # Added by Dart. All Dart comments refer to the following block or line.
   'includes': [
@@ -38,7 +38,7 @@
   'conditions': [[ 'dart_io_support==1', {
   'targets': [
     {
-      'target_name': 'sqlite_dart',
+      'target_name': 'sqlite_dart',  # Added by Dart (the _dart postfix)
       'conditions': [
         [ 'chromeos==1' , {
             'defines': [
@@ -184,12 +184,12 @@
     ['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android" and not use_system_sqlite', {
       'targets': [
         {
-          'target_name': 'sqlite_shell_dart',
+          'target_name': 'sqlite_shell_dart',  # Added by Dart (the _dart postfix)
           'type': 'executable',
           'dependencies': [
             # Disabled by Dart.
             # '../icu/icu.gyp:icuuc',
-            'sqlite_dart',
+            'sqlite_dart',  # Added by Dart (the _dart postfix)
           ],
           'sources': [
             '<(sqlite_directory)/src/src/shell.c',
diff --git a/runtime/bin/net/ssl.gyp b/runtime/bin/net/ssl.gyp
index cee5997..3798baa 100644
--- a/runtime/bin/net/ssl.gyp
+++ b/runtime/bin/net/ssl.gyp
@@ -7,7 +7,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file is a modified copy of Chromium's src/net/third_party/nss/ssl.gyp.
-# Revision 165464 (this should agree with "nss_rev" in DEPS).
+# Revision 169195 (this should agree with "nss_rev" in DEPS).
 {
   # Conditions section for ssl-bodge (Compiling SSL on linux using system
   # NSS and NSPR libraries) removed:
@@ -30,15 +30,14 @@
   'conditions': [[ 'dart_io_support==1', {
   'targets': [
     {
-      'target_name': 'libssl_dart',
+      'target_name': 'libssl_dart',  # Added by Dart (the _dart postfix)
       'type': 'static_library',
       # Changed by Dart: '<(ssl_directory)/' added to all paths.
       'sources': [
         '<(ssl_directory)/ssl/authcert.c',
         '<(ssl_directory)/ssl/cmpcert.c',
         '<(ssl_directory)/ssl/derive.c',
-        '<(ssl_directory)/ssl/dtls1con.c',
-        '<(ssl_directory)/ssl/nsskea.c',
+        '<(ssl_directory)/ssl/dtlscon.c',
         '<(ssl_directory)/ssl/os2_err.c',
         '<(ssl_directory)/ssl/os2_err.h',
         '<(ssl_directory)/ssl/preenc.h',
@@ -77,7 +76,9 @@
         '<(ssl_directory)/ssl/unix_err.h',
         '<(ssl_directory)/ssl/win32err.c',
         '<(ssl_directory)/ssl/win32err.h',
+        # Changed by Dart: All files under '<(ssl_directory)/ssl/bodge' removed.
       ],
+      # Changed by Dart: '<(ssl_directory)/' added to all paths.
       'sources!': [
         '<(ssl_directory)/ssl/os2_err.c',
         '<(ssl_directory)/ssl/os2_err.h',
@@ -92,14 +93,15 @@
         'NO_NSPR_10_SUPPORT',
       ],
       'dependencies': [
-        'zlib.gyp:zlib_dart',
+        # Changed by Dart.
+        'zlib.gyp:zlib_dart',  # Added by Dart (the _dart postfix)
         # Dart: Start of copy of code from 'bodge' conditions section below.
-        'nss.gyp:nspr_dart',
-        'nss.gyp:nss_dart',
+        'nss.gyp:nspr_dart',  # Added by Dart (the _dart postfix)
+        'nss.gyp:nss_dart',  # Added by Dart (the _dart postfix)
       ],
       'export_dependent_settings': [
-        'nss.gyp:nspr_dart',
-        'nss.gyp:nss_dart',
+        'nss.gyp:nspr_dart',  # Added by Dart (the _dart postfix)
+        'nss.gyp:nss_dart',  # Added by Dart (the _dart postfix)
       ],
       'direct_dependent_settings': {
         'include_dirs': [
diff --git a/runtime/bin/net/zlib.gyp b/runtime/bin/net/zlib.gyp
index e2dcd3f..99bca0f 100644
--- a/runtime/bin/net/zlib.gyp
+++ b/runtime/bin/net/zlib.gyp
@@ -7,7 +7,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 # This file is a modified copy of src/third_party/zlib/zlib.gyp from Chromium.
-# Revision 165464 (this should agree with "nss_rev" in DEPS).
+# Revision 169195 (this should agree with "nss_rev" in DEPS).
 {
   # Added by Dart. All Dart comments refer to the following block or line.
   'includes': [
@@ -33,7 +33,7 @@
   'conditions': [[ 'dart_io_support==1', {
   'targets': [
     {
-      'target_name': 'zlib_dart',
+      'target_name': 'zlib_dart',  # Added by Dart (the _dart postfix)
       'type': 'static_library',
       'conditions': [
         ['use_system_zlib==0', {
@@ -96,7 +96,7 @@
       ],
     },
     {
-      'target_name': 'minizip_dart',
+      'target_name': 'minizip_dart',  # Added by Dart (the _dart postfix)
       'type': 'static_library',
       'conditions': [
         ['use_system_minizip==0', {
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 0af539d..750caa6 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "bin/platform.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 
 bool Platform::Initialize() {
@@ -73,7 +74,7 @@
                     NULL);
   if (message_size == 0) {
     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      fprintf(stderr, "FormatMessage failed %d\n", GetLastError());
+      Log::PrintErr("FormatMessage failed %d\n", GetLastError());
     }
     snprintf(error, kBufferSize, "OS Error %d", error_code);
   }
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index c834988..3d593e2 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -15,6 +15,7 @@
 #include <unistd.h>
 
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "bin/thread.h"
 
 
@@ -326,16 +327,15 @@
   bool initialized = ExitCodeHandler::EnsureInitialized();
   if (!initialized) {
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    fprintf(stderr,
-            "Error initializing exit code handler: %s\n",
-            os_error_message);
+    Log::PrintErr("Error initializing exit code handler: %s\n",
+                 os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(read_in));
   if (result < 0) {
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -344,7 +344,7 @@
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -355,7 +355,7 @@
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -368,7 +368,7 @@
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -387,7 +387,7 @@
     TEMP_FAILURE_RETRY(close(write_out[1]));
     TEMP_FAILURE_RETRY(close(exec_control[0]));
     TEMP_FAILURE_RETRY(close(exec_control[1]));
-    fprintf(stderr, "fcntl failed: %s\n", os_error_message);
+    Log::PrintErr("fcntl failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -488,7 +488,7 @@
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index ffc5c88..bd4ed87 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -15,6 +15,7 @@
 #include <unistd.h>
 
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "bin/thread.h"
 
 extern char **environ;
@@ -327,7 +328,7 @@
   bool initialized = ExitCodeHandler::EnsureInitialized();
   if (!initialized) {
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    fprintf(stderr,
+    Log::PrintErr(
             "Error initializing exit code handler: %s\n",
             os_error_message);
     return errno;
@@ -336,7 +337,7 @@
   result = TEMP_FAILURE_RETRY(pipe(read_in));
   if (result < 0) {
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -345,7 +346,7 @@
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -356,7 +357,7 @@
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -369,7 +370,7 @@
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -388,7 +389,7 @@
     TEMP_FAILURE_RETRY(close(write_out[1]));
     TEMP_FAILURE_RETRY(close(exec_control[0]));
     TEMP_FAILURE_RETRY(close(exec_control[1]));
-    fprintf(stderr, "fcntl failed: %s\n", os_error_message);
+    Log::PrintErr("fcntl failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -487,7 +488,7 @@
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 11aac9f..aa15940 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -14,6 +14,7 @@
 #include <unistd.h>
 
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "bin/thread.h"
 
 extern char **environ;
@@ -326,16 +327,15 @@
   bool initialized = ExitCodeHandler::EnsureInitialized();
   if (!initialized) {
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    fprintf(stderr,
-            "Error initializing exit code handler: %s\n",
-            os_error_message);
+    Log::PrintErr("Error initializing exit code handler: %s\n",
+                       os_error_message);
     return errno;
   }
 
   result = TEMP_FAILURE_RETRY(pipe(read_in));
   if (result < 0) {
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -344,7 +344,7 @@
     SetChildOsErrorMessage(os_error_message, os_error_message_len);
     TEMP_FAILURE_RETRY(close(read_in[0]));
     TEMP_FAILURE_RETRY(close(read_in[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -355,7 +355,7 @@
     TEMP_FAILURE_RETRY(close(read_in[1]));
     TEMP_FAILURE_RETRY(close(read_err[0]));
     TEMP_FAILURE_RETRY(close(read_err[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -368,7 +368,7 @@
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -387,7 +387,7 @@
     TEMP_FAILURE_RETRY(close(write_out[1]));
     TEMP_FAILURE_RETRY(close(exec_control[0]));
     TEMP_FAILURE_RETRY(close(exec_control[1]));
-    fprintf(stderr, "fcntl failed: %s\n", os_error_message);
+    Log::PrintErr("fcntl failed: %s\n", os_error_message);
     return errno;
   }
 
@@ -486,7 +486,7 @@
     TEMP_FAILURE_RETRY(close(read_err[1]));
     TEMP_FAILURE_RETRY(close(write_out[0]));
     TEMP_FAILURE_RETRY(close(write_out[1]));
-    fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message);
+    Log::PrintErr("Error pipe creation failed: %s\n", os_error_message);
     return errno;
   }
 
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 3094176..0a9eb52 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -7,6 +7,7 @@
 #include "bin/builtin.h"
 #include "bin/process.h"
 #include "bin/eventhandler.h"
+#include "bin/log.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "platform/globals.h"
@@ -221,7 +222,7 @@
                         NULL);
 
     if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
-      fprintf(stderr, "CreateNamedPipe failed %d\n", GetLastError());
+      Log::PrintErr("CreateNamedPipe failed %d\n", GetLastError());
       return false;
     }
 
@@ -234,7 +235,7 @@
                    FILE_READ_ATTRIBUTES | FILE_FLAG_OVERLAPPED,
                    NULL);
     if (handles[kReadHandle] == INVALID_HANDLE_VALUE) {
-      fprintf(stderr, "CreateFile failed %d\n", GetLastError());
+      Log::PrintErr("CreateFile failed %d\n", GetLastError());
       return false;
     }
   } else {
@@ -250,7 +251,7 @@
                         NULL);
 
     if (handles[kReadHandle] == INVALID_HANDLE_VALUE) {
-      fprintf(stderr, "CreateNamedPipe failed %d\n", GetLastError());
+      Log::PrintErr("CreateNamedPipe failed %d\n", GetLastError());
       return false;
     }
 
@@ -263,7 +264,7 @@
                    FILE_WRITE_ATTRIBUTES | FILE_FLAG_OVERLAPPED,
                    NULL);
     if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
-      fprintf(stderr, "CreateFile failed %d\n", GetLastError());
+      Log::PrintErr("CreateFile failed %d\n", GetLastError());
       return false;
     }
   }
@@ -275,7 +276,7 @@
   for (int i = kReadHandle; i < kWriteHandle; i++) {
     if (handles[i] != INVALID_HANDLE_VALUE) {
       if (!CloseHandle(handles[i])) {
-        fprintf(stderr, "CloseHandle failed %d\n", GetLastError());
+        Log::PrintErr("CloseHandle failed %d\n", GetLastError());
       }
       handles[i] = INVALID_HANDLE_VALUE;
     }
@@ -306,7 +307,7 @@
                     NULL);
   if (message_size == 0) {
     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      fprintf(stderr, "FormatMessage failed %d\n", GetLastError());
+      Log::PrintErr("FormatMessage failed %d\n", GetLastError());
     }
     snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code);
   }
@@ -338,14 +339,14 @@
   UUID uuid;
   RPC_STATUS status = UuidCreateSequential(&uuid);
   if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
-    fprintf(stderr, "UuidCreateSequential failed %d\n", status);
+    Log::PrintErr("UuidCreateSequential failed %d\n", status);
     SetOsErrorMessage(os_error_message, os_error_message_len);
     return status;
   }
   RPC_CSTR uuid_string;
   status = UuidToString(&uuid, &uuid_string);
   if (status != RPC_S_OK) {
-    fprintf(stderr, "UuidToString failed %d\n", status);
+    Log::PrintErr("UuidToString failed %d\n", status);
     SetOsErrorMessage(os_error_message, os_error_message_len);
     return status;
   }
@@ -357,7 +358,7 @@
   }
   status = RpcStringFree(&uuid_string);
   if (status != RPC_S_OK) {
-    fprintf(stderr, "RpcStringFree failed %d\n", status);
+    Log::PrintErr("RpcStringFree failed %d\n", status);
     SetOsErrorMessage(os_error_message, os_error_message_len);
     return status;
   }
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index f539d31..d73b046 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -138,8 +138,8 @@
   bool set_vm_flags_success = Flags::ProcessCommandLineFlags(dart_argc,
                                                              dart_argv);
   ASSERT(set_vm_flags_success);
-  bool init_success = Dart::InitOnce(NULL, NULL, NULL);
-  ASSERT(init_success);
+  const char* err_msg = Dart::InitOnce(NULL, NULL, NULL);
+  ASSERT(err_msg == NULL);
   // Apply the filter to all registered tests.
   TestCaseBase::RunAll();
   // Apply the filter to all registered benchmarks.
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
new file mode 100644
index 0000000..f297aed
--- /dev/null
+++ b/runtime/bin/secure_socket.cc
@@ -0,0 +1,484 @@
+// 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.
+
+#include "bin/secure_socket.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <prerror.h>
+#include <prinit.h>
+#include <prnetdb.h>
+#include <ssl.h>
+#include <sslproto.h>
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/net/nss_memio.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+#include "platform/utils.h"
+
+#include "include/dart_api.h"
+
+bool SSLFilter::library_initialized_ = false;
+dart::Mutex SSLFilter::mutex_;  // To protect library initialization.
+// The password is needed when creating secure server sockets.  It can
+// be null if only secure client sockets are used.
+const char* SSLFilter::password_ = NULL;
+
+static const int kSSLFilterNativeFieldIndex = 0;
+
+static SSLFilter* GetFilter(Dart_NativeArguments args) {
+  SSLFilter* filter;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this,
+      kSSLFilterNativeFieldIndex,
+      reinterpret_cast<intptr_t*>(&filter)));
+  return filter;
+}
+
+
+static void SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_SetNativeInstanceField(
+      dart_this,
+      kSSLFilterNativeFieldIndex,
+      reinterpret_cast<intptr_t>(filter)));
+}
+
+
+void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  SSLFilter* filter = new SSLFilter;
+  SetFilter(args, filter);
+  filter->Init(dart_this);
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
+  Dart_Handle is_server_object = ThrowIfError(Dart_GetNativeArgument(args, 3));
+  Dart_Handle certificate_name_object =
+      ThrowIfError(Dart_GetNativeArgument(args, 4));
+
+  const char* host_name = NULL;
+  // TODO(whesse): Is truncating a Dart string containing \0 what we want?
+  ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
+
+  int64_t port;
+  if (!DartUtils::GetInt64Value(port_object, &port) ||
+      port < 0 || port > 65535) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Illegal port parameter in _SSLFilter.connect"));
+  }
+
+  if (!Dart_IsBoolean(is_server_object)) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Illegal is_server parameter in _SSLFilter.connect"));
+  }
+  bool is_server = DartUtils::GetBooleanValue(is_server_object);
+
+  const char* certificate_name = NULL;
+  // If this is a server connection, get the certificate to connect with.
+  // TODO(whesse): Use this parameter for a client certificate as well.
+  if (is_server) {
+    if (!Dart_IsString(certificate_name_object)) {
+      Dart_ThrowException(DartUtils::NewDartArgumentError(
+          "Non-String certificate parameter in _SSLFilter.connect"));
+    }
+    ThrowIfError(Dart_StringToCString(certificate_name_object,
+                                      &certificate_name));
+  }
+
+  GetFilter(args)->Connect(host_name,
+                              static_cast<int>(port),
+                              is_server,
+                              certificate_name);
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  SSLFilter* filter = GetFilter(args);
+  SetFilter(args, NULL);
+  filter->Destroy();
+  delete filter;
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  GetFilter(args)->Handshake();
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
+    Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle handshake_complete =
+      ThrowIfError(Dart_GetNativeArgument(args, 1));
+  if (!Dart_IsClosure(handshake_complete)) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Illegal argument to RegisterHandshakeCompleteCallback"));
+  }
+  GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_ProcessBuffer)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle buffer_id_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  int64_t buffer_id = DartUtils::GetIntegerValue(buffer_id_object);
+  if (buffer_id < 0 || buffer_id >= SSLFilter::kNumBuffers) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Illegal argument to ProcessBuffer"));
+  }
+
+  intptr_t bytes_read =
+      GetFilter(args)->ProcessBuffer(static_cast<int>(buffer_id));
+  Dart_SetReturnValue(args, Dart_NewInteger(bytes_read));
+  Dart_ExitScope();
+}
+
+
+void FUNCTION_NAME(SecureSocket_SetCertificateDatabase)
+    (Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle certificate_database_object =
+      ThrowIfError(Dart_GetNativeArgument(args, 0));
+  // Check that the type is string, and get the UTF-8 C string value from it.
+  const char* certificate_database = NULL;
+  if (Dart_IsString(certificate_database_object)) {
+    ThrowIfError(Dart_StringToCString(certificate_database_object,
+                                      &certificate_database));
+  } else {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Non-String certificate directory argument to SetCertificateDatabase"));
+  }
+
+  Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  // Check that the type is string or null,
+  // and get the UTF-8 C string value from it.
+  const char* password = NULL;
+  if (Dart_IsString(password_object)) {
+    ThrowIfError(Dart_StringToCString(password_object, &password));
+  } else if (Dart_IsNull(password_object)) {
+    // Pass the empty string as the password.
+    password = "";
+  } else {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Password argument to SetCertificateDatabase is not a String or null"));
+  }
+
+  SSLFilter::InitializeLibrary(certificate_database, password);
+  Dart_ExitScope();
+}
+
+
+void SSLFilter::Init(Dart_Handle dart_this) {
+  string_start_ = ThrowIfError(
+      Dart_NewPersistentHandle(DartUtils::NewString("start")));
+  string_length_ = ThrowIfError(
+      Dart_NewPersistentHandle(DartUtils::NewString("length")));
+
+  InitializeBuffers(dart_this);
+  filter_ = memio_CreateIOLayer(kMemioBufferSize);
+}
+
+
+void SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
+  // Create SSLFilter buffers as ExternalUint8Array objects.
+  Dart_Handle dart_buffers_object = ThrowIfError(
+      Dart_GetField(dart_this, DartUtils::NewString("buffers")));
+  Dart_Handle dart_buffer_object =
+      Dart_ListGetAt(dart_buffers_object, kReadPlaintext);
+  Dart_Handle external_buffer_class =
+      Dart_InstanceGetClass(dart_buffer_object);
+  Dart_Handle dart_buffer_size = ThrowIfError(
+      Dart_GetField(external_buffer_class, DartUtils::NewString("SIZE")));
+  buffer_size_ = DartUtils::GetIntegerValue(dart_buffer_size);
+  if (buffer_size_ <= 0 || buffer_size_ > 1024 * 1024) {
+    Dart_ThrowException(
+        DartUtils::NewString("Invalid buffer size in _ExternalBuffer"));
+  }
+
+  Dart_Handle data_identifier = DartUtils::NewString("data");
+  for (int i = 0; i < kNumBuffers; ++i) {
+    dart_buffer_objects_[i] = ThrowIfError(
+        Dart_NewPersistentHandle(Dart_ListGetAt(dart_buffers_object, i)));
+    buffers_[i] = new uint8_t[buffer_size_];
+    Dart_Handle data = ThrowIfError(
+      Dart_NewExternalByteArray(buffers_[i], buffer_size_, NULL, NULL));
+    ThrowIfError(Dart_SetField(dart_buffer_objects_[i],
+                               data_identifier,
+                               data));
+  }
+}
+
+
+void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
+  ASSERT(NULL == handshake_complete_);
+  handshake_complete_ = ThrowIfError(Dart_NewPersistentHandle(complete));
+}
+
+
+void SSLFilter::InitializeLibrary(const char* certificate_database,
+                                  const char* password) {
+  MutexLocker locker(&mutex_);
+  if (!library_initialized_) {
+    library_initialized_ = true;
+    password_ = strdup(password);  // This one copy persists until Dart exits.
+    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+    // TODO(whesse): Verify there are no UTF-8 issues here.
+    SECStatus status = NSS_Init(certificate_database);
+    if (status != SECSuccess) {
+      ThrowPRException("Unsuccessful NSS_Init call.");
+    }
+
+    status = NSS_SetDomesticPolicy();
+    if (status != SECSuccess) {
+      ThrowPRException("Unsuccessful NSS_SetDomesticPolicy call.");
+    }
+    // Enable TLS, as well as SSL3 and SSL2.
+    status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
+    if (status != SECSuccess) {
+      ThrowPRException("Unsuccessful SSL_OptionSetDefault enable TLS call.");
+    }
+  } else {
+    ThrowException("Called SSLFilter::InitializeLibrary more than once");
+  }
+}
+
+char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) {
+  if (!retry) {
+    return PL_strdup(static_cast<char*>(arg));  // Freed by NSS internals.
+  }
+  return NULL;
+}
+
+void SSLFilter::Connect(const char* host_name,
+                        int port,
+                        bool is_server,
+                        const char* certificate_name) {
+  is_server_ = is_server;
+  if (in_handshake_) {
+    ThrowException("Connect called while already in handshake state.");
+  }
+
+  filter_ = SSL_ImportFD(NULL, filter_);
+  if (filter_ == NULL) {
+    ThrowPRException("Unsuccessful SSL_ImportFD call");
+  }
+
+  SECStatus status;
+  if (is_server) {
+    PK11_SetPasswordFunc(PasswordCallback);
+    CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB();
+    if (certificate_database == NULL) {
+      ThrowPRException("Certificate database cannot be loaded");
+    }
+    CERTCertificate* certificate = CERT_FindCertByNameString(
+        certificate_database,
+        const_cast<char*>(certificate_name));
+    if (certificate == NULL) {
+      ThrowPRException("Cannot find server certificate by name");
+    }
+    SECKEYPrivateKey* key = PK11_FindKeyByAnyCert(
+        certificate,
+        static_cast<void*>(const_cast<char*>(password_)));
+    if (key == NULL) {
+      if (PR_GetError() == -8177) {
+        ThrowPRException("Certificate database password incorrect");
+      } else {
+        ThrowPRException("Unsuccessful PK11_FindKeyByAnyCert call."
+                         " Cannot find private key for certificate");
+      }
+    }
+    // kt_rsa (key type RSA) is an enum constant from the NSS libraries.
+    // TODO(whesse): Allow different key types.
+    status = SSL_ConfigSecureServer(filter_, certificate, key, kt_rsa);
+    if (status != SECSuccess) {
+      ThrowPRException("Unsuccessful SSL_ConfigSecureServer call");
+    }
+  } else {  // Client.
+    if (SSL_SetURL(filter_, host_name) == -1) {
+      ThrowPRException("Unsuccessful SetURL call");
+    }
+  }
+
+  PRBool as_server = is_server ? PR_TRUE : PR_FALSE;  // Convert bool to PRBool.
+  status = SSL_ResetHandshake(filter_, as_server);
+  if (status != SECSuccess) {
+    ThrowPRException("Unsuccessful SSL_ResetHandshake call");
+  }
+
+  // SetPeerAddress
+  PRNetAddr host_address;
+  char host_entry_buffer[PR_NETDB_BUF_SIZE];
+  PRHostEnt host_entry;
+  PRStatus rv = PR_GetHostByName(host_name, host_entry_buffer,
+                                 PR_NETDB_BUF_SIZE, &host_entry);
+  if (rv != PR_SUCCESS) {
+    ThrowPRException("Unsuccessful PR_GetHostByName call");
+  }
+
+  int index = PR_EnumerateHostEnt(0, &host_entry, port, &host_address);
+  if (index == -1 || index == 0) {
+    ThrowPRException("Unsuccessful PR_EnumerateHostEnt call");
+  }
+  memio_SetPeerName(filter_, &host_address);
+}
+
+
+void SSLFilter::Handshake() {
+  SECStatus status = SSL_ForceHandshake(filter_);
+  if (status == SECSuccess) {
+    if (in_handshake_) {
+      ThrowIfError(Dart_InvokeClosure(handshake_complete_, 0, NULL));
+      in_handshake_ = false;
+    }
+  } else {
+    PRErrorCode error = PR_GetError();
+    if (error == PR_WOULD_BLOCK_ERROR) {
+      if (!in_handshake_) {
+        in_handshake_ = true;
+      }
+    } else {
+      if (is_server_) {
+        ThrowPRException("Unexpected handshake error in server");
+      } else {
+        ThrowPRException("Unexpected handshake error in client");
+      }
+    }
+  }
+}
+
+
+void SSLFilter::Destroy() {
+  for (int i = 0; i < kNumBuffers; ++i) {
+    Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
+    delete[] buffers_[i];
+  }
+  Dart_DeletePersistentHandle(string_start_);
+  Dart_DeletePersistentHandle(string_length_);
+  Dart_DeletePersistentHandle(handshake_complete_);
+  // TODO(whesse): Free NSS objects here.
+}
+
+
+intptr_t SSLFilter::ProcessBuffer(int buffer_index) {
+  Dart_Handle buffer_object = dart_buffer_objects_[buffer_index];
+  Dart_Handle start_object = ThrowIfError(
+      Dart_GetField(buffer_object, string_start_));
+  Dart_Handle length_object = ThrowIfError(
+      Dart_GetField(buffer_object, string_length_));
+  int64_t unsafe_start = DartUtils::GetIntegerValue(start_object);
+  int64_t unsafe_length = DartUtils::GetIntegerValue(length_object);
+  ASSERT(unsafe_start >= 0);
+  ASSERT(unsafe_start < buffer_size_);
+  ASSERT(unsafe_length >= 0);
+  ASSERT(unsafe_length <= buffer_size_);
+  intptr_t start = static_cast<intptr_t>(unsafe_start);
+  intptr_t length = static_cast<intptr_t>(unsafe_length);
+  uint8_t* buffer = buffers_[buffer_index];
+
+  int bytes_processed = 0;
+  switch (buffer_index) {
+    case kReadPlaintext: {
+      int bytes_free = buffer_size_ - start - length;
+      bytes_processed = PR_Read(filter_,
+                                buffer + start + length,
+                                bytes_free);
+      if (bytes_processed < 0) {
+        ASSERT(bytes_processed == -1);
+        // TODO(whesse): Handle unexpected errors here.
+        PRErrorCode pr_error = PR_GetError();
+        if (PR_WOULD_BLOCK_ERROR != pr_error) {
+          ThrowPRException("Error reading plaintext from SSLFilter");
+        }
+        bytes_processed = 0;
+      }
+      break;
+    }
+
+    case kWriteEncrypted: {
+      const uint8_t* buf1;
+      const uint8_t* buf2;
+      unsigned int len1;
+      unsigned int len2;
+      int bytes_free = buffer_size_ - start - length;
+      memio_Private* secret = memio_GetSecret(filter_);
+      memio_GetWriteParams(secret, &buf1, &len1, &buf2, &len2);
+      int bytes_to_send =
+          dart::Utils::Minimum(len1, static_cast<unsigned>(bytes_free));
+      if (bytes_to_send > 0) {
+        memmove(buffer + start + length, buf1, bytes_to_send);
+        bytes_processed = bytes_to_send;
+      }
+      bytes_to_send = dart::Utils::Minimum(len2,
+          static_cast<unsigned>(bytes_free - bytes_processed));
+      if (bytes_to_send > 0) {
+        memmove(buffer + start + length + bytes_processed, buf2,
+                bytes_to_send);
+        bytes_processed += bytes_to_send;
+      }
+      if (bytes_processed > 0) {
+        memio_PutWriteResult(secret, bytes_processed);
+      }
+      break;
+    }
+
+    case kReadEncrypted: {
+      if (length > 0) {
+        bytes_processed = length;
+        memio_Private* secret = memio_GetSecret(filter_);
+        uint8_t* filter_buf;
+        int free_bytes = memio_GetReadParams(secret, &filter_buf);
+        if (free_bytes < bytes_processed) bytes_processed = free_bytes;
+        memmove(filter_buf,
+                buffer + start,
+                bytes_processed);
+        memio_PutReadResult(secret, bytes_processed);
+      }
+      break;
+    }
+
+    case kWritePlaintext: {
+      if (length > 0) {
+        bytes_processed = PR_Write(filter_,
+                                   buffer + start,
+                                   length);
+      }
+
+      if (bytes_processed < 0) {
+        ASSERT(bytes_processed == -1);
+        // TODO(whesse): Handle unexpected errors here.
+        PRErrorCode pr_error = PR_GetError();
+        if (PR_WOULD_BLOCK_ERROR != pr_error) {
+          ThrowPRException("Error reading plaintext from SSLFilter");
+        }
+        bytes_processed = 0;
+      }
+      break;
+    }
+  }
+  return bytes_processed;
+}
diff --git a/runtime/bin/tls_socket.h b/runtime/bin/secure_socket.h
similarity index 77%
rename from runtime/bin/tls_socket.h
rename to runtime/bin/secure_socket.h
index fc39b70..22ef7dc 100644
--- a/runtime/bin/tls_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -2,8 +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.
 
-#ifndef BIN_TLS_SOCKET_H_
-#define BIN_TLS_SOCKET_H_
+#ifndef BIN_SECURE_SOCKET_H_
+#define BIN_SECURE_SOCKET_H_
 
 #include <stdlib.h>
 #include <string.h>
@@ -44,15 +44,15 @@
 }
 
 /*
- * TlsFilter encapsulates the NSS SSL(TLS) code in a filter, that communicates
- * with the containing _TlsFilterImpl Dart object through four shared
+ * SSLFilter encapsulates the NSS SSL(TLS) code in a filter, that communicates
+ * with the containing _SecureFilterImpl Dart object through four shared
  * ExternalByteArray buffers, for reading and writing plaintext, and
  * reading and writing encrypted text.  The filter handles handshaking
  * and certificate verification.
  */
-class TlsFilter {
+class SSLFilter {
  public:
-  // These enums must agree with those in sdk/lib/io/tls_socket.dart.
+  // These enums must agree with those in sdk/lib/io/secure_socket.dart.
   enum BufferIndex {
     kReadPlaintext,
     kWritePlaintext,
@@ -61,26 +61,30 @@
     kNumBuffers
   };
 
-  TlsFilter()
+  SSLFilter()
       : string_start_(NULL),
         string_length_(NULL),
         handshake_complete_(NULL),
         in_handshake_(false),
-        memio_(NULL) { }
+        filter_(NULL) { }
 
   void Init(Dart_Handle dart_this);
-  void Connect(const char* host, int port);
+  void Connect(const char* host,
+               int port,
+               bool is_server,
+               const char* certificate_name);
   void Destroy();
-  void DestroyPlatformIndependent();
   void Handshake();
   void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
-  static void InitializeLibrary(const char* pkcert_directory);
+  static void InitializeLibrary(const char* certificate_database,
+                                const char* password);
 
   intptr_t ProcessBuffer(int bufferIndex);
 
  private:
   static const int kMemioBufferSize = 20 * KB;
   static bool library_initialized_;
+  static const char* password_;
   static dart::Mutex mutex_;  // To protect library initialization.
 
   uint8_t* buffers_[kNumBuffers];
@@ -90,12 +94,13 @@
   Dart_Handle dart_buffer_objects_[kNumBuffers];
   Dart_Handle handshake_complete_;
   bool in_handshake_;
-  PRFileDesc* memio_;
+  bool is_server_;
+  PRFileDesc* filter_;
 
   void InitializeBuffers(Dart_Handle dart_this);
   void InitializePlatformData();
 
-  DISALLOW_COPY_AND_ASSIGN(TlsFilter);
+  DISALLOW_COPY_AND_ASSIGN(SSLFilter);
 };
 
-#endif  // BIN_TLS_SOCKET_H_
+#endif  // BIN_SECURE_SOCKET_H_
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
new file mode 100644
index 0000000..34edc7e
--- /dev/null
+++ b/runtime/bin/secure_socket_patch.dart
@@ -0,0 +1,58 @@
+// 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.
+
+patch class SecureSocket {
+  /* patch */ static void setCertificateDatabase(String certificateDatabase,
+                                                 [String password])
+      native "SecureSocket_SetCertificateDatabase";
+}
+
+
+patch class _SecureFilter {
+  /* patch */ factory _SecureFilter() => new _SecureFilterImpl();
+}
+
+
+/**
+ * _SecureFilterImpl wraps a filter that encrypts and decrypts data travelling
+ * over an encrypted socket.  The filter also handles the handshaking
+ * and certificate verification.
+ *
+ * The filter exposes its input and output buffers as Dart objects that
+ * are backed by an external C array of bytes, so that both Dart code and
+ * native code can access the same data.
+ */
+class _SecureFilterImpl
+    extends NativeFieldWrapperClass1
+    implements _SecureFilter {
+  _SecureFilterImpl() {
+    buffers = new List<_ExternalBuffer>(_SecureSocket.NUM_BUFFERS);
+    for (int i = 0; i < _SecureSocket.NUM_BUFFERS; ++i) {
+      buffers[i] = new _ExternalBuffer();
+    }
+  }
+
+  void connect(String hostName,
+               int port,
+               bool is_server,
+               String certificate_name) native "SecureSocket_Connect";
+
+  void destroy() {
+    buffers = null;
+    _destroy();
+  }
+
+  void _destroy() native "SecureSocket_Destroy";
+
+  void handshake() native "SecureSocket_Handshake";
+
+  void init() native "SecureSocket_Init";
+
+  int processBuffer(int bufferIndex) native "SecureSocket_ProcessBuffer";
+
+  void registerHandshakeCompleteCallback(Function handshakeCompleteHandler)
+      native "SecureSocket_RegisterHandshakeCompleteCallback";
+
+  List<_ExternalBuffer> buffers;
+}
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index eac7d12..cffae9f 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -8,8 +8,9 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "bin/fdutils.h"
 #include "bin/socket.h"
+#include "bin/fdutils.h"
+#include "bin/log.h"
 
 
 bool Socket::Initialize() {
@@ -25,7 +26,7 @@
 
   fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
   if (fd < 0) {
-    fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
     return -1;
   }
 
@@ -35,7 +36,7 @@
   server = gethostbyname(host);
   if (server == NULL) {
     TEMP_FAILURE_RETRY(close(fd));
-    fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
     return -1;
   }
 
@@ -93,7 +94,7 @@
           getsockname(fd,
                       reinterpret_cast<struct sockaddr *>(&socket_address),
                       &size))) {
-    fprintf(stderr, "Error getsockname: %s\n", strerror(errno));
+    Log::PrintErr("Error getsockname: %s\n", strerror(errno));
     return 0;
   }
   return ntohs(socket_address.sin_port);
@@ -108,14 +109,14 @@
           getpeername(fd,
                       reinterpret_cast<struct sockaddr *>(&socket_address),
                       &size))) {
-    fprintf(stderr, "Error getpeername: %s\n", strerror(errno));
+    Log::PrintErr("Error getpeername: %s\n", strerror(errno));
     return false;
   }
   if (inet_ntop(socket_address.sin_family,
                 reinterpret_cast<const void *>(&socket_address.sin_addr),
                 host,
                 INET_ADDRSTRLEN) == NULL) {
-    fprintf(stderr, "Error inet_ntop: %s\n", strerror(errno));
+    Log::PrintErr("Error inet_ntop: %s\n", strerror(errno));
     return false;
   }
   *port = ntohs(socket_address.sin_port);
@@ -185,7 +186,7 @@
 
   fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
   if (fd < 0) {
-    fprintf(stderr, "Error CreateBind: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateBind: %s\n", strerror(errno));
     return -1;
   }
 
@@ -205,12 +206,12 @@
                reinterpret_cast<struct sockaddr *>(&server_address),
                sizeof(server_address))) < 0) {
     TEMP_FAILURE_RETRY(close(fd));
-    fprintf(stderr, "Error Bind: %s\n", strerror(errno));
+    Log::PrintErr("Error Bind: %s\n", strerror(errno));
     return -1;
   }
 
   if (TEMP_FAILURE_RETRY(listen(fd, backlog)) != 0) {
-    fprintf(stderr, "Error Listen: %s\n", strerror(errno));
+    Log::PrintErr("Error Listen: %s\n", strerror(errno));
     return -1;
   }
 
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 89dd267..d8be1dc 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -9,6 +9,7 @@
 #include <unistd.h>
 
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 
 
@@ -25,7 +26,7 @@
 
   fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
   if (fd < 0) {
-    fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
     return -1;
   }
 
@@ -39,7 +40,7 @@
   if (gethostbyname_r(
           host, &server, temp_buf, kTempBufSize, &unused, &err) != 0) {
     TEMP_FAILURE_RETRY(close(fd));
-    fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
     return -1;
   }
 
@@ -97,7 +98,7 @@
           getsockname(fd,
                       reinterpret_cast<struct sockaddr *>(&socket_address),
                       &size))) {
-    fprintf(stderr, "Error getsockname: %s\n", strerror(errno));
+    Log::PrintErr("Error getsockname: %s\n", strerror(errno));
     return 0;
   }
   return ntohs(socket_address.sin_port);
@@ -112,14 +113,14 @@
           getpeername(fd,
                       reinterpret_cast<struct sockaddr *>(&socket_address),
                       &size))) {
-    fprintf(stderr, "Error getpeername: %s\n", strerror(errno));
+    Log::PrintErr("Error getpeername: %s\n", strerror(errno));
     return false;
   }
   if (inet_ntop(socket_address.sin_family,
                 reinterpret_cast<const void *>(&socket_address.sin_addr),
                 host,
                 INET_ADDRSTRLEN) == NULL) {
-    fprintf(stderr, "Error inet_ntop: %s\n", strerror(errno));
+    Log::PrintErr("Error inet_ntop: %s\n", strerror(errno));
     return false;
   }
   *port = ntohs(socket_address.sin_port);
@@ -188,7 +189,7 @@
 
   fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
   if (fd < 0) {
-    fprintf(stderr, "Error CreateBind: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateBind: %s\n", strerror(errno));
     return -1;
   }
 
@@ -208,12 +209,12 @@
                reinterpret_cast<struct sockaddr *>(&server_address),
                sizeof(server_address))) < 0) {
     TEMP_FAILURE_RETRY(close(fd));
-    fprintf(stderr, "Error Bind: %s\n", strerror(errno));
+    Log::PrintErr("Error Bind: %s\n", strerror(errno));
     return -1;
   }
 
   if (TEMP_FAILURE_RETRY(listen(fd, backlog)) != 0) {
-    fprintf(stderr, "Error Listen: %s\n", strerror(errno));
+    Log::PrintErr("Error Listen: %s\n", strerror(errno));
     return -1;
   }
 
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 32db433..275169f 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -9,6 +9,7 @@
 #include <unistd.h>
 
 #include "bin/fdutils.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 
 
@@ -25,7 +26,7 @@
 
   fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
   if (fd < 0) {
-    fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
     return -1;
   }
 
@@ -35,7 +36,7 @@
   server = gethostbyname(host);
   if (server == NULL) {
     TEMP_FAILURE_RETRY(close(fd));
-    fprintf(stderr, "Error CreateConnect: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateConnect: %s\n", strerror(errno));
     return -1;
   }
 
@@ -93,7 +94,7 @@
           getsockname(fd,
                       reinterpret_cast<struct sockaddr *>(&socket_address),
                       &size))) {
-    fprintf(stderr, "Error getsockname: %s\n", strerror(errno));
+    Log::PrintErr("Error getsockname: %s\n", strerror(errno));
     return 0;
   }
   return ntohs(socket_address.sin_port);
@@ -108,14 +109,14 @@
           getpeername(fd,
                       reinterpret_cast<struct sockaddr *>(&socket_address),
                       &size))) {
-    fprintf(stderr, "Error getpeername: %s\n", strerror(errno));
+    Log::PrintErr("Error getpeername: %s\n", strerror(errno));
     return false;
   }
   if (inet_ntop(socket_address.sin_family,
                 reinterpret_cast<const void *>(&socket_address.sin_addr),
                 host,
                 INET_ADDRSTRLEN) == NULL) {
-    fprintf(stderr, "Error inet_ntop: %s\n", strerror(errno));
+    Log::PrintErr("Error inet_ntop: %s\n", strerror(errno));
     return false;
   }
   *port = ntohs(socket_address.sin_port);
@@ -184,7 +185,7 @@
 
   fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_STREAM, 0));
   if (fd < 0) {
-    fprintf(stderr, "Error CreateBind: %s\n", strerror(errno));
+    Log::PrintErr("Error CreateBind: %s\n", strerror(errno));
     return -1;
   }
 
@@ -204,12 +205,12 @@
                reinterpret_cast<struct sockaddr *>(&server_address),
                sizeof(server_address))) < 0) {
     TEMP_FAILURE_RETRY(close(fd));
-    fprintf(stderr, "Error Bind: %s\n", strerror(errno));
+    Log::PrintErr("Error Bind: %s\n", strerror(errno));
     return -1;
   }
 
   if (TEMP_FAILURE_RETRY(listen(fd, backlog)) != 0) {
-    fprintf(stderr, "Error Listen: %s\n", strerror(errno));
+    Log::PrintErr("Error Listen: %s\n", strerror(errno));
     return -1;
   }
 
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 7ce75d3..6e58985 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -239,8 +239,8 @@
 
   bool _propagateError(Exception e) => false;
 
-  abstract bool _isListenSocket();
-  abstract bool _isPipe();
+  bool _isListenSocket();
+  bool _isPipe();
 
   // Is this socket closed.
   bool _closed;
@@ -465,7 +465,7 @@
   }
 
   void set onConnect(void callback()) {
-    if (_seenFirstOutEvent || _outputStream != null) {
+    if (_seenFirstOutEvent) {
       throw new StreamException(
           "Cannot set connect handler when already connected");
     }
@@ -509,7 +509,7 @@
     if (_outputStream == null) {
       if (_handlerMap[_SocketBase._OUT_EVENT] != null) {
         throw new StreamException(
-            "Cannot get input stream when socket handlers are used");
+            "Cannot get output stream when socket handlers are used");
       }
       _outputStream = new _SocketOutputStream(this);
     }
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 102f078..6e1a0bc 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -4,6 +4,7 @@
 
 #include "bin/builtin.h"
 #include "bin/eventhandler.h"
+#include "bin/log.h"
 #include "bin/socket.h"
 
 bool Socket::Initialize() {
@@ -12,7 +13,7 @@
   WORD version_requested = MAKEWORD(1, 0);
   err = WSAStartup(version_requested, &winsock_data);
   if (err != 0) {
-    fprintf(stderr, "Unable to initialize Winsock: %d\n", WSAGetLastError());
+    Log::PrintErr("Unable to initialize Winsock: %d\n", WSAGetLastError());
   }
   return err == 0;
 }
@@ -43,7 +44,7 @@
   if (getsockname(socket_handle->socket(),
                   reinterpret_cast<struct sockaddr *>(&socket_address),
                   &size)) {
-    fprintf(stderr, "Error getsockname: %s\n", strerror(errno));
+    Log::PrintErr("Error getsockname: %s\n", strerror(errno));
     return 0;
   }
   return ntohs(socket_address.sin_port);
@@ -58,7 +59,7 @@
   if (getpeername(socket_handle->socket(),
                   reinterpret_cast<struct sockaddr *>(&socket_address),
                   &size)) {
-    fprintf(stderr, "Error getpeername: %s\n", strerror(errno));
+    Log::PrintErr("Error getpeername: %s\n", strerror(errno));
     return false;
   }
   *port = ntohs(socket_address.sin_port);
@@ -72,7 +73,7 @@
                                host,
                                &len);
   if (err != 0) {
-    fprintf(stderr, "Error WSAAddressToString: %d\n", WSAGetLastError());
+    Log::PrintErr("Error WSAAddressToString: %d\n", WSAGetLastError());
     return false;
   }
   return true;
diff --git a/runtime/bin/tls_socket.cc b/runtime/bin/tls_socket.cc
deleted file mode 100644
index c4bc0a5..0000000
--- a/runtime/bin/tls_socket.cc
+++ /dev/null
@@ -1,385 +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.
-
-#include "bin/tls_socket.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <nss.h>
-#include <prerror.h>
-#include <prinit.h>
-#include <prnetdb.h>
-#include <ssl.h>
-
-#include "bin/builtin.h"
-#include "bin/dartutils.h"
-#include "bin/net/nss_memio.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-#include "platform/utils.h"
-
-#include "include/dart_api.h"
-
-bool TlsFilter::library_initialized_ = false;
-dart::Mutex TlsFilter::mutex_;  // To protect library initialization.
-static const int kTlsFilterNativeFieldIndex = 0;
-
-static TlsFilter* GetTlsFilter(Dart_NativeArguments args) {
-  TlsFilter* filter;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(Dart_GetNativeInstanceField(
-      dart_this,
-      kTlsFilterNativeFieldIndex,
-      reinterpret_cast<intptr_t*>(&filter)));
-  return filter;
-}
-
-
-static void SetTlsFilter(Dart_NativeArguments args, TlsFilter* filter) {
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(Dart_SetNativeInstanceField(
-      dart_this,
-      kTlsFilterNativeFieldIndex,
-      reinterpret_cast<intptr_t>(filter)));
-}
-
-
-void FUNCTION_NAME(TlsSocket_Init)(Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  TlsFilter* filter = new TlsFilter;
-  SetTlsFilter(args, filter);
-  filter->Init(dart_this);
-  Dart_ExitScope();
-}
-
-
-void FUNCTION_NAME(TlsSocket_Connect)(Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle host_name = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
-
-  const char* host_name_string = NULL;
-  // TODO(whesse): Is truncating a Dart string containing \0 what we want?
-  ThrowIfError(Dart_StringToCString(host_name, &host_name_string));
-
-  int64_t port;
-  if (!DartUtils::GetInt64Value(port_object, &port) ||
-      port < 0 || port > 65535) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-      "Illegal port parameter in TlsSocket"));
-  }
-
-  GetTlsFilter(args)->Connect(host_name_string, static_cast<int>(port));
-  Dart_ExitScope();
-}
-
-
-void FUNCTION_NAME(TlsSocket_Destroy)(Dart_NativeArguments args) {
-  Dart_EnterScope();
-  TlsFilter* filter = GetTlsFilter(args);
-  SetTlsFilter(args, NULL);
-  filter->Destroy();
-  delete filter;
-  Dart_ExitScope();
-}
-
-
-void FUNCTION_NAME(TlsSocket_Handshake)(Dart_NativeArguments args) {
-  Dart_EnterScope();
-  GetTlsFilter(args)->Handshake();
-  Dart_ExitScope();
-}
-
-
-void FUNCTION_NAME(TlsSocket_RegisterHandshakeCompleteCallback)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle handshake_complete =
-      ThrowIfError(Dart_GetNativeArgument(args, 1));
-  if (!Dart_IsClosure(handshake_complete)) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Illegal argument to RegisterHandshakeCompleteCallback"));
-  }
-  GetTlsFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
-  Dart_ExitScope();
-}
-
-
-void FUNCTION_NAME(TlsSocket_ProcessBuffer)(Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle buffer_id_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  int64_t buffer_id = DartUtils::GetIntegerValue(buffer_id_object);
-  if (buffer_id < 0 || buffer_id >= TlsFilter::kNumBuffers) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Illegal argument to ProcessBuffer"));
-  }
-
-  intptr_t bytes_read =
-      GetTlsFilter(args)->ProcessBuffer(static_cast<int>(buffer_id));
-  Dart_SetReturnValue(args, Dart_NewInteger(bytes_read));
-  Dart_ExitScope();
-}
-
-
-void FUNCTION_NAME(TlsSocket_SetCertificateDatabase)
-    (Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle dart_pkcert_dir = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  // Check that the type is string, and get the UTF-8 C string value from it.
-  if (Dart_IsString(dart_pkcert_dir)) {
-    const char* pkcert_dir = NULL;
-    ThrowIfError(Dart_StringToCString(dart_pkcert_dir, &pkcert_dir));
-    TlsFilter::InitializeLibrary(pkcert_dir);
-  } else {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Non-String argument to SetCertificateDatabase"));
-  }
-  Dart_ExitScope();
-}
-
-
-void TlsFilter::Init(Dart_Handle dart_this) {
-  string_start_ = ThrowIfError(
-      Dart_NewPersistentHandle(DartUtils::NewString("start")));
-  string_length_ = ThrowIfError(
-      Dart_NewPersistentHandle(DartUtils::NewString("length")));
-
-  InitializeBuffers(dart_this);
-  memio_ = memio_CreateIOLayer(kMemioBufferSize);
-}
-
-
-void TlsFilter::InitializeBuffers(Dart_Handle dart_this) {
-  // Create TlsFilter buffers as ExternalUint8Array objects.
-  Dart_Handle dart_buffers_object = ThrowIfError(
-      Dart_GetField(dart_this, DartUtils::NewString("buffers")));
-  Dart_Handle dart_buffer_object =
-      Dart_ListGetAt(dart_buffers_object, kReadPlaintext);
-  Dart_Handle tls_external_buffer_class =
-      Dart_InstanceGetClass(dart_buffer_object);
-  Dart_Handle dart_buffer_size = ThrowIfError(
-      Dart_GetField(tls_external_buffer_class, DartUtils::NewString("SIZE")));
-  buffer_size_ = DartUtils::GetIntegerValue(dart_buffer_size);
-  if (buffer_size_ <= 0 || buffer_size_ > 1024 * 1024) {
-    Dart_ThrowException(
-        DartUtils::NewString("Invalid buffer size in _TlsExternalBuffer"));
-  }
-
-  Dart_Handle data_identifier = DartUtils::NewString("data");
-  for (int i = 0; i < kNumBuffers; ++i) {
-    dart_buffer_objects_[i] = ThrowIfError(
-        Dart_NewPersistentHandle(Dart_ListGetAt(dart_buffers_object, i)));
-    buffers_[i] = new uint8_t[buffer_size_];
-    Dart_Handle data = ThrowIfError(
-      Dart_NewExternalByteArray(buffers_[i], buffer_size_, NULL, NULL));
-    ThrowIfError(Dart_SetField(dart_buffer_objects_[i],
-                               data_identifier,
-                               data));
-  }
-}
-
-
-void TlsFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
-  ASSERT(NULL == handshake_complete_);
-  handshake_complete_ = ThrowIfError(Dart_NewPersistentHandle(complete));
-}
-
-
-void TlsFilter::InitializeLibrary(const char* pkcert_database) {
-  MutexLocker locker(&mutex_);
-  if (!library_initialized_) {
-    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
-    // TODO(whesse): Verify there are no UTF-8 issues here.
-    SECStatus status = NSS_Init(pkcert_database);
-    if (status != SECSuccess) {
-      ThrowPRException("Unsuccessful NSS_Init call.");
-    }
-
-    status = NSS_SetDomesticPolicy();
-    if (status != SECSuccess) {
-      ThrowPRException("Unsuccessful NSS_SetDomesticPolicy call.");
-    }
-  } else {
-    ThrowException("Called TlsFilter::InitializeLibrary more than once");
-  }
-}
-
-
-void TlsFilter::Connect(const char* host, int port) {
-  if (in_handshake_) {
-    ThrowException("Connect called while already in handshake state.");
-  }
-  PRFileDesc* my_socket = memio_;
-
-  my_socket = SSL_ImportFD(NULL, my_socket);
-  if (my_socket == NULL) {
-    ThrowPRException("Unsuccessful SSL_ImportFD call");
-  }
-
-  if (SSL_SetURL(my_socket, host) == -1) {
-    ThrowPRException("Unsuccessful SetURL call");
-  }
-
-  SECStatus status = SSL_ResetHandshake(my_socket, PR_FALSE);
-  if (status != SECSuccess) {
-    ThrowPRException("Unsuccessful SSL_ResetHandshake call");
-  }
-
-  // SetPeerAddress
-  PRNetAddr host_address;
-  char host_entry_buffer[PR_NETDB_BUF_SIZE];
-  PRHostEnt host_entry;
-  PRStatus rv = PR_GetHostByName(host, host_entry_buffer,
-                                 PR_NETDB_BUF_SIZE, &host_entry);
-  if (rv != PR_SUCCESS) {
-    ThrowPRException("Unsuccessful PR_GetHostByName call");
-  }
-
-  int index = PR_EnumerateHostEnt(0, &host_entry, port, &host_address);
-  if (index == -1 || index == 0) {
-    ThrowPRException("Unsuccessful PR_EnumerateHostEnt call");
-  }
-
-  memio_SetPeerName(my_socket, &host_address);
-  memio_ = my_socket;
-}
-
-
-void TlsFilter::Handshake() {
-  SECStatus status = SSL_ForceHandshake(memio_);
-  if (status == SECSuccess) {
-    if (in_handshake_) {
-      ThrowIfError(Dart_InvokeClosure(handshake_complete_, 0, NULL));
-      in_handshake_ = false;
-    }
-  } else {
-    PRErrorCode error = PR_GetError();
-    if (error == PR_WOULD_BLOCK_ERROR) {
-      if (!in_handshake_) {
-        in_handshake_ = true;
-      }
-    } else {
-      ThrowPRException("Unexpected handshake error");
-    }
-  }
-}
-
-
-void TlsFilter::Destroy() {
-  for (int i = 0; i < kNumBuffers; ++i) {
-    Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
-    delete[] buffers_[i];
-  }
-  Dart_DeletePersistentHandle(string_start_);
-  Dart_DeletePersistentHandle(string_length_);
-  Dart_DeletePersistentHandle(handshake_complete_);
-  // TODO(whesse): Free NSS objects here.
-}
-
-
-intptr_t TlsFilter::ProcessBuffer(int buffer_index) {
-  Dart_Handle buffer_object = dart_buffer_objects_[buffer_index];
-  Dart_Handle start_object = ThrowIfError(
-      Dart_GetField(buffer_object, string_start_));
-  Dart_Handle length_object = ThrowIfError(
-      Dart_GetField(buffer_object, string_length_));
-  int64_t unsafe_start = DartUtils::GetIntegerValue(start_object);
-  int64_t unsafe_length = DartUtils::GetIntegerValue(length_object);
-  ASSERT(unsafe_start >= 0);
-  ASSERT(unsafe_start < buffer_size_);
-  ASSERT(unsafe_length >= 0);
-  ASSERT(unsafe_length <= buffer_size_);
-  intptr_t start = static_cast<intptr_t>(unsafe_start);
-  intptr_t length = static_cast<intptr_t>(unsafe_length);
-  uint8_t* buffer = buffers_[buffer_index];
-
-  int bytes_processed = 0;
-  switch (buffer_index) {
-    case kReadPlaintext: {
-      int bytes_free = buffer_size_ - start - length;
-      bytes_processed = PR_Read(memio_,
-                                buffer + start + length,
-                                bytes_free);
-      if (bytes_processed < 0) {
-        ASSERT(bytes_processed == -1);
-        // TODO(whesse): Handle unexpected errors here.
-        PRErrorCode pr_error = PR_GetError();
-        if (PR_WOULD_BLOCK_ERROR != pr_error) {
-          ThrowPRException("Error reading plaintext from TlsFilter");
-        }
-        bytes_processed = 0;
-      }
-      break;
-    }
-
-    case kWriteEncrypted: {
-      const uint8_t* buf1;
-      const uint8_t* buf2;
-      unsigned int len1;
-      unsigned int len2;
-      int bytes_free = buffer_size_ - start - length;
-      memio_Private* secret = memio_GetSecret(memio_);
-      memio_GetWriteParams(secret, &buf1, &len1, &buf2, &len2);
-      int bytes_to_send =
-          dart::Utils::Minimum(len1, static_cast<unsigned>(bytes_free));
-      if (bytes_to_send > 0) {
-        memmove(buffer + start + length, buf1, bytes_to_send);
-        bytes_processed = bytes_to_send;
-      }
-      bytes_to_send = dart::Utils::Minimum(len2,
-          static_cast<unsigned>(bytes_free - bytes_processed));
-      if (bytes_to_send > 0) {
-        memmove(buffer + start + length + bytes_processed, buf2,
-                bytes_to_send);
-        bytes_processed += bytes_to_send;
-      }
-      if (bytes_processed > 0) {
-        memio_PutWriteResult(secret, bytes_processed);
-      }
-      break;
-    }
-
-    case kReadEncrypted: {
-      if (length > 0) {
-        bytes_processed = length;
-        memio_Private* secret = memio_GetSecret(memio_);
-        uint8_t* memio_buf;
-        int free_bytes = memio_GetReadParams(secret, &memio_buf);
-        if (free_bytes < bytes_processed) bytes_processed = free_bytes;
-        memmove(memio_buf,
-                buffer + start,
-                bytes_processed);
-        memio_PutReadResult(secret, bytes_processed);
-      }
-      break;
-    }
-
-    case kWritePlaintext: {
-      if (length > 0) {
-        bytes_processed = PR_Write(memio_,
-                                   buffer + start,
-                                   length);
-      }
-
-      if (bytes_processed < 0) {
-        ASSERT(bytes_processed == -1);
-        // TODO(whesse): Handle unexpected errors here.
-        PRErrorCode pr_error = PR_GetError();
-        if (PR_WOULD_BLOCK_ERROR != pr_error) {
-          ThrowPRException("Error reading plaintext from TlsFilter");
-        }
-        bytes_processed = 0;
-      }
-      break;
-    }
-  }
-  return bytes_processed;
-}
diff --git a/runtime/bin/tls_socket_patch.dart b/runtime/bin/tls_socket_patch.dart
deleted file mode 100644
index 73e40e8..0000000
--- a/runtime/bin/tls_socket_patch.dart
+++ /dev/null
@@ -1,52 +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.
-
-patch class TlsSocket {
-  /* patch */ static void setCertificateDatabase(String pkcertDirectory)
-      native "TlsSocket_SetCertificateDatabase";
-}
-
-
-patch class _TlsFilter {
-  /* patch */ factory _TlsFilter() => new _TlsFilterImpl();
-}
-
-
-/**
- * _TlsFilterImpl wraps a filter that encrypts and decrypts data travelling
- * over a TLS encrypted socket.  The filter also handles the handshaking
- * and certificate verification.
- *
- * The filter exposes its input and output buffers as Dart objects that
- * are backed by an external C array of bytes, so that both Dart code and
- * native code can access the same data.
- */
-class _TlsFilterImpl extends NativeFieldWrapperClass1 implements _TlsFilter {
-  _TlsFilterImpl() {
-    buffers = new List<_TlsExternalBuffer>(_TlsSocket.NUM_BUFFERS);
-    for (int i = 0; i < _TlsSocket.NUM_BUFFERS; ++i) {
-      buffers[i] = new _TlsExternalBuffer();
-    }
-  }
-
-  void connect(String hostName, int port) native "TlsSocket_Connect";
-
-  void destroy() {
-    buffers = null;
-    _destroy();
-  }
-
-  void _destroy() native "TlsSocket_Destroy";
-
-  void handshake() native "TlsSocket_Handshake";
-
-  void init() native "TlsSocket_Init";
-
-  int processBuffer(int bufferIndex) native "TlsSocket_ProcessBuffer";
-
-  void registerHandshakeCompleteCallback(Function handshakeCompleteHandler)
-      native "TlsSocket_RegisterHandshakeCompleteCallback";
-
-  List<_TlsExternalBuffer> buffers;
-}
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index 9ee1777..f9603f8 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -5,6 +5,7 @@
 #include <errno.h>
 
 #include "bin/utils.h"
+#include "bin/log.h"
 
 static void FormatMessageIntoBuffer(DWORD code,
                                     char* buffer,
@@ -19,7 +20,7 @@
                     NULL);
   if (message_size == 0) {
     if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-      fprintf(stderr, "FormatMessage failed %d\n", GetLastError());
+      Log::PrintErr("FormatMessage failed %d\n", GetLastError());
     }
     snprintf(buffer, buffer_length, "OS Error %d", code);
   }
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 8cc518a..821014c 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1388,7 +1388,7 @@
  * \return The String object if no error occurs. Otherwise returns
  *   an error handle.
  */
-DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const uint32_t* utf32_array,
+DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array,
                                                 intptr_t length);
 
 /**
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index 1fb17fb..5bef0d0 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -138,6 +138,10 @@
         "Cannot remove in a non-extendable array");
   }
 
+  E get first {
+    return this[0];
+  }
+
   E get last {
     return this[length - 1];
   }
@@ -285,6 +289,10 @@
         "Cannot remove in a non-extendable array");
   }
 
+  E get first {
+    return this[0];
+  }
+
   E get last {
     return this[length - 1];
   }
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index 5bb7ec2c..2887a99 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -5,7 +5,7 @@
 // Note that the optimizing compiler depends on the algorithm which
 // returns a _GrowableObjectArray if length is null, otherwise returns
 // fixed size array.
-patch class _ListImpl<E> {
+patch class List<E> {
   /* patch */ factory List([int length = null]) {
     if (length == null) {
       return new _GrowableObjectArray<E>();
@@ -14,14 +14,6 @@
     }
   }
 
-  /* patch */ factory List.from(Iterable<E> other) {
-    _GrowableObjectArray<E> list = new _GrowableObjectArray<E>();
-    for (final e in other) {
-      list.add(e);
-    }
-    return list;
-  }
-
   // Factory constructing a mutable List from a parser generated List literal.
   // [elements] contains elements that are already type checked.
   factory List._fromLiteral(List elements) {
diff --git a/runtime/lib/byte_array.dart b/runtime/lib/byte_array.dart
index 0f97c3d..aa8e5dc 100644
--- a/runtime/lib/byte_array.dart
+++ b/runtime/lib/byte_array.dart
@@ -115,11 +115,11 @@
 
 
 abstract class _ByteArrayBase {
-  abstract int lengthInBytes();
+  int lengthInBytes();
 
-  abstract int bytesPerElement();
+  int bytesPerElement();
 
-  abstract operator[](int index);
+  operator[](int index);
 
   // Methods implementing the Collection interface.
 
@@ -184,7 +184,7 @@
   }
 
   void sort([Comparator compare = Comparable.compare]) {
-    _Sort.sort(this, compare);
+    coreSort(this, compare);
   }
 
   int indexOf(element, [int start = 0]) {
@@ -206,6 +206,10 @@
         "Cannot remove from a non-extendable array");
   }
 
+  get first {
+    return this[0];
+  }
+
   get last {
     return this[length - 1];
   }
@@ -1601,7 +1605,7 @@
 
 
 class _ByteArrayViewBase {
-  abstract num operator[](int index);
+  num operator[](int index);
 
   // Methods implementing the Collection interface.
 
@@ -1637,7 +1641,7 @@
     return this.length == 0;
   }
 
-  abstract int get length;
+  int get length;
 
   // Methods implementing the List interface.
 
@@ -1662,7 +1666,7 @@
   }
 
   void sort([Comparator compare = Comparable.compare]) {
-    _Sort.sort(this, compare);
+    coreSort(this, compare);
   }
 
   int indexOf(element, [int start = 0]) {
@@ -1684,6 +1688,10 @@
         "Cannot remove from a non-extendable array");
   }
 
+  get first {
+    return this[0];
+  }
+
   get last {
     return this[length - 1];
   }
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 05977ba..76babac 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -11,6 +11,7 @@
 #include "vm/exceptions.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
+#include "vm/symbols.h"
 
 namespace dart {
 
@@ -202,6 +203,61 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(Double_parse, 1) {
+  GET_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
+  const String& dummy_key = String::Handle(Symbols::Empty());
+  Scanner scanner(value, dummy_key);
+  const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
+  String* number_string;
+  bool is_positive;
+  if (Scanner::IsValidLiteral(tokens,
+                              Token::kDOUBLE,
+                              &is_positive,
+                              &number_string)) {
+    const char* cstr = number_string->ToCString();
+    char* p_end = NULL;
+    double double_value = strtod(cstr, &p_end);
+    ASSERT(p_end != cstr);
+    if (!is_positive) {
+      double_value = -double_value;
+    }
+    return Double::New(double_value);
+  }
+
+  if (Scanner::IsValidLiteral(tokens,
+                              Token::kINTEGER,
+                              &is_positive,
+                              &number_string)) {
+    Integer& res = Integer::Handle(Integer::New(*number_string));
+    if (is_positive) {
+      return Double::New(res.AsDoubleValue());
+    }
+    return Double::New(-res.AsDoubleValue());
+  }
+
+  // Infinity and nan.
+  if (Scanner::IsValidLiteral(tokens,
+                              Token::kIDENT,
+                              &is_positive,
+                              &number_string)) {
+    if (number_string->Equals("NaN")) {
+      return Double::New(NAN);
+    }
+    if (number_string->Equals("Infinity")) {
+      if (is_positive) {
+        return Double::New(INFINITY);
+      }
+      return Double::New(-INFINITY);
+    }
+  }
+
+  GrowableArray<const Object*> args;
+  args.Add(&value);
+  Exceptions::ThrowByType(Exceptions::kFormat, args);
+  return Object::null();
+}
+
+
 DEFINE_NATIVE_ENTRY(Double_toStringAsFixed, 2) {
   // The boundaries are exclusive.
   static const double kLowerBoundary = -1e21;
diff --git a/runtime/lib/double.dart b/runtime/lib/double.dart
index f4025f3..aee84e2 100644
--- a/runtime/lib/double.dart
+++ b/runtime/lib/double.dart
@@ -114,7 +114,9 @@
     if (exponent == 0) {
       return 1.0;  // ECMA-262 15.8.2.13
     }
-    // Throw NullPointerException if exponent is null.
+    if (exponent is! num) {
+      throw new ArgumentError(null);
+    }
     double doubleExponent = exponent.toDouble();
     if (isNaN || exponent.isNaN) {
       return double.NAN;
diff --git a/runtime/lib/double_patch.dart b/runtime/lib/double_patch.dart
index d293249..5e6cc11 100644
--- a/runtime/lib/double_patch.dart
+++ b/runtime/lib/double_patch.dart
@@ -7,5 +7,5 @@
 
 patch class double {
   /* patch */
-  static double parse(String string) native "MathNatives_parseDouble";
+  static double parse(String string) native "Double_parse";
 }
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index d09dc3d..12caead 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class NoSuchMethodError {
+patch class Error {
   /* patch */ static String _objectToString(Object object) {
     return Object._toString(object);
   }
diff --git a/runtime/lib/expando_patch.dart b/runtime/lib/expando_patch.dart
index a218af6..5c61969 100644
--- a/runtime/lib/expando_patch.dart
+++ b/runtime/lib/expando_patch.dart
@@ -54,10 +54,7 @@
   }
 
   static _checkType(object) {
-    if (object == null) {
-      throw new NullPointerException();
-    }
-    if (object is bool || object is num || object is String) {
+    if (object == null || object is bool || object is num || object is String) {
       throw new ArgumentError(object);
     }
   }
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index a34bca0..2e012c2 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -145,6 +145,10 @@
     return elem;
   }
 
+  T get first {
+    return this[0];
+  }
+
   T get last {
     return this[length - 1];
   }
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index c9cf18d..9c379ca 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -9,6 +9,7 @@
 #include "vm/exceptions.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
+#include "vm/symbols.h"
 
 namespace dart {
 
@@ -172,6 +173,32 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(Integer_parse, 1) {
+  GET_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
+  const String& dummy_key = String::Handle(Symbols::Empty());
+  Scanner scanner(value, dummy_key);
+  const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
+  String* int_string;
+  bool is_positive;
+  if (Scanner::IsValidLiteral(tokens,
+                             Token::kINTEGER,
+                             &is_positive,
+                             &int_string)) {
+    if (is_positive) {
+      return Integer::New(*int_string);
+    }
+    String& temp = String::Handle();
+    temp = String::Concat(String::Handle(Symbols::New("-")), *int_string);
+    return Integer::New(temp);
+  }
+
+  GrowableArray<const Object*> args;
+  args.Add(&value);
+  Exceptions::ThrowByType(Exceptions::kFormat, args);
+  return Object::null();
+}
+
+
 static RawInteger* ShiftOperationHelper(Token::Kind kind,
                                         const Integer& value,
                                         const Smi& amount) {
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index c931ed4..162c050 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -6,5 +6,5 @@
 // VM implementation of int.
 
 patch class int {
-  /* patch */ static int parse(String str) native "MathNatives_parseInt";
+  /* patch */ static int parse(String str) native "Integer_parse";
 }
diff --git a/runtime/lib/lib_sources.gypi b/runtime/lib/lib_sources.gypi
index 2bffa7e..28c9afd 100644
--- a/runtime/lib/lib_sources.gypi
+++ b/runtime/lib/lib_sources.gypi
@@ -28,8 +28,6 @@
     'integers_patch.dart',
     'invocation_mirror_patch.dart',
     'map_patch.dart',
-    'math.dart',
-    'math.cc',
     'object.cc',
     'object_patch.dart',
     'print_patch.dart',
diff --git a/runtime/lib/math.cc b/runtime/lib/math.cc
index de48b16..ff4e6af 100644
--- a/runtime/lib/math.cc
+++ b/runtime/lib/math.cc
@@ -10,168 +10,60 @@
 #include "vm/exceptions.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
-#include "vm/random.h"
 #include "vm/scanner.h"
 #include "vm/symbols.h"
 
 namespace dart {
 
-DEFINE_NATIVE_ENTRY(MathNatives_sqrt, 1) {
+DEFINE_NATIVE_ENTRY(Math_sqrt, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(sqrt(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_sin, 1) {
+DEFINE_NATIVE_ENTRY(Math_sin, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(sin(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_cos, 1) {
+DEFINE_NATIVE_ENTRY(Math_cos, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(cos(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_tan, 1) {
+DEFINE_NATIVE_ENTRY(Math_tan, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(tan(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_asin, 1) {
+DEFINE_NATIVE_ENTRY(Math_asin, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(asin(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_acos, 1) {
+DEFINE_NATIVE_ENTRY(Math_acos, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(acos(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_atan, 1) {
+DEFINE_NATIVE_ENTRY(Math_atan, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(atan(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_atan2, 2) {
+DEFINE_NATIVE_ENTRY(Math_atan2, 2) {
   GET_NATIVE_ARGUMENT(Double, operand1, arguments->NativeArgAt(0));
   GET_NATIVE_ARGUMENT(Double, operand2, arguments->NativeArgAt(1));
   return Double::New(atan2(operand1.value(), operand2.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_exp, 1) {
+DEFINE_NATIVE_ENTRY(Math_exp, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(exp(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_log, 1) {
+DEFINE_NATIVE_ENTRY(Math_log, 1) {
   GET_NATIVE_ARGUMENT(Double, operand, arguments->NativeArgAt(0));
   return Double::New(log(operand.value()));
 }
 
-DEFINE_NATIVE_ENTRY(MathNatives_random, 0) {
-  return Double::New(static_cast<double>(Random::RandomInt32()-1)/0x80000000);
-}
-
-
-// TODO(srdjan): Investigate for performance hit; the integer and double parsing
-// may not be efficient as we need to generate two extra growable arrays.
-static bool IsValidLiteral(const Scanner::GrowableTokenStream& tokens,
-                           Token::Kind literal_kind,
-                           bool* is_positive,
-                           String** value) {
-  if ((tokens.length() == 2) &&
-      (tokens[0].kind == literal_kind) &&
-      (tokens[1].kind == Token::kEOS)) {
-    *is_positive = true;
-    *value = tokens[0].literal;
-    return true;
-  }
-  if ((tokens.length() == 3) &&
-      ((tokens[0].kind == Token::kTIGHTADD) ||
-          (tokens[0].kind == Token::kSUB)) &&
-      (tokens[1].kind == literal_kind) &&
-      (tokens[2].kind == Token::kEOS)) {
-    // Check there is no space between "+/-" and number.
-    if ((tokens[0].offset + 1) != tokens[1].offset) {
-      return false;
-    }
-    *is_positive = tokens[0].kind == Token::kTIGHTADD;
-    *value = tokens[1].literal;
-    return true;
-  }
-  return false;
-}
-
-
-DEFINE_NATIVE_ENTRY(MathNatives_parseInt, 1) {
-  GET_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
-  const String& dummy_key = String::Handle(Symbols::Empty());
-  Scanner scanner(value, dummy_key);
-  const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
-  String* int_string;
-  bool is_positive;
-  if (IsValidLiteral(tokens, Token::kINTEGER, &is_positive, &int_string)) {
-    if (is_positive) {
-      return Integer::New(*int_string);
-    } else {
-      String& temp = String::Handle();
-      temp = String::Concat(String::Handle(Symbols::New("-")),
-                            *int_string);
-      return Integer::New(temp);
-    }
-  } else {
-    GrowableArray<const Object*> args;
-    args.Add(&value);
-    Exceptions::ThrowByType(Exceptions::kFormat, args);
-    return Object::null();
-  }
-}
-
-
-DEFINE_NATIVE_ENTRY(MathNatives_parseDouble, 1) {
-  GET_NATIVE_ARGUMENT(String, value, arguments->NativeArgAt(0));
-  const String& dummy_key = String::Handle(Symbols::Empty());
-  Scanner scanner(value, dummy_key);
-  const Scanner::GrowableTokenStream& tokens = scanner.GetStream();
-  String* number_string;
-  bool is_positive;
-  if (IsValidLiteral(tokens, Token::kDOUBLE, &is_positive, &number_string)) {
-    const char* cstr = number_string->ToCString();
-    char* p_end = NULL;
-    double double_value = strtod(cstr, &p_end);
-    ASSERT(p_end != cstr);
-    if (!is_positive) {
-      double_value = -double_value;
-    }
-    return Double::New(double_value);
-  }
-
-  if (IsValidLiteral(tokens, Token::kINTEGER, &is_positive, &number_string)) {
-    Integer& res = Integer::Handle(Integer::New(*number_string));
-    if (is_positive) {
-      return Double::New(res.AsDoubleValue());
-    } else {
-      return Double::New(-res.AsDoubleValue());
-    }
-  }
-
-  // Infinity and nan.
-  if (IsValidLiteral(tokens, Token::kIDENT, &is_positive, &number_string)) {
-    if (number_string->Equals("NaN")) {
-      return Double::New(NAN);
-    }
-    if (number_string->Equals("Infinity")) {
-      if (is_positive) {
-        return Double::New(INFINITY);
-      } else {
-        return Double::New(-INFINITY);
-      }
-    }
-  }
-
-  GrowableArray<const Object*> args;
-  args.Add(&value);
-  Exceptions::ThrowByType(Exceptions::kFormat, args);
-  return Object::null();
-}
-
 }  // namespace dart
diff --git a/runtime/lib/math.dart b/runtime/lib/math.dart
deleted file mode 100644
index bb32560..0000000
--- a/runtime/lib/math.dart
+++ /dev/null
@@ -1,36 +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.
-
-class MathNatives {
-  static num pow(num value, num exponent) {
-    if (exponent is int) {
-      return value.pow(exponent);
-    }
-    // Double.pow will call exponent.toDouble().
-    return value.toDouble().pow(exponent);
-  }
-  static double random() => _random();
-  static double sqrt(num value) => _sqrt(value.toDouble());
-  static double sin(num value) => _sin(value.toDouble());
-  static double cos(num value) => _cos(value.toDouble());
-  static double tan(num value) => _tan(value.toDouble());
-  static double acos(num value) => _acos(value.toDouble());
-  static double asin(num value) => _asin(value.toDouble());
-  static double atan(num value) => _atan(value.toDouble());
-  static double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble());
-  static double exp(num value) => _exp(value.toDouble());
-  static double log(num value) => _log(value.toDouble());
-
-  static double _random() native "MathNatives_random";
-  static double _sqrt(double value) native "MathNatives_sqrt";
-  static double _sin(double value) native "MathNatives_sin";
-  static double _cos(double value) native "MathNatives_cos";
-  static double _tan(double value) native "MathNatives_tan";
-  static double _acos(double value) native "MathNatives_acos";
-  static double _asin(double value) native "MathNatives_asin";
-  static double _atan(double value) native "MathNatives_atan";
-  static double _atan2(double a, double b) native "MathNatives_atan2";
-  static double _exp(double value) native "MathNatives_exp";
-  static double _log(double value) native "MathNatives_log";
-}
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 0612d3d..bfcbacc 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -3,17 +3,35 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // A VM patch of the dart:math library.
-patch num pow(num x, num exponent) => MathNatives.pow(x, exponent);
-patch double atan2(num a, num b) => MathNatives.atan2(a, b);
-patch double sin(num x) => MathNatives.sin(x);
-patch double cos(num x) => MathNatives.cos(x);
-patch double tan(num x) => MathNatives.tan(x);
-patch double acos(num x) => MathNatives.acos(x);
-patch double asin(num x) => MathNatives.asin(x);
-patch double atan(num x) => MathNatives.atan(x);
-patch double sqrt(num x) => MathNatives.sqrt(x);
-patch double exp(num x) => MathNatives.exp(x);
-patch double log(num x) => MathNatives.log(x);
+patch num pow(num x, num exponent) {
+  if (exponent is int) {
+    return x.pow(exponent);
+  }
+  // Double.pow will call exponent.toDouble().
+  return x.toDouble().pow(exponent);
+}
+
+patch double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble());
+patch double sin(num value) => _sin(value.toDouble());
+patch double cos(num value) => _cos(value.toDouble());
+patch double tan(num value) => _tan(value.toDouble());
+patch double acos(num value) => _acos(value.toDouble());
+patch double asin(num value) => _asin(value.toDouble());
+patch double atan(num value) => _atan(value.toDouble());
+patch double sqrt(num value) => _sqrt(value.toDouble());
+patch double exp(num value) => _exp(value.toDouble());
+patch double log(num value) => _log(value.toDouble());
+
+double _atan2(double a, double b) native "Math_atan2";
+double _sin(double x) native "Math_sin";
+double _cos(double x) native "Math_cos";
+double _tan(double x) native "Math_tan";
+double _acos(double x) native "Math_acos";
+double _asin(double x) native "Math_asin";
+double _atan(double x) native "Math_atan";
+double _sqrt(double x) native "Math_sqrt";
+double _exp(double x) native "Math_exp";
+double _log(double x) native "Math_log";
 
 
 // TODO(iposva): Handle patch methods within a patch class correctly.
@@ -33,20 +51,24 @@
 
 class _Random implements Random {
   // Internal state of the random number generator.
-  var _state_lo;
-  var _state_hi;
+  var _state;
+  static const kSTATE_LO = 0;
+  static const kSTATE_HI = 1;
 
-  _Random._internal(state)
-      : _state_lo = (state & _MASK_32), _state_hi = (state >> 32);
+  _Random._internal(state) {
+    _state = new List(2);
+    _state[kSTATE_LO] = state & _MASK_32;
+    _state[kSTATE_HI] = state >> 32;
+  }
 
   // The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32.
   // http://en.wikipedia.org/wiki/Multiply-with-carry
   // The constant A is selected from "Numerical Recipes 3rd Edition" p.348 B1.
   int _nextInt32() {
-    var state = ((_A * (_state_lo)) + _state_hi) & _MASK_64;
-    _state_lo = state & _MASK_32;
-    _state_hi = state >> 32;
-    return _state_lo;
+    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
+    _state[kSTATE_LO] = state & _MASK_32;
+    _state[kSTATE_HI] = state >> 32;
+    return _state[kSTATE_LO];
   }
 
   int nextInt(int max) {
diff --git a/runtime/lib/math_sources.gypi b/runtime/lib/math_sources.gypi
index 5fb0d9e..2a18173 100644
--- a/runtime/lib/math_sources.gypi
+++ b/runtime/lib/math_sources.gypi
@@ -4,6 +4,7 @@
 
 {
   'sources': [
+    'math.cc',
     'math_patch.dart',
   ],
 }
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 3d9ed92..6f1fef5 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -22,14 +22,8 @@
       Instance::CheckedHandle(arguments->NativeArgAt(0));
   GET_NATIVE_ARGUMENT(String, function_name, arguments->NativeArgAt(1));
   GET_NATIVE_ARGUMENT(Array, func_args, arguments->NativeArgAt(2));
-  if (instance.IsNull()) {
-    GrowableArray<const Object*> args;
-    args.Add(&function_name);
-    args.Add(&func_args);
-    Exceptions::ThrowByType(Exceptions::kNullPointer, args);
-  }
   const Object& null_object = Object::Handle(Object::null());
-  GrowableArray<const Object*> dart_arguments(3);
+  GrowableArray<const Object*> dart_arguments(4);
   dart_arguments.Add(&instance);
   dart_arguments.Add(&function_name);
   dart_arguments.Add(&func_args);
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 00088b5..969d5ff 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -12,19 +12,9 @@
 
 namespace dart {
 
-static void CheckAndThrowExceptionIfNull(const Instance& obj) {
-  if (obj.IsNull()) {
-    GrowableArray<const Object*> args;
-    Exceptions::ThrowByType(Exceptions::kNullPointer, args);
-  }
-}
-
-
 DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_factory, 4) {
   ASSERT(AbstractTypeArguments::CheckedHandle(
       arguments->NativeArgAt(0)).IsNull());
-  const Instance& arg1 = Instance::CheckedHandle(arguments->NativeArgAt(1));
-  CheckAndThrowExceptionIfNull(arg1);
   GET_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
   GET_NATIVE_ARGUMENT(Instance, handle_multi_line, arguments->NativeArgAt(2));
   GET_NATIVE_ARGUMENT(Instance, handle_ignore_case, arguments->NativeArgAt(3));
@@ -75,8 +65,6 @@
 DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_ExecuteMatch, 3) {
   const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
-  const Instance& arg1 = Instance::CheckedHandle(arguments->NativeArgAt(1));
-  CheckAndThrowExceptionIfNull(arg1);
   GET_NATIVE_ARGUMENT(String, str, arguments->NativeArgAt(1));
   GET_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
   return Jscre::Execute(regexp, str, start_index.Value());
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index d6e830c..6a921fa 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -77,6 +77,7 @@
   }
 
   Iterable<Match> allMatches(String str) {
+    if (str is! String) throw new ArgumentError(str);
     List<Match> result = new List<Match>();
     int length = str.length;
     int startIndex = 0;
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 76c097a..797cad2 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -20,7 +20,7 @@
   // Unbox the array and determine the maximum element width.
   bool is_one_byte_string = true;
   intptr_t utf16_len = array_len;
-  uint32_t* utf32_array = zone->Alloc<uint32_t>(array_len);
+  int32_t* utf32_array = zone->Alloc<int32_t>(array_len);
   Object& index_object = Object::Handle(isolate);
   for (intptr_t i = 0; i < array_len; i++) {
     index_object = a.At(i);
@@ -102,7 +102,7 @@
   GET_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
   uint32_t value = StringValueAt(receiver, index);
   ASSERT(value <= 0x10FFFF);
-  return Symbols::New(&value, 1);
+  return Symbols::FromCharCode(value);
 }
 
 DEFINE_NATIVE_ENTRY(String_charCodeAt, 2) {
@@ -144,10 +144,6 @@
   Instance& elem = Instance::Handle();
   for (intptr_t i = 0; i < strings.Length(); i++) {
     elem ^= strings.At(i);
-    if (elem.IsNull()) {
-      GrowableArray<const Object*> args;
-      Exceptions::ThrowByType(Exceptions::kNullPointer, args);
-    }
     if (!elem.IsString()) {
       GrowableArray<const Object*> args;
       args.Add(&elem);
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index 821912b..d4b8b88 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -304,9 +304,8 @@
   Expect.equals('dart:core.List', list_intf.qualifiedName);
   Expect.isFalse(list_intf.isPrivate);
   Expect.equals('Object', list_intf.superclass.simpleName);
-  Expect.equals('_ListImpl', list_intf.defaultFactory.simpleName);
   Expect.equals('dart:core', list_intf.owner.simpleName);
-  Expect.isFalse(list_intf.isClass);
+  Expect.isTrue(list_intf.isClass);
   Expect.equals('Collection', list_intf.superinterfaces[0].simpleName);
   Expect.equals("ClassMirror on 'List'", list_intf.toString());
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 5f2ec21..9b8ab80 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -5,6 +5,8 @@
 # When a spawned isolate throws an uncaught exception, we terminate the vm.
 cc/RunLoop_ExceptionChild: Fail
 
+cc/SymbolUnicode: Fail
+
 # These tests are expected to crash on all platforms.
 cc/ArrayNew_Overflow_Crash: Crash
 cc/AllocGeneric_Overflow: Crash
diff --git a/runtime/tools/gyp/nss_configurations.gypi b/runtime/tools/gyp/nss_configurations.gypi
index 2897c6c..74c857c 100644
--- a/runtime/tools/gyp/nss_configurations.gypi
+++ b/runtime/tools/gyp/nss_configurations.gypi
@@ -37,9 +37,6 @@
       '-Werror',
       '-Wall',
       '-ansi',
-      # This flag would let a certain assembly function be inlined,
-      # causing errors in mpcpucache.c.
-      '-fvisibility=hidden',
       # Not supported for C, only for C++.
       '-Wnon-virtual-dtor',
       '-Wno-conversion-null',
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index ec7f4c1..7fa7e21 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -19,15 +19,16 @@
 DEFINE_FLAG(bool, use_sse41, true, "Use SSE 4.1 if available");
 
 
-bool CPUFeatures::sse3_supported_ = false;
+bool CPUFeatures::sse2_supported_ = false;
 bool CPUFeatures::sse4_1_supported_ = false;
 #ifdef DEBUG
 bool CPUFeatures::initialized_ = false;
 #endif
 
-bool CPUFeatures::sse3_supported() {
+
+bool CPUFeatures::sse2_supported() {
   DEBUG_ASSERT(initialized_);
-  return sse3_supported_;
+  return sse2_supported_;
 }
 
 
@@ -60,7 +61,7 @@
   typedef uint64_t (*DetectCPUFeatures)();
   uint64_t features =
       reinterpret_cast<DetectCPUFeatures>(instructions.EntryPoint())();
-  sse3_supported_ = (features & kSSE3BitMask) != 0;
+  sse2_supported_ = (features & kSSE2BitMask) != 0;
   sse4_1_supported_ = (features & kSSE4_1BitMask) != 0;
 #ifdef DEBUG
   initialized_ = true;
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index 5d80c8b..a738df3 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -258,14 +258,14 @@
 class CPUFeatures : public AllStatic {
  public:
   static void InitOnce();
-  static bool sse3_supported();
+  static bool sse2_supported();
   static bool sse4_1_supported();
 
  private:
-  static const uint64_t kSSE3BitMask = static_cast<uint64_t>(1) << 32;
+  static const uint64_t kSSE2BitMask = static_cast<uint64_t>(1) << 26;
   static const uint64_t kSSE4_1BitMask = static_cast<uint64_t>(1) << 51;
 
-  static bool sse3_supported_;
+  static bool sse2_supported_;
   static bool sse4_1_supported_;
 #ifdef DEBUG
   static bool initialized_;
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index 373925e..57ffd01 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -19,18 +19,11 @@
 DEFINE_FLAG(bool, use_sse41, true, "Use SSE 4.1 if available");
 
 
-bool CPUFeatures::sse3_supported_ = false;
 bool CPUFeatures::sse4_1_supported_ = false;
 #ifdef DEBUG
 bool CPUFeatures::initialized_ = false;
 #endif
 
-bool CPUFeatures::sse3_supported() {
-  DEBUG_ASSERT(initialized_);
-  return sse3_supported_;
-}
-
-
 bool CPUFeatures::sse4_1_supported() {
   DEBUG_ASSERT(initialized_);
   return sse4_1_supported_ && FLAG_use_sse41;
@@ -63,7 +56,6 @@
   typedef uint64_t (*DetectCPUFeatures)();
   uint64_t features =
       reinterpret_cast<DetectCPUFeatures>(instructions.EntryPoint())();
-  sse3_supported_ = (features & kSSE3BitMask) != 0;
   sse4_1_supported_ = (features & kSSE4_1BitMask) != 0;
 #ifdef DEBUG
   initialized_ = true;
@@ -395,11 +387,10 @@
 
 
 void Assembler::movss(XmmRegister dst, const Address& src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(dst <= XMM7);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
-  EmitOperandREX(0, src, REX_NONE);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x10);
   EmitOperand(dst & 7, src);
@@ -407,11 +398,10 @@
 
 
 void Assembler::movss(const Address& dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
+  ASSERT(src <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
-  EmitOperandREX(0, dst, REX_NONE);
+  EmitREX_RB(src, dst);
   EmitUint8(0x0F);
   EmitUint8(0x11);
   EmitOperand(src & 7, dst);
@@ -419,11 +409,11 @@
 
 
 void Assembler::movss(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
+  EmitREX_RB(src, dst);
   EmitUint8(0x0F);
   EmitUint8(0x11);
   EmitXmmRegisterOperand(src & 7, dst);
@@ -431,9 +421,10 @@
 
 
 void Assembler::movd(XmmRegister dst, Register src) {
-  ASSERT(dst <= XMM7);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x6E);
   EmitOperand(dst & 7, Operand(src));
@@ -441,9 +432,10 @@
 
 
 void Assembler::movd(Register dst, XmmRegister src) {
-  ASSERT(src <= XMM7);
+  ASSERT(src <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
+  EmitREX_RB(src, dst);
   EmitUint8(0x0F);
   EmitUint8(0x7E);
   EmitOperand(src & 7, Operand(dst));
@@ -451,59 +443,58 @@
 
 
 void Assembler::addss(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x58);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::subss(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x5C);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::mulss(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x59);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::divss(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x5E);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::movsd(XmmRegister dst, const Address& src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(dst <= XMM7);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
-  EmitOperandREX(0, src, REX_NONE);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x10);
   EmitOperand(dst & 7, src);
@@ -511,11 +502,10 @@
 
 
 void Assembler::movsd(const Address& dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
+  ASSERT(src <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
-  EmitOperandREX(0, dst, REX_NONE);
+  EmitREX_RB(src, dst);
   EmitUint8(0x0F);
   EmitUint8(0x11);
   EmitOperand(src & 7, dst);
@@ -523,11 +513,11 @@
 
 
 void Assembler::movsd(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
+  EmitREX_RB(src, dst);
   EmitUint8(0x0F);
   EmitUint8(0x11);
   EmitXmmRegisterOperand(src & 7, dst);
@@ -535,10 +525,10 @@
 
 
 void Assembler::movaps(XmmRegister dst, XmmRegister src) {
-  // TODO(vegorov): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x28);
   EmitXmmRegisterOperand(dst & 7, src);
@@ -546,90 +536,93 @@
 
 
 void Assembler::addsd(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x58);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::subsd(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x5C);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::mulsd(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x59);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::divsd(XmmRegister dst, XmmRegister src) {
-  // TODO(srdjan): implement and test XMM8 - XMM15.
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x5E);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::comisd(XmmRegister a, XmmRegister b) {
-  ASSERT(a <= XMM7);
-  ASSERT(b <= XMM7);
+  ASSERT(a <= XMM15);
+  ASSERT(b <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
+  EmitREX_RB(a, b);
   EmitUint8(0x0F);
   EmitUint8(0x2F);
-  EmitXmmRegisterOperand(a, b);
+  EmitXmmRegisterOperand(a & 7, b);
 }
 
 
 void Assembler::movmskpd(Register dst, XmmRegister src) {
-  ASSERT(src <= XMM7);
+  ASSERT(src <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x50);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::sqrtsd(XmmRegister dst, XmmRegister src) {
-  ASSERT(dst <= XMM7);
-  ASSERT(src <= XMM7);
+  ASSERT(dst <= XMM15);
+  ASSERT(src <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x51);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::xorpd(XmmRegister dst, const Address& src) {
-  ASSERT(dst <= XMM7);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
-  EmitOperandREX(0, src, REX_NONE);
+  EmitOperandREX(dst, src, REX_NONE);
   EmitUint8(0x0F);
   EmitUint8(0x57);
   EmitOperand(dst & 7, src);
@@ -637,59 +630,62 @@
 
 
 void Assembler::xorpd(XmmRegister dst, XmmRegister src) {
-  ASSERT(dst <= XMM7);
-  ASSERT(src <= XMM7);
+  ASSERT(dst <= XMM15);
+  ASSERT(src <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x57);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::cvtsi2sd(XmmRegister dst, Register src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
-  ASSERT(dst <= XMM7);
+  ASSERT(dst <= XMM15);
   Operand operand(src);
   EmitUint8(0xF2);
-  EmitOperandREX(0, operand, REX_W);
+  EmitOperandREX(dst, operand, REX_W);
   EmitUint8(0x0F);
   EmitUint8(0x2A);
-  EmitOperand(dst, operand);
+  EmitOperand(dst & 7, operand);
 }
 
 
 void Assembler::cvttsd2siq(Register dst, XmmRegister src) {
-  ASSERT(src <= XMM7);
+  ASSERT(src <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
   Operand operand(dst);
-  EmitOperandREX(0, operand, REX_W);
+  EmitREX_RB(dst, src, REX_W);
   EmitUint8(0x0F);
   EmitUint8(0x2C);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::cvtss2sd(XmmRegister dst, XmmRegister src) {
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x5A);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
 void Assembler::cvtsd2ss(XmmRegister dst, XmmRegister src) {
-  ASSERT(src <= XMM7);
-  ASSERT(dst <= XMM7);
+  ASSERT(src <= XMM15);
+  ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF2);
+  EmitREX_RB(dst, src);
   EmitUint8(0x0F);
   EmitUint8(0x5A);
-  EmitXmmRegisterOperand(dst, src);
+  EmitXmmRegisterOperand(dst & 7, src);
 }
 
 
@@ -2107,7 +2103,8 @@
 
 
 static const char* xmm_reg_names[kNumberOfXmmRegisters] = {
-  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
+  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
+  "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
 };
 
 
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index cebc865..ab97b2a 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -275,14 +275,13 @@
 class CPUFeatures : public AllStatic {
  public:
   static void InitOnce();
-  static bool sse3_supported();
+  // x64 always has at least SSE2.
+  static bool sse2_supported() { return true; }
   static bool sse4_1_supported();
 
  private:
-  static const uint64_t kSSE3BitMask = static_cast<uint64_t>(1) << 32;
   static const uint64_t kSSE4_1BitMask = static_cast<uint64_t>(1) << 51;
 
-  static bool sse3_supported_;
   static bool sse4_1_supported_;
 #ifdef DEBUG
   static bool initialized_;
@@ -678,7 +677,18 @@
   inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
   inline void EmitFixup(AssemblerFixup* fixup);
   inline void EmitOperandSizeOverride();
-
+  inline void EmitREX_RB(XmmRegister reg,
+                         XmmRegister base,
+                         uint8_t rex = REX_NONE);
+  inline void EmitREX_RB(XmmRegister reg,
+                         const Operand& operand,
+                         uint8_t rex = REX_NONE);
+  inline void EmitREX_RB(XmmRegister reg,
+                         Register base,
+                         uint8_t rex = REX_NONE);
+  inline void EmitREX_RB(Register reg,
+                         XmmRegister base,
+                         uint8_t rex = REX_NONE);
   void EmitOperand(int rm, const Operand& operand);
   void EmitImmediate(const Immediate& imm);
   void EmitComplex(int rm, const Operand& operand, const Immediate& immediate);
@@ -726,6 +736,42 @@
 }
 
 
+inline void Assembler::EmitREX_RB(XmmRegister reg,
+                                  XmmRegister base,
+                                  uint8_t rex) {
+  if (reg > 7) rex |= REX_R;
+  if (base > 7) rex |= REX_B;
+  if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex);
+}
+
+
+inline void Assembler::EmitREX_RB(XmmRegister reg,
+                                  const Operand& operand,
+                                  uint8_t rex) {
+  if (reg > 7) rex |= REX_R;
+  rex |= operand.rex();
+  if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex);
+}
+
+
+inline void Assembler::EmitREX_RB(XmmRegister reg,
+                                  Register base,
+                                  uint8_t rex) {
+  if (reg > 7) rex |= REX_R;
+  if (base > 7) rex |= REX_B;
+  if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex);
+}
+
+
+inline void Assembler::EmitREX_RB(Register reg,
+                                  XmmRegister base,
+                                  uint8_t rex) {
+  if (reg > 7) rex |= REX_R;
+  if (base > 7) rex |= REX_B;
+  if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex);
+}
+
+
 inline void Assembler::EmitFixup(AssemblerFixup* fixup) {
   buffer_.EmitFixup(fixup);
 }
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc
index f2d6fce..32a54fa 100644
--- a/runtime/vm/assembler_x64_test.cc
+++ b/runtime/vm/assembler_x64_test.cc
@@ -1244,6 +1244,14 @@
   __ movss(XMM5, XMM4);
   __ movss(XMM6, XMM5);
   __ movss(XMM7, XMM6);
+  __ movss(XMM8, XMM7);
+  __ movss(XMM9, XMM8);
+  __ movss(XMM10, XMM9);
+  __ movss(XMM11, XMM10);
+  __ movss(XMM12, XMM11);
+  __ movss(XMM13, XMM12);
+  __ movss(XMM14, XMM13);
+  __ movss(XMM15, XMM14);
   __ pushq(R15);  // Callee saved.
   __ pushq(RAX);
   __ movq(Address(RSP, 0), Immediate(0));
@@ -1258,8 +1266,23 @@
   __ movss(XMM3, Address(R15, 0));
   __ movq(RAX, RSP);
   __ movss(Address(RAX, 0), XMM3);
-  __ movss(XMM4, Address(RAX, 0));
-  __ movss(XMM0, Address(RAX, 0));
+  __ movss(XMM1, Address(RAX, 0));
+  __ movss(XMM15, Address(RAX, 0));
+  __ movss(XMM14, XMM15);
+  __ movss(XMM13, XMM14);
+  __ movss(XMM12, XMM13);
+  __ movss(XMM11, XMM12);
+  __ movss(XMM10, XMM11);
+  __ movss(XMM9, XMM10);
+  __ movss(XMM8, XMM9);
+  __ movss(XMM7, XMM8);
+  __ movss(XMM6, XMM7);
+  __ movss(XMM5, XMM6);
+  __ movss(XMM4, XMM5);
+  __ movss(XMM3, XMM4);
+  __ movss(XMM2, XMM3);
+  __ movss(XMM1, XMM2);
+  __ movss(XMM0, XMM1);
   __ popq(RAX);
   __ popq(R15);  // Callee saved.
   __ ret();
@@ -1275,12 +1298,18 @@
 ASSEMBLER_TEST_GENERATE(SingleFPMoves2, assembler) {
   __ movq(RAX, Immediate(bit_cast<int32_t, float>(234.0f)));
   __ movd(XMM0, RAX);
-  __ movss(XMM1, XMM0);
+  __ movd(XMM8, RAX);
+  __ movss(XMM1, XMM8);
   __ pushq(RAX);
   __ movq(Address(RSP, 0), Immediate(0));
   __ movss(XMM0, Address(RSP, 0));
   __ movss(Address(RSP, 0), XMM1);
   __ movss(XMM0, Address(RSP, 0));
+  __ movq(Address(RSP, 0), Immediate(0));
+  __ movss(XMM9, XMM8);
+  __ movss(Address(RSP, 0), XMM9);
+  __ movss(XMM8, Address(RSP, 0));
+  __ movss(XMM0, XMM8);
   __ popq(RAX);
   __ ret();
 }
@@ -1297,12 +1326,19 @@
   __ pushq(RCX);
   __ movq(RBX, Immediate(bit_cast<int32_t, float>(12.3f)));
   __ movd(XMM0, RBX);
+  __ movd(XMM8, RBX);
   __ movq(RCX, Immediate(bit_cast<int32_t, float>(3.4f)));
   __ movd(XMM1, RCX);
+  __ movd(XMM9, RCX);
   __ addss(XMM0, XMM1);  // 15.7f
   __ mulss(XMM0, XMM1);  // 53.38f
   __ subss(XMM0, XMM1);  // 49.98f
   __ divss(XMM0, XMM1);  // 14.7f
+  __ addss(XMM8, XMM9);  // 15.7f
+  __ mulss(XMM8, XMM9);  // 53.38f
+  __ subss(XMM8, XMM9);  // 49.98f
+  __ divss(XMM8, XMM9);  // 14.7f
+  __ subss(XMM0, XMM8);  // 0.0f
   __ popq(RCX);
   __ popq(RBX);
   __ ret();
@@ -1312,7 +1348,7 @@
 ASSEMBLER_TEST_RUN(SingleFPOperations, entry) {
   typedef float (*SingleFPOperationsCode)();
   float res = reinterpret_cast<SingleFPOperationsCode>(entry)();
-  EXPECT_FLOAT_EQ(14.7f, res, 0.001f);
+  EXPECT_FLOAT_EQ(0.0f, res, 0.001f);
 }
 
 
@@ -1328,9 +1364,17 @@
   __ movsd(XMM5, XMM4);
   __ movsd(XMM6, XMM5);
   __ movsd(XMM7, XMM6);
+  __ movsd(XMM8, XMM7);
+  __ movsd(XMM9, XMM8);
+  __ movsd(XMM10, XMM9);
+  __ movsd(XMM11, XMM10);
+  __ movsd(XMM12, XMM11);
+  __ movsd(XMM13, XMM12);
+  __ movsd(XMM14, XMM13);
+  __ movsd(XMM15, XMM14);
   __ movq(Address(RSP, 0), Immediate(0));
   __ movsd(XMM0, Address(RSP, 0));
-  __ movsd(Address(RSP, 0), XMM7);
+  __ movsd(Address(RSP, 0), XMM15);
   __ movsd(XMM1, Address(RSP, 0));
   __ movq(R10, RSP);
   __ movsd(Address(R10, 0), XMM1);
@@ -1341,7 +1385,15 @@
   __ movq(RAX, RSP);
   __ movsd(Address(RAX, 0), XMM3);
   __ movsd(XMM4, Address(RAX, 0));
-  __ movsd(XMM7, Address(RSP, 0));
+  __ movsd(XMM15, Address(RSP, 0));
+  __ movaps(XMM14, XMM15);
+  __ movaps(XMM13, XMM14);
+  __ movaps(XMM12, XMM13);
+  __ movaps(XMM11, XMM12);
+  __ movaps(XMM10, XMM11);
+  __ movaps(XMM9, XMM10);
+  __ movaps(XMM8, XMM9);
+  __ movaps(XMM7, XMM8);
   __ movaps(XMM6, XMM7);
   __ movaps(XMM5, XMM6);
   __ movaps(XMM4, XMM5);
@@ -1365,13 +1417,22 @@
   __ movq(RAX, Immediate(bit_cast<int64_t, double>(12.3)));
   __ pushq(RAX);
   __ movsd(XMM0, Address(RSP, 0));
+  __ movsd(XMM8, Address(RSP, 0));
   __ movq(RAX, Immediate(bit_cast<int64_t, double>(3.4)));
   __ movq(Address(RSP, 0), RAX);
+  __ movsd(XMM12, Address(RSP, 0));
+  __ addsd(XMM8, XMM12);  // 15.7
+  __ mulsd(XMM8, XMM12);  // 53.38
+  __ subsd(XMM8, XMM12);  // 49.98
+  __ divsd(XMM8, XMM12);  // 14.7
+  __ sqrtsd(XMM8, XMM8);  // 3.834
   __ movsd(XMM1, Address(RSP, 0));
   __ addsd(XMM0, XMM1);  // 15.7
   __ mulsd(XMM0, XMM1);  // 53.38
   __ subsd(XMM0, XMM1);  // 49.98
   __ divsd(XMM0, XMM1);  // 14.7
+  __ sqrtsd(XMM0, XMM0);  // 3.834057902
+  __ addsd(XMM0, XMM8);  // 7.6681
   __ popq(RAX);
   __ ret();
 }
@@ -1380,13 +1441,16 @@
 ASSEMBLER_TEST_RUN(DoubleFPOperations, entry) {
   typedef double (*SingleFPOperationsCode)();
   double res = reinterpret_cast<SingleFPOperationsCode>(entry)();
-  EXPECT_FLOAT_EQ(14.7, res, 0.001);
+  EXPECT_FLOAT_EQ(7.668, res, 0.001);
 }
 
 
 ASSEMBLER_TEST_GENERATE(Int32ToDoubleConversion, assembler) {
   __ movl(RDX, Immediate(6));
   __ cvtsi2sd(XMM0, RDX);
+  __ movl(RDX, Immediate(8));
+  __ cvtsi2sd(XMM8, RDX);
+  __ subsd(XMM0, XMM8);
   __ ret();
 }
 
@@ -1394,13 +1458,16 @@
 ASSEMBLER_TEST_RUN(Int32ToDoubleConversion, entry) {
   typedef double (*IntToDoubleConversionCode)();
   double res = reinterpret_cast<IntToDoubleConversionCode>(entry)();
-  EXPECT_FLOAT_EQ(6.0, res, 0.001);
+  EXPECT_FLOAT_EQ(-2.0, res, 0.001);
 }
 
 
 ASSEMBLER_TEST_GENERATE(Int64ToDoubleConversion, assembler) {
   __ movq(RDX, Immediate(12LL << 32));
   __ cvtsi2sd(XMM0, RDX);
+  __ movsd(XMM15, XMM0);  // Move to high register
+  __ addsd(XMM0, XMM0);  // Stomp XMM0
+  __ movsd(XMM0, XMM15);  // Move back to XMM0
   __ ret();
 }
 
@@ -1415,9 +1482,14 @@
 ASSEMBLER_TEST_GENERATE(DoubleToInt64Conversion, assembler) {
   __ movq(RAX, Immediate(bit_cast<int64_t, double>(12.3)));
   __ pushq(RAX);
+  __ movsd(XMM9, Address(RSP, 0));
   __ movsd(XMM6, Address(RSP, 0));
   __ popq(RAX);
+  __ cvttsd2siq(R10, XMM6);
   __ cvttsd2siq(RDX, XMM6);
+  __ cvttsd2siq(R10, XMM9);
+  __ cvttsd2siq(RDX, XMM9);
+  __ subq(RDX, R10);
   __ movq(RAX, RDX);
   __ ret();
 }
@@ -1426,7 +1498,7 @@
 ASSEMBLER_TEST_RUN(DoubleToInt64Conversion, entry) {
   typedef int64_t (*DoubleToInt64ConversionCode)();
   int64_t res = reinterpret_cast<DoubleToInt64ConversionCode>(entry)();
-  EXPECT_EQ(12, res);
+  EXPECT_EQ(0, res);
 }
 
 
@@ -1605,7 +1677,14 @@
 
 
 ASSEMBLER_TEST_GENERATE(XorpdZeroing2, assembler) {
+  Label done;
+  __ xorpd(XMM15, XMM15);
   __ xorpd(XMM0, XMM0);
+  __ xorpd(XMM0, XMM15);
+  __ comisd(XMM0, XMM15);
+  __ j(ZERO, &done);
+  __ int3();
+  __ Bind(&done);
   __ ret();
 }
 
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 29a2417..d719b0e 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -275,7 +275,7 @@
   char* script = NULL;
   if (dart_root != NULL) {
     const char* kFormatStr =
-        "#import('%s/sdk/lib/_internal/compiler/compiler.dart');";
+        "import '%s/sdk/lib/_internal/compiler/compiler.dart';";
     intptr_t len = OS::SNPrint(NULL, 0, kFormatStr, dart_root) + 1;
     script = reinterpret_cast<char*>(malloc(len));
     EXPECT(script != NULL);
@@ -286,7 +286,7 @@
     EXPECT_VALID(lib);
   } else {
     Dart_Handle lib = TestCase::LoadTestScript(
-        "#import('sdk/lib/_internal/compiler/compiler.dart');",
+        "import 'sdk/lib/_internal/compiler/compiler.dart';",
         reinterpret_cast<Dart_NativeEntryResolver>(NativeResolver));
     EXPECT_VALID(lib);
   }
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index 47a8c3a..9978bf7 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -60,7 +60,7 @@
   ASSERT(!library.IsNull());
   library.set_native_entry_resolver(resolver);
 
-  library = Library::CollectionLibrary();
+  library = Library::MathLibrary();
   ASSERT(!library.IsNull());
   library.set_native_entry_resolver(resolver);
 
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 7b424b0..fad33c9 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -27,6 +27,7 @@
   V(Integer_moduloFromInteger, 2)                                              \
   V(Integer_greaterThanFromInteger, 2)                                         \
   V(Integer_equalToInteger, 2)                                                 \
+  V(Integer_parse, 1)                                                          \
   V(ReceivePortImpl_factory, 1)                                                \
   V(ReceivePortImpl_closeInternal, 1)                                          \
   V(SendPortImpl_sendInternal_, 3)                                             \
@@ -55,6 +56,7 @@
   V(Double_ceil, 1)                                                            \
   V(Double_truncate, 1)                                                        \
   V(Double_toInt, 1)                                                           \
+  V(Double_parse, 1)                                                           \
   V(Double_toStringAsFixed, 2)                                                 \
   V(Double_toStringAsExponential, 2)                                           \
   V(Double_toStringAsPrecision, 2)                                             \
@@ -80,19 +82,16 @@
   V(String_toLowerCase, 1)                                                     \
   V(String_toUpperCase, 1)                                                     \
   V(Strings_concatAll, 1)                                                      \
-  V(MathNatives_sqrt, 1)                                                       \
-  V(MathNatives_sin, 1)                                                        \
-  V(MathNatives_cos, 1)                                                        \
-  V(MathNatives_tan, 1)                                                        \
-  V(MathNatives_asin, 1)                                                       \
-  V(MathNatives_acos, 1)                                                       \
-  V(MathNatives_atan, 1)                                                       \
-  V(MathNatives_atan2, 2)                                                      \
-  V(MathNatives_exp, 1)                                                        \
-  V(MathNatives_log, 1)                                                        \
-  V(MathNatives_random, 0)                                                     \
-  V(MathNatives_parseInt, 1)                                                   \
-  V(MathNatives_parseDouble, 1)                                                \
+  V(Math_sqrt, 1)                                                              \
+  V(Math_sin, 1)                                                               \
+  V(Math_cos, 1)                                                               \
+  V(Math_tan, 1)                                                               \
+  V(Math_asin, 1)                                                              \
+  V(Math_acos, 1)                                                              \
+  V(Math_atan, 1)                                                              \
+  V(Math_atan2, 2)                                                             \
+  V(Math_exp, 1)                                                               \
+  V(Math_log, 1)                                                               \
   V(DateNatives_currentTimeMillis, 0)                                          \
   V(DateNatives_timeZoneName, 1)                                               \
   V(DateNatives_timeZoneOffsetInSeconds, 1)                                    \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 3283db1..bae68fd 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -838,16 +838,6 @@
       type_argument = arguments.TypeAt(i);
       type_argument = FinalizeType(cls, type_argument, finalization);
       if (type_argument.IsMalformed()) {
-        // Malformed type arguments to a constructor of a generic type are
-        // reported as a compile-time error.
-        if (finalization >= kCanonicalizeForCreation) {
-          const Script& script = Script::Handle(cls.script());
-          const String& type_name =
-              String::Handle(parameterized_type.UserVisibleName());
-          ReportError(script, parameterized_type.token_pos(),
-                      "type '%s' has malformed type argument",
-                      type_name.ToCString());
-        }
         // In production mode, malformed type arguments are mapped to dynamic.
         // In checked mode, a type with malformed type arguments is malformed.
         if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) {
@@ -877,7 +867,7 @@
   // However, type parameter bounds are checked below, even for a raw type.
   if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
     // Wrong number of type arguments. The type is malformed.
-    if (finalization >= kCanonicalizeForCreation) {
+    if (finalization >= kCanonicalizeExpression) {
       const Script& script = Script::Handle(cls.script());
       const String& type_name =
           String::Handle(parameterized_type.UserVisibleName());
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index 18ce755..2fe9ea6 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -33,10 +33,13 @@
     kDoNotResolve,             // Type resolution is postponed.
     kTryResolve,               // Type resolution is attempted.
     kFinalize,                 // Type resolution and type finalization are
-                               // required; a malformed type is tolerated.
+                               // required; a malformed type is tolerated, since
+                               // the type may be used as a type annotation.
     kCanonicalize,             // Same as kFinalize, but with canonicalization.
-    kCanonicalizeForCreation,  // Same as kCanonicalize, but do not tolerate
-                               // wrong number of type arguments.
+    kCanonicalizeExpression,   // Same as kCanonicalize, but do not tolerate
+                               // wrong number of type arguments or ambiguous
+                               // type reference, since the type is not used as
+                               // a type annotation, but as a type expression.
     kCanonicalizeWellFormed    // Error-free resolution, finalization, and
                                // canonicalization are required; a malformed
                                // type is not tolerated.
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 008673f..f24bd03 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -770,73 +770,38 @@
 }
 
 
-static bool UpdateResolvedStaticCall(const Code& code,
-                              intptr_t offset,
-                              const Code& target_code) {
-  // PC offsets are mapped to the corresponding code object in the
-  // resolved_static_calls array. The array grows as static calls are being
-  // resolved.
-  const int kOffset = 0;
-  const int kCode = 1;
-  const int kEntrySize = 2;
-
-  GrowableObjectArray& resolved_static_calls =
-      GrowableObjectArray::Handle(code.resolved_static_calls());
-  intptr_t index = -1;
-  if (resolved_static_calls.IsNull()) {
-    resolved_static_calls = GrowableObjectArray::New(2, Heap::kOld);
-    code.set_resolved_static_calls(resolved_static_calls);
-  } else {
-    // Search for the offset in the resolved static calls.
-    const intptr_t len = resolved_static_calls.Length();
-    Object& off = Object::Handle();
-    for (intptr_t i = 0; i < len; i += kEntrySize) {
-      off = resolved_static_calls.At(i + kOffset);
-      if (Smi::Cast(off).Value() == offset) {
-        index = i;
-        break;
-      }
-    }
-  }
-  if (index == -1) {
-    // The static call with this offset is not yet present: Add it.
-    resolved_static_calls.Add(Smi::Handle(Smi::New(offset)));
-    resolved_static_calls.Add(target_code);
-  } else {
-    // Overwrite the currently recorded target.
-    resolved_static_calls.SetAt(index + kCode, target_code);
-  }
-  return index != -1;
-}
-
-
+// Patches static call with the target's entry point. Compiles target if
+// necessary.
 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) {
-  // This function is called after successful resolving and compilation of
-  // the target method.
   ASSERT(arguments.ArgCount() == kPatchStaticCallRuntimeEntry.argument_count());
   DartFrameIterator iterator;
   StackFrame* caller_frame = iterator.NextFrame();
   ASSERT(caller_frame != NULL);
-  uword target = 0;
-  Function& target_function = Function::Handle();
-  CodePatcher::GetStaticCallAt(caller_frame->pc(), &target_function, &target);
-  ASSERT(target_function.HasCode());
+  const Code& caller_code = Code::Handle(caller_frame->LookupDartCode());
+  ASSERT(!caller_code.IsNull());
+  const Function& target_function = Function::Handle(
+      caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc()));
+  if (!target_function.HasCode()) {
+    const Error& error =
+        Error::Handle(Compiler::CompileFunction(target_function));
+    if (!error.IsNull()) {
+      Exceptions::PropagateError(error);
+    }
+  }
   const Code& target_code = Code::Handle(target_function.CurrentCode());
-  uword new_target = target_code.EntryPoint();
-  // Verify that we are not patching repeatedly.
-  ASSERT(target != new_target);
-  CodePatcher::PatchStaticCallAt(caller_frame->pc(), new_target);
-  const Code& code = Code::Handle(caller_frame->LookupDartCode());
-  bool found = UpdateResolvedStaticCall(code,
-                                        caller_frame->pc() - code.EntryPoint(),
-                                        target_code);
-  ASSERT(!found);
+  // Before patching verify that we are not repeatedly patching to the same
+  // target.
+  ASSERT(target_code.EntryPoint() !=
+         CodePatcher::GetStaticCallTargetAt(caller_frame->pc()));
+  CodePatcher::PatchStaticCallAt(caller_frame->pc(), target_code.EntryPoint());
+  caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
   if (FLAG_trace_patching) {
     OS::Print("PatchStaticCall: patching from %#"Px" to '%s' %#"Px"\n",
         caller_frame->pc(),
         target_function.ToFullyQualifiedCString(),
-        new_target);
+        target_code.EntryPoint());
   }
+  arguments.SetReturn(target_code);
 }
 
 
@@ -904,8 +869,7 @@
 
 
 // Gets called from debug stub when code reaches a breakpoint.
-//   Arg0: function object of the static function that was about to be called.
-DEFINE_RUNTIME_ENTRY(BreakpointStaticHandler, 1) {
+DEFINE_RUNTIME_ENTRY(BreakpointStaticHandler, 0) {
   ASSERT(arguments.ArgCount() ==
       kBreakpointStaticHandlerRuntimeEntry.argument_count());
   ASSERT(isolate->debugger() != NULL);
@@ -913,13 +877,20 @@
   // Make sure the static function that is about to be called is
   // compiled. The stub will jump to the entry point without any
   // further tests.
-  const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
+  DartFrameIterator iterator;
+  StackFrame* caller_frame = iterator.NextFrame();
+  ASSERT(caller_frame != NULL);
+  const Code& code = Code::Handle(caller_frame->LookupDartCode());
+  const Function& function =
+      Function::Handle(code.GetStaticCallTargetFunctionAt(caller_frame->pc()));
+
   if (!function.HasCode()) {
     const Error& error = Error::Handle(Compiler::CompileFunction(function));
     if (!error.IsNull()) {
       Exceptions::PropagateError(error);
     }
   }
+  arguments.SetReturn(Code::ZoneHandle(function.CurrentCode()));
 }
 
 
@@ -1376,12 +1347,6 @@
   const Array& function_args = Array::CheckedHandle(arguments.ArgAt(1));
   const String& function_name = String::Handle(Symbols::Call());
   GrowableArray<const Object*> dart_arguments(5);
-  if (instance.IsNull()) {
-    dart_arguments.Add(&function_name);
-    dart_arguments.Add(&function_args);
-    Exceptions::ThrowByType(Exceptions::kNullPointer, dart_arguments);
-    UNREACHABLE();
-  }
 
   // TODO(regis): Resolve and invoke "call" method, if existing.
 
@@ -1565,13 +1530,10 @@
 
 
 // The caller must be a static call in a Dart frame, or an entry frame.
-// Patch static call to point to 'new_entry_point'.
-DEFINE_RUNTIME_ENTRY(FixCallersTarget, 1) {
+// Patch static call to point to valid code's entry point.
+DEFINE_RUNTIME_ENTRY(FixCallersTarget, 0) {
   ASSERT(arguments.ArgCount() ==
       kFixCallersTargetRuntimeEntry.argument_count());
-  const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
-  ASSERT(!function.IsNull());
-  ASSERT(function.HasCode());
 
   StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames);
   StackFrame* frame = iterator.NextFrame();
@@ -1579,29 +1541,25 @@
     frame = iterator.NextFrame();
   }
   ASSERT(frame != NULL);
-  if (!frame->IsEntryFrame()) {
-    ASSERT(frame->IsDartFrame());
-    uword target = 0;
-    Function& target_function = Function::Handle();
-    CodePatcher::GetStaticCallAt(frame->pc(), &target_function, &target);
-    ASSERT(target_function.HasCode());
-    ASSERT(target_function.raw() == function.raw());
-    const Code& target_code = Code::Handle(function.CurrentCode());
-    const uword new_entry_point = target_code.EntryPoint();
-    ASSERT(target != new_entry_point);  // Why patch otherwise.
-    CodePatcher::PatchStaticCallAt(frame->pc(), new_entry_point);
-    const Code& code = Code::Handle(frame->LookupDartCode());
-    bool found = UpdateResolvedStaticCall(code,
-                                          frame->pc() - code.EntryPoint(),
-                                          target_code);
-    ASSERT(found);
-    if (FLAG_trace_patching) {
-      OS::Print("FixCallersTarget: patching from %#"Px" to '%s' %#"Px"\n",
-          frame->pc(),
-          target_function.ToFullyQualifiedCString(),
-          new_entry_point);
-    }
+  if (frame->IsEntryFrame()) {
+    // Since function's current code is always unpatched, the entry frame always
+    // calls to unpatched code.
+    UNREACHABLE();
   }
+  ASSERT(frame->IsDartFrame());
+  const Code& caller_code = Code::Handle(frame->LookupDartCode());
+  const Function& target_function = Function::Handle(
+      caller_code.GetStaticCallTargetFunctionAt(frame->pc()));
+  const Code& target_code = Code::Handle(target_function.CurrentCode());
+  CodePatcher::PatchStaticCallAt(frame->pc(), target_code.EntryPoint());
+  caller_code.SetStaticCallTargetCodeAt(frame->pc(), target_code);
+  if (FLAG_trace_patching) {
+    OS::Print("FixCallersTarget: patching from %#"Px" to '%s' %#"Px"\n",
+        frame->pc(),
+        Function::Handle(target_code.function()).ToFullyQualifiedCString(),
+        target_code.EntryPoint());
+  }
+  arguments.SetReturn(target_code);
 }
 
 
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index ebe8980..8377692 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -43,10 +43,7 @@
   // or dynamic Dart call.
   static bool IsDartCall(uword return_address);
 
-  // Get static call information.
-  static void GetStaticCallAt(uword return_address,
-                              Function* function,
-                              uword* target);
+  static uword GetStaticCallTargetAt(uword return_address);
 
   // Get instance call information.
   static void GetInstanceCallAt(uword return_address,
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc
index e67ce9d..0211183 100644
--- a/runtime/vm/code_patcher_arm.cc
+++ b/runtime/vm/code_patcher_arm.cc
@@ -10,7 +10,6 @@
 namespace dart {
 
 void CodePatcher::GetStaticCallAt(uword return_address,
-                                  Function* function,
                                   uword* target) {
   UNIMPLEMENTED();
 }
diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc
index fc9a340..83260ce 100644
--- a/runtime/vm/code_patcher_ia32.cc
+++ b/runtime/vm/code_patcher_ia32.cc
@@ -14,7 +14,7 @@
 
 namespace dart {
 
-// The pattern of a Dart call is:
+// The pattern of a Dart instance call is:
 //  1: mov ECX, immediate 1
 //  2: mov EDX, immediate 2
 //  3: call target_address
@@ -97,27 +97,6 @@
 };
 
 
-// The expected pattern of a dart static call:
-//  mov ECX, function_object
-//  mov EDX, argument_descriptor_array
-//  call target_address
-//  <- return address
-class StaticCall : public DartCallPattern {
- public:
-  explicit StaticCall(uword return_address)
-      : DartCallPattern(return_address) {}
-
-  RawFunction* function() const {
-    Function& f = Function::Handle();
-    f ^= reinterpret_cast<RawObject*>(immediate_one());
-    return f.raw();
-  }
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
-};
-
-
 // The expected pattern of a dart instance call:
 //  mov ECX, ic-data
 //  mov EDX, argument_descriptor_array
@@ -139,14 +118,59 @@
 };
 
 
-void CodePatcher::GetStaticCallAt(uword return_address,
-                                  Function* function,
-                                  uword* target) {
-  ASSERT(function != NULL);
-  ASSERT(target != NULL);
+// The expected pattern of a dart static call:
+//  mov EDX, argument_descriptor_array
+//  call target_address
+//  <- return address
+class StaticCall : public ValueObject {
+ public:
+  explicit StaticCall(uword return_address)
+      : start_(return_address - (kNumInstructions * kInstructionSize)) {
+    ASSERT(IsValid(return_address));
+    ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize);
+  }
+
+  static bool IsValid(uword return_address) {
+    uint8_t* code_bytes =
+        reinterpret_cast<uint8_t*>(
+            return_address - (kNumInstructions * kInstructionSize));
+    return (code_bytes[0] == 0xBA) &&
+           (code_bytes[1 * kInstructionSize] == 0xE8);
+  }
+
+  uword target() const {
+    const uword offset = *reinterpret_cast<uword*>(call_address() + 1);
+    return return_address() + offset;
+  }
+
+  void set_target(uword target) const {
+    uword* target_addr = reinterpret_cast<uword*>(call_address() + 1);
+    uword offset = target - return_address();
+    *target_addr = offset;
+    CPU::FlushICache(call_address(), kInstructionSize);
+  }
+
+  static const int kNumInstructions = 2;
+  static const int kInstructionSize = 5;  // All instructions have same length.
+
+ private:
+  uword return_address() const {
+    return start_ + kNumInstructions * kInstructionSize;
+  }
+
+  uword call_address() const {
+    return start_ + 1 * kInstructionSize;
+  }
+
+  uword start_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
+};
+
+
+uword CodePatcher::GetStaticCallTargetAt(uword return_address) {
   StaticCall call(return_address);
-  *target = call.target();
-  *function = call.function();
+  return call.target();
 }
 
 
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc
index 059c9cd..58a3785 100644
--- a/runtime/vm/code_patcher_x64.cc
+++ b/runtime/vm/code_patcher_x64.cc
@@ -14,7 +14,7 @@
 
 namespace dart {
 
-// The pattern of a Dart call is:
+// The pattern of a Dart instance call is:
 //  00: 48 bb imm64  mov RBX, immediate 1
 //  10: 49 ba imm64  mov R10, immediate 2
 //  20: 49 bb imm64  mov R11, target_address
@@ -87,24 +87,13 @@
 };
 
 
-// A Dart static call passes the function object in RBX.
-class StaticCall : public DartCallPattern {
- public:
-  explicit StaticCall(uword return_address)
-      : DartCallPattern(return_address) {}
-
-  RawFunction* function() const {
-    Function& f = Function::Handle();
-    f ^= reinterpret_cast<RawObject*>(immediate_one());
-    return f.raw();
-  }
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
-};
-
-
 // A Dart instance call passes the ic-data in RBX.
+// The expected pattern of a dart instance call:
+//  mov RBX, ic-data
+//  mov R10, argument_descriptor_array
+//  mov R11, target_address
+//  call R11
+//  <- return address
 class InstanceCall : public DartCallPattern {
  public:
   explicit InstanceCall(uword return_address)
@@ -121,14 +110,50 @@
 };
 
 
-void CodePatcher::GetStaticCallAt(uword return_address,
-                                  Function* function,
-                                  uword* target) {
-  ASSERT(function != NULL);
-  ASSERT(target != NULL);
+// The expected pattern of a dart static call:
+//  mov R10, argument_descriptor_array (10 bytes)
+//  mov R11, target_address (10 bytes)
+//  call R11  (3 bytes)
+//  <- return address
+class StaticCall : public ValueObject {
+ public:
+  explicit StaticCall(uword return_address)
+      : start_(return_address - kCallPatternSize) {
+    ASSERT(IsValid(return_address));
+    ASSERT((kCallPatternSize - 10) == Assembler::kCallExternalLabelSize);
+  }
+
+  static const int kCallPatternSize = 23;
+
+  static bool IsValid(uword return_address) {
+    uint8_t* code_bytes =
+        reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
+    return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
+           (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) &&
+           (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) &&
+           (code_bytes[22] == 0xD3);
+  }
+
+  uword target() const {
+    return *reinterpret_cast<uword*>(start_ + 10 + 2);
+  }
+
+  void set_target(uword target) const {
+    uword* target_addr = reinterpret_cast<uword*>(start_ + 10 + 2);
+    *target_addr = target;
+    CPU::FlushICache(start_ + 10, 2 + 8);
+  }
+
+ private:
+  uword start_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
+};
+
+
+uword CodePatcher::GetStaticCallTargetAt(uword return_address) {
   StaticCall call(return_address);
-  *target = call.target();
-  *function = call.function();
+  return call.target();
 }
 
 
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 4b11672..25cb8a3 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -277,6 +277,7 @@
       graph_compiler.FinalizeVarDescriptors(code);
       graph_compiler.FinalizeExceptionHandlers(code);
       graph_compiler.FinalizeComments(code);
+      graph_compiler.FinalizeStaticCallTargetsTable(code);
       if (optimized) {
         CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
         function.SetCode(code);
@@ -416,6 +417,25 @@
   const ExceptionHandlers& handlers =
         ExceptionHandlers::Handle(code.exception_handlers());
   OS::Print("%s}\n", handlers.ToCString());
+
+  {
+    OS::Print("Static call target functions {\n");
+    const Array& table = Array::Handle(code.static_calls_target_table());
+    Smi& offset = Smi::Handle();
+    Function& function = Function::Handle();
+    Code& code = Code::Handle();
+    for (intptr_t i = 0; i < table.Length();
+        i += Code::kSCallTableEntryLength) {
+      offset ^= table.At(i + Code::kSCallTableOffsetEntry);
+      function ^= table.At(i + Code::kSCallTableFunctionEntry);
+      code ^= table.At(i + Code::kSCallTableCodeEntry);
+      OS::Print("  0x%"Px": %s, %p\n",
+          start + offset.Value(),
+          function.ToFullyQualifiedCString(),
+          code.raw());
+    }
+    OS::Print("}\n");
+  }
 }
 
 
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 1c8325f..02a84b7 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -69,7 +69,8 @@
   TIMES_1 = 0,
   TIMES_2 = 1,
   TIMES_4 = 2,
-  TIMES_8 = 3
+  TIMES_8 = 3,
+  TIMES_HALF_WORD_SIZE = kWordSizeLog2 - 1
 };
 
 
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 579ea56..38a2046 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -51,7 +51,15 @@
   XMM5 = 5,
   XMM6 = 6,
   XMM7 = 7,
-  kNumberOfXmmRegisters = 8,
+  XMM8 = 8,
+  XMM9 = 9,
+  XMM10 = 10,
+  XMM11 = 11,
+  XMM12 = 12,
+  XMM13 = 13,
+  XMM14 = 14,
+  XMM15 = 15,
+  kNumberOfXmmRegisters = 16,
   kNoXmmRegister = -1  // Signals an illegal register.
 };
 
@@ -84,7 +92,8 @@
   TIMES_1 = 0,
   TIMES_2 = 1,
   TIMES_4 = 2,
-  TIMES_8 = 3
+  TIMES_8 = 3,
+  TIMES_HALF_WORD_SIZE = kWordSizeLog2 - 1
 };
 
 
diff --git a/runtime/vm/custom_isolate_test.cc b/runtime/vm/custom_isolate_test.cc
index 2090a7d..d8e2444 100644
--- a/runtime/vm/custom_isolate_test.cc
+++ b/runtime/vm/custom_isolate_test.cc
@@ -24,7 +24,7 @@
 
 
 static const char* kCustomIsolateScriptChars =
-    "#import('dart:isolate');\n"
+    "import 'dart:isolate';\n"
     "\n"
     "ReceivePort mainPort;\n"
     "\n"
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 99e2886..fcc3501 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -48,12 +48,12 @@
 
 
 // TODO(turnidge): We should add a corresponding Dart::Cleanup.
-bool Dart::InitOnce(Dart_IsolateCreateCallback create,
+const char* Dart::InitOnce(Dart_IsolateCreateCallback create,
                     Dart_IsolateInterruptCallback interrupt,
                     Dart_IsolateShutdownCallback shutdown) {
   // TODO(iposva): Fix race condition here.
   if (vm_isolate_ != NULL || !Flags::Initialized()) {
-    return false;
+    return "VM already initialized.";
   }
   OS::InitOnce();
   VirtualMemory::InitOnce();
@@ -78,8 +78,10 @@
     Symbols::InitOnce(vm_isolate_);
     CPUFeatures::InitOnce();
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
-    // Dart VM requires at least SSE3.
-    if (!CPUFeatures::sse3_supported()) return false;
+    // Dart VM requires at least SSE2.
+    if (!CPUFeatures::sse2_supported()) {
+      return "SSE2 is required.";
+    }
 #endif
     PremarkingVisitor premarker(vm_isolate_);
     vm_isolate_->heap()->IterateOldObjects(&premarker);
@@ -89,7 +91,7 @@
   Isolate::SetCreateCallback(create);
   Isolate::SetInterruptCallback(interrupt);
   Isolate::SetShutdownCallback(shutdown);
-  return true;
+  return NULL;
 }
 
 
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 4b741e0..585cddd 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -18,9 +18,9 @@
 
 class Dart : public AllStatic {
  public:
-  static bool InitOnce(Dart_IsolateCreateCallback create,
-                       Dart_IsolateInterruptCallback interrupt,
-                       Dart_IsolateShutdownCallback shutdown);
+  static const char* InitOnce(Dart_IsolateCreateCallback create,
+                              Dart_IsolateInterruptCallback interrupt,
+                              Dart_IsolateShutdownCallback shutdown);
 
   static Isolate* CreateIsolate(const char* name_prefix);
   static RawError* InitializeIsolate(const uint8_t* snapshot, void* data);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 88d0389..aed8a10 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -739,7 +739,12 @@
 DART_EXPORT bool Dart_Initialize(Dart_IsolateCreateCallback create,
                                  Dart_IsolateInterruptCallback interrupt,
                                  Dart_IsolateShutdownCallback shutdown) {
-  return Dart::InitOnce(create, interrupt, shutdown);
+  const char* err_msg = Dart::InitOnce(create, interrupt, shutdown);
+  if (err_msg != NULL) {
+    OS::PrintErr("Dart_Initialize: %s\n", err_msg);
+    return false;
+  }
+  return true;
 }
 
 DART_EXPORT bool Dart_SetVMFlags(int argc, const char** argv) {
@@ -1571,7 +1576,7 @@
 }
 
 
-DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const uint32_t* utf32_array,
+DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array,
                                                 intptr_t length) {
   Isolate* isolate = Isolate::Current();
   DARTSCOPE(isolate);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 0fa7e0b..ecc1df1 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -541,7 +541,7 @@
   EXPECT(Dart_IsString(ext16));
   EXPECT(Dart_IsExternalString(ext16));
 
-  uint32_t data32[] = { 'f', 'o', 'u', 'r', 0x10FFFF };
+  int32_t data32[] = { 'f', 'o', 'u', 'r', 0x10FFFF };
 
   Dart_Handle str32 = Dart_NewStringFromUTF32(data32, ARRAY_SIZE(data32));
   EXPECT_VALID(str32);
@@ -2647,7 +2647,7 @@
       "  return new Fields();\n"
       "}\n";
   const char* kImportedScriptChars =
-      "#library('library_name');\n"
+      "library library_name;\n"
       "var imported_fld = 'imported';\n"
       "var _imported_fld = 'hidden imported';\n"
       "get imported_getset_fld { return _gs_fld1; }\n"
@@ -2951,7 +2951,7 @@
 
 TEST_CASE(InjectNativeFields3) {
   const char* kScriptChars =
-      "#import('dart:nativewrappers');"
+      "import 'dart:nativewrappers';"
       "class NativeFields extends NativeFieldWrapperClass2 {\n"
       "  NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
       "  int fld1;\n"
@@ -2993,7 +2993,7 @@
 
 TEST_CASE(InjectNativeFields4) {
   const char* kScriptChars =
-      "#import('dart:nativewrappers');"
+      "import 'dart:nativewrappers';"
       "class NativeFields extends NativeFieldWrapperClass2 {\n"
       "  NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
       "  int fld1;\n"
@@ -3015,7 +3015,7 @@
   // We expect the test script to fail finalization with the error below:
   EXPECT(Dart_IsError(result));
   Dart_Handle expected_error = Dart_Error(
-      "'dart:test-lib': Error: line 1 pos 38: "
+      "'dart:test-lib': Error: line 1 pos 36: "
       "class 'NativeFields' is trying to extend a native fields class, "
       "but library '%s' has no native resolvers",
       TestCase::url());
@@ -3025,7 +3025,7 @@
 
 TEST_CASE(InjectNativeFieldsSuperClass) {
   const char* kScriptChars =
-      "#import('dart:nativewrappers');"
+      "import 'dart:nativewrappers';"
       "class NativeFieldsSuper extends NativeFieldWrapperClass1 {\n"
       "  NativeFieldsSuper() : fld1 = 42 {}\n"
       "  int fld1;\n"
@@ -3185,7 +3185,7 @@
 
 TEST_CASE(ImplicitNativeFieldAccess) {
   const char* kScriptChars =
-      "#import('dart:nativewrappers');"
+      "import 'dart:nativewrappers';"
       "class NativeFields extends NativeFieldWrapperClass4 {\n"
       "  NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
       "  int fld0;\n"
@@ -3811,11 +3811,11 @@
 
 TEST_CASE(Invoke_CrossLibrary) {
   const char* kLibrary1Chars =
-      "#library('library1_name');\n"
+      "library library1_name;\n"
       "void local() {}\n"
       "void _local() {}\n";
   const char* kLibrary2Chars =
-      "#library('library2_name');\n"
+      "library library2_name;\n"
       "void imported() {}\n"
       "void _imported() {}\n";
 
@@ -5115,11 +5115,11 @@
 
 TEST_CASE(LookupLibrary) {
   const char* kScriptChars =
-      "#import('library1.dart');"
+      "import 'library1_dart';"
       "main() {}";
   const char* kLibrary1Chars =
-      "#library('library1.dart');"
-      "#import('library2.dart');";
+      "library library1_dart;"
+      "import 'library2_dart';";
 
   // Create a test library and Load up a test script in it.
   Dart_Handle url = NewString(TestCase::url());
@@ -5129,7 +5129,7 @@
   result = Dart_LoadScript(url, source);
   EXPECT_VALID(result);
 
-  url = NewString("library1.dart");
+  url = NewString("library1_dart");
   source = NewString(kLibrary1Chars);
   result = Dart_LoadLibrary(url, source);
   EXPECT_VALID(result);
@@ -5162,7 +5162,7 @@
 
 TEST_CASE(LibraryName) {
   const char* kLibrary1Chars =
-      "#library('library1_name');";
+      "library library1_name;";
   Dart_Handle url = NewString("library1_url");
   Dart_Handle source = NewString(kLibrary1Chars);
   Dart_Handle lib = Dart_LoadLibrary(url, source);
@@ -5195,7 +5195,7 @@
 
 TEST_CASE(LibraryUrl) {
   const char* kLibrary1Chars =
-      "#library('library1_name');";
+      "library library1_name;";
   Dart_Handle url = NewString("library1_url");
   Dart_Handle source = NewString(kLibrary1Chars);
   Dart_Handle lib = Dart_LoadLibrary(url, source);
@@ -5228,7 +5228,7 @@
 
 TEST_CASE(LibraryGetClassNames) {
   const char* kLibraryChars =
-      "#library('library_name');\n"
+      "library library_name;\n"
       "\n"
       "class A {}\n"
       "class B {}\n"
@@ -5265,7 +5265,7 @@
 
 TEST_CASE(GetFunctionNames) {
   const char* kLibraryChars =
-      "#library('library_name');\n"
+      "library library_name;\n"
       "\n"
       "void A() {}\n"
       "get B => 11;\n"
@@ -5335,7 +5335,7 @@
 
 TEST_CASE(GetVariableNames) {
   const char* kLibraryChars =
-      "#library('library_name');\n"
+      "library library_name;\n"
       "\n"
       "var A;\n"
       "get B => 12;\n"
@@ -5400,9 +5400,9 @@
 
 TEST_CASE(LibraryImportLibrary) {
   const char* kLibrary1Chars =
-      "#library('library1_name');";
+      "library library1_name;";
   const char* kLibrary2Chars =
-      "#library('library2_name');";
+      "library library2_name;";
   Dart_Handle error = Dart_Error("incoming error");
   Dart_Handle result;
 
@@ -5455,7 +5455,7 @@
 
 TEST_CASE(ImportLibraryWithPrefix) {
   const char* kLibrary1Chars =
-      "#library('library1_name');"
+      "library library1_name;"
       "int bar() => 42;";
   Dart_Handle url1 = NewString("library1_url");
   Dart_Handle source1 = NewString(kLibrary1Chars);
@@ -5464,7 +5464,7 @@
   EXPECT(Dart_IsLibrary(lib1));
 
   const char* kLibrary2Chars =
-      "#library('library2_name');"
+      "library library2_name;"
       "int foobar() => foo.bar();";
   Dart_Handle url2 = NewString("library2_url");
   Dart_Handle source2 = NewString(kLibrary2Chars);
@@ -5496,7 +5496,7 @@
 
 TEST_CASE(LoadLibrary) {
   const char* kLibrary1Chars =
-      "#library('library1_name');";
+      "library library1_name;";
   Dart_Handle error = Dart_Error("incoming error");
   Dart_Handle result;
 
@@ -5548,7 +5548,7 @@
 
 TEST_CASE(LoadLibrary_CompileError) {
   const char* kLibrary1Chars =
-      "#library('library1_name');"
+      "library library1_name;"
       ")";
   Dart_Handle url = NewString("library1_url");
   Dart_Handle source = NewString(kLibrary1Chars);
@@ -5560,7 +5560,7 @@
 
 TEST_CASE(LoadSource) {
   const char* kLibrary1Chars =
-      "#library('library1_name');";
+      "library library1_name;";
   const char* kSourceChars =
       "// Something innocuous";
   const char* kBadSourceChars =
@@ -5643,7 +5643,7 @@
 
 TEST_CASE(LoadSource_LateLoad) {
   const char* kLibrary1Chars =
-      "#library('library1_name');\n"
+      "library library1_name;\n"
       "class OldClass {\n"
       "  foo() => 'foo';\n"
       "}\n";
@@ -5688,7 +5688,7 @@
 
 TEST_CASE(LoadPatch) {
   const char* kLibrary1Chars =
-      "#library('library1_name');";
+      "library library1_name;";
   const char* kSourceChars =
       "external int foo();";
   const char* kPatchChars =
@@ -5737,7 +5737,7 @@
 
 TEST_CASE(ParsePatchLibrary) {
   const char* kLibraryChars =
-  "#library('patched_library');\n"
+  "library patched_library;\n"
   "class A {\n"
   "  final fvalue;\n"
   "  var _f;\n"
@@ -5779,7 +5779,7 @@
   "patch(x) => x*3;\n";
 
   const char* kScriptChars =
-  "#import('theLibrary');\n"
+  "import 'theLibrary';\n"
   "e1() => unpatched();\n"
   "m1() => topLevel(2);\n"
   "m2() {\n"
@@ -5982,16 +5982,16 @@
 // in the importing library.
 TEST_CASE(ImportLibrary2) {
   const char* kScriptChars =
-      "#import('library1.dart');\n"
+      "import 'library1_dart';\n"
       "var foo;\n"
       "main() { foo = 0; }\n";
   const char* kLibrary1Chars =
-      "#library('library1.dart');\n"
-      "#import('library2.dart');\n"
+      "library library1_dart;\n"
+      "import 'library2_dart';\n"
       "var foo;\n";
   const char* kLibrary2Chars =
-      "#library('library2.dart');\n"
-      "#import('library1.dart');\n"
+      "library library2_dart;\n"
+      "import 'library1_dart';\n"
       "var foo;\n";
   Dart_Handle result;
   // Create a test library and Load up a test script in it.
@@ -6001,11 +6001,11 @@
   EXPECT_VALID(result);
   result = Dart_LoadScript(url, source);
 
-  url = NewString("library1.dart");
+  url = NewString("library1_dart");
   source = NewString(kLibrary1Chars);
   Dart_LoadLibrary(url, source);
 
-  url = NewString("library2.dart");
+  url = NewString("library2_dart");
   source = NewString(kLibrary2Chars);
   Dart_LoadLibrary(url, source);
 
@@ -6018,15 +6018,15 @@
 // an error if that name is referenced.
 TEST_CASE(ImportLibrary3) {
   const char* kScriptChars =
-      "#import('library2.dart');\n"
-      "#import('library1.dart');\n"
+      "import 'library2_dart';\n"
+      "import 'library1_dart';\n"
       "var foo_top = 10;  // foo has dup def. So should be an error.\n"
       "main() { foo = 0; }\n";
   const char* kLibrary1Chars =
-      "#library('library1.dart');\n"
+      "library library1_dart;\n"
       "var foo;";
   const char* kLibrary2Chars =
-      "#library('library2.dart');\n"
+      "library library2_dart;\n"
       "var foo;";
   Dart_Handle result;
 
@@ -6038,11 +6038,11 @@
   result = Dart_LoadScript(url, source);
   EXPECT_VALID(result);
 
-  url = NewString("library2.dart");
+  url = NewString("library2_dart");
   source = NewString(kLibrary2Chars);
   Dart_LoadLibrary(url, source);
 
-  url = NewString("library1.dart");
+  url = NewString("library1_dart");
   source = NewString(kLibrary1Chars);
   Dart_LoadLibrary(url, source);
 
@@ -6056,14 +6056,14 @@
 // not an error if that name is not used.
 TEST_CASE(ImportLibrary4) {
   const char* kScriptChars =
-      "#import('library2.dart');\n"
-      "#import('library1.dart');\n"
+      "import 'library2_dart';\n"
+      "import 'library1_dart';\n"
       "main() {  }\n";
   const char* kLibrary1Chars =
-      "#library('library1.dart');\n"
+      "library library1_dart;\n"
       "var foo;";
   const char* kLibrary2Chars =
-      "#library('library2.dart');\n"
+      "library library2_dart;\n"
       "var foo;";
   Dart_Handle result;
 
@@ -6075,11 +6075,11 @@
   result = Dart_LoadScript(url, source);
   EXPECT_VALID(result);
 
-  url = NewString("library2.dart");
+  url = NewString("library2_dart");
   source = NewString(kLibrary2Chars);
   Dart_LoadLibrary(url, source);
 
-  url = NewString("library1.dart");
+  url = NewString("library1_dart");
   source = NewString(kLibrary1Chars);
   Dart_LoadLibrary(url, source);
 
@@ -6090,13 +6090,13 @@
 
 TEST_CASE(ImportLibrary5) {
   const char* kScriptChars =
-      "#import('lib.dart');\n"
+      "import 'lib.dart';\n"
       "interface Y {\n"
       "  void set handler(void callback(List<int> x));\n"
       "}\n"
       "void main() {}\n";
   const char* kLibraryChars =
-      "#library('lib.dart');\n"
+      "library lib.dart;\n"
       "interface X {\n"
       "  void set handler(void callback(List<int> x));\n"
       "}\n";
@@ -6161,7 +6161,7 @@
 
   TestIsolateScope __test_isolate__;
   const char* kScriptChars =
-      "#import('dart:isolate');\n"
+      "import 'dart:isolate';\n"
       "void callPort(SendPort port) {\n"
       "    port.call(null).then((message) {\n"
       "      throw new Exception(message);\n"
@@ -6212,8 +6212,8 @@
                                 void* data,
                                 char** error) {
   const char* kScriptChars =
-      "#import('builtin');\n"
-      "#import('dart:isolate');\n"
+      "import 'builtin';\n"
+      "import 'dart:isolate';\n"
       "void entry() {\n"
       "  port.receive((message, replyTo) {\n"
       "    if (message) {\n"
@@ -6770,7 +6770,7 @@
 TEST_CASE(RangeLimits) {
   uint8_t chars8[1] = {'a'};
   uint16_t chars16[1] = {'a'};
-  uint32_t chars32[1] = {'a'};
+  int32_t chars32[1] = {'a'};
 
   EXPECT_ERROR(Dart_NewList(-1),
                "expects argument 'length' to be in the range");
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 64eea31..4cee392 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -17,7 +17,8 @@
                                    ReAlloc alloc)
     : BaseReader(buffer, length),
       alloc_(alloc),
-      backward_references_(kNumInitialReferences) {
+      backward_references_(kNumInitialReferences),
+      vm_symbol_references_(NULL) {
   Init();
 }
 
@@ -215,13 +216,29 @@
 
 Dart_CObject* ApiMessageReader::ReadVMSymbol(intptr_t object_id) {
   if (Symbols::IsVMSymbolId(object_id)) {
+    intptr_t symbol_id = object_id - kMaxPredefinedObjectIds;
+    Dart_CObject* object;
+    if (vm_symbol_references_ != NULL &&
+        (object = vm_symbol_references_[symbol_id]) != NULL) {
+      return object;
+    }
+
+    if (vm_symbol_references_ == NULL) {
+      intptr_t size = sizeof(*vm_symbol_references_) * Symbols::kMaxId;
+      vm_symbol_references_ =
+          reinterpret_cast<Dart_CObject**>(alloc_(NULL, 0, size));
+      memset(vm_symbol_references_, 0, size);
+    }
+
     RawOneByteString* str =
         reinterpret_cast<RawOneByteString*>(Symbols::GetVMSymbol(object_id));
     intptr_t len = Smi::Value(str->ptr()->length_);
-    Dart_CObject* object = AllocateDartCObjectString(len);
+    object = AllocateDartCObjectString(len);
     char* p = object->value.as_string;
     memmove(p, str->ptr()->data_, len);
     p[len] = '\0';
+    ASSERT(vm_symbol_references_[symbol_id] == NULL);
+    vm_symbol_references_[symbol_id] = object;
     return object;
   }
   // No other VM isolate objects are supported.
diff --git a/runtime/vm/dart_api_message.h b/runtime/vm/dart_api_message.h
index c37d8fb..dbd7278 100644
--- a/runtime/vm/dart_api_message.h
+++ b/runtime/vm/dart_api_message.h
@@ -109,6 +109,7 @@
   // function.
   ReAlloc alloc_;
   ApiGrowableArray<BackRefNode*> backward_references_;
+  Dart_CObject** vm_symbol_references_;
 
   Dart_CObject type_arguments_marker;
   Dart_CObject dynamic_type_marker;
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 96019a9..5d5cf71 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -575,8 +575,7 @@
       break;
     }
     case PcDescriptors::kFuncCall: {
-      Function& func = Function::Handle();
-      CodePatcher::GetStaticCallAt(pc_, &func, &saved_bytes_.target_address_);
+      saved_bytes_.target_address_ = CodePatcher::GetStaticCallTargetAt(pc_);
       CodePatcher::PatchStaticCallAt(pc_,
           StubCode::BreakpointStaticEntryPoint());
       break;
@@ -1403,9 +1402,10 @@
       }
     } else if (bpt->breakpoint_kind_ == PcDescriptors::kFuncCall) {
       func_to_instrument = bpt->function();
-      Function& callee = Function::Handle();
-      uword target;
-      CodePatcher::GetStaticCallAt(bpt->pc_, &callee, &target);
+      const Code& code = Code::Handle(func_to_instrument.CurrentCode());
+      const Function& callee =
+          Function::Handle(code.GetStaticCallTargetFunctionAt(bpt->pc_));
+      ASSERT(!callee.IsNull());
       if (IsDebuggable(callee)) {
         func_to_instrument = callee.raw();
       }
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index fc2e2c9..479ad64 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -144,7 +144,7 @@
   Instance& exception = Instance::Handle(incoming_exception.raw());
   if (exception.IsNull()) {
     GrowableArray<const Object*> arguments;
-    exception ^= Exceptions::Create(Exceptions::kNullPointer, arguments);
+    exception ^= Exceptions::Create(Exceptions::kNullThrown, arguments);
   }
   uword handler_pc = 0;
   uword handler_sp = 0;
@@ -427,18 +427,14 @@
       library = Library::CoreLibrary();
       class_name = Symbols::New("InternalError");
       break;
-    case kNullPointer:
+    case kNullThrown:
       library = Library::CoreLibrary();
-      class_name = Symbols::New("NullPointerException");
+      class_name = Symbols::New("NullThrownError");
       break;
     case kIllegalJSRegExp:
       library = Library::CoreLibrary();
       class_name = Symbols::New("IllegalJSRegExpException");
       break;
-    case kArgumentError:
-      library = Library::CoreLibrary();
-      class_name = Symbols::New("ArgumentError");
-      break;
     case kIsolateSpawn:
       library = Library::IsolateLibrary();
       class_name = Symbols::New("IsolateSpawnException");
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 1fe2665..0cc048f 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -56,9 +56,8 @@
     kStackOverflow,
     kOutOfMemory,
     kInternalError,
-    kNullPointer,
+    kNullThrown,
     kIllegalJSRegExp,
-    kArgumentError,
     kIsolateSpawn
   };
 
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 609d1d6..939f393 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -62,6 +62,7 @@
 
 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph)
   : flow_graph_(flow_graph),
+    reaching_defs_(flow_graph),
     mint_values_(NULL),
     block_order_(flow_graph.reverse_postorder()),
     postorder_(flow_graph.postorder()),
@@ -146,9 +147,15 @@
       }
 
       // Handle uses.
+      LocationSummary* locs = current->locs();
+      ASSERT(locs->input_count() == current->InputCount());
       for (intptr_t j = 0; j < current->InputCount(); j++) {
         Value* input = current->InputAt(j);
         const intptr_t use = input->definition()->ssa_temp_index();
+
+        ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant());
+        if (locs->in(j).IsConstant()) continue;
+
         live_in->Add(use);
       }
 
@@ -182,6 +189,8 @@
           // 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)) {
@@ -517,9 +526,12 @@
 void FlowGraphAllocator::BuildLiveRanges() {
   const intptr_t block_count = postorder_.length();
   ASSERT(postorder_.Last()->IsGraphEntry());
+  BitVector* current_interference_set = NULL;
   for (intptr_t i = 0; i < (block_count - 1); i++) {
     BlockEntryInstr* block = postorder_[i];
 
+    BlockInfo* block_info = BlockInfoAt(block->start_pos());
+
     // For every SSA value that is live out of this block, create an interval
     // that covers the whole block.  It will be shortened if we encounter a
     // definition of this value in this block.
@@ -528,23 +540,33 @@
       range->AddUseInterval(block->start_pos(), block->end_pos());
     }
 
+    BlockInfo* loop_header = block_info->loop_header();
+    if ((loop_header != NULL) && (loop_header->last_block() == block)) {
+      current_interference_set =
+          new BitVector(flow_graph_.max_virtual_register_number());
+      ASSERT(loop_header->backedge_interference() == NULL);
+      loop_header->set_backedge_interference(
+          current_interference_set);
+    }
+
     // Connect outgoing phi-moves that were created in NumberInstructions
     // and find last instruction that contributes to liveness.
-    Instruction* current = ConnectOutgoingPhiMoves(block);
+    Instruction* current = ConnectOutgoingPhiMoves(block,
+                                                   current_interference_set);
 
     // Now process all instructions in reverse order.
     while (current != block) {
       // Skip parallel moves that we insert while processing instructions.
       if (!current->IsParallelMove()) {
-        ProcessOneInstruction(block, current);
+        ProcessOneInstruction(block, current, current_interference_set);
       }
       current = current->previous();
     }
 
 
     // Check if any values live into the loop can be spilled for free.
-    BlockInfo* block_info = BlockInfoAt(block->start_pos());
     if (block_info->is_loop_header()) {
+      current_interference_set = NULL;
       for (BitVector::Iterator it(live_in_[i]); !it.Done(); it.Advance()) {
         LiveRange* range = GetLiveRange(it.Current());
         if (HasOnlyUnconstrainedUsesInLoop(range, block_info)) {
@@ -650,7 +672,7 @@
 //
 
 Instruction* FlowGraphAllocator::ConnectOutgoingPhiMoves(
-    BlockEntryInstr* block) {
+    BlockEntryInstr* block, BitVector* interfere_at_backedge) {
   Instruction* last = block->last_instruction();
 
   GotoInstr* goto_instr = last->AsGoto();
@@ -696,7 +718,9 @@
     //      value    --*
     //
 
-    LiveRange* range = GetLiveRange(val->definition()->ssa_temp_index());
+    const intptr_t vreg = val->definition()->ssa_temp_index();
+    LiveRange* range = GetLiveRange(vreg);
+    if (interfere_at_backedge != NULL) interfere_at_backedge->Add(vreg);
 
     range->AddUseInterval(block->start_pos(), pos);
     range->AddHintedUse(pos, move->src_slot(), move->dest_slot());
@@ -821,7 +845,8 @@
 // Create and update live ranges corresponding to instruction's inputs,
 // temporaries and output.
 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
-                                               Instruction* current) {
+                                               Instruction* current,
+                                               BitVector* interference_set) {
   LocationSummary* locs = current->locs();
 
   Definition* def = current->AsDefinition();
@@ -1065,6 +1090,12 @@
     range->AddHintedUse(pos, out, move->src_slot());
     range->AddUse(pos, move->dest_slot());
     range->AddUse(pos, locs->in_slot(0));
+
+    if ((interference_set != NULL) &&
+        (range->vreg() >= 0) &&
+        interference_set->Contains(range->vreg())) {
+      interference_set->Add(input->ssa_temp_index());
+    }
   } else {
     // Normal unallocated location that requires a register. Expected shape of
     // live range:
@@ -1451,7 +1482,7 @@
 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range,
                                             intptr_t from,
                                             intptr_t to) {
-  TRACE_ALLOC(OS::Print("split %"Pd" [%"Pd", %"Pd") between [%"Pd", %"Pd")\n",
+  TRACE_ALLOC(OS::Print("split v%"Pd" [%"Pd", %"Pd") between [%"Pd", %"Pd")\n",
                         range->vreg(), range->Start(), range->End(), from, to));
 
   intptr_t split_pos = kIllegalPosition;
@@ -1489,7 +1520,7 @@
                                       intptr_t from,
                                       intptr_t to) {
   ASSERT(from < to);
-  TRACE_ALLOC(OS::Print("spill %"Pd" [%"Pd", %"Pd") "
+  TRACE_ALLOC(OS::Print("spill v%"Pd" [%"Pd", %"Pd") "
                         "between [%"Pd", %"Pd")\n",
                         range->vreg(), range->Start(), range->End(), from, to));
   LiveRange* tail = range->SplitAt(from);
@@ -1507,7 +1538,7 @@
 
 
 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) {
-  TRACE_ALLOC(OS::Print("spill %"Pd" [%"Pd", %"Pd") after %"Pd"\n",
+  TRACE_ALLOC(OS::Print("spill v%"Pd" [%"Pd", %"Pd") after %"Pd"\n",
                         range->vreg(), range->Start(), range->End(), from));
 
   // When spilling the value inside the loop check if this spill can
@@ -1614,6 +1645,72 @@
 }
 
 
+void ReachingDefs::AddPhi(PhiInstr* phi) {
+  if (phi->reaching_defs() == NULL) {
+    phi->set_reaching_defs(
+        new BitVector(flow_graph_.max_virtual_register_number()));
+
+    // Compute initial set reaching defs set.
+    bool depends_on_phi = false;
+    for (intptr_t i = 0; i < phi->InputCount(); i++) {
+      Definition* input = phi->InputAt(i)->definition();
+      if (input->IsPhi()) {
+        depends_on_phi = true;
+      }
+      phi->reaching_defs()->Add(input->ssa_temp_index());
+    }
+
+    // If this phi depends on another phi then we need fix point iteration.
+    if (depends_on_phi) phis_.Add(phi);
+  }
+}
+
+
+void ReachingDefs::Compute() {
+  // Transitively collect all phis that are used by the given phi.
+  for (intptr_t i = 0; i < phis_.length(); i++) {
+    PhiInstr* phi = phis_[i];
+
+    // Add all phis that affect this phi to the list.
+    for (intptr_t i = 0; i < phi->InputCount(); i++) {
+      PhiInstr* input_phi = phi->InputAt(i)->definition()->AsPhi();
+      if (input_phi != NULL) {
+        AddPhi(input_phi);
+      }
+    }
+  }
+
+  // Propagate values until fix point is reached.
+  bool changed;
+  do {
+    changed = false;
+    for (intptr_t i = 0; i < phis_.length(); i++) {
+      PhiInstr* phi = phis_[i];
+      for (intptr_t i = 0; i < phi->InputCount(); i++) {
+        PhiInstr* input_phi = phi->InputAt(i)->definition()->AsPhi();
+        if (input_phi != NULL) {
+          if (phi->reaching_defs()->AddAll(input_phi->reaching_defs())) {
+            changed = true;
+          }
+        }
+      }
+    }
+  } while (changed);
+
+  phis_.Clear();
+}
+
+
+BitVector* ReachingDefs::Get(PhiInstr* phi) {
+  if (phi->reaching_defs() == NULL) {
+    ASSERT(phis_.is_empty());
+    AddPhi(phi);
+    Compute();
+  }
+  return phi->reaching_defs();
+}
+
+
 bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
   intptr_t candidate = kNoRegister;
   intptr_t free_until = 0;
@@ -1628,10 +1725,10 @@
       candidate = hint.register_code();
     }
 
-    TRACE_ALLOC(OS::Print("found hint "));
-    TRACE_ALLOC(hint.Print());
-    TRACE_ALLOC(OS::Print(" for %"Pd": free until %"Pd"\n",
-                          unallocated->vreg(), free_until));
+    TRACE_ALLOC(OS::Print("found hint %s for v%"Pd": free until %"Pd"\n",
+                          hint.Name(),
+                          unallocated->vreg(),
+                          free_until));
   } else if (free_until != kMaxPosition) {
     for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
       if (!blocked_registers_[reg] && (registers_[reg].length() == 0)) {
@@ -1642,6 +1739,66 @@
     }
   }
 
+  // We have a very good candidate (either hinted to us or completely free).
+  // If we are in a loop try to reduce number of moves on the back edge by
+  // searching for a candidate that does not interfere with phis on the back
+  // edge.
+  BlockInfo* loop_header = BlockInfoAt(unallocated->Start())->loop_header();
+  if ((unallocated->vreg() >= 0) &&
+      (loop_header != NULL) &&
+      (free_until >= loop_header->last_block()->end_pos()) &&
+      loop_header->backedge_interference()->Contains(unallocated->vreg())) {
+    ASSERT(static_cast<intptr_t>(kNumberOfXmmRegisters) <=
+           kNumberOfCpuRegisters);
+    bool used_on_backedge[kNumberOfCpuRegisters] = { false };
+
+    for (PhiIterator it(loop_header->entry()->AsJoinEntry());
+         !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();
+
+          if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
+            used_on_backedge[reg] = true;
+          }
+        }
+      }
+    }
+
+    if (used_on_backedge[candidate]) {
+      TRACE_ALLOC(OS::Print(
+          "considering %s for v%"Pd": has interference on the back edge"
+          " {loop [%"Pd", %"Pd")}\n",
+          MakeRegisterLocation(candidate, Location::kDouble).Name(),
+          unallocated->vreg(),
+          loop_header->entry()->start_pos(),
+          loop_header->last_block()->end_pos()));
+      for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
+        if (blocked_registers_[reg] ||
+            (reg == candidate) ||
+            used_on_backedge[reg]) {
+          continue;
+        }
+
+        const intptr_t intersection =
+            FirstIntersectionWithAllocated(reg, unallocated);
+        if (intersection >= free_until) {
+          candidate = reg;
+          free_until = intersection;
+          TRACE_ALLOC(OS::Print(
+              "found %s for v%"Pd" with no interference on the back edge\n",
+              MakeRegisterLocation(candidate, Location::kDouble).Name(),
+              candidate));
+          break;
+        }
+      }
+    }
+  }
+
   ASSERT(0 <= kMaxPosition);
   if (free_until != kMaxPosition) {
     for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
@@ -1661,7 +1818,7 @@
 
   TRACE_ALLOC(OS::Print("assigning free register "));
   TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
-  TRACE_ALLOC(OS::Print(" to %"Pd"\n", unallocated->vreg()));
+  TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg()));
 
   if (free_until != kMaxPosition) {
     // There was an intersection. Split unallocated.
@@ -1764,7 +1921,7 @@
 
   TRACE_ALLOC(OS::Print("assigning blocked register "));
   TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
-  TRACE_ALLOC(OS::Print(" to live range %"Pd" until %"Pd"\n",
+  TRACE_ALLOC(OS::Print(" to live range v%"Pd" until %"Pd"\n",
                         unallocated->vreg(), blocked_at));
 
   if (blocked_at < unallocated->End()) {
@@ -2070,6 +2227,7 @@
   const GrowableArray<LiveRange*>& unallocated,
   LiveRange** blocking_ranges,
   bool* blocked_registers) {
+  ASSERT(number_of_registers <= kNumberOfCpuRegisters);
   register_kind_ = register_kind;
   number_of_registers_ = number_of_registers;
 
@@ -2097,7 +2255,7 @@
   while (!unallocated_.is_empty()) {
     LiveRange* range = unallocated_.RemoveLast();
     const intptr_t start = range->Start();
-    TRACE_ALLOC(OS::Print("Processing live range for vreg %"Pd" "
+    TRACE_ALLOC(OS::Print("Processing live range for v%"Pd" "
                           "starting at %"Pd"\n",
                           range->vreg(),
                           start));
@@ -2134,12 +2292,13 @@
 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent,
                                               BlockEntryInstr* source_block,
                                               BlockEntryInstr* target_block) {
-  TRACE_ALLOC(OS::Print("Connect source_block=%"Pd", target_block=%"Pd"\n",
+  TRACE_ALLOC(OS::Print("Connect v%"Pd" on the edge B%"Pd" -> B%"Pd"\n",
+                        parent->vreg(),
                         source_block->block_id(),
                         target_block->block_id()));
   if (parent->next_sibling() == NULL) {
     // Nothing to connect. The whole range was allocated to the same location.
-    TRACE_ALLOC(OS::Print("range %"Pd" has no siblings\n", parent->vreg()));
+    TRACE_ALLOC(OS::Print("range v%"Pd" has no siblings\n", parent->vreg()));
     return;
   }
 
@@ -2176,13 +2335,15 @@
     range = range->next_sibling();
   }
 
-  TRACE_ALLOC(OS::Print("connecting [%"Pd", %"Pd") [",
-                        source_cover->Start(), source_cover->End()));
-  TRACE_ALLOC(source.Print());
-  TRACE_ALLOC(OS::Print("] to [%"Pd", %"Pd") [",
-                        target_cover->Start(), target_cover->End()));
-  TRACE_ALLOC(target.Print());
-  TRACE_ALLOC(OS::Print("]\n"));
+  TRACE_ALLOC(OS::Print("connecting v%"Pd" between [%"Pd", %"Pd") {%s} "
+                        "to [%"Pd", %"Pd") {%s}\n",
+                        parent->vreg(),
+                        source_cover->Start(),
+                        source_cover->End(),
+                        source.Name(),
+                        target_cover->Start(),
+                        target_cover->End(),
+                        target.Name()));
 
   // Siblings were allocated to the same register.
   if (source.Equals(target)) return;
diff --git a/runtime/vm/flow_graph_allocator.h b/runtime/vm/flow_graph_allocator.h
index b98fbb3..d88e6e1 100644
--- a/runtime/vm/flow_graph_allocator.h
+++ b/runtime/vm/flow_graph_allocator.h
@@ -17,6 +17,24 @@
 class UseInterval;
 class UsePosition;
 
+
+class ReachingDefs : public ValueObject {
+ public:
+  explicit ReachingDefs(const FlowGraph& flow_graph)
+      : flow_graph_(flow_graph),
+        phis_(10) { }
+
+  BitVector* Get(PhiInstr* phi);
+
+ private:
+  void AddPhi(PhiInstr* phi);
+  void Compute();
+
+  const FlowGraph& flow_graph_;
+  GrowableArray<PhiInstr*> phis_;
+};
+
+
 class FlowGraphAllocator : public ValueObject {
  public:
   // Number of stack slots needed for a double spill slot.
@@ -94,9 +112,12 @@
   // Visit instructions in the postorder and build live ranges for
   // all SSA values.
   void BuildLiveRanges();
-  Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block);
+  Instruction* ConnectOutgoingPhiMoves(BlockEntryInstr* block,
+                                       BitVector* interference_set);
   void ProcessEnvironmentUses(BlockEntryInstr* block, Instruction* current);
-  void ProcessOneInstruction(BlockEntryInstr* block, Instruction* instr);
+  void ProcessOneInstruction(BlockEntryInstr* block,
+                             Instruction* instr,
+                             BitVector* interference_set);
   void ConnectIncomingPhiMoves(BlockEntryInstr* block);
   void BlockLocation(Location loc, intptr_t from, intptr_t to);
   void BlockRegisterLocation(Location loc,
@@ -214,6 +235,8 @@
 
   const FlowGraph& flow_graph_;
 
+  ReachingDefs reaching_defs_;
+
   // Set of SSA values that have unboxed mint representation. Indexed
   // by SSA temp index.
   BitVector* mint_values_;
@@ -299,7 +322,10 @@
 class BlockInfo : public ZoneAllocated {
  public:
   explicit BlockInfo(BlockEntryInstr* entry)
-    : entry_(entry), loop_(NULL), is_loop_header_(false) {
+    : entry_(entry),
+      loop_(NULL),
+      is_loop_header_(false),
+      backedge_interference_(NULL) {
   }
 
   BlockEntryInstr* entry() const { return entry_; }
@@ -307,6 +333,17 @@
   // Returns true is this node is a header of a structural loop.
   bool is_loop_header() const { return is_loop_header_; }
 
+  // Returns header of the innermost loop containing this block.
+  BlockInfo* loop_header() {
+    if (is_loop_header()) {
+      return this;
+    } else if (loop() != NULL) {
+      return loop();
+    } else {
+      return NULL;
+    }
+  }
+
   // Innermost reducible loop containing this node. Loop headers point to
   // outer loop not to themselves.
   BlockInfo* loop() const { return loop_; }
@@ -326,6 +363,14 @@
   intptr_t loop_id() const { return loop_id_; }
   void set_loop_id(intptr_t loop_id) { loop_id_ = loop_id; }
 
+  BitVector* backedge_interference() const {
+    return backedge_interference_;
+  }
+
+  void set_backedge_interference(BitVector* backedge_interference) {
+    backedge_interference_ = backedge_interference;
+  }
+
  private:
   BlockEntryInstr* entry_;
   BlockInfo* loop_;
@@ -334,6 +379,8 @@
   BlockEntryInstr* last_block_;
   intptr_t loop_id_;
 
+  BitVector* backedge_interference_;
+
   DISALLOW_COPY_AND_ASSIGN(BlockInfo);
 };
 
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 96d4cb8..c9d67eb 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1763,7 +1763,7 @@
   }
 
   if (node->constructor().IsFactory()) {
-    if ((function_class.Name() == Symbols::ListImplementation()) &&
+    if ((function_class.Name() == Symbols::List()) &&
         (function.name() == Symbols::ListFactory())) {
       // If there are no arguments then the result is guaranteed to be a
       // GrowableObjectArray. However if there is an argument the result
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 879799f..02d94fc 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -144,6 +144,8 @@
           is_optimizing ? new StackmapTableBuilder() : NULL),
       block_info_(block_order_.length()),
       deopt_infos_(),
+      static_calls_target_table_(GrowableObjectArray::ZoneHandle(
+          GrowableObjectArray::New())),
       is_optimizing_(is_optimizing),
       may_reoptimize_(false),
       bool_true_(Bool::ZoneHandle(Bool::True())),
@@ -282,6 +284,18 @@
 }
 
 
+void FlowGraphCompiler::AddStaticCallTarget(const Function& func) {
+  ASSERT(Code::kSCallTableEntryLength == 3);
+  ASSERT(Code::kSCallTableOffsetEntry == 0);
+  static_calls_target_table_.Add(
+      Smi::Handle(Smi::New(assembler()->CodeSize())));
+  ASSERT(Code::kSCallTableFunctionEntry == 1);
+  static_calls_target_table_.Add(func);
+  ASSERT(Code::kSCallTableCodeEntry == 2);
+  static_calls_target_table_.Add(Code::Handle());
+}
+
+
 void FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id,
                                             intptr_t token_pos) {
   ASSERT(is_optimizing());
@@ -396,6 +410,7 @@
   code.set_deopt_info_array(array);
   const Array& object_array =
       Array::Handle(Array::MakeArray(builder.object_table()));
+  ASSERT(code.object_table() == Array::null());
   code.set_object_table(object_array);
 }
 
@@ -426,6 +441,13 @@
 }
 
 
+void FlowGraphCompiler::FinalizeStaticCallTargetsTable(const Code& code) {
+  ASSERT(code.static_calls_target_table() == Array::null());
+  code.set_static_calls_target_table(
+      Array::Handle(Array::MakeArray(static_calls_target_table_)));
+}
+
+
 // Returns 'true' if code generation for this function is complete, i.e.,
 // no fall-through to regular code is needed.
 bool FlowGraphCompiler::TryIntrinsify() {
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 3a78f8c..f0236df 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -158,7 +158,7 @@
       __ cmpl(kClassIdReg, Immediate(type_class.id()));
       __ j(EQUAL, is_instance_lbl);
     }
-    if (type_class.raw() == Isolate::Current()->object_store()->list_class()) {
+    if (type_class.IsListClass()) {
       GenerateListTypeCheck(kClassIdReg, is_instance_lbl);
     }
     return GenerateSubtype1TestCacheLookup(
@@ -1092,7 +1092,6 @@
                                        intptr_t deopt_id,
                                        intptr_t token_pos,
                                        LocationSummary* locs) {
-  __ LoadObject(ECX, function);
   __ LoadObject(EDX, 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.
@@ -1101,6 +1100,7 @@
                    &StubCode::CallStaticFunctionLabel(),
                    PcDescriptors::kFuncCall,
                    locs);
+  AddStaticCallTarget(function);
   __ Drop(argument_count);
 }
 
diff --git a/runtime/vm/flow_graph_compiler_ia32.h b/runtime/vm/flow_graph_compiler_ia32.h
index f949317..201b964 100644
--- a/runtime/vm/flow_graph_compiler_ia32.h
+++ b/runtime/vm/flow_graph_compiler_ia32.h
@@ -192,6 +192,7 @@
   void FinalizeStackmaps(const Code& code);
   void FinalizeVarDescriptors(const Code& code);
   void FinalizeComments(const Code& code);
+  void FinalizeStaticCallTargetsTable(const Code& code);
 
   const Bool& bool_true() const { return bool_true_; }
   const Bool& bool_false() const { return bool_false_; }
@@ -227,6 +228,8 @@
                                                 Register index);
 
  private:
+  void AddStaticCallTarget(const Function& function);
+
   void GenerateDeferredCode();
 
   void EmitInstructionPrologue(Instruction* instr);
@@ -320,6 +323,8 @@
   GrowableArray<BlockInfo*> block_info_;
   GrowableArray<CompilerDeoptInfo*> deopt_infos_;
   GrowableArray<SlowPathCode*> slow_path_code_;
+  // Stores: [code offset, function, null(code)].
+  const GrowableObjectArray& static_calls_target_table_;
   const bool is_optimizing_;
   // Set to true if optimized code has IC calls.
   bool may_reoptimize_;
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index eee2c68..a407051 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -158,7 +158,7 @@
       __ cmpl(kClassIdReg, Immediate(type_class.id()));
       __ j(EQUAL, is_instance_lbl);
     }
-    if (type_class.raw() == Isolate::Current()->object_store()->list_class()) {
+    if (type_class.IsListClass()) {
       GenerateListTypeCheck(kClassIdReg, is_instance_lbl);
     }
     return GenerateSubtype1TestCacheLookup(
@@ -1096,7 +1096,6 @@
                                        intptr_t deopt_id,
                                        intptr_t token_pos,
                                        LocationSummary* locs) {
-  __ LoadObject(RBX, function);
   __ LoadObject(R10, 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.
@@ -1105,6 +1104,7 @@
                    &StubCode::CallStaticFunctionLabel(),
                    PcDescriptors::kFuncCall,
                    locs);
+  AddStaticCallTarget(function);
   __ Drop(argument_count);
 }
 
diff --git a/runtime/vm/flow_graph_compiler_x64.h b/runtime/vm/flow_graph_compiler_x64.h
index 146d9eb..3f74bc8 100644
--- a/runtime/vm/flow_graph_compiler_x64.h
+++ b/runtime/vm/flow_graph_compiler_x64.h
@@ -192,6 +192,7 @@
   void FinalizeStackmaps(const Code& code);
   void FinalizeVarDescriptors(const Code& code);
   void FinalizeComments(const Code& code);
+  void FinalizeStaticCallTargetsTable(const Code& code);
 
   const Bool& bool_true() const { return bool_true_; }
   const Bool& bool_false() const { return bool_false_; }
@@ -227,6 +228,8 @@
                                                 Register index);
 
  private:
+  void AddStaticCallTarget(const Function& function);
+
   void GenerateDeferredCode();
 
   void EmitInstructionPrologue(Instruction* instr);
@@ -320,6 +323,8 @@
   GrowableArray<BlockInfo*> block_info_;
   GrowableArray<CompilerDeoptInfo*> deopt_infos_;
   GrowableArray<SlowPathCode*> slow_path_code_;
+  // Stores: [code offset, function, null(code)].
+  const GrowableObjectArray& static_calls_target_table_;
   const bool is_optimizing_;
   // Set to true if optimized code has IC calls.
   bool may_reoptimize_;
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 6172ca5..2321f54 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -1107,6 +1107,43 @@
 }
 
 
+StringCharCodeAtInstr* FlowGraphOptimizer::BuildStringCharCodeAt(
+    InstanceCallInstr* call,
+    intptr_t cid) {
+  Value* str = call->ArgumentAt(0)->value();
+  Value* index = call->ArgumentAt(1)->value();
+  AddCheckClass(call, str->Copy());
+  InsertBefore(call,
+               new CheckSmiInstr(index->Copy(), call->deopt_id()),
+               call->env(),
+               Definition::kEffect);
+  // If both index and string are constants, then do a compile-time check.
+  // TODO(srdjan): Remove once constant propagation handles bounds checks.
+  bool skip_check = false;
+  if (str->BindsToConstant() && index->BindsToConstant()) {
+    ConstantInstr* string_def = str->definition()->AsConstant();
+    const String& constant_string =
+        String::Cast(string_def->value());
+    ConstantInstr* index_def = index->definition()->AsConstant();
+    if (index_def->value().IsSmi()) {
+      intptr_t constant_index = Smi::Cast(index_def->value()).Value();
+      skip_check = (constant_index < constant_string.Length());
+    }
+  }
+  if (!skip_check) {
+    // Insert bounds check.
+    InsertBefore(call,
+                 new CheckArrayBoundInstr(str->Copy(),
+                                          index->Copy(),
+                                          cid,
+                                          call),
+                 call->env(),
+                 Definition::kEffect);
+  }
+  return new StringCharCodeAtInstr(str, index, cid);
+}
+
+
 // Inline only simple, frequently called core library methods.
 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
   ASSERT(call->HasICData());
@@ -1124,42 +1161,24 @@
       (ic_data.NumberOfChecks() == 1) &&
       ((class_ids[0] == kOneByteStringCid) ||
        (class_ids[0] == kTwoByteStringCid))) {
-    Value* str= call->ArgumentAt(0)->value();
-    Value* index = call->ArgumentAt(1)->value();
-    AddCheckClass(call, str->Copy());
-    InsertBefore(call,
-                 new CheckSmiInstr(index->Copy(), call->deopt_id()),
-                 call->env(),
-                 Definition::kEffect);
-    // If both index and string are constants, then do a compile-time check.
-    // TODO(srdjan): Remove once constant propagation handles bounds checks.
-    bool skip_check = false;
-    if (str->BindsToConstant() && index->BindsToConstant()) {
-      ConstantInstr* string_def = str->definition()->AsConstant();
-      const String& constant_string =
-          String::Cast(string_def->value());
-      ConstantInstr* index_def = index->definition()->AsConstant();
-      if (index_def->value().IsSmi()) {
-        intptr_t constant_index = Smi::Cast(index_def->value()).Value();
-        skip_check = (constant_index < constant_string.Length());
-      }
-    }
-    if (!skip_check) {
-      // Insert bounds check.
-      InsertBefore(call,
-                   new CheckArrayBoundInstr(str->Copy(),
-                                            index->Copy(),
-                                            class_ids[0],
-                                            call),
-                   call->env(),
-                   Definition::kEffect);
-    }
-    StringCharCodeAtInstr* instr =
-        new StringCharCodeAtInstr(str, index, class_ids[0]);
+    StringCharCodeAtInstr* instr = BuildStringCharCodeAt(call, class_ids[0]);
     call->ReplaceWith(instr, current_iterator());
     RemovePushArguments(call);
     return true;
   }
+  if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) &&
+      (ic_data.NumberOfChecks() == 1) &&
+      (class_ids[0] == kOneByteStringCid)) {
+    // TODO(fschneider): Handle TwoByteString.
+    StringCharCodeAtInstr* load_char_code =
+        BuildStringCharCodeAt(call, class_ids[0]);
+    InsertBefore(call, load_char_code, NULL, Definition::kValue);
+    StringFromCharCodeInstr* char_at =
+        new StringFromCharCodeInstr(new Value(load_char_code));
+    call->ReplaceWith(char_at, current_iterator());
+    RemovePushArguments(call);
+    return true;
+  }
 
   if ((recognized_kind == MethodRecognizer::kIntegerToDouble) &&
       (class_ids[0] == kSmiCid)) {
@@ -3302,6 +3321,12 @@
 }
 
 
+void ConstantPropagator::VisitStringFromCharCode(
+    StringFromCharCodeInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
+
 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) {
   SetValue(instr, non_constant_);
 }
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 047dd0c..3c81b4a 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -68,6 +68,9 @@
 
   bool TryInlineInstanceMethod(InstanceCallInstr* call);
 
+  StringCharCodeAtInstr* BuildStringCharCodeAt(InstanceCallInstr* call,
+                                               intptr_t cid);
+
   void AddCheckClass(InstanceCallInstr* call, Value* value);
 
   void InsertAfter(Instruction* prev,
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 21d220d..70a1ee8 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -241,9 +241,10 @@
   const String& function_name = String::Handle(function.name());
   const String& class_name = String::Handle(function_class.Name());
 
-#define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name)     \
+#define RECOGNIZE_FUNCTION(test_class_name, test_function_name, enum_name, fp) \
   if (CompareNames(lib, #test_function_name, function_name) &&                 \
       CompareNames(lib, #test_class_name, class_name)) {                       \
+    ASSERT(function.CheckSourceFingerprint(fp));                               \
     return k##enum_name;                                                       \
   }
 RECOGNIZED_LIST(RECOGNIZE_FUNCTION)
@@ -253,7 +254,7 @@
 
 
 const char* MethodRecognizer::KindToCString(Kind kind) {
-#define KIND_TO_STRING(class_name, function_name, enum_name)                   \
+#define KIND_TO_STRING(class_name, function_name, enum_name, fp)               \
   if (kind == k##enum_name) return #enum_name;
 RECOGNIZED_LIST(KIND_TO_STRING)
 #undef KIND_TO_STRING
@@ -1128,6 +1129,16 @@
 }
 
 
+RawAbstractType* StringFromCharCodeInstr::CompileType() const {
+  return Type::StringType();
+}
+
+
+intptr_t StringFromCharCodeInstr::ResultCid() const {
+  return kDynamicCid;
+}
+
+
 RawAbstractType* LoadIndexedInstr::CompileType() const {
   switch (class_id_) {
     case kArrayCid:
@@ -2657,6 +2668,7 @@
   }
 }
 
+
 #undef __
 
 }  // namespace dart
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 23af66f..59ba34e 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -29,18 +29,21 @@
 
 
 // TODO(srdjan): Add _ByteArrayBase, get:length.
-
+// TODO(srdjan): Unify with INTRINSIC_LIST.
+// (class-name, function-name, recognized enum, fingerprint).
+// See intrinsifier for fingerprint computation.
 #define RECOGNIZED_LIST(V)                                                     \
-  V(_ObjectArray, get:length, ObjectArrayLength)                               \
-  V(_ImmutableArray, get:length, ImmutableArrayLength)                         \
-  V(_GrowableObjectArray, get:length, GrowableArrayLength)                     \
-  V(_GrowableObjectArray, get:capacity, GrowableArrayCapacity)                 \
-  V(_StringBase, get:length, StringBaseLength)                                 \
-  V(_StringBase, get:isEmpty, StringBaseIsEmpty)                               \
-  V(_StringBase, charCodeAt, StringBaseCharCodeAt)                             \
-  V(_IntegerImplementation, toDouble, IntegerToDouble)                         \
-  V(_Double, toInt, DoubleToInteger)                                           \
-  V(::, sqrt, MathSqrt)                                                        \
+  V(_ObjectArray, get:length, ObjectArrayLength, 405297088)                    \
+  V(_ImmutableArray, get:length, ImmutableArrayLength, 433698233)              \
+  V(_GrowableObjectArray, get:length, GrowableArrayLength, 725548050)          \
+  V(_GrowableObjectArray, get:capacity, GrowableArrayCapacity, 725548050)      \
+  V(_StringBase, get:length, StringBaseLength, 320803993)                      \
+  V(_StringBase, get:isEmpty, StringBaseIsEmpty, 1065961093)                   \
+  V(_StringBase, charCodeAt, StringBaseCharCodeAt, 984449525)                  \
+  V(_StringBase, [], StringBaseCharAt, 1062366987)                             \
+  V(_IntegerImplementation, toDouble, IntegerToDouble, 1396338041)             \
+  V(_Double, toInt, DoubleToInteger, 362666636)                                \
+  V(::, sqrt, MathSqrt, 2232519)                                               \
 
 // Class that recognizes the name and owner of a function and returns the
 // corresponding enum. See RECOGNIZED_LIST above for list of recognizable
@@ -49,7 +52,7 @@
  public:
   enum Kind {
     kUnknown,
-#define DEFINE_ENUM_LIST(class_name, function_name, enum_name) k##enum_name,
+#define DEFINE_ENUM_LIST(class_name, function_name, enum_name, fp) k##enum_name,
 RECOGNIZED_LIST(DEFINE_ENUM_LIST)
 #undef DEFINE_ENUM_LIST
   };
@@ -264,7 +267,8 @@
   M(UnaryMintOp)                                                               \
   M(CheckArrayBound)                                                           \
   M(Constraint)                                                                \
-  M(StringCharCodeAt)
+  M(StringCharCodeAt)                                                          \
+  M(StringFromCharCode)
 
 
 #define FORWARD_DECLARATION(type) class type##Instr;
@@ -1162,7 +1166,8 @@
     : block_(block),
       inputs_(num_inputs),
       is_alive_(false),
-      representation_(kTagged) {
+      representation_(kTagged),
+      reaching_defs_(NULL) {
     for (intptr_t i = 0; i < num_inputs; ++i) {
       inputs_.Add(NULL);
     }
@@ -1223,6 +1228,14 @@
 
   virtual void InferRange();
 
+  BitVector* reaching_defs() const {
+    return reaching_defs_;
+  }
+
+  void set_reaching_defs(BitVector* reaching_defs) {
+    reaching_defs_ = reaching_defs;
+  }
+
  private:
   friend class ConstantPropagator;  // Direct access to inputs_.
 
@@ -1231,6 +1244,8 @@
   bool is_alive_;
   Representation representation_;
 
+  BitVector* reaching_defs_;
+
   DISALLOW_COPY_AND_ASSIGN(PhiInstr);
 };
 
@@ -2682,6 +2697,36 @@
 };
 
 
+class StringFromCharCodeInstr : public TemplateDefinition<1> {
+ public:
+  explicit StringFromCharCodeInstr(Value* char_code) {
+    ASSERT(char_code != NULL);
+    ASSERT(char_code->definition()->IsStringCharCodeAt() &&
+           (char_code->definition()->AsStringCharCodeAt()->class_id() ==
+            kOneByteStringCid));
+    inputs_[0] = char_code;
+  }
+
+  DECLARE_INSTRUCTION(StringFromCharCode)
+  virtual RawAbstractType* CompileType() const;
+
+  Value* char_code() const { return inputs_[0]; }
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual bool HasSideEffect() const { return false; }
+
+  virtual intptr_t ResultCid() const;
+
+  virtual bool AttributesEqual(Instruction* other) const { return true; }
+
+  virtual bool AffectedBySideEffect() const { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StringFromCharCodeInstr);
+};
+
+
 class LoadIndexedInstr : public TemplateDefinition<2> {
  public:
   LoadIndexedInstr(Value* array, Value* index, intptr_t class_id)
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 74b2a17..fd2c971 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -1124,6 +1124,30 @@
 }
 
 
+LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  // TODO(fschneider): Allow immediate operands for the char code.
+  locs->set_in(0, Location::RequiresRegister());
+  locs->set_out(Location::RequiresRegister());
+  return locs;
+}
+
+
+void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register char_code = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  __ movl(result,
+          Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())));
+  __ movl(result, Address(result,
+                          char_code,
+                          TIMES_HALF_WORD_SIZE,  // Char code is a smi.
+                          Symbols::kNullCharId * kWordSize));
+}
+
+
 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 32766ac1..6933867 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -992,6 +992,30 @@
 }
 
 
+LocationSummary* StringFromCharCodeInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  // TODO(fschneider): Allow immediate operands for the char code.
+  locs->set_in(0, Location::RequiresRegister());
+  locs->set_out(Location::RequiresRegister());
+  return locs;
+}
+
+
+void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register char_code = locs()->in(0).reg();
+  Register result = locs()->out().reg();
+  __ movq(result,
+          Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())));
+  __ movq(result, Address(result,
+                          char_code,
+                          TIMES_HALF_WORD_SIZE,  // Char code is a smi.
+                          Symbols::kNullCharId * kWordSize));
+}
+
+
 LocationSummary* LoadIndexedInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 59adb5c..9e4188b 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -64,6 +64,8 @@
 bool Intrinsifier::CanIntrinsify(const Function& function) {
   if (!FLAG_intrinsify) return false;
   if (function.IsClosureFunction()) return false;
+  // Can occur because of compile-all flag.
+  if (function.is_external()) return false;
   // Intrinsic kind is set lazily below.
   if (function.intrinsic_kind() == Function::kIsIntrinsic) return true;
   if (function.intrinsic_kind() == Function::kIsNotIntrinsic) return false;
@@ -77,7 +79,7 @@
     return false;
   }
   const char* class_name = String::Handle(function_class.Name()).ToCString();
-#define FIND_INTRINSICS(test_class_name, test_function_name, destination)      \
+#define FIND_INTRINSICS(test_class_name, test_function_name, destination, fp)  \
   if (TestFunction(function,                                                   \
                    class_name, function_name,                                  \
                    #test_class_name, #test_function_name)) {                   \
@@ -91,15 +93,17 @@
   return false;
 }
 
+
 bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) {
   if (!CanIntrinsify(function)) return false;
   const char* function_name = String::Handle(function.name()).ToCString();
   const Class& function_class = Class::Handle(function.Owner());
   const char* class_name = String::Handle(function_class.Name()).ToCString();
-#define FIND_INTRINSICS(test_class_name, test_function_name, destination)      \
+#define FIND_INTRINSICS(test_class_name, test_function_name, destination, fp)  \
   if (TestFunction(function,                                                   \
                    class_name, function_name,                                  \
                    #test_class_name, #test_function_name)) {                   \
+    ASSERT(function.CheckSourceFingerprint(fp));                               \
     return destination(assembler);                                             \
   }                                                                            \
 
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index d127750..af4f8d4 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -10,88 +10,97 @@
 
 namespace dart {
 
-// List of intrinsics: (class-name, function-name, intrinsification method).
+// List of intrinsics:
+// (class-name, function-name, intrinsification method, fingerprint).
+//
+// When adding a new function for intrinsification add a 0 as fingerprint,
+// build and run to get the correct fingerprint from the mismatch error.
 #define INTRINSIC_LIST(V)                                                      \
-  V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger)           \
-  V(_IntegerImplementation, +, Integer_add)                                    \
-  V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger)           \
-  V(_IntegerImplementation, -, Integer_sub)                                    \
-  V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger)           \
-  V(_IntegerImplementation, *, Integer_mul)                                    \
-  V(_IntegerImplementation, %, Integer_modulo)                                 \
-  V(_IntegerImplementation, ~/, Integer_truncDivide)                           \
-  V(_IntegerImplementation, unary-, Integer_negate)                            \
-  V(_IntegerImplementation, _bitAndFromInteger, Integer_bitAndFromInteger)     \
-  V(_IntegerImplementation, &, Integer_bitAnd)                                 \
-  V(_IntegerImplementation, _bitOrFromInteger, Integer_bitOrFromInteger)       \
-  V(_IntegerImplementation, |, Integer_bitOr)                                  \
-  V(_IntegerImplementation, _bitXorFromInteger, Integer_bitXorFromInteger)     \
-  V(_IntegerImplementation, ^, Integer_bitXor)                                 \
+  V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger, 726019207)\
+  V(_IntegerImplementation, +, Integer_add, 13708438)                          \
+  V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger, 726019207)\
+  V(_IntegerImplementation, -, Integer_sub, 284482664)                         \
+  V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger, 726019207)\
+  V(_IntegerImplementation, *, Integer_mul, 486761895)                         \
+  V(_IntegerImplementation, %, Integer_modulo, 1370017357)                     \
+  V(_IntegerImplementation, ~/, Integer_truncDivide, 450435650)                \
+  V(_IntegerImplementation, unary-, Integer_negate, 1734168384)                \
+  V(_IntegerImplementation, _bitAndFromInteger,                                \
+    Integer_bitAndFromInteger, 726019207)                                      \
+  V(_IntegerImplementation, &, Integer_bitAnd, 1267520437)                     \
+  V(_IntegerImplementation, _bitOrFromInteger,                                 \
+    Integer_bitOrFromInteger, 726019207)                                       \
+  V(_IntegerImplementation, |, Integer_bitOr, 249432836)                       \
+  V(_IntegerImplementation, _bitXorFromInteger,                                \
+    Integer_bitXorFromInteger, 726019207)                                      \
+  V(_IntegerImplementation, ^, Integer_bitXor, 1177061571)                     \
   V(_IntegerImplementation,                                                    \
     _greaterThanFromInteger,                                                   \
-    Integer_greaterThanFromInt)                                                \
-  V(_IntegerImplementation, >, Integer_greaterThan)                            \
-  V(_IntegerImplementation, ==, Integer_equal)                                 \
-  V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger)           \
-  V(_IntegerImplementation, <, Integer_lessThan)                               \
-  V(_IntegerImplementation, <=, Integer_lessEqualThan)                         \
-  V(_IntegerImplementation, >=, Integer_greaterEqualThan)                      \
-  V(_IntegerImplementation, <<, Integer_shl)                                   \
-  V(_IntegerImplementation, >>, Integer_sar)                                   \
-  V(_Smi, ~, Smi_bitNegate)                                                    \
-  V(_Double, >, Double_greaterThan)                                            \
-  V(_Double, >=, Double_greaterEqualThan)                                      \
-  V(_Double, <, Double_lessThan)                                               \
-  V(_Double, <=, Double_lessEqualThan)                                         \
-  V(_Double, ==, Double_equal)                                                 \
-  V(_Double, +, Double_add)                                                    \
-  V(_Double, -, Double_sub)                                                    \
-  V(_Double, *, Double_mul)                                                    \
-  V(_Double, /, Double_div)                                                    \
-  V(_Double, get:isNaN, Double_getIsNaN)                                       \
-  V(_Double, get:isNegative, Double_getIsNegative)                             \
-  V(_Double, _mulFromInteger, Double_mulFromInteger)                           \
-  V(_Double, .fromInteger, Double_fromInteger)                                 \
-  V(_Double, toInt, Double_toInt)                                              \
-  V(_ObjectArray, ., ObjectArray_Allocate)                                     \
-  V(_ObjectArray, get:length, Array_getLength)                                 \
-  V(_ObjectArray, [], Array_getIndexed)                                        \
-  V(_ObjectArray, []=, Array_setIndexed)                                       \
-  V(_GrowableObjectArray, .fromObjectArray, GArray_Allocate)                   \
-  V(_GrowableObjectArray, get:length, GrowableArray_getLength)                 \
-  V(_GrowableObjectArray, get:capacity, GrowableArray_getCapacity)             \
-  V(_GrowableObjectArray, [], GrowableArray_getIndexed)                        \
-  V(_GrowableObjectArray, []=, GrowableArray_setIndexed)                       \
-  V(_GrowableObjectArray, _setLength, GrowableArray_setLength)                 \
-  V(_GrowableObjectArray, _setData, GrowableArray_setData)                     \
-  V(_GrowableObjectArray, add, GrowableArray_add)                              \
-  V(_ImmutableArray, [], ImmutableArray_getIndexed)                            \
-  V(_ImmutableArray, get:length, ImmutableArray_getLength)                     \
-  V(::, sqrt, Math_sqrt)                                                       \
-  V(::, sin, Math_sin)                                                         \
-  V(::, cos, Math_cos)                                                         \
-  V(Object, ==, Object_equal)                                                  \
-  V(_FixedSizeArrayIterator, get:hasNext, FixedSizeArrayIterator_getHasNext)   \
-  V(_FixedSizeArrayIterator, next, FixedSizeArrayIterator_next)                \
-  V(_StringBase, get:hashCode, String_getHashCode)                             \
-  V(_StringBase, get:isEmpty, String_getIsEmpty)                               \
-  V(_StringBase, get:length, String_getLength)                                 \
-  V(_StringBase, charCodeAt, String_charCodeAt)                                \
-  V(_ByteArrayBase, get:length, ByteArrayBase_getLength)                       \
-  V(_Int8Array, [], Int8Array_getIndexed)                                      \
-  V(_Int8Array, []=, Int8Array_setIndexed)                                     \
-  V(_Uint8Array, [], Uint8Array_getIndexed)                                    \
-  V(_Uint8Array, []=, Uint8Array_setIndexed)                                   \
-  V(_Int16Array, [], Int16Array_getIndexed)                                    \
-  V(_Uint16Array, [], Uint16Array_getIndexed)                                  \
-  V(_Int32Array, [], Int32Array_getIndexed)                                    \
-  V(_Uint32Array, [], Uint32Array_getIndexed)                                  \
-  V(_Int64Array, [], Int64Array_getIndexed)                                    \
-  V(_Uint64Array, [], Uint64Array_getIndexed)                                  \
-  V(_Float32Array, [], Float32Array_getIndexed)                                \
-  V(_Float32Array, []=, Float32Array_setIndexed)                               \
-  V(_Float64Array, [], Float64Array_getIndexed)                                \
-  V(_Float64Array, []=, Float64Array_setIndexed)                               \
+    Integer_greaterThanFromInt, 79222670)                                      \
+  V(_IntegerImplementation, >, Integer_greaterThan, 319553701)                 \
+  V(_IntegerImplementation, ==, Integer_equal, 1163202222)                     \
+  V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger, 79222670) \
+  V(_IntegerImplementation, <, Integer_lessThan, 1306209983)                   \
+  V(_IntegerImplementation, <=, Integer_lessEqualThan, 458673122)              \
+  V(_IntegerImplementation, >=, Integer_greaterEqualThan, 459596643)           \
+  V(_IntegerImplementation, <<, Integer_shl, 1586407617)                       \
+  V(_IntegerImplementation, >>, Integer_sar, 130211175)                        \
+  V(_Smi, ~, Smi_bitNegate, 882629793)                                         \
+  V(_Double, >, Double_greaterThan, 1821658410)                                \
+  V(_Double, >=, Double_greaterEqualThan, 1317118885)                          \
+  V(_Double, <, Double_lessThan, 177557761)                                    \
+  V(_Double, <=, Double_lessEqualThan, 1316195364)                             \
+  V(_Double, ==, Double_equal, 1896071176)                                     \
+  V(_Double, +, Double_add, 1137022234)                                        \
+  V(_Double, -, Double_sub, 1425469940)                                        \
+  V(_Double, *, Double_mul, 1865672692)                                        \
+  V(_Double, /, Double_div, 1832148629)                                        \
+  V(_Double, get:isNaN, Double_getIsNaN, 54462366)                             \
+  V(_Double, get:isNegative, Double_getIsNegative, 54462366)                   \
+  V(_Double, _mulFromInteger, Double_mulFromInteger, 795128)                   \
+  V(_Double, .fromInteger, Double_fromInteger, 842078193)                      \
+  V(_Double, toInt, Double_toInt, 362666636)                                   \
+  V(_ObjectArray, ., ObjectArray_Allocate, 577949617)                          \
+  V(_ObjectArray, get:length, Array_getLength, 405297088)                      \
+  V(_ObjectArray, [], Array_getIndexed, 71937385)                              \
+  V(_ObjectArray, []=, Array_setIndexed, 255863719)                            \
+  V(_GrowableObjectArray, .fromObjectArray, GArray_Allocate, 989879928)        \
+  V(_GrowableObjectArray, get:length, GrowableArray_getLength, 725548050)      \
+  V(_GrowableObjectArray, get:capacity, GrowableArray_getCapacity, 725548050)  \
+  V(_GrowableObjectArray, [], GrowableArray_getIndexed, 581838973)             \
+  V(_GrowableObjectArray, []=, GrowableArray_setIndexed, 1048007636)           \
+  V(_GrowableObjectArray, _setLength, GrowableArray_setLength, 796709584)      \
+  V(_GrowableObjectArray, _setData, GrowableArray_setData, 477312179)          \
+  V(_GrowableObjectArray, add, GrowableArray_add, 1776744235)                  \
+  V(_ImmutableArray, [], ImmutableArray_getIndexed, 486821199)                 \
+  V(_ImmutableArray, get:length, ImmutableArray_getLength, 433698233)          \
+  V(::, sqrt, Math_sqrt, 2232519)                                              \
+  V(::, sin, Math_sin, 837187616)                                              \
+  V(::, cos, Math_cos, 548880317)                                              \
+  V(Object, ==, Object_equal, 1512068535)                                      \
+  V(_FixedSizeArrayIterator, get:hasNext,                                      \
+    FixedSizeArrayIterator_getHasNext, 1847855366)                             \
+  V(_FixedSizeArrayIterator, next, FixedSizeArrayIterator_next, 1739352783)    \
+  V(_StringBase, get:hashCode, String_getHashCode, 320803993)                  \
+  V(_StringBase, get:isEmpty, String_getIsEmpty, 1065961093)                   \
+  V(_StringBase, get:length, String_getLength, 320803993)                      \
+  V(_StringBase, charCodeAt, String_charCodeAt, 984449525)                     \
+  V(_ByteArrayBase, get:length, ByteArrayBase_getLength, 1856909152)           \
+  V(_Int8Array, [], Int8Array_getIndexed, 239810357)                           \
+  V(_Int8Array, []=, Int8Array_setIndexed, 1469038436)                         \
+  V(_Uint8Array, [], Uint8Array_getIndexed, 1635923899)                        \
+  V(_Uint8Array, []=, Uint8Array_setIndexed, 1619321522)                       \
+  V(_Int16Array, [], Int16Array_getIndexed, 2090761657)                        \
+  V(_Uint16Array, [], Uint16Array_getIndexed, 289929708)                       \
+  V(_Int32Array, [], Int32Array_getIndexed, 589442411)                         \
+  V(_Uint32Array, [], Uint32Array_getIndexed, 1474116947)                      \
+  V(_Int64Array, [], Int64Array_getIndexed, 1506836119)                        \
+  V(_Uint64Array, [], Uint64Array_getIndexed, 1856952148)                      \
+  V(_Float32Array, [], Float32Array_getIndexed, 1167607283)                    \
+  V(_Float32Array, []=, Float32Array_setIndexed, 1270729544)                   \
+  V(_Float64Array, [], Float64Array_getIndexed, 1363897161)                    \
+  V(_Float64Array, []=, Float64Array_setIndexed, 283625119)                    \
+  V(_ExternalUint8Array, [], ExternalUint8Array_getIndexed, 632699940)         \
 
 // Forward declarations.
 class Assembler;
@@ -106,7 +115,7 @@
   static bool CanIntrinsify(const Function& function);
 
  private:
-#define DECLARE_FUNCTION(test_class_name, test_function_name, destination)    \
+#define DECLARE_FUNCTION(test_class_name, test_function_name, destination, fp) \
   static bool destination(Assembler* assembler);
 
 INTRINSIC_LIST(DECLARE_FUNCTION)
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index cf47309..5675214 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -538,22 +538,19 @@
   // * EBX has the index into the array.
   // EBX contains the SMI index which is shifted by 1.
   __ SmiUntag(EBX);
-  // Move EBX into EDI.
+  // Free EBX for the value since we want a byte register.
   __ movl(EDI, EBX);
-  // Load the value into EBX.
   __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Value.
-  // If EBX is not an Smi, jump to fall through.
   __ testl(EBX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
   __ SmiUntag(EBX);
-  // Add 128 to EBX to bring it into 0..FF.
+  // Check that the value is a byte. Add 128 to EBX to bring it into
+  // the range 0..FF.
   __ addl(EBX, Immediate(128));
   __ cmpl(EBX, Immediate(0xFF));
-  // If EBX is too large an Int8, jump to fall through.
   __ j(ABOVE, &fall_through, Assembler::kNearJump);
-  // Remove addition.
+  // Undo addition.
   __ subl(EBX, Immediate(128));
-  // Store BL into array EAX[EDI] = BL.
   __ movb(FieldAddress(EAX, EDI, TIMES_1, Int8Array::data_offset()), BL);
   __ ret();
   __ Bind(&fall_through);
@@ -585,18 +582,15 @@
   // * EBX has the index into the array.
   // EBX contains the SMI index which is shifted by 1.
   __ SmiUntag(EBX);
-  // Move EBX into EDI.
+  // Free EBX for the value since we want a byte register.
   __ movl(EDI, EBX);
-  // Load the value into EBX.
   __ movl(EBX, Address(ESP, + 1 * kWordSize));  // Value.
-  // If EBX is not an Smi, jump to fall through.
   __ testl(EBX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
   __ SmiUntag(EBX);
-  // If EBX is too large an Uint8, jump to fall through.
+  // Check that the value is a byte.
   __ cmpl(EBX, Immediate(0xFF));
   __ j(ABOVE, &fall_through, Assembler::kNearJump);
-  // Store BL into array EAX[EDI] = BL.
   __ movb(FieldAddress(EAX, EDI, TIMES_1, Uint8Array::data_offset()), BL);
   __ ret();
   __ Bind(&fall_through);
@@ -792,6 +786,20 @@
 }
 
 
+bool Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  TestByteArrayIndex(assembler, &fall_through);
+  __ SmiUntag(EBX);
+  __ movl(EAX, FieldAddress(EAX, ExternalUint8Array::external_data_offset()));
+  __ movl(EAX, Address(EAX, ExternalByteArrayData<uint8_t>::data_offset()));
+  __ movzxb(EAX, Address(EAX, EBX, TIMES_1, 0));
+  __ SmiTag(EAX);
+  __ ret();
+  __ Bind(&fall_through);
+  return false;
+}
+
+
 // Tests if two top most arguments are smis, jumps to label not_smi if not.
 // Topmost argument is in EAX.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index 5f3f96d..8d52b6a 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -471,6 +471,26 @@
 
 bool Intrinsifier::Int8Array_setIndexed(Assembler* assembler) {
   Label fall_through;
+  // Verify that the array index is valid.
+  TestByteArraySetIndex(assembler, &fall_through);
+  // After TestByteArraySetIndex:
+  // * RAX has the base address of the byte array.
+  // * R12 has the index into the array.
+  // R12 contains the SMI index which is shifted by 1.
+  __ SmiUntag(R12);
+  __ movq(RDI, Address(RSP, + 1 * kWordSize));  // Value.
+  __ testq(RDI, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
+  __ SmiUntag(RDI);
+  // Check that the value is a byte. Add 128 to the value to bring it into
+  // the range 0..FF.
+  __ addq(RDI, Immediate(128));
+  __ cmpq(RDI, Immediate(0xFF));
+  __ j(ABOVE, &fall_through, Assembler::kNearJump);
+  // Undo addition.
+  __ subq(RDI, Immediate(128));
+  __ movb(FieldAddress(RAX, R12, TIMES_1, Uint8Array::data_offset()), RDI);
+  __ ret();
   __ Bind(&fall_through);
   return false;
 }
@@ -478,6 +498,22 @@
 
 bool Intrinsifier::Uint8Array_setIndexed(Assembler* assembler) {
   Label fall_through;
+  // Verify that the array index is valid.
+  TestByteArraySetIndex(assembler, &fall_through);
+  // After TestByteArraySetIndex:
+  // * RAX has the base address of the byte array.
+  // * R12 has the index into the array.
+  // R12 contains the SMI index which is shifted by 1.
+  __ SmiUntag(R12);
+  __ movq(RDI, Address(RSP, + 1 * kWordSize));  // Value.
+  __ testq(RDI, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
+  __ SmiUntag(RDI);
+  // Check that value is a byte.
+  __ cmpq(RDI, Immediate(0xFF));
+  __ j(ABOVE, &fall_through, Assembler::kNearJump);
+  __ movb(FieldAddress(RAX, R12, TIMES_1, Uint8Array::data_offset()), RDI);
+  __ ret();
   __ Bind(&fall_through);
   return false;
 }
@@ -700,6 +736,20 @@
 }
 
 
+bool Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) {
+  Label fall_through;
+  TestByteArrayIndex(assembler, &fall_through);
+  __ SmiUntag(R12);
+  __ movq(RAX, FieldAddress(RAX, ExternalUint8Array::external_data_offset()));
+  __ movq(RAX, Address(RAX, ExternalByteArrayData<uint8_t>::data_offset()));
+  __ movzxb(RAX, Address(RAX, R12, TIMES_1, 0));
+  __ SmiTag(RAX);
+  __ ret();
+  __ Bind(&fall_through);
+  return false;
+}
+
+
 // Tests if two top most arguments are smis, jumps to label not_smi if not.
 // Topmost argument is in RAX.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index af8f5e3..6b9178d 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -17,7 +17,6 @@
 #include "vm/object_store.h"
 #include "vm/parser.h"
 #include "vm/port.h"
-#include "vm/random.h"
 #include "vm/stack_frame.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
@@ -150,7 +149,6 @@
       heap_(NULL),
       object_store_(NULL),
       top_context_(Context::null()),
-      random_seed_(Random::kDefaultRandomSeed),
       top_exit_frame_info_(0),
       init_callback_data_(NULL),
       library_tag_handler_(NULL),
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 76afa3e..5849640 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -145,9 +145,6 @@
     return OFFSET_OF(Isolate, top_context_);
   }
 
-  int32_t random_seed() const { return random_seed_; }
-  void set_random_seed(int32_t value) { random_seed_ = value; }
-
   uword top_exit_frame_info() const { return top_exit_frame_info_; }
   void set_top_exit_frame_info(uword value) { top_exit_frame_info_ = value; }
   static intptr_t top_exit_frame_info_offset() {
@@ -326,7 +323,6 @@
   Heap* heap_;
   ObjectStore* object_store_;
   RawContext* top_context_;
-  int32_t random_seed_;
   uword top_exit_frame_info_;
   void* init_callback_data_;
   Dart_LibraryTagHandler library_tag_handler_;
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 2aadf6d..9812840 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -23,7 +23,7 @@
 // callback has been set by the embedder when an isolate is spawned.
 TEST_CASE(IsolateSpawn) {
   const char* kScriptChars =
-      "#import('dart:isolate');\n"
+      "import 'dart:isolate';\n"
       "void entry() {}\n"
       "int testMain() {\n"
       "  try {\n"
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index 4522b1a..0c2bc09 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -277,6 +277,12 @@
     return value_ == other.value_;
   }
 
+  // If current location is constant might return something that
+  // is not equal to any Kind.
+  Kind kind() const {
+    return KindField::decode(value_);
+  }
+
  private:
   explicit Location(uword value) : value_(value) { }
 
@@ -287,12 +293,6 @@
     return PayloadField::decode(value_);
   }
 
-  // If current location is constant might return something that
-  // is not equal to any Kind.
-  Kind kind() const {
-    return KindField::decode(value_);
-  }
-
   typedef BitField<Kind, 0, kBitsForKind> KindField;
   typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField;
 
diff --git a/runtime/vm/native_entry_test.cc b/runtime/vm/native_entry_test.cc
index 6f945b4..8c58b66 100644
--- a/runtime/vm/native_entry_test.cc
+++ b/runtime/vm/native_entry_test.cc
@@ -58,14 +58,15 @@
 // Test code patching.
 void TestStaticCallPatching(Dart_NativeArguments args) {
   Dart_EnterScope();
-  uword target_address = 0;
-  Function& target_function = Function::Handle();
   DartFrameIterator iterator;
   iterator.NextFrame();  // Skip native call.
   StackFrame* static_caller_frame = iterator.NextFrame();
-  CodePatcher::GetStaticCallAt(static_caller_frame->pc(),
-                               &target_function,
-                               &target_address);
+  uword target_address =
+      CodePatcher::GetStaticCallTargetAt(static_caller_frame->pc());
+  const Code& code = Code::Handle(static_caller_frame->LookupDartCode());
+  const Function& target_function =
+      Function::Handle(code.GetStaticCallTargetFunctionAt(
+          static_caller_frame->pc()));
   EXPECT(String::Handle(target_function.name()).
       Equals(String::Handle(String::New("NativePatchStaticCall"))));
   const uword function_entry_address =
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 5dc09dd..6867359 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -408,6 +408,8 @@
   isolate->object_store()->set_array_class(cls);
   cls = Class::NewStringClass(kOneByteStringCid);
   isolate->object_store()->set_one_byte_string_class(cls);
+  cls = Class::NewStringClass(kTwoByteStringCid);
+  isolate->object_store()->set_two_byte_string_class(cls);
 
   // Allocate and initialize the empty_array instance.
   {
@@ -516,17 +518,6 @@
 }
 
 
-RawClass* Object::CreateAndRegisterInterface(const char* cname,
-                                             const Script& script,
-                                             const Library& lib) {
-  const String& name = String::Handle(Symbols::New(cname));
-  const Class& cls = Class::Handle(
-      Class::NewInterface(name, script, Scanner::kDummyTokenIndex));
-  lib.AddClass(cls);
-  return cls.raw();
-}
-
-
 void Object::RegisterClass(const Class& cls,
                            const String& name,
                            const Library& lib) {
@@ -590,6 +581,10 @@
   cls = Class::NewStringClass(kOneByteStringCid);
   object_store->set_one_byte_string_class(cls);
 
+  // Pre-allocate the TwoByteString class needed by the symbol table.
+  cls = Class::NewStringClass(kTwoByteStringCid);
+  object_store->set_two_byte_string_class(cls);
+
   // Setup the symbol table for the symbols created in the isolate.
   Symbols::SetupSymbolTable(isolate);
 
@@ -650,8 +645,7 @@
   RegisterPrivateClass(cls, name, core_lib);
   pending_classes.Add(cls, Heap::kOld);
 
-  cls = Class::NewStringClass(kTwoByteStringCid);
-  object_store->set_two_byte_string_class(cls);
+  cls = object_store->two_byte_string_class();  // Was allocated above.
   name = Symbols::TwoByteString();
   RegisterPrivateClass(cls, name, core_lib);
   pending_classes.Add(cls, Heap::kOld);
@@ -886,7 +880,9 @@
   type = Type::NewNonParameterizedType(cls);
   object_store->set_string_type(type);
 
-  cls = CreateAndRegisterInterface("List", script, core_lib);
+  name = Symbols::New("List");
+  cls = Class::New<Instance>(name, script, Scanner::kDummyTokenIndex);
+  RegisterClass(cls, name, core_lib);
   pending_classes.Add(cls, Heap::kOld);
   object_store->set_list_class(cls);
 
@@ -2038,6 +2034,11 @@
 }
 
 
+bool Class::IsListClass() const {
+  return raw() == Isolate::Current()->object_store()->list_class();
+}
+
+
 bool Class::IsCanonicalSignatureClass() const {
   const Function& function = Function::Handle(signature_function());
   return (!function.IsNull() && (function.signature_class() == raw()));
@@ -2476,7 +2477,12 @@
 
 
 const char* UnresolvedClass::ToCString() const {
-  return "UnresolvedClass";
+  const char* format = "unresolved class '%s'";
+  const char* cname =  String::Handle(Name()).ToCString();
+  intptr_t len = OS::SNPrint(NULL, 0, format, cname) + 1;
+  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
+  OS::SNPrint(chars, len, format, cname);
+  return chars;
 }
 
 
@@ -4180,6 +4186,45 @@
 }
 
 
+// Construct fingerprint from token stream. The token stream contains also
+// arguments.
+int32_t Function::SourceFingerprint() const {
+  uint32_t result = String::Handle(Signature()).Hash();
+  TokenStream::Iterator tokens_iterator(TokenStream::Handle(
+      Script::Handle(script()).tokens()), token_pos());
+  Object& obj = Object::Handle();
+  String& literal = String::Handle();
+  while (tokens_iterator.CurrentPosition() < end_token_pos()) {
+    uint32_t val = 0;
+    obj = tokens_iterator.CurrentToken();
+    if (obj.IsSmi()) {
+      val = Smi::Cast(obj).Value();
+    } else {
+      literal = tokens_iterator.MakeLiteralToken(obj);
+      val = literal.Hash();
+    }
+    result = 31 * result + val;
+    tokens_iterator.Advance();
+  }
+  result = result & ((static_cast<uint32_t>(1) << 31) - 1);
+  ASSERT(result <= static_cast<uint32_t>(kMaxInt32));
+  return result;
+}
+
+
+bool Function::CheckSourceFingerprint(intptr_t fp) const {
+  if (SourceFingerprint() != fp) {
+    OS::Print("FP mismatch while recogbnizing method %s:"
+      " expecting %"Pd" found %d\n",
+      ToFullyQualifiedCString(),
+      fp,
+      SourceFingerprint());
+    return false;
+  }
+  return true;
+}
+
+
 const char* Function::ToCString() const {
   const char* static_str = is_static() ? " static" : "";
   const char* abstract_str = is_abstract() ? " abstract" : "";
@@ -7002,8 +7047,41 @@
 }
 
 
-void Code::set_resolved_static_calls(const GrowableObjectArray& val) const {
-  StorePointer(&raw_ptr()->resolved_static_calls_, val.raw());
+void Code::set_static_calls_target_table(const Array& value) const {
+  StorePointer(&raw_ptr()->static_calls_target_table_, value.raw());
+}
+
+
+RawFunction* Code::GetStaticCallTargetFunctionAt(uword pc) const {
+  RawObject* raw_code_offset =
+      reinterpret_cast<RawObject*>(Smi::New(pc - EntryPoint()));
+  const Array& array =
+      Array::Handle(raw_ptr()->static_calls_target_table_);
+  for (intptr_t i = 0; i < array.Length(); i += kSCallTableEntryLength) {
+    if (array.At(i) == raw_code_offset) {
+      Function& function = Function::Handle();
+      function ^= array.At(i + kSCallTableFunctionEntry);
+      return function.raw();
+    }
+  }
+  return Function::null();
+}
+
+
+void Code::SetStaticCallTargetCodeAt(uword pc, const Code& code) const {
+  RawObject* raw_code_offset =
+      reinterpret_cast<RawObject*>(Smi::New(pc - EntryPoint()));
+  const Array& array =
+      Array::Handle(raw_ptr()->static_calls_target_table_);
+  for (intptr_t i = 0; i < array.Length(); i += kSCallTableEntryLength) {
+    if (array.At(i) == raw_code_offset) {
+      ASSERT(code.IsNull() ||
+             (code.function() == array.At(i + kSCallTableFunctionEntry)));
+      array.SetAt(i + kSCallTableCodeEntry, code);
+      return;
+    }
+  }
+  UNREACHABLE();
 }
 
 
@@ -7276,12 +7354,11 @@
   deopt_ids->Clear();
   const PcDescriptors& descriptors =
       PcDescriptors::Handle(this->pc_descriptors());
-  Function& function = Function::Handle();
   for (intptr_t i = 0; i < descriptors.Length(); i++) {
     if (descriptors.DescriptorKind(i) == PcDescriptors::kFuncCall) {
       // Static call.
-      uword target_addr;
-      CodePatcher::GetStaticCallAt(descriptors.PC(i), &function, &target_addr);
+      const uword target_addr =
+          CodePatcher::GetStaticCallTargetAt(descriptors.PC(i));
       if (target_addr == StubCode::CallStaticFunctionEntryPoint()) {
         deopt_ids->Add(descriptors.DeoptId(i));
       }
@@ -8977,18 +9054,21 @@
   if (IsResolved()) {
     const AbstractTypeArguments& type_arguments =
         AbstractTypeArguments::Handle(arguments());
+    const char* class_name;
+    if (HasResolvedTypeClass()) {
+      class_name = String::Handle(
+          Class::Handle(type_class()).Name()).ToCString();
+    } else {
+      class_name = UnresolvedClass::Handle(unresolved_class()).ToCString();
+    }
     if (type_arguments.IsNull()) {
       const char* format = "Type: class '%s'";
-      const char* class_name =
-          String::Handle(Class::Handle(type_class()).Name()).ToCString();
       intptr_t len = OS::SNPrint(NULL, 0, format, class_name) + 1;
       char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
       OS::SNPrint(chars, len, format, class_name);
       return chars;
     } else {
       const char* format = "Type: class '%s', args:[%s]";
-      const char* class_name =
-          String::Handle(Class::Handle(type_class()).Name()).ToCString();
       const char* args_cstr =
           AbstractTypeArguments::Handle(arguments()).ToCString();
       intptr_t len = OS::SNPrint(NULL, 0, format, class_name, args_cstr) + 1;
@@ -9875,11 +9955,11 @@
     hash_ ^= hash_ >> 11;
     hash_ += hash_ << 15;
     hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
-    ASSERT(hash_ >= 0);
+    ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32));
     return hash_ == 0 ? 1 : hash_;
   }
  private:
-  intptr_t hash_;
+  uint32_t hash_;
 };
 
 
@@ -9927,7 +10007,7 @@
 }
 
 
-intptr_t String::Hash(const uint32_t* characters, intptr_t len) {
+intptr_t String::Hash(const int32_t* characters, intptr_t len) {
   return HashImpl(characters, len);
 }
 
@@ -9990,36 +10070,37 @@
 }
 
 
-bool String::Equals(const char* str) const {
-  ASSERT(str != NULL);
-  intptr_t len = strlen(str);
-  for (intptr_t i = 0; i < this->Length(); ++i) {
-    if (*str == '\0') {
+bool String::Equals(const char* cstr) const {
+  ASSERT(cstr != NULL);
+  CodePointIterator it(*this);
+  intptr_t len = strlen(cstr);
+  while (it.Next()) {
+    if (*cstr == '\0') {
       // Lengths don't match.
       return false;
     }
     int32_t ch;
-    intptr_t consumed = Utf8::Decode(reinterpret_cast<const uint8_t*>(str),
+    intptr_t consumed = Utf8::Decode(reinterpret_cast<const uint8_t*>(cstr),
                                      len,
                                      &ch);
-    if (consumed == 0 || this->CharAt(i) != ch) {
+    if (consumed == 0 || it.Current() != ch) {
       return false;
     }
-    str += consumed;
+    cstr += consumed;
     len -= consumed;
   }
-  return *str == '\0';
+  return *cstr == '\0';
 }
 
 
-bool String::Equals(const uint8_t* characters, intptr_t len) const {
+bool String::Equals(const uint8_t* latin1_array, intptr_t len) const {
   if (len != this->Length()) {
     // Lengths don't match.
     return false;
   }
 
   for (intptr_t i = 0; i < len; i++) {
-    if (this->CharAt(i) != characters[i]) {
+    if (this->CharAt(i) != latin1_array[i]) {
       return false;
     }
   }
@@ -10027,14 +10108,14 @@
 }
 
 
-bool String::Equals(const uint16_t* characters, intptr_t len) const {
+bool String::Equals(const uint16_t* utf16_array, intptr_t len) const {
   if (len != this->Length()) {
     // Lengths don't match.
     return false;
   }
 
   for (intptr_t i = 0; i < len; i++) {
-    if (this->CharAt(i) != characters[i]) {
+    if (this->CharAt(i) != utf16_array[i]) {
       return false;
     }
   }
@@ -10042,16 +10123,17 @@
 }
 
 
-bool String::Equals(const uint32_t* characters, intptr_t len) const {
-  if (len != this->Length()) {
-    // Lengths don't match.
-    return false;
-  }
-
-  for (intptr_t i = 0; i < len; i++) {
-    if (this->CharAt(i) != static_cast<int32_t>(characters[i])) {
+bool String::Equals(const int32_t* utf32_array, intptr_t len) const {
+  CodePointIterator it(*this);
+  intptr_t i = 0;
+  while (it.Next()) {
+    if (it.Current() != static_cast<int32_t>(utf32_array[i])) {
       return false;
     }
+    ++i;
+  }
+  if (i != len) {
+    return false;
   }
   return true;
 }
@@ -10121,7 +10203,7 @@
     }
     return strobj.raw();
   }
-  ASSERT((type == Utf8::kBMP) || (type == Utf8::kSMP));
+  ASSERT((type == Utf8::kBMP) || (type == Utf8::kSupplementary));
   const String& strobj = String::Handle(TwoByteString::New(len, space));
   NoGCScope no_gc;
   Utf8::DecodeToUTF16(utf8_array, array_len,
@@ -10147,7 +10229,7 @@
 }
 
 
-RawString* String::New(const uint32_t* utf32_array,
+RawString* String::New(const int32_t* utf32_array,
                        intptr_t array_len,
                        Heap::Space space) {
   bool is_one_byte_string = true;
@@ -10512,10 +10594,9 @@
   ASSERT(!str.IsNull());
   bool has_mapping = false;
   int32_t dst_max = 0;
-  intptr_t len = str.Length();
-  // TODO(cshapiro): assume a transform is required, rollback if not.
-  for (intptr_t i = 0; i < len; ++i) {
-    int32_t src = str.CharAt(i);
+  CodePointIterator it(str);
+  while (it.Next()) {
+    int32_t src = it.Current();
     int32_t dst = mapping(src);
     if (src != dst) {
       has_mapping = true;
@@ -10545,6 +10626,25 @@
 }
 
 
+bool String::CodePointIterator::Next() {
+  ASSERT(index_ >= -1);
+  ASSERT(index_ < str_.Length());
+  int d = Utf16::Length(ch_);
+  if (index_ == (str_.Length() - d)) {
+    return false;
+  }
+  index_ += d;
+  ch_ = str_.CharAt(index_);
+  if (Utf16::IsLeadSurrogate(ch_) && (index_ != (str_.Length() - 1))) {
+    int32_t ch2 = str_.CharAt(index_ + 1);
+    if (Utf16::IsTrailSurrogate(ch2)) {
+      ch_ = Utf16::Decode(ch_, ch2);
+    }
+  }
+  return true;
+}
+
+
 RawOneByteString* OneByteString::EscapeSpecialCharacters(const String& str,
                                                          bool raw_str) {
   intptr_t len = str.Length();
@@ -10683,7 +10783,7 @@
 }
 
 
-RawOneByteString* OneByteString::New(const uint32_t* characters,
+RawOneByteString* OneByteString::New(const int32_t* characters,
                                      intptr_t len,
                                      Heap::Space space) {
   const String& result = String::Handle(OneByteString::New(len, space));
@@ -10818,7 +10918,7 @@
 
 
 RawTwoByteString* TwoByteString::New(intptr_t utf16_len,
-                                     const uint32_t* utf32_array,
+                                     const int32_t* utf32_array,
                                      intptr_t array_len,
                                      Heap::Space space) {
   ASSERT((array_len > 0) && (utf16_len >= array_len));
@@ -10829,7 +10929,7 @@
     for (intptr_t i = 0; i < array_len; ++i) {
       if (utf32_array[i] > 0xffff) {
         ASSERT(j < (utf16_len - 1));
-        Utf8::ConvertUTF32ToUTF16(utf32_array[i], CharAddr(result, j));
+        Utf16::Encode(utf32_array[i], CharAddr(result, j));
         j += 2;
       } else {
         ASSERT(j < utf16_len);
@@ -10887,10 +10987,20 @@
   ASSERT(!str.IsNull());
   intptr_t len = str.Length();
   const String& result = String::Handle(TwoByteString::New(len, space));
-  for (intptr_t i = 0; i < len; ++i) {
-    int32_t ch = mapping(str.CharAt(i));
-    ASSERT(ch >= 0 && ch <= 0xFFFF);
-    *CharAddr(result, i) = ch;
+  String::CodePointIterator it(str);
+  intptr_t i = 0;
+  while (it.Next()) {
+    int32_t src = it.Current();
+    int32_t dst = mapping(src);
+    ASSERT(dst >= 0 && dst <= 0x10FFFF);
+    intptr_t len = Utf16::Length(dst);
+    if (len == 1) {
+      *CharAddr(result, i) = dst;
+    } else {
+      ASSERT(len == 2);
+      Utf16::Encode(dst, CharAddr(result, i));
+    }
+    i += len;
   }
   return TwoByteString::raw(result);
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 07cb5bf..e40d545 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -366,9 +366,6 @@
  private:
   static void InitializeObject(uword address, intptr_t id, intptr_t size);
 
-  static RawClass* CreateAndRegisterInterface(const char* cname,
-                                              const Script& script,
-                                              const Library& lib);
   static void RegisterClass(const Class& cls,
                             const String& name,
                             const Library& lib);
@@ -605,6 +602,9 @@
   // Check if this class represents the 'Object' class.
   bool IsObjectClass() const { return id() == kInstanceCid; }
 
+  // Check if this class represents the 'List' class.
+  bool IsListClass() const;
+
   // Check if this class represents a signature class.
   bool IsSignatureClass() const {
     return signature_function() != Object::null();
@@ -1433,6 +1433,13 @@
                                          const Function& parent,
                                          intptr_t token_pos);
 
+  // Slow function, use in asserts to track changes in important library
+  // functions.
+  int32_t SourceFingerprint() const;
+
+  // Return false and report an error if the fingerprint does not match.
+  bool CheckSourceFingerprint(intptr_t fp) const;
+
   static const int kCtorPhaseInit = 1 << 0;
   static const int kCtorPhaseBody = 1 << 1;
   static const int kCtorPhaseAll = (kCtorPhaseInit | kCtorPhaseBody);
@@ -2486,10 +2493,22 @@
   void set_stackmaps(const Array& maps) const;
   RawStackmap* GetStackmap(uword pc, Array* stackmaps, Stackmap* map) const;
 
-  RawGrowableObjectArray* resolved_static_calls() const {
-    return raw_ptr()->resolved_static_calls_;
+  enum {
+    kSCallTableOffsetEntry = 0,
+    kSCallTableFunctionEntry = 1,
+    kSCallTableCodeEntry = 2,
+    kSCallTableEntryLength = 3,
+  };
+
+  void set_static_calls_target_table(const Array& value) const;
+  RawArray* static_calls_target_table() const {
+    return raw_ptr()->static_calls_target_table_;
   }
-  void set_resolved_static_calls(const GrowableObjectArray& val) const;
+
+  // Returns null if there is no static call at 'pc'.
+  RawFunction* GetStaticCallTargetFunctionAt(uword pc) const;
+  // Aborts if there is no static call at 'pc'.
+  void SetStaticCallTargetCodeAt(uword pc, const Code& code) const;
 
   class Comments : public ZoneAllocated {
    public:
@@ -3708,6 +3727,29 @@
   static const intptr_t kSizeofRawString = sizeof(RawObject) + (2 * kWordSize);
   static const intptr_t kMaxElements = kSmiMax / kTwoByteChar;
 
+  class CodePointIterator : public ValueObject {
+   public:
+    explicit CodePointIterator(const String& str)
+        : str_(str),
+          index_(-1),
+          ch_(-1) {
+    }
+
+    int32_t Current() {
+      ASSERT(index_ >= 0);
+      ASSERT(index_ < str_.Length());
+      return ch_;
+    }
+
+    bool Next();
+
+   private:
+    const String& str_;
+    intptr_t index_;
+    int32_t ch_;
+    DISALLOW_IMPLICIT_CONSTRUCTORS(CodePointIterator);
+  };
+
   intptr_t Length() const { return Smi::Value(raw_ptr()->length_); }
   static intptr_t length_offset() { return OFFSET_OF(RawString, length_); }
 
@@ -3716,7 +3758,7 @@
   static intptr_t Hash(const String& str, intptr_t begin_index, intptr_t len);
   static intptr_t Hash(const uint8_t* characters, intptr_t len);
   static intptr_t Hash(const uint16_t* characters, intptr_t len);
-  static intptr_t Hash(const uint32_t* characters, intptr_t len);
+  static intptr_t Hash(const int32_t* characters, intptr_t len);
 
   int32_t CharAt(intptr_t index) const;
 
@@ -3726,10 +3768,18 @@
   inline bool Equals(const String& str,
                      intptr_t begin_index,  // begin index on 'str'.
                      intptr_t len) const;  // len on 'str'.
-  bool Equals(const char* str) const;
+
+  // Compares to a '\0' terminated array of UTF-8 encoded characters.
+  bool Equals(const char* cstr) const;
+
+  // Compares to an array of UTF-8 encoded characters.
   bool Equals(const uint8_t* characters, intptr_t len) const;
+
+  // Compares to an array of UTF-16 encoded characters.
   bool Equals(const uint16_t* characters, intptr_t len) const;
-  bool Equals(const uint32_t* characters, intptr_t len) const;
+
+  // Compares to an array of UTF-32 encoded characters.
+  bool Equals(const int32_t* characters, intptr_t len) const;
 
   virtual bool Equals(const Instance& other) const;
 
@@ -3791,7 +3841,7 @@
                         Heap::Space space = Heap::kNew);
 
   // Creates a new String object from an array of UTF-32 encoded characters.
-  static RawString* New(const uint32_t* utf32_array,
+  static RawString* New(const int32_t* utf32_array,
                         intptr_t array_len,
                         Heap::Space space = Heap::kNew);
 
@@ -3937,7 +3987,7 @@
   static RawOneByteString* New(const uint16_t* characters,
                                intptr_t len,
                                Heap::Space space);
-  static RawOneByteString* New(const uint32_t* characters,
+  static RawOneByteString* New(const int32_t* characters,
                                intptr_t len,
                                Heap::Space space);
   static RawOneByteString* New(const String& str,
@@ -4020,7 +4070,7 @@
                                intptr_t len,
                                Heap::Space space);
   static RawTwoByteString* New(intptr_t utf16_len,
-                               const uint32_t* characters,
+                               const int32_t* characters,
                                intptr_t len,
                                Heap::Space space);
   static RawTwoByteString* New(const String& str,
@@ -4515,7 +4565,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawInt8Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4567,7 +4617,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawUint8Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4619,7 +4669,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawInt16Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4671,7 +4721,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawUint16Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4723,7 +4773,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawInt32Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4775,7 +4825,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawUint32Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4827,7 +4877,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawInt64Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4879,7 +4929,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawUint64Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4931,7 +4981,7 @@
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawFloat32Array, data_);
   }
 
   static intptr_t InstanceSize() {
@@ -4988,7 +5038,7 @@
   }
 
   static intptr_t data_offset() {
-    return length_offset() + kWordSize;
+    return OFFSET_OF(RawFloat64Array, data_);
   }
 
   static intptr_t InstanceSize(intptr_t len) {
@@ -5107,6 +5157,10 @@
     return RoundedAllocationSize(sizeof(RawExternalUint8Array));
   }
 
+  static intptr_t external_data_offset() {
+    return OFFSET_OF(RawExternalUint8Array, external_data_);
+  }
+
   static RawExternalUint8Array* New(uint8_t* data,
                                     intptr_t len,
                                     void* peer,
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 354c11c..f91f5d6 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -5,6 +5,7 @@
 #include "platform/assert.h"
 #include "vm/assembler.h"
 #include "vm/bigint_operations.h"
+#include "vm/class_finalizer.h"
 #include "vm/isolate.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
@@ -273,6 +274,48 @@
 }
 
 
+TEST_CASE(StringCompareTo) {
+  const String& abcd = String::Handle(String::New("abcd"));
+  const String& abce = String::Handle(String::New("abce"));
+  EXPECT_EQ(0, abcd.CompareTo(abcd));
+  EXPECT_EQ(0, abce.CompareTo(abce));
+  EXPECT(abcd.CompareTo(abce) < 0);
+  EXPECT(abce.CompareTo(abcd) > 0);
+
+  const int kMonkeyLen = 4;
+  const uint8_t monkey_utf8[kMonkeyLen] = { 0xf0, 0x9f, 0x90, 0xb5 };
+  const String& monkey_face =
+      String::Handle(String::New(monkey_utf8, kMonkeyLen));
+  const int kDogLen = 4;
+  // 0x1f436 DOG FACE.
+  const uint8_t dog_utf8[kDogLen] = { 0xf0, 0x9f, 0x90, 0xb6 };
+  const String& dog_face = String::Handle(String::New(dog_utf8, kDogLen));
+  EXPECT_EQ(0, monkey_face.CompareTo(monkey_face));
+  EXPECT_EQ(0, dog_face.CompareTo(dog_face));
+  EXPECT(monkey_face.CompareTo(dog_face) < 0);
+  EXPECT(dog_face.CompareTo(monkey_face) > 0);
+
+  const int kDominoLen = 4;
+  // 0x1f036 DOMINO TILE HORIZONTAL-00-05.
+  const uint8_t domino_utf8[kDominoLen] = { 0xf0, 0x9f, 0x80, 0xb6 };
+  const String& domino = String::Handle(String::New(domino_utf8, kDominoLen));
+  EXPECT_EQ(0, domino.CompareTo(domino));
+  EXPECT(domino.CompareTo(dog_face) < 0);
+  EXPECT(domino.CompareTo(monkey_face) < 0);
+  EXPECT(dog_face.CompareTo(domino) > 0);
+  EXPECT(monkey_face.CompareTo(domino) > 0);
+
+  EXPECT(abcd.CompareTo(monkey_face) < 0);
+  EXPECT(abce.CompareTo(monkey_face) < 0);
+  EXPECT(abcd.CompareTo(domino) < 0);
+  EXPECT(abce.CompareTo(domino) < 0);
+  EXPECT(domino.CompareTo(abcd) > 0);
+  EXPECT(domino.CompareTo(abcd) > 0);
+  EXPECT(monkey_face.CompareTo(abce) > 0);
+  EXPECT(monkey_face.CompareTo(abce) > 0);
+}
+
+
 TEST_CASE(Mint) {
 // On 64-bit architectures a Smi is stored in a 64 bit word. A Midint cannot
 // be allocated if it does fit into a Smi.
@@ -559,7 +602,7 @@
     EXPECT_EQ(false, str1.StartsWith(str3));
   }
 
-  const uint32_t four_chars[] = { 'C', 0xFF, 'h', 0xFFFF, 'a', 0x10FFFF, 'r' };
+  const int32_t four_chars[] = { 'C', 0xFF, 'h', 0xFFFF, 'a', 0x10FFFF, 'r' };
   const String& four_str = String::Handle(String::New(four_chars, 7));
   EXPECT_EQ(four_str.Hash(), four_str.Hash());
   EXPECT(four_str.IsTwoByteString());
@@ -587,7 +630,7 @@
 
   // Create a 1-byte string from an array of 4-byte elements.
   {
-    const uint32_t char32[] = { 0x00, 0x1F, 0x7F };
+    const int32_t char32[] = { 0x00, 0x1F, 0x7F };
     const String& str8 = String::Handle(String::New(char32, 3));
     EXPECT(str8.IsOneByteString());
     EXPECT(!str8.IsTwoByteString());
@@ -598,7 +641,7 @@
 
   // Create a 2-byte string from an array of 4-byte elements.
   {
-    const uint32_t char32[] = { 0, 0x7FFF, 0xFFFF };
+    const int32_t char32[] = { 0, 0x7FFF, 0xFFFF };
     const String& str16 = String::Handle(String::New(char32, 3));
     EXPECT(!str16.IsOneByteString());
     EXPECT(str16.IsTwoByteString());
@@ -943,7 +986,7 @@
     EXPECT(str1.IsOneByteString());
     EXPECT_EQ(0, str1.Length());
 
-    uint32_t four[] = { 0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1 };
+    int32_t four[] = { 0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1 };
     intptr_t four_len = sizeof(four) / sizeof(four[0]);
     intptr_t expected_len = (four_len * 2);
     const String& str2 = String::Handle(String::New(four, four_len));
@@ -988,8 +1031,8 @@
     array3.SetAt(2, str2);
     const String& str7 = String::Handle(String::ConcatAll(array3));
     EXPECT(str7.IsTwoByteString());
-    uint32_t fourfour[] = { 0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1,
-                            0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1 };
+    int32_t fourfour[] = { 0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1,
+                           0x1D4D5, 0x1D4DE, 0x1D4E4, 0x1D4E1 };
     intptr_t fourfour_len = sizeof(fourfour) / sizeof(fourfour[0]);
     EXPECT_EQ((fourfour_len * 2), str7.Length());
     const String& fourfour_str =
@@ -999,13 +1042,13 @@
 
   // Concatenate non-empty strings built from 4-byte elements.
   {
-    const uint32_t one[] = { 0x105D0, 0x105D9, 0x105D9, 0x105DF };
+    const int32_t one[] = { 0x105D0, 0x105D9, 0x105D9, 0x105DF };
     intptr_t one_len = sizeof(one) / sizeof(one[0]);
     const String& onestr = String::Handle(String::New(one, one_len));
     EXPECT(onestr.IsTwoByteString());
     EXPECT_EQ((one_len *2), onestr.Length());
 
-    const uint32_t two[] = { 0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9 };
+    const int32_t two[] = { 0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9 };
     intptr_t two_len = sizeof(two) / sizeof(two[0]);
     const String& twostr = String::Handle(String::New(two, two_len));
     EXPECT(twostr.IsTwoByteString());
@@ -1015,8 +1058,8 @@
 
     const String& str1 = String::Handle(String::Concat(onestr, twostr));
     EXPECT(str1.IsTwoByteString());
-    const uint32_t one_two[] = { 0x105D0, 0x105D9, 0x105D9, 0x105DF,
-                                 0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9 };
+    const int32_t one_two[] = { 0x105D0, 0x105D9, 0x105D9, 0x105DF,
+                                0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9 };
     intptr_t one_two_len = sizeof(one_two) / sizeof(one_two[0]);
     EXPECT_EQ((one_two_len * 2), str1.Length());
     const String& one_two_str =
@@ -1025,8 +1068,8 @@
 
     const String& str2 = String::Handle(String::Concat(twostr, onestr));
     EXPECT(str2.IsTwoByteString());
-    const uint32_t two_one[] = { 0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9,
-                                 0x105D0, 0x105D9, 0x105D9, 0x105DF };
+    const int32_t two_one[] = { 0x105E6, 0x105D5, 0x105D5, 0x105D9, 0x105D9,
+                                0x105D0, 0x105D9, 0x105D9, 0x105DF };
     intptr_t two_one_len = sizeof(two_one) / sizeof(two_one[0]);
     EXPECT_EQ((two_one_len * 2), str2.Length());
     const String& two_one_str =
@@ -1060,10 +1103,10 @@
     array3.SetAt(2, onestr);
     const String& str5 = String::Handle(String::ConcatAll(array3));
     EXPECT(str5.IsTwoByteString());
-    const uint32_t one_two_one[] = { 0x105D0, 0x105D9, 0x105D9, 0x105DF,
-                                     0x105E6, 0x105D5, 0x105D5, 0x105D9,
-                                     0x105D9,
-                                     0x105D0, 0x105D9, 0x105D9, 0x105DF };
+    const int32_t one_two_one[] = { 0x105D0, 0x105D9, 0x105D9, 0x105DF,
+                                    0x105E6, 0x105D5, 0x105D5, 0x105D9,
+                                    0x105D9,
+                                    0x105D0, 0x105D9, 0x105D9, 0x105DF };
     intptr_t one_two_one_len = sizeof(one_two_one) / sizeof(one_two_one[0]);
     EXPECT_EQ((one_two_one_len * 2), str5.Length());
     const String& one_two_one_str =
@@ -1077,11 +1120,11 @@
     array4.SetAt(2, twostr);
     const String& str6 = String::Handle(String::ConcatAll(array4));
     EXPECT(str6.IsTwoByteString());
-    const uint32_t two_one_two[] = { 0x105E6, 0x105D5, 0x105D5, 0x105D9,
-                                     0x105D9,
-                                     0x105D0, 0x105D9, 0x105D9, 0x105DF,
-                                     0x105E6, 0x105D5, 0x105D5, 0x105D9,
-                                     0x105D9 };
+    const int32_t two_one_two[] = { 0x105E6, 0x105D5, 0x105D5, 0x105D9,
+                                    0x105D9,
+                                    0x105D0, 0x105D9, 0x105D9, 0x105DF,
+                                    0x105E6, 0x105D5, 0x105D5, 0x105D9,
+                                    0x105D9 };
     intptr_t two_one_two_len = sizeof(two_one_two) / sizeof(two_one_two[0]);
     EXPECT_EQ((two_one_two_len * 2), str6.Length());
     const String& two_one_two_str =
@@ -1312,7 +1355,8 @@
     }
   }
 
-  // Create a SMP 2-byte string from a UTF-8 string literal.
+  // Create a 2-byte string with supplementary characters from a UTF-8
+  // string literal.
   {
     const char* src =
         "\xF0\x9D\x91\xA0\xF0\x9D\x91\xA1"
@@ -1385,6 +1429,37 @@
 }
 
 
+TEST_CASE(StringEqualsUtf8) {
+  const char* onesrc = "abc";
+  const String& onestr = String::Handle(String::New(onesrc));
+  EXPECT(onestr.IsOneByteString());
+  EXPECT(!onestr.Equals(""));
+  EXPECT(!onestr.Equals("a"));
+  EXPECT(!onestr.Equals("ab"));
+  EXPECT(onestr.Equals("abc"));
+  EXPECT(!onestr.Equals("abcd"));
+
+  const char* twosrc = "\xD7\x90\xD7\x91\xD7\x92";
+  const String& twostr = String::Handle(String::New(twosrc));
+  EXPECT(twostr.IsTwoByteString());
+  EXPECT(!twostr.Equals(""));
+  EXPECT(!twostr.Equals("\xD7\x90"));
+  EXPECT(!twostr.Equals("\xD7\x90\xD7\x91"));
+  EXPECT(twostr.Equals("\xD7\x90\xD7\x91\xD7\x92"));
+  EXPECT(!twostr.Equals("\xD7\x90\xD7\x91\xD7\x92\xD7\x93"));
+
+  const char* foursrc = "\xF0\x90\x8E\xA0\xF0\x90\x8E\xA1\xF0\x90\x8E\xA2";
+  const String& fourstr = String::Handle(String::New(foursrc));
+  EXPECT(fourstr.IsTwoByteString());
+  EXPECT(!fourstr.Equals(""));
+  EXPECT(!fourstr.Equals("\xF0\x90\x8E\xA0"));
+  EXPECT(!fourstr.Equals("\xF0\x90\x8E\xA0\xF0\x90\x8E\xA1"));
+  EXPECT(fourstr.Equals("\xF0\x90\x8E\xA0\xF0\x90\x8E\xA1\xF0\x90\x8E\xA2"));
+  EXPECT(!fourstr.Equals("\xF0\x90\x8E\xA0\xF0\x90\x8E\xA1"
+                         "\xF0\x90\x8E\xA2\xF0\x90\x8E\xA3"));
+}
+
+
 TEST_CASE(ExternalOneByteString) {
   uint8_t characters[] = { 0xF6, 0xF1, 0xE9 };
   intptr_t len = ARRAY_SIZE(characters);
@@ -1501,10 +1576,36 @@
   EXPECT_EQ(one.raw(), ein_symbol.raw());
   EXPECT(one.raw() != eins.raw());
 
-  uint32_t char32[] = { 'E', 'l', 'f' };
-  String& elf = String::Handle(Symbols::New(char32, 3));
-  EXPECT(elf.IsSymbol());
-  EXPECT_EQ(elf.raw(), Symbols::New("Elf"));
+  uint16_t char16[] = { 'E', 'l', 'f' };
+  String& elf1 = String::Handle(Symbols::New(char16, 3));
+  int32_t char32[] = { 'E', 'l', 'f' };
+  String& elf2 = String::Handle(Symbols::New(char32, 3));
+  EXPECT(elf1.IsSymbol());
+  EXPECT(elf2.IsSymbol());
+  EXPECT_EQ(elf1.raw(), Symbols::New("Elf"));
+  EXPECT_EQ(elf2.raw(), Symbols::New("Elf"));
+}
+
+
+TEST_CASE(SymbolUnicode) {
+  uint16_t monkey_utf16[] = { 0xd83d, 0xdc35 };  // Unicode Monkey Face.
+  String& monkey = String::Handle(Symbols::New(monkey_utf16, 2));
+  EXPECT(monkey.IsSymbol());
+  const char monkey_utf8[] = {0xf0, 0x9f, 0x90, 0xb5, 0};
+  EXPECT_EQ(monkey.raw(), Symbols::New(monkey_utf8));
+
+  int32_t kMonkeyFace = 0x1f435;
+  String& monkey2 = String::Handle(Symbols::FromCharCode(kMonkeyFace));
+  EXPECT_EQ(monkey.raw(), monkey2.raw());
+
+  // Unicode cat face with tears of joy.
+  int32_t kCatFaceWithTearsOfJoy = 0x1f639;
+  String& cat = String::Handle(Symbols::FromCharCode(kCatFaceWithTearsOfJoy));
+
+  uint16_t cat_utf16[] = { 0xd83d, 0xde39 };
+  String& cat2 = String::Handle(Symbols::New(cat_utf16, 2));
+  EXPECT(cat2.IsSymbol());
+  EXPECT_EQ(cat2.raw(), cat.raw());
 }
 
 
@@ -1552,6 +1653,61 @@
 }
 
 
+TEST_CASE(StringCodePointIterator) {
+  const String& str0 = String::Handle(String::New(""));
+  String::CodePointIterator it0(str0);
+  EXPECT(!it0.Next());
+
+  const String& str1 = String::Handle(String::New(" \xc3\xa7 "));
+  String::CodePointIterator it1(str1);
+  EXPECT(it1.Next());
+  EXPECT_EQ(' ', it1.Current());
+  EXPECT(it1.Next());
+  EXPECT_EQ(0xE7, it1.Current());
+  EXPECT(it1.Next());
+  EXPECT_EQ(' ', it1.Current());
+  EXPECT(!it1.Next());
+
+  const String& str2 = String::Handle(String::New("\xD7\x92\xD7\x9C"
+                                                  "\xD7\xA2\xD7\x93"
+                                                  "\xD7\x91\xD7\xA8"
+                                                  "\xD7\x9B\xD7\x94"));
+  String::CodePointIterator it2(str2);
+  EXPECT(it2.Next());
+  EXPECT_EQ(0x5D2, it2.Current());
+  EXPECT(it2.Next());
+  EXPECT_EQ(0x5DC, it2.Current());
+  EXPECT(it2.Next());
+  EXPECT_EQ(0x5E2, it2.Current());
+  EXPECT(it2.Next());
+  EXPECT_EQ(0x5D3, it2.Current());
+  EXPECT(it2.Next());
+  EXPECT_EQ(0x5D1, it2.Current());
+  EXPECT(it2.Next());
+  EXPECT_EQ(0x5E8, it2.Current());
+  EXPECT(it2.Next());
+  EXPECT_EQ(0x5DB, it2.Current());
+  EXPECT(it2.Next());
+  EXPECT_EQ(0x5D4, it2.Current());
+  EXPECT(!it2.Next());
+
+  const String& str3 = String::Handle(String::New("\xF0\x9D\x91\xA0"
+                                                  "\xF0\x9D\x91\xA1"
+                                                  "\xF0\x9D\x91\xA2"
+                                                  "\xF0\x9D\x91\xA3"));
+  String::CodePointIterator it3(str3);
+  EXPECT(it3.Next());
+  EXPECT_EQ(0x1D460, it3.Current());
+  EXPECT(it3.Next());
+  EXPECT_EQ(0x1D461, it3.Current());
+  EXPECT(it3.Next());
+  EXPECT_EQ(0x1D462, it3.Current());
+  EXPECT(it3.Next());
+  EXPECT_EQ(0x1D463, it3.Current());
+  EXPECT(!it3.Next());
+}
+
+
 TEST_CASE(GrowableObjectArray) {
   const int kArrayLen = 5;
   Smi& value = Smi::Handle();
@@ -3035,6 +3191,64 @@
   EXPECT(weak2.value() == Object::null());
 }
 
+
+static RawFunction* GetFunction(const Class& cls, const char* name) {
+  const Function& result = Function::Handle(cls.LookupDynamicFunction(
+      String::Handle(String::New(name))));
+  ASSERT(!result.IsNull());
+  return result.raw();
+}
+
+
+TEST_CASE(FunctionSourceFingerprint) {
+  const char* kScriptChars =
+      "class A {\n"
+      "  void test1(int a) {\n"
+      "    return a > 1 ? a + 1 : a;\n"
+      "  }\n"
+      "  void test2(int a) {\n"
+      "    return a > 1 ? a + 1 : a;\n"
+      "  }\n"
+      "  void test3(a) {\n"
+      "    return a > 1 ? a + 1 : a;\n"
+      "  }\n"
+      "  void test4(b) {\n"
+      "    return b > 1 ? b + 1 : b;\n"
+      "  }\n"
+      "  void test5(b) {\n"
+      "    return b > 1 ? b - 1 : b;\n"
+      "  }\n"
+      "  void test6(b) {\n"
+      "    return b > 1 ? b - 2 : b;\n"
+      "  }\n"
+      "  void test7(b) {\n"
+      "    return b > 1 ?\n"
+      "        b - 2 : b;\n"
+      "  }\n"
+      "}";
+  TestCase::LoadTestScript(kScriptChars, NULL);
+  EXPECT(ClassFinalizer::FinalizePendingClasses());
+  const String& name = String::Handle(String::New(TestCase::url()));
+  const Library& lib = Library::Handle(Library::LookupLibrary(name));
+  EXPECT(!lib.IsNull());
+
+  const Class& class_a = Class::Handle(
+      lib.LookupClass(String::Handle(Symbols::New("A"))));
+  const Function& test1 = Function::Handle(GetFunction(class_a, "test1"));
+  const Function& test2 = Function::Handle(GetFunction(class_a, "test2"));
+  const Function& test3 = Function::Handle(GetFunction(class_a, "test3"));
+  const Function& test4 = Function::Handle(GetFunction(class_a, "test4"));
+  const Function& test5 = Function::Handle(GetFunction(class_a, "test5"));
+  const Function& test6 = Function::Handle(GetFunction(class_a, "test6"));
+  const Function& test7 = Function::Handle(GetFunction(class_a, "test7"));
+  EXPECT_EQ(test1.SourceFingerprint(), test2.SourceFingerprint());
+  EXPECT_NE(test1.SourceFingerprint(), test3.SourceFingerprint());
+  EXPECT_NE(test3.SourceFingerprint(), test4.SourceFingerprint());
+  EXPECT_NE(test4.SourceFingerprint(), test5.SourceFingerprint());
+  EXPECT_NE(test5.SourceFingerprint(), test6.SourceFingerprint());
+  EXPECT_EQ(test6.SourceFingerprint(), test7.SourceFingerprint());
+}
+
 #endif  // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64).
 
 }  // namespace dart
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 4c9027b..3273891 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -35,6 +35,8 @@
             "Warning on legacy getter syntax");
 DEFINE_FLAG(bool, strict_function_literals, false,
             "enforce new function literal rules");
+DEFINE_FLAG(bool, fail_legacy_abstract, false,
+            "error on explicit use of abstract on class members");
 
 static void CheckedModeHandler(bool value) {
   FLAG_enable_asserts = value;
@@ -2543,7 +2545,8 @@
     const intptr_t type_pos = TokenPos();
     const AbstractType& type = AbstractType::Handle(
         ParseType(ClassFinalizer::kTryResolve));
-    if (type.IsTypeParameter() || type.IsDynamicType()) {
+    if (!type.IsMalformed() &&
+        (type.IsTypeParameter() || type.IsDynamicType())) {
       // Replace the type with a malformed type and compile a throw when called.
       redirection_type = ClassFinalizer::NewFinalizedMalformedType(
           Error::Handle(),  // No previous error.
@@ -2895,6 +2898,9 @@
   current_member_ = &member;
   if ((CurrentToken() == Token::kABSTRACT) &&
       (LookaheadToken(1) != Token::kLPAREN)) {
+    if (FLAG_fail_legacy_abstract) {
+      ErrorMsg("illegal use of abstract");
+    }
     ConsumeToken();
     member.has_abstract = true;
   }
@@ -3736,10 +3742,7 @@
       // Map a malformed type argument to dynamic, so that malformed types with
       // a resolved type class are handled properly in production mode.
       if (type.IsMalformed()) {
-        ASSERT(finalization != ClassFinalizer::kCanonicalizeWellFormed);
-        if (finalization == ClassFinalizer::kCanonicalizeForCreation) {
-          ErrorMsg(*malformed_error);
-        }
+        ASSERT(finalization < ClassFinalizer::kCanonicalizeWellFormed);
         type = Type::DynamicType();
       }
       types.Add(type);
@@ -5035,9 +5038,13 @@
   // class in the current library (but not in its imports) and only create a new
   // canonical signature class if it does not exist yet.
   const String& signature = String::Handle(function.Signature());
-  Class& signature_class = Class::ZoneHandle(
-      library_.LookupLocalClass(signature));
-
+  Class& signature_class = Class::ZoneHandle();
+  if (!is_new_closure) {
+    signature_class = function.signature_class();
+  }
+  if (signature_class.IsNull()) {
+    signature_class = library_.LookupLocalClass(signature);
+  }
   if (signature_class.IsNull()) {
     // If we don't have a signature class yet, this must be a closure we
     // have not parsed before.
@@ -6179,6 +6186,8 @@
     catch_seen = true;
     if (IsLiteral("on")) {
       ConsumeToken();
+      // TODO(regis): The spec may change in the way a malformed 'on' type is
+      // treated. For now, we require the type to be wellformed.
       exception_param.type = &AbstractType::ZoneHandle(
           ParseType(ClassFinalizer::kCanonicalizeWellFormed));
     } else {
@@ -6736,9 +6745,7 @@
 
 
 bool Parser::IsLiteral(const char* literal) {
-  const uint8_t* characters = reinterpret_cast<const uint8_t*>(literal);
-  intptr_t len = strlen(literal);
-  return IsIdentifier() && CurrentLiteral()->Equals(characters, len);
+  return IsIdentifier() && CurrentLiteral()->Equals(literal);
 }
 
 
@@ -6837,8 +6844,8 @@
           op_kind = Token::kISNOT;
         }
         const intptr_t type_pos = TokenPos();
-        const AbstractType& type =
-            AbstractType::ZoneHandle(ParseType(ClassFinalizer::kCanonicalize));
+        const AbstractType& type = AbstractType::ZoneHandle(
+            ParseType(ClassFinalizer::kCanonicalizeExpression));
         if (!type.IsInstantiated() &&
             (current_block_->scope->function_level() > 0)) {
           // Make sure that the instantiator is captured.
@@ -7804,10 +7811,14 @@
       }
       // Resolve classname in the scope of the current library.
       Error& error = Error::Handle();
-      resolved_type_class =
-          ResolveClassInCurrentLibraryScope(unresolved_class.token_pos(),
-                                            unresolved_class_name,
-                                            &error);
+      // If we finalize a type expression, as opposed to a type annotation, we
+      // tell the resolver (by passing NULL) to immediately report an ambiguous
+      // type as a compile time error.
+      resolved_type_class = ResolveClassInCurrentLibraryScope(
+          unresolved_class.token_pos(),
+          unresolved_class_name,
+          finalization >= ClassFinalizer::kCanonicalizeExpression ?
+              NULL : &error);
       if (!error.IsNull()) {
         *type = ClassFinalizer::NewFinalizedMalformedType(
             error,
@@ -7823,11 +7834,15 @@
           LibraryPrefix::Handle(unresolved_class.library_prefix());
       // Resolve class name in the scope of the library prefix.
       Error& error = Error::Handle();
-      resolved_type_class =
-          ResolveClassInPrefixScope(unresolved_class.token_pos(),
-                                    lib_prefix,
-                                    unresolved_class_name,
-                                    &error);
+      // If we finalize a type expression, as opposed to a type annotation, we
+      // tell the resolver (by passing NULL) to immediately report an ambiguous
+      // type as a compile time error.
+      resolved_type_class = ResolveClassInPrefixScope(
+          unresolved_class.token_pos(),
+          lib_prefix,
+          unresolved_class_name,
+          finalization >= ClassFinalizer::kCanonicalizeExpression ?
+              NULL : &error);
       if (!error.IsNull()) {
         *type = ClassFinalizer::NewFinalizedMalformedType(
             error,
@@ -8695,7 +8710,7 @@
   }
   ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1));
   const Class& array_class = Class::Handle(
-      Type::Handle(Type::ArrayType()).type_class());
+      Isolate::Current()->object_store()->array_class());
   Type& type = Type::ZoneHandle(
       Type::New(array_class, type_arguments, type_pos));
   type ^= ClassFinalizer::FinalizeType(
@@ -8763,9 +8778,7 @@
     return new LiteralNode(literal_pos, const_list);
   } else {
     // Factory call at runtime.
-    // TODO(regis): Once _ListImpl is removed, use Symbols::List() instead of
-    // Symbols::ListImplementation() on the following line.
-    String& factory_class_name = String::Handle(Symbols::ListImplementation());
+    String& factory_class_name = String::Handle(Symbols::List());
     const Class& factory_class =
         Class::Handle(LookupCoreClass(factory_class_name));
     ASSERT(!factory_class.IsNull());
@@ -9100,11 +9113,10 @@
   }
   intptr_t type_pos = TokenPos();
   AbstractType& type = AbstractType::Handle(
-      ParseType(ClassFinalizer::kCanonicalizeForCreation));
+      ParseType(ClassFinalizer::kCanonicalizeExpression));
   // In case the type is malformed, throw a dynamic type error after finishing
   // parsing the instance creation expression.
-  if (type.IsTypeParameter() || type.IsDynamicType()) {
-    ASSERT(!type.IsMalformed());
+  if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) {
     // Replace the type with a malformed type.
     type = ClassFinalizer::NewFinalizedMalformedType(
         Error::Handle(),  // No previous error.
diff --git a/runtime/vm/random.cc b/runtime/vm/random.cc
deleted file mode 100644
index ef2455c..0000000
--- a/runtime/vm/random.cc
+++ /dev/null
@@ -1,28 +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.
-
-#include "vm/random.h"
-
-#include "platform/assert.h"
-#include "vm/isolate.h"
-
-namespace dart {
-
-// LSFR step with a period of 31-bits.
-// Based on http://en.wikipedia.org/wiki/Linear_feedback_shift_register
-static int32_t LinearFeedbackShiftRegisterStep(int32_t seed) {
-  return (seed >> 1) ^ ((-(seed & 1)) & (1 << 30 | 1 << 27));
-}
-
-
-int32_t Random::RandomInt32() {
-  Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != NULL);
-  int32_t result = isolate->random_seed();
-  int32_t new_random_seed = LinearFeedbackShiftRegisterStep(result);
-  isolate->set_random_seed(new_random_seed);
-  return result;
-}
-
-}  // namespace dart
diff --git a/runtime/vm/random.h b/runtime/vm/random.h
deleted file mode 100644
index ca1d039..0000000
--- a/runtime/vm/random.h
+++ /dev/null
@@ -1,23 +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.
-
-#ifndef VM_RANDOM_H_
-#define VM_RANDOM_H_
-
-#include "vm/allocation.h"
-
-namespace dart {
-
-class Random : public AllStatic {
- public:
-  static const int32_t kDefaultRandomSeed = 294967;
-
-  // Generate a random number in the range [1, 2^31[ (will never return 0 or a
-  // negative number). Not cryptographically safe.
-  static int32_t RandomInt32();
-};
-
-}  // namespace dart
-
-#endif  // VM_RANDOM_H_
diff --git a/runtime/vm/random_test.cc b/runtime/vm/random_test.cc
deleted file mode 100644
index 2b7f726..0000000
--- a/runtime/vm/random_test.cc
+++ /dev/null
@@ -1,16 +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.
-
-#include "platform/assert.h"
-#include "vm/globals.h"
-#include "vm/random.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-TEST_CASE(Random) {
-  EXPECT(Random::RandomInt32() != 0);
-}
-
-}  // namespace dart
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index a29c3ae..a99dde7 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -350,10 +350,9 @@
   static bool IsByteArrayClassId(intptr_t index);
   static bool IsExternalByteArrayClassId(intptr_t index);
 
- protected:
+ private:
   uword tags_;  // Various object tags (bits).
 
- private:
   class FreeBit : public BitField<bool, kFreeBit, 1> {};
 
   class MarkBit : public BitField<bool, kMarkBit, 1> {};
@@ -745,9 +744,9 @@
   RawPcDescriptors* pc_descriptors_;
   RawArray* deopt_info_array_;
   RawArray* object_table_;
+  RawArray* static_calls_target_table_;  // (code-offset, function, code).
   RawArray* stackmaps_;
   RawLocalVarDescriptors* var_descriptors_;
-  RawGrowableObjectArray* resolved_static_calls_;
   RawArray* comments_;
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->comments_);
@@ -1364,6 +1363,10 @@
     return peer_;
   }
 
+  static intptr_t data_offset() {
+    return OFFSET_OF(ExternalByteArrayData<T>, data_);
+  }
+
  private:
   T* data_;
   void* peer_;
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index 229dfdf..26920c6 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -11,6 +11,7 @@
 #include "vm/symbols.h"
 #include "vm/thread.h"
 #include "vm/token.h"
+#include "vm/unicode.h"
 
 namespace dart {
 
@@ -174,6 +175,36 @@
 }
 
 
+// This method is used when parsing integers and doubles in Dart code. We
+// are reusing the Scanner's handling of number literals in that situation.
+bool Scanner::IsValidLiteral(const Scanner::GrowableTokenStream& tokens,
+                             Token::Kind literal_kind,
+                             bool* is_positive,
+                             String** value) {
+  if ((tokens.length() == 2) &&
+      (tokens[0].kind == literal_kind) &&
+      (tokens[1].kind == Token::kEOS)) {
+    *is_positive = true;
+    *value = tokens[0].literal;
+    return true;
+  }
+  if ((tokens.length() == 3) &&
+      ((tokens[0].kind == Token::kTIGHTADD) ||
+       (tokens[0].kind == Token::kSUB)) &&
+      (tokens[1].kind == literal_kind) &&
+      (tokens[2].kind == Token::kEOS)) {
+    // Check there is no space between "+/-" and number.
+    if ((tokens[0].offset + 1) != tokens[1].offset) {
+      return false;
+    }
+    *is_positive = tokens[0].kind == Token::kTIGHTADD;
+    *value = tokens[1].literal;
+    return true;
+  }
+  return false;
+}
+
+
 void Scanner::ReadChar() {
   if (lookahead_pos_ < source_length_) {
     if (c0_ == '\n') {
@@ -438,7 +469,7 @@
 }
 
 
-bool Scanner::ScanHexDigits(int digits, uint32_t* value) {
+bool Scanner::ScanHexDigits(int digits, int32_t* value) {
   *value = 0;
   for (int i = 0; i < digits; ++i) {
     ReadChar();
@@ -453,7 +484,7 @@
 }
 
 
-bool Scanner::ScanHexDigits(int min_digits, int max_digits, uint32_t* value) {
+bool Scanner::ScanHexDigits(int min_digits, int max_digits, int32_t* value) {
   *value = 0;
   ReadChar();
   for (int i = 0; i < max_digits; ++i) {
@@ -472,7 +503,7 @@
 }
 
 
-void Scanner::ScanEscapedCodePoint(uint32_t* code_point) {
+void Scanner::ScanEscapedCodePoint(int32_t* code_point) {
   ASSERT(c0_ == 'u' || c0_ == 'x');
   bool is_valid;
   if (c0_ == 'x') {
@@ -498,7 +529,7 @@
 
 
 void Scanner::ScanLiteralStringChars(bool is_raw) {
-  GrowableArray<uint32_t> string_chars(64);
+  GrowableArray<int32_t> string_chars(64);
 
   ASSERT(IsScanningString());
   // We are at the first character of a string literal piece. A string literal
@@ -511,7 +542,7 @@
     }
     if (c0_ == '\\' && !is_raw) {
       // Parse escape sequence.
-      uint32_t escape_char = '\0';
+      int32_t escape_char = '\0';
       ReadChar();
       switch (c0_) {
         case 'n':
@@ -852,8 +883,11 @@
           ScanNumber(false);
         } else {
           char msg[128];
+          char utf8_char[5];
+          int len = Utf8::Encode(c0_, utf8_char);
+          utf8_char[len] = '\0';
           OS::SNPrint(msg, sizeof(msg),
-                      "unexpected character: %c  (%02x)\n", c0_, c0_);
+                      "unexpected character: '%s' (U+%04X)\n", utf8_char, c0_);
           ErrorMsg(msg);
           ReadChar();
         }
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
index 5700475..5f1f75e 100644
--- a/runtime/vm/scanner.h
+++ b/runtime/vm/scanner.h
@@ -96,6 +96,13 @@
   // Return true if str is an identifier.
   static bool IsIdent(const String& str);
 
+  // Does the token stream contain a valid literal. This is used to implement
+  // the Dart methods int.parse and double.parse.
+  static bool IsValidLiteral(const Scanner::GrowableTokenStream& tokens,
+                             Token::Kind literal_kind,
+                             bool* is_positive,
+                             String** value);
+
  private:
   struct ScanContext {
     ScanContext* next;
@@ -171,13 +178,13 @@
   void ScanLiteralStringChars(bool is_raw);
 
   // Reads a fixed number of hexadecimal digits.
-  bool ScanHexDigits(int digits, uint32_t* value);
+  bool ScanHexDigits(int digits, int32_t* value);
 
   // Reads a variable number of hexadecimal digits.
-  bool ScanHexDigits(int min_digits, int max_digits, uint32_t* value);
+  bool ScanHexDigits(int min_digits, int max_digits, int32_t* value);
 
   // Reads an escaped code point from within a string literal.
-  void ScanEscapedCodePoint(uint32_t* escaped_char);
+  void ScanEscapedCodePoint(int32_t* escaped_char);
 
   // Reads identifier.
   RawString* ConsumeIdentChars(bool allow_dollar);
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index c11e321..044d34b 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -818,7 +818,7 @@
   if (class_id >= kNumPredefinedCids) {
     if (Class::IsSignatureClass(cls)) {
       // We do not allow closure objects in an isolate message.
-      set_exception_type(Exceptions::kArgumentError);
+      set_exception_type(Exceptions::kArgument);
       // TODO(6726): Allocate these constant strings once in the VM isolate.
       set_exception_msg("Illegal argument in isolate message"
                         " : (object is a closure)");
@@ -1073,7 +1073,7 @@
   if (class_id >= kNumPredefinedCids) {
     if (Class::IsSignatureClass(cls)) {
       // We do not allow closure objects in an isolate message.
-      set_exception_type(Exceptions::kArgumentError);
+      set_exception_type(Exceptions::kArgument);
       // TODO(6726): Allocate these constant strings once in the VM isolate.
       set_exception_msg("Illegal argument in isolate message"
                         " : (object is a closure)");
@@ -1081,7 +1081,7 @@
     }
     if (cls->ptr()->num_native_fields_ != 0) {
       // We do not allow objects with native fields in an isolate message.
-      set_exception_type(Exceptions::kArgumentError);
+      set_exception_type(Exceptions::kArgument);
       // TODO(6726): Allocate these constant strings once in the VM isolate.
       set_exception_msg("Illegal argument in isolate message"
                         " : (object extends NativeWrapper)");
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 083b28f..07326ae 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -528,13 +528,13 @@
 TEST_CASE(SerializeString) {
   TestString("This string shall be serialized");
   TestString("æøå");  // This file is UTF-8 encoded.
-  char data[] = {0x01,
-                 0x7f,
-                 0xc2, 0x80,         // 0x80
-                 0xdf, 0xbf,         // 0x7ff
-                 0xe0, 0xa0, 0x80,   // 0x800
-                 0xef, 0xbf, 0xbf,   // 0xffff
-                 0x00};              // String termination.
+  const char* data = "\x01"
+                     "\x7F"
+                     "\xC2\x80"       // U+0080
+                     "\xDF\xBF"       // U+07FF
+                     "\xE0\xA0\x80"   // U+0800
+                     "\xEF\xBF\xBF";  // U+FFFF
+
   TestString(data);
   // TODO(sgjesse): Add tests with non-BMP characters.
 }
@@ -1030,7 +1030,7 @@
 
 UNIT_TEST_CASE(ScriptSnapshot) {
   const char* kLibScriptChars =
-      "#library('dart:import-lib');"
+      "library dart_import_lib;"
       "class LibFields  {"
       "  LibFields(int i, int j) : fld1 = i, fld2 = j {}"
       "  int fld1;"
@@ -1095,7 +1095,7 @@
     Dart_EnterScope();  // Start a Dart API scope for invoking API functions.
 
     // Load the library.
-    Dart_Handle import_lib = Dart_LoadLibrary(NewString("dart:import-lib"),
+    Dart_Handle import_lib = Dart_LoadLibrary(NewString("dart_import_lib"),
                                               NewString(kLibScriptChars));
     EXPECT_VALID(import_lib);
 
@@ -1701,7 +1701,7 @@
 UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
   const int kArrayLength = 10;
   static const char* kScriptChars =
-      "#import('dart:scalarlist');\n"
+      "import 'dart:scalarlist';\n"
       "final int kArrayLength = 10;\n"
       "getStringList() {\n"
       "  var s = 'Hello, world!';\n"
@@ -1872,7 +1872,7 @@
 UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
   const int kArrayLength = 10;
   static const char* kScriptChars =
-      "#import('dart:scalarlist');\n"
+      "import 'dart:scalarlist';\n"
       "final int kArrayLength = 10;\n"
       "getStringList() {\n"
       "  var s = 'Hello, world!';\n"
@@ -1911,7 +1911,7 @@
       "getMixedList() {\n"
       "  var list = [];\n"
       "  for (var i = 0; i < kArrayLength; i++) {\n"
-      "    list.add(((i % 2) == 0) ? 'A' : 2.72);\n"
+      "    list.add(((i % 2) == 0) ? '.' : 2.72);\n"
       "  }\n"
       "  return list;\n"
       "}\n"
@@ -2017,7 +2017,7 @@
         if ((i % 2) == 0) {
           EXPECT_EQ(root->value.as_array.values[0], element);
           EXPECT_EQ(Dart_CObject::kString, element->type);
-          EXPECT_STREQ("A", element->value.as_string);
+          EXPECT_STREQ(".", element->value.as_string);
         } else {
           EXPECT_EQ(root->value.as_array.values[1], element);
           EXPECT_EQ(Dart_CObject::kDouble, element->type);
@@ -2048,7 +2048,7 @@
   // Create a native port for posting from C to Dart
   TestIsolateScope __test_isolate__;
   const char* kScriptChars =
-      "#import('dart:isolate');\n"
+      "import 'dart:isolate';\n"
       "main() {\n"
       "  var messageCount = 0;\n"
       "  var exception = '';\n"
@@ -2107,7 +2107,7 @@
   EXPECT(Dart_PostCObject(send_port_id, &object));
 
   // Try to post an invalid UTF-8 sequence (lead surrogate).
-  char data[] = {0xed, 0xa0, 0x80, 0};  // 0xd800
+  const char* data = "\xED\xA0\x80";  // U+D800
   object.type = Dart_CObject::kString;
   object.value.as_string = const_cast<char*>(data);
   EXPECT(!Dart_PostCObject(send_port_id, &object));
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 79badc1..f354cab 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -183,48 +183,19 @@
 
 
 // Input parameters:
-//   ECX: function object.
 //   EDX: arguments descriptor array (num_args is first Smi element).
 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
   const Immediate raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
-
-  __ movl(EAX, FieldAddress(ECX, Function::code_offset()));
-  __ cmpl(EAX, raw_null);
-  Label function_compiled;
-  __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump);
-
-  // Create a stub frame as we are pushing some objects on the stack before
-  // calling into the runtime.
   AssemblerMacros::EnterStubFrame(assembler);
-
   __ pushl(EDX);  // Preserve arguments descriptor array.
-  __ pushl(ECX);
-  __ CallRuntime(kCompileFunctionRuntimeEntry);
-  __ popl(ECX);  // Restore read-only function object argument in ECX.
-  __ popl(EDX);  // Restore arguments descriptor array.
-  // Restore EAX.
-  __ movl(EAX, FieldAddress(ECX, Function::code_offset()));
-
-  // Remove the stub frame as we are about to jump to the dart function.
-  __ LeaveFrame();
-
-  __ Bind(&function_compiled);
-  // Patch caller.
-
-  // Create a stub frame as we are pushing some objects on the stack before
-  // calling into the runtime.
-  AssemblerMacros::EnterStubFrame(assembler);
-
-  __ pushl(EDX);  // Preserve arguments descriptor array.
-  __ pushl(ECX);  // Preserve function object.
+  __ pushl(raw_null);  // Setup space on stack for return value.
   __ CallRuntime(kPatchStaticCallRuntimeEntry);
-  __ popl(ECX);  // Restore function object argument in ECX.
+  __ popl(EAX);  // Get Code object result.
   __ popl(EDX);  // Restore arguments descriptor array.
   // Remove the stub frame as we are about to jump to the dart function.
   __ LeaveFrame();
 
-  __ movl(EAX, FieldAddress(ECX, Function::code_offset()));
   __ movl(ECX, FieldAddress(EAX, Code::instructions_offset()));
   __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(ECX);
@@ -233,20 +204,18 @@
 
 // Called from a static call only when an invalid code has been entered
 // (invalid because its function was optimized or deoptimized).
-// ECX: function object.
 // EDX: arguments descriptor array (num_args is first Smi element).
 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
+  const Immediate raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   AssemblerMacros::EnterStubFrame(assembler);
   __ pushl(EDX);  // Preserve arguments descriptor array.
-  __ pushl(ECX);  // Preserve target function.
-  __ pushl(ECX);  // Target function.
+  __ pushl(raw_null);  // Setup space on stack for return value.
   __ CallRuntime(kFixCallersTargetRuntimeEntry);
-  __ popl(EAX);  // discard argument.
-  __ popl(EAX);  // Restore function.
+  __ popl(EAX);  // Get Code object.
   __ popl(EDX);  // Restore arguments descriptor array.
-  __ movl(EAX, FieldAddress(EAX, Function::code_offset()));
   __ movl(EAX, FieldAddress(EAX, Code::instructions_offset()));
   __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ LeaveFrame();
@@ -1816,23 +1785,23 @@
 }
 
 
-//  ECX: Function object.
 //  EDX: Arguments array.
 //  TOS(0): return address (Dart code).
 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   AssemblerMacros::EnterStubFrame(assembler);
-  __ pushl(EDX);
-  __ pushl(ECX);
+  __ pushl(EDX);  // Preserve arguments descriptor.
+  const Immediate raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  __ pushl(raw_null);  // Room for result.
   __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
-  __ popl(ECX);
-  __ popl(EDX);
+  __ popl(EAX);  // Code object.
+  __ popl(EDX);  // Restore arguments descriptor.
   __ LeaveFrame();
 
   // Now call the static function. The breakpoint handler function
   // ensures that the call target is compiled.
-  __ movl(EAX, FieldAddress(ECX, Function::code_offset()));
   __ movl(ECX, FieldAddress(EAX, Code::instructions_offset()));
   __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(ECX);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 5048aa5..65ea307 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -182,44 +182,18 @@
 
 
 // Input parameters:
-//   RBX: function object.
 //   R10: arguments descriptor array (num_args is first Smi element).
 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
   const Immediate raw_null =
       Immediate(reinterpret_cast<intptr_t>(Object::null()));
-
-  __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
-  __ cmpq(RAX, raw_null);
-  Label function_compiled;
-  __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump);
-
-  // Create a stub frame as we are pushing some objects on the stack before
-  // calling into the runtime.
   AssemblerMacros::EnterStubFrame(assembler);
-
   __ pushq(R10);  // Preserve arguments descriptor array.
-  __ pushq(RBX);
-  __ CallRuntime(kCompileFunctionRuntimeEntry);
-  __ popq(RBX);  // Restore read-only function object argument in RBX.
-  __ popq(R10);  // Restore arguments descriptor array.
-  // Restore RAX.
-  __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
-
-  // Remove the stub frame as we are about to jump to the dart function.
-  __ LeaveFrame();
-
-  __ Bind(&function_compiled);
-  // Patch caller.
-  AssemblerMacros::EnterStubFrame(assembler);
-
-  __ pushq(R10);  // Preserve arguments descriptor array.
-  __ pushq(RBX);  // Preserve function object.
+  __ pushq(raw_null);  // Setup space on stack for return value.
   __ CallRuntime(kPatchStaticCallRuntimeEntry);
-  __ popq(RBX);  // Restore function object argument in RBX.
+  __ popq(RAX);  // Get Code object result.
   __ popq(R10);  // Restore arguments descriptor array.
   // Remove the stub frame as we are about to jump to the dart function.
   __ LeaveFrame();
-  __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
 
   __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
   __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
@@ -229,18 +203,16 @@
 
 // Called from a static call only when an invalid code has been entered
 // (invalid because its function was optimized or deoptimized).
-// RBX: function object.
 // R10: arguments descriptor array (num_args is first Smi element).
 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
+  const Immediate raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   AssemblerMacros::EnterStubFrame(assembler);
   __ pushq(R10);  // Preserve arguments descriptor array.
-  __ pushq(RBX);  // Preserve target function.
-  __ pushq(RBX);  // Target function.
+  __ pushq(raw_null);  // Setup space on stack for return value.
   __ CallRuntime(kFixCallersTargetRuntimeEntry);
-  __ popq(RAX);  // discard argument.
-  __ popq(RAX);  // Restore function.
+  __ popq(RAX);  // Get Code object.
   __ popq(R10);  // Restore arguments descriptor array.
-  __ movq(RAX, FieldAddress(RAX, Function::code_offset()));
   __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
   __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ LeaveFrame();
@@ -1787,21 +1759,21 @@
   GenerateNArgsCheckInlineCacheStub(assembler, 1);
 }
 
-//  RBX: Function object.
 //  R10: Arguments array.
 //  TOS(0): return address (Dart code).
 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
+  const Immediate raw_null =
+      Immediate(reinterpret_cast<intptr_t>(Object::null()));
   AssemblerMacros::EnterStubFrame(assembler);
-  __ pushq(R10);
-  __ pushq(RBX);
+  __ pushq(R10);  // Preserve arguments descriptor.
+  __ pushq(raw_null);  // Room for result.
   __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
-  __ popq(RBX);
-  __ popq(R10);
+  __ popq(RAX);  // Code object.
+  __ popq(R10);  // Restore arguments descriptor.
   __ LeaveFrame();
 
   // Now call the static function. The breakpoint handler function
   // ensures that the call target is compiled.
-  __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
   __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
   __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
   __ jmp(RBX);
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 33c0ac6..c7da37c 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -26,8 +26,8 @@
 };
 
 
-const char* Symbols::Name(intptr_t symbol) {
-  ASSERT((symbol > kIllegal) && (symbol < kMaxId));
+const char* Symbols::Name(SymbolId symbol) {
+  ASSERT((symbol > kIllegal) && (symbol < kMaxPredefinedId));
   return names[symbol];
 }
 
@@ -40,12 +40,12 @@
   SetupSymbolTable(isolate);
 
   // Create all predefined symbols.
-  ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kMaxId);
+  ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kMaxPredefinedId);
   ObjectStore* object_store = isolate->object_store();
   Array& symbol_table = Array::Handle();
   dart::String& str = String::Handle();
 
-  for (intptr_t i = 1; i < Symbols::kMaxId; i++) {
+  for (intptr_t i = 1; i < Symbols::kMaxPredefinedId; i++) {
     // The symbol_table needs to be reloaded as it might have grown in the
     // previous iteration.
     symbol_table = object_store->symbol_table();
@@ -54,6 +54,11 @@
     predefined_[i] = str.raw();
   }
   Object::RegisterSingletonClassNames();
+
+  for (int32_t c = 0; c <= kMaxOneCharCodeSymbol; c++) {
+    ASSERT(kMaxPredefinedId + c < kMaxId);
+    predefined_[kMaxPredefinedId + c] = New(&c, 1);
+  }
 }
 
 
@@ -107,7 +112,7 @@
     Utf8::DecodeToLatin1(utf8_array, str_len, characters, len);
     return New(characters, len);
   }
-  ASSERT((type == Utf8::kBMP) || (type == Utf8::kSMP));
+  ASSERT((type == Utf8::kBMP) || (type == Utf8::kSupplementary));
   uint16_t* characters = zone->Alloc<uint16_t>(len);
   Utf8::DecodeToUTF16(utf8_array, str_len, characters, len);
   return New(characters, len);
@@ -117,7 +122,6 @@
 template<typename T>
 RawString* Symbols::New(const T* characters, intptr_t len) {
   Isolate* isolate = Isolate::Current();
-  ASSERT(isolate != Dart::vm_isolate());
   String& symbol = String::Handle(isolate, String::null());
   Array& symbol_table = Array::Handle(isolate, Array::null());
 
@@ -148,7 +152,7 @@
 
 template RawString* Symbols::New(const uint8_t* characters, intptr_t len);
 template RawString* Symbols::New(const uint16_t* characters, intptr_t len);
-template RawString* Symbols::New(const uint32_t* characters, intptr_t len);
+template RawString* Symbols::New(const int32_t* characters, intptr_t len);
 
 
 RawString* Symbols::New(const String& str) {
@@ -200,6 +204,14 @@
 }
 
 
+RawString* Symbols::FromCharCode(int32_t char_code) {
+  if (char_code > kMaxOneCharCodeSymbol) {
+    return New(&char_code, 1);
+  }
+  return predefined_[kNullCharId + char_code];
+}
+
+
 void Symbols::GrowSymbolTable(const Array& symbol_table) {
   // TODO(iposva): Avoid exponential growth.
   intptr_t table_size = symbol_table.Length() - 1;
@@ -277,7 +289,7 @@
                                      intptr_t len,
                                      intptr_t hash);
 template intptr_t Symbols::FindIndex(const Array& symbol_table,
-                                     const uint32_t* characters,
+                                     const int32_t* characters,
                                      intptr_t len,
                                      intptr_t hash);
 
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 16c1fd4..0e6cc21 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -42,8 +42,8 @@
     "AbstractClassInstantiationErrorImplementation")                           \
   V(NoSuchMethodError, "NoSuchMethodErrorImplementation")                      \
   V(ThrowNew, "_throwNew")                                                     \
+  V(List, "List")                                                              \
   V(ListLiteralFactory, "List._fromLiteral")                                   \
-  V(ListImplementation, "_ListImpl")                                           \
   V(ListFactory, "List.")                                                      \
   V(MapImplementation, "_HashMapImpl")                                         \
   V(MapLiteralFactory, "Map._fromLiteral")                                     \
@@ -146,16 +146,19 @@
 // without having to maintain copies in each isolate.
 class Symbols : public AllStatic {
  public:
+  enum { kMaxOneCharCodeSymbol = 0xFF };
+
   // List of strings that are pre created in the vm isolate.
-  enum {
+  enum SymbolId {
     kIllegal = 0,
 
 #define DEFINE_SYMBOL_INDEX(symbol, literal)                                   \
     k##symbol,
 PREDEFINED_SYMBOLS_LIST(DEFINE_SYMBOL_INDEX)
 #undef DEFINE_SYMBOL_INDEX
-
-    kMaxId,
+    kMaxPredefinedId,
+    kNullCharId = kMaxPredefinedId,
+    kMaxId = kNullCharId + kMaxOneCharCodeSymbol + 1,
   };
 
   // Access methods for symbols stored in the vm isolate.
@@ -183,11 +186,17 @@
                         intptr_t length);
 
   // Returns char* of predefined symbol.
-  static const char* Name(intptr_t symbol);
+  static const char* Name(SymbolId symbol);
+
+  static RawString* FromCharCode(int32_t char_code);
+
+  static RawString** PredefinedAddress() {
+    return reinterpret_cast<RawString**>(&predefined_);
+  }
 
  private:
   enum {
-    kInitialVMIsolateSymtabSize = ((Symbols::kMaxId + 15) & -16),
+    kInitialVMIsolateSymtabSize = ((kMaxId + 15) & -16),
     kInitialSymtabSize = 256
   };
 
@@ -218,11 +227,11 @@
   static RawObject* GetVMSymbol(intptr_t object_id);
   static bool IsVMSymbolId(intptr_t object_id) {
     return (object_id >= kMaxPredefinedObjectIds &&
-            object_id < (kMaxPredefinedObjectIds + Symbols::kMaxId));
+            object_id < (kMaxPredefinedObjectIds + kMaxId));
   }
 
   // List of symbols that are stored in the vm isolate for easy access.
-  static RawString* predefined_[Symbols::kMaxId];
+  static RawString* predefined_[kMaxId];
 
   friend class SnapshotReader;
   friend class SnapshotWriter;
diff --git a/runtime/vm/unicode.cc b/runtime/vm/unicode.cc
index e2e741d8..3129a06 100644
--- a/runtime/vm/unicode.cc
+++ b/runtime/vm/unicode.cc
@@ -64,18 +64,12 @@
 }
 
 
-static bool IsSmpSequenceStart(uint8_t code_unit) {
+static bool IsSupplementarySequenceStart(uint8_t code_unit) {
   // Check is codepoint is >= U+10000.
   return (code_unit >= 0xF0);
 }
 
 
-// Returns true if the code point is a high- or low-surrogate.
-static bool IsSurrogate(uint32_t code_point) {
-  return (code_point & 0xfffff800) == 0xd800;
-}
-
-
 // Returns true if the code point value is above Plane 17.
 static bool IsOutOfRange(uint32_t code_point) {
   return (code_point > 0x10FFFF);
@@ -88,14 +82,6 @@
 }
 
 
-void Utf8::ConvertUTF32ToUTF16(int32_t codepoint, uint16_t* dst) {
-  ASSERT(codepoint > kMaxBmpCodepoint);
-  ASSERT(dst != NULL);
-  dst[0] = (Utf8::kLeadOffset + (codepoint >> 10));
-  dst[1] = (0xDC00 + (codepoint & 0x3FF));
-}
-
-
 // Returns a count of the number of UTF-8 trail bytes.
 intptr_t Utf8::CodePointCount(const uint8_t* utf8_array,
                               intptr_t array_len,
@@ -108,8 +94,8 @@
       ++len;
     }
     if (!IsLatin1SequenceStart(code_unit)) {  // > U+00FF
-      if (IsSmpSequenceStart(code_unit)) {  // >= U+10000
-        char_type = kSMP;
+      if (IsSupplementarySequenceStart(code_unit)) {  // >= U+10000
+        char_type = kSupplementary;
         ++len;
       } else if (char_type == kLatin1) {
         char_type = kBMP;
@@ -144,7 +130,7 @@
             (j == num_trail_bytes) &&
             !IsOutOfRange(ch) &&
             !IsNonShortestForm(ch, j) &&
-            !IsSurrogate(ch))) {
+            !Utf16::IsSurrogate(ch))) {
         return false;
       }
     }
@@ -169,8 +155,9 @@
 
 intptr_t Utf8::Length(const String& str) {
   intptr_t length = 0;
-  for (intptr_t i = 0; i < str.Length(); ++i) {
-    int32_t ch = str.CharAt(i);
+  String::CodePointIterator it(str);
+  while (it.Next()) {
+    int32_t ch = it.Current();
     length += Utf8::Length(ch);
   }
   return length;
@@ -205,8 +192,9 @@
 
 intptr_t Utf8::Encode(const String& src, char* dst, intptr_t len) {
   intptr_t pos = 0;
-  for (intptr_t i = 0; i < src.Length(); ++i) {
-    intptr_t ch = src.CharAt(i);
+  String::CodePointIterator it(src);
+  while (it.Next()) {
+    int32_t ch = it.Current();
     intptr_t num_bytes = Utf8::Length(ch);
     if (pos + num_bytes > len) {
       break;
@@ -224,7 +212,7 @@
   uint32_t ch = utf8_array[0] & 0xFF;
   intptr_t i = 1;
   if (ch >= 0x80) {
-    int32_t num_trail_bytes = kTrailBytes[ch];
+    intptr_t num_trail_bytes = kTrailBytes[ch];
     bool is_malformed = false;
     for (; i < num_trail_bytes; ++i) {
       if (i < array_len) {
@@ -241,7 +229,7 @@
           (i == num_trail_bytes) &&
           !IsOutOfRange(ch) &&
           !IsNonShortestForm(ch, i) &&
-          !IsSurrogate(ch))) {
+          !Utf16::IsSurrogate(ch))) {
       *dst = -1;
       return 0;
     }
@@ -284,13 +272,13 @@
   intptr_t num_bytes;
   for (; (i < array_len) && (j < len); i += num_bytes, ++j) {
     int32_t ch;
-    bool is_smp = IsSmpSequenceStart(utf8_array[i]);
+    bool is_supplementary = IsSupplementarySequenceStart(utf8_array[i]);
     num_bytes = Utf8::Decode(&utf8_array[i], (array_len - i), &ch);
     if (ch == -1) {
       return false;  // invalid input
     }
-    if (is_smp) {
-      ConvertUTF32ToUTF16(ch, &(dst[j]));
+    if (is_supplementary) {
+      Utf16::Encode(ch, &dst[j]);
       j = j + 1;
     } else {
       dst[j] = ch;
@@ -305,7 +293,7 @@
 
 bool Utf8::DecodeToUTF32(const uint8_t* utf8_array,
                          intptr_t array_len,
-                         uint32_t* dst,
+                         int32_t* dst,
                          intptr_t len) {
   intptr_t i = 0;
   intptr_t j = 0;
@@ -324,4 +312,12 @@
   return true;  // success
 }
 
+
+void Utf16::Encode(int32_t codepoint, uint16_t* dst) {
+  ASSERT(codepoint > kMaxBmpCodepoint);
+  ASSERT(dst != NULL);
+  dst[0] = (Utf16::kLeadSurrogateOffset + (codepoint >> 10));
+  dst[1] = (0xDC00 + (codepoint & 0x3FF));
+}
+
 }  // namespace dart
diff --git a/runtime/vm/unicode.h b/runtime/vm/unicode.h
index 28beaad..03a4b29 100644
--- a/runtime/vm/unicode.h
+++ b/runtime/vm/unicode.h
@@ -15,20 +15,16 @@
 class Utf8 : AllStatic {
  public:
   enum Type {
-    kLatin1 = 0,  // Latin-1 character set.
-    kBMP,  // Basic Multilingual Plane.
-    kSMP,  // Supplementary Multilingual Plane.
+    kLatin1 = 0,  // Latin-1 code point [U+0000, U+00FF].
+    kBMP,  // Basic Multilingual Plane code point [U+0000, U+FFFF].
+    kSupplementary,  // Supplementary code point [U+010000, U+10FFFF].
   };
 
   static const intptr_t kMaxOneByteChar   = 0x7F;
   static const intptr_t kMaxTwoByteChar   = 0x7FF;
   static const intptr_t kMaxThreeByteChar = 0xFFFF;
   static const intptr_t kMaxFourByteChar  = 0x10FFFF;
-  static const intptr_t kMaxBmpCodepoint  = 0xffff;
-  static const int32_t kLeadOffset = (0xD800 - (0x10000 >> 10));
-  static const int32_t kSurrogateOffset = (0x10000 - (0xD800 << 10) - 0xDC00);
 
-  static void ConvertUTF32ToUTF16(int32_t codepoint, uint16_t* dst);
   static intptr_t CodePointCount(const uint8_t* utf8_array,
                                  intptr_t array_len,
                                  Type* type);
@@ -56,10 +52,10 @@
                             intptr_t len);
   static bool DecodeToUTF32(const uint8_t* utf8_array,
                             intptr_t array_len,
-                            uint32_t* dst,
+                            int32_t* dst,
                             intptr_t len);
   static bool DecodeCStringToUTF32(const char* str,
-                                   uint32_t* dst,
+                                   int32_t* dst,
                                    intptr_t len) {
     ASSERT(str != NULL);
     intptr_t array_len = strlen(str);
@@ -69,6 +65,44 @@
 };
 
 
+class Utf16 : AllStatic {
+ public:
+  static const int32_t kMaxBmpCodepoint  = 0xFFFF;
+
+  static const int32_t kLeadSurrogateOffset = (0xD800 - (0x10000 >> 10));
+
+  static const int32_t kSurrogateOffset = (0x10000 - (0xD800 << 10) - 0xDC00);
+
+  // Returns the length of the code point in UTF-16 code units.
+  static intptr_t Length(int32_t ch) {
+    return (ch <= kMaxBmpCodepoint) ? 1 : 2;
+  }
+
+  // Returns true if ch is a lead or trail surrogate.
+  static bool IsSurrogate(int32_t ch) {
+    return (ch & 0xFFFFF800) == 0xD800;
+  }
+
+  // Returns true if ch is a lead surrogate.
+  static bool IsLeadSurrogate(int32_t ch) {
+    return (ch & 0xFFFFFC00) == 0xD800;
+  }
+
+  // Returns true if ch is a low surrogate.
+  static bool IsTrailSurrogate(int32_t ch) {
+    return (ch & 0xFFFFFC00) == 0xDC00;
+  }
+
+  // Decodes a surrogate pair into a supplementary code point.
+  static int32_t Decode(int32_t lead, int32_t trail) {
+    return 0x10000 + ((lead & 0x3FF) << 10) + (trail & 0x3FF);
+  }
+
+  // Encodes a single code point.
+  static void Encode(int32_t codepoint, uint16_t* dst);
+};
+
+
 class CaseMapping : AllStatic {
  public:
   // Maps a code point to uppercase.
diff --git a/runtime/vm/unicode_test.cc b/runtime/vm/unicode_test.cc
index 967e9ca..582a2a6 100644
--- a/runtime/vm/unicode_test.cc
+++ b/runtime/vm/unicode_test.cc
@@ -12,8 +12,8 @@
   // Examples from the Unicode specification, chapter 3
   {
     const char* src = "\x41\xC3\xB1\x42";
-    uint32_t expected[] = { 0x41, 0xF1, 0x42 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x41, 0xF1, 0x42 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -22,8 +22,8 @@
 
   {
     const char* src = "\x4D";
-    uint32_t expected[] = { 0x4D };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x4D };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -32,8 +32,8 @@
 
   {
     const char* src = "\xD0\xB0";
-    uint32_t expected[] = { 0x430 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x430 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -42,8 +42,8 @@
 
   {
     const char* src = "\xE4\xBA\x8C";
-    uint32_t expected[] = { 0x4E8C };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x4E8C };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -52,8 +52,8 @@
 
   {
     const char* src = "\xF0\x90\x8C\x82";
-    uint32_t expected[] = { 0x10302 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x10302 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -62,8 +62,8 @@
 
   {
     const char* src = "\x4D\xD0\xB0\xE4\xBA\x8C\xF0\x90\x8C\x82";
-    uint32_t expected[] = { 0x4D, 0x430, 0x4E8C, 0x10302 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x4D, 0x430, 0x4E8C, 0x10302 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -75,10 +75,10 @@
     const char* src = "\xD7\x92\xD7\x9C\xD7\xA2\xD7\x93"
                       "\x20"
                       "\xD7\x91\xD7\xA8\xD7\x9B\xD7\x94";
-    uint32_t expected[] = { 0x5D2, 0x5DC, 0x5E2, 0x5D3,
-                            0x20,
-                            0x5D1, 0x5E8, 0x5DB, 0x5D4 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x5D2, 0x5DC, 0x5E2, 0x5D3,
+                           0x20,
+                           0x5D1, 0x5E8, 0x5DB, 0x5D4 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -90,8 +90,8 @@
   // 1 - Some correct UTF-8 text
   {
     const char* src = "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5";
-    uint32_t expected[] = { 0x3BA, 0x1F79, 0x3C3, 0x3BC, 0x3B5 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x3BA, 0x1F79, 0x3C3, 0x3BC, 0x3B5 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -105,8 +105,8 @@
   // 2.1.1 - 1 byte (U-00000000):        "\x00"
   {
     const char* src = "\x00";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -116,8 +116,8 @@
   // 2.1.2 - 2 bytes (U-00000080):        "\xC2\x80"
   {
     const char* src = "\xC2\x80";
-    uint32_t expected[] = { 0x80 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x80 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -127,8 +127,8 @@
   // 2.1.3 - 3 bytes (U-00000800):        "\xE0\xA0\x80"
   {
     const char* src = "\xE0\xA0\x80";
-    uint32_t expected[] = { 0x800 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x800 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -138,8 +138,8 @@
   // 2.1.4 - 4 bytes (U-00010000):        "\xF0\x90\x80\x80"
   {
     const char* src = "\xF0\x90\x80\x80";
-    uint32_t expected[] = { 0x10000 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x10000 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -149,8 +149,8 @@
   // 2.1.5 - 5 bytes (U-00200000):        "\xF8\x88\x80\x80\x80"
   {
     const char* src = "\xF8\x88\x80\x80\x80";
-    uint32_t expected[] = { 0x200000 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x200000 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -160,8 +160,8 @@
   // 2.1.6 - 6 bytes (U-04000000):        "\xFC\x84\x80\x80\x80\x80"
   {
     const char* src = "\xFC\x84\x80\x80\x80\x80";
-    uint32_t expected[] = { 0x400000 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x400000 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -173,8 +173,8 @@
   // 2.2.1 - 1 byte (U-0000007F):        "\x7F"
   {
     const char* src = "\x7F";
-    uint32_t expected[] = { 0x7F };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x7F };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -184,8 +184,8 @@
   // 2.2.2 - 2 bytes (U-000007FF):        "\xDF\xBF"
   {
     const char* src = "\xDF\xBF";
-    uint32_t expected[] = { 0x7FF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x7FF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -195,8 +195,8 @@
   // 2.2.3 - 3 bytes (U-0000FFFF):        "\xEF\xBF\xBF"
   {
     const char* src = "\xEF\xBF\xBF";
-    uint32_t expected[] = { 0xFFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xFFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -206,8 +206,8 @@
   // 2.2.4 - 4 bytes (U-001FFFFF):        "\xF7\xBF\xBF\xBF"
   {
     const char* src = "\xF7\xBF\xBF\xBF";
-    uint32_t expected[] = { 0x1FFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x1FFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -217,8 +217,8 @@
   // 2.2.5 - 5 bytes (U-03FFFFFF):        "\xFB\xBF\xBF\xBF\xBF"
   {
     const char* src = "\xFB\xBF\xBF\xBF\xBF";
-    uint32_t expected[] = { 0x3FFFFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x3FFFFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -228,8 +228,8 @@
   // 2.2.6 - 6 bytes (U-7FFFFFFF):        "\xFD\xBF\xBF\xBF\xBF\xBF"
   {
     const char* src = "\xFD\xBF\xBF\xBF\xBF\xBF";
-    uint32_t expected[] = { 0x7FFFFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x7FFFFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -241,8 +241,8 @@
   // 2.3.1 - U-0000D7FF = ed 9f bf = "\xED\x9F\xBF"
   {
     const char* src = "\xED\x9F\xBF";
-    uint32_t expected[] = { 0xD7FF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xD7FF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -252,8 +252,8 @@
   // 2.3.2 - U-0000E000 = ee 80 80 = "\xEE\x80\x80"
   {
     const char* src = "\xEE\x80\x80";
-    uint32_t expected[] = { 0xE000 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xE000 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -263,8 +263,8 @@
   // 2.3.3 - U-0000FFFD = ef bf bd = "\xEF\xBF\xBD"
   {
     const char* src = "\xEF\xBF\xBD";
-    uint32_t expected[] = { 0xFFFD };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xFFFD };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -274,8 +274,8 @@
   // 2.3.4 - U-0010FFFF = f4 8f bf bf = "\xF4\x8F\xBF\xBF"
   {
     const char* src = "\xF4\x8F\xBF\xBF";
-    uint32_t expected[] = { 0x10FFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x10FFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -285,8 +285,8 @@
   // 2.3.5 - U-00110000 = f4 90 80 80 = "\xF4\x90\x80\x80"
   {
     const char* src = "\xF4\x90\x80\x80";
-    uint32_t expected[] = { 0x110000 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x110000 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -300,8 +300,8 @@
   // 3.1.1 - First continuation byte 0x80: "\x80"
   {
     const char* src = "\x80";
-    uint32_t expected[] = { 0x80 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x80 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -311,8 +311,8 @@
   // 3.1.2 - Last continuation byte 0xbf: "\xBF"
   {
     const char* src = "\xBF";
-    uint32_t expected[] = { 0xBF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xBF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -322,8 +322,8 @@
   // 3.1.3 - 2 continuation bytes: "\x80\xBF"
   {
     const char* src = "\x80\xBF";
-    uint32_t expected[] = { 0x80, 0xBF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x80, 0xBF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -333,8 +333,8 @@
   // 3.1.4 - 3 continuation bytes: "\x80\xBF\x80"
   {
     const char* src = "\x80\xBF\x80";
-    uint32_t expected[] = { 0x80, 0xBF, 0x80 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x80, 0xBF, 0x80 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -344,8 +344,8 @@
   // 3.1.5 - 4 continuation bytes: "\x80\xBF\x80\xBF"
   {
     const char* src = "\x80\xBF\x80\xBF";
-    uint32_t expected[] = { 0x80, 0xBF, 0x80, 0xBF  };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x80, 0xBF, 0x80, 0xBF  };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -355,8 +355,8 @@
   // 3.1.6 - 5 continuation bytes: "\x80\xBF\x80\xBF\x80"
   {
     const char* src = "\x80\xBF\x80\xBF\x80";
-    uint32_t expected[] = { 0x80, 0xBF, 0x80, 0xBF, 0x80 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x80, 0xBF, 0x80, 0xBF, 0x80 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -366,8 +366,8 @@
   // 3.1.7 - 6 continuation bytes: "\x80\xBF\x80\xBF\x80\xBF"
   {
     const char* src = "\x80\xBF\x80\xBF\x80\xBF";
-    uint32_t expected[] = { 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -377,8 +377,8 @@
   // 3.1.8 - 7 continuation bytes: "\x80\xBF\x80\xBF\x80\xBF\x80"
   {
     const char* src = "\x80\xBF\x80\xBF\x80\xBF\x80";
-    uint32_t expected[] = { 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF, 0x80 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF, 0x80 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -395,8 +395,8 @@
                       "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
                       "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
                       "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     for (size_t i = 0; i < strlen(src); ++i) {
       memset(dst, 0xFF, sizeof(dst));
       bool is_valid = Utf8::DecodeCStringToUTF32(&src[i], dst, ARRAY_SIZE(dst));
@@ -418,8 +418,8 @@
                       "\xD4\x20\xD5\x20\xD6\x20\xD7\x20"
                       "\xD8\x20\xD9\x20\xDA\x20\xDB\x20"
                       "\xDC\x20\xDD\x20\xDE\x20\xDF\x20";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     for (size_t i = 0; i < strlen(src); i += 2) {
       memset(dst, 0xFF, sizeof(dst));
       bool is_valid = Utf8::DecodeCStringToUTF32(&src[i], dst, ARRAY_SIZE(dst));
@@ -435,8 +435,8 @@
                       "\xE4\x20\xE5\x20\xE6\x20\xE7\x20"
                       "\xE8\x20\xE9\x20\xEA\x20\xEB\x20"
                       "\xEC\x20\xED\x20\xEE\x20\xEF\x20";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     for (size_t i = 0; i < strlen(src); i += 2) {
       memset(dst, 0xFF, sizeof(dst));
       bool is_valid = Utf8::DecodeCStringToUTF32(&src[i], dst, ARRAY_SIZE(dst));
@@ -450,8 +450,8 @@
   {
     const char* src = "\xF0\x20\xF1\x20\xF2\x20\xF3\x20"
                       "\xF4\x20\xF5\x20\xF6\x20\xF7\x20";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     for (size_t i = 0; i < strlen(src); i += 2) {
       memset(dst, 0xFF, sizeof(dst));
       bool is_valid = Utf8::DecodeCStringToUTF32(&src[i], dst, ARRAY_SIZE(dst));
@@ -464,8 +464,8 @@
   //         followed by a space character:
   {
     const char* src = "\xF8\x20\xF9\x20\xFA\x20\xFB\x20";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     for (size_t i = 0; i < strlen(src); i += 2) {
       memset(dst, 0xFF, sizeof(dst));
       bool is_valid = Utf8::DecodeCStringToUTF32(&src[i], dst, ARRAY_SIZE(dst));
@@ -478,8 +478,8 @@
   //         followed by a space character:
   {
     const char* src = "\xFC\x20\xFD\x20";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     for (size_t i = 0; i < strlen(src); i += 2) {
       memset(dst, 0xFF, sizeof(dst));
       bool is_valid = Utf8::DecodeCStringToUTF32(&src[i], dst, ARRAY_SIZE(dst));
@@ -493,8 +493,8 @@
   // 3.3.1 - 2-byte sequence with last byte missing (U+0000): "\xC0"
   {
     const char* src = "\xC0";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -504,8 +504,8 @@
   // 3.3.2 - 3-byte sequence with last byte missing (U+0000): "\xE0\x80"
   {
     const char* src = "\xE0\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -515,8 +515,8 @@
   // 3.3.3 - 4-byte sequence with last byte missing (U+0000): "\xF0\x80\x80"
   {
     const char* src = "\xF0\x80\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -526,8 +526,8 @@
   // 3.3.4 - 5-byte sequence with last byte missing (U+0000): "\xF8\x80\x80\x80"
   {
     const char* src = "\xF8\x80\x80\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -538,8 +538,8 @@
   // "\xFC\x80\x80\x80\x80"
   {
     const char* src = "\xFC\x80\x80\x80\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -549,8 +549,8 @@
   // 3.3.6 - 2-byte sequence with last byte missing (U-000007FF): "\xDF"
   {
     const char* src = "\xDF";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -560,8 +560,8 @@
   // 3.3.7 - 3-byte sequence with last byte missing (U-0000FFFF): "\xEF\xBF"
   {
     const char* src = "\xEF\xBF";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -571,8 +571,8 @@
   // 3.3.8 - 4-byte sequence with last byte missing (U-001FFFFF): "\xF7\xBF\xBF"
   {
     const char* src = "\xF7\xBF\xBF";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -583,8 +583,8 @@
   // "\xFB\xBF\xBF\xBF"
   {
     const char* src = "\xFB\xBF\xBF\xBF";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -595,8 +595,8 @@
   // "\xFD\xBF\xBF\xBF\xBF"
   {
     const char* src = "\xFD\xBF\xBF\xBF\xBF";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -610,8 +610,8 @@
                       "\x80\x80\x80\xDF\xEF\xBF"
                       "\xF7\xBF\xBF\xFB\xBF\xBF"
                       "\xBF\xFD\xBF\xBF\xBF\xBF";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     for (size_t i = 0; i < strlen(src); ++i) {
       for (size_t j = 1; j < (strlen(src) - i); ++j) {
         memset(dst, 0xFF, sizeof(dst));
@@ -628,8 +628,8 @@
   // 3.5.1 - fe = "\xFE"
   {
     const char* src = "\xFE";
-    uint32_t expected[] = { 0xFE };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xFE };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -639,8 +639,8 @@
   // 3.5.2 - ff = "\xFF"
   {
     const char* src = "\xFF";
-    uint32_t expected[] = { 0xFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -650,8 +650,8 @@
   // 3.5.3 - fe fe ff ff = "\xFE\xFE\xFF\xFF"
   {
     const char* src = "\xFE\xFE\xFF\xFF";
-    uint32_t expected[] = { 0xFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -665,8 +665,8 @@
   // 4.1.1 - U+002F = c0 af             = "\xC0\xAF"
   {
     const char* src = "\xC0\xAF";
-    uint32_t expected[] = { 0x2F };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x2F };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -676,8 +676,8 @@
   // 4.1.2 - U+002F = e0 80 af          = "\xE0\x80\xAF"
   {
     const char* src = "\xE0\x80\xAF";
-    uint32_t expected[] = { 0x2F };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x2F };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -687,8 +687,8 @@
   // 4.1.3 - U+002F = f0 80 80 af       = "\xF0\x80\x80\xAF"
   {
     const char* src = "\xF0\x80\x80\xAF";
-    uint32_t expected[] = { 0x2F };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x2F };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -698,8 +698,8 @@
   // 4.1.4 - U+002F = f8 80 80 80 af    = "\xF8\x80\x80\x80\xAF"
   {
     const char* src = "\xF8\x80\x80\x80\xAF";
-    uint32_t expected[] = { 0x2F };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x2F };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -709,8 +709,8 @@
   // 4.1.5 - U+002F = fc 80 80 80 80 af = "\xFC\x80\x80\x80\x80\xAF"
   {
     const char* src = "\xFC\x80\x80\x80\x80\xAF";
-    uint32_t expected[] = { 0x2F };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x2F };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -722,8 +722,8 @@
   // 4.2.1 - U-0000007F = c1 bf             = "\xC1\xBF"
   {
     const char* src = "\xC1\xBF";
-    uint32_t expected[] = { 0x7F };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x7F };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -733,8 +733,8 @@
   // 4.2.2 U+000007FF = e0 9f bf          = "\xE0\x9F\xBF"
   {
     const char* src = "\xE0\x9F\xBF";
-    uint32_t expected[] = { 0x7FF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x7FF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -744,8 +744,8 @@
   // 4.2.3 - U+0000FFFF = f0 8f bf bf       = "\xF0\x8F\xBF\xBF"
   {
     const char* src = "\xF0\x8F\xBF\xBF";
-    uint32_t expected[] = { 0xFFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xFFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -755,8 +755,8 @@
   // 4.2.4  U-001FFFFF = f8 87 bf bf bf    = "\xF8\x87\xBF\xBF\xBF"
   {
     const char* src = "\xF8\x87\xBF\xBF\xBF";
-    uint32_t expected[] = { 0x1FFFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x1FFFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -766,8 +766,8 @@
   // 4.2.5  U-03FFFFFF = fc 83 bf bf bf bf = "\xFC\x83\xBF\xBF\xBF\xBF"
   {
     const char* src = "\xFC\x83\xBF\xBF\xBF\xBF";
-    uint32_t expected[] = { 0x3FFFFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x3FFFFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -779,8 +779,8 @@
   // 4.3.1 - U+0000 = "\xC0\x80"
   {
     const char* src = "\xC0\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -790,8 +790,8 @@
   // 4.3.2  U+0000 = e0 80 80 = "\xE0\x80\x80"
   {
     const char* src = "\xE0\x80\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -801,8 +801,8 @@
   // 4.3.3  U+0000 = f0 80 80 80 = "\xF0\x80\x80\x80"
   {
     const char* src = "\xF0\x80\x80\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -812,8 +812,8 @@
   // 4.3.4  U+0000 = f8 80 80 80 80 = "\xF8\x80\x80\x80\x80"
   {
     const char* src = "\xF8\x80\x80\x80\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -823,8 +823,8 @@
   // 4.3.5  U+0000 = fc 80 80 80 80 80 = "\xFC\x80\x80\x80\x80\x80"
   {
     const char* src = "\xFC\x80\x80\x80\x80\x80";
-    uint32_t expected[] = { 0x0 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0x0 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0xFF, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -836,8 +836,8 @@
   // 5.1.1 - U+D800 = ed a0 80 = "\xED\xA0\x80"
   {
     const char* src = "\xED\xA0\x80";
-    uint32_t expected[] = { 0xD800 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xD800 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -847,8 +847,8 @@
   // 5.1.2 - U+DB7F = ed ad bf = "\xED\xAD\xBF"
   {
     const char* src = "\xED\xAD\xBF";
-    uint32_t expected[] = { 0xDB7F };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDB7F };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -858,8 +858,8 @@
   // 5.1.3 - U+DB80 = ed ae 80 = "\xED\xAE\x80"
   {
     const char* src = "\xED\xAE\x80";
-    uint32_t expected[] = { 0xDB80 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDB80 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -869,8 +869,8 @@
   // 5.1.4 - U+DBFF = ed af bf = "\xED\xAF\xBF"
   {
     const char* src = "\xED\xAF\xBF";
-    uint32_t expected[] = { 0xDBFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDBFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -880,8 +880,8 @@
   // 5.1.5 - U+DC00 = ed b0 80 = "\xED\xB0\x80"
   {
     const char* src = "\xED\xB0\x80";
-    uint32_t expected[] = { 0xDC00 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDC00 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -891,8 +891,8 @@
   // 5.1.6 - U+DF80 = ed be 80 = "\xED\xBE\x80"
   {
     const char* src = "\xED\xBE\x80";
-    uint32_t expected[] = { 0xDF80 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDF80 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -902,8 +902,8 @@
   // 5.1.7 - U+DFFF = ed bf bf = "\xED\xBF\xBF"
   {
     const char* src = "\xED\xBF\xBF";
-    uint32_t expected[] = { 0xDFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -915,8 +915,8 @@
   // 5.2.1 - U+D800 U+DC00 = ed a0 80 ed b0 80 = "\xED\xA0\x80\xED\xB0\x80"
   {
     const char* src = "\xED\xA0\x80\xED\xB0\x80";
-    uint32_t expected[] = { 0xD800, 0xDC00 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xD800, 0xDC00 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -926,8 +926,8 @@
   // 5.2.2 - U+D800 U+DFFF = ed a0 80 ed bf bf = "\xED\xA0\x80\xED\xBF\xBF"
   {
     const char* src = "\xED\xA0\x80\xED\xBF\xBF";
-    uint32_t expected[] = { 0xD800, 0xDFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xD800, 0xDFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -937,8 +937,8 @@
   // 5.2.3 - U+DB7F U+DC00 = ed a0 80 ed bf bf = "\xED\xAD\xBF\xED\xB0\x80"
   {
     const char* src = "\xED\xAD\xBF\xED\xB0\x80";
-    uint32_t expected[] = { 0xDB7F, 0xDC00 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDB7F, 0xDC00 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -948,8 +948,8 @@
   // 5.2.4 - U+DB7F U+DFFF = ed ad bf ed bf bf = "\xED\xAD\xBF\xED\xBF\xBF"
   {
     const char* src = "\xED\xAD\xBF\xED\xBF\xBF";
-    uint32_t expected[] = { 0xDB7F, 0xDFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDB7F, 0xDFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -959,8 +959,8 @@
   // 5.2.5 - U+DB80 U+DC00 = ed ae 80 ed b0 80 = "\xED\xAE\x80\xED\xB0\x80"
   {
     const char* src = "\xED\xAE\x80\xED\xB0\x80";
-    uint32_t expected[] = { 0xDB80, 0xDC00 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDB80, 0xDC00 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -970,8 +970,8 @@
   // 5.2.6 - U+DB80 U+DFFF = ed ae 80 ed bf bf = "\xED\xAE\x80\xED\xBF\xBF"
   {
     const char* src = "\xED\xAE\x80\xED\xBF\xBF";
-    uint32_t expected[] = { 0xDB80, 0xDFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDB80, 0xDFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -981,8 +981,8 @@
   // 5.2.7 - U+DBFF U+DC00 = ed af bf ed b0 80 = "\xED\xAF\xBF\xED\xB0\x80"
   {
     const char* src = "\xED\xAF\xBF\xED\xB0\x80";
-    uint32_t expected[] = { 0xDBFF, 0xDC00 };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDBFF, 0xDC00 };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -992,8 +992,8 @@
   // 5.2.8 - U+DBFF U+DFFF = ed af bf ed bf bf = "\xED\xAF\xBF\xED\xBF\xBF"
   {
     const char* src = "\xED\xAF\xBF\xED\xBF\xBF";
-    uint32_t expected[] = { 0xDBFF, 0xDFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xDBFF, 0xDFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(!is_valid);
@@ -1005,8 +1005,8 @@
   // 5.3.1 - U+FFFE = ef bf be = "\xEF\xBF\xBE"
   {
     const char* src = "\xEF\xBF\xBE";
-    uint32_t expected[] = { 0xFFFE };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xFFFE };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
@@ -1016,8 +1016,8 @@
   // 5.3.2 - U+FFFF = ef bf bf = "\xEF\xBF\xBF"
   {
     const char* src = "\xEF\xBF\xBF";
-    uint32_t expected[] = { 0xFFFF };
-    uint32_t dst[ARRAY_SIZE(expected)];
+    int32_t expected[] = { 0xFFFF };
+    int32_t dst[ARRAY_SIZE(expected)];
     memset(dst, 0, sizeof(dst));
     bool is_valid = Utf8::DecodeCStringToUTF32(src, dst, ARRAY_SIZE(dst));
     EXPECT(is_valid);
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index 0fb1bd9..7104aa5 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -78,6 +78,7 @@
       'includes': [
         '../lib/lib_sources.gypi',
         '../lib/isolate_sources.gypi',
+        '../lib/math_sources.gypi',
         '../lib/mirrors_sources.gypi',
         '../lib/scalarlist_sources.gypi',
       ],
@@ -106,6 +107,7 @@
       'includes': [
         '../lib/lib_sources.gypi',
         '../lib/isolate_sources.gypi',
+        '../lib/math_sources.gypi',
         '../lib/mirrors_sources.gypi',
         '../lib/scalarlist_sources.gypi',
       ],
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index d45c8fa..2b2f9d4 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -236,9 +236,6 @@
     'port.cc',
     'port.h',
     'port_test.cc',
-    'random.cc',
-    'random.h',
-    'random_test.cc',
     'raw_object.cc',
     'raw_object.h',
     'raw_object_snapshot.cc',
diff --git a/sdk/lib/_internal/compiler/compiler.dart b/sdk/lib/_internal/compiler/compiler.dart
index af37116..9ef6aa8 100644
--- a/sdk/lib/_internal/compiler/compiler.dart
+++ b/sdk/lib/_internal/compiler/compiler.dart
@@ -8,8 +8,7 @@
 import 'implementation/apiimpl.dart';
 
 // Unless explicitly allowed, passing [:null:] for any argument to the
-// methods of library will result in a NullPointerException being
-// thrown.
+// methods of library will result in an Error being thrown.
 
 /**
  * Returns a future that completes to the source corresponding to
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 4d6be1c..3d5feef 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -371,7 +371,7 @@
         return true;
       } else if (type is InterfaceType) {
         InterfaceType ifcType = type;
-        for (DartType argument in ifcType.arguments) {
+        for (DartType argument in ifcType.typeArguments) {
           if (hasTypeVariable(argument)) {
             return true;
           }
@@ -385,7 +385,7 @@
         useLocal(type.element);
       } else if (type is InterfaceType) {
         InterfaceType ifcType = type;
-        for (DartType argument in ifcType.arguments) {
+        for (DartType argument in ifcType.typeArguments) {
           analyzeTypeVariables(argument);
         }
       }
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 1f16080..975d4e5 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -28,7 +28,6 @@
   /** Caches the statics where the initial value cannot be eagerly compiled. */
   final Set<VariableElement> lazyStatics;
 
-
   ConstantHandler(Compiler compiler, this.constantSystem)
       : initialVariableValues = new Map<VariableElement, dynamic>(),
         compiledConstants = new Set<Constant>(),
@@ -134,7 +133,7 @@
             && element.isField()) {
           DartType elementType = element.computeType(compiler);
           DartType constantType = value.computeType(compiler);
-          if (!compiler.types.isSubtype(constantType, elementType)) {
+          if (!constantSystem.isSubtype(compiler, constantType, elementType)) {
             if (isConst) {
               MessageKind kind = MessageKind.NOT_ASSIGNABLE;
               compiler.reportError(node, new CompileTimeConstantError(
@@ -248,6 +247,7 @@
   final ConstantSystem constantSystem;
   final TreeElements elements;
   final Compiler compiler;
+  bool enabledRuntimeTypeSupport = false;
 
   CompileTimeConstantEvaluator(this.constantSystem,
                                this.elements,
@@ -400,6 +400,25 @@
     return constantSystem.createString(accumulator, node);
   }
 
+  Constant makeTypeConstant(Element element) {
+    // If we use a type literal in a constant, the compile time constant
+    // emitter will generate a call to the runtime type cache helper, so we
+    // resolve it and put it into the codegen work list.
+    if (!enabledRuntimeTypeSupport) {
+      SourceString helperName = const SourceString('createRuntimeType');
+      Element helper = compiler.findHelper(helperName);
+      compiler.enqueuer.resolution.addToWorkList(helper);
+      compiler.enqueuer.codegen.addToWorkList(helper);
+      enabledRuntimeTypeSupport = true;
+    }
+
+    DartType elementType = element.computeType(compiler).asRaw();
+    DartType constantType = compiler.typeClass.computeType(compiler);
+    Constant constant = new TypeConstant(elementType, constantType);
+    compiler.constantHandler.registerCompileTimeConstant(constant);
+    return constant;
+  }
+
   // TODO(floitsch): provide better error-messages.
   Constant visitSend(Send send) {
     Element element = elements[send];
@@ -418,6 +437,8 @@
           result = compiler.compileVariable(element);
         }
         if (result != null) return result;
+      } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
+        return makeTypeConstant(element);
       }
       return signalNotCompileTimeConstant(send);
     } else if (send.isCall) {
@@ -427,6 +448,8 @@
         Constant right = evaluate(send.argumentsNode.nodes.tail.head);
         Constant result = constantSystem.identity.fold(left, right);
         if (result != null) return result;
+      } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
+        return makeTypeConstant(element);
       }
       return signalNotCompileTimeConstant(send);
     } else if (send.isPrefix) {
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index e416804..e770cff 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -96,8 +96,6 @@
 
   SourceString getCheckedModeHelper(DartType type) => null;
   void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {}
-
-  Element getInterceptor(Selector selector);
 }
 
 abstract class Compiler implements DiagnosticListener {
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index 6e20124..ad5dc74 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -16,6 +16,7 @@
   R visitList(ListConstant constant);
   R visitMap(MapConstant constant);
   R visitConstructed(ConstructedConstant constant);
+  R visitType(TypeConstant constant);
 }
 
 abstract class Constant {
@@ -37,6 +38,7 @@
   bool isPrimitive() => false;
   /** Returns true if the constant is a list, a map or a constructed object. */
   bool isObject() => false;
+  bool isType() => false;
   bool isSentinel() => false;
 
   bool isNaN() => false;
@@ -46,7 +48,7 @@
 
   List<Constant> getDependencies();
 
-  accept(ConstantVisitor);
+  accept(ConstantVisitor visitor);
 }
 
 class SentinelConstant extends Constant {
@@ -100,7 +102,7 @@
   bool operator ==(var other) {
     if (other is !PrimitiveConstant) return false;
     PrimitiveConstant otherPrimitive = other;
-    // We use == instead of === so that DartStrings compare correctly.
+    // We use == instead of 'identical' so that DartStrings compare correctly.
     return value == otherPrimitive.value;
   }
 
@@ -315,10 +317,25 @@
   bool isObject() => true;
 
   DartType computeType(Compiler compiler) => type;
+}
 
-  // TODO(1603): The class should be marked as abstract, but the VM doesn't
-  // currently allow this.
-  int get hashCode;
+class TypeConstant extends ObjectConstant {
+  /// The user type that this constant represents.
+  final DartType representedType;
+
+  TypeConstant(this.representedType, type) : super(type);
+
+  bool isType() => true;
+
+  bool operator ==(other) {
+    return other is TypeConstant && representedType == other.representedType;
+  }
+
+  int get hashCode => representedType.hashCode * 13;
+
+  List<Constant> getDependencies() => const <Constant>[];
+
+  accept(ConstantVisitor visitor) => visitor.visitType(this);
 }
 
 class ListConstant extends ObjectConstant {
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index 101918b..c012488 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -196,8 +196,6 @@
         stripAsserts = strips.indexOf('asserts') != -1,
         super(compiler);
 
-  Element getInterceptor(Selector selector) => null;
-
   void enqueueHelpers(Enqueuer 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 b31e471..63e14f9 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -30,6 +30,7 @@
   final bool isRedirectingCall;
   ConstructorPlaceholder(this.node, this.type)
       : this.isRedirectingCall = false;
+  // Note: factory redirection is not redirecting call!
   ConstructorPlaceholder.redirectingCall(this.node)
       : this.type = null, this.isRedirectingCall = true;
 }
@@ -141,7 +142,7 @@
   final Set<String> fixedMemberNames; // member names which cannot be renamed.
   final Map<Element, ElementAst> elementAsts;
   final Set<Node> nullNodes;  // Nodes that should not be in output.
-  final Set<Identifier> unresolvedNodes;
+  final Set<Node> unresolvedNodes;
   final Map<Element, Set<Node>> elementNodes;
   final Map<FunctionElement, FunctionScope> functionScopes;
   final Map<LibraryElement, Set<Identifier>> privateNodes;
@@ -161,7 +162,7 @@
 
   PlaceholderCollector(this.compiler, this.fixedMemberNames, this.elementAsts) :
       nullNodes = new Set<Node>(),